/* ============================================================
   uiNodeGraph.css — стили, вынесенные из uiNodeGraph.js (Unified Theme)
   Подключить в index.html после style.css:
   <link rel="stylesheet" href="css/uiNodeGraph.css">
   ============================================================ */

/* ── Меню «Добавить модуль» ─────────────────────────────────── */
.module-add-menu {
    position: fixed;
    z-index: 10000;
    background: var(--ui-bg);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius);
    padding: 4px;
    min-width: 160px;
    box-shadow: var(--ui-shadow);
    font-family: var(--ui-font);
}

.module-menu-sep {
    height: 1px;
    background: var(--ui-border);
    margin: 4px 0;
}

.module-menu-item {
    padding: 8px 12px;
    cursor: pointer;
    border-radius: var(--ui-radius-sm);
    color: var(--ui-text);
    font-size: 13px;
    display: flex;
    align-items: center;
    gap: 8px;
    opacity: 1;
}

.module-menu-item:hover {
    background: var(--ui-bg-hover);
}

.module-menu-item > span:first-child {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
}
.module-menu-item svg { width: 14px; height: 14px; opacity: 0.8; }

.module-menu-item.disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* ── Рендер-нода ─────────────────────────────────────────────── */
.node-render {
    background: var(--ui-bg) !important;
    border: 2px dashed var(--ui-accent) !important;
    box-shadow: 0 0 16px var(--ui-accent-glow) !important;
    min-height: 80px;
    border-radius: var(--ui-radius);
}

.node-render-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    gap: 4px;
    padding: 8px 0;
}

.node-render-icon {
    font-size: 18px;
    line-height: 1;
}

.node-render-title {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 3px;
    color: var(--ui-accent);
    text-align: center;
}

.node-render-count {
    font-size: 9px;
    letter-spacing: 1.5px;
    color: var(--ui-text-dim);
    text-align: center;
    opacity: 0.8;
}

/* ── Варианты block-chars ────────────────────────────────────── */
.block-chars-render {
    opacity: 0.7;
    font-size: 10px;
    letter-spacing: 1px;
    text-align: center;
    color: var(--ui-text);
}

.block-chars-scene {
    opacity: 0.6;
    font-size: 10px;
    font-style: italic;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--ui-text);
}

.block-chars-label {
    opacity: 0.45;
    font-size: 10px;
    letter-spacing: 1px;
    color: var(--ui-text);
}


/* ── Кнопка «+» на ноде и между модулями ────────────────────── */
.node-add-module-btn, .module-insert-btn {
    position: absolute;
    bottom: -10px;
    left: 50%;
    transform: translateX(-50%);
    width: 20px;
    height: 20px;
    background: var(--ui-bg-input);
    border: 1px solid var(--ui-border);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 20;
    color: var(--ui-text-dim);
    box-shadow: var(--ui-shadow-sm);
    transition: background 0.1s, color 0.1s;
}

.node-add-module-btn:hover, .module-insert-btn:hover {
    background: var(--ui-accent);
    color: #fff;
    border-color: var(--ui-accent-hover);
}

/* ── Мета-порты AI ─────────────────────────────── */
.port-meta-in, .port-meta-out {
    position: absolute;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--ui-bg-deep);
    border: 1.5px solid var(--ui-accent);
    box-shadow: 0 0 0 2px var(--ui-accent-glow), 0 2px 8px rgba(0, 0, 0, 0.4);
    cursor: crosshair;
    z-index: 110;
    pointer-events: all;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    line-height: 1;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.port-meta-out::after {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--ui-accent);
}

.port-meta-in:hover, .port-meta-out:hover {
    border-color: var(--ui-border-focus);
    box-shadow: 0 0 0 3px var(--ui-accent-glow), 0 2px 12px rgba(0, 0, 0, 0.4);
}

/* ── AI-нода: позиционирование-обёртка ──────────────────────── */
.ai-agent-node-wrap {
    position: absolute;
    width: 240px;
    overflow: visible;
    z-index: 5;
    padding: 0;
}

/* ── Бейдж «модули скрыты» ───────────────────────────────────── */
.module-collapsed-badge {
    position: absolute;
    bottom: -18px;
    left: 50%;
    transform: translateX(-50%);
    font-size: 9px;
    font-family: var(--ui-font);
    color: var(--ui-text-dim);
    background: var(--ui-bg-input);
    border: 1px solid var(--ui-border);
    border-radius: 10px;
    padding: 1px 8px;
    white-space: nowrap;
    pointer-events: none;
}

