llm-agent-plugin/src/css/styles.css

1663 lines
51 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

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

/* src/styles.css или куда ты добавляешь стили */
/* CSS переменные, чтобы создать атмосферу Шира из "Властелина колец" */
:root {
/* Общие стили узлов графа */
--node-padding: 10px;
--node-border-radius: 5px;
--node-font-size: 14px;
--node-font-weight: bold;
--node-text-align: center;
/* Переменные для текста */
--font-text-size: 14px;
--font-monospace: 'Roboto Mono', monospace;
--border-color-light: #d3cbbd; /* Светлая граница, землистая */
--border-color-dark: #a99b87; /* Темная граница, землистая */
--background-modifier-form-field: #f5efe1; /* Светлый земляной фон для полей */
--background-modifier-form-field-highlighted: #e4dccf; /* Немного темнее для выделенных полей */
--node-text-color: var(
--text-normal
); /* Используем общую переменную для текста узлов */
}
/* Определение для светлой темы */
.theme-light {
/* Цвета для кнопок и интерактивных элементов (светлая тема) */
--button-primary-background: #5a8f6a; /* Насыщенный ширский зеленый для кнопок */
--button-primary-hover-background: #4a7a5c; /* Темнее для наведения */
--button-primary-text-color: #ffffff; /* Белый текст */
--button-secondary-background: #d9d1bf; /* Светлый землистый для второстепенных кнопок */
--button-secondary-hover-background: #c4bda9; /* Темнее для наведения */
--button-secondary-text-color: #333333; /* Темный текст для второстепенных */
/* Цвета сообщений чата */
--llm-user-border-color: #79a07e; /* Ширский зеленый */
--llm-user-background-color: #e6f2e6; /* Очень светлый ширский зеленый */
--llm-llm-border-color: #b2a27e; /* Нейтральный, землистый оттенок */
--llm-llm-background-color: #f8f3e9; /* Светлый кремовый */
--llm-tool-border-color: #b08d57; /* Древесный коричневый */
--llm-tool-background-color: #fdf4e3; /* Светлый песочный */
--llm-error-border-color: #c25b5b; /* Приглушенный красный */
--llm-error-background-color: #f7e0e0; /* Светлый приглушенный красный */
--llm-assistant-border-color: #9c9c8f; /* Серый камень */
--llm-assistant-background-color: #ecece4; /* Светло-серый, землистый */
/* Переменные для текста (светлая тема) */
--text-normal: #333;
--text-muted: #666;
--background-secondary-alt: #f0f0f0;
--text-accent: #007bff;
}
/* Определение для тёмной темы */
.theme-dark {
/* Цвета для кнопок и интерактивных элементов (темная тема) */
--button-primary-background: #4a7a5c; /* Более глубокий зеленый для темной темы */
--button-primary-hover-background: #3a6a4c;
--button-primary-text-color: #ffffff;
--button-secondary-background: #a99d8b; /* Более темный землистый */
--button-secondary-hover-background: #948d7b;
--button-secondary-text-color: #f0f0f0;
/* Переменные для темной темы, сохраняющие "ширскую" атмосферу */
--llm-user-border-color: #5a8f6a; /* Темнее зеленый */
--llm-user-background-color: #2b3a2d; /* Глубокий зеленый фон */
--llm-llm-border-color: #8c7e60; /* Темный землистый */
--llm-llm-background-color: #3a3227; /* Темный кремовый/коричневый */
--llm-tool-border-color: #806842; /* Темный древесный коричневый */
--llm-tool-background-color: #3b2c1c; /* Глубокий песочный/коричневый */
--llm-error-border-color: #9c4b4b; /* Более глубокий красный */
--llm-error-background-color: #4a2d2d; /* Темный приглушенный красный */
--llm-assistant-border-color: #7c7c70; /* Темный серый камень */
--llm-assistant-background-color: #3a3a35; /* Глубокий серо-землистый */
/* Переменные для текста (темная тема) */
--text-normal: #f0f0f0; /* Светлый текст */
--text-muted: #b0b0b0; /* Светлый приглушенный текст */
--background-secondary-alt: #2a2a2a; /* Темный фон */
--text-accent: #6aa84f; /* Более приглушенный зеленый акцент */
}
.llm-agent-chat-panel .message-type-user {
border: 1px solid var(--llm-user-border-color); /* Цвет для user */
background-color: var(
--llm-user-background-color
); /* Светло-голубой фон для user */
}
.llm-agent-chat-panel .message-type-llm {
border: 1px solid var(--llm-llm-border-color); /* Цвет для llm */
background-color: var(
--llm-llm-background-color
); /* Светло-зеленый фон для llm */
}
.llm-agent-chat-panel .message-type-tool {
border: 1px solid var(--llm-tool-border-color); /* Цвет для tool */
background-color: var(
--llm-tool-background-color
); /* Светло-оранжевый фон для tool */
}
.llm-agent-chat-panel .message-type-error {
border: 1px solid var(--llm-error-border-color); /* Красный цвет для error */
background-color: var(
--llm-error-background-color
); /* Светло-красный фон для error */
}
.llm-agent-chat-panel .message-type-assistant {
border: 1px solid var(--llm-assistant-border-color); /* Цвет для assistant */
background-color: var(
--llm-assistant-background-color
); /* Светло-серый фон для assistant */
}
/* Общие стили для сообщений */
.llm-agent-chat-panel .message {
margin-bottom: 10px;
display: flex; /* Flex-контейнер для всего сообщения */
flex-direction: column; /* Элементы внутри сообщения будут выстраиваться вертикально */
padding: 10px; /* Общие отступы для всего сообщения */
border-radius: 5px;
max-width: 80%; /* Ограничение ширины сообщения */
word-break: break-word; /* Разбиение слов для длинных сообщений */
overflow-wrap: break-word; /* Перенос слов */
}
.llm-agent-chat-panel .message.user {
margin-left: auto; /* Выравнивание по правому краю для пользователя */
}
.llm-agent-chat-panel .message.assistant {
margin-right: auto; /* Выравнивание по левому краю для ассистента, если потребуется */
}
.chat-meta {
margin-bottom: 5px; /* Отступ между мета-информацией и содержимым */
}
.chat-sender-info {
display: flex; /* Делаем sender-info flex-контейнером */
align-items: center; /* Выравнивание иконки и текста по центру */
gap: 8px; /* Расстояние между иконкой и текстом */
}
.chat-message-icon svg {
width: 20px; /* Размер иконки */
height: 20px;
flex-shrink: 0; /* Предотвращает сжатие иконки */
}
.chat-role-label {
font-weight: bold;
font-size: 0.9em;
color: var(--text-muted);
}
.chat-message-content {
font-size: var(--font-text-size);
line-height: 1.5;
color: var(--text-normal);
user-select: text; /* Разрешить выделение текста внутри содержимого */
}
/* ----------------------------------------------- Chat Panel Styles -------------------------------------------------------- */
.llm-agent-chat-panel {
display: flex;
flex-direction: column;
height: 100%;
position: relative;
}
.chat-history {
flex-grow: 1;
overflow-y: auto;
padding: 10px;
-webkit-user-select: text; /* Разрешить выделение для WebKit-браузеров */
-moz-user-select: text; /* Разрешить выделение для Firefox */
user-select: text; /* Стандартное свойство для выделения текста */
scroll-behavior: smooth;
}
/* Стили для inline-кода в сообщениях */
.chat-message-content code {
background-color: var(--background-secondary-alt);
border-radius: 4px;
padding: 2px 4px;
font-family: var(--font-monospace);
font-size: 0.9em;
color: var(--text-accent);
}
/* Стили для блоков кода (pre) */
.chat-message-content pre {
white-space: pre-wrap; /* Сохраняет пробелы и переносит строки, когда это необходимо */
word-break: break-word; /* Разбивает длинные слова, чтобы они помещались в контейнер */
overflow-x: auto; /* Добавляет горизонтальную прокрутку, если содержимое все же не помещается */
}
/* Убедимся, что стили code внутри pre не конфликтуют с родительским pre */
.chat-message-content pre code {
background-color: transparent; /* Убираем фон, так как он уже задан для pre */
}
/* Стиль для форм ввода чата */
.chat-input-form {
display: flex;
padding: 10px;
border-top: 1px solid #eee;
gap: 10px;
}
.command-input {
position: relative;
flex-grow: 1;
}
#message-input {
width: 100%;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
scroll-margin-bottom: 30px; /* Добавляет отступ в 20px снизу при прокрутке к этому элементу */
}
.chat-input-container {
border-top: 1px solid var(--background-modifier-border);
padding: 8px 10px 4px 10px;
position: relative;
/* Добавляем плавность для эффекта Drag-n-Drop */
transition: background-color 0.2s ease, border-color 0.2s ease, border-radius 0.2s ease;
}
/* Состояние при перетаскивании файлов (Drag-n-Drop) над полем чата */
.chat-input-container.drag-over {
border: 2px dashed var(--interactive-accent) !important;
border-top: 2px dashed var(--interactive-accent) !important;
background-color: var(--background-modifier-hover);
border-radius: var(--node-border-radius); /* Используем вашу переменную из :root */
z-index: 10;
}
/* Опционально: Добавляем легкое свечение, чтобы ясно дать понять, что зона активна */
.theme-dark .chat-input-container.drag-over {
box-shadow: 0 0 15px rgba(106, 168, 79, 0.15); /* Ваш --text-accent: #6aa84f */
}
.theme-light .chat-input-container.drag-over {
box-shadow: 0 0 15px rgba(0, 123, 255, 0.15); /* Ваш --text-accent: #007bff */
}
.scroll-container {
overflow-y: auto;
scrollbar-width: thin;
max-height: 70vh;
margin-bottom: 8px;
}
.message-input-editor {
min-height: 20px;
max-height: 200px;
overflow-y: auto;
word-wrap: break-word;
white-space: pre-wrap;
padding: 0; /*8px 0*/ /* Отступы для контента и плейсхолдера */
line-height: 1.5; /* Высота строки для контента и плейсхолдера */
box-sizing: border-box; /* Включаем padding в общую ширину/высоту */
}
/* Скрываем <br> элемент, когда редактор пуст и плейсхолдер активен */
.message-input-editor.is-empty > br {
display: none;
}
.message-input-editor.is-empty::before {
content: attr(data-placeholder);
color: var(--text-muted);
pointer-events: none;
display: block; /* Делаем плейсхолдер блочным элементом, чтобы он занимал место и переносил строки */
}
.message-input-editor[data-placeholder]::before {
content: attr(data-placeholder);
color: var(--text-muted);
/* position: absolute; <-- УДАЛЕНО: Свойство будет применяться только когда .is-empty */
pointer-events: none;
opacity: 0.6;
}
.message-input-editor:not(.is-empty)[data-placeholder]::before,
.message-input-editor:focus[data-placeholder]::before {
display: none;
}
.message-input-editor .reference-box {
display: inline-flex !important;
vertical-align: middle;
margin: 0 1px;
}
.message-input-editor .reference-box:focus {
outline: 2px solid var(--interactive-accent);
outline-offset: 1px;
}
.chat-controls {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 12px;
color: var(--text-muted);
}
.control-buttons-left {
display: flex;
align-items: center;
gap: 8px;
}
.control-buttons-right {
display: flex;
align-items: center;
gap: 8px;
}
.model-select-container {
position: relative;
display: flex; /* Добавляем flex-контейнер */
align-items: center; /* Выравниваем элементы по центру */
gap: 8px; /* Добавляем расстояние между кнопкой и индикатором */
}
.model-select-button {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 8px;
border: none;
border-radius: 8px;
background-color: var(
--button-secondary-background
); /* Используем переменную для второстепенных кнопок */
color: var(
--button-secondary-text-color
); /* Используем переменную для текста второстепенных кнопок */
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.model-select-button:hover {
background-color: var(
--button-secondary-hover-background
); /* Используем переменную для наведения второстепенных кнопок */
filter: brightness(1.1); /* Можно оставить или скорректировать под тему */
}
.model-name {
max-width: 120px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dropdown-icon {
width: 12px;
height: 12px;
flex-shrink: 0;
}
.model-dropdown {
position: absolute;
/* Убираем жесткое bottom: 100%; т.к. позиционирование будет задаваться в JS */
/* bottom: 100%; */
left: 0;
/* right: 0; */ /* Это может привести к растягиванию, лучше оставить auto или задать ширину */
width: max-content; /* Чтобы дропдаун не растягивался на всю ширину родителя */
min-width: 150px; /* Минимальная ширина */
background-color: var(
--background-primary
); /* Предполагается, что --background-primary есть и подходит */
border: 1px solid var(--border-color-dark); /* Используем новую переменную для границы */
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); /* Можно скорректировать тень в соответствии с темой */
z-index: 1000;
/* margin-bottom: 4px; */ /* Это будет задавать JS через top/bottom */
max-height: 200px;
overflow-y: auto;
}
.model-option {
padding: 8px 12px;
cursor: pointer;
font-size: 11px;
color: var(--text-normal);
transition: background-color 0.2s;
}
.model-option:hover {
}
.model-option.selected {
background-color: var(
--background-modifier-selected
); /* Или другой подходящий цвет */
color: var(--text-highlighted); /* Или другой подходящий цвет */
}
.model-option:first-child {
border-radius: 8px 8px 0 0;
}
.model-option:last-child {
border-radius: 0 0 8px 8px;
}
.stop-button, .submit-button {
padding: 4px 10px; /* Восстанавливаем паддинг */
border: none; /* Убираем рамку */
border-radius: 8px;
cursor: pointer;
font-size: 14px;
transition: all 0.2s;
/* Явно переопределяем стили, которые могли быть затронуты */
width: auto; /* Убедимся, что ширина не ограничена */
height: auto; /* Убедимся, что высота не ограничена */
background-color: var(
--button-primary-background
) !important; /* Используем переменную для основного цвета кнопки */
color: var(
--button-primary-text-color
) !important; /* Используем переменную для цвета текста кнопки */
opacity: 1; /* Если .clickable-icon устанавливает opacity */
display: inline-flex; /* Или flex, если нужно выравнивание элементов внутри */
align-items: center; /* Для вертикального выравнивания контента, если display: flex */
justify-content: center; /* Для горизонтального выравнивания контента, если display: flex */
}
.stop-button:hover, .submit-button:hover {
background-color: var(
--button-primary-hover-background
) !important; /* Переменная для наведения */
}
.stop-button:hover:enabled, .submit-button:hover:enabled {
filter: brightness(1.25);
}
.stop-button:disabled, .submit-button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.submit-text {
font-family: system-ui, -apple-system, sans-serif;
}
/* Обновляем стили для suggestions */
.suggestions {
position: absolute;
bottom: 100%;
left: 0;
right: 0;
background-color: var(
--background-primary
); /* Предполагается, что --background-primary есть и подходит */
border: 1px solid var(--border-color-dark); /* Используем новую переменную для границы */
border-radius: 8px;
max-height: 150px;
overflow-y: auto;
z-index: 100;
margin-bottom: 4px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); /* Можно скорректировать тень в соответствии с темой */
}
.suggestion-item {
padding: 8px 12px;
cursor: pointer;
font-size: 12px;
color: var(--text-normal);
transition: background-color 0.2s;
}
.suggestion-item:hover {
}
.suggestion-item.selected {
background-color: var(--background-modifier-selected);
color: var(--text-highlighted);
}
/* Удаляем старые стили для chat-input-form и message-input */
.chat-input-form {
display: none;
}
#message-input {
display: none;
}
/* ----------------------------------------------- Кнопка прокрутки чат-панели до низа --------------------------------------------------- */
/* "Липкая" обертка, которая зависает в самом верху контейнера */
.sticky-btn-wrapper {
position: sticky;
top: 14px;
z-index: 100;
display: flex;
flex-direction: column; /* Кнопки в колонку */
align-items: flex-end; /* Прижать к правому краю */
gap: 8px; /* Расстояние между кнопками */
padding-right: 14px;
height: 0;
width: 100%;
pointer-events: none;
flex-shrink: 0;
/* Скрываем по умолчанию */
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s ease;
}
/* Класс, который добавляется JS, когда есть скролл */
.sticky-btn-wrapper.is-visible {
opacity: 1;
visibility: visible;
}
/* Добавить общий стиль для обеих кнопок и специфичный для новой */
.scroll-to-bottom-btn,
.scroll-to-top-btn {
pointer-events: auto;
border: 2px solid var(--background-primary);
border-radius: 50%;
/* Жестко задаем размеры (например, 40px) */
width: 40px;
height: 40px;
min-width: 40px;
min-height: 40px;
/* Запрещаем flexbox сжимать эти элементы */
flex-shrink: 0;
/* Сбрасываем стандартные паддинги Obsidian */
padding: 0;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: white;
background-color: var(--button-secondary-background); /* По умолчанию тусклее */
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
opacity: 0.8;
}
.scroll-to-bottom-btn:hover,
.scroll-to-top-btn:hover {
opacity: 1;
transform: scale(1.1);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
background-color: var(--button-primary-background) !important;
}
.scroll-to-bottom-btn:active,
.scroll-to-top-btn:active {
transform: scale(0.95);
}
/* Иконки кнопок */
.scroll-to-bottom-btn svg,
.scroll-to-top-btn svg {
width: 18px;
height: 18px;
stroke-width: 3px;
}
/* ----------------------------------------------- Reference System Styles --------------------------------------------------- */
/* Reference Boxes */
.reference-box {
display: inline-flex;
align-items: center;
padding: 2px 6px;
border-radius: 4px;
font-size: 11px;
margin: 0 2px;
cursor: pointer;
user-select: none;
vertical-align: middle;
transition: all 0.2s ease;
}
.reference-box:hover {
opacity: 0.8;
transform: translateY(-1px);
}
.reference-box-icon {
width: 12px;
height: 12px;
margin-right: 4px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
}
.reference-box-name {
font-weight: 500;
white-space: nowrap;
}
/* Файлы - одинарная ссылка @ */
.reference-box.file.single {
background: rgba(100, 150, 255, 0.1);
border: 1px solid rgba(100, 150, 255, 0.3);
color: var(--text-normal);
}
/* Файлы - постоянная ссылка @@ */
.reference-box.file.permanent {
background: rgba(100, 150, 255, 0.2);
border: 1px solid rgba(100, 150, 255, 0.6);
color: var(--text-normal);
font-weight: 600;
}
.reference-box.file.permanent .reference-box-name {
font-weight: 600;
}
/* Перебиваем стиль Obsidian для prompt*/
.reference-box.prompt {
display: inline-flex;
flex-direction: row;
box-shadow: none; /* var(--shadow-l) */
z-index: auto;
position: static;
top: auto;
width: auto;
max-width: none;
max-height: none;
overflow: hidden;
}
/* Промпты - одинарная ссылка # */
.reference-box.prompt.single {
background: rgba(255, 150, 100, 0.1);
border: 1px solid rgba(255, 150, 100, 0.3);
color: var(--text-normal);
}
/* Промпты - постоянная ссылка ## */
.reference-box.prompt.permanent {
background: rgba(238, 122, 69, 0.2);
border: 1px solid rgba(255, 150, 100, 0.6);
color: var(--text-normal);
font-weight: 600;
}
.reference-box.prompt.permanent .reference-box-name {
font-weight: 600;
}
/* Внешние файлы - одинарная ссылка $ */
.reference-box.external.single {
background: rgba(100, 150, 255, 0.1);
border: 1px solid rgba(100, 150, 255, 0.3);
color: var(--text-normal);
}
/* Внешние файлы - постоянная ссылка !$ */
.reference-box.external.permanent {
background: rgba(100, 150, 255, 0.2);
border: 1px solid rgba(100, 150, 255, 0.6);
color: var(--text-normal);
font-weight: 600;
}
/* Reference Autocomplete */
.reference-autocomplete {
/* 200px для 5 элементов, возможно, нужно заменить на расчёт с помощью padding и размером шрифта */
--item-height: 33px; /* высота одного элемента */
--visible-items: 10; /* количество видимых элементов */
position: absolute;
background: var(--background-primary);
border: 1px solid var(--border-color);
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
z-index: 1000;
max-height: calc(var(--item-height) * var(--visible-items));
overflow-y: auto;
min-width: 250px;
max-width: 400px;
}
.reference-option {
display: flex;
align-items: center;
padding: 8px 12px;
cursor: pointer;
font-size: 12px;
color: var(--text-normal);
transition: background-color 0.2s;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.reference-option:hover,
.reference-option.selected {
background-color: var(--background-modifier-hover);
}
.reference-option:last-child {
border-bottom: none;
}
.reference-option-icon {
width: 16px;
height: 16px;
margin-right: 8px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
color: var(--text-muted);
}
.reference-option-name {
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 500;
}
.reference-option-path {
font-size: 10px;
color: var(--text-muted);
margin-left: 8px;
max-width: 150px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* Темная тема */
.theme-dark .reference-autocomplete {
background: var(--background-primary);
border-color: var(--border-color);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.theme-dark .reference-option:hover,
.theme-dark .reference-option.selected {
background-color: rgba(255, 255, 255, 0.1);
}
/* Светлая тема */
.theme-light .reference-autocomplete {
background: #ffffff;
border-color: #e0e0e0;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.theme-light .reference-option:hover,
.theme-light .reference-option.selected {
background-color: rgba(0, 0, 0, 0.05);
}
/* Скроллбар для автокомплита */
.reference-autocomplete::-webkit-scrollbar {
width: 6px;
}
.reference-autocomplete::-webkit-scrollbar-track {
background: transparent;
}
.reference-autocomplete::-webkit-scrollbar-thumb {
background: var(--scrollbar-thumb-bg);
border-radius: 3px;
}
.reference-autocomplete::-webkit-scrollbar-thumb:hover {
background: var(--scrollbar-thumb-bg-hover);
}
/* ----------------------------------------------- Settings Views ------------------------------------------------------------ */
.setting-item.llm-agent-excluded-folder-item {
padding-left: 30px; /* Отступ для элементов списка */
border-left: 2px solid var(--background-modifier-border); /* Разделитель */
margin-bottom: 5px;
margin-top: 5px;
}
.setting-item.llm-agent-excluded-folder-item .setting-item-control {
display: flex;
align-items: center;
gap: 5px;
}
.setting-item.llm-agent-excluded-folder-item .setting-item-control input {
flex-grow: 1; /* Поле ввода занимает все доступное пространство */
}
/* ----------------------------------------------- Obsidian core override ------------------------------------------------------------ */
.status-bar-item {
display: none;
padding: 0;
&.plugin-editor-width-slider {
display: inline-flex;
& .editor-width-slider {
width: 80px !important;
}
& .editor-width-slider-value {
padding: 4px 3px !important;
font-size: 10px !important;
margin: 0 !important;
}
}
}
/* ----------------------------------------------- Graph Panel Styles --------------------------------------------------------------- */
.llm-agent-graph-main {
display: flex;
flex-direction: column;
height: 100%;
}
.upper-content-wrapper {
flex: 1;
display: flex;
overflow: hidden;
}
/* Голосовая панель */
.voice-panel-fixed-bottom {
display: flex;
flex-direction: column;
border-top: 1px solid var(--background-modifier-border);
}
.voice-panel-resizer {
height: 4px;
width: 100%;
cursor: ns-resize;
background-color: var(--divider-color);
flex-shrink: 0;
z-index: 10;
}
.voice-panel-resizer:hover {
background-color: var(--interactive-accent);
}
/* Убедимся, что нижняя панель не перекрывает контент */
.voice-panel-fixed-bottom {
display: flex;
flex-direction: column;
min-height: 50px; /* Минимальная доступная высота */
}
.voice-panel-container {
height: 100%;
display: flex;
flex-direction: column;
user-select: text; /* Разрешает выделение текста */
-webkit-user-select: text; /* Для совместимости с Obsidian/Electron */
}
.voice-body {
flex: 1;
overflow-y: auto;
/* Убираем горизонтальный скролл на уровне контейнера */
overflow-x: hidden;
background-color: var(--background-primary);
border: 1px inset var(--background-modifier-border);
margin: 4px;
padding: 8px;
user-select: text;
-webkit-user-select: text;
cursor: text;
/* Добавляем перенос слов для обычного текста */
word-wrap: break-word;
overflow-wrap: break-word;
}
.voice-body pre {
white-space: pre-wrap; /* Включает перенос строк в pre */
word-wrap: break-word; /* Перенос длинных слов */
word-break: break-word;
overflow-x: hidden; /* Запрет горизонтальной прокрутки */
background-color: var(--background-secondary-alt);
padding: 10px;
border-radius: 4px;
max-width: 100%; /* Чтобы блок не расширял родителя */
box-sizing: border-box;
}
.voice-body code {
white-space: pre-wrap; /* Перенос для inline и блочного кода */
word-break: break-word;
max-width: 100%;
}
.voice-header {
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 5px;
border-bottom: 1px solid var(--background-modifier-border);
}
.voice-message-block {
border-bottom: 1px solid var(--background-modifier-border);
padding-bottom: 10px;
margin-bottom: 10px;
position: relative; /* Для позиционирования тулсета */
scroll-margin-top: 10px;
}
/* Чтобы у последнего сообщения (самого нижнего) не было линии */
.voice-message-block:last-child {
border-bottom: none;
}
.voice-message-toolset {
display: flex;
gap: 4px;
margin-top: 8px;
transition: opacity 0.2s ease;
}
.voice-tool-btn {
background: transparent;
border: none;
cursor: pointer;
padding: 4px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
color: var(--text-muted);
}
.voice-tool-btn:hover {
background-color: var(--background-modifier-hover);
color: var(--text-normal);
}
.voice-tool-btn svg {
width: 16px;
height: 16px;
}
.v-tabs {
display: flex;
gap: 2px;
}
.v-tab {
padding: 4px 8px;
font-size: 11px;
cursor: pointer;
background: transparent;
border: none;
color: var(--text-muted);
}
.v-tab.active {
color: var(--text-accent);
border-bottom: 2px solid var(--text-accent);
}
/* Кнопки управления голосом */
.v-controls button {
margin-right: 5px;
padding: 4px 10px;
user-select: none;
-webkit-user-select: none;
}
.llm-agent-history-sidebar {
border-right: 1px solid var(--background-modifier-border);
overflow-y: auto;
background-color: var(--background-secondary);
transition: width 0.3s ease, min-width 0.3s ease, border-right 0.3s ease;
min-width: 0;
}
.llm-agent-history-sidebar.expanded {
width: 200px;
min-width: 200px;
}
.llm-agent-history-sidebar.collapsed {
width: 0;
min-width: 0;
border-right: none;
overflow: hidden;
}
.graph-title-generated {
color: var(--text-normal);
}
.graph-title-pending {
color: var(--text-muted);
}
.react-flow__node-default,
.react-flow__node-user,
.react-flow__node-llm,
.react-flow__node-tool,
.react-flow__node-error,
.react-flow__node-assistant {
padding: var(--node-padding);
border-radius: var(--node-border-radius);
text-align: var(--node-text-align);
font-size: var(--node-font-size);
font-weight: var(--node-font-weight);
color: var(--node-text-color);
}
.react-flow__node-user {
border: 1px solid var(--llm-user-border-color);
background-color: var(
--llm-user-background-color
);
}
.react-flow__node-llm {
border: 1px solid var(--llm-llm-border-color);
background-color: var(
--llm-llm-background-color
);
}
.react-flow__node-tool {
border: 1px solid var(--llm-tool-border-color);
background-color: var(
--llm-tool-background-color
);
}
.react-flow__node-error {
border: 1px solid var(--llm-error-border-color);
background-color: var(
--llm-error-background-color
);
}
.react-flow__node-assistant {
border: 1px solid var(--llm-assistant-border-color);
background-color: var(--llm-assistant-background-color);
}
.react-flow__node {
font-size: 12px !important;
padding: 4px 8px !important;
min-width: 100px !important;
max-width: 130px !important;
min-height: 30px !important;
border-radius: 6px !important;
}
.react-flow__node-default {
width: auto !important;
height: auto !important;
}
.react-flow__node.active-node {
border: 2px solid var(--interactive-accent); /* Красная рамка для активного узла */
box-shadow: 0 0 8px var(--interactive-accent); /* Небольшая тень для выделения */
}
/* Стиль для выделенных узлов */
.react-flow__node.selected-node {
border-color: var(--interactive-accent-hover); /* Яркая рамка */
box-shadow: 0 0 0 2px var(--interactive-accent-hover); /* Более заметная тень */
}
/* Node Toolbar: Контейнер для кнопок действий */
.react-flow__node .node-toolbar {
position: absolute;
top: 4px; /* Отступ сверху */
right: 3px; /* <-- ИЗМЕНЕНО: Сдвинуто на 4px правее */
z-index: 10; /* Чтобы кнопки были поверх содержимого узла */
display: flex;
flex-direction: column; /* Вертикальное расположение кнопок */
gap: 1px; /* Отступ между кнопками */
background-color: transparent; /* Прозрачный фон */
padding: 0px; /* Нет внутреннего отступа */
pointer-events: none; /* Изначально игнорировать события мыши */
opacity: 0; /* Изначально скрыт */
transition: opacity 0.2s ease-in-out; /* Плавное появление/исчезновение */
}
/* Показать toolbar при наведении на узел */
.react-flow__node:hover .node-toolbar {
pointer-events: auto; /* Разрешить события мыши при наведении */
opacity: 1; /* Полностью показать */
}
/* Стили для отдельных кнопок действий внутри узла */
.react-flow__node .node-action-button {
background-color: var(--background-secondary-alt); /* Фон как у вторичных кнопок */
border: 1px solid var(--background-modifier-border); /* Граница */
border-radius: 4px; /* Скругленные углы */
padding: 4px; /* <-- ИЗМЕНЕНО: Отступ для соответствия новому размеру иконок */
height: 16px; /* <-- ИЗМЕНЕНО: Уменьшенная высота */
width: 16px; /* <-- ИЗМЕНЕНО: Уменьшенная ширина */
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: var(--text-muted); /* Цвет текста/иконки */
transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
box-shadow: var(--shadow-s); /* Небольшая тень */
flex-shrink: 0; /* Чтобы кнопки не сжимались */
}
.react-flow__node .node-action-button:hover {
background-color: var(--background-secondary); /* <-- ИЗМЕНЕНО: Более плотный фон при наведении */
color: var(--text-normal); /* <-- ИЗМЕНЕНО: Цвет иконки при наведении */
border-color: var(--background-modifier-border); /* <-- ИЗМЕНЕНО: Цвет границы при наведении */
}
/* Удаляем старые стили, которые конфликтуют или больше не нужны */
.react-flow__node button.node-delete-button,
.react-flow__node button.node-regenerate-button {
position: static; /* Сбрасываем абсолютное позиционирование */
bottom: auto; /* Сбрасываем позицию */
left: auto; /* Сбрасываем позицию */
margin-top: 0; /* Сбрасываем внешний отступ */
font-size: 1em; /* Размер шрифта, если используется текст */
}
/* Убеждаемся, что SVG иконка внутри кнопки получает цвет */
.react-flow__node .node-action-button svg {
width: 8px; /* <-- ИЗМЕНЕНО: Размер иконки уменьшен в 2 раза */
height: 8px; /* <-- ИЗМЕНЕНО: Размер иконки уменьшен в 2 раза */
stroke: currentColor; /* Использовать текущий цвет текста для иконки */
}
/* Стиль для рёбер */
/*.react-flow__edge-path {
stroke: var(--background-modifier-border);
stroke-width: 1.5;
}*/
/* Общие стили для глобальных кнопок действий */
.graph-view-toolbar {
position: absolute;
top: 10px;
left: 10px; /* Рядом с кнопкой переключения */
z-index: 50;
display: flex;
flex-direction: column; /* Вертикальное расположение */
gap: 10px; /* Отступ между кнопками */
}
.global-action-button {
background-color: var(--background-secondary-alt);
border: 1px solid var(--background-modifier-border);
height: auto;
border-radius: 8px;
padding: 10px 10px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 1.2em;
color: var(--text-normal);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
transition: background-color 0.2s ease, color 0.2s ease;
}
.global-action-button:hover {
background-color: var(--background-modifier-hover);
color: var(--interactive-accent);
}
/* Tooltip стили для глобальных кнопок */
[data-tooltip]:hover:after {
content: attr(data-tooltip);
position: absolute;
left: calc(100% + 10px); /* Справа от кнопки */
top: 50%;
transform: translateY(-50%);
white-space: nowrap;
background-color: var(--background-modifier-hover);
color: var(--text-normal);
padding: 5px 8px;
border-radius: 4px;
font-size: 0.8em;
z-index: 100; /* Чтобы быть над всем */
}
/* ----------------------------------------------- History Panel ------------------------------------------------------------ */
.llm-agent-history-panel { /* ДОБАВЛЕНО */
position: relative;
height: 100%;
display: flex;
flex-direction: column;
}
.llm-agent-history-panel .history-header { /* ДОБАВЛЕНО */
padding: 10px;
border-bottom: 1px solid var(--background-modifier-border);
}
.llm-agent-history-panel .history-header h3 { /* ДОБАВЛЕНО */
margin: 0 0 10px 0;
}
.llm-agent-history-panel .history-header-buttons { /* ДОБАВЛЕНО */
display: flex;
gap: 8px;
}
.llm-agent-history-panel .new-chat-button, /* ДОБАВЛЕНО */
.llm-agent-history-panel .clear-all-button { /* ДОБАВЛЕНО */
flex: 1;
padding: 8px 12px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
transition: all 0.2s;
}
.llm-agent-history-panel .new-chat-button { /* ДОБАВЛЕНО */
background-color: var(--button-primary-background);
color: var(--button-primary-text-color);
}
.llm-agent-history-panel .new-chat-button:hover { /* ДОБАВЛЕНО */
background-color: var(--button-primary-hover-background);
}
.llm-agent-history-panel .clear-all-button { /* ДОБАВЛЕНО */
background-color: var(--button-secondary-background);
color: var(--button-secondary-text-color);
}
.llm-agent-history-panel .clear-all-button:hover { /* ДОБАВЛЕНО */
background-color: var(--button-secondary-hover-background);
}
.llm-agent-history-panel .chat-list { /* ДОБАВЛЕНО */
overflow-y: auto;
flex: 1;
}
.llm-agent-history-panel .chat-list-item { /* ДОБАВЛЕНО */
padding: 10px;
cursor: pointer;
border-bottom: 1px solid var(--background-modifier-border);
transition: background-color 0.2s;
}
.llm-agent-history-panel .chat-list-item:hover { /* ДОБАВЛЕНО */
background-color: var(--background-modifier-hover);
}
.llm-agent-history-panel .chat-item-content { /* ДОБАВЛЕНО */
display: flex;
justify-content: space-between;
align-items: center;
}
.llm-agent-history-panel .chat-item-text { /* ДОБАВЛЕНО */
flex: 1;
overflow: hidden;
}
.llm-agent-history-panel .truncate { /* ДОБАВЛЕНО */
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.llm-agent-history-panel .chat-item-options-button { /* ДОБАВЛЕНО */
background: none;
border: none;
cursor: pointer;
font-size: 16px;
padding: 4px 8px;
color: var(--text-muted);
border-radius: 4px;
transition: all 0.2s;
}
.llm-agent-history-panel .chat-item-options-button:hover { /* ДОБАВЛЕНО */
background-color: var(--background-modifier-hover);
color: var(--text-normal);
}
.llm-agent-history-panel .pagination-container { /* ДОБАВЛЕНО */
padding: 10px;
border-top: 1px solid var(--background-modifier-border);
}
.llm-agent-history-panel .pagination-buttons { /* ДОБАВЛЕНО */
display: flex;
justify-content: center;
align-items: center;
gap: 4px;
flex-wrap: wrap;
}
.llm-agent-history-panel .pagination-button { /* ДОБАВЛЕНО */
min-width: 32px;
height: 32px;
padding: 4px 8px;
border: 1px solid var(--background-modifier-border);
background-color: var(--background-secondary);
color: var(--text-normal);
border-radius: 4px;
cursor: pointer;
font-size: 12px;
transition: all 0.2s;
}
.llm-agent-history-panel .pagination-button:hover { /* ДОБАВЛЕНО */
background-color: var(--background-modifier-hover);
border-color: var(--interactive-accent);
}
.llm-agent-history-panel .pagination-button.active { /* ДОБАВЛЕНО */
background-color: var(--interactive-accent);
color: var(--text-on-accent);
border-color: var(--interactive-accent);
}
.llm-agent-history-panel .pagination-ellipsis { /* ДОБАВЛЕНО */
padding: 4px 8px;
color: var(--text-muted);
}
/* ----------------------------------------------- Dialog Styles ------------------------------------------------------------ */
/* Общие стили для сообщения в диалоге */
.dialog-message {
margin-bottom: 15px;
font-size: var(--font-text-size);
color: var(--text-normal);
line-height: 1.5;
}
/* Стили для поля ввода в диалоге prompt */
.dialog-input {
width: 100%;
padding: 10px;
margin-bottom: 20px;
border: 1px solid var(--border-color-dark);
border-radius: var(--node-border-radius);
background-color: var(--background-modifier-form-field);
color: var(--text-normal);
font-size: var(--font-text-size);
box-sizing: border-box; /* Учитываем padding и border в общей ширине */
}
.dialog-input:focus {
border-color: var(--interactive-accent);
box-shadow: 0 0 0 1px var(--interactive-accent);
background-color: var(--background-modifier-form-field-highlighted);
outline: none; /* Убираем стандартное свечение фокуса */
}
/* Контейнер для кнопок диалога */
.dialog-buttons {
display: flex;
justify-content: center; /* Центрируем кнопки */
gap: 15px; /* Увеличиваем отступ между кнопками для лучшего вида */
}
/* Стили для всех кнопок в диалоге */
.dialog-buttons button {
padding: 15px 20px; /* Увеличиваем внутренние отступы, чтобы кнопки стали больше */
border: 1px solid transparent; /* Добавляем прозрачную рамку, которую будем переопределять */
border-radius: var(--node-border-radius);
cursor: pointer;
font-size: var(--node-font-size);
transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease; /* Добавляем transition для border-color */
min-width: 100px; /* Добавляем минимальную ширину для единообразия */
font-weight: 500; /* Немного уплотняем шрифт */
}
/* Стили для основной кнопки (OK, Confirm) */
.dialog-buttons button.mod-cta {
background-color: var(--button-primary-background);
color: var(--button-primary-text-color);
border-color: var(--button-primary-hover-background); /* Делаем рамку чуть темнее фона */
}
.dialog-buttons button.mod-cta:hover {
background-color: var(--button-primary-hover-background);
border-color: var(--button-primary-background); /* При наведении рамка может стать светлее */
}
/* Стили для второстепенной кнопки (Cancel) */
.dialog-buttons button:not(.mod-cta) {
background-color: var(--button-secondary-background);
color: var(--button-secondary-text-color);
border-color: var(--border-color-dark); /* Темная рамка для второстепенных кнопок */
}
.dialog-buttons button:not(.mod-cta):hover {
background-color: var(--button-secondary-hover-background);
border-color: var(--border-color-light); /* При наведении рамка может стать светлее */
}
/* ----------------------------------------------- Attachment Boxes --------------------------------------------------------------- */
.message-attachments {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-bottom: 8px;
}
.attachment-box {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 4px 8px;
background-color: var(--background-modifier-border);
border: 1px solid var(--background-modifier-border-hover);
border-radius: 4px;
font-size: 0.9em;
opacity: 0.8;
transition: opacity 0.2s, background-color 0.2s;
}
.attachment-box.clickable {
cursor: pointer;
}
.attachment-box.clickable:hover {
opacity: 1;
background-color: var(--background-modifier-border-hover);
}
.attachment-box .reference-icon {
font-size: 1em;
}
.attachment-box .reference-name {
color: var(--text-muted);
}
/* Прикрепленные файлы в поле ввода */
.attached-files-container {
display: flex;
flex-wrap: wrap;
gap: 6px;
padding: 8px;
border-top: 1px solid var(--background-modifier-border);
}
.attachment-box.removable {
background-color: var(--interactive-normal);
padding-right: 4px;
}
.attachment-box.removable:hover {
background-color: var(--interactive-hover);
}
.attachment-remove {
background: none;
border: none;
color: var(--text-muted);
cursor: pointer;
font-size: 1.2em;
line-height: 1;
padding: 0 4px;
margin-left: 4px;
transition: color 0.2s;
}
.attachment-remove:hover {
color: var(--text-error);
}
/* Кнопка прикрепления файла */
.attach-file-button {
background: none;
border: none;
color: var(--text-muted);
cursor: pointer;
padding: 6px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
transition: background-color 0.2s, color 0.2s;
}
.attach-file-button:hover {
background-color: var(--background-modifier-hover);
color: var(--text-normal);
}
.attach-file-button svg {
width: 20px;
height: 20px;
}
/* ----------------------------------------------- Params UI Styles (Temp & Tokens) --------------------------------------------------------------- */
.param-select-container {
display: flex;
align-items: center;
/*background-color: var(--button-secondary-background);
border: 1px solid var(--border-color-dark);*/
border-radius: 8px;
padding: 2px 6px;
gap: 2px;
}
.param-icon {
font-size: 11px;
color: var(--text-muted);
/*font-weight: bold;*/
}
.param-input {
width: 48px;
background: transparent;
border: none;
color: var(--text-normal);
font-size: 11px;
padding: 0;
outline: none;
text-align: center;
box-shadow: none !important;
}
.param-input::-webkit-inner-spin-button,
.param-input::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
.param-reset-btn {
background: transparent;
border: none;
color: var(--text-muted) !important;
cursor: pointer;
padding: 1px 4px !important;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
height: auto !important;
min-width: 0 !important;
}
.param-reset-btn:hover {
color: var(--text-normal) !important;
background-color: var(--background-modifier-hover);
}
/* ----------------------------------------------- Stop button and dictation --------------------------------------------------------------- */
/* Новая глобальная кнопка отмены генерации (внутри wrapper) */
.global-stop-stream-btn {
pointer-events: auto;
border: 2px solid var(--text-error); /* Красная окантовка для опасности */
border-radius: 8px; /* Квадратная форма с закруглением вместо 50% */
width: 40px;
height: 40px;
min-width: 40px;
min-height: 40px;
flex-shrink: 0;
padding: 0;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: white;
background-color: var(--background-modifier-error); /* Фон красного толка */
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
opacity: 0.8;
}
.global-stop-stream-btn:hover {
opacity: 1;
transform: scale(1.1);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
background-color: var(--text-error) !important;
}
.global-stop-stream-btn:active {
transform: scale(0.95);
}
.global-stop-stream-btn svg {
width: 18px;
height: 18px;
stroke-width: 3px;
fill: currentColor;
}
/* Кнопка диктовки */
.dictation-button {
background: transparent;
border: none;
color: var(--text-muted);
cursor: pointer;
padding: 6px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
transition: background-color 0.2s, color 0.2s, transform 0.2s;
}
.dictation-button:hover {
background-color: var(--background-modifier-hover);
color: var(--text-normal);
}
/* Анимация пульсации при записи */
.dictation-button.pulsing {
animation: dictation-pulse 1.5s infinite;
color: var(--text-error); /* Красный цвет записи */
}
@keyframes dictation-pulse {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.2); opacity: 0.6; }
100% { transform: scale(1); opacity: 1; }
}