Files
HadTavern/static/editor.css
2025-10-03 21:55:24 +03:00

1604 lines
58 KiB
CSS
Raw Permalink 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.

@import url('https://fonts.googleapis.com/css2?family=Merriweather:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&display=swap');
/* Глобальный шрифт: Merriweather — только для бренда; остальной UI — системный/Inter */
html, body, button, input, select, textarea, code, pre, a, .chip-btn, .group-title, .hint, details.help summary, #sidebar, #inspector, #canvas, #drawflow, .drawflow, .drawflow * {
font-family: Inter, system-ui, Arial, sans-serif;
}
:root {
/* Цвета темы (совпадают с editor.html) */
color-scheme: dark;
--bg: #0b0d10;
--panel: #11151a;
--muted: #a7b0bf;
--border: #1f2937;
--accent: #6ee7b7; /* зелёный */
--accent-2: #60a5fa; /* синий */
--node: #0e1116;
--node-border: #334155;
--node-selected: #1f2937;
/* Базовый цвет проводов по умолчанию */
--connector: #7aa2f7;
--connector-muted: #3b82f6;
/* Неброские цвета для разных типов/веток */
--wire-true: #34d399; /* мягкий зелёный для If:true */
--wire-false: #94a3b8; /* сланцево‑серый для If:false */
--wire-provider: #5b86e5; /* приглушённый синий */
--wire-raw: #8b7de6; /* мягкий фиолетовый */
--wire-setvars: #4fbfa0; /* приглушённая мята */
--wire-return: #93a9d1; /* холодный серо‑синий */
/* DRY tokens: unified shadows and transitions */
--ring3-22-shadow: 0 0 0 3px rgba(96,165,250,.22), 0 4px 10px rgba(0,0,0,.35);
--ring3-20-shadow: 0 0 0 3px rgba(96,165,250,.20), 0 4px 10px rgba(0,0,0,.35);
--ring2-20-shadow: 0 0 0 2px rgba(96,165,250,.20), 0 2px 6px rgba(0,0,0,.35);
--focus-ring3-20: 0 0 0 3px rgba(96,165,250,.20);
--focus-ring3-22: 0 0 0 3px rgba(96,165,250,.22);
--tr-base: border-color .12s ease, box-shadow .12s ease, background-color .12s ease, color .12s ease;
--tr-pop: transform .12s ease;
--tr-pop-fast: transform .08s ease;
}
html, body {
height: 100%;
overflow: hidden; /* убираем общие скролл-бары страницы, чтобы не перекрывать правую стрелку */
}
#container {
position: relative; /* якорь для абсолютных стрелок-переключателей */
}
/* Grid areas to hard-pin layout regardless of hidden panels or absolute children */
#container {
display: grid;
grid-template-areas: "side main insp";
/* Базовая ширина колонок по умолчанию; переопределяется collapse-* ниже */
grid-template-columns: 260px 1fr 360px;
/* Растяжение по высоте: родитель (body/html) уже 100% */
height: 100%;
min-height: 100%;
}
/* Map children to areas explicitly */
#container > #sidebar { grid-area: side; }
#container > #canvas { grid-area: main; }
#container > #inspector { grid-area: insp; }
/* Снимаем скролл-бары с контейнера Drawflow, чтобы не перекрывать правую стрелку */
#drawflow {
overflow: hidden !important;
position: relative;
z-index: 1; /* гарантируем, что канвас виден под HUD и над фоном */
/* Растянем контейнер Drawflow на всю центральную колонку */
width: 100%;
height: 100%;
display: block;
}
/* Узлы: аккуратные контейнеры + предотвращение вылезания текста */
.drawflow .drawflow-node {
background: transparent !important;
box-shadow: none !important;
}
.drawflow .drawflow-node .title-box {
background: var(--node);
border: 1px solid var(--node-border);
color: #e5e7eb;
border-radius: 12px 12px 0 0;
padding: 4px 8px; /* компактнее заголовок */
font-size: 12px; /* компактнее шрифт заголовка */
line-height: 1.2;
}
/* Иконка типа ноды в заголовке (монохромная, спокойная) */
.drawflow .drawflow-node .title-box .node-ico {
display: inline-block;
width: 14px;
height: 14px;
margin-right: 6px;
vertical-align: -2px;
background-size: 14px 14px;
background-repeat: no-repeat;
filter: opacity(.9);
}
/* SVG-иконки по типам (цвета под стиль проекта) */
.drawflow .drawflow-node .title-box .node-ico-If {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 4v6a4 4 0 0 0 4 4h4'/><polyline points='14 14 18 10 14 6'/></svg>");
}
.drawflow .drawflow-node .title-box .node-ico-ProviderCall {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%235b86e5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M3 15a4 4 0 0 0 4 4h10a4 4 0 0 0 4-4'/><path d='M7 19V5a4 4 0 0 1 4-4h2a4 4 0 0 1 4 4v14'/></svg>");
}
.drawflow .drawflow-node .title-box .node-ico-RawForward {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%238b7de6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='5 12 19 12'/><polyline points='12 5 19 12 12 19'/></svg>");
}
.drawflow .drawflow-node .title-box .node-ico-SetVars {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%234fbfa0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='3'/><path d='M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06A1.65 1.65 0 0 0 15 19.4a1.65 1.65 0 0 0-1 .6l-.09.1a2 2 0 1 1-3.2 0l-.09-.1a1.65 1.65 0 0 0-1-.6 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-.6-1l-.1-.09a2 2 0 1 1 0-3.2l.1-.09a1.65 1.65 0 0 0 .6-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06A2 2 0 1 1 6.94 2.6l.06.06A1.65 1.65 0 0 0 8 3.6a1.65 1.65 0 0 0 1-.6l.09-.1a2 2 0 1 1 3.2 0l.09.1a1.65 1.65 0 0 0 1 .6 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82 1.65 1.65 0 0 0 .6 1l.1.09a2 2 0 1 1 0 3.2l-.1.09a1.65 1.65 0 0 0-.6 1z'/></svg>");
}
.drawflow .drawflow-node .title-box .node-ico-Return {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2393a9d1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M9 10l-5 5 5 5'/><path d='M20 4v7a4 4 0 0 1-4 4H4'/></svg>");
}
.drawflow .drawflow-node .box {
background: var(--node);
border: 1px solid var(--node-border);
border-top: 0;
color: #e5e7eb;
border-radius: 0 0 12px 12px;
overflow: hidden; /* не даём контенту вылезать за края */
font-size: 11px; /* компактнее содержимое */
line-height: 1.25;
}
/* Контент превью внутри .box: можем скрывать его в LOD, не меняя коробку ноды */
.drawflow .drawflow-node .node-preview {
pointer-events: auto; /* разрешаем клики по summary (<details>) */
opacity: .85;
font-size: 10.5px; /* мелкий общий текст превью */
}
/* На самом канвасе поля превью недоступны для редактирования/клика */
.drawflow .drawflow-node .node-preview input,
.drawflow .drawflow-node .node-preview textarea {
pointer-events: none;
}
.drawflow .drawflow-node .node-preview label {
font-size: 10px;
margin: 4px 0 2px;
}
/* Адресные поля читаемые «обычным» кеглем */
.drawflow .drawflow-node .node-preview .np-url,
.drawflow .drawflow-node .node-preview .np-endpoint {
font-size: 12px !important;
}
.drawflow .drawflow-node .box textarea,
.drawflow .drawflow-node .box pre,
.drawflow .drawflow-node .box input[type="text"] {
background: #0f141a;
border: 1px solid #2b3646;
border-radius: 8px;
color: #e5e7eb;
width: 100%;
max-width: 100%;
box-sizing: border-box;
padding: 6px 8px; /* компактнее поля превью */
font-size: 10.5px; /* мелкий текст по умолчанию */
resize: none; /* запрет изменения размера на канвасе */
}
.df-node .box textarea {
white-space: pre-wrap;
word-break: break-word;
overflow-y: auto; /* только вертикальный скролл при необходимости */
overflow-x: hidden; /* убираем горизонтальный скролл внутри textarea */
max-height: 180px; /* предотвращаем бесконечную высоту */
resize: none; /* запрет ручного ресайза превью */
}
/* Выделение выбранного узла — мягкое */
.drawflow .drawflow-node.selected .title-box,
.drawflow .drawflow-node.selected .box {
border-color: var(--accent);
box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 40%, transparent);
}
/* Привести disabled к виду обычных превью (без «серости» браузера) */
.drawflow .drawflow-node .box input[disabled],
.drawflow .drawflow-node .box textarea[disabled] {
opacity: 1;
color: #e5e7eb;
background: #0f141a;
border-color: #2b3646;
cursor: default;
}
/* Порты: более аккуратные, без «оранжевого» */
.drawflow .drawflow-node .inputs .input,
.drawflow .drawflow-node .outputs .output {
background: var(--accent-2) !important;
border: 2px solid color-mix(in srgb, var(--accent-2) 70%, white 0%) !important;
width: 16px !important; /* ↑ hit-area */
height: 16px !important; /* ↑ hit-area */
box-shadow: 0 0 0 2px rgba(0,0,0,.25);
}
/* Линии соединений: тоньше и спокойнее */
.drawflow .connection .main-path {
stroke: var(--connector) !important;
stroke-width: clamp(1px, calc(2.2px / var(--zoom, 1)), 4.5px) !important;
opacity: 0.9 !important;
stroke-linecap: round; /* сглаженные окончания */
stroke-linejoin: round; /* сглажённые соединения */
}
/* Connection styling classes (set by JS; stable even if Drawflow re-renders paths) */
.drawflow .connection.conn-if-true .main-path {
stroke: var(--wire-true) !important;
stroke-dasharray: 6 6 !important;
}
.drawflow .connection.conn-if-false .main-path {
stroke: var(--wire-false) !important;
stroke-dasharray: 6 6 !important;
}
.drawflow .connection.conn-provider .main-path { stroke: var(--wire-provider) !important; }
.drawflow .connection.conn-raw .main-path { stroke: var(--wire-raw) !important; }
.drawflow .connection.conn-setvars .main-path { stroke: var(--wire-setvars) !important; }
.drawflow .connection.conn-return .main-path { stroke: var(--wire-return) !important; }
/* Подсветка входящих к ошибочной ноде рёбер (мягкий красный) */
.drawflow .connection.conn-upstream-err .main-path { stroke: #ef4444 !important; opacity: .95 !important; }
.drawflow .connection .main-path.selected,
.drawflow .connection:hover .main-path {
stroke: var(--accent-2) !important;
/* На hover/selected — слегка толще базовой формулы */
stroke-width: clamp(1.3px, calc(2.6px / var(--zoom, 1)), 5px) !important;
}
/* Точки изгибов/ручки */
.drawflow .connection .point {
stroke: var(--connector-muted) !important;
fill: var(--panel) !important;
}
/* Убираем «уродливый крестик» удаления соединений (оставляем удаление через контекст-меню/клавиши) */
.drawflow .connection .delete,
.drawflow .connection .remove,
.drawflow .connection .connection-remove,
.drawflow .connection [class*="remove"],
.drawflow .connection [class*="delete"] {
display: none !important;
}
/* Сайдбар: выравнивание и аккуратные подсказки */
.group-title {
font-size: 12px;
text-transform: uppercase;
color: var(--muted);
margin: 12px 0 6px;
letter-spacing: .08em;
}
.hint {
color: var(--muted);
font-size: 12px;
margin-top: 4px;
}
details.help { margin: 6px 0; }
details.help summary {
list-style: none;
cursor: pointer;
display: inline-grid;
place-items: center;
width: 20px;
height: 20px;
border-radius: 50%;
background: #334155;
color: #e5e7eb;
font-weight: 700;
border: 1px solid #2b3646;
}
details.help summary::-webkit-details-marker { display: none; }
details.help .panel {
margin-top: 8px;
background: #0f141a;
border: 1px solid #2b3646;
padding: 10px;
border-radius: 8px;
}
/* Sidebar help: make the toggle text styled like regular sidebar hint/title, not a round icon */
#sidebar details.sidebar-help summary.sidebar-help-toggle {
all: unset; /* сбросить круглую кнопку от общего ruleset */
cursor: pointer;
color: var(--muted);
font-size: 12px;
line-height: 1.4;
display: block; /* как обычный текст строки подсказки */
margin: 4px 0 6px; /* как у .hint */
}
#sidebar details.sidebar-help summary.sidebar-help-toggle:hover {
color: #cbd5e1;
text-decoration: underline;
}
#sidebar details.sidebar-help summary.sidebar-help-toggle::-webkit-details-marker { display: none; }
/* Инпуты/тексты внутри нод — одинаковые отступы и скругления */
textarea, input[type=text] {
width: 100%;
background: #0f141a;
color: #e5e7eb;
border: 1px solid #2b3646;
border-radius: 8px;
padding: 8px;
}
/* Кнопки (базовые) */
button {
background: #1f2937;
border: 1px solid #334155;
color: #e5e7eb;
padding: 6px 10px;
border-radius: 8px;
cursor: pointer;
}
button:hover { background: #273246; }
/* Верхняя панель — стиль как у чип‑стрелок и как заголовок «ПЕРЕМЕННЫЕ И МАКРОСЫ» */
header .brand {
font-size: 12px;
text-transform: uppercase;
color: var(--muted);
letter-spacing: .08em;
font-weight: 700;
font-family: 'Merriweather', serif !important;
}
header .actions {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
/* Чип‑кнопки в шапке (и ссылки как кнопки) */
.chip-btn,
a.chip-btn {
display: inline-grid;
place-items: center;
text-decoration: none;
text-transform: uppercase;
font-size: 12px;
letter-spacing: .04em;
padding: 6px 10px;
border-radius: 8px;
background: #0f141a;
color: #e5e7eb;
border: 1px solid #334155;
box-shadow: 0 2px 6px rgba(0,0,0,.35);
transition: var(--tr-base), var(--tr-pop);
user-select: none;
}
.chip-btn:hover,
a.chip-btn:hover {
background: #1f2937;
border-color: var(--accent-2);
box-shadow: var(--ring3-22-shadow);
}
.chip-btn:active,
a.chip-btn:active {
transform: translateY(1px);
box-shadow: var(--ring2-20-shadow);
}
/* Инпуты и селекты в шапке — в одном визуальном ряду с чипами */
.top-input {
height: 32px;
min-width: 160px;
background: #0f141a;
border: 1px solid #334155;
border-radius: 8px;
color: #e5e7eb;
padding: 6px 8px;
box-sizing: border-box;
outline: none;
}
.top-input:focus {
border-color: var(--accent-2);
box-shadow: var(--focus-ring3-20);
}
/* Внутренние заголовки в блоке ноды */
#inspector label { font-size: 12px; color: var(--muted); display: block; margin: 8px 0 4px; }
/* Мелкие фиксы */
.drawflow .drawflow-node .input, .drawflow .drawflow-node .output { color: var(--muted); }
/* Connection delete control — show and restyle (kept functional) */
.drawflow .connection foreignObject,
.drawflow .connection [class*="remove"],
.drawflow .connection [class*="delete"],
.drawflow .connection .connection-remove {
display: inline-flex !important;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
border-radius: 999px;
background: #0f141a;
color: #e5e7eb;
border: 1px solid #334155;
box-shadow: 0 2px 6px rgba(0,0,0,.35);
cursor: pointer;
opacity: .85;
transition: var(--tr-base), var(--tr-pop), opacity .12s ease;
}
.drawflow .connection:hover foreignObject,
.drawflow .connection:hover [class*="remove"],
.drawflow .connection:hover [class*="delete"],
.drawflow .connection:hover .connection-remove {
opacity: 1;
transform: scale(1.05);
border-color: var(--accent-2);
box-shadow: var(--ring3-20-shadow);
}
/* If delete control is rendered inside foreignObject, normalize inner box */
.drawflow .connection foreignObject div,
.drawflow .connection foreignObject span {
display: inline-flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
border-radius: 999px;
background: #0f141a;
color: #e5e7eb;
border: 1px solid #334155;
}
/* If delete control is rendered as SVG text "x" */
.drawflow .connection text {
font-family: Inter, system-ui, Arial, sans-serif;
font-size: 12px;
font-weight: 700;
fill: #e5e7eb;
}
/* Subtle canvas background (lightweight dot grid) */
#canvas {
background-color: var(--bg);
background-image: radial-gradient(circle at 1px 1px, rgba(255,255,255,0.06) 1px, transparent 0);
background-size: 24px 24px;
position: relative; /* ensure HUD overlay absolute positioning works */
overflow: visible; /* позволяем HUD-элементам (чипам) выходить за границы канваса */
/* Растяжение на всю область grid-ячейки main */
width: 100%;
height: 100%;
display: block;
pointer-events: auto;
}
/* HUD overlay layer for LOD labels (screen-space, not affecting node geometry) */
#lod-label-layer,
#lod-hints {
position: absolute;
inset: 0;
pointer-events: none; /* do not intercept mouse */
z-index: 5; /* над нодами/линиями (у них z-index auto), но ниже боковых панелей */
overflow: visible; /* НЕ клипать чипы — пусть уходят под панели */
}
/* Visual chip for node label at far zoom */
/* Generic LOD chip style (used in #lod-hints and legacy #lod-label-layer) */
.lod-chip {
position: absolute;
background: #10151c;
color: #e5e7eb;
border: 2px solid #3b82f6;
border-radius: 8px;
padding: 2px 6px;
white-space: nowrap;
line-height: 1.2;
text-shadow: 0 1px 1px rgba(0,0,0,.6);
box-shadow: 0 0 0 2px rgba(59,130,246,.20), 0 2px 6px rgba(0,0,0,.35);
transform: translate(-50%, -100%); /* centered by JS; here as default */
font: 18px/1.2 Inter, system-ui, Arial, sans-serif;
}
/* LOD: level-of-detail tuned by classes on #canvas (set from JS) */
#canvas.lod-compact .drawflow .drawflow-node .node-preview,
#canvas.lod-tiny .drawflow .drawflow-node .node-preview {
display: none !important; /* скрываем только содержимое превью, не меняя коробку ноды */
}
/* Порты и линии — тоньше в компактных режимах */
/* Убраны фиксированные толщины в LOD — используется формула от --zoom */
#canvas.lod-compact .drawflow .drawflow-node .inputs .input,
#canvas.lod-compact .drawflow .drawflow-node .outputs .output { width: 12px !important; height: 12px !important; }
#canvas.lod-tiny .drawflow .drawflow-node .inputs .input,
#canvas.lod-tiny .drawflow .drawflow-node .outputs .output { width: 10px !important; height: 10px !important; }
/* Индикатор статуса — свечением по рамке остаётся, доп. эффект на тайтле */
#canvas.lod-compact .drawflow .drawflow-node.node-running .title-box,
#canvas.lod-tiny .drawflow .drawflow-node.node-running .title-box { box-shadow: 0 0 0 2px rgba(96,165,250,.25) !important; }
#canvas.lod-compact .drawflow .drawflow-node.node-ok .title-box,
#canvas.lod-tiny .drawflow .drawflow-node.node-ok .title-box { box-shadow: 0 0 0 2px rgba(52,211,153,.25) !important; }
#canvas.lod-compact .drawflow .drawflow-node.node-err .title-box,
#canvas.lod-tiny .drawflow .drawflow-node.node-err .title-box { box-shadow: 0 0 0 2px rgba(239,68,68,.25) !important; }
/* Sleep (amber) */
#canvas.lod-compact .drawflow .drawflow-node.node-sleep .title-box,
#canvas.lod-tiny .drawflow .drawflow-node.node-sleep .title-box { box-shadow: 0 0 0 2px rgba(245,158,11,.28) !important; }
/* Run drawer (settings) */
#run-drawer {
position: fixed;
top: 52px;
right: -380px;
width: 360px;
height: calc(100vh - 52px);
background: var(--panel);
border-left: 1px solid var(--border);
box-shadow: -8px 0 24px rgba(0,0,0,.35);
z-index: 10000;
transition: right .18s ease-in-out;
padding: 12px;
color: #e5e7eb;
}
#run-drawer.open { right: 0; }
#run-drawer h3 { margin: 0 0 8px; font-size: 14px; color: var(--muted); }
#run-drawer .row { display: flex; gap: 8px; margin: 8px 0; align-items: center; }
#run-drawer input[type=number], #run-drawer select {
width: 100%;
background: #0f141a;
border: 1px solid #2b3646;
color: #e5e7eb;
border-radius: 8px;
padding: 6px 8px;
}
#run-drawer .actions { display: flex; justify-content: space-between; gap: 8px; margin-top: 12px; }
/* Logs panel — перенос строк и стили списка + подсветка видов событий */
#logs-panel pre {
white-space: pre-wrap;
word-break: break-word;
overflow-wrap: anywhere;
}
/* Список логов слева */
#logs-panel #logs-list {
overflow-y: auto;
overflow-x: hidden;
}
#logs-panel #logs-list .logs-row {
padding: 8px 10px;
border-bottom: 1px solid #1f2b3b;
cursor: pointer;
display: block;
}
#logs-panel #logs-list .logs-row .title {
font-weight: 600;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#logs-panel #logs-list .logs-row .sub {
opacity: .85;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#logs-panel #logs-list .logs-row:hover {
background: rgba(96,165,250,.08);
}
#logs-panel #logs-list .logs-row.selected {
background: #0f1e2d;
outline: 2px solid #60a5fa;
box-shadow: 0 0 0 2px rgba(96,165,250,.18) inset;
}
#logs-panel #logs-list .logs-row.selected .title {
color: #eaf2ff;
}
/* Dim non-main logs (anything except start/done/error and HTTP errors) */
#logs-panel #logs-list .logs-row.dim:not(.selected) {
opacity: .55;
}
#logs-panel #logs-list .logs-row.dim:not(.selected) .title {
color: #94a3b8;
font-weight: 500;
}
#logs-panel #logs-list .logs-row.dim:not(.selected) .sub {
color: #7c8797;
}
/* Ensure selection overrides dimming */
#logs-panel #logs-list .logs-row.selected.dim {
opacity: 1 !important;
}
/* Subtle emphasis for main node events even when not selected */
#logs-panel #logs-list .logs-row.kind-node.ev-start:not(.selected) {
background: rgba(96,165,250,.07);
}
#logs-panel #logs-list .logs-row.kind-node.ev-done:not(.selected) {
background: rgba(52,211,153,.07);
}
/* Типы логов — цветовая метка по левому бордеру */
#logs-panel #logs-list .logs-row.kind-node.ev-start { border-left: 3px solid #60a5fa; } /* start — синий */
#logs-panel #logs-list .logs-row.kind-node.ev-done { border-left: 3px solid #34d399; } /* done — зелёный */
#logs-panel #logs-list .logs-row.kind-node.ev-error { border-left: 3px solid #ef4444; } /* error — красный */
#logs-panel #logs-list .logs-row.kind-node.ev-sleep { border-left: 3px solid #f59e0b; } /* sleep — янтарный */
#logs-panel #logs-list .logs-row.kind-http.http-ok { border-left: 3px solid #34d399; } /* HTTP 2xx/3xx */
#logs-panel #logs-list .logs-row.kind-http.http-err { border-left: 3px solid #ef4444; } /* HTTP 4xx/5xx */
#logs-panel #logs-list .logs-row.kind-vars { border-left: 3px solid #a78bfa; } /* Vars — фиолетовый */
/* Тонкие скролл-бары для панелей/textarea, чтобы не «мешали» интерфейсу */
#sidebar, #inspector, #scheme-panel, #run-drawer, .vars-popover, #logs-panel pre, #logs-list {
scrollbar-width: thin;
scrollbar-color: #334155 transparent;
}
#sidebar::-webkit-scrollbar,
#inspector::-webkit-scrollbar,
#scheme-panel::-webkit-scrollbar,
#run-drawer::-webkit-scrollbar,
.vars-popover::-webkit-scrollbar,
#logs-panel pre::-webkit-scrollbar,
#logs-list::-webkit-scrollbar {
width: 8px;
height: 8px;
}
#sidebar::-webkit-scrollbar-thumb,
#inspector::-webkit-scrollbar-thumb,
#scheme-panel::-webkit-scrollbar-thumb,
#run-drawer::-webkit-scrollbar-thumb,
.vars-popover::-webkit-scrollbar-thumb,
#logs-panel pre::-webkit-scrollbar-thumb,
#logs-list::-webkit-scrollbar-thumb {
background-color: #334155;
border-radius: 8px;
}
/* Убираем горизонтальный скролл в текстовых редакторах инспектора */
#inspector textarea { overflow-x: hidden; }
/* Mini-scheme panel */
#scheme-panel {
position: fixed;
top: 52px;
right: 24px;
width: 380px;
height: auto;
max-height: calc(100vh - 72px);
background: var(--panel);
border: 1px solid var(--border);
box-shadow: -8px 0 24px rgba(0,0,0,.35);
z-index: 10000;
padding: 12px;
color: #e5e7eb;
overflow: hidden; /* запрещаем выход содержимого за границы панели */
}
#scheme-panel h3 { margin: 0 0 8px; font-size: 14px; color: var(--muted); }
#scheme-panel canvas {
width: 100%;
height: auto; /* фактический размер управляется JS с учётом DPR */
border: 1px solid #2b3646;
border-radius: 8px;
background: #0f141a;
display: block; /* убираем нижний пробел как у inline */
}
/* Docked STORE panel (reuse existing popover node, просто фиксируем сбоку) */
#vars-popover {
position: fixed !important;
top: 52px !important;
right: 24px !important;
height: calc(100vh - 72px) !important;
max-height: none !important;
z-index: 9999 !important;
}
/* Vars popover visual layout */
.vars-popover {
width: 520px; /* фиксированная удобная ширина */
background: #0f141a;
border: 1px solid #2b3646;
border-radius: 10px;
box-shadow: 0 6px 28px rgba(0,0,0,.45);
color: #e5e7eb;
overflow: hidden; /* чтобы шапка/низ не вылезали */
}
/* Header as compact grid */
.vars-popover .vars-head {
display: grid;
grid-template-columns: 1fr minmax(160px, 1.2fr) 120px auto auto auto;
gap: 8px;
align-items: center;
padding: 10px;
border-bottom: 1px solid #2b3646;
}
.vars-popover .vars-head > strong {
font-size: 14px;
color: var(--muted);
}
.vars-popover .vars-head input#vars-search,
.vars-popover .vars-head select#vars-scope {
width: 100%;
background: #0f141a;
border: 1px solid #2b3646;
color: #e5e7eb;
border-radius: 8px;
padding: 6px 8px;
box-sizing: border-box;
}
.vars-popover .vars-head .vars-braces {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: #a7b0bf;
white-space: nowrap;
}
.vars-popover .vars-head button {
background: #1f2937;
border: 1px solid #334155;
color: #e5e7eb;
padding: 6px 8px;
border-radius: 8px;
cursor: pointer;
}
.vars-popover .vars-head button:hover { background: #273246; }
/* Info line */
.vars-popover #vars-info {
padding: 8px 10px;
border-bottom: 1px solid #2b3646;
color: #a7b0bf;
}
/* List area */
.vars-popover #vars-list {
padding: 8px 0;
overflow: auto;
max-height: calc(100% - 110px); /* остаток высоты относительно контейнера */
}
/* Rows styling (override inline minimal grid by sizing columns and clamping) */
.vars-popover #vars-list .row {
display: grid !important;
grid-template-columns: 220px 1fr !important; /* фиксируем ширину колонки макроса */
gap: 8px !important;
padding: 8px 10px !important;
border-bottom: 1px solid #1f2b3b !important;
cursor: pointer !important;
}
.vars-popover #vars-list .row:hover {
background: rgba(96,165,250,.08);
}
.vars-popover #vars-list .row code {
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
color: #60a5fa !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
white-space: nowrap !important;
max-width: 220px !important;
display: block !important;
}
.vars-popover #vars-list .row > div {
overflow: hidden !important;
text-overflow: ellipsis !important;
white-space: nowrap !important;
}
/* Port hover affordance (no heavy effects) */
.drawflow .drawflow-node .inputs .input,
.drawflow .drawflow-node .outputs .output {
transition: var(--tr-pop-fast);
will-change: transform;
}
.drawflow .drawflow-node .inputs .input:hover,
.drawflow .drawflow-node .outputs .output:hover {
transform: scale(1.25);
box-shadow: 0 0 0 3px rgba(96,165,250,.25);
}
/* Node delete "X" — minimal, clean, consistent with theme (kept functional) */
.drawflow .drawflow-node .close {
position: absolute !important; /* stays in node corner */
top: -8px !important;
right: -8px !important;
width: 18px !important;
height: 18px !important;
display: grid !important;
place-items: center !important;
border-radius: 999px !important;
font-size: 12px !important;
line-height: 1 !important;
font-weight: 700 !important;
background: #0f141a !important; /* dark chip */
color: #e5e7eb !important;
border: 1px solid #334155 !important; /* subtle border */
box-shadow: 0 2px 6px rgba(0,0,0,.35) !important;
cursor: pointer !important;
z-index: 10 !important;
transition: var(--tr-base), var(--tr-pop) !important;
}
.drawflow .drawflow-node .close:hover {
transform: scale(1.06) !important;
background: #1f2937 !important;
border-color: var(--accent-2) !important;
color: #f8fafc !important;
box-shadow: var(--ring3-22-shadow) !important;
}
.drawflow .drawflow-node .close:active {
transform: scale(0.98) !important;
box-shadow: var(--ring2-20-shadow) !important;
}
/* Drawflow floating delete handle (class: .drawflow-delete) — restyle but keep behavior */
#drawflow .drawflow-delete,
.drawflow-delete {
position: absolute !important;
transform: translate(-50%, -50%) !important;
width: 20px !important;
height: 20px !important;
display: grid !important;
place-items: center !important;
border-radius: 999px !important;
background: #0f141a !important;
border: 1px solid #334155 !important;
color: transparent !important; /* hide default "x" text to avoid double symbol */
box-shadow: 0 2px 6px rgba(0,0,0,.35) !important;
cursor: pointer !important;
z-index: 1000 !important;
transition: var(--tr-base), var(--tr-pop) !important;
}
#drawflow .drawflow-delete::before,
.drawflow-delete::before {
content: "×";
font-family: Inter, system-ui, Arial, sans-serif;
font-size: 13px;
font-weight: 700;
line-height: 1;
color: #e5e7eb;
}
#drawflow .drawflow-delete:hover,
.drawflow-delete:hover {
transform: translate(-50%, -50%) scale(1.06) !important;
background: #1f2937 !important;
border-color: var(--accent-2) !important;
box-shadow: var(--ring3-22-shadow) !important;
}
#drawflow .drawflow-delete:active,
.drawflow-delete:active {
transform: translate(-50%, -50%) scale(0.97) !important;
}
/* Execution highlight states (SSE-driven) */
.drawflow .drawflow-node .title-box,
.drawflow .drawflow-node .box {
transition: var(--tr-base);
}
.drawflow .drawflow-node.node-running .title-box,
.drawflow .drawflow-node.node-running .box {
border-color: #60a5fa !important; /* blue */
box-shadow: 0 0 0 2px rgba(96,165,250,.35) !important;
}
.drawflow .drawflow-node.node-ok .title-box,
.drawflow .drawflow-node.node-ok .box {
border-color: #34d399 !important; /* green */
box-shadow: 0 0 0 2px rgba(52,211,153,.35) !important;
}
.drawflow .drawflow-node.node-err .title-box,
.drawflow .drawflow-node.node-err .box {
border-color: #ef4444 !important; /* red */
box-shadow: 0 0 0 2px rgba(239,68,68,.35) !important;
}
/* Sleep state — amber */
.drawflow .drawflow-node.node-sleep .title-box,
.drawflow .drawflow-node.node-sleep .box {
border-color: #f59e0b !important; /* amber */
box-shadow: 0 0 0 2px rgba(245,158,11,.35) !important;
}
/* LOD hover tooltip (shown only in compact/tiny via JS) */
.lod-tooltip {
position: absolute;
pointer-events: none;
background: #10151c;
color: #e5e7eb;
border: 2px solid #3b82f6;
border-radius: 8px;
padding: 2px 6px;
white-space: nowrap;
font: 18px/1.2 Inter, system-ui, Arial, sans-serif;
box-shadow: 0 0 0 2px rgba(59,130,246,.20), 0 2px 6px rgba(0,0,0,.35);
transform: translate(-50%, -100%);
z-index: 1000; /* above nodes/edges but below menus */
}
/* Panels collapse controls and layout */
#container.collapse-left {
grid-template-columns: 0 1fr 360px !important;
}
#container.collapse-right {
grid-template-columns: 260px 1fr 0 !important;
}
/* BOTH collapsed: высокий приоритет, чтобы не осталась «пустая колонка» */
#container.collapse-left.collapse-right {
grid-template-columns: 0 1fr 0 !important;
}
/* removed explicit grid placement to avoid grid misplacement on some browsers */
/* Поверх HUD: панели выше, чтобы чипы уходили ПОД них */
#sidebar, #inspector {
position: relative;
z-index: 10;
}
/* Inspector: extra bottom padding + no horizontal scroll to ensure OUTx block reachable */
#inspector {
overflow-y: auto;
overflow-x: hidden;
padding-bottom: 240px;
}
#container.collapse-left #sidebar {
/* Полностью исключаем сайдбар из потока при сворачивании,
чтобы он не создавал «чёрную накладку» и не перехватывал клики */
display: none !important;
/* Страховочные свойства на случай кеша/старых стилей */
width: 0 !important;
padding: 0 !important;
border-right: 0 !important;
overflow: hidden !important;
pointer-events: none !important;
background: transparent !important;
visibility: hidden !important;
}
#container.collapse-right #inspector {
/* Полностью исключаем инспектор из потока и стэка,
чтобы гарантированно не перекрывал канвас (фикс «чёрной накладки») */
display: none !important;
/* Ниже — страховочные свойства для старых кешированных стилей */
width: 0 !important;
padding: 0 !important;
border-left: 0 !important;
overflow: hidden !important;
pointer-events: none !important;
background: transparent !important;
visibility: hidden !important;
}
/* На случай, если браузер продолжит хит‑тестить потомков —
дополнительно отключаем события на всём поддереве инспектора */
#container.collapse-right #inspector * {
pointer-events: none !important;
}
/* Edge toggle buttons — positioned relative to #container; coordinates set by JS (placeToggles) */
.panel-toggle {
position: absolute;
top: 50%;
transform: translateY(-50%); /* vertical center */
width: 22px;
height: 36px;
display: grid;
place-items: center;
border-radius: 8px;
background: #0f141a;
color: #e5e7eb;
border: 1px solid #334155;
box-shadow: 0 2px 6px rgba(0,0,0,.35);
z-index: 9000; /* below drawers/popovers (#run-drawer/#scheme-panel/#vars-popover), above HUD/chips */
cursor: pointer;
user-select: none;
opacity: .95;
pointer-events: auto; /* ensure clickable over HUD layers */
}
/* Left/Right offsets are set dynamically via JS, no static left/right here */
.panel-toggle:hover {
background: #1f2937;
border-color: var(--accent-2);
box-shadow: 0 0 0 3px rgba(96,165,250,.22), 0 4px 10px rgba(0,0,0,.35);
}
/* Safety: hide any leftover debug overlay if it still exists in DOM */
#dbg-hit { display: none !important; }
/* Remove dotted/dashed focus outlines on controls (requested) */
button:focus,
a.chip-btn:focus,
.chip-btn:focus,
.panel-toggle:focus {
outline: none !important;
box-shadow: none !important;
}
/* Logs UI: stronger selected row and readable details override */
#logs-panel #logs-list .logs-row.selected {
border-left-width: 5px; /* stronger accent on selected */
}
#logs-panel #logs-list .logs-row.selected .title {
font-weight: 700;
letter-spacing: .01em;
}
#logs-panel #logs-list .logs-row.selected .sub {
color: #cbd5e1;
}
/* Smooth collapse/expand of side panels via grid columns transition */
#container {
transition: grid-template-columns .18s ease-in-out;
}
/* Optional: soften perceived change on panel boxes themselves */
#sidebar,
#inspector {
transition: opacity .18s ease-in-out;
}
#container.collapse-left #sidebar { opacity: 0; }
#container.collapse-right #inspector { opacity: 0; }
/* Smooth appear animations for overlay/panels (trigger on display: block) */
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(6px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeInRight {
from { opacity: 0; transform: translateX(8px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes fadeInDown {
from { opacity: 0; transform: translateY(-6px); }
to { opacity: 1; transform: translateY(0); }
}
/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
#container {
transition: none !important;
}
#sidebar, #inspector,
#vars-popover, #logs-panel, #scheme-panel {
transition: none !important;
animation: none !important;
}
}
/* Vars popover: quick fade + slight upward motion on open (display becomes block in JS) */
#vars-popover[style*="display: block"] {
animation: fadeInUp .16s ease-out;
will-change: opacity, transform;
}
/* Logs panel: fade + slight leftward motion (panel is fixed on the right) */
#logs-panel[style*="display: block"] {
animation: fadeInRight .16s ease-out;
will-change: opacity, transform;
}
/* Mini-scheme panel: fade + slight downward motion (drops from header area) */
#scheme-panel[style*="display: block"] {
animation: fadeInDown .16s ease-out;
will-change: opacity, transform;
}
/* Unify select look to match preset-select (header .top-input style) */
select#f-provider,
select#tx-preset,
select#vars-scope,
select.v-mode,
select#pm-role {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
background: #0f141a;
color: #e5e7eb;
border: 1px solid #334155;
border-radius: 8px;
height: 32px;
padding: 6px 30px 6px 8px;
box-sizing: border-box;
outline: none;
font: 12px/1 Inter, system-ui, Arial, sans-serif;
transition: var(--tr-base);
}
/* Hover and focus states consistent with .top-input */
select#f-provider:hover,
select#tx-preset:hover,
select#vars-scope:hover,
select.v-mode:hover,
select#pm-role:hover {
background: #121820;
border-color: var(--accent-2);
}
select#f-provider:focus,
select#tx-preset:focus,
select#vars-scope:focus,
select.v-mode:focus,
select#pm-role:focus {
border-color: var(--accent-2);
box-shadow: var(--focus-ring3-20);
}
/* Compact width contexts: keep natural width unless container forces 100% */
#inspector select#f-provider,
#inspector select#tx-preset,
#inspector select.v-mode,
#inspector select#pm-role {
width: 100%;
}
/* Vars dock header already grid-fit; just unify visuals */
.vars-popover .vars-head select#vars-scope {
height: 32px;
}
/* Add a minimal dropdown arrow via background SVG, aligned right */
select#f-provider,
select#tx-preset,
select#vars-scope,
select.v-mode,
select#pm-role {
background-image:
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23a7b0bf' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
background-repeat: no-repeat;
background-position: right 8px center;
background-size: 12px 12px;
}
/* High-contrast for disabled */
select#f-provider:disabled,
select#tx-preset:disabled,
select#vars-scope:disabled,
select.v-mode:disabled,
select#pm-role:disabled {
opacity: .6;
cursor: not-allowed;
}
/* Respect reduced motion for focus rings */
@media (prefers-reduced-motion: reduce) {
select#f-provider,
select#tx-preset,
select#vars-scope,
select.v-mode,
select#pm-role {
transition: none;
}
}
/* Header spacing: add safe gap after brand and small indent for wrapped action rows */
header .brand {
margin-right: 12px; /* space after "НАДTAVERN" */
padding-right: 2px; /* micro buffer to avoid optical collision */
}
header .actions {
margin-left: 8px; /* indent when rows wrap under brand */
}
@media (max-width: 860px) {
header .brand { margin-right: 10px; }
header .actions { margin-left: 6px; }
}
/* Danmaku (bullet chat) over header */
header { position: relative; }
#danmaku-layer {
position: fixed; /* покрывает весь вьюпорт, не только шапку */
inset: 0;
pointer-events: none; /* не перехватывать клики по кнопкам */
overflow: hidden;
opacity: 0;
transition: opacity .18s ease-in-out;
z-index: 8000; /* ниже боковых панелей/дроверов (run-drawer ~10000), выше канваса */
}
#danmaku-layer.is-on { opacity: 1; }
/* Базовый стиль «пули» */
.danmaku-bullet {
position: absolute;
left: 100%; /* старт за правым краем */
top: 8px;
white-space: nowrap;
color: #e5e7eb;
text-shadow: 0 1px 2px rgba(0,0,0,.6);
background: rgba(15, 20, 26, .35);
border: 1px solid rgba(96,165,250,.28);
border-radius: 8px;
padding: 2px 8px;
line-height: 1.15;
transform: translateZ(0); /* чуть сгладить анимацию */
animation-name: danmaku-move;
animation-timing-function: linear;
animation-fill-mode: forwards;
}
/* Вариации размера/выразительности */
.danmaku-bullet.sm { font: 11px/1.15 Inter, system-ui, Arial, sans-serif; opacity: .9; }
.danmaku-bullet.md { font: 12px/1.15 Inter, system-ui, Arial, sans-serif; }
.danmaku-bullet.lg { font: 13px/1.15 Inter, system-ui, Arial, sans-serif; box-shadow: 0 0 0 2px rgba(59,130,246,.12), 0 2px 6px rgba(0,0,0,.35); }
.danmaku-bullet.tint-blue { border-color: rgba(96,165,250,.35); color:#eaf2ff; }
.danmaku-bullet.tint-green { border-color: rgba(52,211,153,.35); color:#dcfce7; }
.danmaku-bullet.tint-pink { border-color: rgba(236,72,153,.35); color:#fde2f2; }
.danmaku-bullet.tint-amber { border-color: rgba(245,158,11,.35); color:#fff3d6; }
/* Движение слева направо (через всю ширину хедера + небольшой запас) */
@keyframes danmaku-move {
from { left: 100%; }
to { left: -40%; }
}
/* Rune highlight inside danmaku bullets */
.danmaku-bullet .rune {
color: var(--accent-2); /* фирменный синий */
font-size: 1.35em; /* немного крупнее текста пули */
letter-spacing: .06em;
text-shadow:
0 0 2px rgba(96,165,250,.95),
0 0 6px rgba(96,165,250,.75),
0 0 12px rgba(96,165,250,.45),
0 0 20px rgba(96,165,250,.30);
animation: rune-glow 1.8s ease-in-out infinite alternate;
}
@keyframes rune-glow {
0% { text-shadow: 0 0 2px rgba(96,165,250,.85), 0 0 6px rgba(96,165,250,.60), 0 0 10px rgba(96,165,250,.35); }
50% { text-shadow: 0 0 3px rgba(96,165,250,1), 0 0 10px rgba(96,165,250,.85), 0 0 18px rgba(96,165,250,.55); }
100% { text-shadow: 0 0 2px rgba(96,165,250,.90), 0 0 8px rgba(96,165,250,.70), 0 0 14px rgba(96,165,250,.45); }
}
/* Sisters highlight inside danmaku bullets (pleasant pink + gentle glow) */
.danmaku-bullet .sisters {
color: #f9a8d4; /* soft pink */
font-weight: 600;
letter-spacing: .02em;
text-shadow:
0 0 2px rgba(249,168,212,.95),
0 0 6px rgba(249,168,212,.70),
0 0 12px rgba(249,168,212,.40),
0 0 18px rgba(249,168,212,.28);
animation: sisters-glow 1.8s ease-in-out infinite alternate;
}
@keyframes sisters-glow {
0% { text-shadow: 0 0 2px rgba(249,168,212,.85), 0 0 6px rgba(249,168,212,.60), 0 0 10px rgba(249,168,212,.35); }
50% { text-shadow: 0 0 3px rgba(249,168,212,1), 0 0 10px rgba(249,168,212,.85), 0 0 18px rgba(249,168,212,.55); }
100% { text-shadow: 0 0 2px rgba(249,168,212,.90), 0 0 8px rgba(249,168,212,.70), 0 0 14px rgba(249,168,212,.45); }
}
/* Fix SetVars inspector layout: make name input wide and mode select compact */
#inspector .var-row .v-name {
width: auto; /* override generic width:100% */
flex: 1 1 260px; /* grow and take available space */
min-width: 240px; /* keep readable even on narrow layouts */
}
#inspector .var-row select.v-mode {
width: auto !important; /* override earlier #inspector select.v-mode { width:100% } */
min-width: 120px; /* compact, but not too small */
flex: 0 0 auto; /* do not stretch in flex row */
}
#inspector .var-row .v-del {
flex: 0 0 auto; /* keep delete button compact */
}
/* SetVars row: keep mode selector visible even on narrow widths */
#inspector .var-row > div {
flex-wrap: wrap !important; /* allow wrapping to next line */
}
#inspector .var-row label {
flex: 0 0 auto; /* labels don't stretch */
}
#inspector .var-row .v-name {
flex: 1 1 260px; /* wide name input */
min-width: 260px;
max-width: calc(100% - 220px); /* leave room for mode+delete on one line when possible */
}
#inspector .var-row select.v-mode {
width: auto !important;
flex: 0 0 140px; /* fixed, visible width */
min-width: 120px;
margin-top: 4px; /* if wrapped to next line, add a little spacing */
}
#inspector .var-row .v-del {
flex: 0 0 auto;
}
/* --- Wire labels and arrows overlay --- */
#wire-labels {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 4; /* над линиями, под панелями */
}
.wire-label {
position: absolute;
transform: translate(-50%, -50%);
background: #10151c;
color: #e5e7eb;
border: 1px solid rgba(148,163,184,.35);
border-radius: 6px;
padding: 1px 4px;
font: 10px/1.2 Inter, system-ui, Arial, sans-serif;
white-space: nowrap;
opacity: .9;
user-select: none;
}
.wire-arrow {
position: absolute;
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 8px solid var(--connector); /* перекрашивается inline из цвета линии */
transform-origin: 50% 70%;
opacity: .95;
}
/* Димминг посторонних связей при фокусе ноды */
.drawflow .connection.dim .main-path {
opacity: .35 !important;
}
/* --- Сворачиваемые блоки превью в нодах --- */
.np-coll { margin: 4px 0; }
.np-coll > summary {
list-style: none;
cursor: pointer;
color: var(--muted);
font-size: 10px;
margin: 4px 0 2px;
}
.np-coll > summary::-webkit-details-marker { display: none; }
.np-coll[open] > summary { color: #cbd5e1; }
/* groups overlay removed */
/* --- Canvas preview sanitization: hide hints/labels/checkboxes (only on canvas node previews) --- */
/* Скрываем визуальные хинты, подписи и «галочки» только внутри превью нод на канвасе.
Summary секции (headers/template) остаются видимыми, textarea/inputs продолжают отображать значения. */
#canvas .drawflow .drawflow-node .node-preview .hint,
#canvas .drawflow .drawflow-node .node-preview label,
#canvas .drawflow .drawflow-node .node-preview input[type="checkbox"] {
display: none !important;
}
/* --- Unified checkbox style across UI --- */
/* Единый тёмный стиль чекбоксов под тему проекта (акцент — var(--accent-2)).
Применяется ко всей UI (инспектор, «Запуск», Prompt Blocks, STOREпанель и т.д.).
На канвасе в превью чекбоксы скрыты блоком выше. */
input[type="checkbox"] {
-webkit-appearance: none;
appearance: none;
width: 16px;
height: 16px;
display: inline-block;
vertical-align: -2px;
border: 1px solid #334155;
border-radius: 4px;
background: #0f141a;
box-shadow: 0 0 0 0 rgba(96,165,250,0.0);
transition:
background-color .12s ease,
border-color .12s ease,
box-shadow .12s ease,
transform .06s ease;
cursor: pointer;
}
input[type="checkbox"]:hover {
background: #121820;
border-color: var(--accent-2);
box-shadow: 0 0 0 3px rgba(96,165,250,.18);
}
input[type="checkbox"]:active {
transform: scale(0.96);
}
input[type="checkbox"]:checked {
border-color: var(--accent-2);
background-color: #0f141a;
background-image: url("data:image/svg+xml;utf8,&lt;svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2360a5fa' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'&gt;&lt;polyline points='20 6 9 17 4 12'/&gt;&lt;/svg&gt;");
background-repeat: no-repeat;
background-position: center;
background-size: 12px 12px;
}
input[type="checkbox"]:focus-visible {
outline: none;
border-color: var(--accent-2);
box-shadow: var(--focus-ring3-22);
}
input[type="checkbox"]:disabled {
opacity: .6;
cursor: not-allowed;
box-shadow: none;
}
/* --- Enhanced checkbox visual: add glowing blue dot at center --- */
/* Применяется ко всем чекбоксам в UI (инспектор, Запуск, Prompt Blocks, STORE и т.д.).
В превью нод на канвасе чекбоксы скрыты ранее добавленным правилом. */
input[type="checkbox"] {
position: relative; /* для центрирования псевдо-элемента */
overflow: visible; /* безопасно для свечения */
}
input[type="checkbox"]::after {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 6px;
height: 6px;
border-radius: 999px;
background: var(--accent-2);
transform: translate(-50%, -50%) scale(0.6);
opacity: .6;
/* мягкое синее свечение в покое */
box-shadow:
0 0 4px rgba(96,165,250,.45),
0 0 10px rgba(96,165,250,.25);
transition:
transform .12s ease,
opacity .12s ease,
box-shadow .12s ease;
}
input[type="checkbox"]:checked::after {
transform: translate(-50%, -50%) scale(1.0);
opacity: 1;
/* усиленное свечение при включении */
box-shadow:
0 0 6px rgba(96,165,250,.80),
0 0 14px rgba(96,165,250,.60),
0 0 24px rgba(96,165,250,.35);
}
input[type="checkbox"]:disabled::after {
opacity: .35;
box-shadow: 0 0 2px rgba(96,165,250,.25);
}
/* --- Unified number input style across UI --- */
/* Единый стиль для всех input[type=number], включая инспектор, «Запуск», SERVICEпанели и т.д. */
input[type="number"] {
width: 100%;
background: #0f141a;
color: #e5e7eb;
border: 1px solid #2b3646;
border-radius: 8px;
padding: 6px 8px;
height: 32px;
box-sizing: border-box;
font: 12px/1 Inter, system-ui, Arial, sans-serif;
transition: var(--tr-base);
}
input[type="number"]:hover {
background: #121820;
border-color: var(--accent-2);
}
input[type="number"]:focus {
outline: none;
border-color: var(--accent-2);
box-shadow: var(--focus-ring3-20);
}
input[type="number"]:disabled {
opacity: .6;
cursor: not-allowed;
box-shadow: none;
}
/* Убираем нативные «стрелочки», чтобы стиль был единым во всех браузерах */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type="number"] {
-moz-appearance: textfield;
}
/* --- Canvas preview sanitization (напоминание): хинты/лейблы/чекбоксы скрыты в превью --- */
/* Секции summary (headers/template) остаются видимыми */
/* --- Logs panel: base layout ------------------------------------------------- */
#logs-list { --log-border: #1f2b3b; }
#logs-list .logs-row {
padding: 8px 10px;
border-bottom: 1px solid var(--log-border);
background: #0f141a;
cursor: pointer;
transition: background-color .15s ease, box-shadow .15s ease, opacity .2s ease;
}
#logs-list .logs-row:hover { background: #111821; }
#logs-list .logs-row.selected {
outline: 0;
box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent-2) 40%, transparent);
}
#logs-list .logs-row.dim { opacity: .70; }
#logs-list .logs-row .title { font-size: 13px; }
#logs-list .logs-row .sub {
font-size: 11px;
opacity: .85;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* --- HTTP status styling ----------------------------------------------------- */
/* Shimmer animation for pending HTTP rows */
@keyframes logs-shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
/* Pending request (no response yet): blue accent shimmer using --accent-2 */
#logs-list .logs-row.kind-http.http-pending {
border-left: 3px solid var(--accent-2);
background:
linear-gradient(90deg,
color-mix(in srgb, var(--accent-2) 10%, transparent) 0%,
color-mix(in srgb, var(--accent-2) 20%, transparent) 50%,
color-mix(in srgb, var(--accent-2) 10%, transparent) 100%);
background-size: 200% 100%;
animation: logs-shimmer 1.4s linear infinite;
}
/* Success/Failure borders for completed HTTP rows */
#logs-list .logs-row.kind-http.http-ok { border-left: 3px solid #10b981; } /* emerald-500 */
#logs-list .logs-row.kind-http.http-err { border-left: 3px solid #ef4444; } /* red-500 */
/* --- Node sleep pulse -------------------------------------------------------- */
@keyframes logs-sleep-pulse {
0% { box-shadow: inset 0 0 0 0 rgba(245,158,11, 0.00); }
50% { box-shadow: inset 0 0 0 2px rgba(245,158,11, 0.35); }
100% { box-shadow: inset 0 0 0 0 rgba(245,158,11, 0.00); }
}
#logs-list .logs-row.kind-node.ev-sleep {
border-left: 3px dashed #f59e0b; /* amber-500 */
animation: logs-sleep-pulse 1.8s ease-in-out infinite;
}
/* --- Node "water" running effect (blue→violet gradient, slow, saturated) ----- */
@keyframes node-water {
0% { background-position: 0% 0%; }
50% { background-position: 100% 100%; }
100% { background-position: 0% 0%; }
}
/* Применяется, когда нода исполняется (класс .node-running вешается из SSE) */
#drawflow .drawflow-node.node-running .title-box,
#drawflow .drawflow-node.node-running .box {
/* База: наш стандартный фон ноды, сверху — насыщенный градиент воды */
background:
linear-gradient(125deg,
color-mix(in srgb, #60a5fa 78%, transparent) 0%,
color-mix(in srgb, #7c3aed 56%, transparent) 50%,
color-mix(in srgb, #60a5fa 78%, transparent) 100%),
var(--node);
background-size: 360% 360%;
animation: node-water 5.0s ease-in-out infinite; /* медленнее и гуще, «водная гладь» */
border-color: color-mix(in srgb, var(--accent-2) 55%, #7c3aed 45%);
/* Лёгкое свечение, чтобы подчеркнуть активность, без ядовитости */
box-shadow:
0 0 0 2px color-mix(in srgb, var(--accent-2) 30%, transparent),
0 0 16px rgba(96,165,250,.18),
inset 0 0 22px rgba(167,139,250,.12);
}
/* Безопасность: при успехе/ошибке временные классы могут перебить рамку */
#drawflow .drawflow-node.node-ok .title-box,
#drawflow .drawflow-node.node-ok .box {
border-color: #10b981 !important; /* emerald */
box-shadow:
0 0 0 2px color-mix(in srgb, #10b981 35%, transparent),
0 0 12px rgba(16,185,129,.18);
background-image: none; /* убрать «воду» после окончания */
}
#drawflow .drawflow-node.node-err .title-box,
#drawflow .drawflow-node.node-err .box {
border-color: #ef4444 !important; /* red */
box-shadow:
0 0 0 2px color-mix(in srgb, #ef4444 35%, transparent),
0 0 12px rgba(239,68,68,.18);
background-image: none; /* убрать «воду» после ошибки */
}
/* --- Water overlay: full-node coverage with fade-out on stop ------------------ */
/* База: прозрачный градиент-оверлей на ВСЕЙ .drawflow_content_node,
который плавно меняет прозрачность. Когда нода активна (.node-running) —
поднимаем непрозрачность и двигаем «волну». При снятии .node-running
оверлей сам «затухает» благодаря transition на opacity. */
#drawflow .drawflow-node .drawflow_content_node {
position: relative;
overflow: hidden;
z-index: 0; /* чтобы ::before можно было поднять поверх */
}
#drawflow .drawflow-node .drawflow_content_node::before {
content: '';
position: absolute;
inset: 0;
z-index: 1; /* поверх содержимого ноды, но без кликов */
pointer-events: none;
border-radius: 10px;
background: linear-gradient(125deg,
color-mix(in srgb, #60a5fa 78%, transparent) 0%,
color-mix(in srgb, #7c3aed 56%, transparent) 50%,
color-mix(in srgb, #60a5fa 78%, transparent) 100%);
background-size: 360% 360%;
opacity: 0; /* по умолчанию невидим */
transition: opacity 1.4s ease-in-out; /* «затухание» при остановке */
}
#drawflow .drawflow-node.node-running .drawflow_content_node::before {
opacity: .42; /* насыщенно, но читаемо; плавно исчезает при снятии класса */
animation: node-water 5.0s ease-in-out infinite; /* медленная водная гладь */
}
/* Отключаем прежнюю «водную» анимацию на частях, оставляя оверлей на всю ноду */
#drawflow .drawflow-node.node-running .title-box,
#drawflow .drawflow-node.node-running .box {
background: var(--node) !important;
animation: none !important;
}