/* ── Плейсхолдер имени персонажа в шапке модуля ─────────────── */
.mod-char-placeholder {
    opacity: 0.35;
    font-weight: 400;
    font-style: italic;
}

/* ═══════════════════════════════════════════════════════════════
   AI-нода — Строгий Theme Design
   ═══════════════════════════════════════════════════════════════ */

.tl-block.ai-node.premium-ios-look {
    background: var(--ui-bg);
    border-radius: var(--ui-radius);
    border: 1px solid var(--ui-border);
    box-shadow: var(--ui-shadow);
    width: 260px;
    height: auto !important;
    min-height: 0 !important;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: 0;
    font-family: var(--ui-font);
    color: var(--ui-text);
}

.tl-block.ai-node.premium-ios-look.active {
    border-color: var(--ui-border-focus);
    box-shadow: 0 0 0 1px var(--ui-accent-glow), var(--ui-shadow);
}

/* Шапка */
.ai-header {
    background: var(--ui-bg-deep);
    padding: 10px 14px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid var(--ui-border);
}

.ai-header-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    color: var(--ui-accent);
}

.ai-icon { font-size: 14px; }

.ai-node-model-label {
    font-size: 10px;
    color: var(--ui-text-dim);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ai-status-icon {
    font-size: 13px;
    min-width: 16px;
    text-align: center;
}

/* ── Переключатель режима — сегментированная пилюля ─────────── */
.ai-mode-switcher {
    display: flex;
    margin: 10px 12px 0;
    background: var(--ui-bg-input);
    border-radius: var(--ui-radius-sm);
    padding: 3px;
    gap: 3px;
    border: 1px solid var(--ui-border);
}

.ai-mode-btn {
    flex: 1;
    padding: 7px 4px;
    border: none;
    border-radius: var(--ui-radius-xs);
    background: transparent;
    color: var(--ui-text-dim);
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.18s, color 0.18s, box-shadow 0.18s;
    white-space: nowrap;
    font-family: var(--ui-font);
}

.ai-mode-btn[data-mode="add"].active,
.ai-mode-btn[data-mode="rewrite"].active {
    background: var(--ui-accent-glow);
    color: #fff;
    box-shadow: inset 0 0 0 1px var(--ui-accent);
}

.ai-mode-btn:not(.active):hover {
    color: var(--ui-text);
    background: rgba(255, 255, 255, 0.04);
}

/* ── Обёртка промпт-блока — единый визуальный блок ─────────── */
.ai-prompt-wrap {
    margin: 8px 12px 0;
    border-radius: var(--ui-radius-sm);
    overflow: hidden;
    border: 1px solid var(--ui-border);
    background: var(--ui-bg-input);
    transition: border-color 0.2s;
}

.ai-prompt-wrap.mode-add,
.ai-prompt-wrap.mode-rewrite {
    border-color: var(--ui-border-focus);
}

/* Метка режима внутри блока */
.ai-prompt-mode-label {
    padding: 5px 11px;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    border-bottom: 1px solid var(--ui-border);
    user-select: none;
    font-family: var(--ui-font);
}

.ai-prompt-mode-label.mode-add,
.ai-prompt-mode-label.mode-rewrite {
    color: #fff;
    background: var(--ui-accent);
}

/* Поле промпта */
.ai-prompt-field {
    width: 100%;
    box-sizing: border-box;
    min-height: 72px;
    max-height: 180px;
    background: transparent;
    border: none;
    padding: 10px 12px;
    color: var(--ui-text);
    font-size: 12.5px;
    font-family: var(--ui-font);
    line-height: 1.55;
    resize: none;
    outline: none;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--ui-border) transparent;
    display: block;
}
.ai-prompt-field::placeholder { color: var(--ui-text-muted); }

/* ⚡ v164.1. БЛОК ТЕКСТОВОЙ НОДЫ НА ГРАФЕ — без шапки, только текст.
   Высота карточки на 8px меньше шага модулей (MOD_H = 58): шаг остаётся
   арифметикой, на которой держатся якоря проводов и перелёт камеры, а зазор
   между блоками появляется — раньше они стояли впритык. */
.tl-module.tl-module-textblock {
    min-height: 50px;
    height: 50px;
    padding: 8px 22px 8px 10px;   /* справа — место под крестик */
    display: flex;
    align-items: center;
}
/* Текст блока — основное содержимое карточки, а не служебная подпись: обычный
   цвет вместо приглушённого курсива .node-mod-line, до трёх строк. */
