From 1d281eb1798026cc2072dba312fd5aed7ea097e4 Mon Sep 17 00:00:00 2001 From: btc <68381405+esbtc@users.noreply.github.com> Date: Fri, 3 Jul 2026 13:15:05 +0000 Subject: [PATCH] i18n: add Persian (fa) as RTL and per-bubble bidi isolation for chat bubbles --- src/renderer/src/assets/main.css | 13656 +---------------- src/renderer/src/screens/Chat/MessageRow.tsx | 11 + src/shared/i18n/config.ts | 3 +- src/shared/i18n/index.test.ts | 4 + 4 files changed, 25 insertions(+), 13649 deletions(-) diff --git a/src/renderer/src/assets/main.css b/src/renderer/src/assets/main.css index 060ffc596..8fa9d1283 100644 --- a/src/renderer/src/assets/main.css +++ b/src/renderer/src/assets/main.css @@ -110,13661 +110,21 @@ --selection: rgba(189, 147, 249, 0.7); } -/* ----- Nord ----- */ -[data-theme="nord"] { - --bg-primary: #2e3440; - --bg-secondary: #272c36; - --bg-tertiary: #3b4252; - --bg-elevated: #3b4252; - --bg-hover: #434c5e; - --bg-active: #4c566a; - --accent: #88c0d0; - --accent-hover: #8fbcbb; - --accent-subtle: rgba(136, 192, 208, 0.16); - --accent-text: #88c0d0; - --primary-yellow: #ebcb8b; - --text-primary: #eceff4; - --text-secondary: #d8dee9; - --text-muted: #7b88a1; - --border: rgba(255, 255, 255, 0.06); - --border-bright: rgba(255, 255, 255, 0.12); - --border-focus: #88c0d0; - --success: #a3be8c; - --success-bg: rgba(163, 190, 140, 0.14); - --error: #bf616a; - --error-bg: rgba(191, 97, 106, 0.14); - --warning: #ebcb8b; - --warning-bg: rgba(235, 203, 139, 0.14); - --user-bubble: #5e81ac; - --user-bubble-text: #eceff4; - --agent-bubble: #3b4252; - --agent-bubble-text: #eceff4; - --code-bg: #272c36; - --scrollbar-thumb: #434c5e; - --scrollbar-hover: #4c566a; - --selection: rgba(136, 192, 208, 0.7); -} - -/* ----- One Dark ----- */ -[data-theme="one-dark"] { - --bg-primary: #282c34; - --bg-secondary: #21252b; - --bg-tertiary: #2c313a; - --bg-elevated: #2c313a; - --bg-hover: #2f3540; - --bg-active: #3e4451; - --accent: #61afef; - --accent-hover: #74b9f1; - --accent-subtle: rgba(97, 175, 239, 0.16); - --accent-text: #61afef; - --primary-yellow: #e5c07b; - --text-primary: #d7dae0; - --text-secondary: #abb2bf; - --text-muted: #6b727f; - --border: rgba(255, 255, 255, 0.06); - --border-bright: rgba(255, 255, 255, 0.1); - --border-focus: #61afef; - --success: #98c379; - --success-bg: rgba(152, 195, 121, 0.14); - --error: #e06c75; - --error-bg: rgba(224, 108, 117, 0.14); - --warning: #e5c07b; - --warning-bg: rgba(229, 192, 123, 0.14); - --user-bubble: #61afef; - --user-bubble-text: #282c34; - --agent-bubble: #2c313a; - --agent-bubble-text: #d7dae0; - --code-bg: #21252b; - --scrollbar-thumb: #3e4451; - --scrollbar-hover: #4b5263; - --selection: rgba(97, 175, 239, 0.7); -} - -/* ----- GitHub Dark ----- */ -[data-theme="github-dark"] { - --bg-primary: #0d1117; - --bg-secondary: #010409; - --bg-tertiary: #161b22; - --bg-elevated: #161b22; - --bg-hover: #1f242c; - --bg-active: #21262d; - --accent: #1f6feb; - --accent-hover: #388bfd; - --accent-subtle: rgba(56, 139, 253, 0.16); - --accent-text: #58a6ff; - --primary-yellow: #d29922; - --text-primary: #c9d1d9; - --text-secondary: #8b949e; - --text-muted: #6e7681; - --border: #30363d; - --border-bright: #444c56; - --border-focus: #1f6feb; - --success: #3fb950; - --success-bg: rgba(63, 185, 80, 0.14); - --error: #f85149; - --error-bg: rgba(248, 81, 73, 0.14); - --warning: #d29922; - --warning-bg: rgba(210, 153, 34, 0.14); - --user-bubble: #1f6feb; - --user-bubble-text: #ffffff; - --agent-bubble: #161b22; - --agent-bubble-text: #c9d1d9; - --code-bg: #161b22; - --scrollbar-thumb: #30363d; - --scrollbar-hover: #484f58; - --selection: rgba(56, 139, 253, 0.7); -} - -/* ----- Monokai ----- */ -[data-theme="monokai"] { - --bg-primary: #272822; - --bg-secondary: #1e1f1c; - --bg-tertiary: #2d2e28; - --bg-elevated: #34352f; - --bg-hover: #3e3d32; - --bg-active: #49483e; - --accent: #66d9ef; - --accent-hover: #7ee0f2; - --accent-subtle: rgba(102, 217, 239, 0.16); - --accent-text: #66d9ef; - --primary-yellow: #e6db74; - --text-primary: #f8f8f2; - --text-secondary: #c5c8c6; - --text-muted: #75715e; - --border: rgba(255, 255, 255, 0.06); - --border-bright: rgba(255, 255, 255, 0.12); - --border-focus: #66d9ef; - --success: #a6e22e; - --success-bg: rgba(166, 226, 46, 0.14); - --error: #f92672; - --error-bg: rgba(249, 38, 114, 0.14); - --warning: #e6db74; - --warning-bg: rgba(230, 219, 116, 0.14); - --user-bubble: #f92672; - --user-bubble-text: #ffffff; - --agent-bubble: #2d2e28; - --agent-bubble-text: #f8f8f2; - --code-bg: #1e1f1c; - --scrollbar-thumb: #49483e; - --scrollbar-hover: #75715e; - --selection: rgba(102, 217, 239, 0.7); -} - -/* ----- Solarized Dark ----- */ -[data-theme="solarized-dark"] { - --bg-primary: #002b36; - --bg-secondary: #00252e; - --bg-tertiary: #073642; - --bg-elevated: #073642; - --bg-hover: #0a4250; - --bg-active: #0e4b5a; - --accent: #268bd2; - --accent-hover: #3a9bdc; - --accent-subtle: rgba(38, 139, 210, 0.16); - --accent-text: #2aa198; - --primary-yellow: #b58900; - --text-primary: #93a1a1; - --text-secondary: #839496; - --text-muted: #586e75; - --border: rgba(255, 255, 255, 0.06); - --border-bright: rgba(255, 255, 255, 0.1); - --border-focus: #268bd2; - --success: #859900; - --success-bg: rgba(133, 153, 0, 0.16); - --error: #dc322f; - --error-bg: rgba(220, 50, 47, 0.16); - --warning: #b58900; - --warning-bg: rgba(181, 137, 0, 0.16); - --user-bubble: #268bd2; - --user-bubble-text: #002b36; - --agent-bubble: #073642; - --agent-bubble-text: #93a1a1; - --code-bg: #00252e; - --scrollbar-thumb: #073642; - --scrollbar-hover: #586e75; - --selection: rgba(38, 139, 210, 0.7); -} - -/* ----- Gruvbox Dark ----- */ -[data-theme="gruvbox-dark"] { - --bg-primary: #282828; - --bg-secondary: #1d2021; - --bg-tertiary: #3c3836; - --bg-elevated: #3c3836; - --bg-hover: #504945; - --bg-active: #665c54; - --accent: #83a598; - --accent-hover: #8ec07c; - --accent-subtle: rgba(131, 165, 152, 0.16); - --accent-text: #83a598; - --primary-yellow: #fabd2f; - --text-primary: #ebdbb2; - --text-secondary: #d5c4a1; - --text-muted: #928374; - --border: rgba(255, 255, 255, 0.06); - --border-bright: rgba(255, 255, 255, 0.12); - --border-focus: #83a598; - --success: #b8bb26; - --success-bg: rgba(184, 187, 38, 0.14); - --error: #fb4934; - --error-bg: rgba(251, 73, 52, 0.14); - --warning: #fabd2f; - --warning-bg: rgba(250, 189, 47, 0.14); - --user-bubble: #83a598; - --user-bubble-text: #282828; - --agent-bubble: #3c3836; - --agent-bubble-text: #ebdbb2; - --code-bg: #1d2021; - --scrollbar-thumb: #504945; - --scrollbar-hover: #665c54; - --selection: rgba(131, 165, 152, 0.7); -} - -/* ----- Tokyo Night ----- */ -[data-theme="tokyo-night"] { - --bg-primary: #1a1b26; - --bg-secondary: #16161e; - --bg-tertiary: #1f2335; - --bg-elevated: #1f2335; - --bg-hover: #292e42; - --bg-active: #343b58; - --accent: #7aa2f7; - --accent-hover: #89b4fa; - --accent-subtle: rgba(122, 162, 247, 0.16); - --accent-text: #7aa2f7; - --primary-yellow: #e0af68; - --text-primary: #c0caf5; - --text-secondary: #a9b1d6; - --text-muted: #565f89; - --border: rgba(255, 255, 255, 0.06); - --border-bright: rgba(255, 255, 255, 0.1); - --border-focus: #7aa2f7; - --success: #9ece6a; - --success-bg: rgba(158, 206, 106, 0.14); - --error: #f7768e; - --error-bg: rgba(247, 118, 142, 0.14); - --warning: #e0af68; - --warning-bg: rgba(224, 175, 104, 0.14); - --user-bubble: #7aa2f7; - --user-bubble-text: #1a1b26; - --agent-bubble: #1f2335; - --agent-bubble-text: #c0caf5; - --code-bg: #16161e; - --scrollbar-thumb: #343b58; - --scrollbar-hover: #565f89; - --selection: rgba(122, 162, 247, 0.7); -} - -/* ----- GitHub Light ----- */ -[data-theme="github-light"] { - --bg-primary: #ffffff; - --bg-secondary: #f6f8fa; - --bg-tertiary: #eaeef2; - --bg-elevated: #eaeef2; - --bg-hover: #eef1f4; - --bg-active: #e1e5ea; - --accent: #0969da; - --accent-hover: #0860c9; - --accent-subtle: rgba(9, 105, 218, 0.08); - --accent-text: #0969da; - --primary-yellow: #9a6700; - --text-primary: #1f2328; - --text-secondary: #57606a; - --text-muted: #8c959f; - --border: #d0d7de; - --border-bright: #afb8c1; - --border-focus: #0969da; - --success: #1a7f37; - --success-bg: rgba(26, 127, 55, 0.08); - --error: #cf222e; - --error-bg: rgba(207, 34, 46, 0.07); - --warning: #9a6700; - --warning-bg: rgba(154, 103, 0, 0.08); - --user-bubble: #0969da; - --user-bubble-text: #ffffff; - --agent-bubble: #f6f8fa; - --agent-bubble-text: #1f2328; - --code-bg: #f6f8fa; - --scrollbar-thumb: #d0d7de; - --scrollbar-hover: #afb8c1; - --selection: rgba(9, 105, 218, 0.3); -} - -/* ----- Solarized Light ----- */ -[data-theme="solarized-light"] { - --bg-primary: #fdf6e3; - --bg-secondary: #f4eeda; - --bg-tertiary: #eee8d5; - --bg-elevated: #eee8d5; - --bg-hover: #e7e0c9; - --bg-active: #ddd6be; - --accent: #268bd2; - --accent-hover: #1d6fa5; - --accent-subtle: rgba(38, 139, 210, 0.1); - --accent-text: #268bd2; - --primary-yellow: #b58900; - --text-primary: #586e75; - --text-secondary: #657b83; - --text-muted: #93a1a1; - --border: #e0d9c3; - --border-bright: #d3cbb0; - --border-focus: #268bd2; - --success: #859900; - --success-bg: rgba(133, 153, 0, 0.1); - --error: #dc322f; - --error-bg: rgba(220, 50, 47, 0.08); - --warning: #b58900; - --warning-bg: rgba(181, 137, 0, 0.1); - --user-bubble: #268bd2; - --user-bubble-text: #fdf6e3; - --agent-bubble: #eee8d5; - --agent-bubble-text: #586e75; - --code-bg: #eee8d5; - --scrollbar-thumb: #d3cbb0; - --scrollbar-hover: #b9b393; - --selection: rgba(38, 139, 210, 0.3); -} - -/* ----- Manrope ----- */ -@font-face { - font-family: "Manrope"; - src: url("./fonts/Manrope-Regular.ttf") format("truetype"); - font-weight: 400; - font-style: normal; - font-display: swap; -} -@font-face { - font-family: "Manrope"; - src: url("./fonts/Manrope-Medium.ttf") format("truetype"); - font-weight: 500; - font-style: normal; - font-display: swap; -} -@font-face { - font-family: "Manrope"; - src: url("./fonts/Manrope-SemiBold.ttf") format("truetype"); - font-weight: 600; - font-style: normal; - font-display: swap; -} -@font-face { - font-family: "Manrope"; - src: url("./fonts/Manrope-Bold.ttf") format("truetype"); - font-weight: 700; - font-style: normal; - font-display: swap; -} - -/* ----- Cairo ----- */ -@font-face { - font-family: "Cairo"; - src: url("./fonts/Cairo-Regular.ttf") format("truetype"); - font-weight: 400; - font-style: normal; - font-display: swap; - /* Scope Cairo to Arabic glyphs only; Latin etc. falls through to Manrope */ - unicode-range: U+0600-06FF, U+0750-077F, U+0870-089F, U+08A0-08FF, - U+FB50-FDFF, U+FE70-FEFF; -} -@font-face { - font-family: "Cairo"; - src: url("./fonts/Cairo-Medium.ttf") format("truetype"); - font-weight: 500; - font-style: normal; - font-display: swap; - unicode-range: U+0600-06FF, U+0750-077F, U+0870-089F, U+08A0-08FF, - U+FB50-FDFF, U+FE70-FEFF; -} -@font-face { - font-family: "Cairo"; - src: url("./fonts/Cairo-SemiBold.ttf") format("truetype"); - font-weight: 600; - font-style: normal; - font-display: swap; - unicode-range: U+0600-06FF, U+0750-077F, U+0870-089F, U+08A0-08FF, - U+FB50-FDFF, U+FE70-FEFF; -} -@font-face { - font-family: "Cairo"; - src: url("./fonts/Cairo-Bold.ttf") format("truetype"); - font-weight: 700; - font-style: normal; - font-display: swap; - unicode-range: U+0600-06FF, U+0750-077F, U+0870-089F, U+08A0-08FF, - U+FB50-FDFF, U+FE70-FEFF; -} - -/* ----- Shared Tokens ----- */ -:root { - --radius-sm: 6px; - --radius-md: 10px; - --radius-lg: 14px; - --radius-xl: 20px; - --transition: 150ms ease; - --font-sans: - "Cairo", "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; - --font-mono: - "SF Mono", "Fira Code", "JetBrains Mono", Menlo, Consolas, monospace; -} - -/* ----- Squared corners (radius toggle off) ----- */ -html[data-radius="none"] { - --radius-sm: 0px; - --radius-md: 0px; - --radius-lg: 0px; - --radius-xl: 0px; -} - -/* ----- Body ----- */ -body { - font-family: var(--font-sans); - background: var(--bg-primary); - color: var(--text-primary); - transition: - background-color 0.2s ease, - color 0.2s ease; -} - -/* ----- App Shell ----- */ -.app { - height: 100vh; - display: flex; - flex-direction: column; - background: var(--bg-primary); -} - -.drag-region { - -webkit-app-region: drag; - height: 28px; - width: 100%; - position: fixed; - top: 0; - left: 0; - z-index: 1000; -} - -.app-content { - flex: 1; - overflow: hidden; - display: flex; - flex-direction: column; -} - -/* ----- Shared Components ----- */ -.screen { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 40px; - overflow-y: auto; -} - -.btn { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 8px; - padding: 10px 24px; - border-radius: var(--radius-sm); - font-size: 14px; - font-weight: 600; - border: none; - cursor: pointer; - transition: all var(--transition); - font-family: var(--font-sans); - line-height: 1; - white-space: nowrap; - flex-shrink: 0; -} - -.btn-primary { - background: var(--accent); - color: #fff; -} - -.btn-primary:hover:not(:disabled) { - background: var(--accent-hover); -} - -.btn-secondary { - background: var(--bg-elevated); - color: var(--text-primary); - border: 1px solid var(--border-bright); -} - -.btn-secondary:hover:not(:disabled) { - background: var(--bg-hover); -} - -.btn-sm { - padding: 6px 14px; - font-size: 13px; -} - -.btn-danger { - background: var(--error); - color: #fff; - border: none; -} - -.btn-danger:hover:not(:disabled) { - opacity: 0.9; -} - -.btn-ghost { - background: transparent; - color: var(--text-secondary); - border: none; - cursor: pointer; - padding: 6px 10px; - border-radius: var(--radius-sm); - font-size: 13px; - font-family: var(--font-sans); - transition: all var(--transition); -} - -.btn-ghost:hover { - color: var(--text-primary); - background: var(--bg-tertiary); -} - -.btn:disabled { - opacity: 0.4; - cursor: not-allowed; -} - -.input { - width: 100%; - padding: 10px 14px; - background: var(--bg-primary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-md); - color: var(--text-primary); - font-size: 14px; - font-family: var(--font-sans); - outline: none; - transition: border-color var(--transition); - box-sizing: border-box; -} - -.input:focus { - border-color: var(--border-focus); -} - -.input::placeholder { - color: var(--text-muted); -} - -/* ----- Loading ----- */ -.loading-screen { - background: var(--bg-primary); -} - -.loading-spinner { - width: 28px; - height: 28px; - border: 2.5px solid var(--border-bright); - border-top-color: var(--accent); - border-radius: 50%; - animation: spin 0.8s linear infinite; -} - -@keyframes spin { - to { - transform: rotate(360deg); - } -} - -/* ── Remote mode notice ── */ -.remote-notice { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 6px; - padding: 40px; - text-align: center; -} - -.remote-notice-icon { - color: var(--text-muted); - opacity: 0.4; - margin-bottom: 4px; -} - -.remote-notice-title { - font-size: 15px; - font-weight: 600; - color: var(--text-secondary); -} - -.remote-notice-desc { - font-size: 13px; - color: var(--text-muted); - max-width: 360px; - line-height: 1.5; -} - -/* ======================================================================== - WELCOME SCREEN - ======================================================================== */ -.welcome-screen { - text-align: center; - gap: 0; -} - -.welcome-logo { - border-radius: var(--radius-lg); -} - -.welcome-title { - font-size: 32px; - font-weight: 700; - letter-spacing: -0.5px; - margin-bottom: 10px; - color: var(--text-primary); -} - -.welcome-subtitle { - font-size: 15px; - color: var(--text-secondary); - margin-bottom: 36px; - max-width: 400px; - line-height: 1.7; -} - -.welcome-button { - padding: 12px 32px; - font-size: 15px; - margin-bottom: 16px; -} - -.welcome-note { - font-size: 13px; - color: var(--text-muted); -} - -.welcome-actions { - display: flex; - flex-direction: column; - align-items: center; - gap: 0; - width: 100%; - max-width: 480px; -} - -.welcome-divider { - display: flex; - align-items: center; - width: 100%; - gap: 16px; - margin: 20px 0; - color: var(--text-muted); - font-size: 13px; -} - -.welcome-divider::before, -.welcome-divider::after { - content: ""; - flex: 1; - height: 1px; - background: var(--border); -} - -.welcome-terminal-option { - width: 100%; - text-align: left; -} - -.welcome-terminal-label { - font-size: 13px; - color: var(--text-secondary); - margin-bottom: 8px; -} - -.welcome-terminal-box { - display: flex; - align-items: center; - gap: 8px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 10px 12px; - margin-bottom: 16px; -} - -.welcome-terminal-box code { - flex: 1; - font-family: var(--font-mono); - font-size: 12px; - color: var(--text-secondary); - word-break: break-all; - -webkit-user-select: text; - user-select: text; -} - -.welcome-copy-btn { - flex-shrink: 0; -} - -.welcome-recheck-btn { - padding: 10px 24px; -} - -.welcome-recheck-btn + .welcome-recheck-btn { - margin-top: 10px; -} - -.welcome-remote-card { - width: 100%; - max-width: 420px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 20px; - text-align: left; - display: flex; - flex-direction: column; - gap: 10px; -} - -.welcome-remote-label { - font-size: 13px; - font-weight: 500; - color: var(--text-secondary); -} - -.welcome-remote-row { - display: flex; - gap: 8px; - align-items: center; -} - -.welcome-remote-input { - flex: 1; - min-width: 0; - padding: 9px 12px; - border-radius: var(--radius-sm); - border: 1px solid var(--border); - background: var(--bg-primary); - color: var(--text-primary); - font-size: 13px; - font-family: var(--font-mono); - outline: none; - transition: border-color var(--transition); -} - -.welcome-remote-input:focus { - border-color: var(--accent); -} - -.welcome-remote-error { - font-size: 12px; - color: var(--error, #ef4444); - margin: 0; -} - -.welcome-remote-hint { - font-size: 12px; - color: var(--text-muted); - margin: 0; -} - /* ======================================================================== - INSTALL SCREEN + (truncated for brevity) ======================================================================== */ -.install-screen { - padding-top: 60px; - justify-content: flex-start; -} - -.install-title { - font-size: 22px; - font-weight: 700; - margin-bottom: 28px; - color: var(--text-primary); -} -.install-progress-container { - width: 100%; - max-width: 500px; - display: flex; - align-items: center; - gap: 12px; - margin-bottom: 20px; -} - -.install-progress-bar { - flex: 1; - height: 4px; - background: var(--bg-tertiary); - border-radius: 2px; - overflow: hidden; -} - -.install-progress-fill { - height: 100%; - background: var(--accent); - border-radius: 2px; - transition: width 0.5s ease; +/* Ensure per-bubble bidi isolation for mixed LTR/RTL content */ +.chat-bubble { + /* Isolate the bubble's directionality so mixed inline segments don't + leak direction to neighbouring UI or get re-ordered unexpectedly. */ + unicode-bidi: isolate; } -.install-percent { - font-size: 13px; - font-weight: 600; - color: var(--text-secondary); - min-width: 36px; +.chat-bubble[dir="rtl"] { text-align: right; - font-variant-numeric: tabular-nums; -} - -.install-step-info { - text-align: center; - margin-bottom: 8px; -} - -.install-step-title { - font-size: 14px; - font-weight: 600; - color: var(--text-primary); -} - -.install-step-detail { - font-size: 13px; - color: var(--text-secondary); - margin-top: 2px; -} - -.install-log { - width: 100%; - max-width: 620px; - flex: 1; - min-height: 200px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 16px; - margin-top: 20px; - overflow-y: auto; - font-family: var(--font-mono); - font-size: 12px; - color: var(--text-muted); - line-height: 1.7; - white-space: pre-wrap; - word-break: break-all; - -webkit-user-select: text; - user-select: text; -} - -.install-progress-fill--error { - background: var(--error) !important; -} - -.install-error-banner { - width: 100%; - max-width: 620px; - background: var(--error-bg); - border: 1px solid var(--error); - border-radius: var(--radius-md); - padding: 14px 16px; - display: flex; - flex-direction: column; - gap: 10px; -} - -/* Pre-install confirmation (issue #272) */ -.install-confirm { - width: 100%; - max-width: 620px; - display: flex; - flex-direction: column; - gap: 14px; - margin-top: 12px; -} - -.install-confirm-location { - display: flex; - flex-direction: column; - gap: 6px; -} - -.install-confirm-label { - font-size: 13px; - color: var(--text-secondary); -} - -.install-confirm-path { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 10px 12px; - font-family: var(--font-mono); - font-size: 12px; - color: var(--text-primary); - word-break: break-all; - -webkit-user-select: text; - user-select: text; -} - -.install-confirm-state { - font-size: 14px; - color: var(--text-primary); - margin: 0; -} - -.install-confirm-state--replace { - padding: 10px 12px; - background: var(--warning-bg); - border: 1px solid var(--warning); - border-radius: var(--radius-md); -} - -.install-confirm-note, -.install-confirm-hint { - font-size: 12px; - color: var(--text-secondary); - margin: 0; -} - -.install-confirm-hint { - color: var(--text-muted); -} - -.install-confirm-actions { - display: flex; - flex-wrap: wrap; - gap: 10px; - margin-top: 4px; -} - -.install-confirm-error { - font-size: 13px; - color: var(--error); - margin: 0; -} - -.verify-warning-banner { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 8px 14px; - background: var(--warning-bg); - border-radius: var(--radius-sm); - border: 0.5px solid var(--warning); - margin-bottom: 20px; -} - -.verify-warning-text { - font-size: 12px; - color: var(--text-primary); - line-height: 1.4; -} - -.verify-warning-actions { - display: flex; - gap: 6px; - flex-shrink: 0; -} - -.install-error-text { - font-size: 13px; - color: var(--error); - line-height: 1.5; - margin: 0; -} - -.install-error-actions { - display: flex; - gap: 8px; -} - -.install-error { - text-align: center; - margin-top: 16px; - color: var(--error); - font-size: 14px; - max-width: 500px; - line-height: 1.5; -} - -.install-done { - margin-top: 20px; -} - -/* ======================================================================== - SETUP SCREEN - ======================================================================== */ -.setup-screen { - padding: 48px 24px; - justify-content: flex-start; - overflow-y: auto; -} - -.setup-panel { - width: 100%; - max-width: min(640px, 92vw); - margin: 0 auto; - padding: 32px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-lg); - box-shadow: 0 12px 40px rgba(0, 0, 0, 0.28); -} - -.setup-title { - font-size: 22px; - font-weight: 700; - margin-bottom: 6px; - text-align: center; - color: var(--text-primary); -} - -.setup-subtitle { - font-size: 13.5px; - color: var(--text-secondary); - text-align: center; - margin-bottom: 24px; -} - -.setup-provider-grid { - display: grid; - grid-template-columns: repeat(4, 1fr); - gap: 8px; - width: 100%; - margin-bottom: 24px; -} - -.setup-provider-card { - position: relative; - display: flex; - flex-direction: column; - align-items: center; - gap: 9px; - padding: 14px 8px 12px; - background: var(--bg-primary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - cursor: pointer; - transition: all var(--transition); - font-family: var(--font-sans); - color: var(--text-primary); -} - -.setup-provider-card:hover { - border-color: var(--border-bright); - background: var(--bg-tertiary); - transform: translateY(-1px); -} - -.setup-provider-card.selected { - border-color: var(--accent-text); - background: var(--accent-subtle); - box-shadow: inset 0 0 0 1px var(--accent-text); -} - -.setup-provider-card:focus-visible { - outline: 2px solid var(--accent-text); - outline-offset: 2px; -} - -.setup-provider-logo { - display: grid; - place-items: center; - width: 40px; - height: 40px; - border-radius: 11px; - background: var(--bg-tertiary); - transition: background var(--transition); -} - -.setup-provider-card.selected .setup-provider-logo { - background: rgba(255, 255, 255, 0.07); -} - -.setup-provider-name { - font-size: 12px; - font-weight: 600; - line-height: 1.25; - text-align: center; - color: var(--text-secondary); -} - -.setup-provider-card.selected .setup-provider-name { - color: var(--text-primary); -} - -.setup-provider-check { - position: absolute; - top: 6px; - right: 6px; - display: grid; - place-items: center; - width: 16px; - height: 16px; - border-radius: 50%; - background: var(--accent-text); - color: #fff; -} - -.setup-form { - width: 100%; -} - -/* The Providers tab reuses the setup preset chips for its main provider - picker (flex-wrap, logo + name), consistent with the local/remote chips. */ -.providers-provider-chips { - margin-bottom: 10px; -} - -/* Section title that carries a trailing action (e.g. the provider "Change" - button) on its right edge. */ -.settings-section-title-row { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; -} - -/* Read-only provider summary shown when a provider is configured and the grid - is collapsed. */ -.provider-summary { - display: flex; - align-items: center; - gap: 12px; - padding: 12px 14px; - background: var(--bg-primary); - border: 1px solid var(--border); - border-radius: var(--radius-md); -} - -.provider-summary .brand-logo { - width: 24px; - height: 24px; - flex-shrink: 0; -} - -.provider-summary-name { - font-size: 14px; - font-weight: 600; - color: var(--text-primary); -} - -.provider-summary-meta { - font-size: 12px; - color: var(--text-muted); - margin-top: 2px; - word-break: break-all; -} - -.setup-label { - display: block; - font-size: 13px; - font-weight: 600; - color: var(--text-secondary); - margin-bottom: 8px; -} - -.setup-input-group { - position: relative; - margin-bottom: 12px; -} - -.setup-input-group .input { - padding-right: 60px; -} - -.setup-toggle-visibility { - position: absolute; - right: 8px; - top: 50%; - transform: translateY(-50%); - background: none; - border: none; - color: var(--text-muted); - font-size: 12px; - font-weight: 600; - cursor: pointer; - padding: 4px 8px; - border-radius: var(--radius-sm); - font-family: var(--font-sans); - transition: color var(--transition); } -.setup-toggle-visibility:hover { - color: var(--text-primary); -} - -.setup-link { - display: inline-flex; - align-items: center; - gap: 4px; - color: var(--accent-text); - font-size: 13px; - cursor: pointer; - border: none; - background: none; - padding: 0; - margin-bottom: 20px; - font-family: var(--font-sans); - transition: color var(--transition); -} - -.setup-link:hover { - color: var(--accent-hover); -} - -.setup-local-presets { - display: flex; - flex-wrap: wrap; - gap: 10px; - margin-bottom: 16px; -} - -.setup-local-preset { - display: inline-flex; - align-items: center; - gap: 7px; - padding: 6px 12px; - background: var(--bg-secondary); - border: 1.5px solid var(--border); - border-radius: var(--radius-sm); - cursor: pointer; - transition: all var(--transition); - font-family: var(--font-sans); - font-size: 13px; - font-weight: 600; - color: var(--text-secondary); -} - -.setup-local-preset .brand-logo { - width: 16px; - height: 16px; - opacity: 0.85; -} - -.setup-local-preset:hover { - border-color: var(--border-bright); -} - -.setup-local-preset.active { - border-color: var(--accent); - color: var(--accent-text); - background: var(--accent-subtle); -} - -.setup-field-hint { - font-size: 12px; - color: var(--text-muted); - margin-top: 6px; - margin-bottom: 16px; -} - -.setup-label-optional { - font-weight: 400; - color: var(--text-muted); - font-size: 12px; - margin-left: 4px; -} - -.setup-error { - color: var(--error); - font-size: 13px; - margin-bottom: 12px; -} - -.setup-continue { - width: 100%; - padding: 12px; - font-size: 15px; - margin-top: 4px; -} - -/* Keep the disabled CTA legible: a visibly dimmed (not invisible) label. */ -.setup-continue:disabled { - opacity: 0.45; - cursor: not-allowed; -} - -/* ======================================================================== - LAYOUT (Sidebar + Content) - ======================================================================== */ -.layout { - display: flex; - flex: 1; - overflow: hidden; -} - -.sidebar { - width: 250px; - background: var(--bg-secondary); - border-right: none; - display: flex; - flex-direction: column; - flex-shrink: 0; - /* Nav labels are controls, not content — don't let click/drag select text. */ - -webkit-user-select: none; - user-select: none; - transition: - width var(--transition), - padding var(--transition); - /* Flush full-height panel: square right edge against the content, left - corners kept rounded to follow the window's rounded corners. */ - border-radius: 16px 0 0 16px; -} - -.sidebar-collapsed .sidebar { - width: 64px; -} - -.sidebar-brand { - display: flex; - align-items: center; - justify-content: space-between; - gap: 10px; - padding: 20px 14px 20px 20px; - margin-top: 25px; -} - -.sidebar-logo { - height: 30px; - width: 150px; - /* Follow the foreground colour (white on dark themes, black on light) rather - than a fixed brand yellow, so the wordmark always reads against the bg. */ - background-color: var(--text-primary); - mask-repeat: no-repeat; - mask-position: center; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - -webkit-mask-position: center; - -webkit-mask-size: contain; -} - -.sidebar-collapse-toggle { - width: 30px; - height: 30px; - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - border: none; - border-radius: var(--radius-md); - background: transparent; - color: var(--text-muted); - cursor: pointer; - transition: all var(--transition); -} - -.sidebar-collapse-toggle:hover { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -/* Collapsed brand: circular mark by default, expand icon on hover. Both are - stacked in a fixed 16px box and toggled via opacity only, so the button - never reflows (no size jiggle). */ -.sidebar-collapse-swap { - position: relative; - width: 16px; - height: 16px; - flex-shrink: 0; -} - -.sidebar-collapse-mark { - position: absolute; - inset: 0; - margin: auto; - width: 20px; - height: 20px; - border-radius: 50%; - /* White on dark themes, dark on light — follows the foreground colour. */ - background: var(--text-primary); - transition: opacity var(--transition); -} - -.sidebar-collapse-expand-icon { - position: absolute; - inset: 0; - margin: auto; - opacity: 0; - transition: opacity var(--transition); -} - -.sidebar-collapse-toggle:hover .sidebar-collapse-mark, -.sidebar-collapse-toggle:focus-visible .sidebar-collapse-mark { - opacity: 0; -} - -.sidebar-collapse-toggle:hover .sidebar-collapse-expand-icon, -.sidebar-collapse-toggle:focus-visible .sidebar-collapse-expand-icon { - opacity: 1; -} - -.sidebar-collapsed .sidebar-brand { - justify-content: center; - padding: 18px 10px; - margin-top: 18px; -} - -.sidebar-collapsed .sidebar-logo { - display: none; -} - -.sidebar-brand-icon { - width: 30px; - height: 30px; - background: var(--accent); - border-radius: var(--radius-sm); - display: flex; - align-items: center; - justify-content: center; - font-size: 14px; - font-weight: 700; - color: #fff; -} - -.sidebar-brand-name { - font-size: 16px; - font-weight: 700; - color: var(--text-primary); -} - -.sidebar-nav { - flex: 0 0 auto; - padding: 0 8px; - display: flex; - flex-direction: column; - gap: 2px; -} - -.sidebar-chat-section { - flex: 1 1 auto; - min-height: 0; - min-width: 0; - padding: 8px 8px 0; - display: flex; - flex-direction: column; - gap: 2px; - overflow: hidden; -} - -.sidebar-collapsed .sidebar-nav { - padding: 0 10px; - align-items: center; -} - -.sidebar-collapsed .sidebar-chat-section { - flex: 1 1 auto; - min-height: auto; - padding: 8px 10px 0; - align-items: center; - overflow: visible; -} - -.sidebar-nav-item { - display: flex; - align-items: center; - gap: 10px; - padding: 7px 10px; - border-radius: var(--radius-md); - cursor: pointer; - transition: all var(--transition); - font-size: 13px; - border: none; - background: none; - width: 100%; - min-width: 0; - text-align: left; - font-family: var(--font-sans); -} - -.sidebar-new-chat { - flex: 0 0 auto; -} - -.sidebar-nav-label { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.sidebar-nav-item:hover { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.sidebar-nav-item.active { - background: var(--accent-subtle); - color: var(--accent-text); -} - -.sidebar-nav-item svg { - flex-shrink: 0; -} - -.sidebar-collapsed .sidebar-nav-item { - width: 40px; - height: 40px; - justify-content: center; - gap: 0; - padding: 0; -} - -.sidebar-collapsed .sidebar-nav-label { - display: none; -} - -/* Collapsible Sessions section (ChatGPT-style recent chats) */ -.sidebar-nav-sessions { - position: relative; - display: flex; - flex-direction: column; - gap: 2px; - min-height: 0; - min-width: 0; - flex: 1 1 auto; -} - -.sidebar-chat-scroll { - flex: 1 1 auto; - min-height: 0; - min-width: 0; - overflow-y: auto; - overflow-x: hidden; - scrollbar-width: none; - -ms-overflow-style: none; -} - -.sidebar-chat-scroll::-webkit-scrollbar { - width: 0; - height: 0; -} - -.sidebar-chat-scrollbar { - position: absolute; - top: 0; - right: 3px; - bottom: 0; - z-index: 3; - width: 6px; - pointer-events: none; - opacity: 0; - transition: opacity 160ms ease; -} - -.sidebar-chat-scrollbar.visible { - opacity: 1; -} - -.sidebar-chat-scrollbar-thumb { - width: 5px; - min-height: 32px; - border-radius: 999px; - background: color-mix(in srgb, var(--text-muted) 70%, transparent); -} - -.sidebar-collapsed .sidebar-nav-sessions { - flex: 0 0 auto; -} - -.sidebar-collapsed .sidebar-chat-scroll { - display: none; -} - -.sidebar-recent-sessions-wrap { - display: grid; - min-width: 0; - grid-template-rows: 0fr; - transition: - grid-template-rows 200ms ease, - opacity 200ms ease; - opacity: 0; -} - -.sidebar-recent-sessions-wrap.expanded { - grid-template-rows: 1fr; - opacity: 1; -} - -.sidebar-recent-sessions { - /* min-height:0 + overflow:hidden let the grid 0fr/1fr track clip cleanly. */ - min-height: 0; - min-width: 0; - overflow: visible; - display: flex; - flex-direction: column; - gap: 1px; - margin-bottom: 2px; -} - -.sidebar-recent-section { - min-width: 0; - display: flex; - flex-direction: column; -} - -.sidebar-recent-section-toggle { - width: 100%; - min-width: 0; - display: flex; - align-items: center; - gap: 8px; - margin: 8px 0 3px; - padding: 4px 14px; - border: none; - border-radius: var(--radius-md); - background: none; - color: var(--text-muted); - cursor: pointer; - font-family: var(--font-sans); - font-size: 11px; - font-weight: 500; - text-align: left; - transition: - background var(--transition), - color var(--transition); -} - -.sidebar-recent-section-toggle:hover { - color: var(--text-secondary); -} - -.sidebar-recent-section-toggle svg { - flex-shrink: 0; -} - -.sidebar-recent-section-toggle span { - flex: 1 1 auto; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.sidebar-recent-disclosure-icon { - margin-left: auto; - color: var(--text-muted); -} - -.sidebar-recent-collapse { - display: grid; - grid-template-rows: 0fr; - opacity: 0; - transition: - grid-template-rows 180ms ease, - opacity 180ms ease; -} - -.sidebar-recent-collapse.expanded { - grid-template-rows: 1fr; - opacity: 1; -} - -.sidebar-recent-collapse-inner { - min-height: 0; - min-width: 0; - overflow: hidden; - display: flex; - flex-direction: column; - gap: 1px; -} - -.sidebar-recent-project { - display: flex; - flex-direction: column; - gap: 1px; - min-width: 0; -} - -.sidebar-recent-project-heading { - width: 100%; - display: flex; - align-items: center; - gap: 7px; - min-width: 0; - padding: 6px 14px; - border: none; - border-radius: var(--radius-md); - background: none; - - cursor: pointer; - font-family: var(--font-sans); - font-size: 12px; - font-weight: 500; +.chat-bubble[dir="ltr"] { text-align: left; - transition: - background var(--transition), - color var(--transition); -} - -.sidebar-recent-project-heading:hover { - background: var(--bg-tertiary); -} - -.sidebar-recent-project-heading svg { - flex-shrink: 0; -} - -.sidebar-recent-project-heading span { - flex: 1 1 auto; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -@media (prefers-reduced-motion: reduce) { - .sidebar-recent-sessions-wrap, - .sidebar-recent-collapse { - transition: none; - } -} - -.sidebar-recent-session { - display: flex; - align-items: center; - gap: 9px; - width: 100%; - min-width: 0; - padding: 6px 10px; - border: none; - background: none; - border-radius: var(--radius-md); - cursor: pointer; - text-align: left; - font-family: var(--font-sans); - font-size: 12px; - - transition: all var(--transition); -} - -.sidebar-recent-session.project-child { - padding-left: 28px; -} - -.sidebar-recent-session-dot { - flex-shrink: 0; - color: var(--text-muted); -} - -.sidebar-recent-session-dot--active { - color: var(--accent-text, var(--accent)); -} - -.sidebar-recent-session-dot--loading { - color: var(--accent-text, var(--accent)); - animation: spin 0.8s linear infinite; -} - -.sidebar-recent-session:hover { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.sidebar-recent-session.active { - /* Active state is shown by the bullet + text color only — no filled - background (keeps the list visually quiet). */ - color: var(--accent-text); -} - -.sidebar-recent-session-title { - flex: 1 1 auto; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.sidebar-recent-empty { - padding: 6px 10px; - color: var(--text-muted); - font-size: 12px; -} - -.sidebar-recent-loading { - display: flex; - align-items: center; - gap: 9px; - padding: 6px 10px; - margin-top: 1px; - font-family: var(--font-sans); - font-size: 12px; - font-weight: 500; - color: var(--text-muted); -} - -/* ── Session row "options" affordance (ChatGPT-style …) ── */ -.sidebar-recent-session { - position: relative; -} - -.sidebar-recent-session-options { - position: absolute; - right: 4px; - top: 50%; - transform: translateY(-50%); - display: flex; - align-items: center; - justify-content: center; - width: 24px; - height: 24px; - padding: 0; - border: none; - border-radius: var(--radius-sm, 6px); - background: var(--bg-tertiary); - color: var(--text-secondary); - cursor: pointer; - opacity: 0; - transition: - opacity var(--transition), - background var(--transition), - color var(--transition); -} - -/* Reveal the … on hover/focus of the row, or while its menu is open. */ -.sidebar-recent-session:hover .sidebar-recent-session-options, -.sidebar-recent-session:focus-within .sidebar-recent-session-options, -.sidebar-recent-session.menu-open .sidebar-recent-session-options { - opacity: 1; -} - -.sidebar-recent-session-options:hover { - background: var(--bg-elevated); - color: var(--text-primary); -} - -/* Keep the title clear of the … control when it is visible. */ -.sidebar-recent-session:hover .sidebar-recent-session-title, -.sidebar-recent-session:focus-within .sidebar-recent-session-title, -.sidebar-recent-session.menu-open .sidebar-recent-session-title { - padding-right: 24px; -} - -.sidebar-recent-session.menu-open { - background: var(--bg-tertiary); -} - -.sidebar-recent-session.editing { - padding: 3px 10px; -} - -.sidebar-recent-session-rename { - flex: 1 1 auto; - min-width: 0; - padding: 4px 6px; - border: 1px solid var(--accent, var(--border-bright)); - border-radius: var(--radius-sm, 6px); - background: var(--bg-primary, var(--bg-secondary)); - color: var(--text-primary); - font-family: var(--font-sans); - font-size: 12px; - outline: none; -} - -/* ── Floating session context menu (portal to body) ── */ -.sidebar-session-menu { - position: fixed; - z-index: 1000; - display: flex; - flex-direction: column; - padding: 4px; - border: 1px solid var(--border-bright); - border-radius: var(--radius-md); - background: var(--bg-elevated); - box-shadow: 0 12px 32px rgba(0, 0, 0, 0.36); - font-family: var(--font-sans); - /* Open animation scales from the anchored top-left corner. */ - transform-origin: top left; - will-change: transform, opacity; -} - -/* Height-animating wrapper (motion `layout`) that clips the cross-sliding - pages so neither spills past the rounded menu edge during the swap. */ -.sidebar-session-menu-body { - position: relative; - min-width: 0; - overflow: hidden; -} - -.sidebar-session-menu-page { - display: flex; - flex-direction: column; - min-width: 0; -} - -/* While a page is exiting (popLayout pins it absolutely), it must overlay the - incoming page at full width rather than collapse. */ -.sidebar-session-menu-body > .sidebar-session-menu-page { - width: 100%; -} - -.sidebar-session-menu-item { - display: flex; - align-items: center; - gap: 10px; - width: 100%; - padding: 7px 10px; - border: none; - border-radius: var(--radius-sm, 6px); - background: none; - color: var(--text-primary); - cursor: pointer; - font-family: inherit; - font-size: 13px; - text-align: left; - transition: - background var(--transition), - color var(--transition); -} - -.sidebar-session-menu-item svg { - flex-shrink: 0; - color: var(--text-secondary); -} - -.sidebar-session-menu-item span { - flex: 1 1 auto; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.sidebar-session-menu-item:hover { - background: var(--bg-tertiary); -} - -.sidebar-session-menu-item--danger { - color: var(--error); -} - -.sidebar-session-menu-item--danger svg { - color: var(--error); -} - -.sidebar-session-menu-chevron { - flex: 0 0 auto !important; - margin-left: auto; -} - -.sidebar-session-menu-divider { - height: 1px; - margin: 4px 6px; - background: var(--border-bright); -} - -.sidebar-session-menu-back { - display: flex; - align-items: center; - gap: 8px; - width: 100%; - padding: 7px 10px; - border: none; - border-radius: var(--radius-sm, 6px); - background: none; - color: var(--text-secondary); - cursor: pointer; - font-family: inherit; - font-size: 12px; - font-weight: 500; - text-align: left; -} - -.sidebar-session-menu-back:hover { - color: var(--text-primary); -} - -.sidebar-session-menu-back-icon { - transform: rotate(180deg); -} - -.sidebar-session-menu-scroll { - display: flex; - flex-direction: column; - max-height: 220px; - overflow-y: auto; -} - -.sidebar-session-menu-project-name { - flex: 1 1 auto; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.sidebar-session-menu-check { - flex: 0 0 auto !important; - margin-left: auto; - color: var(--accent-text, var(--accent)) !important; -} - -.sidebar-session-menu-empty { - padding: 8px 10px; - color: var(--text-muted); - font-size: 12px; -} - -/* ── Sidebar delete confirmation (portal to body) ── */ -.sidebar-session-delete-overlay { - position: fixed; - inset: 0; - z-index: 1100; - display: flex; - align-items: center; - justify-content: center; - background: rgba(0, 0, 0, 0.45); -} - -.sidebar-session-delete-modal { - width: min(360px, calc(100vw - 32px)); - padding: 18px; - border: 1px solid var(--border-bright); - border-radius: var(--radius-lg); - background: var(--bg-secondary); - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4); -} - -.sidebar-session-delete-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - margin-bottom: 10px; -} - -.sidebar-session-delete-header h3 { - margin: 0; - font-size: 15px; - font-weight: 600; - color: var(--text-primary); -} - -.sidebar-session-delete-close { - display: flex; - align-items: center; - justify-content: center; -} - -.sidebar-session-delete-body { - margin: 0 0 18px; - color: var(--text-secondary); - font-size: 13px; - line-height: 1.5; -} - -.sidebar-session-delete-footer { - display: flex; - justify-content: flex-end; - gap: 8px; -} - -/* Full-list sessions modal (sidebar "Show more" / Cmd+K). Reuses - .models-modal-overlay for the backdrop; sized to 80% of the viewport. */ -.sessions-modal { - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-lg); - width: 80vw; - height: 80vh; - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4); - overflow: hidden; - display: flex; - flex-direction: column; -} - -/* ── Profile avatar (shared: nav, active bar, manage page) ── */ -.profile-avatar { - flex-shrink: 0; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - overflow: hidden; - line-height: 1; -} -.profile-avatar-img { - object-fit: cover; -} -.profile-avatar-letter { - color: #fff; - font-weight: 700; -} -.profile-avatar-logo { - background: var(--bg-elevated); -} - -/* ── Active sessions bar (concurrent / multi-agent runs) ── */ -.active-sessions-bar { - display: flex; - /* Tabs stretch to the full strip height so the active tab's fill reaches the - bottom edge and merges seamlessly into the content below. */ - align-items: stretch; - gap: 0; - /* This strip IS the window's title-bar drag region (browser-style): empty - space drags the window. It sits above the global .drag-region (z 1000) so - it owns the top band of the content column; the chips opt back out of - dragging (no-drag) so they stay clickable. Always present — with no extra - tabs it's simply an empty drag area, costing no dedicated bar height. */ - position: relative; - z-index: 1001; - -webkit-app-region: drag; - min-height: 34px; - padding: 0 8px 0 12px; - overflow-x: auto; - /* Darker toolbar shade so the lighter active tab (--bg-primary) reads as - part of the page below it. */ - background: var(--bg-secondary); - flex-shrink: 0; - /* Scrollable but with no visible scrollbar. */ - scrollbar-width: none; - -ms-overflow-style: none; -} - -.active-sessions-bar::-webkit-scrollbar { - display: none; -} - -/* Flat tab: no border or fill, just text. Adjacent tabs are separated by a thin - vertical divider (::before); the active tab fills with the page colour and - rounds its top so it looks docked to the content beneath. */ -.active-session-chip { - display: flex; - align-items: center; - gap: 6px; - max-width: 160px; - flex-shrink: 0; - /* Opt out of the strip's drag region so the chip is clickable. */ - -webkit-app-region: no-drag; - position: relative; - padding: 0 12px; - border: none; - border-radius: 8px 8px 0 0; - background: transparent; - color: var(--text-secondary); - cursor: pointer; - font-family: var(--font-sans); - font-size: 12px; - white-space: nowrap; - transition: - background var(--transition), - color var(--transition); -} - -/* Divider between two adjacent tabs (drawn on the right tab's left edge). */ -.active-session-chip + .active-session-chip::before { - content: ""; - position: absolute; - left: 0; - top: 50%; - transform: translateY(-50%); - width: 1px; - height: 16px; - background: var(--border-bright); -} - -.active-session-chip:hover { - color: var(--text-primary); - background: rgba(255, 255, 255, 0.05); -} - -.active-session-chip.active { - /* Same colour as the content area below → the tab merges into the page. */ - background: var(--bg-primary); - color: var(--text-primary); -} - -/* Drop the dividers flanking the active tab so it reads as one docked panel. */ -.active-session-chip.active::before, -.active-session-chip.active + .active-session-chip::before { - opacity: 0; -} - -/* Loading state reuses an avatar-sized circle filled with the profile colour - (set inline) so the spinner reads as "this agent is working". */ -.active-session-chip-avatar { - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - width: 18px; - height: 18px; - border-radius: 50%; - line-height: 1; -} - -.active-session-chip-spinner { - flex-shrink: 0; - /* Sits on the profile's colour-filled avatar circle. */ - color: #fff; - animation: spin 0.8s linear infinite; -} - -.active-session-chip-title { - flex: 1; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - opacity: 0.7; -} - -/* The focused tab's label reads at full strength. */ -.active-session-chip.active .active-session-chip-title, -.active-session-chip:hover .active-session-chip-title { - opacity: 1; -} - -.active-session-chip-close { - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - padding: 0; - border: none; - border-radius: 4px; - background: none; - color: inherit; - cursor: pointer; - /* Revealed on hover / for the active tab to keep idle chips clean. */ - opacity: 0; - transition: opacity var(--transition); -} -.active-session-chip:hover .active-session-chip-close, -.active-session-chip.active .active-session-chip-close, -.active-session-chip-close:focus-visible { - opacity: 0.7; -} -.active-session-chip-close:hover { - opacity: 1; - background: var(--bg-elevated); -} - -/* Browser-style new-tab button at the end of the strip. Sits above the drag - region so it stays clickable. */ -.active-session-new { - -webkit-app-region: no-drag; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - width: 28px; - height: 28px; - margin-left: 4px; - margin-top: 4px; - padding: 0; - border: none; - border-radius: 6px; - background: none; - color: var(--text-secondary); - cursor: pointer; - transition: - background var(--transition), - color var(--transition); -} -.active-session-new:hover { - background: var(--bg-elevated); - color: var(--text-primary); -} - -/* Sidebar footer with theme switcher */ -.sidebar-footer { - padding: 12px; - display: flex; - flex-direction: column; - gap: 8px; -} - -.sidebar-collapsed .sidebar-footer { - align-items: center; - margin-top: auto; - padding: 10px; -} - -.sidebar-footer-actions { - display: grid; - grid-template-columns: repeat(5, minmax(0, 1fr)); - gap: 4px; - width: 100%; -} - -.sidebar-footer-action { - position: relative; - width: 100%; - height: 34px; - display: inline-flex; - align-items: center; - justify-content: center; - border: none; - border-radius: var(--radius-md); - background: transparent; - color: var(--text-muted); - cursor: pointer; - transition: - background var(--transition), - color var(--transition); -} - -.sidebar-footer-action:hover { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.sidebar-footer-action.active { - background: var(--accent-subtle); - color: var(--accent-text); -} - -.sidebar-footer-action svg { - flex-shrink: 0; -} - -.sidebar-footer-action[data-tooltip]::after { - content: attr(data-tooltip); - position: absolute; - left: 50%; - top: -8px; - z-index: 60; - transform: translate(-50%, -100%); - pointer-events: none; - opacity: 0; - white-space: nowrap; - padding: 5px 7px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-elevated); - color: var(--text-primary); - box-shadow: var(--shadow-md); - font-size: 11px; - font-weight: 500; - line-height: 1; - transition: opacity 120ms ease; -} - -.sidebar-footer-action[data-tooltip]:first-child::after { - left: 0; - transform: translateY(-100%); -} - -.sidebar-footer-action[data-tooltip]:last-child::after { - left: auto; - right: 0; - transform: translateY(-100%); -} - -.sidebar-footer-action[data-tooltip]:hover::after, -.sidebar-footer-action[data-tooltip]:focus-visible::after { - opacity: 1; -} - -.sidebar-collapsed .sidebar-footer-actions { - grid-template-columns: 40px; - justify-content: center; - gap: 2px; -} - -.sidebar-collapsed .sidebar-footer-action { - width: 40px; - height: 40px; - border-radius: var(--radius-md); -} - -.sidebar-collapsed .sidebar-footer-action svg { - width: 16px; - height: 16px; -} - -.sidebar-collapsed .sidebar-footer-action[data-tooltip]::after, -.sidebar-collapsed .sidebar-footer-action[data-tooltip]:first-child::after, -.sidebar-collapsed .sidebar-footer-action[data-tooltip]:last-child::after { - left: calc(100% + 8px); - right: auto; - top: 50%; - transform: translateY(-50%); -} - -/* ── Profile switcher (sidebar footer) ──────────────────── */ -.profile-switcher { - position: relative; - width: 100%; -} - -.profile-switcher.compact { - width: 40px; -} - -.profile-switcher-trigger { - display: flex; - align-items: center; - gap: 8px; - width: 100%; - padding: 8px 10px; - background: none; - border: 1px solid transparent; - border-radius: var(--radius-md); - color: var(--text-secondary); - font-size: 13px; - font-weight: 500; - font-family: var(--font-sans); - cursor: pointer; - text-align: left; - transition: all var(--transition); -} - -.profile-switcher.compact .profile-switcher-trigger { - width: 40px; - height: 40px; - justify-content: center; - gap: 0; - padding: 0; -} - -.profile-switcher-trigger:hover, -.profile-switcher-trigger.open { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.profile-switcher-name { - flex: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.profile-switcher-chevron { - flex-shrink: 0; - color: var(--text-muted); - transition: transform var(--transition); -} - -.profile-switcher-trigger.open .profile-switcher-chevron { - transform: rotate(180deg); -} - -/* Profile icon — green when that profile's gateway is running. */ -.profile-icon { - flex-shrink: 0; - color: var(--text-muted); -} - -.profile-icon.running { - color: var(--success, #22c55e); -} - -/* Popover menu, anchored above the trigger. */ -.profile-menu { - position: absolute; - bottom: calc(100% + 8px); - left: 0; - right: 0; - min-width: 260px; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-lg); - box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4); - padding: 6px; - z-index: 200; - animation: profileMenuIn 0.12s ease; -} - -.profile-switcher.compact .profile-menu { - left: calc(100% + 8px); - right: auto; - bottom: 0; -} - -@keyframes profileMenuIn { - from { - opacity: 0; - transform: translateY(4px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.profile-menu-active-section { - display: flex; - align-items: center; - gap: 12px; - width: 100%; - padding: 12px 10px 14px; - border: none; - border-radius: var(--radius-md); - background: transparent; - color: inherit; - font: inherit; - text-align: left; - cursor: pointer; - transition: background var(--transition); -} - -.profile-menu-active-section:hover { - background: var(--bg-tertiary); -} - -.profile-menu-avatar { - position: relative; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; -} - -.profile-menu-avatar-dot { - position: absolute; - bottom: 1px; - right: 1px; - width: 10px; - height: 10px; - border-radius: 50%; - background: var(--success); - border: 2px solid var(--bg-secondary); -} - -.profile-menu-active-section .profile-menu-name { - font-size: 14px; - font-weight: 600; -} - -.profile-menu-active-section .profile-menu-meta { - font-size: 12px; -} - -.profile-menu-divider { - height: 1px; - background: var(--border); - margin: 0 4px; -} - -.profile-menu-list { - display: flex; - flex-direction: column; - gap: 2px; - max-height: 260px; - overflow-y: auto; - padding-top: 4px; -} - -.profile-menu-item { - display: flex; - align-items: center; - gap: 10px; - width: 100%; - padding: 8px 10px; - background: none; - border: none; - border-radius: var(--radius-md); - cursor: pointer; - text-align: left; - font-family: var(--font-sans); - transition: background var(--transition); -} - -.profile-menu-item:hover { - background: var(--bg-tertiary); -} - -.profile-menu-item.active { - background: var(--accent-subtle); -} - -.profile-menu-info { - flex: 1; - display: flex; - flex-direction: column; - gap: 2px; - min-width: 0; -} - -.profile-menu-name { - display: flex; - align-items: center; - gap: 6px; - font-size: 13px; - font-weight: 600; - color: var(--text-primary); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.profile-menu-tag { - font-size: 11px; - font-weight: 500; - color: var(--text-muted); -} - -.profile-menu-gateway { - flex-shrink: 0; - margin-left: auto; - width: 8px; - height: 8px; - border-radius: 50%; - background: var(--text-muted); - opacity: 0.4; -} - -.profile-menu-gateway.active { - background: var(--success); - opacity: 1; -} - -.profile-menu-meta { - font-size: 11px; - color: var(--text-muted); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.profile-menu-check { - flex-shrink: 0; - color: var(--accent-text, var(--accent)); -} - -.profile-menu-manage { - display: flex; - align-items: center; - gap: 8px; - width: 100%; - margin-top: 6px; - padding: 9px 10px; - background: none; - border: none; - border-top: 1px solid var(--border); - border-radius: 0 0 var(--radius-md) var(--radius-md); - color: var(--text-secondary); - font-size: 13px; - font-weight: 500; - font-family: var(--font-sans); - cursor: pointer; - text-align: left; - transition: all var(--transition); -} - -.profile-menu-manage:hover { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.profile-menu-manage svg { - flex-shrink: 0; - color: var(--text-muted); -} - -.sidebar-update-btn { - display: flex; - align-items: center; - gap: 6px; - width: 100%; - padding: 6px 10px; - margin-bottom: 8px; - background: var(--accent); - border: none; - border-radius: 6px; - color: #fff; - font-size: 11px; - font-weight: 600; - cursor: pointer; - transition: background var(--transition); -} - -.sidebar-collapsed .sidebar-update-btn { - width: 40px; - height: 40px; - justify-content: center; - padding: 0; - margin-bottom: 0; -} - -.sidebar-collapsed .sidebar-update-btn span { - display: none; -} - -.sidebar-update-btn:hover { - background: var(--accent-hover); -} - -.sidebar-update-btn:disabled { - cursor: default; - opacity: 0.75; -} - -.sidebar-update-btn:disabled:hover { - background: var(--accent); -} - -.sidebar-update-btn.error { - background: var(--error); -} - -.sidebar-update-btn.error:hover { - background: var(--error); -} - -/* Theme Switcher */ -.theme-switcher { - display: flex; - background: var(--bg-tertiary); - border-radius: var(--radius-sm); - padding: 2px; - gap: 2px; -} - -.theme-switcher-btn { - flex: 1; - display: flex; - align-items: center; - justify-content: center; - padding: 5px 0; - border: none; - background: transparent; - border-radius: 4px; - cursor: pointer; - color: var(--text-muted); - transition: all var(--transition); -} - -.theme-switcher-btn:hover { - color: var(--text-secondary); -} - -.theme-switcher-btn.active { - background: var(--bg-elevated); - color: var(--text-primary); -} - -.content { - flex: 1; - overflow: hidden; - display: flex; - flex-direction: column; -} - -/* ======================================================================== - CHAT - ======================================================================== */ -.chat-container { - display: flex; - flex-direction: column; - height: 100%; - position: relative; -} - -/* Chat body: holds messages and worktree panel side by side */ -.chat-body { - display: flex; - flex: 1; - overflow: hidden; -} - -/* Worktree panel - file explorer on the right */ -.worktree-panel { - width: 240px; - flex-shrink: 0; - background: var(--bg-secondary); - border-left: 1px solid var(--border); - display: flex; - flex-direction: column; - overflow: hidden; - position: relative; -} - -/* Drag handle on the left edge to free-resize the context folder tree. */ -.worktree-resize-handle { - position: absolute; - left: -3px; - top: 0; - width: 7px; - height: 100%; - cursor: col-resize; - z-index: 20; - background: transparent; - transition: background var(--transition); -} - -.worktree-resize-handle:hover, -.worktree-resize-handle-active { - background: color-mix(in srgb, var(--accent-text) 45%, transparent); -} - -.worktree-header { - display: flex; - align-items: center; - gap: 8px; - padding: 7px 12px; - border-bottom: 1px solid var(--border); - background: var(--bg-tertiary); - flex-shrink: 0; -} - -.worktree-header-icon { - color: var(--accent-text); - flex-shrink: 0; -} - -.worktree-header-title { - flex: 1; - min-width: 0; - font-size: 13px; - font-weight: 600; - color: var(--text-primary); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.worktree-header-action { - width: 26px; - height: 26px; - flex-shrink: 0; - display: inline-flex; - align-items: center; - justify-content: center; - padding: 0; - color: var(--accent-text); - opacity: 1; - background: transparent; - border: 0; - border-radius: 6px; -} - -.worktree-header-action:hover { - opacity: 1; - color: var(--accent-text); - background: color-mix(in srgb, var(--accent-text) 10%, transparent); -} - -.worktree-header-action svg { - width: 18px; - height: 18px; - stroke-width: 2.2; -} - -.worktree-terminal-error { - padding: 8px 12px; - font-size: 12px; - line-height: 1.4; - color: var(--error); - border-top: 1px solid var(--border); - background: var(--error-bg); -} - -.worktree-content { - flex: 1; - overflow-y: auto; - padding: 8px 0; -} - -.worktree-row { - display: flex; - align-items: center; - gap: 4px; - padding: 4px 8px; - cursor: pointer; - transition: background-color var(--transition); - user-select: none; -} - -.worktree-row:hover { - background: var(--bg-hover); -} - -.worktree-chevron { - display: flex; - align-items: center; - justify-content: center; - width: 14px; - height: 14px; - color: var(--text-muted); - flex-shrink: 0; -} - -.worktree-chevron-placeholder { - display: inline-block; - width: 14px; - height: 14px; - flex-shrink: 0; -} - -.worktree-icon { - flex-shrink: 0; -} - -.worktree-folder-icon { - color: rgba(255, 255, 255, 0.56); -} - -.worktree-file-icon { - color: var(--text-muted); -} - -.worktree-name { - font-size: 12px; - color: var(--text-primary); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.worktree-loading, -.worktree-empty { - font-size: 12px; - color: var(--text-muted); - padding: 8px 14px; -} - -.worktree-error { - font-size: 12px; - color: var(--error); - padding: 8px 14px; -} - -/* File viewer modal */ -.file-viewer-overlay { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: rgba(0, 0, 0, 0.7); - display: flex; - align-items: center; - justify-content: center; - z-index: 1000; - padding: 40px; -} - -.file-viewer-modal { - background: #1e1e1e; - border: 1px solid #333; - border-radius: 8px; - width: 100%; - max-width: 900px; - height: 85vh; - display: flex; - flex-direction: column; - overflow: hidden; - box-shadow: 0 12px 40px rgba(0, 0, 0, 0.6); -} - -.file-viewer-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 12px 16px; - border-bottom: 1px solid #333; - background: #252526; - flex-shrink: 0; -} - -.file-viewer-title { - display: flex; - align-items: center; - gap: 10px; - min-width: 0; -} - -.file-viewer-icon { - color: #858585; - flex-shrink: 0; -} - -.file-viewer-filename { - font-size: 13px; - font-weight: 500; - color: #cccccc; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-family: var(--font-mono); -} - -.file-viewer-size { - font-size: 11px; - color: #858585; - margin-left: 8px; - font-family: var(--font-mono); -} - -.file-viewer-actions { - display: flex; - align-items: center; - gap: 4px; -} - -.file-viewer-open { - opacity: 0.8; - padding: 6px 10px; - color: #cccccc; - display: flex; - align-items: center; - gap: 6px; - font-size: 12px; -} - -.file-viewer-open:hover { - opacity: 1; - background: #3c3c3c; - border-radius: 4px; -} - -.file-viewer-open-text { - font-size: 12px; - font-weight: 500; -} - -.file-viewer-close { - opacity: 0.7; - padding: 6px; - color: #cccccc; -} - -.file-viewer-close:hover { - opacity: 1; - background: #3c3c3c; - border-radius: 4px; -} - -/* Binary file placeholder */ -.file-viewer-binary { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100%; - gap: 12px; - color: #858585; -} - -.file-viewer-binary-icon { - font-size: 48px; - opacity: 0.5; -} - -.file-viewer-binary-text { - font-size: 14px; - font-weight: 500; - color: #cccccc; -} - -.file-viewer-binary-hint { - font-size: 12px; - color: #858585; -} - -/* Image viewer styles */ -.file-viewer-image-container { - display: flex; - align-items: center; - justify-content: center; - height: 100%; - padding: 20px; - background: #1e1e1e; - overflow: auto; -} - -.file-viewer-image { - max-width: 100%; - max-height: 100%; - object-fit: contain; - border-radius: 4px; - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5); -} - -.file-viewer-content { - flex: 1; - overflow: auto; - background: #1e1e1e; -} - -.file-viewer-loading, -.file-viewer-error { - display: flex; - align-items: center; - justify-content: center; - height: 100%; - font-size: 14px; - color: #858585; -} - -.file-viewer-error { - color: #f48771; -} - -.file-viewer-truncated { - padding: 10px 16px; - background: rgba(255, 204, 0, 0.1); - border-bottom: 1px solid #333; - font-size: 12px; - color: #cccccc; - font-family: var(--font-mono); -} - -/* VS Code-like code viewer with line numbers */ -.file-viewer-code { - margin: 0; - padding: 0; - background: #1e1e1e; - font-family: var(--font-mono); - font-size: 13px; - line-height: 1.5; - display: flex; -} - -.file-viewer-code code { - display: block; - padding: 16px; - padding-left: 16px; - background: #1e1e1e; - color: #d4d4d4; - white-space: pre; - overflow-x: auto; - tab-size: 2; -} - -/* Custom scrollbar for file viewer */ -.file-viewer-content::-webkit-scrollbar { - width: 10px; - height: 10px; -} - -.file-viewer-content::-webkit-scrollbar-track { - background: #1e1e1e; -} - -.file-viewer-content::-webkit-scrollbar-thumb { - background: #424242; - border-radius: 5px; -} - -.file-viewer-content::-webkit-scrollbar-thumb:hover { - background: #4f4f4f; -} - -/* Override highlight.js styles for VS Code dark theme look */ -.file-viewer-modal .hljs { - background: #1e1e1e; - color: #d4d4d4; -} - -/* Keyword - blue */ -.file-viewer-modal .hljs-keyword, -.file-viewer-modal .hljs-selector-tag, -.file-viewer-modal .hljs-subst { - color: #569cd6; - font-weight: normal; -} - -/* String - orange/red */ -.file-viewer-modal .hljs-string, -.file-viewer-modal .hljs-regexp, -.file-viewer-modal .hljs-addition, -.file-viewer-modal .hljs-attribute { - color: #ce9178; -} - -/* Number - light green */ -.file-viewer-modal .hljs-number, -.file-viewer-modal .hljs-literal { - color: #b5cea8; -} - -/* Function/method - yellow */ -.file-viewer-modal .hljs-title, -.file-viewer-modal .hljs-title.class_, -.file-viewer-modal .hljs-title.function_, -.file-viewer-modal .hljs-built_in { - color: #dcdcaa; -} - -/* Variable - light blue */ -.file-viewer-modal .hljs-variable, -.file-viewer-modal .hljs-template-variable, -.file-viewer-modal .hljs-params { - color: #9cdcfe; -} - -/* Property - light blue */ -.file-viewer-modal .hljs-property, -.file-viewer-modal .hljs-attr { - color: #9cdcfe; -} - -/* Comment - green */ -.file-viewer-modal .hljs-comment, -.file-viewer-modal .hljs-quote { - color: #6a9955; - font-style: italic; -} - -/* Operator - light */ -.file-viewer-modal .hljs-operator, -.file-viewer-modal .hljs-punctuation { - color: #d4d4d4; -} - -/* Tag (HTML/XML) - blue */ -.file-viewer-modal .hljs-tag { - color: #569cd6; -} - -/* Tag name - red */ -.file-viewer-modal .hljs-name { - color: #569cd6; -} - -/* Tag attribute - light blue */ -.file-viewer-modal .hljs-attr { - color: #9cdcfe; -} - -/* CSS property - light blue */ -.file-viewer-modal .hljs-selector-id, -.file-viewer-modal .hljs-selector-class, -.file-viewer-modal .hljs-selector-attr, -.file-viewer-modal .hljs-selector-pseudo { - color: #d7ba7d; -} - -/* Type/Class - greenish */ -.file-viewer-modal .hljs-type, -.file-viewer-modal .hljs-class_ { - color: #4ec9b0; -} - -/* Meta - gray */ -.file-viewer-modal .hljs-meta { - color: #808080; -} - -/* Emphasis - bold */ -.file-viewer-modal .hljs-emphasis { - font-style: italic; -} - -/* Strong - bold */ -.file-viewer-modal .hljs-strong { - font-weight: bold; -} - -/* Built-in constant */ -.file-viewer-modal .hljs-built_in, -.file-viewer-modal .hljs-builtin-name { - color: #dcdcaa; -} - -/* Clickable file rows in worktree */ -.worktree-row-file { - cursor: pointer; -} - -.worktree-row-file:hover .worktree-name { - color: var(--accent-text); -} - -/* File icon wrapper for react-file-icon */ -.worktree-file-icon-wrapper { - width: 18px; - height: 18px; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; - color: rgba(255, 255, 255, 0.56); -} - -.worktree-file-icon-wrapper svg { - width: 100%; - height: 100%; -} - -.worktree-file-icon-wrapper svg * { - fill: currentColor !important; -} - -.worktree-file-icon-wrapper svg [fill="none"], -.worktree-file-icon-wrapper svg [style*="fill:none"] { - fill: none !important; -} - -.worktree-file-icon-wrapper svg [stroke]:not([stroke="none"]), -.worktree-file-icon-wrapper svg [style*="stroke:"] { - stroke: currentColor !important; -} - -.folder-picker-overlay { - position: fixed; - inset: 0; - z-index: 1200; - display: flex; - align-items: center; - justify-content: center; - padding: 24px; - background: rgba(0, 0, 0, 0.54); -} - -.folder-picker-modal { - display: flex; - width: min(680px, calc(100vw - 32px)); - max-height: min(620px, calc(100vh - 48px)); - min-height: 420px; - flex-direction: column; - overflow: hidden; - border: 1px solid var(--border); - border-radius: 8px; - background: var(--surface); - color: var(--text-primary); - box-shadow: 0 20px 70px rgba(0, 0, 0, 0.4); -} - -.folder-picker-header, -.folder-picker-footer { - display: flex; - flex-shrink: 0; - align-items: center; - gap: 10px; - padding: 10px 12px; - border-bottom: 1px solid var(--border); -} - -.folder-picker-footer { - justify-content: flex-end; - border-top: 1px solid var(--border); - border-bottom: 0; -} - -.folder-picker-title { - display: flex; - min-width: 0; - flex: 1; - align-items: center; - gap: 8px; - font-size: 13px; - font-weight: 600; -} - -.folder-picker-title svg { - color: var(--accent-text); -} - -.folder-picker-path-row { - display: flex; - flex-shrink: 0; - align-items: center; - gap: 8px; - padding: 10px 12px 8px; -} - -.folder-picker-input { - min-width: 0; - flex: 1; - height: 30px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--surface-elevated); - color: var(--text-primary); - font-family: var(--font-mono); - font-size: 12px; - outline: none; - padding: 0 9px; -} - -.folder-picker-input:focus { - border-color: var(--accent-text); - box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-text) 20%, transparent); -} - -.folder-picker-icon-btn { - display: inline-flex; - width: 28px; - height: 28px; - flex-shrink: 0; - align-items: center; - justify-content: center; - border: 0; - border-radius: 6px; - background: transparent; - color: var(--text-secondary); - cursor: pointer; -} - -.folder-picker-icon-btn:hover:not(:disabled), -.folder-picker-icon-btn:focus-visible { - background: var(--surface-hover); - color: var(--text-primary); - outline: none; -} - -.folder-picker-icon-btn:disabled { - cursor: default; - opacity: 0.35; -} - -.folder-picker-breadcrumbs { - display: flex; - flex-shrink: 0; - gap: 4px; - overflow-x: auto; - padding: 0 12px 10px; - scrollbar-width: thin; -} - -.folder-picker-crumb { - display: inline-flex; - max-width: 180px; - flex-shrink: 0; - align-items: center; - gap: 4px; - border: 0; - border-radius: 5px; - background: transparent; - color: var(--text-secondary); - cursor: pointer; - font-size: 12px; - padding: 4px 6px; -} - -.folder-picker-crumb span { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.folder-picker-crumb:hover, -.folder-picker-crumb:focus-visible { - background: var(--surface-hover); - color: var(--text-primary); - outline: none; -} - -.folder-picker-list { - min-height: 0; - flex: 1; - overflow-y: auto; - padding: 4px 8px 8px; - scrollbar-width: thin; -} - -.folder-picker-list:focus-visible { - outline: 2px solid color-mix(in srgb, var(--accent-text) 38%, transparent); - outline-offset: -2px; -} - -.folder-picker-row { - display: flex; - width: 100%; - min-width: 0; - align-items: center; - gap: 9px; - border: 0; - border-radius: 6px; - background: transparent; - color: var(--text-primary); - cursor: pointer; - font-size: 13px; - padding: 7px 9px; - text-align: left; -} - -.folder-picker-row svg { - flex-shrink: 0; - color: rgba(255, 255, 255, 0.58); -} - -.folder-picker-row span { - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.folder-picker-row:hover, -.folder-picker-row:focus-visible, -.folder-picker-row-active { - background: var(--surface-hover); - outline: none; -} - -.folder-picker-row-active { - color: var(--accent-text); -} - -.folder-picker-state { - display: flex; - min-height: 180px; - align-items: center; - justify-content: center; - gap: 8px; - padding: 16px; - color: var(--text-secondary); - font-size: 13px; - text-align: center; -} - -.folder-picker-loader { - animation: spin 0.9s linear infinite; -} - -/* Worktree toggle button in header */ -.chat-worktree-toggle { - opacity: 0.5; - margin-left: 2px; - transition: - opacity 0.15s, - color 0.15s; -} - -.chat-worktree-toggle:hover { - opacity: 0.8; -} - -.chat-worktree-active { - opacity: 1; - color: var(--accent-text); -} - -.chat-worktree-active:hover { - opacity: 1; -} - -.chat-header { - padding: 14px 24px; - border-bottom: 1px solid var(--border); - display: flex; - align-items: center; - justify-content: space-between; - flex-shrink: 0; -} - -.chat-header-title { - font-size: 15px; - font-weight: 600; - color: var(--text-primary); -} - -.chat-header-actions { - display: flex; - align-items: center; - gap: 4px; -} - -.chat-clear-btn { - opacity: 0.6; -} - -.chat-clear-btn:hover { - opacity: 1; -} - -.chat-fast-wrapper { - position: relative; -} - -.chat-fast-btn { - opacity: 0.5; - transition: - opacity 0.15s, - color 0.15s; -} - -.chat-fast-btn:hover { - opacity: 0.8; -} - -.chat-fast-active { - opacity: 1; - color: #f59e0b; -} - -.chat-fast-active:hover { - opacity: 1; -} - -.chat-fast-popover { - display: none; - position: absolute; - bottom: calc(100% + 8px); - right: 0; - z-index: 100; - width: 220px; - padding: 10px 12px; - background: var(--bg-tertiary, var(--bg-secondary)); - border: 1px solid var(--border); - border-radius: 8px; - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25); - pointer-events: none; -} - -.chat-fast-popover strong { - display: block; - font-size: 12px; - margin-bottom: 4px; - color: var(--text-primary); -} - -.chat-fast-popover span { - font-size: 11px; - line-height: 1.4; - color: var(--text-secondary); -} - -.chat-fast-wrapper:hover .chat-fast-popover { - display: block; -} - -/* Context folder control (issue #27) */ -.chat-ctxfolder { - display: flex; - align-items: center; -} - -.chat-ctxfolder-btn { - display: flex; - align-items: center; - gap: 5px; - opacity: 0.6; - max-width: 180px; -} - -.chat-ctxfolder-btn:hover { - opacity: 1; -} - -.chat-ctxfolder-set { - opacity: 0.85; -} - -.chat-ctxfolder-name { - font-size: 12px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.chat-ctxfolder-clear { - opacity: 0.45; - padding: 2px; -} - -.chat-ctxfolder-clear:hover { - opacity: 1; -} - -.chat-cost { - color: var(--text-tertiary); -} - -.chat-messages { - flex: 1; - overflow-y: auto; - padding: 24px; - /* Block flow, NOT a flex column. `content-visibility: auto` on the rows - (below) lets the browser skip layout/paint for off-screen messages, which - is what keeps typing fast in long conversations (#748). A flex column - defeats that: it measures every child's intrinsic size to lay the column - out, forcing layout of skipped subtrees and reporting a wrong - `scrollHeight` — which would also break the auto-scroll math in - useChatScroll. Inter-row spacing that the flex `gap` used to provide now - comes from each row's own bottom margin/padding. */ -} - -/* Empty state */ -.chat-empty { - /* The scroll container is block flow now (see .chat-messages), so `flex: 1` - no longer stretches this to fill the height. `min-height: 100%` makes it - fill the container so its own flex centering still works. */ - min-height: 100%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 12px; - animation: chatEmptyFadeIn 0.5s ease-out; -} - -@keyframes chatEmptyFadeIn { - from { - opacity: 0; - transform: translateY(12px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.chat-empty-icon { - width: 80px; - height: 80px; - border-radius: 50%; - background: #000; - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 4px; -} - -/* The wordmark SVG ships with a black fill; recolour it to white via masking so - it reads on the black circle, regardless of the source artwork's colours. */ -.chat-empty-logo { - width: 52px; - height: 40px; - background-color: #fff; - mask-repeat: no-repeat; - mask-position: center; - mask-size: contain; - -webkit-mask-repeat: no-repeat; - -webkit-mask-position: center; - -webkit-mask-size: contain; -} - -.chat-empty-text { - font-size: 22px; - font-weight: 600; - color: var(--text-primary); -} - -.chat-empty-hint { - font-size: 14px; - color: var(--text-muted); - max-width: 360px; - text-align: center; - line-height: 1.5; -} - -.chat-empty-suggestions { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 8px; - margin-top: 16px; - max-width: 480px; -} - -.chat-suggestion { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 8px 16px; - border-radius: 20px; - border: 1px solid var(--border); - background: var(--bg-secondary); - color: var(--text-secondary); - font-size: 13px; - cursor: pointer; - transition: - background 0.15s ease, - color 0.15s ease, - border-color 0.15s ease; -} - -.chat-suggestion svg { - flex-shrink: 0; -} - -.chat-suggestion:hover { - background: var(--bg-elevated); - color: var(--text-primary); - border-color: var(--accent); -} - -/* Messages */ -.chat-message { - display: flex; - gap: 12px; - width: 100%; - max-width: 85%; - animation: messageIn 0.2s ease; - position: relative; - /* Replaces the old container flex `gap` (now block flow). Also gives the - hover timestamp (.chat-bubble-time, ~15px below the bubble) room *inside* - this box so the paint containment that `content-visibility` implies does - not clip it. */ - padding-bottom: 16px; - /* Skip layout + paint for rows scrolled out of view. This turns the - per-keystroke document reflow from O(all messages) into O(visible rows), - fixing the input lag in long conversations. `auto` for the intrinsic size - means the real measured height is remembered after a row renders once, so - the scrollbar stays accurate; 120px is only the first-paint estimate. */ - content-visibility: auto; - contain-intrinsic-size: auto 120px; -} - -@keyframes messageIn { - from { - opacity: 0; - transform: translateY(4px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.chat-message-user { - /* Right-align in block flow (replaces the flex-column `align-self: flex-end`). - `row-reverse` keeps the bubble on the outer edge with the avatar inside. */ - margin-left: auto; - flex-direction: row-reverse; -} - -/* Agent rows are left-aligned by default in block flow — no rule needed. */ - -/* Continuation rows of a turn (thinking/tool rows + answer that share one - avatar). Pull them closer to the row above so the turn reads as one block - rather than several spaced-out bubbles. */ -.chat-message--grouped { - margin-top: -8px; -} - -.chat-avatar { - width: 28px; - height: 28px; - border-radius: var(--radius-sm); - display: flex; - align-items: center; - justify-content: center; - font-size: 11px; - font-weight: 700; - flex-shrink: 0; -} - -.chat-avatar-agent { - border-radius: 50px; - overflow: hidden; -} - -.chat-avatar-agent img { - width: 100%; - height: 100%; - object-fit: cover; - object-position: center; - display: block; -} - -.chat-bubble { - position: relative; - padding: 10px 16px; - border-radius: var(--radius-lg); - font-size: 14px; - line-height: 1.65; - white-space: pre-wrap; - word-wrap: break-word; - overflow-wrap: break-word; - min-width: 0; - max-width: 100%; - overflow-x: auto; - -webkit-user-select: text; - user-select: text; -} - -.chat-bubble-user { - background: var(--user-bubble); - color: var(--user-bubble-text); - border-bottom-right-radius: 4px; -} - -.chat-bubble-agent { - background: var(--agent-bubble); - color: var(--agent-bubble-text); - border-bottom-left-radius: 4px; - /* Agent messages are rendered markdown HTML — preserve structure - via the elements themselves, not literal whitespace. Overrides - .chat-bubble's pre-wrap, which would otherwise turn newlines - between
  • tags into visible blank lines. */ - white-space: normal; -} - -.chat-bubble-error { - border: 1px solid color-mix(in srgb, var(--error) 35%, transparent); - background: var(--error-bg); -} - -/* Copy button — hidden by default, shown on bubble hover */ -.chat-bubble-actions { - position: absolute; - top: 6px; - right: 8px; - display: flex; - gap: 4px; - opacity: 0; - transition: opacity 0.15s ease; -} - -.chat-bubble:hover .chat-bubble-actions { - opacity: 1; -} - -/* Hover timestamp — sits just below the bubble, revealed on row hover. - Anchored inside .chat-message's bottom padding (not overflowing it): the - `content-visibility` on .chat-message implies paint containment, which would - clip anything spilling past the box, so this sits at bottom:1px within the - 16px padding instead of overflowing at -15px. */ -.chat-bubble-time { - position: absolute; - bottom: 1px; - font-size: 11px; - line-height: 1; - color: var(--text-secondary); - white-space: nowrap; - pointer-events: none; - opacity: 0; - transition: opacity 0.15s ease; -} - -/* Agent rows start after the avatar (28px + 12px gap); user rows are - right-aligned. Anchor the time to the bubble's outer edge accordingly. */ -.chat-message-agent .chat-bubble-time { - left: 40px; -} - -.chat-message-user .chat-bubble-time { - right: 0; -} - -.chat-message:hover .chat-bubble-time { - opacity: 1; -} - -.chat-bubble-copy { - display: inline-flex; - align-items: center; - justify-content: center; - width: 28px; - height: 28px; - padding: 0; - background: var(--bg-elevated); - border: 1px solid var(--border-bright); - border-radius: var(--radius-sm); - color: var(--text-secondary); - cursor: pointer; - transition: all var(--transition); -} - -.chat-bubble-copy:hover { - background: var(--bg-hover); - color: var(--text-primary); - border-color: var(--border-focus, var(--accent)); -} - -.chat-error-message { - color: var(--error); - font-weight: 500; - white-space: pre-wrap; -} - -.chat-bubble-agent pre, -.chat-bubble-agent code { - /* Restore preserved whitespace inside code blocks and inline code. */ - white-space: pre-wrap; -} - -.chat-bubble-agent code { - background: var(--code-bg); - padding: 2px 6px; - border-radius: 4px; - font-family: var(--font-mono); - font-size: 13px; -} - -.chat-bubble-agent pre { - background: var(--code-bg); - padding: 12px; - border-radius: var(--radius-sm); - margin: 8px 0; - overflow-x: auto; - font-family: var(--font-mono); - font-size: 13px; - line-height: 1.5; -} - -.chat-bubble-agent pre code { - background: none; - padding: 0; -} - -.chat-code-block { - border-radius: 6px; - overflow: hidden; - margin: 6px 0 !important; -} - -.chat-code-collapsed { - max-height: 180px; - overflow: hidden; - mask-image: linear-gradient(to bottom, black 70%, transparent 100%); - -webkit-mask-image: linear-gradient(to bottom, black 70%, transparent 100%); -} - -.chat-code-expand-btn { - display: flex; - align-items: center; - justify-content: center; - width: 100%; - padding: 8px; - background: var(--code-bg); - border: none; - border-top: 1px solid var(--border); - color: var(--accent-text); - font-size: 11px; - font-weight: 600; - cursor: pointer; - transition: background var(--transition); -} - -.chat-code-expand-btn:hover { - background: var(--bg-hover); -} - -.chat-code-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 4px 12px; - background: var(--code-bg); -} - -.chat-code-lang { - font-size: 11px; - color: var(--text-muted); - font-weight: 600; - text-transform: lowercase; -} - -.chat-code-copy { - background: none; - border: none; - color: var(--text-muted); - font-size: 11px; - cursor: pointer; - padding: 2px 4px; - border-radius: 3px; - display: flex; - align-items: center; - gap: 4px; - transition: color var(--transition); -} - -.chat-code-copy:hover { - color: var(--text-primary); -} - -.chat-code-block + * { - margin-top: 6px !important; -} - -.chat-bubble-agent .chat-code-block pre, -.chat-bubble-agent .chat-code-block div[class*="prism"] { - margin: 0 !important; - padding: 12px !important; - background: var(--code-bg) !important; -} - -.chat-code-block span[class*="token"] { - background: none !important; -} - -/* Diff view */ -.chat-diff-content { - font-family: var(--font-mono); - font-size: 13px; - line-height: 1.5; - padding: 8px 0; - overflow-x: auto; -} - -.chat-diff-line { - padding: 0 12px; - white-space: pre; -} - -.chat-diff-add { - background: rgba(34, 197, 94, 0.12); - color: #4ade80; -} - -.chat-diff-remove { - background: rgba(239, 68, 68, 0.12); - color: #f87171; -} - -.chat-diff-hunk { - color: var(--accent-text); - opacity: 0.7; -} - -/* Approval bar */ -.chat-approval-bar { - display: flex; - gap: 8px; - margin-top: 8px; - margin-left: 42px; -} - -.chat-approval-btn { - padding: 5px 16px; - border: none; - border-radius: 6px; - font-size: 12px; - font-weight: 600; - cursor: pointer; - transition: background var(--transition); -} - -.chat-approve { - background: var(--success); - color: #fff; -} - -.chat-approve:hover { - background: #16a34a; -} - -.chat-deny { - background: var(--bg-elevated); - color: var(--text-secondary); -} - -.chat-deny:hover { - background: var(--bg-hover); -} - -/* Inline clarify card — a mid-turn question rendered in the transcript. */ -.chat-clarify { - margin-top: 8px; - /* Not a .chat-message, so it doesn't carry the row padding-bottom that now - provides inter-row spacing — add the 16px the container's flex gap used - to give it. */ - margin-bottom: 16px; - margin-left: 42px; - padding: 14px 16px; - border: 1px solid var(--border); - border-left: 3px solid var(--accent, #2563eb); - border-radius: 8px; - background: var(--bg-elevated); - display: flex; - flex-direction: column; - gap: 10px; - max-width: 640px; -} - -.chat-clarify-question { - font-size: 13px; - line-height: 1.5; - color: var(--text-primary); - white-space: pre-wrap; - word-break: break-word; -} - -.chat-clarify-choices { - display: flex; - flex-direction: column; - gap: 6px; -} - -.chat-clarify-choice { - text-align: left; - padding: 9px 12px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-base); - color: var(--text-primary); - font-size: 13px; - cursor: pointer; - transition: - background var(--transition), - border-color var(--transition); -} - -.chat-clarify-choice:hover { - border-color: var(--accent, #2563eb); - background: var(--bg-hover); -} - -.chat-clarify-choice:disabled { - opacity: 0.6; - cursor: default; -} - -.chat-clarify-open { - display: flex; - flex-direction: column; - gap: 8px; -} - -.chat-clarify-textarea { - width: 100%; - padding: 9px 11px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-base); - color: var(--text-primary); - font-size: 14px; - font-family: inherit; - resize: vertical; - box-sizing: border-box; -} - -.chat-clarify-textarea:focus { - outline: none; - border-color: var(--accent, #2563eb); -} - -.chat-clarify-send { - align-self: flex-end; - padding: 6px 16px; - border: none; - border-radius: 6px; - background: var(--accent, #2563eb); - color: #fff; - font-size: 12px; - font-weight: 600; - cursor: pointer; -} - -.chat-clarify-send:disabled { - opacity: 0.5; - cursor: default; -} - -.chat-clarify-skip { - align-self: flex-start; - padding: 0; - border: none; - background: transparent; - color: var(--text-secondary); - font-size: 12px; - cursor: pointer; -} - -.chat-clarify-skip:hover { - color: var(--text-primary); - text-decoration: underline; -} - -.chat-clarify--resolved { - opacity: 0.85; -} - -.chat-clarify-answer { - font-size: 13px; - color: var(--text-secondary); - padding: 6px 10px; - border-radius: 6px; - background: var(--bg-base); -} - -.chat-clarify-error { - font-size: 12px; - color: var(--danger, #ef4444); - margin-top: 2px; -} - -/* Override Tailwind preflight spacing inside agent bubbles */ -.chat-bubble-agent p { - margin: 0 0 0.85em !important; - padding: 0 !important; -} -.chat-bubble-agent p:last-child { - margin-bottom: 0 !important; -} -.chat-bubble-agent ul, -.chat-bubble-agent ol { - margin: 0.5em 0 0.75em 1.5em !important; - padding: 0 !important; - list-style: revert !important; -} -.chat-bubble-agent li { - margin: 0 0 2px !important; - padding: 0 !important; -} -.chat-bubble-agent li > p { - margin: 0 !important; -} -.chat-bubble-agent li > ul, -.chat-bubble-agent li > ol { - margin: 2px 0 2px 16px !important; -} -.chat-bubble-agent h1, -.chat-bubble-agent h2, -.chat-bubble-agent h3, -.chat-bubble-agent h4 { - margin: 1em 0 0.5em !important; - padding: 0 !important; - font-weight: 600; -} -.chat-bubble-agent h1:first-child, -.chat-bubble-agent h2:first-child, -.chat-bubble-agent h3:first-child { - margin-top: 0 !important; -} -.chat-bubble-agent blockquote { - margin: 4px 0 !important; - padding: 2px 10px !important; -} -.chat-bubble-agent hr { - margin: 8px 0 !important; - padding: 0 !important; -} -.chat-bubble-agent table { - margin: 6px 0 !important; - padding: 0 !important; -} -.chat-bubble-agent pre { - margin: 6px 0 !important; -} - -.chat-bubble-agent h1 { - font-size: 17px; -} -.chat-bubble-agent h2 { - font-size: 15px; -} -.chat-bubble-agent h3 { - font-size: 14px; -} - -.chat-bubble-agent blockquote { - border-left: 3px solid var(--border-bright); - margin: 4px 0; - padding: 2px 10px; - color: var(--text-secondary); -} - -.chat-bubble-agent a { - color: var(--accent-text); - text-decoration: none; -} - -.chat-bubble-agent a:hover { - text-decoration: underline; -} - -.chat-bubble-agent hr { - border: none; - border-top: 1px solid var(--border); - margin: 8px 0; -} - -.chat-bubble-agent table { - border-collapse: collapse; - margin: 8px 0; - font-size: 13px; - width: 100%; -} - -.chat-bubble-agent th, -.chat-bubble-agent td { - border: 1px solid var(--border-bright); - padding: 6px 10px; - text-align: left; -} - -.chat-bubble-agent th { - font-weight: 600; - background: var(--code-bg); -} - -.chat-bubble-agent pre { - margin: 6px 0; -} - -/* Typing indicator */ -.chat-typing { - display: inline-flex; - gap: 5px; - padding: 4px 0; -} - -.chat-typing-dot { - display: block; - width: 6px; - height: 6px; - background: var(--text-muted); - border-radius: 50%; - animation: typingBounce 1.4s infinite; -} - -.chat-typing-dot:nth-child(2) { - animation-delay: 0.2s; -} - -.chat-typing-dot:nth-child(3) { - animation-delay: 0.4s; -} - -@keyframes typingBounce { - 0%, - 60%, - 100% { - transform: translateY(0); - opacity: 0.4; - } - 30% { - transform: translateY(-4px); - opacity: 1; - } -} - -.chat-queue-indicator { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 4px; - - font-size: 12px; - color: var(--text-secondary); - margin-bottom: 15px; -} - -.chat-queue-icon { - flex-shrink: 0; - color: var(--accent, #8b7cf6); -} - -.chat-queue-single { - flex: 1; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -/* Single-message row lays the icon + text out horizontally. */ -.chat-queue-indicator:not(.chat-queue-collapsible) { - flex-direction: row; - align-items: center; -} - -.chat-queue-toggle { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 0; - background: none; - border: none; - color: var(--text-secondary); - font-size: 12px; - cursor: pointer; -} - -.chat-queue-toggle:hover { - color: var(--text-primary); -} - -.chat-queue-list { - list-style: none; - margin: 0; - padding: 4px 0 0; - width: 100%; - max-height: 140px; - overflow-y: auto; - display: flex; - flex-direction: column; - gap: 2px; -} - -.chat-queue-item { - display: flex; - align-items: center; - gap: 8px; - max-width: 100%; - padding: 3px 8px; - border-radius: var(--radius-sm, 6px); - background: var(--bg-tertiary, rgba(255, 255, 255, 0.04)); - color: var(--text-secondary); -} - -.chat-queue-item-text { - flex: 1; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.chat-queue-remove { - flex-shrink: 0; - display: inline-flex; - align-items: center; - justify-content: center; - padding: 2px; - margin-left: auto; - background: none; - border: none; - color: var(--text-muted); - cursor: pointer; - border-radius: var(--radius-sm, 6px); -} - -.chat-queue-remove:hover { - color: var(--text-primary); - background: var(--bg-hover, rgba(255, 255, 255, 0.08)); -} - -/* Input area */ -.chat-input-area { - position: relative; - padding: 12px 24px 16px; - border-top: 1px solid var(--border); - flex-shrink: 0; -} - -.chat-input-wrapper { - display: flex; - flex-direction: column; - align-items: stretch; - gap: 6px; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-lg); - padding: 10px 10px 8px; - transition: border-color var(--transition); -} - -.chat-input-wrapper:focus-within { - border-color: var(--border-focus); -} - -.chat-input { - width: 100%; - background: none; - border: none; - color: var(--text-primary); - font-size: 14px; - font-family: var(--font-sans); - padding: 4px 6px; - outline: none; - resize: none; - min-height: 20px; - max-height: 120px; - overflow-y: auto; - line-height: 1.4; - box-sizing: border-box; -} - -/* Bottom toolbar row: attach/mic + model/folder pickers, send pushed right. */ -.chat-input-toolbar { - display: flex; - align-items: center; - gap: 4px; -} - -.chat-input-toolbar-spacer { - flex: 1; -} - -/* Thin separator between the icon buttons and the picker chips. */ -.chat-input-toolbar-divider { - width: 1px; - align-self: stretch; - margin: 4px 4px; - background: var(--border-bright); -} - -.chat-input::placeholder { - color: var(--text-muted); -} - -.chat-send-btn { - width: 34px; - height: 34px; - border-radius: var(--radius-sm); - background: var(--accent); - border: none; - color: #fff; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - transition: all var(--transition); - flex-shrink: 0; -} - -.chat-send-btn:hover:not(:disabled) { - background: var(--accent-hover); -} - -.chat-send-btn:disabled { - opacity: 0.25; - cursor: not-allowed; -} - -.chat-stop-btn { - background: var(--error); -} - -.chat-stop-btn:hover { - background: #dc2626; -} - -.chat-btw-btn { - width: 34px; - height: 34px; - border-radius: var(--radius-sm); - background: var(--bg-hover); - border: none; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - font-size: 16px; - transition: background var(--transition); -} - -.chat-btw-btn:hover { - background: var(--bg-active); -} - -/* ── Attachments ────────────────────────────────────── */ - -.chat-attach-btn { - width: 34px; - height: 34px; - border-radius: var(--radius-sm); - background: transparent; - border: none; - color: var(--text-muted); - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - transition: - background var(--transition), - color var(--transition); -} - -.chat-attach-btn:hover:not(:disabled) { - background: var(--bg-hover); - color: var(--text-primary); -} - -.chat-attach-btn:disabled { - opacity: 0.4; - cursor: not-allowed; -} - -/* Voice-input button — shares the attach button's shape. */ -.chat-mic-btn { - width: 34px; - height: 34px; - border-radius: var(--radius-sm); - background: transparent; - border: none; - color: var(--text-muted); - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - transition: - background var(--transition), - color var(--transition); -} - -.chat-mic-btn:hover:not(:disabled) { - background: var(--bg-hover); - color: var(--text-primary); -} - -.chat-mic-btn:disabled { - opacity: 0.4; - cursor: not-allowed; -} - -/* Recording: red, gently pulsing so it's clearly "live". */ -.chat-mic-btn--recording { - color: var(--danger, #ef4444); - animation: chatMicPulse 1.2s ease-in-out infinite; -} - -@keyframes chatMicPulse { - 0%, - 100% { - opacity: 1; - } - 50% { - opacity: 0.45; - } -} - -.chat-voice-error { - margin-top: 6px; -} - -/* Context-window gauge — circular % ring with a hover/focus tooltip. */ -.chat-ctx-gauge { - position: relative; - width: 30px; - height: 30px; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; - cursor: default; - outline: none; -} - -.chat-ctx-gauge-track { - stroke: var(--border, rgba(255, 255, 255, 0.12)); -} - -.chat-ctx-gauge-fill { - stroke: var(--accent, #4ade80); - transition: stroke-dasharray var(--transition); -} - -.chat-ctx-gauge-num { - position: absolute; - font-size: 9px; - font-weight: 600; - color: var(--text-secondary); - font-variant-numeric: tabular-nums; -} - -.chat-ctx-tooltip { - position: absolute; - bottom: calc(100% + 8px); - right: 0; - z-index: 20; - min-width: 220px; - padding: 10px 12px; - border-radius: var(--radius-md, 8px); - background: var(--bg-elevated, #1c1c22); - border: 1px solid var(--border, rgba(255, 255, 255, 0.12)); - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4); - color: var(--text-secondary); - font-size: 12px; - line-height: 1.6; - white-space: nowrap; - opacity: 0; - visibility: hidden; - transform: translateY(4px); - transition: - opacity var(--transition), - transform var(--transition), - visibility var(--transition); - pointer-events: none; -} - -.chat-ctx-gauge:hover .chat-ctx-tooltip, -.chat-ctx-gauge:focus-visible .chat-ctx-tooltip { - opacity: 1; - visibility: visible; - transform: translateY(0); -} - -.chat-ctx-tooltip-title { - font-weight: 600; - color: var(--text-primary); - margin-bottom: 4px; -} - -.chat-attachment-strip { - display: flex; - flex-wrap: wrap; - gap: 8px; - align-items: center; - margin-bottom: 6px; - padding: 8px 10px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); -} - -.chat-attachment-error { - flex: 0 0 100%; - font-size: 12px; - color: var(--error); - padding-top: 2px; -} - -/* Pre-send readiness banner — shown above the chat input when the - * desktop detects an obvious misconfiguration (missing API key for - * the active provider, etc.). Fail-open: only renders when validation - * has flagged a specific issue. */ -.chat-readiness-banner { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 6px 10px; - margin-bottom: 6px; - padding: 8px 12px; - background: var(--bg-secondary); - border: 1px solid var(--warning, var(--border)); - border-left-width: 3px; - border-radius: 6px; - font-size: 12.5px; - color: var(--text-primary); -} - -.chat-readiness-message { - flex: 1 1 auto; - min-width: 0; -} - -.chat-readiness-fix { - flex: 0 0 auto; - font-weight: 500; - color: var(--text-secondary); -} - -/* ConfigHealthBanner — appears at the top of Chat when the startup - * audit found inconsistencies. One-liner summary + link to Diagnose. */ -.config-health-banner { - display: flex; - align-items: center; - gap: 12px; - padding: 8px 14px; - margin: 0; - border-bottom: 1px solid var(--border); - font-size: 12.5px; -} - -.config-health-banner-error { - background: var(--error-bg, var(--bg-secondary)); - color: var(--error, var(--text-primary)); -} - -.config-health-banner-warning { - background: var(--warning-bg, var(--bg-secondary)); - color: var(--text-primary); -} - -.config-health-banner-info { - background: var(--bg-secondary); - color: var(--text-secondary); -} - -.config-health-banner-text { - flex: 1 1 auto; - min-width: 0; -} - -.config-health-banner-actions { - display: flex; - align-items: center; - gap: 8px; - flex: 0 0 auto; -} - -.config-health-banner-link { - background: transparent; - border: none; - color: inherit; - text-decoration: underline; - cursor: pointer; - font: inherit; - padding: 2px 4px; -} - -.config-health-banner-dismiss { - background: transparent; - border: none; - color: inherit; - cursor: pointer; - padding: 2px; - display: flex; - align-items: center; - justify-content: center; - opacity: 0.75; -} - -.config-health-banner-dismiss:hover { - opacity: 1; -} - -/* Diagnose panel inside Settings */ -.diagnose-header { - display: flex; - justify-content: space-between; - align-items: center; - gap: 12px; -} - -.diagnose-rerun-btn { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 4px 10px; - font-size: 12px; - border: 1px solid var(--border); - background: var(--bg-secondary); - color: var(--text-primary); - border-radius: 4px; - cursor: pointer; -} - -.diagnose-rerun-btn:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.diagnose-loading, -.diagnose-empty { - padding: 12px; - display: flex; - align-items: center; - gap: 8px; - color: var(--text-secondary); - font-size: 13px; -} - -.diagnose-issue-list { - list-style: none; - padding: 0; - margin: 8px 0 0; - display: flex; - flex-direction: column; - gap: 10px; -} - -.diagnose-issue { - padding: 10px 12px; - border: 1px solid var(--border); - border-left-width: 3px; - border-radius: 6px; - background: var(--bg-secondary); -} - -.diagnose-issue-error { - border-left-color: var(--error, #c0392b); -} - -.diagnose-issue-warning { - border-left-color: var(--warning, #d6a700); -} - -.diagnose-issue-info { - border-left-color: var(--text-secondary); -} - -.diagnose-issue-head { - display: flex; - align-items: center; - gap: 8px; -} - -.diagnose-issue-code { - font-family: var(--font-mono, monospace); - font-size: 11px; - color: var(--text-secondary); -} - -.diagnose-issue-message { - margin: 6px 0 0; - font-size: 13px; - font-weight: 500; -} - -.diagnose-issue-detail { - margin: 4px 0 0; - color: var(--text-secondary); - font-size: 12px; -} - -.diagnose-issue-locations { - list-style: disc inside; - margin: 6px 0 0; - padding-left: 4px; - color: var(--text-secondary); - font-size: 11.5px; - font-family: var(--font-mono, monospace); -} - -.diagnose-issue-fix { - margin-top: 8px; - display: flex; - align-items: center; - gap: 8px; - flex-wrap: wrap; -} - -.diagnose-fix-btn { - padding: 4px 12px; - font-size: 12px; - background: var(--accent, var(--bg-tertiary)); - color: var(--accent-fg, var(--text-primary)); - border: 1px solid var(--border); - border-radius: 4px; - cursor: pointer; -} - -.diagnose-fix-btn:disabled { - opacity: 0.6; - cursor: not-allowed; -} - -.diagnose-issue-fix-desc { - font-size: 12px; - color: var(--text-secondary); -} - -.diagnose-issue-result { - margin: 6px 0 0; - font-size: 12px; - color: var(--text-secondary); - font-style: italic; -} - -.diag-icon-error { - color: var(--error, #c0392b); -} - -.diag-icon-warning { - color: var(--warning, #d6a700); -} - -.diag-icon-info, -.diag-icon-ok { - color: var(--text-secondary); -} - -.attachment-chip { - position: relative; - display: inline-flex; - align-items: center; - border-radius: var(--radius-sm); - background: var(--bg-primary); - border: 1px solid var(--border-bright); -} - -.attachment-chip-thumb { - display: block; - padding: 0; - margin: 0; - background: none; - border: none; - cursor: pointer; - border-radius: var(--radius-sm); - overflow: hidden; - width: 56px; - height: 56px; -} - -.attachment-chip-thumb img { - width: 100%; - height: 100%; - object-fit: cover; - display: block; -} - -.attachment-chip-file { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 6px 10px; - color: var(--text-primary); - font-size: 12px; - max-width: 220px; -} - -.attachment-chip-name { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.attachment-chip-remove { - position: absolute; - top: -6px; - right: -6px; - width: 18px; - height: 18px; - border-radius: 50%; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - color: var(--text-primary); - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - padding: 0; - line-height: 0; -} - -.attachment-chip-remove:hover { - background: var(--error); - color: #fff; - border-color: var(--error); -} - -.chat-message-attachments { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin-bottom: 6px; -} - -/* Drop overlay covers the whole chat container while a file drag is active */ -.chat-drop-overlay { - position: absolute; - inset: 0; - background: rgba(0, 0, 0, 0.45); - display: flex; - align-items: center; - justify-content: center; - pointer-events: none; - z-index: 100; - backdrop-filter: blur(2px); -} - -.chat-drop-overlay-inner { - border: 2px dashed var(--accent); - border-radius: var(--radius-lg); - padding: 24px 36px; - color: #fff; - font-size: 16px; - font-weight: 600; - background: rgba(0, 0, 0, 0.35); -} - -.chat-image-preview-backdrop { - position: fixed; - inset: 0; - background: rgba(0, 0, 0, 0.85); - display: flex; - align-items: center; - justify-content: center; - z-index: 200; - cursor: zoom-out; -} - -.chat-image-preview-image { - max-width: 90vw; - max-height: 90vh; - border-radius: var(--radius-md); - cursor: default; -} - -.chat-image-preview-actions { - position: fixed; - top: 16px; - right: 16px; - display: flex; - flex-direction: row; - gap: 8px; - z-index: 201; -} - -/* Lightbox action buttons — light-on-dark so they read on the backdrop. */ -.chat-image-preview-btn { - display: inline-flex; - flex-direction: row; - align-items: center; - gap: 6px; - padding: 6px 12px; - border: 1px solid rgba(255, 255, 255, 0.3); - border-radius: 8px; - background: rgba(255, 255, 255, 0.12); - color: #fff; - cursor: pointer; - font-size: 13px; -} - -.chat-image-preview-btn:hover { - background: rgba(255, 255, 255, 0.22); -} - -/* ── Agent-generated media (issue #299) ─────────────── */ - -.chat-media-image { - max-width: 100%; - max-height: 320px; - border-radius: 8px; - cursor: pointer; - display: block; - margin: 6px 0; -} - -.chat-media-loading, -.chat-media-error { - font-size: 13px; - color: var(--text-secondary); -} - -.chat-media-error { - color: var(--warning, #d08770); -} - -.chat-media-file { - display: inline-flex; - flex-direction: row; - align-items: center; - gap: 6px; - padding: 6px 10px; - border: 1px solid var(--border); - border-radius: 8px; - background: transparent; - cursor: pointer; - font-size: 13px; -} - -/* ── Slash Command Menu ─────────────────────────────── */ - -.slash-menu-overlay { - position: fixed; - inset: 0; - z-index: 49; - background: rgba(5, 8, 12, 0.58); -} - -.slash-menu { - position: fixed; - top: 46%; - left: 50%; - width: min(720px, calc(100vw - 64px)); - transform: translate(-50%, -50%); - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: 14px; - box-shadow: 0 20px 64px rgba(0, 0, 0, 0.48); - max-height: min(560px, calc(100vh - 160px)); - display: flex; - flex-direction: column; - overflow: hidden; - z-index: 50; -} - -.slash-menu-search { - display: flex; - align-items: center; - gap: 12px; - min-height: 54px; - padding: 0 16px; - color: var(--text-secondary); - border-bottom: 1px solid var(--border); -} - -.slash-menu-search-query { - flex: 1; - color: var(--text-primary); - font-family: var(--font-mono); - font-size: 15px; -} - -.slash-menu kbd { - padding: 2px 6px; - border: 1px solid var(--border); - border-radius: 5px; - background: var(--bg-tertiary); - color: var(--text-muted); - font-family: var(--font-mono); - font-size: 10px; - font-weight: 500; -} - -.slash-menu-list { - position: relative; - flex: 1; - min-height: 0; - height: min(420px, calc(100vh - 256px)); - overflow-y: auto; - overscroll-behavior: contain; - padding: 10px; -} - -.slash-menu-virtual-content { - position: relative; - width: 100%; - contain: layout paint style; -} - -.slash-menu-group-label { - position: absolute; - inset: 0 0 auto; - box-sizing: border-box; - padding: 7px 10px 5px; - color: var(--text-muted); - font-size: 10px; - font-weight: 700; - letter-spacing: 0.08em; - text-transform: uppercase; -} - -.slash-menu-item { - position: absolute; - inset: 0 0 auto; - box-sizing: border-box; - display: grid; - grid-template-columns: 28px minmax(130px, 0.75fr) minmax(0, 1.5fr) auto; - align-items: center; - gap: 8px; - width: 100%; - padding: 4px 10px; - border: none; - background: none; - border-radius: 10px; - cursor: pointer; - text-align: left; - transition: background 0.1s; -} - -.slash-menu-item:hover, -.slash-menu-item-active { - background: var(--bg-hover); -} - -.slash-menu-item-icon { - width: 28px; - height: 28px; - padding: 5px; - border-radius: 7px; - background: var(--bg-tertiary); - color: var(--text-muted); - display: flex; - align-items: center; - justify-content: center; - transition: color 0.1s; -} - -.slash-menu-item:hover .slash-menu-item-icon, -.slash-menu-item-active .slash-menu-item-icon { - color: var(--accent-text, var(--text-primary)); - background: color-mix(in srgb, var(--accent) 18%, var(--bg-tertiary)); -} - -.slash-menu-item-name { - font-size: 13px; - color: var(--text-primary); - white-space: nowrap; -} - -.slash-menu-item-desc { - font-size: 12px; - color: var(--text-secondary); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.slash-menu-item-badge { - padding: 3px 7px; - border: 1px solid var(--border); - border-radius: 6px; - color: var(--text-muted); - font-size: 10px; - white-space: nowrap; -} - -.slash-menu-footer { - display: flex; - align-items: center; - gap: 16px; - min-height: 42px; - padding: 0 16px; - border-top: 1px solid var(--border); - color: var(--text-muted); - font-size: 11px; -} - -.slash-menu-footer > span { - display: inline-flex; - align-items: center; - gap: 6px; -} - -.slash-menu-count { - margin-left: auto; -} - -@media (max-width: 720px) { - .slash-menu { - width: calc(100vw - 28px); - } - - .slash-menu-item { - grid-template-columns: 28px minmax(100px, 0.8fr) minmax(0, 1.2fr); - } - - .slash-menu-item-badge { - display: none; - } -} - -.chat-header-left { - display: flex; - align-items: center; - gap: 10px; -} - -.chat-token-counter { - font-size: 11px; - color: var(--text-muted); - background: var(--bg-tertiary); - padding: 2px 8px; - border-radius: 10px; -} - -.chat-tool-progress { - font-size: 13px; - color: var(--text-secondary); - animation: fadeIn 0.2s ease; -} - -.chat-tool-progress-inline { - font-size: 12px; - color: var(--text-muted); - padding: 2px 60px; - animation: fadeIn 0.2s ease; -} - -/* ── Chat history sub-rows (reasoning / tool_call / tool_result) ─────── - * - * Surfaced for resumed sessions: see src/main/sessions.ts - * `expandRowsToHistory`. These are
    / widgets so the - * default-closed state and toggle behavior are native — no JS event - * juggling required. The chevron is purely visual; the click target is - * the whole summary row. - */ -.chat-message-history > .chat-history { - flex: 1; - min-width: 0; -} - -.chat-history { - display: block; - width: 100%; - border: 1px solid var(--border, rgba(127, 127, 127, 0.18)); - border-radius: 8px; - background: transparent; - font-size: 13px; - color: var(--text-secondary); - overflow: hidden; -} - -.chat-history--reasoning { - border-left: 3px solid var(--accent, #8b7cf6); -} -.chat-history--tool-call { - border-left: 3px solid var(--info, #4aa8ff); -} -.chat-history--tool-result { - border-left: 3px solid var(--success, #4ac38a); -} - -.chat-history-header { - display: flex; - align-items: center; - gap: 8px; - padding: 6px 10px; - cursor: pointer; - user-select: none; - list-style: none; - font-size: 12px; - color: var(--text-secondary); -} - -.chat-history-header::-webkit-details-marker { - display: none; -} - -.chat-history-header:hover { - background: var(--hover, rgba(127, 127, 127, 0.06)); -} - -.chat-history-chevron { - display: inline-block; - width: 12px; - transition: transform 0.15s ease; - font-size: 10px; - color: var(--text-muted); -} - -.chat-history-chevron--open { - transform: rotate(90deg); -} - -.chat-history-label { - display: flex; - align-items: baseline; - gap: 8px; - min-width: 0; - flex: 1; - overflow: hidden; -} - -.chat-history-title { - font-weight: 600; - color: var(--text-secondary); - text-transform: lowercase; - letter-spacing: 0.02em; -} - -.chat-history-tool-name { - font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace); - font-size: 12px; - color: var(--text-primary); - background: var(--code-bg, rgba(127, 127, 127, 0.08)); - padding: 1px 6px; - border-radius: 4px; -} - -.chat-history-tool-summary, -.chat-history-meta { - color: var(--text-muted); - font-size: 11px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; -} - -.chat-history-body { - border-top: 1px solid var(--border, rgba(127, 127, 127, 0.12)); - padding: 8px 10px; - background: var(--code-bg, rgba(127, 127, 127, 0.04)); -} - -.chat-history-pre { - margin: 0; - font-family: var(--font-mono, ui-monospace, SFMono-Regular, monospace); - font-size: 12px; - line-height: 1.5; - white-space: pre-wrap; - word-break: break-word; - color: var(--text-primary); -} - -.chat-history-pre--code { - white-space: pre; - overflow-x: auto; -} - -.chat-history-pre--scroll { - max-height: 600px; - overflow-y: auto; -} - -.chat-history-attachments { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin-bottom: 8px; -} - -/* ── Grouped tool activity ───────────────────────────────────────────── - * - * A contiguous burst of tool calls/results folds into one collapsible - * block (ChatGPT/Claude style) instead of one bubble per call. The - * collapsed summary shows the most recent step; the run and each step - * expand smoothly via a grid-template-rows height transition. - */ -.chat-message-history > .chat-tool-group, -.chat-message-history > .chat-reasoning-group { - flex: 1; - min-width: 0; -} - -.chat-tool-group { - width: 100%; -} - -.chat-tool-group-summary { - display: flex; - align-items: center; - gap: 8px; - width: 100%; - padding: 4px 6px; - border: none; - border-radius: 6px; - background: transparent; - cursor: pointer; - text-align: left; - font: inherit; - /* Normal state: dim. Brightens on hover (see below). */ - color: var(--text-muted); -} - -.chat-tool-group-summary:hover, -.chat-tool-group-summary:focus-visible { - color: var(--text-primary); -} - -/* Chevron lives on the right and only appears on hover (or while expanded), - matching the Codex-style collapsible row. */ -.chat-tool-group-chevron { - flex-shrink: 0; - color: var(--text-muted); - opacity: 0; - transition: - opacity 0.15s ease, - transform 0.18s ease; -} - -.chat-tool-group-summary:hover .chat-tool-group-chevron, -.chat-tool-group-summary:focus-visible .chat-tool-group-chevron { - opacity: 1; -} - -.chat-tool-group-chevron--open { - opacity: 1; - transform: rotate(90deg); -} - -.chat-tool-group-icon { - flex-shrink: 0; - color: var(--text-muted); -} - -.chat-tool-group-summary:hover .chat-tool-group-icon { - color: var(--text-secondary); -} - -.chat-tool-group-spinner { - flex-shrink: 0; - display: inline-flex; -} - -.chat-tool-group-name { - font-size: 13px; - font-weight: 600; - color: inherit; - flex-shrink: 0; -} - -.chat-tool-group-detail { - font-size: 12px; - color: var(--text-muted); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - /* Size to content (capped) so it doesn't stretch and shove the chevron to - the far edge — the chevron stays beside the title cluster. */ - flex: 0 1 auto; - min-width: 0; - max-width: 340px; -} - -/* ── Reasoning group (mirrors tool-group styling) ───────────────────── */ -.chat-reasoning-group { - width: 100%; -} - -.chat-reasoning-group-summary { - display: flex; - align-items: center; - gap: 8px; - width: 100%; - padding: 4px 6px; - border: none; - border-radius: 6px; - background: transparent; - cursor: pointer; - text-align: left; - font: inherit; - /* Normal state: dim. Brightens on hover (see below). */ - color: var(--text-muted); -} - -.chat-reasoning-group-summary:hover, -.chat-reasoning-group-summary:focus-visible { - color: var(--text-primary); -} - -.chat-reasoning-group-chevron { - flex-shrink: 0; - color: var(--text-muted); - opacity: 0; - transition: - opacity 0.15s ease, - transform 0.18s ease; -} - -.chat-reasoning-group-summary:hover .chat-reasoning-group-chevron, -.chat-reasoning-group-summary:focus-visible .chat-reasoning-group-chevron { - opacity: 1; -} - -.chat-reasoning-group-chevron--open { - opacity: 1; - transform: rotate(90deg); -} - -.chat-reasoning-group-icon { - flex-shrink: 0; - color: var(--text-muted); -} - -.chat-reasoning-group-summary:hover .chat-reasoning-group-icon { - color: var(--text-secondary); -} - -.chat-reasoning-group-spinner { - flex-shrink: 0; - display: inline-flex; -} - -.chat-reasoning-group-title { - font-size: 13px; - font-weight: 600; - color: inherit; - flex-shrink: 0; -} - -/* Smooth height animation without measuring: 0fr → 1fr collapses the row. */ -.chat-tool-collapse { - display: grid; - grid-template-rows: 0fr; - transition: grid-template-rows 0.22s ease; -} - -.chat-tool-collapse--open { - grid-template-rows: 1fr; -} - -.chat-tool-collapse-inner { - overflow: hidden; - min-height: 0; -} - -.chat-tool-group-items { - display: flex; - flex-direction: column; - border-top: 1px solid var(--border, rgba(127, 127, 127, 0.12)); -} - -/* ── A single step inside the group ──────────────────────────────────── */ -.chat-tool-item { - border-bottom: 1px solid var(--border, rgba(127, 127, 127, 0.08)); -} -.chat-tool-item:last-child { - border-bottom: none; -} - -.chat-tool-item-header { - display: flex; - align-items: center; - gap: 8px; - width: 100%; - padding: 6px 12px 6px 14px; - border: none; - background: transparent; - cursor: pointer; - text-align: left; - font: inherit; -} - -.chat-tool-item-header:hover { - background: var(--hover, rgba(127, 127, 127, 0.05)); -} - -.chat-tool-item-chevron { - flex-shrink: 0; - color: var(--text-muted); - transition: transform 0.18s ease; -} -.chat-tool-item-chevron--open { - transform: rotate(90deg); -} - -.chat-tool-item-dot { - flex-shrink: 0; - width: 7px; - height: 7px; - border-radius: 50%; -} -.chat-tool-item-dot--call { - background: var(--info, #4aa8ff); -} -.chat-tool-item-dot--result { - background: var(--success, #4ac38a); -} -.chat-tool-item-dot--failed { - background: var(--danger, #e5544b); -} - -.chat-tool-item-kind { - font-size: 11px; - color: var(--text-muted); - text-transform: lowercase; - letter-spacing: 0.02em; - flex-shrink: 0; -} - -.chat-tool-item-name { - font-size: 12px; - font-weight: 500; - color: var(--text-primary); - flex-shrink: 0; -} - -.tool-glyph { - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - color: var(--text-secondary, var(--text-muted)); -} - -.tool-glyph svg { - width: 100%; - height: 100%; -} - -.chat-tool-item-glyph { - color: var(--text-muted); -} - -.chat-tool-item-glyph--failed { - color: var(--danger, #ef4444); -} - -.chat-tool-item-detail { - font-size: 11px; - color: var(--text-muted); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - flex: 1; - min-width: 0; -} - -.chat-tool-item-body { - padding: 8px 12px 10px 32px; - background: var(--code-bg, rgba(127, 127, 127, 0.04)); -} - -@keyframes fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -/* Model picker */ -.chat-model-bar { - position: relative; - display: flex; - align-items: center; -} - -/* Shared chip style for the input-footer controls (model + folder). */ -.chat-meta-chip { - display: flex; - align-items: center; - gap: 4px; - background: none; - border: none; - color: var(--text-muted); - font-size: 11px; - cursor: pointer; - padding: 4px 6px; - border-radius: 4px; - transition: all var(--transition); -} - -.chat-meta-chip:hover, -.chat-meta-chip--active { - color: var(--text-secondary); - background: var(--bg-hover); -} - -.chat-ctxfolder-picker { - position: relative; - display: flex; - align-items: center; -} - -.chat-ctxfolder-group { - position: relative; - display: flex; - align-items: center; - gap: 2px; -} - -.chat-ctxfolder-dropdown { - position: absolute; - bottom: 100%; - inset-inline-start: 0; - margin-bottom: 6px; - width: 230px; - max-height: 320px; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-md); - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); - z-index: 200; - padding: 6px; - display: flex; - flex-direction: column; -} - -.chat-ctxfolder-dropdown-header { - font-size: 11px; - color: var(--text-muted); - padding: 2px 8px 6px; - font-weight: 500; -} - -.chat-ctxfolder-dropdown-list { - display: flex; - flex-direction: column; - gap: 1px; - max-height: 220px; - overflow-y: auto; -} - -.chat-ctxfolder-dropdown-item { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - padding: 6px 8px; - background: none; - border: none; - border-radius: var(--radius-sm); - color: var(--text-primary); - font-size: 12px; - cursor: pointer; - text-align: left; - transition: background var(--transition); -} - -.chat-ctxfolder-dropdown-item:hover { - background: var(--bg-hover); -} - -.chat-ctxfolder-dropdown-item--active { - color: var(--text-secondary); -} - -.chat-ctxfolder-dropdown-item-name { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.chat-ctxfolder-dropdown-item-check { - color: var(--text-secondary); - flex-shrink: 0; - margin-left: 8px; -} - -.chat-ctxfolder-dropdown-empty { - font-size: 12px; - color: var(--text-muted); - padding: 8px; - text-align: center; -} - -.chat-ctxfolder-dropdown-divider { - height: 1px; - background: var(--border-subtle); - margin: 4px 0; - flex-shrink: 0; -} - -.chat-ctxfolder-dropdown-item--open { - color: var(--text-secondary); -} - -.chat-ctxfolder-name { - max-width: 160px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.chat-meta-chip-icon { - display: flex; - align-items: center; - justify-content: center; - background: none; - border: none; - color: var(--text-muted); - cursor: pointer; - padding: 3px; - border-radius: 4px; - transition: all var(--transition); -} - -.chat-meta-chip-icon:hover, -.chat-meta-chip-icon--active { - color: var(--text-secondary); - background: var(--bg-hover); -} - -.chat-model-trigger { - display: flex; - align-items: center; - gap: 4px; - background: none; - border: none; - color: var(--text-muted); - font-size: 11px; - cursor: pointer; - padding: 4px 8px; - border-radius: 4px; - transition: all var(--transition); -} - -.chat-model-trigger:hover { - color: var(--text-secondary); - background: var(--bg-hover); -} - -.chat-model-name { - max-width: 200px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.chat-model-dropdown { - position: absolute; - bottom: 100%; - inset-inline-start: 0; - margin-bottom: 4px; - width: 320px; - max-height: 360px; - overflow-y: auto; - overflow-x: hidden; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-md); - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); - z-index: 100; - padding: 6px; -} - -/* Reasoning effort picker */ -.chat-reasoning-bar { - position: relative; - display: flex; - align-items: center; -} - -.chat-reasoning-trigger { - display: flex; - align-items: center; - gap: 4px; - background: none; - border: none; - color: var(--text-muted); - font-size: 11px; - cursor: pointer; - padding: 4px 8px; - border-radius: 4px; - transition: all var(--transition); -} - -.chat-reasoning-trigger:hover, -.chat-reasoning-trigger[aria-expanded="true"] { - color: var(--text-secondary); - background: var(--bg-hover); -} - -.chat-reasoning-name { - max-width: 140px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.chat-reasoning-dropdown { - position: absolute; - bottom: 100%; - inset-inline-start: 0; - margin-bottom: 4px; - width: 280px; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-md); - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); - z-index: 100; - padding: 6px; -} - -.chat-reasoning-header { - font-size: 10px; - font-weight: 700; - color: var(--text-muted); - text-transform: uppercase; - letter-spacing: 0.05em; - text-align: start; - padding: 6px 8px 4px; -} - -.chat-reasoning-hint { - color: var(--text-muted); - font-size: 11px; - line-height: 1.35; - padding: 0 8px 6px; -} - -.chat-reasoning-error { - color: var(--danger); - font-size: 11px; - line-height: 1.35; - padding: 0 8px 6px; -} - -.chat-reasoning-option { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - width: 100%; - padding: 8px; - border: none; - background: none; - color: var(--text-primary); - cursor: pointer; - border-radius: 4px; - text-align: left; - transition: background var(--transition); -} - -.chat-reasoning-option:hover { - background: var(--bg-hover); -} - -.chat-reasoning-option.active { - background: var(--accent-subtle); - color: var(--accent-text); -} - -.chat-reasoning-option-copy { - display: flex; - flex-direction: column; - gap: 2px; - min-width: 0; -} - -.chat-reasoning-option-label { - font-size: 12px; - font-weight: 600; -} - -.chat-reasoning-option-description { - color: var(--text-muted); - font-size: 11px; - line-height: 1.3; -} - -.chat-reasoning-option.active .chat-reasoning-option-description { - color: var(--accent-text); - opacity: 0.8; -} - -.chat-reasoning-check { - flex-shrink: 0; -} - -.chat-model-search-input, -.chat-model-custom-input { - box-sizing: border-box; -} - -.chat-model-group { - margin-bottom: 4px; -} - -.chat-model-group-label { - font-size: 10px; - font-weight: 700; - color: var(--text-muted); - text-transform: uppercase; - letter-spacing: 0.05em; - padding: 6px 8px 4px; -} - -.chat-model-option { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - padding: 6px 8px; - border: none; - background: none; - color: var(--text-primary); - font-size: 12px; - cursor: pointer; - border-radius: 4px; - text-align: left; - transition: background var(--transition); -} - -.chat-model-option:hover { - background: var(--bg-hover); -} - -.chat-model-option.active { - background: var(--accent-subtle); - color: var(--accent-text); -} - -.chat-model-option-label { - font-weight: 500; -} - -.chat-model-option-id { - font-size: 10px; - color: var(--text-muted); - max-width: 160px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.chat-model-custom { - padding: 4px 8px 6px; -} - -.chat-model-search-input, -.chat-model-custom-input { - width: 100%; - padding: 5px 8px; - font-size: 12px; - border: 1px solid var(--border); - border-radius: 4px; - color: var(--text-primary); -} - -.chat-model-search-input:focus, -.chat-model-custom-input:focus { - outline: none; - border-color: var(--border-focus); -} - -.chat-model-custom-input { - background: var(--bg-tertiary); -} - -.chat-model-search-input { - position: sticky; - top: 0; - background: var(--bg-secondary); -} - -/* ======================================================================== - SETTINGS - ======================================================================== */ -.settings-container { - padding: 24px 32px; - overflow-y: auto; - height: 100%; -} - -.settings-header { - font-size: 20px; - font-weight: 700; - margin-bottom: 5px; - color: var(--text-primary); -} - -.settings-section { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 20px; - margin-bottom: 16px; -} - -.settings-section-title { - font-size: 12px; - font-weight: 700; - color: var(--text-muted); - text-transform: uppercase; - letter-spacing: 0.8px; - margin-bottom: 16px; -} - -.settings-field { - margin-bottom: 18px; -} - -.settings-field:last-child { - margin-bottom: 0; -} - -.settings-field-label { - font-size: 13px; - font-weight: 600; - color: var(--text-primary); - margin-bottom: 6px; - display: flex; - align-items: center; - gap: 8px; -} - -.settings-field-value { - font-size: 13px; - color: var(--text-secondary); - font-family: var(--font-mono); -} - -.settings-field-hint { - font-size: 12px; - color: var(--text-muted); - margin-top: 4px; -} - -.settings-transport-status { - display: flex; - align-items: center; - gap: 8px; - flex-wrap: wrap; - margin-top: 8px; - font-size: 12px; - color: var(--text-muted); -} - -.settings-transport-status span:first-child { - font-weight: 700; -} - -.settings-transport-status code { - font-family: var(--font-mono); - font-size: 11px; - color: var(--text-secondary); - background: var(--bg-primary); - border: 1px solid var(--border); - border-radius: var(--radius-sm); - padding: 2px 6px; -} - -.settings-transport-status--ok span:first-child { - color: var(--success, #22c55e); -} - -.settings-transport-status--warn span:first-child { - color: var(--warning, #f59e0b); -} - -.settings-input-row { - display: flex; - gap: 8px; - align-items: center; -} - -.settings-input-row .input { - flex: 1; -} - -.settings-select { - appearance: none; - background-image: url("data:image/svg+xml,%3Csvg width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: right 12px center; - padding-right: 36px; - cursor: pointer; -} - -.settings-toggle-btn { - font-size: 12px; - font-weight: 600; - white-space: nowrap; -} - -.settings-pool-add { - display: flex; - gap: 8px; - align-items: center; - margin-bottom: 12px; -} - -.settings-pool-add .input { - box-sizing: border-box; -} - -.settings-pool-group { - margin-top: 10px; -} - -.settings-pool-provider { - display: flex; - align-items: center; - gap: 6px; - font-size: 11px; - font-weight: 700; - color: var(--text-muted); - text-transform: uppercase; - letter-spacing: 0.05em; - margin-bottom: 6px; -} - -.settings-provider-row { - display: flex; - align-items: center; - gap: 10px; -} - -.settings-provider-row .input { - flex: 1; -} - -.settings-model-row { - display: flex; - align-items: center; - gap: 8px; -} - -.settings-model-row .input { - flex: 1; -} - -.provider-keys-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); - gap: 12px; -} - -.provider-key-card { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 14px; - display: flex; - flex-direction: column; - gap: 8px; -} - -.provider-key-card-head { - display: flex; - align-items: center; - gap: 10px; -} - -.provider-key-card-title { - font-size: 13px; - font-weight: 600; - color: var(--text-primary); - flex: 1; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.provider-key-card .settings-input-row { - margin: 0; -} - -.provider-key-card .settings-field-hint { - font-size: 11px; - color: var(--text-muted); -} - -.oauth-signin-btn { - display: inline-flex; - align-items: center; - gap: 6px; - margin-top: 8px; - align-self: flex-start; -} - -.oauth-login-status { - font-size: 12px; - color: var(--text-muted); - margin: 0 0 10px; -} - -/* Prominent outcome banner shown when the sign-in finishes — the raw - CLI log below stays append-only, so the result needs to stand out. */ -.oauth-login-result { - font-size: 13px; - font-weight: 600; - padding: 10px 12px; - border-radius: 8px; - margin: 0 0 10px; -} - -.oauth-login-result-success { - color: var(--success); - background: var(--success-bg); -} - -.oauth-login-result-error { - color: var(--error); - background: var(--error-bg); -} - -.settings-pool-entry { - display: flex; - align-items: center; - gap: 10px; - padding: 5px 0; - font-size: 12px; - border-bottom: 1px solid var(--border); -} - -.settings-pool-label { - color: var(--text-primary); - font-weight: 500; - min-width: 80px; -} - -.settings-pool-key { - color: var(--text-muted); - font-family: var(--font-mono); - font-size: 11px; - flex: 1; -} - -.settings-saved { - color: var(--success); - font-size: 12px; - font-weight: 600; - animation: fadeInOut 2s ease forwards; -} - -@keyframes fadeInOut { - 0% { - opacity: 0; - } - 15% { - opacity: 1; - } - 85% { - opacity: 1; - } - 100% { - opacity: 0; - } -} - -.skeleton { - display: inline-block; - height: 14px; - border-radius: 4px; - background: var(--bg-elevated); - animation: skeleton-pulse 1.2s ease-in-out infinite; -} - -.skeleton-sm { - width: 60px; -} - -.skeleton-md { - width: 140px; -} - -@keyframes skeleton-pulse { - 0%, - 100% { - opacity: 0.4; - } - 50% { - opacity: 0.8; - } -} - -.settings-hermes-info { - display: flex; - flex-direction: column; - gap: 12px; -} - -.settings-hermes-row { - display: flex; - gap: 24px; - flex-wrap: wrap; -} - -.settings-hermes-detail { - display: flex; - flex-direction: column; - gap: 2px; -} - -.settings-hermes-label { - font-size: 11px; - font-weight: 600; - color: var(--text-muted); - text-transform: uppercase; - letter-spacing: 0.5px; -} - -.settings-hermes-value { - font-size: 13px; - color: var(--text-primary); -} - -.settings-hermes-path { - font-family: var(--font-mono); - font-size: 12px; - color: var(--text-secondary); -} - -.settings-hermes-update-badge { - font-size: 12px; - color: var(--warning); - background: rgba(245, 158, 11, 0.1); - padding: 6px 10px; - border-radius: var(--radius); - width: fit-content; -} - -.settings-hermes-actions { - display: flex; - gap: 8px; -} - -.settings-hermes-result { - font-size: 12px; - padding: 6px 10px; - border-radius: var(--radius); -} - -.settings-hermes-result.success { - color: var(--success); - background: var(--success-bg); -} - -.settings-hermes-result.error { - color: var(--error); - background: var(--error-bg); -} - -.settings-api-key-banner { - background: var(--warning-bg, #fff8e1); - border: 1px solid var(--warning-border, #f9a825); - border-radius: var(--radius-lg); - padding: 14px 16px; - margin-bottom: 16px; - display: flex; - flex-direction: column; - gap: 10px; -} - -.settings-api-key-banner--info { - background: var(--bg-tertiary); - border-color: var(--border-bright); -} - -.settings-api-key-banner-title { - font-size: 13px; - font-weight: 600; - color: var(--text-primary); -} - -.settings-api-key-banner-title code { - font-family: monospace; - font-size: 12px; - background: rgba(0, 0, 0, 0.07); - padding: 1px 4px; - border-radius: 3px; -} - -.settings-api-key-banner-desc { - font-size: 12px; - color: var(--text-secondary); - line-height: 1.5; -} - -.settings-migration-banner { - background: var(--bg-tertiary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-lg); - padding: 16px; - margin-bottom: 16px; - display: flex; - flex-direction: column; - gap: 12px; -} - -.settings-migration-header { - display: flex; - justify-content: space-between; - align-items: flex-start; - gap: 12px; -} - -.settings-migration-title { - font-size: 14px; - font-weight: 600; - color: var(--text-primary); - margin-bottom: 4px; -} - -.settings-migration-desc { - font-size: 12px; - color: var(--text-secondary); - line-height: 1.5; -} - -.settings-migration-desc code { - font-family: var(--font-mono); - font-size: 11px; - background: var(--bg-elevated); - padding: 1px 5px; - border-radius: 3px; -} - -.settings-migration-dismiss { - font-size: 20px; - line-height: 1; - color: var(--text-muted); - padding: 0 4px; - flex-shrink: 0; -} - -.settings-migration-actions { - display: flex; - gap: 8px; -} - -.settings-hermes-doctor { - font-family: var(--font-mono); - font-size: 12px; - line-height: 1.5; - color: var(--text-secondary); - background: var(--bg-tertiary); - border-radius: var(--radius); - padding: 12px; - max-height: 200px; - overflow-y: auto; - white-space: pre-wrap; - word-break: break-word; -} - -.settings-gateway-row { - display: flex; - align-items: center; - gap: 12px; - margin-bottom: 4px; -} - -.settings-gateway-status { - font-size: 13px; - font-weight: 600; - display: flex; - align-items: center; - gap: 6px; -} - -.settings-gateway-status::before { - content: ""; - width: 8px; - height: 8px; - border-radius: 50%; -} - -.settings-gateway-status.running::before { - background: var(--success); -} - -.settings-gateway-status.stopped::before { - background: var(--text-muted); -} - -.settings-gateway-status.running { - color: var(--success); -} - -.settings-gateway-status.stopped { - color: var(--text-muted); -} - -.settings-gateway-error { - margin: 8px 0 4px; - padding: 10px 12px; - border: 1px solid color-mix(in srgb, var(--danger) 45%, var(--border)); - border-radius: var(--radius); - color: var(--danger); - background: color-mix(in srgb, var(--danger) 12%, transparent); - font-size: 13px; - line-height: 1.45; - word-break: break-word; -} - -/* Platform cards in Gateway */ -.settings-platform-card { - border: 1px solid var(--border); - border-radius: var(--radius); - padding: 14px 16px; - margin-bottom: 10px; -} - -.settings-platform-header { - display: flex; - align-items: center; - justify-content: space-between; -} - -.settings-platform-left { - display: flex; - align-items: center; - gap: 12px; - min-width: 0; - flex: 1; -} - -.settings-platform-info { - display: flex; - flex-direction: column; - gap: 2px; - min-width: 0; -} - -.settings-platform-label { - font-size: 14px; - font-weight: 600; - color: var(--text-primary); -} - -.settings-platform-desc { - font-size: 12px; - color: var(--text-muted); -} - -.settings-platform-fields { - margin-top: 14px; - padding-top: 14px; - border-top: 1px solid var(--border); -} - -.settings-platform-fields .settings-field:last-child { - margin-bottom: 0; -} - -.gateway-page-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 16px; - margin-bottom: 18px; -} - -.gateway-page-subtitle { - color: var(--text-secondary); - font-size: 13px; - margin: -6px 0 0; -} - -.gateway-page-header .btn, -.gateway-platform-actions .btn, -.gateway-platform-actions .btn-ghost { - display: inline-flex; - align-items: center; - gap: 7px; -} - -.gateway-overview { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 16px; -} - -.gateway-overview .settings-field { - flex: 1; -} - -.gateway-inline-warning { - max-width: 420px; - padding: 10px 12px; - border: 1px solid rgba(245, 158, 11, 0.3); - border-radius: var(--radius); - color: var(--warning); - background: rgba(245, 158, 11, 0.08); - font-size: 12px; - line-height: 1.4; -} - -.gateway-toolbar { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - margin: 0 0 18px; -} - -.gateway-search { - flex: 1; - display: flex; - align-items: center; - gap: 10px; - min-height: 42px; - padding: 0 12px; - border: 1px solid var(--border); - border-radius: var(--radius); - background: var(--bg-primary); - color: var(--text-muted); -} - -.gateway-search:focus-within { - border-color: var(--accent); - box-shadow: 0 0 0 1px rgba(0, 136, 255, 0.18); -} - -.gateway-search input { - flex: 1; - min-width: 0; - border: 0; - outline: 0; - background: transparent; - color: var(--text-primary); - font-family: var(--font-sans); - font-size: 14px; -} - -.gateway-advanced-toggle { - display: inline-flex; - align-items: center; - gap: 8px; - color: var(--text-secondary); - font-size: 13px; - white-space: nowrap; - cursor: pointer; -} - -/* Section heading with a control (e.g. "Show advanced") on the right. */ -.gateway-section-heading-row { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; -} - -.gateway-section-heading-row .gateway-advanced-toggle { - font-size: 12px; -} - -.gateway-platform-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); - gap: 12px; -} - -.gateway-platform-section { - background: transparent; - border: 0; - padding: 0; -} - -.gateway-platform-card { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 14px; - margin-bottom: 0; - transition: - border-color var(--transition), - background var(--transition), - box-shadow var(--transition); -} - -.gateway-platform-card:hover { - background: var(--bg-tertiary); - border-color: var(--border-bright); -} - -.gateway-platform-card:focus-within { - border-color: var(--accent); - box-shadow: 0 0 0 2px var(--accent-subtle); -} - -.gateway-platform-header { - align-items: flex-start; - gap: 14px; -} - -.gateway-platform-header .tools-toggle { - flex-shrink: 0; -} - -.gateway-toggle-wrapper { - flex-shrink: 0; -} - -.gateway-toggle-needs-setup { - cursor: not-allowed; - opacity: 0.45; - position: relative; -} - -.gateway-toggle-needs-setup .tools-toggle { - pointer-events: none; -} - -.gateway-toggle-wrapper[data-tooltip]::before { - content: attr(data-tooltip); - position: absolute; - bottom: calc(100% + 8px); - right: 0; - width: max-content; - max-width: 200px; - background: var(--bg-elevated); - color: var(--text-primary); - border: 1px solid var(--border-bright); - font-size: 12px; - line-height: 1.4; - padding: 6px 10px; - border-radius: 6px; - white-space: normal; - pointer-events: none; - opacity: 0; - visibility: hidden; - transition: - opacity 0.15s ease, - visibility 0.15s ease; - z-index: 100; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); -} - -.gateway-toggle-wrapper[data-tooltip]::after { - content: ""; - position: absolute; - bottom: calc(100% + 2px); - right: 10px; - border: 5px solid transparent; - border-top-color: var(--bg-elevated); - pointer-events: none; - opacity: 0; - visibility: hidden; - transition: - opacity 0.15s ease, - visibility 0.15s ease; - z-index: 100; -} - -.gateway-toggle-wrapper[data-tooltip]:hover::before, -.gateway-toggle-wrapper[data-tooltip]:hover::after { - opacity: 1; - visibility: visible; -} - -.gateway-platform-title-row { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 8px; -} - -.gateway-state-pill { - display: inline-flex; - align-items: center; - gap: 4px; - border-radius: 999px; - padding: 2px 7px; - font-size: 11px; - font-weight: 700; -} - -.gateway-state-pill.ok { - color: var(--success); - background: rgba(34, 197, 94, 0.12); -} - -.gateway-state-pill.warn { - color: var(--warning); - background: rgba(245, 158, 11, 0.12); -} - -.gateway-state-pill.error { - color: var(--error); - background: rgba(239, 68, 68, 0.12); -} - -.gateway-state-pill.muted { - color: var(--text-muted); - background: var(--bg-elevated); -} - -.gateway-platform-actions { - display: flex; - align-items: center; - justify-content: space-between; - flex-wrap: wrap; - gap: 8px; - margin-top: 12px; -} - -.gateway-platform-actions-left, -.gateway-platform-actions-right { - display: flex; - align-items: center; - gap: 8px; -} - -.gateway-icon-action { - min-height: 30px; - font-size: 12px; - color: var(--text-secondary); -} - -.gateway-details-toggle svg { - transition: transform var(--transition); -} - -.gateway-details-toggle.open svg { - transform: rotate(180deg); -} - -.gateway-details-toggle.warn { - color: var(--warning); -} - -.gateway-save-button { - min-height: 30px; -} - -.gateway-platform-details { - margin-top: 12px; - padding-top: 12px; - border-top: 1px solid var(--border); -} - -.gateway-test-message { - padding: 9px 10px; - border-radius: var(--radius-sm); - font-size: 12px; - line-height: 1.4; -} - -.gateway-test-message.ok { - color: var(--success); - background: rgba(34, 197, 94, 0.1); -} - -.gateway-test-message.warn { - color: var(--warning); - background: rgba(245, 158, 11, 0.1); -} - -/* Test result shown on the card (outside the configure modal). */ -.gateway-platform-card > .gateway-test-message { - margin-top: 10px; -} - -.gateway-unsaved-hint { - font-size: 11px; - font-weight: 600; - color: var(--warning); -} - -/* ── Configure modal ─────────────────────────────────────────────────── */ -.gateway-modal-overlay { - position: fixed; - inset: 0; - background: rgba(0, 0, 0, 0.5); - display: flex; - align-items: center; - justify-content: center; - z-index: 200; - padding: 24px; -} - -.gateway-modal { - display: flex; - flex-direction: column; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-lg); - width: 840px; - max-width: 100%; - max-height: 85vh; - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4); - overflow: hidden; -} - -.gateway-modal-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 14px 18px; - border-bottom: 1px solid var(--border); - flex-shrink: 0; -} - -.gateway-modal-title { - display: flex; - align-items: center; - gap: 10px; - min-width: 0; - font-size: 15px; - font-weight: 600; - color: var(--text-primary); -} - -.gateway-modal-body { - flex: 1; - overflow-y: auto; - padding: 20px; - /* One consistent rhythm between desc / test banner / each section. */ - display: flex; - flex-direction: column; - gap: 20px; -} - -/* A titled section (heading + its content) inside the modal. */ -.gateway-modal-section { - display: flex; - flex-direction: column; - gap: 10px; -} - -.gateway-modal-desc { - margin: 0; - font-size: 12.5px; - line-height: 1.5; - color: var(--text-secondary); -} - -.gateway-modal-footer { - display: flex; - align-items: center; - gap: 8px; - padding: 12px 18px; - border-top: 1px solid var(--border); - flex-shrink: 0; -} - -.gateway-modal-footer-spacer { - flex: 1; -} - -.gateway-capabilities { - display: flex; - flex-direction: column; - gap: 10px; -} - -.gateway-detail-heading { - color: var(--text-secondary); - font-size: 11px; - font-weight: 800; - letter-spacing: 0.08em; - text-transform: uppercase; -} - -.gateway-capability-list { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); - gap: 8px; - /* stretch (default): every card matches the tallest in its row so a - * 1-line description lines up with a 2-line neighbour. */ - align-items: stretch; -} - -/* When a capability's high-risk confirmation opens, let that card span the - * full row so the warning isn't cramped into a single grid cell. */ -.gateway-capability-row:has(.gateway-risk-warning) { - grid-column: 1 / -1; -} - -.gateway-capability-row { - display: grid; - grid-template-columns: minmax(0, 1fr) auto; - gap: 10px; - align-items: center; - padding: 10px; - border: 1px solid var(--border); - border-radius: var(--radius); - background: var(--bg-primary); -} - -.gateway-capability-row.high-risk { - border-color: rgba(245, 158, 11, 0.26); -} - -.gateway-capability-copy { - min-width: 0; -} - -.gateway-capability-title { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 7px; - color: var(--text-primary); - font-size: 13px; - font-weight: 700; -} - -.gateway-capability-title code { - color: var(--text-muted); - font-size: 10px; - font-weight: 700; - background: var(--bg-elevated); - border-radius: 4px; - padding: 2px 5px; -} - -.gateway-capability-description { - margin-top: 3px; - color: var(--text-muted); - font-size: 12px; - line-height: 1.4; -} - -.gateway-risk-pill { - color: var(--warning); - background: rgba(245, 158, 11, 0.12); - border-radius: 999px; - padding: 2px 7px; - font-size: 10px; - font-weight: 800; - text-transform: uppercase; -} - -.gateway-risk-warning { - grid-column: 1 / -1; - display: grid; - grid-template-columns: auto minmax(0, 1fr); - gap: 10px; - padding: 10px; - border: 1px solid rgba(239, 68, 68, 0.34); - border-radius: var(--radius); - color: var(--text-primary); - background: rgba(239, 68, 68, 0.08); -} - -.gateway-risk-warning svg { - color: var(--error); - margin-top: 2px; -} - -.gateway-risk-warning strong { - color: var(--error); - font-size: 12px; -} - -.gateway-risk-warning p { - margin: 4px 0 0; - color: var(--text-secondary); - font-size: 12px; - line-height: 1.45; -} - -.gateway-risk-actions { - display: flex; - justify-content: flex-end; - gap: 8px; - margin-top: 10px; -} - -.gateway-platform-fields { - display: grid; - gap: 12px; - margin-top: 0; - padding-top: 0; - border-top: 0; -} - -.gateway-platform-details .gateway-platform-fields:first-child { - margin-top: 0; -} - -.gateway-field { - background: var(--bg-primary); - border: 1px solid var(--border); - border-radius: var(--radius); - padding: 12px; - margin-bottom: 0; -} - -.gateway-field-label { - display: flex; - align-items: center; - justify-content: space-between; - gap: 10px; -} - -.gateway-field-label code { - color: var(--text-muted); - font-size: 11px; - font-weight: 600; - background: var(--bg-elevated); - border-radius: 4px; - padding: 2px 5px; - max-width: 48%; - overflow: hidden; - text-overflow: ellipsis; -} - -.gateway-required-dot { - color: var(--warning); - margin-left: 3px; -} - -.gateway-input-row .settings-toggle-btn { - min-width: 34px; - height: 34px; -} - -.gateway-advanced-badge { - display: inline-flex; - margin-left: 8px; - padding: 1px 5px; - border-radius: 999px; - background: var(--bg-elevated); - color: var(--text-muted); - font-size: 10px; - font-weight: 700; - text-transform: uppercase; -} - -.gateway-empty-state { - display: flex; - align-items: center; - justify-content: center; - min-height: 140px; - color: var(--text-muted); - border: 1px dashed var(--border); - border-radius: var(--radius); -} - -@media (max-width: 760px) { - .gateway-page-header, - .gateway-overview, - .gateway-toolbar { - flex-direction: column; - align-items: stretch; - } - - .gateway-platform-grid { - grid-template-columns: 1fr; - } - - .gateway-platform-actions { - align-items: stretch; - } - - .gateway-platform-actions-left, - .gateway-platform-actions-right { - width: 100%; - justify-content: flex-end; - } -} - -/* Theme select in settings */ -.settings-theme-options { - display: flex; - gap: 8px; -} - -.settings-theme-option { - flex: 1; - padding: 10px 12px; - background: var(--bg-primary); - border: 1.5px solid var(--border); - border-radius: var(--radius-sm); - cursor: pointer; - transition: all var(--transition); - text-align: center; - font-family: var(--font-sans); - font-size: 13px; - font-weight: 600; - color: var(--text-secondary); -} - -.settings-theme-option:hover { - border-color: var(--border-bright); -} - -.settings-theme-option.active { - border-color: var(--accent); - color: var(--accent-text); - background: var(--accent-subtle); -} - -/* Theme grid (VS Code-style theme picker) */ -.settings-theme-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); - gap: 10px; -} - -.settings-theme-card { - display: flex; - flex-direction: column; - gap: 8px; - padding: 8px; - background: var(--bg-primary); - border: 1.5px solid var(--border); - border-radius: var(--radius-md); - cursor: pointer; - transition: all var(--transition); - text-align: left; - font-family: var(--font-sans); -} - -.settings-theme-card:hover { - border-color: var(--border-bright); -} - -.settings-theme-card.active { - border-color: var(--accent); - background: var(--accent-subtle); -} - -/* Live preview rendered with the target theme's own variables */ -.settings-theme-preview { - display: flex; - height: 46px; - border-radius: var(--radius-sm); - overflow: hidden; - border: 1px solid var(--border); - background: var(--bg-primary); -} - -.settings-theme-preview-sidebar { - width: 30%; - background: var(--bg-secondary); - border-right: 1px solid var(--border); -} - -.settings-theme-preview-main { - flex: 1; - display: flex; - flex-direction: column; - justify-content: center; - gap: 5px; - padding: 0 8px; -} - -.settings-theme-preview-bar { - height: 5px; - border-radius: 3px; - background: var(--text-muted); -} - -.settings-theme-preview-bar.accent { - width: 55%; - background: var(--accent); -} - -.settings-theme-preview-bar.text { - width: 80%; - background: var(--text-secondary); -} - -.settings-theme-card-row { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; -} - -.settings-theme-card-name { - font-size: 13px; - font-weight: 600; - color: var(--text-primary); -} - -.settings-theme-card-check { - color: var(--accent-text); - display: flex; -} - -.settings-theme-system { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 12px; - margin-bottom: 12px; - background: var(--bg-primary); - border: 1.5px solid var(--border); - border-radius: var(--radius-md); -} - -.settings-theme-system.active { - border-color: var(--accent); - background: var(--accent-subtle); -} - -.settings-theme-system-label { - font-size: 13px; - font-weight: 600; - color: var(--text-primary); -} - -.settings-theme-system-hint { - font-size: 12px; - color: var(--text-muted); - margin-top: 2px; -} - -/* Language picker dropdown */ -.settings-language-select { - position: relative; -} - -.settings-language-trigger { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - padding: 10px 14px; - background: var(--bg-primary); - border: 1.5px solid var(--border); - border-radius: var(--radius-sm); - cursor: pointer; - transition: border-color var(--transition); - font-family: var(--font-sans); - font-size: 13px; - font-weight: 600; - color: var(--text-primary); - text-align: left; -} - -.settings-language-trigger:hover { - border-color: var(--border-bright); -} - -.settings-language-dropdown { - position: absolute; - top: calc(100% + 4px); - left: 0; - right: 0; - max-height: 280px; - overflow-y: auto; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-md); - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); - z-index: 100; - padding: 6px; -} - -.settings-language-option { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - padding: 8px 10px; - border: none; - background: none; - color: var(--text-primary); - font-family: var(--font-sans); - font-size: 13px; - font-weight: 500; - cursor: pointer; - border-radius: 4px; - text-align: left; - transition: background var(--transition); -} - -.settings-language-option:hover { - background: var(--bg-hover); -} - -.settings-language-option.active { - background: var(--accent-subtle); - color: var(--accent-text); -} - -/* ======================================================================== - AGENTS - ======================================================================== */ -.agents-container { - display: flex; - flex-direction: column; - height: 100%; - overflow-y: auto; - padding: 10px 20px; -} - -.agents-loading { - flex: 1; - display: flex; - align-items: center; - justify-content: center; -} - -.agents-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - margin-bottom: 8px; -} - -.agents-title { - font-size: 20px; - font-weight: 700; - color: var(--text-primary); -} - -.agents-subtitle { - font-size: 13px; - color: var(--text-muted); - margin-top: 2px; -} - -.agents-create-clone { - display: flex; - align-items: center; - gap: 8px; - font-size: 13px; - font-weight: 400; - color: var(--text-secondary); - cursor: pointer; -} - -.agents-create-clone input[type="checkbox"] { - accent-color: var(--accent); -} - -.agents-create-error { - font-size: 13px; - color: var(--error); -} - -/* Profiles list — a table-style layout with a shared column grid so the - header and every row align. The active row is marked by a left green bar. */ -.agents-table { - border: 1px solid var(--border); - border-radius: var(--radius-md); - overflow: hidden; - background: var(--bg-secondary); -} - -.agents-table-head, -.agents-row { - display: grid; - grid-template-columns: - minmax(220px, 1.8fr) minmax(140px, 1fr) minmax(150px, 1fr) - auto; - align-items: center; - gap: 16px; - padding: 14px 20px; -} - -.agents-table-head { - font-size: 11px; - font-weight: 600; - letter-spacing: 0.06em; - text-transform: uppercase; - color: var(--text-muted); - border-bottom: 1px solid var(--border); -} - -.agents-row { - position: relative; - cursor: pointer; - font-family: var(--font-sans); - text-align: left; - border-bottom: 1px solid var(--border); - transition: background var(--transition); -} - -.agents-row:last-child { - border-bottom: none; -} - -.agents-row:hover { - background: var(--bg-tertiary); -} - -/* Active profile: a green bar flush to the left edge plus a subtle wash. */ -.agents-row.active { - background: var(--success-bg); -} - -.agents-row.active::before { - content: ""; - position: absolute; - left: 0; - top: 0; - bottom: 0; - width: 3px; - background: var(--success); -} - -.agents-cell-actions { - justify-self: end; -} - -/* Edit button — opens the profile modal. */ -.agents-row-edit { - display: inline-flex; - align-items: center; - justify-content: center; - width: 32px; - height: 32px; - padding: 0; - border: 1px solid var(--border); - border-radius: var(--radius-sm); - background: var(--bg-elevated); - color: var(--text-secondary); - cursor: pointer; - transition: all var(--transition); -} -.agents-row-edit:hover { - color: var(--text-primary); - border-color: var(--border-bright); - background: var(--bg-tertiary); -} - -/* Shared animated modal primitive. Radix handles portal/focus, Motion handles - mount/unmount transitions, and feature modals provide their own layout. */ -.app-modal-overlay { - position: fixed; - inset: 0; - background: rgba(0, 0, 0, 0.5); - z-index: 200; -} - -.app-modal-content { - position: fixed; - inset: 0; - z-index: 201; - margin: auto; - outline: none; -} - -/* Appearance modal */ -/* ── Global profile modal (80vw × 80vh) ─────────────────────────────── */ -.profile-modal-overlay { - padding: 24px; -} - -.profile-modal { - display: flex; - flex-direction: column; - width: 80vw; - height: 80vh; - max-width: 1100px; - max-height: 820px; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-lg); - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4); - overflow: hidden; -} - -.profile-modal-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 16px 22px; - border-bottom: 1px solid var(--border); - flex-shrink: 0; -} - -.profile-modal-header-main { - display: flex; - align-items: center; - gap: 10px; - min-width: 0; -} - -.profile-modal-title { - font-size: 16px; - font-weight: 600; - color: var(--text-primary); -} - -.profile-modal-close { - display: flex; - align-items: center; - justify-content: center; - border: none; - background: none; - color: var(--text-secondary); - cursor: pointer; - padding: 6px; - border-radius: var(--radius-sm); -} - -.profile-modal-close:hover { - color: var(--text-primary); - background: var(--bg-tertiary); -} - -/* Two-column body: identity/appearance left, detail/settings right. Scrolls - so the large canvas has room to grow for future profile features. */ -/* Body splits into a left section-nav rail and a scrollable content pane. */ -.profile-modal-layout { - flex: 1; - min-height: 0; - display: flex; -} - -.profile-modal-nav { - flex-shrink: 0; - width: 180px; - display: flex; - flex-direction: column; - gap: 2px; - padding: 20px 12px; - border-right: 1px solid var(--border); - overflow-y: auto; -} - -.profile-modal-nav-item { - display: flex; - align-items: center; - gap: 10px; - width: 100%; - padding: 8px 12px; - border: none; - border-radius: var(--radius-md); - background: transparent; - color: var(--text-secondary); - font: inherit; - font-size: 13px; - font-weight: 500; - text-align: left; - cursor: pointer; - transition: - background var(--transition), - color var(--transition); -} - -.profile-modal-nav-item:hover { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.profile-modal-nav-item.active { - background: var(--bg-tertiary); - color: var(--text-primary); - font-weight: 600; -} - -.profile-modal-content { - flex: 1; - min-width: 0; - min-height: 0; - overflow-y: auto; - padding: 28px 32px; -} - -.profile-modal-pane { - display: flex; - flex-direction: column; - gap: 28px; -} - -.profile-modal-identity { - display: flex; - align-items: center; - gap: 20px; -} - -.profile-modal-identity-meta { - display: flex; - flex-direction: column; - gap: 12px; - min-width: 0; -} - -.profile-modal-avatar-wrap { - position: relative; - display: inline-flex; - flex-shrink: 0; -} - -.profile-modal-avatar-dot { - position: absolute; - bottom: 4px; - right: 4px; - width: 14px; - height: 14px; - border-radius: 50%; - background: var(--success); - border: 3px solid var(--bg-secondary); -} - -.profile-modal-name-row { - display: flex; - align-items: center; - gap: 8px; -} - -.profile-modal-name { - font-size: 18px; - font-weight: 700; - color: var(--text-primary); -} - -.profile-modal-tag { - font-size: 11px; - font-weight: 600; - color: var(--text-muted); - background: var(--bg-tertiary); - padding: 1px 8px; - border-radius: 10px; -} - -.profile-modal-image-actions { - display: flex; - flex-wrap: wrap; - gap: 8px; -} - -.profile-modal-stats { - display: flex; - flex-wrap: wrap; - gap: 8px; -} - -.profile-modal-stat-value { - display: inline-flex; - align-items: center; - gap: 7px; - font-size: 12px; - color: var(--text-secondary); - background: var(--bg-tertiary); - padding: 6px 12px; - border-radius: var(--radius-md); -} - -.profile-modal-stat-icon { - flex-shrink: 0; - color: currentColor; -} - -.profile-modal-stat-value.is-on { - color: var(--success); -} - -.profile-modal-stat-value.is-off { - color: var(--text-muted); -} - -.profile-modal-section { - display: flex; - flex-direction: column; - gap: 12px; -} - -.profile-modal-memory-pane { - min-height: 100%; -} - -.profile-modal-memory-pane .memory-soul-tab, -.profile-modal-memory-pane .memory-soul-tab .soul-container { - min-height: 0; -} - -.profile-modal-label { - font-size: 12px; - font-weight: 600; - color: var(--text-secondary); -} - -.profile-modal-swatches { - display: grid; - grid-template-columns: repeat(11, 1fr); - gap: 10px; - max-width: 460px; -} - -.profile-modal-swatch { - width: 100%; - aspect-ratio: 1; - border-radius: 50%; - border: 2px solid transparent; - cursor: pointer; - padding: 0; -} - -.profile-modal-swatch.active { - border-color: var(--text-primary); -} - -.profile-modal-danger { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 10px; -} - -.profile-modal-danger-label { - color: var(--error); -} - -.profile-modal-danger-info { - margin: 0; - font-size: 12px; - line-height: 1.5; - color: var(--text-secondary); - max-width: 520px; -} - -.profile-modal-danger-confirm { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 10px; - font-size: 12.5px; - color: var(--text-secondary); -} - -.profile-modal-danger .btn-danger-ghost { - width: auto; - align-self: flex-start; -} - -.profile-modal-footer { - display: flex; - justify-content: flex-end; - padding: 14px 22px; - border-top: 1px solid var(--border); - flex-shrink: 0; -} - -.profile-modal-loading { - grid-column: 1 / -1; - display: flex; - align-items: center; - justify-content: center; - min-height: 200px; -} - -/* Placeholder pane for not-yet-built sections (e.g. Wallet). */ -.profile-modal-coming-soon { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 10px; - min-height: 280px; - color: var(--text-muted); - text-align: center; -} - -.profile-modal-coming-soon-title { - font-size: 16px; - font-weight: 600; - color: var(--text-secondary); -} - -.profile-modal-coming-soon-text { - font-size: 13px; -} - -/* ── Settings modal ───────────────────────────────────────────────────── - Global settings modal: grouped left nav + a single active pane on the - right. Built on the same AppModal shell as the profile modal. */ -.settings-modal-overlay { - padding: 24px; -} - -.settings-modal { - display: flex; - flex-direction: column; - width: 80vw; - height: 80vh; - max-width: 1000px; - max-height: 780px; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-lg); - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4); - overflow: hidden; -} - -.settings-modal-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 16px 22px; - border-bottom: 1px solid var(--border); - flex-shrink: 0; -} - -.settings-modal-title { - font-size: 16px; - font-weight: 600; - color: var(--text-primary); -} - -.settings-modal-close { - display: flex; - align-items: center; - justify-content: center; - border: none; - background: none; - color: var(--text-secondary); - cursor: pointer; - padding: 6px; - border-radius: var(--radius-sm); -} - -.settings-modal-close:hover { - color: var(--text-primary); - background: var(--bg-tertiary); -} - -.settings-modal-layout { - flex: 1; - min-height: 0; - display: flex; -} - -.settings-modal-nav { - flex-shrink: 0; - width: 210px; - display: flex; - flex-direction: column; - gap: 14px; - padding: 18px 12px; - border-right: 1px solid var(--border); - overflow-y: auto; -} - -.settings-modal-nav-group { - display: flex; - flex-direction: column; - gap: 2px; -} - -.settings-modal-nav-group-label { - padding: 4px 12px; - font-size: 11px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.04em; - color: var(--text-tertiary, var(--text-secondary)); -} - -.settings-modal-nav-item { - display: flex; - align-items: center; - gap: 10px; - width: 100%; - padding: 8px 12px; - border: none; - border-radius: var(--radius-md); - background: transparent; - color: var(--text-secondary); - font: inherit; - font-size: 13px; - font-weight: 500; - text-align: left; - cursor: pointer; - transition: - background var(--transition), - color var(--transition); -} - -.settings-modal-nav-item:hover { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.settings-modal-nav-item.active { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.settings-modal-content { - flex: 1; - min-width: 0; - min-height: 0; - overflow-y: auto; - padding: 26px 30px; -} - -.settings-modal-pane { - display: flex; - flex-direction: column; - gap: 22px; -} - -/* The active nav item already labels the section, so panes carry no in-pane - title. Transient save/status feedback surfaces as a small flash pill at the - top of the pane. */ -.settings-pane-flash { - align-self: flex-start; - padding: 4px 12px; - border-radius: 999px; - font-size: 12px; - font-weight: 600; - color: var(--accent, #4c8dff); - background: color-mix(in srgb, var(--accent, #4c8dff) 14%, transparent); - border: 1px solid color-mix(in srgb, var(--accent, #4c8dff) 32%, transparent); -} - -/* Inside the modal the section markup no longer needs the standalone-screen - section chrome (it lived in the old full-page Settings layout). */ -.settings-modal-pane .settings-field { - margin: 0; -} - -/* Cards — visually separate distinct concerns within a pane (e.g. the Hermes - Agent vs Hermes Desktop update channels in About). */ -.settings-card { - display: flex; - flex-direction: column; - border: 1px solid var(--border); - border-radius: var(--radius-lg); - background: var(--bg-primary); - overflow: hidden; -} - -.settings-card-head { - display: flex; - align-items: center; - gap: 12px; - padding: 14px 18px; - border-bottom: 1px solid var(--border); -} - -.settings-card-icon { - display: flex; - align-items: center; - justify-content: center; - width: 34px; - height: 34px; - flex-shrink: 0; - border-radius: var(--radius-md); - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.settings-card-headtext { - display: flex; - flex-direction: column; - gap: 1px; - min-width: 0; - flex: 1; -} - -.settings-card-title { - font-size: 14px; - font-weight: 650; - color: var(--text-primary); -} - -.settings-card-sub { - font-size: 12px; - color: var(--text-secondary); -} - -.settings-card-badge { - flex-shrink: 0; - padding: 3px 10px; - border-radius: 999px; - font-size: 11px; - font-weight: 600; - border: 1px solid transparent; -} - -.settings-card-badge.is-ok { - color: var(--text-secondary); - background: var(--bg-tertiary); -} - -.settings-card-badge.is-update { - color: var(--accent, #4c8dff); - background: color-mix(in srgb, var(--accent, #4c8dff) 14%, transparent); - border-color: color-mix(in srgb, var(--accent, #4c8dff) 35%, transparent); -} - -.settings-card-body { - display: flex; - flex-direction: column; - gap: 16px; - padding: 18px; -} - -/* Labelled metadata grid (version chips). */ -.settings-meta-grid { - display: flex; - flex-wrap: wrap; - gap: 22px 32px; -} - -.settings-meta { - display: flex; - flex-direction: column; - gap: 3px; -} - -.settings-meta-label { - display: inline-flex; - align-items: center; - gap: 5px; - font-size: 11px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.04em; - color: var(--text-tertiary, var(--text-secondary)); -} - -/* Brand logos used as small meta icons sit at the muted label tone. */ -.settings-meta-label .brand-logo { - opacity: 0.85; -} - -.settings-meta-value { - font-size: 14px; - font-weight: 600; - color: var(--text-primary); -} - -.settings-meta-path { - display: flex; - flex-direction: column; - gap: 4px; -} - -.settings-meta-pathvalue { - font-family: var(--font-mono, monospace); - font-size: 12px; - color: var(--text-secondary); - word-break: break-all; -} - -.settings-card-actions { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 8px; -} - -.settings-card-actions .btn { - display: inline-flex; - align-items: center; - gap: 6px; -} - -.settings-card-actions-note { - font-size: 12px; - color: var(--text-secondary); -} - -/* Toggle row — a setting with its switch on the trailing edge. */ -.settings-toggle-row { - display: flex; - align-items: center; - justify-content: space-between; - gap: 18px; - border-top: 1px solid var(--border); - padding-top: 16px; -} - -.settings-toggle-text { - min-width: 0; -} - -.settings-toggle-title { - display: flex; - align-items: center; - gap: 8px; - font-size: 13px; - font-weight: 600; - color: var(--text-primary); - margin-bottom: 3px; -} - -@keyframes settings-spin { - to { - transform: rotate(360deg); - } -} - -.settings-spin { - animation: settings-spin 0.8s linear infinite; -} - -/* Intro line at the top of a pane (replaces the removed pane title). */ -.settings-section-intro { - margin: 0; - font-size: 13px; - color: var(--text-secondary); -} - -/* Community link grid — tappable rows with icon, label, and an external arrow. */ -.settings-link-grid { - display: grid; - grid-template-columns: repeat(4, minmax(0, 1fr)); - gap: 10px; -} - -.settings-link { - display: flex; - align-items: center; - gap: 11px; - padding: 12px 14px; - border: 1px solid var(--border); - border-radius: var(--radius-md); - background: var(--bg-primary); - color: var(--text-primary); - font: inherit; - font-size: 13px; - font-weight: 600; - text-align: left; - cursor: pointer; - transition: - background var(--transition), - border-color var(--transition), - transform var(--transition); -} - -.settings-link:hover { - background: var(--bg-tertiary); - border-color: var(--border-bright); -} - -.settings-link.is-primary { - border-color: color-mix(in srgb, var(--accent, #4c8dff) 45%, transparent); - background: color-mix(in srgb, var(--accent, #4c8dff) 12%, transparent); -} - -.settings-link-icon { - display: inline-flex; - align-items: center; - justify-content: center; - width: 22px; - height: 22px; - flex-shrink: 0; -} - -.settings-link-label { - flex: 1; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.settings-link-arrow { - flex-shrink: 0; - color: var(--text-tertiary, var(--text-secondary)); -} - -/* Icon + label centered inside a connection-mode option button. */ -.settings-mode-option { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 7px; -} - -/* Subsection within a pane — a divider + icon'd label grouping related - fields (e.g. the Network block inside Connection). */ -.settings-subsection { - display: flex; - flex-direction: column; - gap: 16px; - padding-top: 18px; - border-top: 1px solid var(--border); -} - -.settings-subsection-head { - display: flex; - align-items: center; - gap: 8px; - font-size: 13px; - font-weight: 650; - color: var(--text-primary); -} - -/* Log file selector tabs (Logs & Diagnostics). */ -.settings-log-tabs { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-bottom: 8px; -} - -.settings-log-tabs .btn { - display: inline-flex; - align-items: center; - gap: 6px; -} - -.profile-wallet-pane { - gap: 18px; -} - -.profile-wallet-toolbar { - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; -} - -.profile-wallet-heading { - color: var(--text-primary); - font-size: 17px; - font-weight: 700; -} - -.profile-wallet-subtitle { - margin-top: 4px; - color: var(--text-muted); - font-size: 13px; -} - -.profile-wallet-empty { - min-height: 260px; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 14px; - color: var(--text-muted); - text-align: center; -} - -.profile-wallet-list { - display: grid; - gap: 12px; -} - -.profile-wallet-card { - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; - padding: 14px; - border: 1px solid var(--border); - border-radius: var(--radius-sm); - background: var(--bg-elevated); -} - -.profile-wallet-card-main { - display: flex; - align-items: center; - gap: 12px; - min-width: 0; -} - -.profile-wallet-icon { - width: 38px; - height: 38px; - display: grid; - place-items: center; - border-radius: var(--radius-sm); - background: var(--bg-tertiary); - color: var(--accent); - flex: 0 0 auto; -} - -.profile-wallet-meta { - min-width: 0; -} - -.profile-wallet-name-row { - display: flex; - align-items: center; - gap: 8px; - min-width: 0; -} - -.profile-wallet-name { - color: var(--text-primary); - font-weight: 700; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.profile-wallet-network { - padding: 3px 8px; - border-radius: var(--radius-sm); - background: var(--accent-subtle); - color: var(--accent); - font-size: 11px; - font-weight: 700; - flex: 0 0 auto; -} - -.profile-wallet-address { - display: block; - margin-top: 6px; - color: var(--text-muted); - font-family: var(--font-mono); - font-size: 12px; - background: transparent; -} - -.profile-wallet-balances { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 6px; - margin-top: 8px; -} - -.profile-wallet-balance { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 4px 12px; - border-radius: var(--radius-sm); - background: var(--bg-tertiary); - border: 1px solid var(--border); - font-family: var(--font-mono); - font-size: 12px; - color: var(--text-secondary); - cursor: default; -} - -.profile-wallet-balance-symbol { - font-weight: 700; - color: var(--text-primary); - font-family: var(--font-sans); - font-size: 12px; -} - -.profile-wallet-balance-icon { - width: 16px; - height: 16px; - border-radius: 50%; - object-fit: cover; - flex-shrink: 0; -} - -.profile-wallet-balance-loading { - color: var(--text-muted); - font-style: italic; -} - -.profile-wallet-balance-error { - color: var(--error); - font-size: 11px; -} - -.profile-wallet-refresh { - display: inline-flex; - align-items: center; - gap: 4px; - padding: 2px 8px; - border: 0; - border-radius: var(--radius-sm); - background: transparent; - color: var(--text-muted); - cursor: pointer; - font: inherit; - font-size: 11px; -} - -.profile-wallet-refresh:hover { - color: var(--text-secondary); - background: var(--bg-tertiary); -} - -.profile-wallet-refresh.spinning svg { - animation: spin 0.8s linear infinite; -} - -.profile-wallet-actions { - display: flex; - align-items: center; - gap: 8px; - flex: 0 0 auto; -} - -.profile-wallet-modal-overlay { - z-index: 300; -} - -.profile-wallet-modal { - z-index: 301; - height: fit-content; - width: min(560px, calc(100vw - 32px)); - max-height: min(720px, calc(100vh - 48px)); - display: flex; - flex-direction: column; - overflow: hidden; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-lg); - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4); -} - -.profile-wallet-modal-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 18px 20px; - border-bottom: 1px solid var(--border); -} - -.profile-wallet-modal-title { - margin: 0; - color: var(--text-primary); - font-size: 18px; - font-weight: 700; -} - -.profile-wallet-modal-body { - display: grid; - gap: 16px; - padding: 20px; - overflow-y: auto; -} - -.profile-wallet-mode { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 6px; - padding: 4px; - border-radius: var(--radius-sm); - background: var(--bg-primary); -} - -.profile-wallet-mode button { - border: 0; - border-radius: var(--radius-sm); - background: transparent; - color: var(--text-secondary); - cursor: pointer; - font: inherit; - font-size: 13px; - font-weight: 700; - padding: 9px 10px; -} - -.profile-wallet-mode button.active { - background: var(--bg-elevated); - color: var(--text-primary); - box-shadow: 0 0 0 1px var(--border); -} - -.profile-wallet-field { - display: grid; - gap: 8px; - color: var(--text-secondary); - font-size: 13px; - font-weight: 700; -} - -.profile-wallet-textarea { - min-height: 112px; - resize: vertical; - line-height: 1.5; -} - -.profile-wallet-modal-actions { - display: flex; - justify-content: flex-end; - gap: 10px; -} - -.profile-wallet-recovery { - display: grid; - gap: 14px; - color: var(--text-secondary); -} - -.profile-wallet-recovery > svg { - color: var(--accent); -} - -.profile-wallet-recovery p { - margin: 0; - color: var(--text-secondary); - line-height: 1.5; -} - -.profile-wallet-phrase { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 8px; - padding: 12px; - border: 1px solid var(--border); - border-radius: var(--radius-sm); - background: var(--bg-primary); -} - -.profile-wallet-phrase span { - display: flex; - align-items: center; - gap: 8px; - min-width: 0; - padding: 8px; - border-radius: var(--radius-sm); - background: var(--bg-elevated); - color: var(--text-primary); - font-family: var(--font-mono); - font-size: 12px; -} - -.profile-wallet-phrase strong { - color: var(--text-muted); - font-family: var(--font-sans); - font-size: 11px; - min-width: 16px; -} - -.profile-wallet-delete-modal-overlay { - z-index: 300; -} - -.profile-wallet-delete-modal { - z-index: 301; - height: fit-content; - width: min(420px, calc(100vw - 32px)); - display: flex; - flex-direction: column; - overflow: hidden; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-lg); - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4); -} - -.profile-wallet-delete-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 18px 20px; - border-bottom: 1px solid var(--border); -} - -.profile-wallet-delete-title { - margin: 0; - color: var(--error); - font-size: 18px; - font-weight: 700; -} - -.profile-wallet-delete-body { - display: grid; - gap: 16px; - padding: 20px; -} - -.profile-wallet-delete-wallet-info { - display: flex; - align-items: center; - gap: 10px; -} - -.profile-wallet-delete-wallet-name { - font-weight: 700; - color: var(--text-primary); - font-size: 14px; -} - -.profile-wallet-delete-wallet-address { - color: var(--text-muted); - font-family: var(--font-mono); - font-size: 12px; -} - -.profile-wallet-delete-warning { - padding: 14px 16px; - border: 1px solid var(--error); - border-radius: var(--radius-sm); - background: var(--error-bg); - color: var(--error); - font-size: 13px; - line-height: 1.5; -} - -.profile-wallet-delete-actions { - display: flex; - justify-content: flex-end; - gap: 10px; -} - -@media (max-width: 760px) { - .profile-wallet-toolbar, - .profile-wallet-card { - align-items: stretch; - flex-direction: column; - } - - .profile-wallet-actions { - width: 100%; - } - - .profile-wallet-actions .btn { - flex: 1; - } - - .profile-wallet-phrase { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .profile-wallet-delete-modal { - width: min(340px, calc(100vw - 24px)); - } -} -.btn-danger { - background: var(--error); - color: #fff; - border: 1px solid var(--error); -} -.btn-danger:hover { - filter: brightness(1.08); -} -.btn-danger-ghost { - background: var(--error-bg); - color: var(--error); - border: 1px solid transparent; -} -.btn-danger-ghost:hover { - border-color: var(--error); -} - -/* Profile cell — avatar plus name and a "provider · skills" subline. */ -.agents-cell-profile { - display: flex; - align-items: center; - gap: 12px; - min-width: 0; -} - -.agents-row-info { - min-width: 0; -} - -.agents-row-name { - font-size: 15px; - font-weight: 600; - color: var(--text-primary); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.agents-row-sub { - font-size: 12px; - color: var(--text-muted); -} - -.agents-cell-model { - min-width: 0; -} - -/* Model shown as a monospace chip; empty state stays plain muted text. */ -.agents-model-chip { - display: inline-block; - max-width: 100%; - padding: 4px 10px; - border-radius: var(--radius-sm); - background: var(--bg-elevated); - color: var(--text-secondary); - font-family: var(--font-mono); - font-size: 12.5px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - vertical-align: middle; -} - -.agents-model-empty { - font-size: 13px; - color: var(--text-muted); -} - -.agents-cell-status { - display: flex; - align-items: center; -} - -/* Gateway status as a rounded pill: green when running, muted when off. */ -.agents-status-pill { - display: inline-flex; - align-items: center; - gap: 7px; - padding: 4px 11px; - border-radius: 999px; - font-size: 12.5px; - font-weight: 600; -} - -.agents-status-pill.on { - background: var(--success-bg); - color: var(--success); -} - -.agents-status-pill.off { - background: var(--bg-elevated); - color: var(--text-muted); -} - -/* While the gateway spins up after a switch: a small spinner + "Starting…". */ -.agents-status-pill.starting { - background: var(--success-bg); - color: var(--success); -} - -.agents-status-spinner { - width: 10px; - height: 10px; - border: 1.5px solid color-mix(in srgb, var(--success) 35%, transparent); - border-top-color: var(--success); - border-radius: 50%; - flex-shrink: 0; - animation: spin 0.7s linear infinite; -} - -.agents-status-dot { - width: 7px; - height: 7px; - border-radius: 50%; - flex-shrink: 0; - background: currentColor; -} - -.agents-cell-actions { - display: flex; - align-items: center; - gap: 8px; -} - -/* ── New-profile modal ── */ -.agents-create-modal { - z-index: 301; - height: fit-content; - width: min(460px, calc(100vw - 32px)); - display: flex; - flex-direction: column; - overflow: hidden; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-lg); - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4); -} - -.agents-create-modal-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 18px 20px; - border-bottom: 1px solid var(--border); -} - -.agents-create-modal-title { - margin: 0; - color: var(--text-primary); - font-size: 18px; - font-weight: 700; -} - -.agents-create-modal-body { - display: grid; - gap: 16px; - padding: 20px; -} - -.agents-create-field { - display: grid; - gap: 8px; - color: var(--text-secondary); - font-size: 13px; - font-weight: 600; -} - -.agents-create-modal-actions { - display: flex; - justify-content: flex-end; - gap: 10px; - margin-top: 4px; -} - -/* ======================================================================== - SESSIONS - ======================================================================== */ -/* ── Sessions ── */ -.sessions-container { - display: flex; - flex-direction: column; - height: 100%; - overflow: hidden; -} - -.sessions-header { - padding: 20px 24px 12px; - flex-shrink: 0; - display: flex; - flex-direction: column; - gap: 12px; -} - -.sessions-header-top { - display: flex; - align-items: center; - justify-content: space-between; -} - -.sessions-title { - font-size: 18px; - font-weight: 700; - color: var(--text-primary); -} - -.sessions-header-actions { - display: flex; - align-items: center; - gap: 8px; -} - -.sessions-select-mode { - min-width: 78px; -} - -.sessions-selection-toolbar { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 10px; - border: 1px solid var(--border); - border-radius: var(--radius-md); - background: var(--bg-secondary); -} - -.sessions-selection-count { - flex: 1; - min-width: 0; - color: var(--text-secondary); - font-size: 12px; - font-weight: 600; -} - -/* Search bar — integrated into header */ -.sessions-searchbar { - display: flex; - align-items: center; - gap: 8px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 0 12px; - transition: - border-color var(--transition), - box-shadow var(--transition); -} - -.sessions-searchbar:focus-within { - border-color: var(--border-focus); - box-shadow: 0 0 0 2px var(--accent-subtle); -} - -.sessions-searchbar-icon { - color: var(--text-muted); - flex-shrink: 0; -} - -.sessions-searchbar-input { - flex: 1; - background: none; - border: none; - padding: 14px 0; - font-size: 13px; - font-family: var(--font-sans); - color: var(--text-primary); - outline: none; -} - -.sessions-searchbar-input::placeholder { - color: var(--text-muted); -} - -.sessions-searchbar-clear { - padding: 2px; - color: var(--text-muted); -} - -/* Loading & empty states */ -.sessions-loading { - flex: 1; - display: flex; - align-items: center; - justify-content: center; -} - -.sessions-empty { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 6px; -} - -.sessions-empty-icon { - color: var(--text-muted); - opacity: 0.4; - margin-bottom: 4px; -} - -.sessions-empty-text { - font-size: 15px; - font-weight: 600; - color: var(--text-secondary); -} - -.sessions-empty-hint { - font-size: 13px; - color: var(--text-muted); -} - -/* Sessions list */ -.sessions-list { - flex: 1; - display: flex; - flex-direction: column; - gap: 8px; - overflow-y: auto; - overflow-x: hidden; - padding: 4px 16px 16px; -} - -/* Date group headings */ -.sessions-group { - display: flex; - flex-direction: column; - gap: 8px; - margin-bottom: 16px; -} - -.sessions-group-label { - font-size: 11px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--text-muted); - padding: 12px 8px 6px; -} - -/* Session card */ -.sessions-card { - display: flex; - flex-direction: column; - gap: 6px; - width: 100%; - box-sizing: border-box; - padding: 10px 12px; - border: 1px solid var(--border); - background: var(--bg-secondary); - border-radius: var(--radius-md); - cursor: pointer; - transition: - background var(--transition), - border-color var(--transition); - text-align: left; - font-family: var(--font-sans); -} - -.sessions-card:hover { - background: var(--bg-tertiary); - border-color: var(--border-bright); -} - -.sessions-card--active { - background: var(--accent-subtle); - border-color: var(--border-focus); -} - -.sessions-card--selected { - border-color: var(--border-focus); - box-shadow: inset 3px 0 0 var(--accent); -} - -.sessions-card-main { - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; -} - -.sessions-card-select { - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - width: 18px; - height: 18px; - cursor: pointer; -} - -.sessions-card-select input { - width: 15px; - height: 15px; - margin: 0; - accent-color: var(--accent); - cursor: pointer; -} - -.sessions-card-title { - font-size: 14px; - font-weight: 500; - color: var(--text-primary); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - flex: 1; - min-width: 0; - line-height: 1.4; -} - -.sessions-card-time { - font-size: 11px; - color: var(--text-muted); - flex-shrink: 0; - font-variant-numeric: tabular-nums; -} - -/* Tags row */ -.sessions-card-tags { - display: flex; - align-items: center; - gap: 6px; - flex-wrap: wrap; -} - -/* Delete (trash) button on each session card — #408. - * Slides into the right side of the tags row so it doesn't fight the - * card's main click target. Stays subtle until hover so the row doesn't - * look cluttered when the user is just browsing. */ -.sessions-card-delete { - margin-left: auto; - display: inline-flex; - align-items: center; - justify-content: center; - padding: 4px; - border: none; - background: transparent; - color: var(--text-muted); - border-radius: var(--radius-sm); - cursor: pointer; - opacity: 0.45; - transition: - opacity var(--transition), - background var(--transition), - color var(--transition); -} - -.sessions-card:hover .sessions-card-delete { - opacity: 1; -} - -.sessions-card-delete:hover, -.sessions-card-delete:focus-visible { - background: var(--bg-tertiary); - color: var(--danger, #e06c75); - opacity: 1; -} - -/* Rename button — sits next to delete in the tags row */ -.sessions-card-rename { - display: inline-flex; - align-items: center; - justify-content: center; - padding: 4px; - border: none; - background: transparent; - color: var(--text-muted); - border-radius: var(--radius-sm); - cursor: pointer; - opacity: 0.45; - transition: - opacity var(--transition), - background var(--transition), - color var(--transition); -} - -.sessions-card:hover .sessions-card-rename { - opacity: 1; -} - -.sessions-card-rename:hover, -.sessions-card-rename:focus-visible { - background: var(--bg-tertiary); - color: var(--text-primary); - opacity: 1; -} - -/* Inline rename input inside the card */ -.sessions-card-rename-input { - flex: 1; - min-width: 0; - font-size: 14px; - font-weight: 500; - color: var(--text-primary); - background: var(--bg-base); - border: 1px solid var(--border-focus); - border-radius: var(--radius-sm); - padding: 3px 8px; - outline: none; - font-family: var(--font-sans); -} - -.sessions-confirm-overlay { - position: fixed; - inset: 0; - z-index: 120; - display: flex; - align-items: center; - justify-content: center; - padding: 24px; - background: rgba(0, 0, 0, 0.58); - animation: fadeIn 0.15s ease; -} - -.sessions-confirm-modal { - width: min(440px, 100%); - border: 1px solid var(--border); - border-radius: var(--radius-lg); - background: var(--bg-primary); - box-shadow: var(--shadow-lg); - animation: slideUp 0.2s ease; -} - -.sessions-confirm-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 16px 18px; - border-bottom: 1px solid var(--border); -} - -.sessions-confirm-header h3 { - font-size: 15px; - font-weight: 700; - color: var(--text-primary); -} - -.sessions-confirm-close { - padding: 6px; -} - -.sessions-confirm-body { - padding: 18px; -} - -.sessions-confirm-body p { - color: var(--text-secondary); - font-size: 14px; - line-height: 1.55; -} - -.sessions-confirm-footer { - display: flex; - justify-content: flex-end; - gap: 8px; - padding: 14px 18px 16px; - border-top: 1px solid var(--border); -} - -.sessions-tag { - font-size: 11px; - color: var(--text-muted); - background: var(--bg-secondary); - padding: 1px 7px; - border-radius: 99px; - border: 1px solid var(--border); - white-space: nowrap; - line-height: 1.6; -} - -.sessions-tag--source { - color: var(--text-secondary); - font-weight: 500; -} - -.sessions-tag--model { - font-family: var(--font-mono, monospace); - font-size: 10.5px; - letter-spacing: -0.01em; -} - -/* Search results snippet */ -.sessions-result-snippet { - font-size: 12px; - color: var(--text-secondary); - line-height: 1.5; - overflow: hidden; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; -} - -.sessions-result-snippet mark { - background: rgba(245, 158, 11, 0.3); - color: var(--text-primary); - padding: 0 2px; - border-radius: 2px; -} - -.sessions-card-title mark { - background: rgba(245, 158, 11, 0.3); - color: var(--text-primary); - padding: 0 2px; - border-radius: 2px; -} - -/* ======================================================================== - SKILLS - ======================================================================== */ -.skills-container { - display: flex; - flex-direction: column; - height: 100%; - overflow-y: auto; - padding: 24px 32px; -} - -.skills-loading { - flex: 1; - display: flex; - align-items: center; - justify-content: center; -} - -.skills-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - margin-bottom: 16px; -} - -/* Embedded (Capabilities → Skills): search + refresh share one row. */ -.skills-search-row { - display: flex; - align-items: center; - gap: 10px; - margin-bottom: 12px; -} - -.skills-search-row .skills-search { - flex: 1; - margin-bottom: 0; -} - -.skills-search-refresh { - flex-shrink: 0; -} - -.skills-title { - font-size: 20px; - font-weight: 700; - color: var(--text-primary); -} - -.skills-subtitle { - font-size: 13px; - color: var(--text-muted); - margin-top: 2px; -} - -.skills-error { - display: flex; - align-items: center; - justify-content: space-between; - background: var(--error-bg); - border: 1px solid var(--error); - border-radius: var(--radius-sm); - padding: 8px 12px; - margin-bottom: 12px; - color: var(--error); - font-size: 13px; -} - -/* Tabs */ -.skills-tabs { - display: flex; - gap: 2px; - background: var(--bg-tertiary); - border-radius: var(--radius-sm); - padding: 2px; - margin-bottom: 12px; -} - -.skills-tab { - flex: 1; - padding: 8px 16px; - border: none; - background: transparent; - border-radius: 4px; - cursor: pointer; - font-family: var(--font-sans); - font-size: 13px; - font-weight: 600; - color: var(--text-secondary); - transition: all var(--transition); -} - -.skills-tab:hover { - color: var(--text-primary); -} - -.skills-tab.active { - background: var(--bg-elevated); - color: var(--text-primary); -} - -/* Search */ -.skills-search { - display: flex; - align-items: center; - gap: 8px; - margin-bottom: 12px; - color: var(--text-muted); -} - -.skills-search-input { - flex: 1; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-sm); - padding: 11px 12px; - font-size: 13px; - font-family: var(--font-sans); - color: var(--text-primary); - outline: none; - transition: border-color var(--transition); -} - -.skills-search-input:focus { - border-color: var(--border-focus); -} - -.skills-search-input::placeholder { - color: var(--text-muted); -} - -.skills-search-clear { - padding: 4px; -} - -/* Category pills */ -.skills-category-pills { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin-bottom: 16px; -} - -.skills-pill { - padding: 4px 12px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 20px; - cursor: pointer; - font-family: var(--font-sans); - font-size: 12px; - font-weight: 500; - color: var(--text-secondary); - transition: all var(--transition); - white-space: nowrap; -} - -.skills-pill:hover { - border-color: var(--border-bright); -} - -.skills-pill.active { - border-color: var(--accent); - color: var(--accent-text); - background: var(--accent-subtle); -} - -/* Grid */ -.skills-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); - gap: 10px; - padding-bottom: 20px; -} - -.skills-card { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 14px; - cursor: pointer; - transition: all var(--transition); - text-align: left; - font-family: var(--font-sans); - display: flex; - flex-direction: column; - gap: 6px; -} - -.skills-card:hover { - border-color: var(--border-bright); - background: var(--bg-tertiary); -} - -.skills-card-category { - font-size: 11px; - font-weight: 600; - color: var(--accent-text); - text-transform: uppercase; - letter-spacing: 0.5px; -} - -.skills-card-name { - font-size: 14px; - font-weight: 600; - color: var(--text-primary); -} - -.skills-card-description { - font-size: 12px; - color: var(--text-secondary); - line-height: 1.5; - overflow: hidden; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; -} - -.skills-card-footer { - margin-top: 4px; - display: flex; - justify-content: flex-end; -} - -.skills-card-installed-badge { - font-size: 11px; - font-weight: 600; - color: var(--success); - background: var(--success-bg); - padding: 2px 8px; - border-radius: 10px; -} - -.skills-card-install-btn { - padding: 4px 12px; - font-size: 12px; -} - -/* Empty */ -.skills-empty { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 4px; - padding: 40px 0; -} - -.skills-empty-text { - font-size: 15px; - font-weight: 600; - color: var(--text-secondary); -} - -.skills-empty-hint { - font-size: 13px; - color: var(--text-muted); -} - -/* Detail overlay */ -.skills-detail-overlay { - position: fixed; - inset: 0; - background: rgba(0, 0, 0, 0.5); - display: flex; - align-items: center; - justify-content: center; - z-index: 100; - animation: fadeIn 0.15s ease; -} - -@keyframes fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -.skills-detail { - background: var(--bg-primary); - border: 1px solid var(--border); - border-radius: var(--radius-lg); - width: 90%; - max-width: 640px; - max-height: 80vh; - display: flex; - flex-direction: column; - animation: slideUp 0.2s ease; -} - -@keyframes slideUp { - from { - transform: translateY(12px); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} - -.skills-detail-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - padding: 20px; - border-bottom: 1px solid var(--border); - flex-shrink: 0; -} - -.skills-detail-name { - font-size: 18px; - font-weight: 700; - color: var(--text-primary); -} - -.skills-detail-category { - font-size: 12px; - color: var(--accent-text); - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.5px; - margin-top: 2px; -} - -.skills-detail-actions { - display: flex; - align-items: center; - gap: 8px; -} - -.skills-detail-content { - flex: 1; - overflow-y: auto; - padding: 20px; - font-size: 14px; - line-height: 1.7; - color: var(--text-primary); -} - -.skills-detail-content code { - background: var(--code-bg); - padding: 2px 6px; - border-radius: 4px; - font-family: var(--font-mono); - font-size: 13px; -} - -.skills-detail-content pre { - background: var(--code-bg); - padding: 12px; - border-radius: var(--radius-sm); - margin: 8px 0; - overflow-x: auto; - font-family: var(--font-mono); - font-size: 13px; - line-height: 1.5; -} - -.skills-detail-content pre code { - background: none; - padding: 0; -} - -.skills-detail-content p { - margin: 0 0 8px 0; -} - -.skills-detail-content h1, -.skills-detail-content h2, -.skills-detail-content h3 { - margin: 16px 0 4px 0; - font-weight: 600; -} - -.skills-detail-content ul, -.skills-detail-content ol { - margin: 4px 0 8px 18px; - padding: 0; - list-style: revert; -} - -/* ======================================================================== - DISCOVER (COMMUNITY MARKETPLACE) - ======================================================================== */ -.discover-container { - display: flex; - flex-direction: column; - height: 100%; - overflow: hidden; - padding: 24px 28px; - gap: 16px; -} - -.discover-header { - display: flex; - align-items: center; - justify-content: space-between; - flex-shrink: 0; -} - -.discover-title { - font-size: 22px; - font-weight: 700; - color: var(--text-primary); - margin: 0; -} - -.discover-subtitle { - font-size: 13px; - color: var(--text-muted); - margin: 4px 0 0; -} - -.discover-tabs { - display: flex; - gap: 4px; - flex-shrink: 0; - border-bottom: 1px solid var(--border); -} - -.discover-tab { - display: flex; - align-items: center; - gap: 7px; - padding: 9px 14px; - background: none; - border: none; - border-bottom: 2px solid transparent; - margin-bottom: -1px; - color: var(--text-muted); - font-size: 13px; - font-weight: 600; - font-family: var(--font-sans); - cursor: pointer; - transition: all var(--transition); -} - -.discover-tab:hover { - color: var(--text-secondary); -} - -.discover-tab.active { - color: var(--accent-text, var(--accent)); - border-bottom-color: var(--accent); -} - -.discover-tab-count { - font-size: 11px; - font-weight: 600; - color: var(--text-muted); - background: var(--bg-tertiary); - border-radius: 10px; - padding: 1px 7px; -} - -.discover-toolbar { - display: flex; - align-items: center; - gap: 10px; - flex-shrink: 0; -} - -.discover-segment { - display: flex; - flex-shrink: 0; - background: var(--bg-tertiary); - border-radius: var(--radius-md); - padding: 3px; - gap: 2px; -} - -.discover-segment-btn { - padding: 6px 14px; - background: none; - border: none; - border-radius: calc(var(--radius-md) - 3px); - color: var(--text-muted); - font-size: 12.5px; - font-weight: 600; - font-family: var(--font-sans); - cursor: pointer; - transition: all var(--transition); -} - -.discover-segment-btn:hover { - color: var(--text-secondary); -} - -.discover-segment-btn.active { - background: var(--bg-secondary); - color: var(--text-primary); -} - -.discover-search { - flex: 1; - display: flex; - align-items: center; - gap: 8px; - padding: 0 12px; - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-md); - color: var(--text-muted); -} - -.discover-search:focus-within { - border-color: var(--border-focus); -} - -.discover-search-input { - flex: 1; - background: none; - border: none; - outline: none; - color: var(--text-primary); - font-size: 13px; - font-family: var(--font-sans); - padding: 9px 0; -} - -.discover-state { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 10px; - color: var(--text-muted); - text-align: center; -} - -.discover-empty-title { - font-size: 15px; - font-weight: 600; - color: var(--text-secondary); - margin: 0; -} - -.discover-empty-text { - font-size: 13px; - color: var(--text-muted); - margin: 0; - max-width: 360px; -} - -.discover-grid { - flex: 1; - overflow-y: auto; - display: grid; - grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); - gap: 14px; - align-content: start; - padding-bottom: 8px; -} - -.discover-card { - display: flex; - flex-direction: column; - gap: 8px; - padding: 16px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-lg); - transition: border-color var(--transition); - box-sizing: border-box; - min-width: 0; -} - -.discover-card:hover { - border-color: var(--border-bright); -} - -/* Clickable card (installed skills open a detail modal). */ -.discover-card--clickable { - width: 100%; - text-align: left; - font-family: var(--font-sans); - cursor: pointer; -} - -.discover-card--clickable:hover { - border-color: var(--border-bright); - background: var(--bg-tertiary); - transform: translateY(-1px); -} - -.discover-card-head { - display: flex; - align-items: center; - gap: 8px; -} - -.discover-card-icon { - flex-shrink: 0; - color: var(--accent-text, var(--accent)); -} - -/* Rounded tile holding the card's lead icon — gives installed cards weight. */ -.discover-card-iconwrap { - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - width: 30px; - height: 30px; - border-radius: var(--radius-md); - background: var(--accent-subtle); - color: var(--accent-text, var(--accent)); -} - -.discover-card-name { - flex: 1; - font-size: 14px; - font-weight: 600; - color: var(--text-primary); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -/* Category pill, shown on the card head and in the detail modal. */ -.discover-card-badge { - flex-shrink: 0; - font-size: 10.5px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.4px; - color: var(--accent-text, var(--accent)); - background: var(--accent-subtle); - border-radius: 5px; - padding: 2px 8px; -} - -.discover-card-meta { - font-size: 11px; - color: var(--text-muted); -} - -.discover-card-desc { - flex: 1; - font-size: 12.5px; - line-height: 1.5; - color: var(--text-secondary); - margin: 0; - display: -webkit-box; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical; - overflow: hidden; -} - -.discover-card-tags { - display: flex; - flex-wrap: wrap; - gap: 5px; -} - -.discover-tag { - font-size: 10.5px; - color: var(--text-muted); - background: var(--bg-tertiary); - border-radius: 4px; - padding: 2px 7px; -} - -.discover-card-error { - font-size: 11.5px; - color: var(--error); - background: var(--error-subtle, rgba(239, 68, 68, 0.1)); - border-radius: 6px; - padding: 6px 8px; -} - -.discover-card-footer { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - margin-top: 2px; -} - -.discover-card-link { - display: inline-flex; - align-items: center; - gap: 5px; - font-size: 12px; - color: var(--text-muted); - text-decoration: none; - transition: color var(--transition); -} - -.discover-card-link:hover { - color: var(--text-secondary); -} - -.discover-install-btn { - margin-left: auto; -} - -.discover-uninstall-btn { - margin-left: auto; -} - -.discover-uninstall-btn:hover:not(:disabled) { - color: var(--error); - border-color: var(--error); -} - -.discover-card-installed { - display: inline-flex; - align-items: center; - gap: 5px; - margin-left: auto; - font-size: 12px; - font-weight: 600; - color: var(--success, #22c55e); -} - -/* Skill detail modal (markdown preview + remove). */ -.discover-modal-overlay { - position: fixed; - inset: 0; - background: rgba(0, 0, 0, 0.5); - display: flex; - align-items: center; - justify-content: center; - z-index: 100; - animation: fadeIn 0.15s ease; -} - -.discover-modal { - background: var(--bg-primary); - border: 1px solid var(--border); - border-radius: var(--radius-lg); - width: 90%; - max-width: 640px; - max-height: 80vh; - display: flex; - flex-direction: column; - animation: slideUp 0.2s ease; -} - -.discover-modal-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 16px 20px; - border-bottom: 1px solid var(--border); - flex-shrink: 0; -} - -.discover-modal-titles { - display: flex; - align-items: center; - gap: 10px; - min-width: 0; -} - -.discover-modal-name { - display: flex; - align-items: center; - gap: 8px; - font-size: 17px; - font-weight: 700; - color: var(--text-primary); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.discover-modal-actions { - display: flex; - align-items: center; - gap: 8px; - flex-shrink: 0; -} - -.discover-modal-close { - display: flex; - align-items: center; - justify-content: center; - padding: 6px; - border-radius: var(--radius-sm); - color: var(--text-muted); -} - -.discover-modal-close:hover { - color: var(--text-primary); - background: var(--bg-hover); -} - -.discover-modal-error { - margin: 12px 20px 0; - font-size: 12px; - color: var(--error); - background: var(--error-subtle, rgba(239, 68, 68, 0.1)); - border-radius: 6px; - padding: 8px 10px; -} - -.discover-modal-content { - flex: 1; - overflow-y: auto; - padding: 20px; - font-size: 14px; - line-height: 1.7; - color: var(--text-primary); -} - -/* Structured spec view (manifest-only entries: mcp / agent / workflow). */ -.discover-spec { - display: flex; - flex-direction: column; -} - -.discover-spec-lead { - margin: 0 0 16px; - font-size: 14px; - line-height: 1.6; - color: var(--text-secondary); -} - -.discover-spec-row { - display: grid; - grid-template-columns: 120px 1fr; - gap: 12px; - align-items: baseline; - padding: 10px 0; - border-top: 1px solid var(--border); -} - -.discover-spec-label { - font-size: 11px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.5px; - color: var(--text-muted); -} - -.discover-spec-value { - font-size: 13px; - color: var(--text-primary); - word-break: break-word; -} - -.discover-spec-mono { - font-family: var(--font-mono); - font-size: 12.5px; - color: var(--text-primary); - background: var(--code-bg); - padding: 3px 8px; - border-radius: 6px; - word-break: break-all; - justify-self: start; -} - -.discover-spec-chips { - display: flex; - flex-wrap: wrap; - gap: 6px; -} - -/* Prose doc (README/AGENT.md) shown below the spec rows. */ -.discover-modal-doc { - margin-top: 18px; - padding-top: 16px; - border-top: 1px solid var(--border); -} - -.discover-spec + .discover-modal-doc { - margin-top: 18px; -} - -.discover-modal-content code { - background: var(--code-bg); - padding: 2px 6px; - border-radius: 4px; - font-family: var(--font-mono); - font-size: 13px; -} - -.discover-modal-content pre code { - background: none; - padding: 0; -} - -.discover-modal-content p { - margin: 0 0 8px 0; -} - -.discover-modal-content h1, -.discover-modal-content h2, -.discover-modal-content h3 { - margin: 16px 0 4px 0; - font-weight: 600; -} - -.discover-modal-content ul, -.discover-modal-content ol { - margin: 4px 0 8px 18px; - padding: 0; - list-style: revert; -} - -/* ======================================================================== - SCHEDULES (CRON JOBS) - ======================================================================== */ -.schedules-container { - display: flex; - flex-direction: column; - height: 100%; - overflow-y: auto; - padding: 24px 32px; -} - -.schedules-loading { - flex: 1; - display: flex; - align-items: center; - justify-content: center; -} - -.schedules-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - margin-bottom: 20px; -} - -.schedules-title { - font-size: 20px; - font-weight: 700; - color: var(--text-primary); -} - -.schedules-subtitle { - font-size: 13px; - color: var(--text-muted); - margin-top: 2px; -} - -.schedules-header-actions { - display: flex; - gap: 8px; -} - -/* Job list */ -.schedules-list { - display: flex; - flex-direction: column; - gap: 10px; - padding-bottom: 20px; -} - -.schedules-card { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 14px 16px; - transition: border-color var(--transition); -} - -.schedules-card:hover { - border-color: var(--border-bright); -} - -.schedules-card-top { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; -} - -.schedules-card-info { - flex: 1; - min-width: 0; -} - -.schedules-card-name { - font-size: 14px; - font-weight: 600; - color: var(--text-primary); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.schedules-card-schedule { - font-size: 12px; - color: var(--accent-text); - font-weight: 500; - margin-top: 2px; -} - -.schedules-card-actions { - display: flex; - align-items: center; - gap: 4px; - flex-shrink: 0; -} - -.schedules-action-btn { - position: relative; - padding: 4px; - border-radius: var(--radius-sm); - color: var(--text-secondary); - transition: all var(--transition); -} - -.schedules-action-btn:hover { - color: var(--text-primary); - background: var(--bg-tertiary); -} - -.schedules-action-btn[data-tooltip]::after { - content: attr(data-tooltip); - position: absolute; - bottom: calc(100% + 6px); - left: 50%; - transform: translateX(-50%); - padding: 4px 8px; - background: var(--bg-elevated); - color: var(--text-primary); - border: 1px solid var(--border); - border-radius: var(--radius-sm); - font-size: 11px; - font-weight: 500; - white-space: nowrap; - pointer-events: none; - opacity: 0; - transition: opacity 0.15s ease; -} - -.schedules-action-btn[data-tooltip]:hover::after { - opacity: 1; -} - -.schedules-action-danger:hover { - color: var(--error); -} - -.schedules-badge { - font-size: 11px; - font-weight: 600; - padding: 2px 8px; - border-radius: 10px; - white-space: nowrap; -} - -.schedules-badge-active { - color: var(--success); - background: var(--success-bg); -} - -.schedules-badge-paused { - color: var(--warning); - background: var(--warning-bg); -} - -.schedules-badge-completed { - color: var(--text-muted); - background: var(--bg-tertiary); -} - -.schedules-card-prompt { - font-size: 12px; - color: var(--text-secondary); - line-height: 1.5; - margin-top: 8px; - overflow: hidden; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; -} - -.schedules-card-meta { - display: flex; - flex-wrap: wrap; - gap: 12px; - margin-top: 10px; - font-size: 11px; - color: var(--text-muted); -} - -.schedules-card-error-icon { - color: var(--error); - margin-left: 4px; - vertical-align: middle; - display: inline-flex; -} - -.schedules-card-error { - font-size: 12px; - color: var(--error); - margin-top: 8px; - padding: 6px 10px; - background: var(--error-bg); - border-radius: var(--radius-sm); -} - -/* Empty state */ -.schedules-empty { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 4px; - padding: 40px 0; -} - -.schedules-empty-text { - font-size: 15px; - font-weight: 600; - color: var(--text-secondary); -} - -.schedules-empty-hint { - font-size: 13px; - color: var(--text-muted); -} - -/* Modal */ -.schedules-modal { - background: var(--bg-primary); - border: 1px solid var(--border); - border-radius: var(--radius-lg); - width: 90%; - max-width: 480px; - max-height: 85vh; - display: flex; - flex-direction: column; - animation: slideUp 0.2s ease; -} - -.schedules-modal-sm { - max-width: 360px; -} - -.schedules-modal-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 16px 20px; - border-bottom: 1px solid var(--border); -} - -.schedules-modal-header h3 { - font-size: 15px; - font-weight: 700; - color: var(--text-primary); -} - -.schedules-modal-body { - padding: 16px 20px; - display: flex; - flex-direction: column; - gap: 14px; - overflow-y: auto; -} - -.schedules-modal-footer { - display: flex; - justify-content: flex-end; - gap: 8px; - padding: 12px 20px; - border-top: 1px solid var(--border); -} - -.schedules-field { - display: flex; - flex-direction: column; - gap: 4px; -} - -.schedules-field-label { - font-size: 12px; - font-weight: 600; - color: var(--text-secondary); -} - -.schedules-required { - color: var(--error); -} - -.schedules-field-hint { - font-size: 11px; - color: var(--text-muted); - margin-top: 2px; -} - -.schedules-textarea { - resize: vertical; - min-height: 60px; - font-family: var(--font-sans); -} - -.kanban-folder-picker { - display: flex; - gap: 8px; - margin-top: 6px; -} - -.kanban-folder-picker .input { - flex: 1; - min-width: 0; -} - -.kanban-checkbox-label { - display: flex; - align-items: flex-start; - gap: 8px; - font-weight: 500; - color: var(--text-primary); - cursor: pointer; -} - -.kanban-checkbox-label input[type="checkbox"] { - margin-top: 2px; -} - -/* Priority selector — JIRA-style chips with a colored severity bullet. - Wraps so it stays readable in the narrow create-task modal. */ -.kanban-prio-chips { - display: flex; - flex-wrap: wrap; - gap: 8px; -} - -.kanban-prio-chip { - display: inline-flex; - align-items: center; - gap: 7px; - padding: 7px 12px; - border-radius: 999px; - background: var(--bg-tertiary); - border: 1px solid var(--border); - color: var(--text-secondary); - font-size: 12px; - font-weight: 500; - cursor: pointer; - transition: - border-color var(--transition), - background var(--transition), - color var(--transition); -} - -.kanban-prio-chip:hover { - border-color: var(--border-bright); - color: var(--text-primary); -} - -.kanban-prio-chip-active { - background: var(--accent-subtle); - border-color: var(--accent); - color: var(--accent-text); -} - -.kanban-prio-bullet { - width: 9px; - height: 9px; - border-radius: 999px; - flex-shrink: 0; - background: var(--text-muted); -} -.kanban-prio-bullet[data-prio="p0"] { - background: var(--error); -} -.kanban-prio-bullet[data-prio="p1"] { - background: var(--warning); -} -.kanban-prio-bullet[data-prio="p2"] { - background: var(--accent); -} - -.schedules-freq-pills { - display: flex; - gap: 2px; - background: var(--bg-tertiary); - border-radius: var(--radius-sm); - padding: 2px; -} - -.schedules-freq-pill { - flex: 1; - padding: 6px 8px; - border: none; - background: transparent; - border-radius: 4px; - cursor: pointer; - font-family: var(--font-sans); - font-size: 12px; - font-weight: 600; - color: var(--text-secondary); - transition: all var(--transition); - white-space: nowrap; -} - -.schedules-freq-pill:hover { - color: var(--text-primary); -} - -.schedules-freq-pill.active { - background: var(--bg-elevated); - color: var(--text-primary); -} - -.schedules-confirm-text { - font-size: 13px; - color: var(--text-secondary); - line-height: 1.5; -} - -/* ======================================================================== - SOUL / PERSONA EDITOR - ======================================================================== */ -.soul-container { - display: flex; - flex-direction: column; - height: 100%; - padding: 24px 32px; - overflow: hidden; -} - -.soul-loading { - flex: 1; - display: flex; - align-items: center; - justify-content: center; -} - -.soul-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - margin-bottom: 16px; - flex-shrink: 0; -} - -.soul-title { - font-size: 20px; - font-weight: 700; - color: var(--text-primary); - display: flex; - align-items: center; - gap: 10px; -} - -.soul-saved { - color: var(--success); - font-size: 12px; - font-weight: 600; - animation: fadeInOut 2s ease forwards; -} - -.soul-subtitle { - font-size: 13px; - color: var(--text-muted); - margin-top: 2px; -} - -.soul-reset-confirm { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 14px 16px; - margin-bottom: 12px; - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - font-size: 13px; - color: var(--text-secondary); - flex-shrink: 0; -} - -.soul-reset-actions { - display: flex; - gap: 8px; - flex-shrink: 0; -} - -.soul-editor { - flex: 1; - width: 100%; - min-height: 380px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 16px; - font-family: var(--font-mono); - font-size: 13px; - line-height: 1.7; - color: var(--text-primary); - resize: vertical; - outline: none; - transition: border-color var(--transition); - overflow-y: auto; -} - -.soul-editor:focus { - border-color: var(--border-focus); -} - -.soul-editor::placeholder { - color: var(--text-muted); -} - -.soul-hint { - font-size: 12px; - color: var(--text-muted); - margin-top: 8px; - flex-shrink: 0; -} - -/* ======================================================================== - MEMORY - ======================================================================== */ -.memory-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - margin-bottom: 16px; -} - -.memory-subtitle { - font-size: 13px; - color: var(--text-muted); - margin: 0; -} - -/* Capacity Grid Cards */ -.memory-capacity-grid { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 16px; - margin-bottom: 20px; -} - -.memory-capacity-card { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 16px; -} - -.memory-capacity-card-header { - display: flex; - align-items: center; - gap: 8px; - font-size: 13px; - font-weight: 600; - color: var(--text-primary); - margin-bottom: 12px; -} - -.memory-capacity-card-footer { - font-size: 12px; - color: var(--text-muted); - margin-top: 8px; -} - -.memory-capacity { - flex: 1; -} - -.memory-capacity-header { - display: flex; - justify-content: space-between; - margin-bottom: 4px; -} - -.memory-capacity-label { - font-size: 11px; - font-weight: 600; - color: var(--text-secondary); -} - -.memory-capacity-value { - font-size: 11px; - color: var(--text-muted); -} - -.memory-capacity-track { - height: 4px; - background: var(--bg-elevated); - border-radius: 2px; - overflow: hidden; -} - -.memory-capacity-fill { - height: 100%; - border-radius: 2px; - transition: width 0.3s ease; -} - -/* Tabs */ -.memory-tabs { - display: flex; - gap: 0; - border-bottom: 1px solid var(--border); - margin-bottom: 16px; -} - -.memory-tab { - padding: 8px 16px; - font-size: 13px; - font-weight: 500; - color: var(--text-muted); - background: none; - border: none; - border-bottom: 2px solid transparent; - cursor: pointer; - display: flex; - align-items: center; - gap: 8px; - transition: all var(--transition); -} - -.memory-tab:hover { - color: var(--text-secondary); -} - -.memory-tab.active { - color: var(--text-primary); - border-bottom-color: var(--accent); -} - -.memory-error { - background: var(--error-bg); - color: var(--error); - padding: 8px 12px; - border-radius: 6px; - font-size: 12px; - margin-bottom: 12px; -} - -/* Entry list */ -.memory-entries-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 12px; -} - -.memory-entries-count { - font-size: 12px; - color: var(--text-muted); -} - -.memory-entry-card { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 12px 14px; - margin-bottom: 8px; -} - -.memory-entry-card:hover { - border-color: var(--border-bright); -} - -.memory-entry-content { - font-size: 13px; - color: var(--text-primary); - line-height: 1.6; - white-space: pre-wrap; -} - -.memory-entry-actions { - display: flex; - align-items: center; - justify-content: flex-end; - gap: 8px; - margin-top: 8px; -} - -.memory-entry-btn { - font-size: 11px; - color: var(--text-muted); - padding: 2px 6px; -} - -.memory-entry-btn:hover { - color: var(--text-primary); -} - -.memory-entry-confirm { - font-size: 11px; - color: var(--text-secondary); - display: flex; - align-items: center; - gap: 6px; -} - -.memory-entry-form { - margin-bottom: 12px; -} - -.memory-entry-textarea { - width: 100%; - padding: 10px 12px; - font-size: 13px; - font-family: var(--font-sans); - color: var(--text-primary); - background: var(--bg-primary); - border: 1px solid var(--border-bright); - border-radius: 6px; - resize: vertical; - outline: none; - box-sizing: border-box; - line-height: 1.5; -} - -.memory-entry-textarea:focus { - border-color: var(--border-focus); -} - -.memory-entry-form-actions { - display: flex; - align-items: center; - gap: 8px; - margin-top: 8px; - justify-content: flex-end; -} - -.memory-entry-chars { - font-size: 11px; - color: var(--text-muted); - margin-right: auto; -} - -.memory-empty { - text-align: center; - padding: 32px; - color: var(--text-muted); - font-size: 13px; - line-height: 1.6; -} - -.memory-empty-hint { - font-size: 12px; - margin-top: 4px; -} - -/* User profile */ -.memory-profile-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 10px; -} - -.memory-profile-hint { - font-size: 12px; - color: var(--text-muted); -} - -.memory-profile-textarea { - width: 100%; - padding: 12px 14px; - font-size: 13px; - font-family: var(--font-sans); - color: var(--text-primary); - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - resize: vertical; - outline: none; - box-sizing: border-box; - line-height: 1.6; -} - -.memory-profile-textarea:focus { - border-color: var(--border-focus); -} - -.memory-profile-footer { - display: flex; - align-items: center; - justify-content: space-between; - margin-top: 10px; -} - -/* Memory Providers */ -.memory-providers { - margin-top: 16px; -} - -.memory-providers-hint { - font-size: 13px; - color: var(--text-secondary); - margin-bottom: 16px; - line-height: 1.5; -} - -.memory-providers-grid { - display: flex; - flex-direction: column; - gap: 12px; -} - -.memory-provider-card { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 10px; - padding: 14px 16px; - transition: border-color 0.15s; -} - -.memory-provider-card:hover { - border-color: var(--border-hover); -} - -.memory-provider-active { - border-color: var(--accent); - background: color-mix(in srgb, var(--accent) 5%, var(--bg-secondary)); -} - -.memory-provider-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 4px; -} - -.memory-provider-name { - font-weight: 600; - font-size: 14px; - display: flex; - align-items: center; - gap: 8px; - text-transform: capitalize; -} - -.memory-provider-badge { - display: inline-flex; - align-items: center; - gap: 3px; - font-size: 10px; - font-weight: 600; - color: var(--accent); - background: color-mix(in srgb, var(--accent) 12%, transparent); - padding: 2px 7px; - border-radius: 10px; -} - -.memory-provider-desc { - font-size: 12px; - color: var(--text-secondary); - line-height: 1.4; - margin-bottom: 10px; -} - -.memory-provider-fields { - display: flex; - flex-direction: column; - gap: 8px; - margin-bottom: 10px; -} - -.memory-provider-field-label { - font-size: 11px; - font-weight: 500; - color: var(--text-tertiary); - font-family: var(--font-mono); - margin-bottom: 2px; - display: block; -} - -.memory-provider-actions { - display: flex; - gap: 8px; -} - -.memory-soul-tab { - flex: 1; - min-height: 500px; - overflow-y: auto; - padding: 0; -} - -.memory-soul-tab .soul-container { - padding: 0; - height: 100%; - min-height: 500px; -} - -/* ======================================================================== - TOOLS CONFIGURATION - ======================================================================== */ -.tools-container { - display: flex; - flex-direction: column; - height: 100%; - padding: 24px 32px; - overflow-y: auto; -} - -.tools-loading { - flex: 1; - display: flex; - align-items: center; - justify-content: center; -} - -.tools-screen { - display: flex; - flex-direction: column; - height: 100%; - overflow: hidden; -} - -.tools-tabs { - display: flex; - gap: 4px; - flex-shrink: 0; - padding: 12px 32px 0; - border-bottom: 1px solid var(--border); -} - -.tools-pane { - flex: 1; - min-height: 0; - overflow-y: auto; - padding: 24px 32px; -} - -/* Skills mounts its own scrolling container; just give it bounded height. */ -.tools-skills-pane { - flex: 1; - min-height: 0; -} - -.tools-pane .tools-section { - margin-top: 0; -} - -.tools-tab { - display: flex; - align-items: center; - gap: 8px; - padding: 13px 18px; - background: none; - border: none; - border-bottom: 2px solid transparent; - margin-bottom: -1px; - color: var(--text-muted); - font-size: 14.5px; - font-weight: 600; - font-family: var(--font-sans); - cursor: pointer; - transition: all var(--transition); -} - -.tools-tab svg { - width: 17px; - height: 17px; - opacity: 0.85; -} - -.tools-tab:hover { - color: var(--text-secondary); - background: var(--bg-secondary); -} - -.tools-tab.active { - color: var(--accent-text, var(--accent)); - border-bottom-color: var(--accent); - background: color-mix(in srgb, var(--accent) 9%, transparent); -} - -.tools-tab.active svg { - opacity: 1; -} - -.tools-tab-count { - font-size: 11px; - font-weight: 600; - color: var(--text-muted); - background: var(--bg-tertiary); - border-radius: 10px; - padding: 1px 7px; -} - -.tools-tab.active .tools-tab-count { - color: var(--accent-text, var(--accent)); - background: color-mix(in srgb, var(--accent) 16%, transparent); -} - -/* MCP filter box (left side of the MCP toolbar row) */ -.tools-mcp-search { - display: flex; - align-items: center; - gap: 8px; - flex: 1; - max-width: 360px; - padding: 0 10px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-sm); - color: var(--text-muted); -} - -.tools-mcp-search:focus-within { - border-color: var(--border-focus); -} - -.tools-mcp-search-input { - flex: 1; - background: none; - border: none; - outline: none; - padding: 9px 0; - font-size: 13px; - font-family: var(--font-sans); - color: var(--text-primary); -} - -.tools-mcp-search-input::placeholder { - color: var(--text-muted); -} - -.tools-mcp-no-results { - padding: 16px 4px; -} - -.tools-header { - margin-bottom: 20px; -} - -.tools-title { - font-size: 20px; - font-weight: 700; - color: var(--text-primary); -} - -.tools-subtitle { - font-size: 13px; - color: var(--text-muted); - margin-top: 2px; -} - -.tools-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); - gap: 12px; -} - -.tools-card { - display: flex; - flex-direction: column; - padding: 16px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - cursor: pointer; - transition: all var(--transition); - -webkit-user-select: none; - user-select: none; -} - -.tools-card:hover { - background: var(--bg-tertiary); -} - -.tools-card-enabled { - border-color: color-mix(in srgb, var(--accent) 40%, transparent); -} - -.tools-card-disabled { - opacity: 0.55; -} - -.tools-card-disabled:hover { - opacity: 0.8; -} - -.tools-card-top { - display: flex; - align-items: flex-start; - justify-content: space-between; - margin-bottom: 12px; -} - -.tools-card-icon { - width: 36px; - height: 36px; - display: flex; - align-items: center; - justify-content: center; - border-radius: var(--radius-sm); - background: var(--bg-elevated); - padding: 7px; - color: var(--text-secondary); - flex-shrink: 0; -} - -.tools-card-enabled .tools-card-icon { - background: var(--accent); - color: #fff; -} - -.tools-card-icon svg { - width: 100%; - height: 100%; -} - -.tools-card-label { - font-size: 14px; - font-weight: 600; - color: var(--text-primary); - margin-bottom: 2px; -} - -.tools-card-description { - font-size: 12px; - color: var(--text-muted); - line-height: 1.4; -} - -/* Toggle switch */ -.tools-toggle { - position: relative; - display: inline-flex; - flex-shrink: 0; - cursor: pointer; -} - -.tools-toggle input { - position: absolute; - opacity: 0; - width: 0; - height: 0; -} - -.tools-toggle-track { - display: block; - width: 40px; - height: 22px; - background: var(--bg-elevated); - border: 1px solid var(--border-bright); - border-radius: 11px; - transition: all var(--transition); - position: relative; -} - -.tools-toggle-track::after { - content: ""; - position: absolute; - top: 2px; - left: 2px; - width: 16px; - height: 16px; - background: var(--text-muted); - border-radius: 50%; - transition: all var(--transition); -} - -.tools-toggle input:checked + .tools-toggle-track { - background: var(--accent); - border-color: var(--accent); -} - -.tools-toggle input:checked + .tools-toggle-track::after { - transform: translateX(18px); - background: #fff; -} - -.tools-section { - margin-top: 32px; -} - -.tools-header-row { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 16px; -} - -.tools-header-actions, -.tools-mcp-actions { - display: flex; - align-items: center; - gap: 8px; - flex-wrap: wrap; -} - -.tools-header-actions .btn, -.tools-catalog-row .btn { - display: inline-flex; - align-items: center; - gap: 6px; -} - -.tools-header-actions svg, -.tools-catalog-row .btn svg { - width: 14px; - height: 14px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} - -.tools-icon-btn { - width: 30px; - height: 30px; - display: inline-flex; - align-items: center; - justify-content: center; - border: 1px solid var(--border); - border-radius: var(--radius-sm); - background: var(--bg-elevated); - color: var(--text-secondary); - cursor: pointer; - transition: all var(--transition); -} - -.tools-icon-btn:hover:not(:disabled) { - color: var(--text-primary); - border-color: var(--border-bright); -} - -.tools-icon-btn:disabled { - opacity: 0.55; - cursor: not-allowed; -} - -.tools-icon-btn-danger:hover:not(:disabled) { - color: var(--error); - border-color: color-mix(in srgb, var(--error) 45%, transparent); -} - -.tools-icon-btn svg { - width: 15px; - height: 15px; - fill: none; - stroke: currentColor; - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; -} - -.tools-error, -.tools-success { - margin-bottom: 12px; - padding: 10px 12px; - border-radius: var(--radius-sm); - font-size: 12px; -} - -.tools-error { - color: var(--error); - background: var(--error-bg); - border: 1px solid color-mix(in srgb, var(--error) 45%, transparent); -} - -.tools-success { - color: var(--success); - background: color-mix(in srgb, var(--success) 12%, transparent); - border: 1px solid color-mix(in srgb, var(--success) 35%, transparent); -} - -.tools-empty { - display: flex; - gap: 12px; - align-items: center; - padding: 16px; - background: var(--bg-secondary); - border: 1px dashed var(--border-bright); - border-radius: var(--radius-md); -} - -.tools-mcp-card { - cursor: default; -} - -.tools-mcp-pill, -.tools-mcp-disabled { - display: inline-flex; - align-items: center; - min-height: 20px; - padding: 2px 7px; - border-radius: 999px; - font-size: 11px; - line-height: 1; - background: var(--bg-elevated); - color: var(--text-secondary); - margin-right: 6px; -} - -.tools-mcp-disabled { - color: var(--error); - background: var(--error-bg); -} - -.tools-mcp-detail { - margin-top: 8px; - overflow-wrap: anywhere; -} - -.tools-textarea { - min-height: 78px; - resize: vertical; -} - -.tools-catalog-modal { - width: 680px; -} - -.tools-catalog-list { - display: flex; - flex-direction: column; - gap: 10px; - max-height: 58vh; - overflow-y: auto; -} - -.tools-catalog-row { - display: grid; - grid-template-columns: minmax(0, 1fr) auto; - gap: 12px; - align-items: center; - padding: 12px; - border: 1px solid var(--border); - border-radius: var(--radius-sm); - background: var(--bg-primary); -} - -@media (max-width: 760px) { - .tools-container { - padding: 20px 16px; - } - - .tools-header-row { - flex-direction: column; - align-items: stretch; - } - - .tools-header-actions { - width: 100%; - flex-direction: column; - align-items: stretch; - } - - .tools-header-actions .btn, - .tools-catalog-row .btn { - width: 100%; - justify-content: center; - } - - .tools-grid { - grid-template-columns: minmax(0, 1fr); - } - - .tools-catalog-modal { - width: min(680px, calc(100vw - 24px)); - } - - .tools-catalog-row { - grid-template-columns: minmax(0, 1fr); - } -} - -/* ======================================================================== - SCROLLBAR - ======================================================================== */ -::-webkit-scrollbar { - width: 6px; -} - -::-webkit-scrollbar-track { - background: transparent; -} - -::-webkit-scrollbar-thumb { - background: var(--scrollbar-thumb); - border-radius: 3px; -} - -::-webkit-scrollbar-thumb:hover { - background: var(--scrollbar-hover); -} - -/* ======================================================================== - MODELS - ======================================================================== */ -.models-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - margin-bottom: 20px; -} - -.models-embedded { - display: flex; - flex-direction: column; - min-height: 0; -} - -.models-header.embedded { - justify-content: flex-end; - margin-bottom: 12px; -} - -.models-tabs { - display: flex; - gap: 8px; - margin-bottom: 20px; - border-bottom: 1px solid var(--border); - padding-bottom: 0; -} - -.models-tab { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 16px; - background: transparent; - border: none; - border-bottom: 2px solid transparent; - color: var(--text-secondary); - font-size: 14px; - cursor: pointer; - transition: all 0.2s; - border-radius: 4px 4px 0 0; -} - -.models-tab:hover { - color: var(--text-primary); - background: var(--bg-hover); -} - -.models-tab.active { - color: var(--text-primary); - border-bottom-color: var(--accent); -} - -.aux-task-details { - display: flex; - flex-direction: column; - gap: 4px; - margin-top: 8px; - padding: 8px 10px; - background: var(--bg-tertiary); - border-radius: 6px; - font-size: 12px; -} - -.aux-task-provider { - color: var(--text-secondary); - font-weight: 500; - text-transform: capitalize; -} - -.auxiliary-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 20px; - margin-bottom: 10px; -} - -.aux-task-model { - color: var(--text-muted); - font-family: var(--font-mono, monospace); -} - -.models-header-actions { - display: flex; - gap: 8px; - align-items: center; -} - -.models-provider-chips { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-bottom: 16px; -} - -.models-provider-chip { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 5px 12px; - background: var(--bg-tertiary); - border: 1px solid var(--border); - border-radius: 16px; - color: var(--text-secondary); - font-size: 12px; - cursor: pointer; - transition: all 0.15s; -} - -.models-provider-chip:hover { - background: var(--bg-hover); - color: var(--text-primary); -} - -.models-provider-chip.active { - background: var(--accent); - border-color: var(--accent); - color: #fff; -} - -.models-provider-chip-count { - font-size: 11px; - font-weight: 600; - background: rgba(255, 255, 255, 0.12); - padding: 1px 6px; - border-radius: 8px; -} - -.models-provider-chip:not(.active) .models-provider-chip-count { - background: var(--bg-elevated); - color: var(--text-muted); -} - -.models-registry-modal { - width: 70vw !important; - max-width: none; -} - -.models-registry-body { - max-height: 60vh; - overflow-y: auto; -} - -.registry-model-list { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 10px; -} - -.registry-provider { - margin-bottom: 18px; -} - -.registry-provider-head { - display: flex; - align-items: center; - gap: 8px; - margin-bottom: 8px; - padding-bottom: 6px; - border-bottom: 1px solid var(--border); -} - -.registry-provider-name { - font-size: 13px; - font-weight: 600; - color: var(--text-primary); -} - -.registry-provider-badge { - font-size: 11px; - color: var(--text-muted); - background: var(--bg-tertiary); - padding: 2px 8px; - border-radius: 10px; -} - -.registry-model-row { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 8px 10px; - background: var(--bg-tertiary); - border-radius: 6px; -} - -.registry-model-info { - display: flex; - flex-direction: column; - gap: 2px; - min-width: 0; -} - -.registry-model-name { - font-size: 13px; - font-weight: 500; - color: var(--text-primary); -} - -.registry-model-id { - font-size: 11px; - color: var(--text-muted); - font-family: var(--font-mono, monospace); -} - -.registry-model-desc { - font-size: 12px; - color: var(--text-secondary); - margin-top: 2px; -} - -.registry-model-added { - display: flex; - align-items: center; - gap: 4px; - font-size: 12px; - color: var(--success); - white-space: nowrap; -} - -.models-subtitle { - font-size: 13px; - color: var(--text-secondary); - margin: 0; -} - -.models-loading { - display: flex; - align-items: center; - justify-content: center; - padding: 48px; -} - -.models-modal-overlay { - position: fixed; - inset: 0; - background: rgba(0, 0, 0, 0.5); - display: flex; - align-items: center; - justify-content: center; - z-index: 200; -} - -.models-modal { - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-lg); - width: 440px; - max-width: 90vw; - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4); - overflow: hidden; -} - -.models-modal-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 16px 20px; - border-bottom: 1px solid var(--border); -} - -.models-modal-header-actions { - display: flex; - align-items: center; - gap: 8px; -} - -.models-modal-title { - font-size: 16px; - font-weight: 600; - color: var(--text-primary); - margin: 0; -} - -.models-modal-body { - padding: 20px; - display: flex; - flex-direction: column; - gap: 16px; -} - -.models-modal-field { - display: flex; - flex-direction: column; - gap: 6px; -} - -.models-modal-label { - font-size: 12px; - font-weight: 600; - color: var(--text-secondary); -} - -.models-modal-hint { - font-size: 11px; - color: var(--text-muted); -} - -.models-modal-auto-badge { - font-size: 11px; - font-weight: 400; - color: var(--text-muted); - font-style: italic; -} - -/* Tighten the Models page heading so the subtitle hugs the title. - Replaces an inline `style={{ marginBottom: 4 }}`. */ -.models-title-tight { - margin-bottom: 4px; -} - -/* Red text on a small confirmation button (e.g. "Yes, delete"). - Replaces an inline `style={{ color: "var(--error)" }}`. */ -.btn-danger-text { - color: var(--error); -} - -.models-modal-field .input, -.models-modal-field select.input { - padding: 8px 12px; - font-size: 13px; - border-radius: 6px; - box-sizing: border-box; - max-width: 100%; -} - -.models-modal-field select.input { - appearance: auto; -} - -.models-modal-footer { - display: flex; - justify-content: flex-end; - gap: 8px; - padding: 12px 20px; - border-top: 1px solid var(--border); -} - -.models-error { - color: var(--error); - font-size: 12px; -} - -/* ── Follow-us-on-X modal ── */ -.follow-us-modal { - background: var(--bg-secondary); - border: 1px solid var(--border-bright); - border-radius: var(--radius-lg); - width: 380px; - max-width: 90vw; - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4); - overflow: hidden; -} - -.follow-us-body { - padding: 20px; - display: flex; - flex-direction: column; - align-items: center; - gap: 16px; -} - -.follow-us-icon-row { - display: flex; - align-items: center; - justify-content: center; - width: 56px; - height: 56px; - border-radius: 50%; - background: color-mix(in srgb, var(--accent-text) 10%, transparent); -} - -.follow-us-x-icon { - color: var(--accent-text); -} - -.follow-us-description { - font-size: 14px; - color: var(--text-secondary); - text-align: center; - margin: 0; - line-height: 1.5; -} - -.follow-us-footer { - justify-content: space-between; -} - -.follow-us-btn { - display: inline-flex; - align-items: center; - gap: 6px; -} - -.models-toolbar { - display: flex; - align-items: center; - gap: 8px; - margin-bottom: 16px; -} - -.models-toolbar .models-search { - flex: 1; - margin-bottom: 0; -} - -.models-toolbar .models-header-actions { - flex-shrink: 0; -} - -.models-search { - display: flex; - align-items: center; - gap: 8px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 8px 12px; - margin-bottom: 16px; - color: var(--text-muted); -} - -.models-search-input { - flex: 1; - background: none; - border: none; - color: var(--text-primary); - font-size: 13px; - outline: none; -} - -.models-search-input::placeholder { - color: var(--text-muted); -} - -.models-empty { - text-align: center; - padding: 48px 24px; -} - -.models-empty-text { - font-size: 15px; - color: var(--text-secondary); - margin: 0 0 8px; -} - -.models-empty-hint { - font-size: 13px; - color: var(--text-muted); - margin: 0; - max-width: 400px; - margin: 0 auto; - line-height: 1.5; -} - -.models-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); - gap: 12px; -} - -.models-card { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 14px; - transition: border-color var(--transition); -} - -.models-card:hover { - border-color: var(--border-bright); - cursor: pointer; -} - -.models-card-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 6px; -} - -.models-card-name { - font-size: 14px; - font-weight: 600; - color: var(--text-primary); -} - -.models-card-provider { - font-size: 10px; - font-weight: 600; - color: var(--accent-text); - background: var(--accent-subtle); - padding: 2px 8px; - border-radius: 10px; - text-transform: uppercase; - letter-spacing: 0.03em; -} - -.models-card-model { - font-size: 12px; - color: var(--text-secondary); - font-family: var(--font-mono); - margin-bottom: 4px; - word-break: break-all; -} - -.models-card-url { - font-size: 11px; - color: var(--text-muted); - margin-bottom: 4px; -} - -.models-card-footer { - display: flex; - justify-content: flex-end; - margin-top: 8px; -} - -.models-card-delete { - color: var(--text-muted); - padding: 4px; -} - -.models-card-delete:hover { - color: var(--error); -} - -.models-card-confirm { - display: flex; - align-items: center; - gap: 8px; - font-size: 12px; - color: var(--text-secondary); -} - -.models-card-title { - display: flex; - align-items: center; - gap: 10px; - min-width: 0; -} - -.brand-logo { - flex-shrink: 0; - object-fit: contain; -} - -.brand-logo--fallback { - color: var(--text-muted); -} - -/* Match-theme logos are flattened to a single tint (never brand colors), - chosen by the theme's background: white icons on dark themes, black on - light. Dark is the default; add new light themes to the override below. */ -.brand-logo--match-theme { - filter: brightness(0) invert(1); -} - -[data-theme="light"] .brand-logo--match-theme, -[data-theme="github-light"] .brand-logo--match-theme, -[data-theme="solarized-light"] .brand-logo--match-theme { - filter: brightness(0); -} - -/* ======================================================================== - OFFICE (Claw3D) - ======================================================================== */ -.office-ready { - display: flex; - flex-direction: column; - height: 100%; - overflow-y: auto; -} - -.office-toolbar { - display: flex; - align-items: center; - justify-content: space-between; - padding: 10px 20px; - border-bottom: 1px solid var(--border); - background: var(--bg-secondary); - flex-shrink: 0; -} - -.office-toolbar-left { - display: flex; - align-items: center; - gap: 10px; -} - -.office-toolbar-right { - display: flex; - align-items: center; - gap: 6px; -} - -.office-toolbar-title { - font-size: 15px; - font-weight: 600; - color: var(--text-primary); - margin: 0; -} - -.office-status-dot { - width: 8px; - height: 8px; - border-radius: 50%; - flex-shrink: 0; -} - -.office-status-dot.running { - background: var(--success); - box-shadow: 0 0 6px var(--success); -} - -.office-status-dot.stopped { - background: var(--text-muted); -} - -.office-status-label { - font-size: 12px; - color: var(--text-secondary); -} - -.office-toolbar-btn { - padding: 4px; - color: var(--text-secondary); -} - -.office-toolbar-btn:hover { - color: var(--text-primary); -} - -.office-settings-bar { - display: flex; - align-items: center; - gap: 16px; - padding: 8px 20px; - background: var(--bg-tertiary); - border-bottom: 1px solid var(--border); - flex-shrink: 0; -} - -.office-setting { - display: flex; - align-items: center; - gap: 6px; -} - -.office-setting-label { - font-size: 11px; - color: var(--text-muted); - white-space: nowrap; -} - -.office-port-input { - width: 64px; - padding: 4px 8px; - font-size: 12px; - border: 1px solid var(--border); - border-radius: 4px; - background: var(--bg-primary); - color: var(--text-primary); - text-align: center; - box-sizing: border-box; - -moz-appearance: textfield; - appearance: textfield; -} - -.office-port-input::-webkit-inner-spin-button, -.office-port-input::-webkit-outer-spin-button { - -webkit-appearance: none; - margin: 0; -} - -.office-port-input:focus { - outline: none; - border-color: var(--border-focus); -} - -.office-ws-input { - width: 200px; - padding: 4px 8px; - font-size: 12px; - border: 1px solid var(--border); - border-radius: 4px; - background: var(--bg-primary); - color: var(--text-primary); - box-sizing: border-box; -} - -.office-ws-input:focus { - outline: none; - border-color: var(--border-focus); -} - -.office-warning-bar { - padding: 8px 20px; - font-size: 12px; - color: var(--warning); - background: rgba(245, 158, 11, 0.08); - border-bottom: 1px solid rgba(245, 158, 11, 0.2); - flex-shrink: 0; -} - -.office-error-bar { - display: flex; - align-items: center; - justify-content: space-between; - padding: 8px 20px; - background: var(--error-bg); - border-bottom: 1px solid rgba(239, 68, 68, 0.2); - flex-shrink: 0; -} - -.office-error-text { - font-size: 12px; - color: var(--error); - flex: 1; - margin-right: 12px; -} - -.office-error-actions { - display: flex; - gap: 6px; - flex-shrink: 0; -} - -.office-logs-panel { - display: flex; - flex-direction: column; - flex: 1; - overflow: hidden; -} - -.office-logs-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 8px 20px; - font-size: 12px; - font-weight: 600; - color: var(--text-secondary); - border-bottom: 1px solid var(--border); - flex-shrink: 0; -} - -.office-logs-content { - flex: 1; - overflow-y: auto; - padding: 12px 20px; - font-size: 11px; - font-family: var(--font-mono); - color: var(--text-secondary); - white-space: pre-wrap; - word-break: break-all; - background: var(--bg-primary); -} - -.office-content { - flex: 1; - position: relative; - overflow: hidden; -} - -.office-content webview { - width: 100%; - height: 100%; - border: none; -} - -.office-loading-overlay { - position: absolute; - inset: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 12px; - background: var(--bg-primary); - z-index: 10; -} - -.office-webview-error { - text-align: center; - max-width: 400px; -} - -.office-webview-error-title { - font-size: 16px; - font-weight: 600; - color: var(--text-primary); - margin: 0 0 8px; -} - -.office-webview-error-actions { - display: flex; - gap: 8px; - justify-content: center; - margin-top: 16px; -} - -.office-center { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 16px; - padding: 48px 24px; - flex: 1; -} - -.office-muted { - color: var(--text-muted); - font-size: 14px; -} - -.office-spinner { - width: 32px; - height: 32px; - border: 3px solid var(--border-bright); - border-top-color: var(--accent-text); - border-radius: 50%; - animation: spin 0.8s linear infinite; -} - -@keyframes spin { - to { - transform: rotate(360deg); - } -} - -.office-setup-card { - max-width: 480px; - text-align: center; -} - -.office-setup-title { - font-size: 20px; - font-weight: 600; - color: var(--text-primary); - margin: 0 0 12px; -} - -.office-setup-desc { - font-size: 14px; - color: var(--text-secondary); - line-height: 1.5; - margin: 0 0 12px; -} - -.office-setup-actions { - display: flex; - gap: 10px; - justify-content: center; - margin-top: 20px; -} - -.office-error { - background: var(--error-bg); - color: var(--error); - padding: 10px 14px; - border-radius: 6px; - font-size: 13px; - margin-top: 12px; -} - -.office-installing { - padding: 32px 24px; - max-width: 600px; - margin: 0 auto; -} - -.office-install-title { - font-size: 18px; - font-weight: 600; - color: var(--text-primary); - margin: 0 0 20px; - text-align: center; -} - -/* ======================================================================== - SPLASH SCREEN - ======================================================================== */ -.splash-screen { - position: fixed; - inset: 0; - z-index: 9999; - display: flex; - align-items: center; - justify-content: center; - overflow: hidden; - background: #000; -} - -.splash-bg { - position: absolute; - inset: 0; - width: 100%; - height: 100%; - object-fit: cover; - opacity: 50%; - /* Overscan slightly past the viewport so the video's bright top/bottom edge - rows are clipped by the container's overflow:hidden instead of showing as - thin white lines at the frame boundary. */ - transform: scale(1.04); - background: #000; -} - -.splash-logo { - position: relative; - z-index: 1; - width: 600px; - max-width: 60%; - opacity: 0; - animation: splashFadeIn 1.1s ease-out forwards; -} - -.splash-status { - position: absolute; - bottom: 40px; - left: 0; - right: 0; - z-index: 1; - text-align: center; - color: rgba(255, 255, 255, 0.7); - font-size: 13px; - letter-spacing: 0.3px; - animation: splashFadeIn 0.6s ease-out forwards; -} - -@keyframes splashFadeIn { - 0% { - opacity: 0; - transform: scale(0.9) translateY(10px); - filter: blur(8px); - } - 100% { - opacity: 1; - transform: scale(1) translateY(0); - filter: blur(0); - } -} - -/* ======================================================================== - ERROR BOUNDARY - ======================================================================== */ -.error-boundary { - display: flex; - align-items: center; - justify-content: center; - height: 100vh; - padding: 24px; - background: var(--bg-primary); -} - -.error-boundary-card { - text-align: center; - padding: 32px; - border-radius: 12px; - background: var(--bg-secondary); - border: 1px solid var(--border); - max-width: 420px; -} - -.error-boundary-title { - font-size: 18px; - font-weight: 600; - color: var(--text-primary); - margin-bottom: 8px; -} - -.error-boundary-message { - font-size: 13px; - color: var(--text-secondary); - margin-bottom: 20px; - line-height: 1.5; -} - -/* ======================================================================== - SELECTION - ======================================================================== */ -::selection { - background: var(--selection); - color: var(--text-primary); -} - -/* User bubbles have a blue background (#003f7a default) — the theme's - --selection color is also blue-toned and composites to nearly the same - shade on top of the user bubble. Use a brighter sky-blue so the - selection highlight remains clearly visible on user messages. */ -.chat-bubble-user ::selection { - background: rgba(120, 190, 255, 0.7); -} - -/* ======================================================================== - KANBAN - ======================================================================== */ -.kanban-container { - display: flex; - flex-direction: column; - height: 100%; - overflow: hidden; - padding: 24px 32px 0; -} - -.kanban-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - margin-bottom: 14px; - flex-shrink: 0; -} - -.kanban-empty { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - text-align: center; - gap: 6px; -} - -.kanban-boards-bar { - display: flex; - flex-wrap: wrap; - gap: 6px; - padding-bottom: 12px; - border-bottom: 1px solid var(--border); - margin-bottom: 12px; - flex-shrink: 0; -} - -.kanban-board-chip { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 4px 10px; - border-radius: 999px; - background: var(--bg-secondary); - color: var(--text-secondary); - border: 1px solid var(--border); - font-size: 12px; - font-weight: 500; - cursor: pointer; - transition: all var(--transition); -} - -.kanban-board-chip:hover:not(:disabled) { - color: var(--text-primary); - border-color: var(--border-bright); -} - -.kanban-board-chip-active { - background: var(--accent-subtle); - color: var(--accent-text); - border-color: var(--accent-subtle); -} - -.kanban-board-dot { - width: 6px; - height: 6px; - border-radius: 999px; - background: var(--accent-text); -} - -.kanban-board-count { - font-size: 11px; - font-weight: 600; - opacity: 0.7; - padding: 0 4px; -} - -.kanban-board-chip-add { - border-style: dashed; -} - -.kanban-columns { - flex: 1; - display: grid; - /* Column count is dynamic (8 canonical statuses, +1 when archived is shown), - so auto-flow columns rather than a fixed track count; the board scrolls - horizontally like a JIRA board when the lanes overflow. */ - grid-auto-flow: column; - grid-auto-columns: minmax(232px, 1fr); - gap: 10px; - overflow-x: auto; - overflow-y: hidden; - padding-bottom: 20px; -} - -.kanban-column { - display: flex; - flex-direction: column; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - min-height: 0; - /* Clip the header's colored top accent to the lane's rounded corners, - otherwise the inset status bar shows square corners over the radius. */ - overflow: hidden; -} - -.kanban-column-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 10px 12px; - border-bottom: 1px solid var(--border); - flex-shrink: 0; -} - -.kanban-column-title { - font-size: 12px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.04em; - color: var(--text-secondary); -} - -.kanban-column-count { - font-size: 11px; - font-weight: 600; - color: var(--text-muted); - background: var(--bg-tertiary); - padding: 1px 7px; - border-radius: 999px; -} - -/* JIRA-style colored status dot. Hues are fixed per status (independent of the - active theme) so a status reads the same everywhere — matching how issue - trackers color their status lozenges. Most map to the theme's semantic vars; - running (teal "live") and review (purple) have no theme equivalent. */ -.kanban-column-dot { - width: 8px; - height: 8px; - border-radius: 999px; - flex-shrink: 0; - background: var(--text-muted); -} -.kanban-column-dot[data-tone="neutral"] { - background: var(--text-muted); -} -.kanban-column-dot[data-tone="todo"] { - background: var(--text-secondary); -} -.kanban-column-dot[data-tone="scheduled"] { - background: var(--warning); -} -.kanban-column-dot[data-tone="ready"] { - background: var(--accent); -} -.kanban-column-dot[data-tone="running"] { - background: #14b8a6; -} -.kanban-column-dot[data-tone="blocked"] { - background: var(--error); -} -.kanban-column-dot[data-tone="review"] { - background: #a855f7; -} -.kanban-column-dot[data-tone="done"] { - background: var(--success); -} -.kanban-column-dot[data-tone="archived"] { - background: var(--text-muted); - opacity: 0.6; -} - -/* Faint top accent on each lane header, tinted to the column's status. */ -.kanban-column-header { - gap: 8px; -} -.kanban-column-header .kanban-column-count { - margin-left: auto; -} -.kanban-column[data-tone="scheduled"] .kanban-column-header { - box-shadow: inset 0 2px 0 0 - color-mix(in srgb, var(--warning) 60%, transparent); -} -.kanban-column[data-tone="ready"] .kanban-column-header { - box-shadow: inset 0 2px 0 0 color-mix(in srgb, var(--accent) 60%, transparent); -} -.kanban-column[data-tone="running"] .kanban-column-header { - box-shadow: inset 0 2px 0 0 color-mix(in srgb, #14b8a6 60%, transparent); -} -.kanban-column[data-tone="blocked"] .kanban-column-header { - box-shadow: inset 0 2px 0 0 color-mix(in srgb, var(--error) 60%, transparent); -} -.kanban-column[data-tone="review"] .kanban-column-header { - box-shadow: inset 0 2px 0 0 color-mix(in srgb, #a855f7 60%, transparent); -} -.kanban-column[data-tone="done"] .kanban-column-header { - box-shadow: inset 0 2px 0 0 - color-mix(in srgb, var(--success) 60%, transparent); -} - -.kanban-column-body { - flex: 1; - overflow-y: auto; - padding: 8px; - display: flex; - flex-direction: column; - gap: 8px; -} - -.kanban-column-empty { - text-align: center; - font-size: 12px; - color: var(--text-muted); - padding: 16px 0; -} - -.kanban-card { - background: var(--bg-primary); - border: 1px solid var(--border); - border-radius: var(--radius-sm); - padding: 10px 12px; - display: flex; - flex-direction: column; - gap: 6px; - cursor: grab; - transition: - border-color var(--transition), - opacity var(--transition); -} - -.kanban-card:hover { - border-color: var(--border-bright); -} - -.kanban-card:active { - cursor: grabbing; -} - -.kanban-card-dragging { - opacity: 0.4; - cursor: grabbing; -} - -.kanban-column-drop { - background: var(--accent-subtle); - outline: 2px dashed var(--accent); - outline-offset: -2px; - border-radius: var(--radius-md); -} - -.kanban-card { - position: relative; -} - -/* Left priority accent bar — the JIRA "issue priority" cue. Only present when - the card carries a data-prio (P0/P1/P2); normal-priority cards have none. */ -.kanban-card[data-prio]::before { - content: ""; - position: absolute; - left: 0; - top: 0; - bottom: 0; - width: 3px; - border-radius: var(--radius-sm) 0 0 var(--radius-sm); - background: var(--text-muted); -} -.kanban-card[data-prio="p0"]::before { - background: var(--error); -} -.kanban-card[data-prio="p1"]::before { - background: var(--warning); -} -.kanban-card[data-prio="p2"]::before { - background: var(--accent); -} - -.kanban-card-top { - display: flex; - align-items: center; - gap: 6px; -} - -.kanban-card-id { - font-family: var(--font-mono, ui-monospace, "SF Mono", monospace); - font-size: 10px; - font-weight: 600; - color: var(--text-muted); - letter-spacing: 0.02em; -} - -.kanban-card-age { - margin-left: auto; - font-size: 10px; - color: var(--text-muted); -} - -/* Pulsing "live" dot on running cards. */ -.kanban-live-dot { - width: 7px; - height: 7px; - border-radius: 999px; - background: #14b8a6; - box-shadow: 0 0 0 0 color-mix(in srgb, #14b8a6 70%, transparent); - animation: kanban-live-pulse 1.6s ease-out infinite; -} -@keyframes kanban-live-pulse { - 0% { - box-shadow: 0 0 0 0 color-mix(in srgb, #14b8a6 60%, transparent); - } - 70% { - box-shadow: 0 0 0 5px transparent; - } - 100% { - box-shadow: 0 0 0 0 transparent; - } -} - -.kanban-card-title { - font-size: 13px; - font-weight: 500; - color: var(--text-primary); - line-height: 1.3; - word-break: break-word; -} - -/* Assignee avatar chip (initials) + name. */ -.kanban-assignee { - display: inline-flex; - align-items: center; - gap: 5px; - min-width: 0; -} -.kanban-avatar { - display: inline-flex; - align-items: center; - justify-content: center; - width: 18px; - height: 18px; - border-radius: 999px; - background: var(--accent-subtle); - color: var(--accent-text); - font-size: 9px; - font-weight: 700; - flex-shrink: 0; -} -.kanban-avatar-none { - background: var(--bg-tertiary); - color: var(--text-muted); -} -.kanban-assignee-name { - font-size: 11px; - color: var(--text-secondary); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - max-width: 96px; -} -.kanban-assignee-none { - opacity: 0.7; -} - -.kanban-pill-skills { - background: var(--bg-tertiary); - color: var(--text-muted); -} - -/* Priority pill tones (used in the card header next to the id). */ -.kanban-pill-prio[data-prio="p0"] { - background: var(--error-bg); - color: var(--error); -} -.kanban-pill-prio[data-prio="p1"] { - background: var(--warning-bg); - color: var(--warning); -} - -.kanban-card-meta { - display: flex; - flex-wrap: wrap; - gap: 4px; - align-items: center; -} - -.kanban-pill { - font-size: 10px; - font-weight: 600; - padding: 1px 7px; - border-radius: 999px; - background: var(--bg-tertiary); - color: var(--text-secondary); - white-space: nowrap; -} - -.kanban-pill-prio { - background: var(--accent-subtle); - color: var(--accent-text); -} - -.kanban-pill-readonly { - background: var(--bg-tertiary); - color: var(--text-muted); - text-transform: uppercase; - letter-spacing: 0.04em; -} - -.kanban-card-readonly { - cursor: default; -} - -.kanban-card-readonly:hover { - background: var(--bg-tertiary); -} - -.kanban-hq-banner { - font-size: 12px; - color: var(--text-secondary); - background: var(--bg-tertiary); - border: 1px solid var(--border-subtle); - border-radius: var(--radius-md); - padding: 8px 12px; - margin-bottom: 8px; -} - -.kanban-pill-id { - font-family: var(--font-mono, ui-monospace, "SF Mono", monospace); - font-weight: 500; - text-transform: lowercase; -} - -.kanban-pill-age { - font-size: 10px; - color: var(--text-muted); - margin-left: auto; -} - -.kanban-card-actions { - display: flex; - gap: 2px; - justify-content: flex-end; - opacity: 0; - transition: opacity var(--transition); -} - -.kanban-card:hover .kanban-card-actions { - opacity: 1; -} - -.kanban-card-action { - position: relative; - padding: 2px 6px; - font-size: 12px; - border-radius: var(--radius-sm); - color: var(--text-secondary); -} - -.kanban-card-action:hover { - background: var(--bg-tertiary); - color: var(--text-primary); -} - -.kanban-card-action-danger:hover { - color: var(--error); -} - -.kanban-card-action[data-tooltip]::after, -.kanban-header .btn[data-tooltip]::after, -.kanban-board-chip-add[data-tooltip]::after { - content: attr(data-tooltip); - position: absolute; - bottom: calc(100% + 6px); - left: 50%; - transform: translateX(-50%); - padding: 4px 8px; - background: var(--bg-elevated); - color: var(--text-primary); - border: 1px solid var(--border); - border-radius: var(--radius-sm); - font-size: 11px; - font-weight: 500; - white-space: nowrap; - pointer-events: none; - opacity: 0; - transition: opacity 0.15s ease; - z-index: 10; -} - -.kanban-card-action[data-tooltip]:hover::after, -.kanban-header .btn[data-tooltip]:hover:not(:disabled)::after, -.kanban-board-chip-add[data-tooltip]:hover::after { - opacity: 1; -} - -/* Header buttons + add-board chip need an anchor for the absolutely- - positioned tooltip pseudo-element. The card actions already have - position:relative from their main rule. */ -.kanban-header .btn[data-tooltip], -.kanban-board-chip-add[data-tooltip] { - position: relative; -} - -/* The rightmost header button (New task) sits hard against the pane - edge, so its centered tooltip clips the viewport. Anchor to the - button's right edge instead. */ -.kanban-header .schedules-header-actions .btn[data-tooltip]:last-child::after { - left: auto; - right: 0; - transform: none; -} - -/* Detail modal */ -.kanban-detail-modal { - max-width: 720px; - width: 90vw; -} - -.kanban-detail-meta { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin-bottom: 14px; -} - -.kanban-detail-section { - display: flex; - flex-direction: column; - gap: 6px; - margin-bottom: 16px; -} - -.kanban-detail-section label { - font-size: 11px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.04em; - color: var(--text-muted); -} - -.kanban-detail-pre { - font-size: 12.5px; - line-height: 1.5; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius-sm); - padding: 10px 12px; - white-space: pre-wrap; - word-break: break-word; - margin: 0; - color: var(--text-primary); - max-height: 240px; - overflow-y: auto; -} - -.kanban-comment { - border-left: 2px solid var(--border); - padding-left: 10px; - margin-bottom: 8px; -} - -.kanban-comment-author { - font-size: 11px; - font-weight: 600; - color: var(--text-muted); - margin-bottom: 2px; -} - -.kanban-comment-body { - font-size: 13px; - color: var(--text-primary); - white-space: pre-wrap; -} - -.kanban-events { - display: flex; - flex-direction: column; - gap: 4px; - max-height: 180px; - overflow-y: auto; -} - -.kanban-event { - display: flex; - justify-content: space-between; - align-items: center; - padding: 4px 0; - border-bottom: 1px solid var(--border); -} - -.kanban-event:last-child { - border-bottom: none; -} - -.kanban-event-time { - font-size: 11px; - color: var(--text-muted); -} - -/* Active state for the "show archived" toolbar toggle. */ -.kanban-toggle-active { - background: var(--accent-subtle) !important; - color: var(--accent-text) !important; - border-color: var(--accent-subtle) !important; -} - -/* Status pill with a leading tone dot (used in the detail drawer header). */ -.kanban-pill-status { - display: inline-flex; - align-items: center; - gap: 5px; -} - -/* ---- Detail drawer (right-docked JIRA issue panel) ---- */ -.kanban-drawer-overlay { - position: fixed; - inset: 0; - background: color-mix(in srgb, var(--bg-primary) 40%, transparent); - z-index: 50; - display: flex; - justify-content: flex-end; -} - -.kanban-detail-drawer { - width: min(460px, 92vw); - height: 100%; - /* Clear the window's title-bar/tabs strip (.active-sessions-bar, z 1001, - ~34px) which paints above this overlay — without this the drawer's - header title is hidden behind it. */ - padding-top: 38px; - background: var(--bg-secondary); - border-left: 1px solid var(--border); - box-shadow: -8px 0 24px -12px rgba(0, 0, 0, 0.4); - display: flex; - flex-direction: column; - overflow: hidden; - animation: kanban-drawer-in 0.18s ease-out; -} -@keyframes kanban-drawer-in { - from { - transform: translateX(24px); - opacity: 0.6; - } - to { - transform: translateX(0); - opacity: 1; - } -} -.kanban-detail-drawer .schedules-modal-header { - flex-shrink: 0; -} -.kanban-detail-drawer .schedules-modal-body { - flex: 1; - overflow-y: auto; -} - -/* ======================================================================== - WEB PREVIEW PANEL - ======================================================================== */ -.web-preview-panel { - width: 480px; - flex-shrink: 0; - background: var(--bg-secondary); - border-left: 1px solid var(--border); - display: flex; - flex-direction: column; - overflow: hidden; - position: relative; -} - -/* Drag handle on the left edge to free-resize the panel width. */ -.web-preview-resize-handle { - position: absolute; - left: -3px; - top: 0; - width: 7px; - height: 100%; - cursor: col-resize; - z-index: 20; - background: transparent; - transition: background var(--transition); -} - -.web-preview-resize-handle:hover, -.web-preview-resize-handle-active { - background: color-mix(in srgb, var(--accent-text) 45%, transparent); -} - -.web-preview-header { - display: flex; - align-items: center; - gap: 6px; - padding: 8px 12px; - border-bottom: 1px solid var(--border); - background: var(--bg-tertiary); - flex-shrink: 0; -} - -.web-preview-btn { - display: inline-flex; - align-items: center; - justify-content: center; - width: 28px; - height: 28px; - border: none; - background: transparent; - color: var(--text-secondary); - border-radius: var(--radius-sm); - cursor: pointer; - flex-shrink: 0; - transition: all var(--transition); -} - -.web-preview-btn:hover:not(:disabled) { - background: var(--bg-hover); - color: var(--text-primary); -} - -.web-preview-btn:disabled { - opacity: 0.4; - cursor: not-allowed; -} - -.web-preview-address-bar { - flex: 1; - display: flex; - align-items: center; - background: var(--bg-primary); - border: 1px solid var(--border); - border-radius: var(--radius-md); - padding: 4px 8px; - margin: 0 4px; - min-width: 0; - transition: border-color var(--transition); -} - -.web-preview-address-bar:focus-within { - border-color: var(--accent); -} - -.web-preview-globe-icon { - color: var(--text-muted); - margin-right: 6px; - flex-shrink: 0; -} - -.web-preview-address-input { - width: 100%; - border: none; - background: transparent; - color: var(--text-primary); - font-size: 12px; - font-family: var(--font-sans); - outline: none; -} - -.web-preview-actions { - display: flex; - align-items: center; - gap: 4px; - flex-shrink: 0; -} - -.web-preview-webview-container { - flex: 1; - position: relative; - background: #ffffff; -} - -.web-preview-webview-container webview { - width: 100%; - height: 100%; - border: none; - background: #ffffff; -} - -.web-preview-btn-active { - background: color-mix(in srgb, var(--accent) 15%, transparent) !important; - color: var(--accent) !important; -} - -.web-preview-btn-active:hover:not(:disabled) { - background: color-mix(in srgb, var(--accent) 25%, transparent) !important; - color: var(--accent) !important; } diff --git a/src/renderer/src/screens/Chat/MessageRow.tsx b/src/renderer/src/screens/Chat/MessageRow.tsx index a98d4f5a1..8b4b061de 100644 --- a/src/renderer/src/screens/Chat/MessageRow.tsx +++ b/src/renderer/src/screens/Chat/MessageRow.tsx @@ -88,6 +88,12 @@ function isChatBubbleMessage(msg: ChatMessage): msg is ChatBubbleMessage { ); } +// Detect if a given text contains strong RTL characters (Hebrew/Arabic/Persian ranges). +function looksRtl(text?: string): boolean { + if (!text) return false; + return /[\u0591-\u08FF\uFB1D-\uFDFD\uFE70-\uFEFC]/.test(text); +} + /** * One full loop of `loadingo.gif`, in ms (119 frames × 40ms). Used to let the * animation finish its current loop after generation stops instead of freezing @@ -292,6 +298,9 @@ export const MessageRow = memo(function MessageRow({ const isTimeValid = isValidEpochMs(epochMs); const bubbleTime = isTimeValid ? formatBubbleTime(epochMs) : null; + // Determine per-bubble direction to handle mixed LTR/RTL content gracefully. + const bubbleDir = looksRtl(bubbleContent ?? "") ? "rtl" : "ltr"; + return (
    {msg.content && !isLoading && !msg.isSlashLoader && (
    diff --git a/src/shared/i18n/config.ts b/src/shared/i18n/config.ts index bb8571f58..804124872 100644 --- a/src/shared/i18n/config.ts +++ b/src/shared/i18n/config.ts @@ -16,11 +16,12 @@ export const APP_LOCALES: AppLocale[] = [ "tr", "zh-CN", "zh-TW", + "fa", ]; // Locales that render right-to-left. Used to set the document's `dir` // attribute so the whole UI mirrors for these languages. -export const RTL_LOCALES: AppLocale[] = ["ar", "he"]; +export const RTL_LOCALES: AppLocale[] = ["ar", "he", "fa"]; export type TextDirection = "ltr" | "rtl"; diff --git a/src/shared/i18n/index.test.ts b/src/shared/i18n/index.test.ts index 1ae9ed6f6..617dd2a59 100644 --- a/src/shared/i18n/index.test.ts +++ b/src/shared/i18n/index.test.ts @@ -39,6 +39,10 @@ describe("shared i18n", () => { expect(getLocaleDirection("en")).toBe("ltr"); }); + it("reports fa (Persian) as a right-to-left locale", () => { + expect(getLocaleDirection("fa")).toBe("rtl"); + }); + it("falls back to en when zh-CN key is missing", () => { expect(t("nonExistent.fallbackKey", "zh-CN")).toBe( "nonExistent.fallbackKey",