logboard/app/static/css/index.css
Sergey Antropoff 46855dc0c7 feat: Улучшения интерфейса и очистка логов
- Удалены избыточные console.log из JavaScript для чистой консоли браузера
- Исправлена проблема с выделением текста в multi-view панелях
- Сохранена функциональность drag & drop для перетаскивания панелей
- Добавлены CSS правила для корректного выделения текста в логах
- Исправлена синтаксическая ошибка в CSS файле

Изменения:
- app/static/js/index.js: удалены логи WebSocket, setupMultiView, createMultiViewPanel, Processing, AJAX Update, applyPanelOrder, Recalculating, Document click event, Container selected/deselected, switchToSingle, openWs
- app/static/css/index.css: добавлены правила user-select для multi-view логов, исправлена синтаксическая ошибка
2025-09-01 19:04:38 +03:00

2676 lines
55 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.

/* THEME TOKENS */
:root{
--bg:#0e0f13; --panel:#151821; --muted:#8b94a8; --accent:#7aa2f7; --ok:#9ece6a; --warn:#e0af68; --err:#f7768e; --fg:#e5e9f0;
--border:#2a2f3a; --tab:#1b2030; --tab-active:#22283a; --chip:#2b3142; --link:#9ab8ff;
--sidebar-width: 280px; --header-height: 60px;
}
:root[data-theme="light"]{
--bg:#f7f9fc; --panel:#ffffff; --muted:#667085; --accent:#3b82f6; --ok:#15803d; --warn:#b45309; --err:#b91c1c; --fg:#0f172a;
--border:#e5e7eb; --tab:#eef2ff; --tab-active:#dbeafe; --chip:#eef2f7; --link:#1d4ed8;
}
*{box-sizing:border-box}
html,body{height:100%; margin: 0; padding: 0;}
body{background:var(--bg);color:var(--fg);font:13px/1.45 ui-monospace,Menlo,Consolas,monospace; overflow: hidden;}
a{color:var(--link)}
/* Modern Layout */
.app-container {
display: flex;
height: 100vh;
overflow: hidden;
}
/* Sidebar */
.sidebar {
width: var(--sidebar-width);
background: var(--panel);
border-right: 1px solid var(--border);
display: flex;
flex-direction: column;
overflow: hidden;
transition: width 0.3s ease, transform 0.3s ease;
}
.sidebar.collapsed {
width: 42px;
}
.sidebar.collapsed .sidebar-header h1,
.sidebar.collapsed .sidebar-header .subtitle,
.sidebar.collapsed .sidebar-controls,
.sidebar.collapsed .container-list {
display: none;
}
/* Миникарточки контейнеров для свернутого sidebar */
.sidebar.collapsed .mini-container-list {
display: flex;
flex-direction: column;
gap: 4px;
padding: 8px 4px;
overflow-y: auto;
flex: 1;
scrollbar-width: thin;
scrollbar-color: var(--border) transparent;
}
/* Всплывающие подсказки для миникарточек */
.mini-container-tooltip {
position: absolute;
background: var(--panel);
border: 1px solid var(--border);
border-radius: 8px;
padding: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
z-index: 1000;
pointer-events: auto;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s ease, visibility 0.2s ease;
max-width: 280px;
min-width: 200px;
font-size: 12px;
line-height: 1.4;
}
.mini-container-tooltip.show {
opacity: 1;
visibility: visible;
}
.mini-container-tooltip-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
font-weight: 600;
color: var(--fg);
}
.mini-container-tooltip-icon {
font-size: 14px;
color: var(--accent);
}
.mini-container-tooltip-name {
font-size: 13px;
font-weight: 600;
color: var(--fg);
margin-bottom: 4px;
}
.mini-container-tooltip-service {
font-size: 11px;
color: var(--muted);
margin-bottom: 6px;
}
.mini-container-tooltip-status {
display: flex;
align-items: center;
gap: 6px;
font-size: 10px;
margin-bottom: 4px;
}
.mini-container-tooltip-status-indicator {
width: 6px;
height: 6px;
border-radius: 50%;
}
.mini-container-tooltip-status-indicator.running { background: var(--ok); }
.mini-container-tooltip-status-indicator.stopped { background: var(--err); }
.mini-container-tooltip-status-indicator.paused { background: var(--warn); }
.mini-container-tooltip-port {
font-size: 10px;
color: var(--muted);
margin-bottom: 4px;
}
.mini-container-tooltip-url {
font-size: 10px;
color: var(--accent);
text-decoration: none;
display: flex;
align-items: center;
gap: 4px;
padding: 2px 4px;
border-radius: 4px;
transition: all 0.2s ease;
cursor: pointer;
}
.mini-container-tooltip-url:hover {
text-decoration: underline;
color: var(--link);
background: var(--chip);
}
/* Дополнительные стили для светлой темы */
:root[data-theme="light"] .mini-container-tooltip {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
border-color: var(--border);
}
/* Анимация появления подсказки */
@keyframes tooltipFadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.mini-container-tooltip.show {
opacity: 1;
visibility: visible;
animation: tooltipFadeIn 0.2s ease;
}
/* Позиционирование подсказки */
.mini-container-tooltip.top {
bottom: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
}
.mini-container-tooltip.bottom {
top: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
}
.mini-container-tooltip.left {
right: calc(100% + 8px);
top: 50%;
transform: translateY(-50%);
}
.mini-container-tooltip.right {
left: calc(100% + 8px);
top: 50%;
transform: translateY(-50%);
}
/* Стрелка подсказки */
.mini-container-tooltip::before {
content: '';
position: absolute;
width: 0;
height: 0;
border: 4px solid transparent;
}
.mini-container-tooltip.top::before {
bottom: -8px;
left: 50%;
transform: translateX(-50%);
border-top-color: var(--panel);
}
.mini-container-tooltip.bottom::before {
top: -8px;
left: 50%;
transform: translateX(-50%);
border-bottom-color: var(--panel);
}
.mini-container-tooltip.left::before {
right: -8px;
top: 50%;
transform: translateY(-50%);
border-left-color: var(--panel);
}
.mini-container-tooltip.right::before {
left: -8px;
top: 50%;
transform: translateY(-50%);
border-right-color: var(--panel);
}
.sidebar.collapsed .mini-container-list::-webkit-scrollbar {
width: 4px;
}
.sidebar.collapsed .mini-container-list::-webkit-scrollbar-track {
background: transparent;
}
.sidebar.collapsed .mini-container-list::-webkit-scrollbar-thumb {
background: var(--border);
border-radius: 2px;
}
.sidebar.collapsed .mini-container-list::-webkit-scrollbar-thumb:hover {
background: var(--muted);
}
.sidebar:not(.collapsed) .mini-container-list {
display: none;
}
.mini-container-item {
background: var(--chip);
border: 1px solid var(--border);
border-radius: 6px;
padding: 6px;
cursor: pointer;
transition: all 0.2s ease;
position: relative;
min-height: 32px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.mini-container-item:hover {
background: var(--tab-active);
border-color: var(--accent);
transform: scale(1.05);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.mini-container-item.active {
background: var(--tab-active);
border-color: var(--accent);
color: var(--accent);
box-shadow: 0 0 0 1px var(--accent);
}
.mini-container-item.active:hover {
transform: scale(1.05);
box-shadow: 0 0 0 1px var(--accent), 0 2px 8px rgba(0, 0, 0, 0.2);
}
.mini-container-item.active::before {
content: "";
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 2px;
background: var(--accent);
border-radius: 0 1px 1px 0;
}
.mini-container-item.selected {
border-color: var(--ok);
box-shadow: 0 0 0 1px var(--ok);
background: var(--tab-active);
}
.mini-container-item.selected .mini-container-icon {
color: var(--ok);
}
.mini-container-item.selected .mini-container-name {
color: var(--ok);
}
.mini-container-item.selected:hover {
transform: scale(1.05);
box-shadow: 0 0 0 1px var(--ok), 0 2px 8px rgba(0, 0, 0, 0.2);
}
/* Индикатор выбора для миникарточек */
.mini-container-item.selected::after {
content: '';
position: absolute;
top: -2px;
right: -2px;
width: 8px;
height: 8px;
background: var(--ok);
border-radius: 50%;
border: 1px solid var(--panel);
z-index: 10;
animation: selectionPulse 0.3s ease;
}
@keyframes selectionPulse {
0% {
transform: scale(0);
opacity: 0;
}
50% {
transform: scale(1.2);
opacity: 1;
}
100% {
transform: scale(1);
opacity: 1;
}
}
.mini-container-icon {
font-size: 12px;
margin-bottom: 2px;
color: var(--muted);
}
.mini-container-item.active .mini-container-icon {
color: var(--accent);
}
.mini-container-name {
font-size: 8px;
font-weight: 500;
text-align: center;
line-height: 1.2;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--fg);
}
.mini-container-item.active .mini-container-name {
color: var(--accent);
}
.mini-container-status {
position: absolute;
top: 2px;
right: 2px;
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--ok);
}
.mini-container-status.running { background: var(--ok); }
.mini-container-status.stopped { background: var(--err); }
.mini-container-status.paused { background: var(--warn); }
/* Плейсхолдер для миникарточек */
.mini-container-item.placeholder {
opacity: 0.5;
cursor: default;
background: var(--chip);
border-color: var(--border);
}
.mini-container-item.placeholder:hover {
transform: none;
background: var(--chip);
border-color: var(--border);
box-shadow: none;
}
.mini-container-item.placeholder .mini-container-icon,
.mini-container-item.placeholder .mini-container-name {
color: var(--muted);
}
.sidebar.collapsed .sidebar-header {
display: flex;
align-items: center;
justify-content: center;
padding: 10px;
}
.sidebar.collapsed .header-buttons {
flex-direction: column;
gap: 4px;
align-items: center;
justify-content: center;
width: 100%;
}
/* Логотип в свернутом состоянии */
.sidebar.collapsed .sidebar-logo {
display: flex;
align-items: center;
justify-content: center;
height: 40px;
font-size: 18px;
color: var(--accent);
font-weight: bold;
margin-bottom: 10px;
border-bottom: 1px solid var(--border);
}
.sidebar:not(.collapsed) .sidebar-logo {
display: none;
}
/* Сворачивание header вместе с sidebar */
.sidebar.collapsed ~ .main-content .header {
height: 40px;
padding: 0 20px;
display: flex;
align-items: center;
gap: 10px;
}
.sidebar.collapsed ~ .main-content .header .header-title,
.sidebar.collapsed ~ .main-content .header .header-badge,
.sidebar.collapsed ~ .main-content .header .mobile-toggle {
display: none;
}
.sidebar.collapsed ~ .main-content .header .header-filter {
flex: 1;
max-width: none;
margin: 0 8px;
min-width: 150px;
}
.sidebar.collapsed ~ .main-content .header .header-controls { display: flex; align-items: center; gap: 8px; margin-left: auto; }
/* Скрыть кнопки loglevels в компактном header */
.sidebar.collapsed ~ .main-content .header .header-compact-controls { display: none; }
/* Скрыть весь log-header */
.log-header { display: none; }
/* Минимальный padding для log-content в свернутом состоянии */
.sidebar.collapsed ~ .main-content .log-content {
padding: 0;
}
/* Обеспечиваем правильное отображение логов при свернутом sidebar */
.sidebar.collapsed ~ .main-content .log-area {
height: calc(100vh - var(--header-height)) !important;
overflow: hidden !important;
}
.sidebar.collapsed ~ .main-content .log-content {
overflow: visible !important;
height: 100% !important;
padding: 0 !important;
}
.sidebar.collapsed ~ .main-content .single-view-content .log {
height: calc(100vh - var(--header-height)) !important;
overflow: auto !important;
display: block !important;
max-height: none !important;
min-height: 200px !important;
position: relative !important;
}
/* Исправляем скролл для multi-view в свернутом состоянии */
.sidebar.collapsed ~ .main-content .multi-view-content {
height: calc(100vh - var(--header-height) - 60px) !important;
overflow: hidden !important;
}
.sidebar.collapsed ~ .main-content .multi-view-log {
height: 100% !important;
overflow: auto !important;
display: block !important;
max-height: none !important;
min-height: 200px !important;
position: relative !important;
}
/* Обеспечиваем правильное отображение логов при развернутом sidebar */
.sidebar:not(.collapsed) ~ .main-content .single-view-content .log,
.sidebar:not(.collapsed) ~ .main-content .multi-view-log {
height: 100% !important;
overflow: auto !important;
display: block !important;
min-height: 200px !important;
position: relative !important;
}
/* Стили для multi-view-content контейнеров */
.sidebar.collapsed ~ .main-content .multi-view-content {
height: calc(100vh - var(--header-height) - 60px) !important;
overflow: hidden !important;
display: flex !important;
flex-direction: column !important;
}
.sidebar:not(.collapsed) ~ .main-content .multi-view-content {
height: 100% !important;
overflow: hidden !important;
display: flex !important;
flex-direction: column !important;
}
/* Дополнительные стили для multi-view-log в свернутом состоянии */
.sidebar.collapsed ~ .main-content .multi-view-log {
height: 100% !important;
overflow: auto !important;
display: block !important;
max-height: none !important;
min-height: 200px !important;
position: relative !important;
flex: 1 !important;
min-height: 0 !important;
}
/* Более специфичные правила для multi-view логов */
.sidebar.collapsed ~ .main-content .multi-view-content .multi-view-log {
height: 100% !important;
overflow: auto !important;
display: block !important;
max-height: none !important;
min-height: 200px !important;
position: relative !important;
flex: 1 !important;
min-height: 0 !important;
}
.sidebar.collapsed ~ .main-content .multi-view-grid .multi-view-panel .multi-view-content .multi-view-log {
height: 100% !important;
overflow: auto !important;
display: block !important;
max-height: none !important;
min-height: 200px !important;
position: relative !important;
flex: 1 !important;
min-height: 0 !important;
}
/* Multi-view panel для Single View режима */
.multi-view-panel {
display: none;
background: var(--panel);
border-bottom: 1px solid var(--border);
padding: 8px 16px;
font-size: 14px;
font-weight: 500;
color: var(--accent);
}
.sidebar.collapsed ~ .main-content .multi-view-panel {
display: block;
}
/* Дополнительные стили для обеспечения правильного скролла в multi-view */
.multi-view-grid {
display: grid;
gap: 2px;
height: 100%;
padding: 0px;
/* Равная высота строк для нескольких рядов (3+ окон) */
grid-auto-rows: 1fr;
align-items: stretch;
}
.multi-view-panel {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 8px;
display: flex;
flex-direction: column;
overflow: hidden;
padding: 2px;
height: 100%;
/* Drag & Drop стили */
cursor: move;
transition: all 0.2s ease;
position: relative;
user-select: none;
}
/* Разрешаем выделение текста в области логов */
.multi-view-panel .multi-view-log {
user-select: text;
cursor: text;
}
/* Стили для перетаскиваемого элемента */
.multi-view-panel.dragging {
opacity: 0.7;
transform: scale(1.02);
z-index: 1000;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
border-color: var(--accent);
}
/* Стили для области drop - готовность к перестановке */
.multi-view-panel.drop-target {
border-color: var(--ok);
background: var(--tab-active);
box-shadow: 0 0 0 2px var(--ok), 0 0 15px rgba(158, 206, 106, 0.2);
transform: scale(1.01);
transition: all 0.2s ease;
}
/* Стили для области drop - перестановка в процессе */
.multi-view-panel.drop-target.swapping {
box-shadow: 0 0 0 3px var(--ok), 0 0 25px rgba(158, 206, 106, 0.4);
transform: scale(1.02);
animation: dropTargetSwap 0.3s ease-in-out;
}
/* Анимация перестановки */
@keyframes dropTargetSwap {
0% {
box-shadow: 0 0 0 3px var(--ok), 0 0 25px rgba(158, 206, 106, 0.4);
transform: scale(1.02);
}
50% {
box-shadow: 0 0 0 4px var(--ok), 0 0 35px rgba(158, 206, 106, 0.6);
transform: scale(1.03);
}
100% {
box-shadow: 0 0 0 3px var(--ok), 0 0 25px rgba(158, 206, 106, 0.4);
transform: scale(1.02);
}
}
/* Стили для заголовка панели - область для захвата */
.multi-view-header {
cursor: grab;
position: relative;
user-select: none; /* Запрещаем выделение в заголовке */
}
.multi-view-header:active {
cursor: grabbing;
}
/* Индикатор возможности перетаскивания */
.multi-view-header::before {
content: "⋮⋮";
position: absolute;
left: 8px;
top: 50%;
transform: translateY(-50%);
color: var(--muted);
font-size: 12px;
opacity: 0.5;
transition: opacity 0.2s ease;
}
.multi-view-panel:hover .multi-view-header::before {
opacity: 1;
}
/* Скрываем индикатор при перетаскивании */
.multi-view-panel.dragging .multi-view-header::before {
opacity: 0;
}
.multi-view-content {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
}
.multi-view-log {
height: 100%;
margin: 0;
padding: 12px;
font-size: 11px;
line-height: 1.4;
white-space: pre;
word-break: break-word;
overflow: auto;
background: var(--bg);
color: var(--fg);
font-family: ui-monospace, Menlo, Consolas, monospace;
flex: 1;
min-height: 0;
}
/* Принудительный сброс стилей для multi-view логов */
.multi-view-log {
height: 100% !important;
overflow: auto !important;
display: block !important;
max-height: none !important;
min-height: 200px !important;
position: relative !important;
flex: 1 !important;
min-height: 0 !important;
}
/* Универсальные стили для всех multi-view логов */
.multi-view-content .multi-view-log {
height: 100% !important;
overflow: auto !important;
display: block !important;
max-height: none !important;
min-height: 200px !important;
position: relative !important;
flex: 1 !important;
min-height: 0 !important;
width: 100% !important;
box-sizing: border-box !important;
}
/* Универсальные стили для всех multi-view логов в свернутом состоянии */
.sidebar.collapsed ~ .main-content .multi-view-content .multi-view-log {
height: 100% !important;
overflow: auto !important;
display: block !important;
max-height: none !important;
min-height: 200px !important;
position: relative !important;
flex: 1 !important;
min-height: 0 !important;
width: 100% !important;
box-sizing: border-box !important;
}
/* Всегда скрываем одиночный блок multi-view панели в Single View */
#multiViewPanel {
display: none !important;
}
/* Приводим Single View лог к виду multi-view-log */
.log-area .log-content .log {
height: 100%;
margin: 0;
padding: 12px;
font-size: 11px;
line-height: 1.4;
white-space: pre; /* по умолчанию как у multi-view; переключается applyWrapSettings() */
word-break: break-word;
overflow: auto;
background: var(--bg);
color: var(--fg);
font-family: ui-monospace, Menlo, Consolas, monospace;
}
.sidebar-toggle {
position: fixed;
top: 50vh;
left: var(--sidebar-width);
transform: translate(-50%, -50%);
width: 30px;
height: 30px;
background: var(--accent);
border: 2px solid var(--panel);
border-radius: 50%;
color: #0b0d12;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
z-index: 1001;
transition: all 0.2s ease;
}
.sidebar.collapsed + .sidebar-toggle {
left: 42px;
}
.sidebar-toggle:hover {
background: var(--ok);
}
.sidebar-header {
padding: 20px;
border-bottom: 1px solid var(--border);
background: var(--panel);
}
.header-top {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 0px;
}
.header-buttons {
display: flex;
gap: 8px;
align-items: center;
}
.sidebar-header h1 {
font-size: 18px;
margin: 0;
color: var(--accent);
font-weight: 600;
}
.sidebar-header .subtitle {
font-size: 12px;
color: var(--muted);
margin: 0;
}
.options-btn,
.help-btn,
.logout-btn {
background: var(--chip);
border: 1px solid var(--border);
color: var(--muted);
padding: 6px 8px;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
}
/* Компактные контролы в header: по умолчанию скрыты */
.header-compact-controls { display: none; align-items: center; gap: 6px; }
/* Модальное окно для кнопки помощи */
.help-tooltip {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: var(--bg);
z-index: 10000;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
pointer-events: none;
display: flex;
flex-direction: column;
overflow-y: auto;
}
.help-tooltip.show {
opacity: 1;
visibility: visible;
pointer-events: auto;
}
.help-tooltip-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px 30px;
border-bottom: 1px solid var(--border);
background: var(--panel);
flex-shrink: 0;
}
.help-tooltip-header-content {
display: flex;
align-items: center;
gap: 12px;
}
.help-tooltip-close {
background: var(--chip);
border: 1px solid var(--border);
border-radius: 6px;
padding: 8px 12px;
color: var(--muted);
cursor: pointer;
transition: all 0.2s ease;
font-size: 16px;
}
.help-tooltip-close:hover {
background: var(--tab-active);
color: var(--fg);
border-color: var(--accent);
}
.help-tooltip-logo {
width: 24px;
height: 24px;
background: var(--accent);
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
color: #0b0d12;
font-weight: bold;
font-size: 12px;
}
.help-tooltip-title {
font-weight: 600;
color: var(--fg);
font-size: 18px;
}
.help-tooltip-section {
margin-bottom: 24px;
padding: 20px;
background: var(--panel);
border: 1px solid var(--border);
border-radius: 8px;
}
.help-tooltip-section:last-child {
margin-bottom: 0;
}
.help-tooltip-section-title {
font-weight: 600;
color: var(--accent);
margin-bottom: 12px;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.help-tooltip-content {
color: var(--muted);
font-size: 12px;
line-height: 1.4;
}
.help-tooltip-body {
flex: 1;
padding: 30px;
overflow-y: auto;
}
.help-tooltip-content-wrapper {
display: flex;
gap: 40px;
max-width: 1200px;
margin: 0 auto;
}
.help-tooltip-left-column,
.help-tooltip-right-column {
flex: 1;
min-width: 0;
}
.help-tooltip-hotkeys {
display: grid;
grid-template-columns: auto 1fr;
gap: 12px 20px;
font-size: 12px;
margin-top: 8px;
}
.help-tooltip-hotkey {
background: var(--chip);
border: 1px solid var(--border);
border-radius: 6px;
padding: 6px 12px;
font-family: 'Courier New', monospace;
font-weight: 600;
color: var(--fg);
text-align: center;
min-width: 60px;
font-size: 11px;
}
.help-tooltip-description {
color: var(--muted);
font-size: 12px;
line-height: 1.4;
}
.help-tooltip-footer {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px 30px;
border-top: 1px solid var(--border);
background: var(--panel);
flex-shrink: 0;
}
.help-tooltip-author {
font-size: 12px;
color: var(--muted);
}
.help-tooltip-version {
font-size: 12px;
color: var(--accent);
font-weight: 500;
}
.help-tooltip-author a {
color: var(--accent);
text-decoration: none;
}
.help-tooltip-author a:hover {
text-decoration: underline;
}
.help-btn:hover {
background: #a78bfa;
color: #0b0d12;
border-color: #a78bfa;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(187, 154, 247, 0.5);
}
.logout-btn:hover {
background: var(--tab-active);
color: var(--fg);
border-color: var(--accent);
}
/* Специальный hover эффект для кнопки options с цветом accent */
.options-btn:hover {
background: var(--accent) !important; /* Цвет логотипа */
color: #0b0d12 !important;
border-color: var(--accent) !important;
}
/* Кнопка options когда меню открыто (неактивное состояние) */
.options-btn:not(.active) {
background: #e0a800; /* Цвет как у кнопки warning */
color: #0b0d12;
border-color: #e0a800;
}
.options-btn.active {
background: var(--chip);
color: var(--muted);
border-color: var(--border);
}
.logout-btn:hover {
background: var(--err);
color: #fff;
border-color: var(--err);
}
.options-btn i,
.logout-btn i {
font-size: 12px;
}
/* Кнопка состояния WebSocket */
.ws-status-btn {
background: var(--chip);
color: var(--muted);
border: 1px solid var(--border);
border-radius: 6px;
padding: 6px 12px;
font-size: 11px;
font-weight: 500;
cursor: default;
transition: all 0.3s ease;
font-family: inherit;
min-width: 60px;
text-align: center;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.ws-status-btn.ws-on {
background: #7ea855; /* Темнее на 20% */
color: white;
border-color: #7ea855;
}
.ws-status-btn.ws-off {
background: #f7768e;
color: white;
border-color: #f7768e;
}
.ws-status-btn.ws-err {
background: #e0af68;
color: white;
border-color: #e0af68;
}
.ws-status-btn.ws-available {
background: #7aa2f7;
color: white;
border-color: #7aa2f7;
}
/* Кнопка состояния AJAX Update */
.ajax-update-btn {
background: var(--chip);
color: var(--muted);
border: 1px solid var(--border);
border-radius: 6px;
padding: 6px 12px;
font-size: 11px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
font-family: inherit;
min-width: 60px;
text-align: center;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.ajax-update-btn.ajax-on {
background: #7ea855; /* Зеленый цвет */
color: white;
border-color: #7ea855;
}
.ajax-update-btn.ajax-off {
background: #f7768e; /* Красный цвет */
color: white;
border-color: #f7768e;
}
.ajax-update-btn:hover {
opacity: 0.8;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
/* Sidebar Controls */
.sidebar-controls {
padding: 16px;
border-bottom: 1px solid var(--border);
}
.control-group {
margin-bottom: 16px;
}
.control-group:last-child {
margin-bottom: 0;
}
/* Collapsible sections */
.control-group.collapsible {
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
}
.control-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
background: var(--chip);
cursor: pointer;
user-select: none;
transition: background-color 0.2s ease;
}
.control-header:hover {
background: var(--tab-active);
}
.control-header label {
display: block;
font-size: 11px;
color: var(--muted);
margin: 0;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.collapse-btn {
background: none;
border: none;
color: var(--muted);
cursor: pointer;
padding: 4px;
border-radius: 4px;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
}
.collapse-btn:hover {
background: var(--border);
color: var(--fg);
}
.collapse-btn i {
font-size: 12px;
transition: transform 0.2s ease;
}
.control-group.collapsed .collapse-btn i {
transform: rotate(-90deg);
}
.control-content {
padding: 16px;
transition: all 0.3s ease;
overflow: hidden;
}
.control-group.collapsed .control-content {
padding: 0 16px;
max-height: 0;
opacity: 0;
}
/* Полностью свернутое состояние - только заголовки */
.control-group.minimized {
margin-bottom: 4px;
}
.control-group.minimized .control-header {
padding: 8px 12px;
font-size: 10px;
}
.control-group.minimized .control-header label {
font-size: 10px;
text-transform: none;
letter-spacing: 0;
}
.control-group.minimized .control-content {
display: none;
}
/* Скрытие всех секций при активной кнопке Options */
.sidebar-controls.hidden {
display: none;
}
.control-group label {
display: block;
font-size: 11px;
color: var(--muted);
margin-bottom: 6px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.control-group select,
.control-group input[type="text"] {
width: 100%;
background: var(--chip);
color: var(--fg);
border: 1px solid var(--border);
border-radius: 6px;
padding: 8px 12px;
font-size: 12px;
transition: border-color 0.2s ease;
}
.control-group select:focus,
.control-group input[type="text"]:focus {
outline: none;
border-color: var(--accent);
}
/* Checkbox Groups */
.checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.checkbox-group.levels-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px 16px;
width: 100%;
align-items: center;
}
.checkbox-group.options-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px 16px;
width: 100%;
align-items: center;
}
.checkbox-item {
display: flex;
align-items: center;
gap: 6px;
font-size: 11px;
color: var(--muted);
}
.levels-grid .checkbox-item {
min-height: 20px;
justify-content: flex-start;
}
.options-grid .checkbox-item {
min-height: 20px;
justify-content: flex-start;
}
.checkbox-item input[type="checkbox"] {
margin: 0;
}
/* Секция исключенных контейнеров */
.excluded-containers-list {
max-height: 150px;
overflow-y: auto;
margin-bottom: 12px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--bg);
}
.excluded-container-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 12px;
border-bottom: 1px solid var(--border);
font-size: 12px;
}
.excluded-container-item:last-child {
border-bottom: none;
}
.excluded-container-item:first-child {
border-top-left-radius: 6px;
border-top-right-radius: 6px;
}
.excluded-container-item:last-child {
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
}
.excluded-container-name {
color: var(--fg);
flex: 1;
word-break: break-word;
}
.remove-excluded-btn {
background: var(--err);
color: white;
border: none;
border-radius: 4px;
padding: 4px 8px;
font-size: 11px;
cursor: pointer;
transition: all 0.2s ease;
margin-left: 8px;
min-width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
}
.remove-excluded-btn:hover {
opacity: 0.8;
transform: scale(1.05);
}
.excluded-containers-controls {
display: flex;
gap: 8px;
align-items: center;
}
.excluded-input {
flex: 1;
padding: 6px 10px;
border: 1px solid var(--border);
border-radius: 4px;
background: var(--bg);
color: var(--fg);
font-size: 12px;
transition: border-color 0.2s ease;
}
.excluded-input:focus {
outline: none;
border-color: var(--accent);
}
.excluded-input::placeholder {
color: var(--muted);
}
/* Buttons */
.btn {
background: var(--chip);
color: var(--fg);
border: 1px solid var(--border);
border-radius: 6px;
padding: 8px 12px;
font-size: 12px;
cursor: pointer;
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
gap: 6px;
}
.btn:hover {
background: var(--tab-active);
border-color: var(--accent);
}
.btn-primary {
background: var(--accent);
color: #0b0d12;
border-color: var(--accent);
font-weight: 500;
}
.btn-primary:hover {
background: #6b8fd8;
}
.btn-small {
padding: 4px 8px;
font-size: 10px;
min-width: auto;
}
.btn-full-width {
width: 100%;
justify-content: center;
}
/* Стили для кнопки refresh */
.log-refresh-btn {
background: var(--accent);
color: white;
border: 1px solid var(--accent);
border-radius: 6px;
transition: all 0.2s ease;
padding: 6px 12px;
font-size: 11px;
font-weight: 500;
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 60px;
text-align: center;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.log-refresh-btn:hover {
background: var(--accent);
opacity: 0.8;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
/* Стили для кнопки помощи в header */
.help-btn {
background: var(--accent);
color: #0b0d12;
border: 1px solid var(--accent);
border-radius: 6px;
padding: 6px 8px;
font-size: 11px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
min-width: 32px;
text-align: center;
box-shadow: 0 2px 6px rgba(187, 154, 247, 0.3);
}
.help-btn i {
font-size: 12px;
animation: help-pulse 2s ease-in-out infinite;
}
@keyframes help-pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
}
/* Стили для счетчиков-кнопок */
.counter-btn {
display: inline-flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 6px 12px;
margin: 0 4px;
border: none;
border-radius: 6px;
font-size: 11px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
min-width: 70px;
}
.counter-btn:hover {
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
/* Убираем стиль hidden, так как счетчики больше не скрываются */
.counter-btn.disabled {
opacity: 0.5;
background: var(--muted) !important;
cursor: pointer;
}
.counter-btn.disabled:hover {
opacity: 0.7;
}
.counter-label {
font-size: 10px;
opacity: 0.9;
margin-right: 4px;
}
.counter-value {
font-size: 12px;
font-weight: bold;
}
/* Цвета для разных уровней логов */
.debug-btn {
background: #6c757d; /* Серый */
color: white;
}
.debug-btn:hover {
background: #5a6268; /* Затемненный серый */
}
.info-btn {
background: var(--ok); /* Зеленый цвет */
color: white;
border: 1px solid var(--ok);
}
.info-btn:hover {
background: #7ea855; /* Затемненный зеленый */
}
.warn-btn {
background: #ffc107; /* Оставляем текущий цвет */
color: #212529;
}
.warn-btn:hover {
background: #e0a800; /* Затемненный желтый */
}
.error-btn {
background: #dc3545; /* Оставляем текущий цвет */
color: white;
}
.error-btn:hover {
background: #c82333; /* Затемненный красный */
}
.other-btn {
background: #f8f9fa; /* Самый светлый серый */
color: #212529;
}
.other-btn:hover {
background: #dee2e6; /* Затемненный серый */
}
.btn-group {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.btn-group.actions-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px 16px;
width: 100%;
}
.btn-group.actions-grid .btn-full-width {
grid-column: 1 / -1;
}
/* Main Content */
.main-content {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* Header */
.header {
height: var(--header-height);
background: var(--panel);
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
padding: 0 20px;
gap: 16px;
flex-wrap: wrap;
}
.header-title {
font-size: 16px;
font-weight: 600;
color: var(--fg);
margin: 0;
display: flex;
align-items: center;
gap: 8px;
}
.header-badge {
color: var(--muted);
padding: 8px 12px;
font-size: 12px;
display: flex;
align-items: center;
gap: 8px;
height: fit-content;
}
.header-badge select {
background: var(--chip);
color: var(--fg);
border: 1px solid var(--border);
border-radius: 6px;
padding: 8px 12px;
font-size: 12px;
cursor: pointer;
outline: none;
transition: border-color 0.2s ease;
min-width: 120px;
}
.header-badge select:focus {
border-color: var(--accent);
}
.header-badge select option {
background: var(--bg);
color: var(--fg);
}
/* Мультивыбор проектов */
.multi-select-container {
position: relative;
min-width: 120px;
}
.multi-select-display {
background: var(--chip);
color: var(--fg);
border: 1px solid var(--border);
border-radius: 6px;
padding: 8px 12px;
font-size: 12px;
cursor: pointer;
outline: none;
transition: border-color 0.2s ease;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.multi-select-display:hover {
border-color: var(--accent);
}
.multi-select-display.active {
border-color: var(--accent);
background: var(--tab-active);
}
.multi-select-text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.multi-select-dropdown {
position: absolute;
top: 100%;
left: 0;
right: 0;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 6px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 1000;
max-height: 200px;
overflow-y: auto;
margin-top: 4px;
}
.multi-select-option {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
cursor: pointer;
transition: background-color 0.2s ease;
}
.multi-select-option:hover {
background: var(--chip);
}
.multi-select-option input[type="checkbox"] {
margin: 0;
}
.multi-select-option label {
cursor: pointer;
font-size: 12px;
color: var(--fg);
flex: 1;
}
.header-controls {
margin-left: auto;
display: flex;
align-items: center;
gap: 12px;
}
.header-filter {
flex: 1;
min-width: 200px;
max-width: none;
padding: 8px 12px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--bg);
color: var(--fg);
font-size: 12px;
transition: border-color 0.2s ease;
margin: 0 16px;
width: 100%;
}
.header-filter:focus {
outline: none;
border-color: var(--accent);
}
.header-filter::placeholder {
color: var(--muted);
}
/* Адаптивность для header-filter */
@media (max-width: 1200px) {
.header-filter {
min-width: 150px;
margin: 0 12px;
}
.sidebar.collapsed ~ .main-content .header .header-filter {
min-width: 120px;
margin: 0 6px;
}
}
@media (max-width: 768px) {
.header-filter {
min-width: 120px;
margin: 0 8px;
padding: 6px 10px;
font-size: 11px;
}
.header {
gap: 12px;
padding: 0 16px;
}
.sidebar.collapsed ~ .main-content .header .header-filter {
min-width: 100px;
margin: 0 4px;
padding: 4px 8px;
font-size: 10px;
}
}
@media (max-width: 480px) {
.header-filter {
min-width: 100px;
margin: 0 4px;
padding: 4px 8px;
font-size: 10px;
}
.header {
gap: 8px;
padding: 0 12px;
}
.header-controls {
gap: 8px;
}
/* Адаптивность для свернутого sidebar */
.sidebar.collapsed ~ .main-content .header .header-filter {
min-width: 100px;
margin: 0 4px;
}
}
.header-project-select {
padding: 6px 12px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--bg);
color: var(--fg);
font-size: 12px;
cursor: pointer;
transition: border-color 0.2s ease;
min-width: 120px;
}
.header-project-select:focus {
outline: none;
border-color: var(--accent);
}
.header-project-select option {
background: var(--bg);
color: var(--fg);
}
/* Theme Toggle */
.theme-toggle {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
color: var(--muted);
}
.theme-toggle input {
appearance: none;
width: 40px;
height: 20px;
border-radius: 999px;
position: relative;
background: var(--chip);
border: 1px solid var(--border);
cursor: pointer;
transition: background 0.2s ease;
}
.theme-toggle input::after {
content: "";
position: absolute;
top: 2px;
left: 2px;
width: 14px;
height: 14px;
border-radius: 50%;
background: var(--fg);
transition: transform 0.2s ease;
}
.theme-toggle input:checked::after {
transform: translateX(20px);
}
.theme-toggle input:checked {
background: var(--accent);
}
/* Container List */
.container-list {
flex: 1;
overflow-y: auto;
padding: 16px;
}
.container-item {
background: var(--chip);
border: 1px solid var(--border);
border-radius: 8px;
padding: 12px;
margin-bottom: 8px;
cursor: pointer;
transition: all 0.2s ease;
position: relative;
}
.container-item:hover {
background: var(--tab-active);
border-color: var(--accent);
}
.container-item.active {
background: var(--tab-active);
border-color: var(--accent);
color: var(--accent);
}
.container-item.active::before {
content: "";
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 3px;
background: var(--accent);
border-radius: 0 2px 2px 0;
}
.container-name {
font-size: 13px;
font-weight: 500;
margin-bottom: 4px;
display: flex;
align-items: center;
gap: 8px;
}
.container-service {
font-size: 11px;
color: var(--muted);
margin-bottom: 4px;
}
.container-status {
display: flex;
align-items: center;
gap: 8px;
font-size: 10px;
}
.status-indicator {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--ok);
}
.status-indicator.running { background: var(--ok); }
.status-indicator.stopped { background: var(--err); }
.status-indicator.paused { background: var(--warn); }
.container-link {
color: var(--accent);
text-decoration: none;
opacity: 0.7;
transition: opacity 0.2s ease;
margin-left: 4px;
}
.container-link:hover {
opacity: 1;
color: var(--accent);
}
/* Чекбоксы для мультивыбора контейнеров */
.container-select {
position: absolute;
bottom: 8px;
right: 8px;
z-index: 10;
}
.container-checkbox {
display: none;
}
.container-checkbox-label {
display: flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
border: 2px solid var(--border);
border-radius: 4px;
background: var(--bg);
cursor: pointer;
transition: all 0.2s ease;
position: relative;
}
.container-checkbox-label:hover {
border-color: var(--accent);
background: var(--chip);
}
.container-checkbox:checked + .container-checkbox-label {
background: var(--accent);
border-color: var(--accent);
}
.container-checkbox:checked + .container-checkbox-label::after {
content: "✓";
color: white;
font-size: 12px;
font-weight: bold;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.container-item.selected {
border-color: var(--accent);
background: var(--tab-active);
}
/* Мультипросмотр */
.multi-view-grid {
display: grid;
gap: 2px;
height: 100%;
padding: 0px;
/* Равная высота строк для нескольких рядов (3+ окон) */
grid-auto-rows: 1fr;
align-items: stretch;
/* Поддержка drag & drop */
position: relative;
}
.multi-view-panel {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 8px;
display: flex;
flex-direction: column;
overflow: hidden;
padding: 2px;
}
.multi-view-header {
padding: 5px 16px 5px 24px; /* Увеличиваем левый отступ для индикатора перетаскивания */
background: var(--chip);
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
min-height: 16px;
}
.multi-view-title {
font-size: 13px;
font-weight: 500;
color: var(--fg);
margin: 0;
flex: 1;
min-width: 0; /* Позволяет flex-элементу сжиматься */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.multi-view-content {
flex: 1;
overflow: hidden;
}
/* Single View Panel - аналогично Multi View */
.single-view-panel {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 8px;
display: flex;
flex-direction: column;
overflow: hidden;
padding: 2px;
height: 100%;
}
.single-view-header {
padding: 5px 16px;
background: var(--chip);
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
min-height: 16px;
}
.single-view-title {
font-size: 13px;
font-weight: 500;
color: var(--fg);
margin: 0;
flex: 1;
min-width: 0; /* Позволяет flex-элементу сжиматься */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Кнопки уровней логирования для заголовков */
.single-view-levels,
.multi-view-levels {
display: flex;
gap: 4px;
align-items: center;
flex-shrink: 0; /* Предотвращает сжатие кнопок */
user-select: none; /* Запрещаем выделение в кнопках */
}
.level-btn {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
padding: 4px 6px;
border: 1px solid var(--border);
border-radius: 4px;
background: var(--panel);
color: var(--fg);
cursor: pointer;
transition: all 0.2s ease;
font-size: 10px;
min-width: 40px;
max-width: 50px;
position: relative;
flex-shrink: 0; /* Предотвращает сжатие кнопок */
}
.level-btn:hover {
background: var(--chip);
border-color: var(--accent);
}
.level-btn.active {
background: var(--accent);
color: #0b0d12;
border-color: var(--accent);
}
.level-btn.disabled {
opacity: 0.5;
cursor: not-allowed;
}
.level-btn.disabled:hover {
background: var(--panel);
border-color: var(--border);
}
.level-label {
font-weight: 500;
font-size: 9px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.level-value {
font-weight: 600;
font-size: 11px;
}
/* Цвета для разных уровней */
.level-btn.debug-btn {
border-color: #6c757d; /* Серый */
color: #6c757d;
}
.level-btn.debug-btn:hover,
.level-btn.debug-btn.active {
background: #5a6268; /* Затемненный серый */
color: white;
}
.level-btn.info-btn {
border-color: var(--ok); /* Зеленый цвет */
color: var(--ok);
}
.level-btn.info-btn:hover,
.level-btn.info-btn.active {
background: #7ea855; /* Затемненный зеленый */
color: white;
}
.level-btn.warn-btn {
border-color: var(--warn); /* Оставляем текущий цвет */
color: var(--warn);
}
.level-btn.warn-btn:hover,
.level-btn.warn-btn.active {
background: #e0a800; /* Затемненный желтый */
color: #0b0d12;
}
.level-btn.error-btn {
border-color: var(--err); /* Оставляем текущий цвет */
color: var(--err);
}
.level-btn.error-btn:hover,
.level-btn.error-btn.active {
background: #c82333; /* Затемненный красный */
color: white;
}
.level-btn.other-btn {
border-color: #f8f9fa; /* Самый светлый серый */
color: #f8f9fa;
}
.level-btn.other-btn:hover,
.level-btn.other-btn.active {
background: #dee2e6; /* Затемненный серый */
color: #212529;
}
.single-view-content {
flex: 1;
overflow: hidden;
}
.single-view-content .log {
height: 100%;
margin: 0;
padding: 12px;
font-size: 11px;
line-height: 1.4;
white-space: pre;
word-break: break-word;
overflow: auto;
background: var(--bg);
color: var(--fg);
font-family: ui-monospace, Menlo, Consolas, monospace;
}
.multi-view-log {
height: 100%;
margin: 0;
padding: 12px;
font-size: 11px;
line-height: 1.4;
white-space: pre;
word-break: break-word;
overflow: auto;
background: var(--bg);
color: var(--fg);
font-family: ui-monospace, Menlo, Consolas, monospace;
}
/* Log Area */
.log-area {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
.log-header {
padding: 12px 20px;
background: var(--panel);
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
}
.log-title {
font-size: 14px;
font-weight: 500;
color: var(--fg);
margin: 0;
}
.log-controls {
margin-left: auto;
display: flex;
align-items: center;
gap: 8px;
}
.log-content {
flex: 1;
overflow: hidden;
padding: 0;
background: var(--bg);
}
.log {
white-space: pre-wrap;
word-break: break-word;
font-size: 12px;
line-height: 1.5;
margin: 0;
tab-size: 2;
height: 100%;
overflow: auto;
}
/* Responsive */
@media (max-width: 768px) {
.sidebar {
width: 100%;
position: absolute;
z-index: 1000;
height: 100%;
transform: translateX(-100%);
transition: transform 0.3s ease;
}
.sidebar.open {
transform: translateX(0);
}
.main-content {
width: 100%;
}
.mobile-toggle {
display: block;
}
}
.mobile-toggle {
display: none;
background: none;
border: none;
color: var(--fg);
font-size: 18px;
cursor: pointer;
padding: 8px;
}
/* Legacy styles for compatibility */
#tabs{display:none}
main{display:none}
.grid-1{grid-template-columns:1fr}
.grid-2{grid-template-columns:1fr 1fr}
.grid-3{grid-template-columns:1fr 1fr 1fr}
.grid-4{grid-template-columns:1fr 1fr;grid-auto-rows:45vh}
.panel{border:1px solid var(--border);border-radius:10px;background:color-mix(in oklab, var(--panel) 96%, var(--bg));display:flex;flex-direction:column;min-height:0}
.panel .title{padding:6px 10px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px;color:var(--muted);font-size:12px}
.badge{padding:2px 8px;border-radius:999px;background:var(--chip);border:1px solid var(--border);margin-left:6px;color:var(--muted)}
.controls .badge{margin-left:0}
.toolbar{display:flex;gap:6px;margin-left:auto}
.counter{font-size:11px;color:var(--muted)}
.logwrap{flex:1;overflow:auto;padding:10px}
.log{white-space:pre-wrap;word-break:break-word;font-size:12px;line-height:1.5;margin:0;tab-size:2}
.line{color:var(--fg); display:block; margin:0; padding:0; line-height:1.4} .ok{color:var(--ok)} .warn{color:var(--warn)} .err{color:var(--err)} .dbg{color:#7dcfff} .ts{color:var(--muted)}
/* Цвета для multi-view логов */
.multi-view-log .line{color:var(--fg) !important; display:block; margin:0; padding:0; line-height:1.4}
.multi-view-log .ok{color:var(--ok) !important}
.multi-view-log .warn{color:var(--warn) !important}
.multi-view-log .err{color:var(--err) !important}
.multi-view-log .dbg{color:#7dcfff !important}
.multi-view-log .ts{color:var(--muted) !important}
/* Дополнительные стили для multi-view логов */
.multi-view-log span.line{color:var(--fg) !important; display:block; margin:0; padding:0; line-height:1.4}
.multi-view-log span.ok{color:var(--ok) !important}
.multi-view-log span.warn{color:var(--warn) !important}
.multi-view-log span.err{color:var(--err) !important}
.multi-view-log span.dbg{color:#7dcfff !important}
.multi-view-log span.ts{color:var(--muted) !important}
/* Стили для ANSI цветов в multi-view */
.multi-view-log .ansi-red{color:#f7768e !important}
.multi-view-log .ansi-green{color:#22c55e !important}
.multi-view-log .ansi-yellow{color:#eab308 !important}
.multi-view-log .ansi-blue{color:#3b82f6 !important}
.multi-view-log .ansi-magenta{color:#a855f7 !important}
.multi-view-log .ansi-cyan{color:#06b6d4 !important}
.multi-view-log .ansi-white{color:var(--fg) !important}
.multi-view-log .ansi-black{color:#79808f !important}
footer{position:fixed;right:10px;bottom:10px;opacity:.6;font-size:11px}
.filterlvl{display:flex;gap:6px;align-items:center}
/* Instance tag */
.inst-tag{display:inline-block;padding:0 6px;margin-right:6px;border-radius:6px;border:1px solid var(--border);opacity:.9}
/* ANSI */
.ansi-black{color:#79808f} .ansi-red{color:#f7768e} .ansi-green{color:#22c55e} .ansi-yellow{color:#eab308}
.ansi-blue{color:#3b82f6} .ansi-magenta{color:#a855f7} .ansi-cyan{color:#06b6d4} .ansi-white{color:var(--fg)}
.ansi-bold{font-weight:bold} .ansi-italic{font-style:italic} .ansi-underline{text-decoration:underline}
/* Theme toggle */
.theme-toggle{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted)}
.theme-toggle input{appearance:none;width:36px;height:20px;border-radius:999px;position:relative;background:var(--chip);border:1px solid var(--border);cursor:pointer}
.theme-toggle input::after{content:"";position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:var(--fg);transition:transform .2s ease}
.theme-toggle input:checked::after{transform:translateX(16px)}
/* Floating copy button */
.copy-fab{
position:fixed; z-index:9999; display:none; padding:6px 10px; border-radius:8px;
background:var(--accent); color:#0b0d12; border:none; box-shadow:0 6px 20px rgba(0,0,0,.25);
font-size:12px;
}
.copy-fab.show{display:block}
.copy-fab:active{transform:translateY(1px)}
/* Модальное окно с горячими клавишами */
.hotkeys-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 10000;
display: none;
align-items: center;
justify-content: center;
}
.hotkeys-modal.show {
display: flex;
}
.hotkeys-modal-content {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 12px;
box-shadow: 0 16px 64px rgba(0,0,0,0.4);
max-width: 500px;
width: 90%;
max-height: 80vh;
overflow-y: auto;
animation: modalSlideIn 0.3s ease;
}
@keyframes modalSlideIn {
from {
opacity: 0;
transform: scale(0.9) translateY(-20px);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
.hotkeys-modal-header {
padding: 20px 24px 16px;
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: space-between;
}
.hotkeys-modal-title {
font-size: 18px;
font-weight: 600;
color: var(--accent);
margin: 0;
display: flex;
align-items: center;
gap: 8px;
}
.hotkeys-modal-close {
background: none;
border: none;
color: var(--muted);
cursor: pointer;
padding: 8px;
border-radius: 6px;
transition: all 0.2s ease;
font-size: 16px;
}
.hotkeys-modal-close:hover {
background: var(--chip);
color: var(--fg);
}
.hotkeys-modal-body {
padding: 20px 24px;
}
.hotkeys-section {
margin-bottom: 24px;
}
.hotkeys-section:last-child {
margin-bottom: 0;
}
.hotkeys-section-title {
font-size: 14px;
font-weight: 600;
color: var(--fg);
margin: 0 0 12px 0;
padding-bottom: 8px;
border-bottom: 1px solid var(--border);
}
.hotkeys-list {
list-style: none;
padding: 0;
margin: 0;
}
.hotkeys-list li {
display: flex;
align-items: center;
gap: 12px;
margin: 8px 0;
font-size: 13px;
color: var(--fg);
}
.hotkeys-list kbd {
background: var(--chip);
border: 1px solid var(--border);
border-radius: 4px;
padding: 4px 8px;
font-size: 11px;
font-family: monospace;
color: var(--accent);
min-width: 20px;
text-align: center;
}
/* Hotkeys notification */
.hotkeys-notification {
position: fixed;
top: 20px;
right: 20px;
z-index: 10000;
background: var(--panel);
border: 1px solid var(--border);
border-radius: 8px;
box-shadow: 0 8px 32px rgba(0,0,0,0.3);
max-width: 350px;
animation: slideInRight 0.3s ease;
}
@keyframes slideInRight {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.notification-content {
padding: 16px;
position: relative;
}
.notification-content h4 {
margin: 0 0 12px 0;
color: var(--accent);
font-size: 14px;
display: flex;
align-items: center;
gap: 8px;
}
.notification-content ul {
margin: 0;
padding: 0;
list-style: none;
}
.notification-content li {
margin: 8px 0;
font-size: 12px;
color: var(--fg);
display: flex;
align-items: center;
gap: 8px;
}
.notification-content kbd {
background: var(--chip);
border: 1px solid var(--border);
border-radius: 4px;
padding: 2px 6px;
font-size: 10px;
font-family: monospace;
color: var(--accent);
}
.notification-close {
position: absolute;
top: 8px;
right: 8px;
background: none;
border: none;
color: var(--muted);
cursor: pointer;
padding: 4px;
border-radius: 4px;
transition: all 0.2s ease;
}
.notification-close:hover {
background: var(--chip);
color: var(--fg);
}