.tl-module.tl-module-textblock .mod-text-preview {
    font-style: normal;
    color: #ccc;
    font-size: 11px;
    line-height: 1.3;
    max-height: none;
    -webkit-line-clamp: 3;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
    width: 100%;
}
.tl-module.tl-module-textblock .mod-text-preview.is-empty { color: #666; font-style: italic; }
/* Без шапки крестику негде висеть — уходит в угол абсолютом, как .mod-a4-del. */
.tl-module .node-mod-del.mod-del-corner {
    position: absolute;
    top: 3px;
    right: 5px;
    margin-left: 0;
    line-height: 1;
    padding: 0 2px;
}

/* ⚡ v164.1. НАЙДЕНО ПРИ РАБОТЕ НАД п.1.5 — БАГ СТАРШЕ ЭТОЙ ВЕРСИИ.
   `.block-title { pointer-events: none }` (style.css:118) означает, что
   заголовок карточки НЕ ПОЛУЧАЕТ событий вовсе: двойной клик проходит сквозь
   него в карточку и вызывает перелёт камеры. Поэтому инлайн-переименование не
   работало и у БЮДЖЕТНОЙ ноды, где живёт с момента появления. Возвращаем
   события ровно тем заголовкам, которые объявлены редактируемыми. */
.tl-block .block-title[data-editable-heading] {
    pointer-events: auto;
    cursor: text;
}
.tl-block .block-title[data-editable-heading][contenteditable="true"] {
    outline: 1px solid var(--ui-border-focus, #87b8c4);
    border-radius: 3px;
    white-space: normal;
    overflow: visible;
}

/* ── Верхний конфиг-блок (модель + параметры проекта) — тот же визуальный
      паттерн, что и промпт-блок ниже: единая рамка, внутренние секции ────── */
.ai-config-wrap {
    margin: 8px 12px 0;
    border-radius: var(--ui-radius-sm);
    overflow: hidden;
    border: 1px solid var(--ui-border);
    background: var(--ui-bg-input);
}
.ai-config-select {
    width: 100%;
    box-sizing: border-box;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--ui-border);
    padding: 8px 11px;
    color: var(--ui-text);
    font-size: 11px;
    font-family: var(--ui-font);
    outline: none;
    cursor: pointer;
}
.ai-config-select option { background: var(--ui-bg-deep, #111114); color: var(--ui-text); }
.ai-config-label {
    padding: 5px 11px;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: var(--ui-text-muted);
    border-bottom: 1px solid var(--ui-border);
    user-select: none;
    font-family: var(--ui-font);
}
.ai-config-field {
    width: 100%;
    box-sizing: border-box;
    min-height: 46px;
    max-height: 120px;
    background: transparent;
    border: none;
    padding: 8px 11px;
    color: var(--ui-text);
    font-size: 11px;
    font-family: var(--ui-font);
    line-height: 1.5;
    resize: none;
    outline: none;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--ui-border) transparent;
    display: block;
}
.ai-config-field::placeholder { color: var(--ui-text-muted); }

/* Блок ошибки */
.ai-error-msg {
    padding: 7px 14px;
    font-size: 11px;
    line-height: 1.5;
    color: #fca5a5;
    background: rgba(239, 68, 68, 0.1);
    border-bottom: 1px solid rgba(239, 68, 68, 0.2);
}

/* Список сцен */
.ai-results-list {
    border-top: 1px solid var(--ui-border);
}

.ai-scene-count {
    padding: 8px 14px;
    font-size: 12px;
    color: var(--ui-text-dim);
    font-family: var(--ui-font);
    text-align: center;
}
.ai-scene-count b { color: var(--ui-text); font-size: 14px; }
.ai-scene-count.empty { color: var(--ui-text-muted); font-style: italic; }

/* Подвал */
.ai-footer { padding: 10px 14px; }

.ai-footer .ai-run-btn {
    width: 100%;
    padding: 10px 0;
    border-radius: var(--ui-radius-sm);
    border: 1px solid var(--ui-border);
    background: var(--ui-bg-hover);
    color: var(--ui-text);
    font-weight: 600;
    font-size: 13px;
    cursor: pointer;
    transition: opacity 0.2s, background 0.2s, border-color 0.2s;
    font-family: var(--ui-font);
}
.ai-footer .ai-run-btn:hover:not(:disabled) { 
    background: var(--ui-accent); 
    border-color: var(--ui-accent-hover);
    color: #fff;
}
.ai-footer .ai-run-btn.loading {
    background: var(--ui-bg-input);
    border-color: rgba(239, 68, 68, 0.5);
    color: #fca5a5;
    opacity: 1;
    cursor: pointer;
}
.ai-footer .ai-run-btn.loading:hover {
    background: rgba(239, 68, 68, 0.2);
}

/* ═══════════════════════════════════════════════════════════════
   Нода раскадровки — image_board
   ═══════════════════════════════════════════════════════════════ */

.tl-block.imgboard-node {
    background: var(--ui-bg);
    border-radius: var(--ui-radius);
    border: 1px solid var(--ui-border);
    box-shadow: var(--ui-shadow);
    width: 220px;
    height: auto !important;
    min-height: 0 !important;
    display: flex;
    flex-direction: column;
    padding: 0;
}

.tl-block.imgboard-node > .imgboard-header {
    border-radius: var(--ui-radius) var(--ui-radius) 0 0;
    overflow: hidden;
}
.tl-block.imgboard-node > .imgboard-thumb {
    border-radius: 0 0 var(--ui-radius) var(--ui-radius);
    overflow: hidden;
}

.imgboard-thumb img {
    -webkit-user-drag: none;
    user-drag: none;
    pointer-events: none;
}

.tl-block.imgboard-node.active {
    border-color: var(--ui-border-focus);
    box-shadow: 0 0 0 1px var(--ui-accent-glow), var(--ui-shadow);
}

.imgboard-header {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 9px 12px 7px;
    background: var(--ui-bg-deep);
    border-bottom: 1px solid var(--ui-border);
    flex-shrink: 0;
}

.imgboard-icon { font-size: 13px; line-height: 1; opacity: 0.7; }

.imgboard-title {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--ui-text-dim);
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.imgboard-count {
    font-size: 9px;
    font-weight: 600;
    color: var(--ui-text);
    background: var(--ui-bg-hover);
    padding: 2px 7px;
    border-radius: 20px;
    white-space: nowrap;
    font-family: var(--ui-font-mono);
    letter-spacing: 0.3px;
}

.imgboard-thumb {
    width: 100%;
    aspect-ratio: 16 / 9;
    background: #000;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0;
    color: transparent;
    position: relative;
    flex-shrink: 0;
    overflow: hidden;
}

.imgboard-thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

/* Мета-порт IN (сверху) */
.imgboard-meta-in {
    position: absolute;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--ui-bg-deep);
    border: 1.5px solid var(--ui-border);
    box-shadow: 0 0 0 2px rgba(0,0,0,0.1), 0 2px 8px rgba(0,0,0,0.4);
    cursor: crosshair;
    z-index: 110;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 9px;
    color: var(--ui-text-dim);
    transition: border-color 0.15s, box-shadow 0.15s;
    pointer-events: all;
}
.imgboard-meta-in:hover {
    border-color: var(--ui-accent);
    box-shadow: 0 0 0 2px var(--ui-accent-glow), 0 2px 12px rgba(0,0,0,0.3);
}

/* Side-порты внутри imgboard-node — выровнены по центру высоты */
.tl-block.imgboard-node .port-in,
.tl-block.imgboard-node .port-out {
    top: 50%;
    transform: translateY(-50%);
}

.tl-block.imgboard-node .port-in::after,
.tl-block.imgboard-node .port-out::after {
    background: var(--ui-accent);
    border-color: var(--ui-border);
}

.tl-block.budget-node {
    background-color: var(--ui-bg-deep) !important;
    background-image: 
        linear-gradient(rgba(72, 130, 126, 0.08) 1px, transparent 1px),
        linear-gradient(90deg, rgba(72, 130, 126, 0.08) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.35)) !important;
    background-size: 10px 10px, 10px 10px, 100% 100% !important;
    border-color: rgba(72, 130, 126, 0.3) !important;
}

