Changeset 0.25.0 (#160)

This commit is contained in:
2026-03-08 16:54:17 +00:00
parent 937be26578
commit 2b01d540d6
63 changed files with 6942 additions and 2773 deletions

153
src/css/admin-surfaces.css Normal file
View File

@@ -0,0 +1,153 @@
/* ==========================================
Chat Switchboard — Admin Surfaces
==========================================
v0.25.0: Surface lifecycle management UI.
========================================== */
.admin-surface-list {
display: flex;
flex-direction: column;
gap: 1px;
background: var(--border, #2a2a2e);
border: 1px solid var(--border, #2a2a2e);
border-radius: 8px;
overflow: hidden;
}
.admin-surface-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 14px 16px;
background: var(--bg-secondary, #151517);
}
.admin-surface-row:hover {
background: var(--bg-tertiary, #1e1e22);
}
.admin-surface-info {
flex: 1;
min-width: 0;
}
.admin-surface-title {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 4px;
}
.admin-surface-name {
font-size: 14px;
font-weight: 600;
color: var(--text, #eee);
}
.admin-surface-badge {
font-size: 10px;
font-weight: 600;
padding: 2px 6px;
border-radius: 4px;
text-transform: uppercase;
letter-spacing: 0.3px;
}
.admin-surface-badge--core {
background: var(--accent-dim, rgba(179, 138, 78, 0.15));
color: var(--accent, #b38a4e);
}
.admin-surface-badge--extension {
background: var(--purple-dim, rgba(160, 120, 255, 0.1));
color: var(--purple, #a078ff);
}
.admin-surface-badge--required {
background: var(--bg-raised, #2a2a2e);
color: var(--text-3, #555);
}
.admin-surface-meta {
display: flex;
align-items: center;
gap: 12px;
font-size: 12px;
color: var(--text-3, #555);
}
.admin-surface-id {
font-family: var(--mono, 'SF Mono', monospace);
font-size: 11px;
}
.admin-surface-route {
font-family: var(--mono, 'SF Mono', monospace);
font-size: 11px;
color: var(--text-3, #555);
}
.admin-surface-actions {
display: flex;
align-items: center;
gap: 12px;
flex-shrink: 0;
}
/* Toggle switch */
.admin-surface-toggle {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
user-select: none;
}
.admin-surface-toggle--locked {
opacity: 0.5;
cursor: not-allowed;
}
.admin-surface-toggle input[type="checkbox"] {
width: 36px;
height: 20px;
appearance: none;
-webkit-appearance: none;
background: var(--bg-raised, #2a2a2e);
border-radius: 10px;
position: relative;
cursor: pointer;
transition: background 0.2s;
flex-shrink: 0;
}
.admin-surface-toggle input[type="checkbox"]:checked {
background: var(--accent, #b38a4e);
}
.admin-surface-toggle input[type="checkbox"]::after {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: 16px;
height: 16px;
background: #fff;
border-radius: 50%;
transition: transform 0.2s;
}
.admin-surface-toggle input[type="checkbox"]:checked::after {
transform: translateX(16px);
}
.admin-surface-toggle input[type="checkbox"]:disabled {
cursor: not-allowed;
}
.admin-surface-toggle-label {
font-size: 12px;
color: var(--text-2, #999);
min-width: 56px;
}

412
src/css/chat-pane.css Normal file
View File

@@ -0,0 +1,412 @@
/* ==========================================
Chat Switchboard — ChatPane Component CSS
==========================================
v0.25.0-cs11.1: Self-contained styles for the ChatPane
component. Works in any context — sidebar chat, editor
assist pane, standalone embed. No external CSS dependencies.
========================================== */
/* ── Container ─────────────────────────────── */
.chat-pane {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
background: var(--bg, #0e0e10);
}
/* ── Header Bar (standalone mode) ──────────── */
.chat-pane-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 6px;
padding: 6px 10px;
border-bottom: 1px solid var(--border, #2a2a2e);
background: var(--bg-secondary, #151517);
flex-shrink: 0;
min-height: 36px;
}
.chat-pane-header-left {
display: flex;
align-items: center;
gap: 4px;
flex: 1;
min-width: 0;
}
.chat-pane-header-right {
display: flex;
align-items: center;
gap: 4px;
flex-shrink: 0;
}
.chat-pane-chat-select {
flex: 1;
min-width: 0;
background: var(--bg, #0e0e10);
border: 1px solid var(--border, #2a2a2e);
border-radius: 4px;
color: var(--text, #eee);
font-size: 11px;
font-family: inherit;
padding: 4px 6px;
cursor: pointer;
overflow: hidden;
text-overflow: ellipsis;
}
.chat-pane-chat-select:focus {
border-color: var(--accent, #b38a4e);
outline: none;
}
.chat-pane-new-btn {
display: flex;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
background: none;
border: 1px solid var(--border, #2a2a2e);
border-radius: 4px;
color: var(--text-2, #999);
cursor: pointer;
flex-shrink: 0;
transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.chat-pane-new-btn:hover {
color: var(--accent, #b38a4e);
border-color: var(--accent, #b38a4e);
background: var(--accent-dim, rgba(179, 138, 78, 0.1));
}
/* Model selector in header */
.chat-pane-model-select {
background: var(--bg, #0e0e10);
border: 1px solid var(--border, #2a2a2e);
border-radius: 4px;
color: var(--text-2, #999);
font-size: 11px;
font-family: inherit;
padding: 4px 6px;
cursor: pointer;
max-width: 140px;
overflow: hidden;
text-overflow: ellipsis;
}
.chat-pane-model-select:focus {
border-color: var(--accent, #b38a4e);
outline: none;
color: var(--text, #eee);
}
/* ── Messages Area ─────────────────────────── */
.chat-pane-messages {
flex: 1;
overflow-y: auto;
scroll-behavior: smooth;
padding: 12px 0;
min-height: 0;
}
/* ── Message Bubbles ───────────────────────── */
.chat-msg {
padding: 8px 16px;
font-size: var(--msg-font, 14px);
line-height: 1.65;
color: var(--text, #eee);
}
.chat-msg + .chat-msg {
margin-top: 2px;
}
/* User messages — right-aligned bubble */
.chat-msg--user {
display: flex;
justify-content: flex-end;
padding: 8px 16px;
}
.chat-msg--user .chat-msg__content {
background: var(--accent-dim, rgba(179, 138, 78, 0.15));
color: var(--text, #eee);
padding: 8px 14px;
border-radius: 12px 12px 2px 12px;
max-width: 85%;
word-wrap: break-word;
}
/* Assistant messages — left-aligned */
.chat-msg--assistant {
padding: 8px 16px;
}
.chat-msg--assistant .chat-msg__content {
max-width: 100%;
word-wrap: break-word;
}
/* ── Streaming indicator ───────────────────── */
.chat-msg--streaming .chat-msg__content::after {
content: '';
display: inline-block;
width: 6px;
height: 14px;
background: var(--accent, #b38a4e);
margin-left: 2px;
vertical-align: text-bottom;
animation: cp-cursor-blink 0.8s step-end infinite;
}
@keyframes cp-cursor-blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
/* ── Typing dots ───────────────────────────── */
.chat-msg--typing {
padding: 8px 16px;
}
/* System/error messages */
.chat-msg--system {
padding: 6px 16px;
font-size: 12px;
}
.chat-msg--typing .typing-dots {
display: flex;
gap: 4px;
padding: 4px 0;
}
.chat-msg--typing .typing-dots span {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--text-3, #555);
animation: cp-dot-bounce 1.2s ease-in-out infinite;
}
.chat-msg--typing .typing-dots span:nth-child(2) { animation-delay: 0.2s; }
.chat-msg--typing .typing-dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes cp-dot-bounce {
0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
30% { transform: translateY(-4px); opacity: 1; }
}
/* ── Markdown content ──────────────────────── */
.chat-msg__content p { margin: 0 0 0.5em; }
.chat-msg__content p:last-child { margin-bottom: 0; }
.chat-msg__content pre {
background: var(--bg-secondary, #151517);
border: 1px solid var(--border, #2a2a2e);
border-radius: 6px;
padding: 10px 12px;
overflow-x: auto;
margin: 8px 0;
font-size: 12px;
line-height: 1.5;
font-family: var(--mono, 'SF Mono', monospace);
}
.chat-msg__content code {
background: var(--bg-secondary, #151517);
padding: 1px 5px;
border-radius: 3px;
font-size: 0.88em;
font-family: var(--mono, 'SF Mono', monospace);
}
.chat-msg__content pre code {
background: none;
padding: 0;
border-radius: 0;
font-size: inherit;
}
.chat-msg__content ul, .chat-msg__content ol {
margin: 4px 0;
padding-left: 1.5em;
}
.chat-msg__content blockquote {
border-left: 3px solid var(--accent, #b38a4e);
padding: 4px 12px;
margin: 8px 0;
color: var(--text-2, #999);
}
.chat-msg__content a {
color: var(--accent, #b38a4e);
text-decoration: none;
}
.chat-msg__content a:hover {
text-decoration: underline;
}
.chat-msg__content table {
border-collapse: collapse;
margin: 8px 0;
font-size: 13px;
}
.chat-msg__content th,
.chat-msg__content td {
border: 1px solid var(--border, #2a2a2e);
padding: 4px 8px;
}
.chat-msg__content th {
background: var(--bg-secondary, #151517);
font-weight: 600;
}
/* ── Welcome / Empty State ─────────────────── */
.chat-welcome {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
text-align: center;
padding: 40px 20px;
opacity: 0.6;
}
.chat-welcome__title {
font-size: 15px;
font-weight: 600;
color: var(--text, #eee);
margin: 0 0 6px;
}
.chat-welcome__hint {
font-size: 13px;
color: var(--text-3, #555);
margin: 0;
}
/* ── Input Bar ─────────────────────────────── */
.chat-pane-input-bar {
flex-shrink: 0;
border-top: 1px solid var(--border, #2a2a2e);
background: var(--bg-secondary, #151517);
padding: 8px 12px;
}
.chat-pane-input-wrap {
display: flex;
align-items: flex-end;
gap: 6px;
background: var(--bg, #0e0e10);
border: 1px solid var(--border, #2a2a2e);
border-radius: 8px;
padding: 6px 8px;
transition: border-color 0.15s;
}
.chat-pane-input-wrap:focus-within {
border-color: var(--accent, #b38a4e);
}
.chat-pane-input {
flex: 1;
min-height: 20px;
max-height: 160px;
overflow-y: auto;
font-size: 13px;
color: var(--text, #eee);
line-height: 1.5;
}
/* CM6 editor inside chat-pane-input */
.chat-pane-input .cm-editor {
max-height: 160px;
overflow-y: auto;
font-size: 13px;
}
.chat-pane-input .cm-editor .cm-content {
padding: 0;
}
.chat-pane-input .cm-editor .cm-line {
padding: 0;
}
.chat-pane-input .cm-editor.cm-focused {
outline: none;
}
/* Textarea fallback */
.chat-pane-input textarea {
width: 100%;
min-height: 20px;
max-height: 160px;
background: transparent;
border: none;
color: var(--text, #eee);
font-size: 13px;
font-family: inherit;
line-height: 1.5;
resize: none;
outline: none;
padding: 0;
}
/* ── Send Button ───────────────────────────── */
.chat-pane-send {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
background: none;
border: none;
border-radius: 6px;
color: var(--accent, #b38a4e);
cursor: pointer;
transition: background 0.15s, color 0.15s;
}
.chat-pane-send:hover {
background: var(--accent-dim, rgba(179, 138, 78, 0.15));
color: var(--accent-hover, #c9a05e);
}
.chat-pane-send:disabled {
opacity: 0.3;
cursor: not-allowed;
}
/* ── Toolbar ───────────────────────────────── */
.chat-pane-toolbar {
margin-top: 6px;
}
.chat-pane-toolbar:empty {
display: none;
margin: 0;
}

View File

@@ -1,288 +0,0 @@
/* ==========================================
Editor Surface (v0.21.5)
IDE-like layout: file tree | code + chat
========================================== */
/* ── Header ──────────────────────────────── */
.editor-header {
display: flex; align-items: center; justify-content: space-between;
padding: 6px 12px; gap: 8px;
font-size: 13px; color: var(--text-secondary);
border-bottom: 1px solid var(--border);
min-height: 36px; box-sizing: border-box;
}
.editor-header-left { display: flex; align-items: center; gap: 8px; min-width: 0; }
.editor-ws-name { font-weight: 600; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.editor-branch { font-size: 12px; color: var(--text-tertiary); white-space: nowrap; }
.editor-header-right { display: flex; align-items: center; gap: 4px; }
.editor-hdr-btn {
background: none; border: none; color: var(--text-secondary);
cursor: pointer; padding: 4px; border-radius: 4px;
display: flex; align-items: center;
}
.editor-hdr-btn:hover { background: var(--hover); color: var(--text-primary); }
.editor-hdr-label { font-size: 12px; margin-left: 3px; }
.editor-hdr-sep { width: 1px; height: 16px; background: var(--border); margin: 0 2px; }
/* Chat toggle */
.editor-chat-toggle.active { color: var(--accent); }
/* Export dropdown */
.editor-export-wrap { position: relative; }
.editor-export-menu {
display: none; position: absolute; right: 0; top: 100%;
background: var(--bg-primary); border: 1px solid var(--border);
border-radius: 6px; padding: 4px 0; z-index: 100;
box-shadow: 0 4px 16px rgba(0,0,0,0.2); min-width: 160px;
}
.editor-export-menu.open { display: block; }
.editor-export-item {
display: block; width: 100%; padding: 6px 12px; font-size: 13px;
background: none; border: none; text-align: left; cursor: pointer;
color: var(--text-primary);
}
.editor-export-item:hover { background: var(--hover); }
/* ── File Tree (sidebar-content region) ──── */
.editor-file-tree {
flex: 1; overflow-y: auto; overflow-x: hidden;
font-size: 13px; user-select: none;
display: flex; flex-direction: column;
}
.editor-tree-header {
display: flex; align-items: center; justify-content: space-between;
padding: 6px 8px; flex-shrink: 0;
border-bottom: 1px solid var(--border);
}
.editor-tree-title { font-size: 11px; font-weight: 600; text-transform: uppercase; color: var(--text-tertiary); letter-spacing: 0.5px; }
.editor-tree-add {
background: none; border: none; color: var(--text-tertiary);
cursor: pointer; padding: 2px; border-radius: 4px;
display: flex; align-items: center;
}
.editor-tree-add:hover { background: var(--hover); color: var(--accent); }
.editor-tree-content { flex: 1; overflow-y: auto; padding: 4px 0; }
.editor-file-tree.drag-over { outline: 2px dashed var(--accent, #5865f2); outline-offset: -2px; background: rgba(88,101,242,0.05); }
.editor-tree-row {
display: flex; align-items: center; gap: 4px;
padding: 3px 8px; cursor: pointer;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
border-radius: 4px; margin: 0 4px;
}
.editor-tree-row:hover { background: var(--hover); }
.editor-tree-row.active { background: var(--active-bg, rgba(59,130,246,0.12)); color: var(--accent); }
.editor-tree-arrow { width: 14px; text-align: center; font-size: 10px; color: var(--text-tertiary); flex-shrink: 0; }
.editor-tree-arrow.expanded { /* already rotated via character */ }
.editor-tree-icon { flex-shrink: 0; font-size: 14px; line-height: 1; }
.editor-tree-name { overflow: hidden; text-overflow: ellipsis; }
/* Git status indicators (v0.21.6) */
.editor-tree-row.git-modified .editor-tree-name { color: var(--warning, #e5a50a); }
.editor-tree-row.git-added .editor-tree-name { color: var(--success, #22c55e); }
.editor-tree-row.git-untracked .editor-tree-name { color: var(--text-tertiary); font-style: italic; }
.editor-tree-row.git-deleted .editor-tree-name { color: var(--error, #ef4444); text-decoration: line-through; }
.editor-tree-row.git-modified::after,
.editor-tree-row.git-added::after,
.editor-tree-row.git-untracked::after {
font-size: 10px; margin-left: auto; padding-right: 4px; flex-shrink: 0;
color: var(--text-tertiary);
}
.editor-tree-row.git-modified::after { content: 'M'; color: var(--warning, #e5a50a); }
.editor-tree-row.git-added::after { content: 'A'; color: var(--success, #22c55e); }
.editor-tree-row.git-untracked::after { content: 'U'; }
.editor-tree-loading, .editor-tree-empty, .editor-tree-error {
padding: 16px; text-align: center; color: var(--text-tertiary); font-size: 12px;
}
/* ── Main Split Layout ───────────────────── */
.editor-main {
display: flex; flex: 1; min-height: 0; overflow: hidden;
}
.editor-left-pane {
display: flex; flex-direction: column; min-width: 200px; overflow: hidden;
}
.editor-right-pane {
display: flex; flex-direction: column; min-width: 200px; overflow: hidden;
border-left: 1px solid var(--border);
}
/* Resize handle */
.editor-split-handle {
width: 5px; cursor: col-resize; flex-shrink: 0;
background: transparent; position: relative; z-index: 5;
}
.editor-split-handle:hover,
.editor-split-handle:active {
background: var(--accent);
opacity: 0.3;
}
/* ── Tab Bar ─────────────────────────────── */
.editor-tab-bar {
display: flex; overflow-x: auto; overflow-y: hidden;
border-bottom: 1px solid var(--border);
min-height: 32px; flex-shrink: 0;
scrollbar-width: none;
}
.editor-tab-bar::-webkit-scrollbar { height: 0; }
.editor-tab {
display: flex; align-items: center; gap: 4px;
padding: 4px 10px; font-size: 12px;
cursor: pointer; white-space: nowrap;
border-right: 1px solid var(--border);
color: var(--text-secondary);
flex-shrink: 0; max-width: 180px;
position: relative;
}
.editor-tab:hover { background: var(--hover); }
.editor-tab.active {
background: var(--bg-primary);
color: var(--text-primary);
border-bottom: 2px solid var(--accent);
}
.editor-tab.modified .editor-tab-name { font-style: italic; }
.editor-tab-icon { font-size: 13px; flex-shrink: 0; }
.editor-tab-name { overflow: hidden; text-overflow: ellipsis; }
.editor-tab-modified { color: var(--accent); font-size: 10px; margin-left: 2px; }
.editor-tab-close {
background: none; border: none; color: var(--text-tertiary);
cursor: pointer; font-size: 11px; padding: 0 2px;
border-radius: 3px; opacity: 0; transition: opacity 0.1s;
margin-left: 4px;
}
.editor-tab:hover .editor-tab-close { opacity: 1; }
.editor-tab-close:hover { background: var(--hover); color: var(--text-primary); }
/* ── Code Editor Area ────────────────────── */
.editor-code-area {
flex: 1; min-height: 0; position: relative; overflow: hidden;
}
.editor-cm-wrap {
position: absolute; inset: 0; overflow: hidden;
}
.editor-cm-wrap .cm-editor { height: 100%; }
.editor-cm-wrap .cm-scroller { overflow: auto; }
/* Textarea fallback */
.editor-textarea-fallback {
width: 100%; height: 100%; resize: none; border: none; outline: none;
background: var(--bg-primary); color: var(--text-primary);
font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
font-size: 13px; line-height: 1.5;
padding: 8px 12px; box-sizing: border-box;
tab-size: 4;
}
/* Welcome screen */
.editor-welcome {
position: absolute; inset: 0;
display: flex; align-items: center; justify-content: center;
}
.editor-welcome-inner { text-align: center; color: var(--text-tertiary); }
.editor-welcome-inner p { margin: 8px 0; font-size: 14px; }
.editor-welcome-hint { font-size: 12px; opacity: 0.6; }
.editor-welcome-hint kbd {
background: var(--hover); border: 1px solid var(--border);
border-radius: 3px; padding: 1px 5px; font-size: 11px;
font-family: inherit;
}
/* ── Chat Panel (right pane) ─────────────── */
.editor-chat-header {
padding: 6px 12px; font-size: 12px; font-weight: 600;
color: var(--text-secondary); border-bottom: 1px solid var(--border);
flex-shrink: 0;
}
.editor-chat-messages {
flex: 1; overflow-y: auto; min-height: 0;
}
/* Inherit chat message styles when embedded */
.editor-chat-messages .messages { height: auto; overflow: visible; }
.editor-chat-input { flex-shrink: 0; max-height: 140px; overflow: hidden; }
/* Inherit input-area styles — constrain for narrow pane */
.editor-chat-input .input-area { border-top: 1px solid var(--border); padding: 0 8px 8px; }
.editor-chat-input .input-wrap { max-width: none; }
.editor-chat-input .input-wrap textarea,
.editor-chat-input #messageInputWrap .cm-editor { max-height: 80px; padding: 8px; font-size: 13px; }
.editor-chat-input .input-meta { min-height: 0; padding: 2px 4px 0; }
.editor-chat-input .input-toolbar { gap: 2px; }
.editor-chat-input .input-toolbar button { padding: 4px; }
/* ── Status Bar (footer) ─────────────────── */
.editor-status-bar {
display: flex; align-items: center; gap: 8px;
padding: 2px 12px; font-size: 11px;
color: var(--text-tertiary);
border-top: 1px solid var(--border);
min-height: 22px; flex-shrink: 0;
background: var(--bg-secondary);
}
.editor-status-sep { opacity: 0.3; }
.editor-status-right { margin-left: auto; display: flex; gap: 8px; }
.editor-status-branch { font-size: 11px; }
.editor-status-file { max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.editor-status-save { font-size: 11px; }
.editor-status-save.unsaved { color: var(--warning, #e5a50a); }
.editor-status-words { font-size: 11px; }
/* ── Context Menu ────────────────────────── */
.editor-ctx-menu {
position: fixed; z-index: 1000;
background: var(--bg-primary); border: 1px solid var(--border);
border-radius: 6px; padding: 4px 0;
box-shadow: 0 4px 16px rgba(0,0,0,0.2);
min-width: 120px; font-size: 13px;
}
.editor-ctx-item {
padding: 6px 12px; cursor: pointer;
color: var(--text-primary);
}
.editor-ctx-item:hover { background: var(--hover); }
/* ── Quick Open Overlay ──────────────────── */
.editor-quick-open {
position: fixed; inset: 0; z-index: 2000;
background: rgba(0,0,0,0.4);
display: flex; align-items: flex-start; justify-content: center;
padding-top: 15vh;
}
.editor-qo-dialog {
background: var(--bg-primary); border: 1px solid var(--border);
border-radius: 8px; width: 460px; max-width: 90vw;
box-shadow: 0 8px 32px rgba(0,0,0,0.3);
overflow: hidden;
}
.editor-qo-input {
width: 100%; padding: 10px 14px; font-size: 14px;
border: none; outline: none; box-sizing: border-box;
background: var(--bg-primary); color: var(--text-primary);
border-bottom: 1px solid var(--border);
}
.editor-qo-results { max-height: 300px; overflow-y: auto; }
.editor-qo-row {
padding: 6px 14px; cursor: pointer; font-size: 13px;
display: flex; align-items: center; gap: 6px;
color: var(--text-primary);
}
.editor-qo-row:hover { background: var(--hover); }
.editor-qo-icon { font-size: 14px; flex-shrink: 0; }
/* ── Mobile: single pane ─────────────────── */
@media (max-width: 768px) {
.editor-main { flex-direction: column; }
.editor-left-pane { flex: 1 !important; min-width: 0; }
.editor-right-pane { min-width: 0; border-left: none; border-top: 1px solid var(--border); max-height: 40vh; }
.editor-split-handle { display: none; }
}

535
src/css/editor-surface.css Normal file
View File

@@ -0,0 +1,535 @@
/* ==========================================
Chat Switchboard — Editor Surface (v0.25.0)
==========================================
Replaces editor-mode.css for the pane-based editor.
Covers: topbar, bootstrap, and component-specific
overrides within the editor context.
========================================== */
/* ── Surface Shell ─────────────────────────── */
.surface-editor {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
background: var(--bg, #0e0e10);
}
/* ── Topbar ────────────────────────────────── */
.editor-topbar {
display: flex;
align-items: center;
gap: 8px;
padding: 0 12px;
height: 40px;
flex-shrink: 0;
background: var(--bg-secondary, #151517);
border-bottom: 1px solid var(--border, #2a2a2e);
font-size: 13px;
position: relative;
z-index: 20;
}
.editor-topbar-back {
display: flex;
align-items: center;
gap: 4px;
color: var(--text-3, #777);
text-decoration: none;
font-size: 12px;
font-weight: 500;
padding: 4px 8px;
border-radius: 4px;
transition: color 0.15s, background 0.15s;
}
.editor-topbar-back:hover {
color: var(--text, #eee);
background: var(--bg-tertiary, #1e1e22);
}
.editor-topbar-sep {
width: 1px;
height: 18px;
background: var(--border, #2a2a2e);
}
.editor-topbar-name {
font-size: 13px;
font-weight: 600;
color: var(--text, #eee);
}
/* ── Workspace Selector ────────────────────── */
.editor-ws-selector {
position: relative;
}
.editor-ws-selector-btn {
display: flex;
align-items: center;
gap: 6px;
background: none;
border: 1px solid transparent;
color: var(--text, #eee);
font-size: 13px;
font-weight: 600;
font-family: inherit;
padding: 4px 8px;
border-radius: 4px;
cursor: pointer;
transition: border-color 0.15s, background 0.15s;
}
.editor-ws-selector-btn:hover {
border-color: var(--border, #2a2a2e);
background: var(--bg-tertiary, #1e1e22);
}
.editor-ws-dropdown {
display: none;
position: absolute;
top: 100%;
left: 0;
margin-top: 4px;
background: var(--bg-secondary, #1a1a1e);
border: 1px solid var(--border, #2a2a2e);
border-radius: 8px;
min-width: 220px;
max-height: 320px;
overflow-y: auto;
z-index: 1000;
box-shadow: 0 4px 16px rgba(0,0,0,0.4);
padding: 4px 0;
}
.editor-ws-dropdown.open { display: block; }
.editor-ws-list {
max-height: 240px;
overflow-y: auto;
}
.editor-ws-dropdown-item {
display: block;
width: 100%;
text-align: left;
background: none;
border: none;
color: var(--text, #eee);
font-size: 12px;
font-family: inherit;
padding: 8px 12px;
cursor: pointer;
transition: background 0.1s;
}
.editor-ws-dropdown-item:hover {
background: var(--bg-tertiary, #1e1e22);
}
.editor-ws-dropdown-item.active {
color: var(--accent, #b38a4e);
font-weight: 600;
}
.editor-ws-dropdown-divider {
height: 1px;
background: var(--border, #2a2a2e);
margin: 4px 0;
}
.editor-ws-new {
display: flex;
align-items: center;
gap: 6px;
color: var(--accent, #b38a4e);
}
.editor-topbar-branch {
display: flex;
align-items: center;
gap: 4px;
background: var(--purple-dim, rgba(160, 120, 255, 0.1));
padding: 2px 8px;
border-radius: 4px;
}
.editor-topbar-branch-text {
font-size: 11px;
font-weight: 600;
color: var(--purple, #a078ff);
font-family: var(--mono, 'SF Mono', monospace);
}
/* ── Body ──────────────────────────────────── */
.editor-body {
flex: 1;
min-height: 0;
overflow: hidden;
}
/* ── Bootstrap (no workspace) ──────────────── */
.editor-bootstrap {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.editor-bootstrap-card {
text-align: center;
padding: 40px;
background: var(--bg-secondary, #151517);
border: 1px solid var(--border, #2a2a2e);
border-radius: 12px;
max-width: 360px;
}
.editor-bootstrap-input {
width: 100%;
padding: 8px 12px;
background: var(--bg, #0e0e10);
border: 1px solid var(--border, #2a2a2e);
border-radius: 6px;
color: var(--text, #eee);
font-size: 13px;
font-family: inherit;
outline: none;
margin-bottom: 12px;
box-sizing: border-box;
}
.editor-bootstrap-input:focus {
border-color: var(--accent, #b38a4e);
}
.editor-bootstrap-btn {
width: 100%;
padding: 10px 16px;
background: var(--accent, #b38a4e);
color: #fff;
border: none;
border-radius: 6px;
font-size: 13px;
font-weight: 600;
font-family: inherit;
cursor: pointer;
transition: opacity 0.15s;
}
.editor-bootstrap-btn:hover { opacity: 0.9; }
.editor-bootstrap-btn:disabled { opacity: 0.5; cursor: not-allowed; }
/* Workspace list in bootstrap */
.editor-bootstrap-ws-item {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 10px 12px;
background: var(--bg, #0e0e10);
border: 1px solid var(--border, #2a2a2e);
border-radius: 6px;
color: var(--text, #eee);
font-size: 13px;
font-family: inherit;
cursor: pointer;
transition: border-color 0.15s, background 0.15s;
margin-bottom: 6px;
text-align: left;
}
.editor-bootstrap-ws-item:hover {
border-color: var(--accent, #b38a4e);
background: var(--bg-tertiary, #1e1e22);
}
.editor-bootstrap-ws-name {
font-weight: 600;
}
.editor-bootstrap-ws-date {
font-size: 11px;
color: var(--text-3, #777);
}
/* User menu in editor topbar — uses user-menu.css base styles.
No overrides needed: user-menu.css defaults to drop-down (topbar) mode.
Sidebar context flipped via .sidebar parent selector in user-menu.css. */
/* ── FileTree overrides (in editor context) ── */
.surface-editor .file-tree {
height: 100%;
display: flex;
flex-direction: column;
border-right: 1px solid var(--border, #2a2a2e);
}
.surface-editor .file-tree-header {
display: flex;
align-items: center;
gap: 6px;
padding: 8px 12px;
border-bottom: 1px solid var(--border, #2a2a2e);
}
.surface-editor .file-tree-title {
font-size: 11px;
font-weight: 600;
color: var(--text-2, #999);
text-transform: uppercase;
letter-spacing: 0.4px;
flex: 1;
}
.surface-editor .file-tree-items {
flex: 1;
overflow-y: auto;
padding: 4px 0;
}
.surface-editor .file-tree-row {
display: flex;
align-items: center;
gap: 4px;
padding: 3px 8px;
cursor: pointer;
font-size: 12px;
color: var(--text-2, #999);
transition: background 0.1s;
}
.surface-editor .file-tree-row:hover {
background: var(--bg-tertiary, #1e1e22);
}
.surface-editor .file-tree-row.active {
background: var(--accent-dim, rgba(179, 138, 78, 0.15));
color: var(--text, #eee);
}
.surface-editor .file-tree-arrow {
width: 12px;
font-size: 10px;
color: var(--text-3, #555);
text-align: center;
}
.surface-editor .file-tree-icon {
font-size: 13px;
width: 18px;
text-align: center;
}
.surface-editor .file-tree-name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Git status indicators */
.surface-editor .file-tree-row.git-modified .file-tree-name { color: var(--warning, #e5a842); }
.surface-editor .file-tree-row.git-added .file-tree-name { color: var(--success, #4caf50); }
.surface-editor .file-tree-row.git-untracked .file-tree-name { color: var(--text-3, #555); font-style: italic; }
.surface-editor .file-tree-row.git-deleted .file-tree-name { color: var(--danger, #f44336); text-decoration: line-through; }
/* Context menu */
.file-tree-ctx-menu {
position: fixed;
background: var(--bg-secondary, #1a1a1e);
border: 1px solid var(--border, #2a2a2e);
border-radius: 6px;
padding: 4px 0;
min-width: 120px;
z-index: 1000;
box-shadow: 0 4px 12px rgba(0,0,0,0.4);
}
.file-tree-ctx-item {
padding: 6px 12px;
font-size: 12px;
color: var(--text, #eee);
cursor: pointer;
}
.file-tree-ctx-item:hover {
background: var(--bg-tertiary, #1e1e22);
}
/* ── CodeEditor overrides ──────────────────── */
.surface-editor .code-editor {
height: 100%;
display: flex;
flex-direction: column;
}
.surface-editor .code-editor-tabs {
display: flex;
align-items: center;
gap: 0;
background: var(--bg-secondary, #151517);
border-bottom: 1px solid var(--border, #2a2a2e);
height: 32px;
overflow-x: auto;
flex-shrink: 0;
}
.surface-editor .code-editor-tabs::-webkit-scrollbar { height: 0; }
.surface-editor .code-editor-tab {
display: flex;
align-items: center;
gap: 4px;
padding: 0 12px;
height: 100%;
font-size: 12px;
color: var(--text-3, #777);
cursor: pointer;
border-right: 1px solid var(--border, #2a2a2e);
transition: background 0.1s;
white-space: nowrap;
}
.surface-editor .code-editor-tab:hover { background: var(--bg-tertiary, #1e1e22); }
.surface-editor .code-editor-tab.active { color: var(--text, #eee); background: var(--bg, #0e0e10); }
.surface-editor .code-editor-tab.modified .code-editor-tab-modified { color: var(--warning, #e5a842); }
.surface-editor .code-editor-tab-icon { font-size: 12px; }
.surface-editor .code-editor-tab-modified { font-size: 10px; color: var(--text-3); }
.surface-editor .code-editor-tab-close {
background: none;
border: none;
color: var(--text-3, #555);
font-size: 12px;
cursor: pointer;
padding: 0 2px;
margin-left: 4px;
border-radius: 2px;
line-height: 1;
}
.surface-editor .code-editor-tab-close:hover {
background: var(--danger-dim, rgba(244, 67, 54, 0.15));
color: var(--danger, #f44336);
}
.surface-editor .code-editor-content {
flex: 1;
min-height: 0;
overflow: hidden;
position: relative;
}
.surface-editor .code-editor-welcome {
height: 100%;
}
.surface-editor .code-editor-cm-wrap {
height: 100%;
overflow: auto;
}
.surface-editor .code-editor-cm-wrap .cm-editor {
height: 100%;
}
.surface-editor .code-editor-statusbar {
display: flex;
align-items: center;
gap: 16px;
padding: 0 12px;
height: 24px;
flex-shrink: 0;
background: var(--bg-secondary, #151517);
border-top: 1px solid var(--border, #2a2a2e);
font-size: 11px;
color: var(--text-3, #777);
font-family: var(--mono, 'SF Mono', monospace);
}
.surface-editor .code-editor-textarea-fallback {
width: 100%;
height: 100%;
background: var(--bg, #0e0e10);
color: var(--text, #eee);
border: none;
padding: 12px;
font-family: var(--mono, 'SF Mono', monospace);
font-size: 13px;
resize: none;
outline: none;
box-sizing: border-box;
}
/* ── Tabbed assist pane overrides ──────────── */
.surface-editor .pane-tabbed {
border-left: 1px solid var(--border, #2a2a2e);
}
/* ChatPane in editor tabbed pane */
.surface-editor .chat-pane {
position: absolute;
inset: 0;
}
/* Notes in editor pane */
.surface-editor .note-editor {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
overflow: hidden;
}
.surface-editor .note-editor-list-view {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
.surface-editor .notes-list {
flex: 1;
overflow-y: auto;
}
/* Compact notes toolbar for narrow pane */
.surface-editor .notes-toolbar {
display: flex;
flex-wrap: wrap;
gap: 4px;
padding: 6px 8px;
border-bottom: 1px solid var(--border, #2a2a2e);
}
.surface-editor .notes-toolbar .btn-small {
font-size: 11px;
padding: 3px 6px;
}
.surface-editor .notes-search-row {
padding: 4px 8px;
}
.surface-editor .notes-filter-row {
padding: 2px 8px 4px;
display: flex;
gap: 4px;
}
.surface-editor .notes-filter-select {
font-size: 11px;
flex: 1;
min-width: 0;
}

167
src/css/pane-container.css Normal file
View File

@@ -0,0 +1,167 @@
/* ==========================================
Chat Switchboard — Pane Container
==========================================
v0.25.0: Styles for the multi-pane layout system.
Covers: pane container, leaf panes, tabbed panes,
drag handles, and tab bars.
========================================== */
/* ── Container ─────────────────────────────── */
.pane-container {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
/* ── Split ─────────────────────────────────── */
.pane-split--horizontal {
display: flex;
flex-direction: row;
height: 100%;
overflow: hidden;
}
.pane-split--vertical {
display: flex;
flex-direction: column;
width: 100%;
overflow: hidden;
}
/* ── Leaf Pane ─────────────────────────────── */
.pane-leaf {
display: flex;
flex-direction: column;
overflow: hidden;
position: relative;
box-sizing: border-box;
}
.pane-minimized {
max-width: 0 !important;
max-height: 0 !important;
padding: 0 !important;
border: none !important;
overflow: hidden !important;
}
/* ── Tabbed Pane ───────────────────────────── */
.pane-tabbed {
display: flex;
flex-direction: column;
overflow: hidden;
box-sizing: border-box;
}
/* Tab Bar */
.pane-tab-bar {
display: flex;
align-items: center;
gap: 0;
background: var(--bg-secondary, #1a1a1e);
border-bottom: 1px solid var(--border, #2a2a2e);
flex-shrink: 0;
height: 32px;
padding: 0 4px;
overflow-x: auto;
overflow-y: hidden;
}
.pane-tab-bar::-webkit-scrollbar { height: 0; }
.pane-tab-btn {
background: none;
border: none;
color: var(--text-3, #777);
font-size: 11px;
font-weight: 600;
font-family: inherit;
padding: 6px 12px;
cursor: pointer;
border-bottom: 2px solid transparent;
transition: color 0.15s, border-color 0.15s;
white-space: nowrap;
text-transform: uppercase;
letter-spacing: 0.3px;
}
.pane-tab-btn:hover {
color: var(--text, #eee);
}
.pane-tab-btn--active {
color: var(--accent, #b38a4e);
border-bottom-color: var(--accent, #b38a4e);
}
/* Tab Content */
.pane-tab-content {
flex: 1;
min-height: 0;
min-width: 0;
overflow: hidden;
position: relative;
}
.pane-tab-panel {
position: absolute;
inset: 0;
overflow: hidden;
}
/* When panel is hidden (inactive tab), override absolute positioning */
.pane-tab-panel[style*="display: none"] {
position: absolute;
}
/* ── Drag Handle ───────────────────────────── */
.pane-handle {
flex-shrink: 0;
background: var(--border, #2a2a2e);
transition: background 0.15s;
z-index: 10;
}
.pane-handle--horizontal {
width: 4px;
cursor: col-resize;
}
.pane-handle--vertical {
height: 4px;
cursor: row-resize;
}
.pane-handle:hover,
.pane-handle--active {
background: var(--accent, #b38a4e);
}
/* ── Responsive ────────────────────────────── */
@media (max-width: 768px) {
/* On mobile, splits collapse to vertical stack */
.pane-split--horizontal {
flex-direction: column;
}
.pane-handle--horizontal {
width: 100%;
height: 4px;
cursor: row-resize;
}
/* Hide non-primary panes on mobile */
.pane-split--horizontal > .pane:not(:first-child) {
display: none;
}
.pane-split--horizontal > .pane-handle {
display: none;
}
}

41
src/css/tool-grants.css Normal file
View File

@@ -0,0 +1,41 @@
/* v0.25.0: Tool grants section in persona form */
.tool-grants-list {
border: 1px solid var(--border, #2a2a2e);
border-radius: 6px;
padding: 8px;
background: var(--bg, #0e0e10);
}
.tool-grants-category {
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--text-3, #777);
padding: 6px 0 2px;
margin-top: 4px;
}
.tool-grants-category:first-child {
margin-top: 0;
padding-top: 0;
}
.tool-grants-item {
display: flex;
align-items: center;
gap: 6px;
padding: 3px 4px;
font-size: 12px;
color: var(--text, #eee);
cursor: pointer;
border-radius: 4px;
}
.tool-grants-item:hover {
background: var(--bg-tertiary, #1e1e22);
}
.tool-grants-item input[type="checkbox"] {
margin: 0;
}

162
src/css/user-menu.css Normal file
View File

@@ -0,0 +1,162 @@
/* ==========================================
Chat Switchboard — UserMenu Component CSS
==========================================
v0.25.0-cs11.1: Self-contained styles for the UserMenu
component. Works in two contexts:
1. Sidebar (flyout pops UP) — default in .sidebar
2. Topbar (flyout drops DOWN) — default standalone
========================================== */
/* ── Wrapper ───────────────────────────────── */
.user-menu-wrap {
position: relative;
display: flex;
align-items: center;
}
/* ── Trigger Button ────────────────────────── */
.user-menu-wrap .user-btn {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 8px;
border-radius: var(--radius, 6px);
background: none;
border: none;
color: var(--text, #eee);
cursor: pointer;
width: 100%;
font-family: inherit;
transition: background 0.15s;
}
.user-menu-wrap .user-btn:hover {
background: var(--bg-hover, rgba(255,255,255,0.06));
}
/* ── Avatar ────────────────────────────────── */
.user-menu-wrap .user-avatar {
width: 28px;
height: 28px;
border-radius: 50%;
background: var(--accent-dim, rgba(179, 138, 78, 0.2));
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 600;
color: var(--accent, #b38a4e);
flex-shrink: 0;
position: relative;
overflow: hidden;
}
.user-menu-wrap .user-avatar-img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 50%;
}
.user-menu-wrap .sb-label {
font-size: 12px;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* ── Flyout (default: drops DOWN for topbar) ─ */
.user-menu-wrap .user-flyout {
display: none;
position: absolute;
top: 100%;
right: 0;
margin-top: 4px;
background: var(--bg-raised, #1a1a1e);
border: 1px solid var(--border-light, #333);
border-radius: var(--radius-lg, 8px);
padding: 4px;
min-width: 170px;
z-index: 200;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
}
.user-menu-wrap .user-flyout.open {
display: block;
}
/* ── Flyout Items ──────────────────────────── */
.user-menu-wrap .flyout-item {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 12px;
border-radius: var(--radius, 6px);
background: none;
border: none;
color: var(--text-2, #999);
cursor: pointer;
font-size: 13px;
font-family: inherit;
width: 100%;
transition: background 0.15s, color 0.15s;
}
.user-menu-wrap .flyout-item:hover {
background: var(--bg-hover, rgba(255,255,255,0.06));
color: var(--text, #eee);
}
.user-menu-wrap .flyout-item svg {
flex-shrink: 0;
opacity: 0.7;
}
.user-menu-wrap .flyout-danger {
color: var(--danger, #f44336);
}
.user-menu-wrap .flyout-danger:hover {
background: var(--danger-dim, rgba(244, 67, 54, 0.1));
color: var(--danger, #f44336);
}
.user-menu-wrap .flyout-divider {
border: none;
height: 1px;
background: var(--border, #2a2a2e);
margin: 4px 0;
}
/* ── Sidebar Context (flyout pops UP) ──────── */
/* When user-menu is inside .sidebar, flip the flyout direction */
.sidebar .user-menu-wrap .user-flyout {
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: 4px;
box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.5);
}
/* Sidebar collapsed: hide label, center avatar */
.sidebar.collapsed .user-menu-wrap .user-btn {
justify-content: center;
padding: 6px 0;
gap: 0;
}
.sidebar.collapsed .user-menu-wrap .sb-label {
display: none;
}
.sidebar.collapsed .user-menu-wrap .user-flyout {
left: 8px;
right: 8px;
}