.tl-block.budget-node.active {
    border-color: var(--ui-accent) !important;
    box-shadow: 0 0 15px var(--ui-accent-glow) !important;
}
/* ⚡ Тач: перетаскивание нод не должно выделять текст/запускать iOS callout.
   Редактируемые заголовки (contenteditable) — исключаем. */
#node-canvas,
#node-canvas .tl-block {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
}
#node-canvas [contenteditable="true"],
#node-canvas input,
#node-canvas textarea {
    -webkit-user-select: text;
    -moz-user-select: text;
    user-select: text;
}

/* ⚡ Зум-контрол + миникарта графа — статичные стили, чтобы кнопки не
   мелькали без оформления при загрузке (раньше CSS инжектился из JS). */
#graph-zoom-control {
    position: absolute; left: 14px; bottom: 14px; z-index: 40;
    display: flex; align-items: center; gap: 1px;
    background: rgba(20,20,24,0.85); border: 1px solid rgba(255,255,255,0.1);
    border-radius: 8px; overflow: hidden; backdrop-filter: blur(6px);
    font-family: 'Manrope', sans-serif;
}
#graph-zoom-control button {
    border: none; background: transparent; color: rgba(255,255,255,0.7);
    cursor: pointer; font-size: 13px; font-weight: 700; height: 28px;
    font-family: inherit; transition: background 0.12s;
}
#graph-zoom-control button:hover { background: rgba(255,255,255,0.08); color: #fff; }
#graph-zoom-out, #graph-zoom-in { width: 30px; }
#graph-zoom-pct { min-width: 54px; font-size: 11px; font-variant-numeric: tabular-nums; }
#graph-minimap {
    position: absolute; right: 14px; bottom: 14px; z-index: 40;
    width: 180px; height: 120px; border-radius: 8px; overflow: hidden;
    background: rgba(20,20,24,0.85); border: 1px solid rgba(255,255,255,0.1);
    backdrop-filter: blur(6px); cursor: pointer;
}
#graph-minimap canvas { display: block; width: 100%; height: 100%; }

/* ⚡ Минимизация ноды (видео/раскадровка/canvas) до плитки — только хедер
   и порты, без превью/ячеек. Высота схлопывается до строки хедера. */
.tl-block.minimized {
    min-height: 0 !important;
    height: auto !important;
    overflow: visible !important;   /* порты IN/OUT торчат на 15px за край — не обрезаем */
}
.tl-block.minimized > *:not(.imgboard-header):not(.port) {
    display: none !important;
}
.tl-block.minimized .imgboard-header {
    border-radius: 6px;
    margin: 0;
}
/* порты поверх свёрнутой шапки + ЦЕНТРИРУЕМ их по высоте короткой плитки прямо
   в CSS (синхронно). Раньше позицию выставлял JS в requestAnimationFrame уже
   ПОСЛЕ сборки карточки — и отрисовка связей успевала замерить порт на старом
   месте (top:45px из базового .port), отчего провода «дёргались» каждый кадр. */
.tl-block.minimized .port-in,
.tl-block.minimized .port-out {
    z-index: 30;
    top: 50% !important;
}

/* ⚡ Подсветка выделенного модуля сцены (Shift/Ctrl-клик или рамка) — для
   группового действия: тянуть OUT-порт → создать ноду на каждый модуль. */
.tl-module.module-selected {
    outline: 2px solid #65dcb4;
    outline-offset: 1px;
    box-shadow: 0 0 10px rgba(101, 220, 180, 0.55);
}


/* ⚡ Точечные цели ИИ-агента: блоки сцены, подключённые проводом от порта модуля */
.ai-module-targets { display:flex; flex-wrap:wrap; gap:4px; padding:6px 12px 0; }
.ai-module-chip {
    display:inline-flex; align-items:center; gap:5px; max-width:100%;
    padding:3px 6px; border-radius:5px; background:var(--ui-bg-input);
    border:1px solid var(--ui-border); font-size:9px; color:var(--ui-text-dim);
}
.ai-module-chip b { color:var(--ui-accent); font-weight:700; letter-spacing:.04em; text-transform:uppercase; }
.ai-module-chip span { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ai-module-chip i { cursor:pointer; font-style:normal; padding:0 2px; opacity:.6; }
.ai-module-chip i:hover { opacity:1; color:#e05252; }

/* ⚡ v166. Секция, выключенная тумблером (общий стиль), остаётся видимой и
   редактируемой — гаснет только её вклад в промт. Приглушаем, чтобы состояние
   читалось с одного взгляда, но не прячем: текст общий на проект, и правят его
   отсюда же. */
.aig-sec.aig-sec-off > textarea,
.aig-sec.aig-sec-off > .aig-hint,
.vai-sec.vai-sec-off > textarea,
.vai-sec.vai-sec-off > .vai-hint { opacity: 0.4; }

/* ⚡ v167. Чипы блоков текстовой ноды на карточке ИИ-агента. Форма — у чипов
   точечных целей (.ai-module-chip), отличается только состояние выбора:
   невыбранный приглушён, выбранный — обычной яркости. */
.ai-textblocks .ai-module-chip { opacity: 0.45; cursor: pointer; }
.ai-textblocks .ai-module-chip.on { opacity: 1; }
.ai-textblocks .ai-chip-unlink { opacity: 0.6; }
.ai-textblocks .ai-chip-unlink:hover { opacity: 1; color: #ff6b6b; }
