(function (global) {
  'use strict';

  /**
   * Информационная картина (InfoPicture) — оперативный контекст осмысления.
   * Не сохраняется между сессиями; при перезагрузке восстанавливается по текущей активности.
   */
  function ensureInfoPicture() {
    if (!global.InfoPicture) {
      global.InfoPicture = {
        themeId: 0,
        situationId: 0,
        problemFinalImageId: 0,   // связана с unsolved_problem
        step: 0,
        tree: {
          baseID: 0,
          emotionID: 0,
          activityID: 0,
          toneMoodID: 0,
          simbolID: 0,
          phraseID: 0
        },
        stimulus: {
          source: 'external',     // 'external' | 'imagination'
          finalImageId: 0
        },
        // Детекторные переменные инфокартины (целые числа, по умолчанию 0):
        // criticalVital: 0 — нет, >0 — ID критического витала.
        criticalVital: 0,
        // shockState: 0 — нет, 1 — шоковое состояние активно.
        shockState: 0,
        // suddenChange: 0 — нет, |value| — величина резкого изменения состояния (нормализованная).
        suddenChange: 0,
        // playMode: 0 — нет, 1 — игровой режим активен.
        playMode: 0,
        // learningMode: 0 — нет, 1 — режим обучения активен.
        learningMode: 0,
        // isPlayMode / isLearningMode — дубль для ур.3 (синхрон с playMode / learningMode на ур.2).
        isPlayMode: 0,
        isLearningMode: 0,
        // negativeMotorEffect: 0 — нет, <0 — сумма/уровень негативного эффекта моторных автоматизмов.
        negativeMotorEffect: 0,
        // negativeMentalEffect: 0 — нет, <0 — сумма/уровень негативного эффекта ментальных автоматизмов.
        negativeMentalEffect: 0,
        // badState: 0 — не Плохо, 1 — состояние Плохо активно.
        badState: 0,
        // consoleStimulus: 0 — нет, >0 — ID последнего стимула с пульта.
        consoleStimulus: 0,
        // searchInterest: 0 — нет, 1 — поисковый интерес активен.
        searchInterest: 0,
        // teacherLearning: 0 — нет, 1 — идёт обучение с учителем.
        teacherLearning: 0,
        // operatorIgnoring: 0 — нет, 1 — оператор игнорирует.
        operatorIgnoring: 0,
        // dissatisfaction: 0 — нет, 1 — есть неудовлетворённость существующим.
        dissatisfaction: 0,
        // isDissatisfaction: 0 — нет, 1 — активна «неудовлетворённость существующим» (триггер 3-го уровня).
        isDissatisfaction: 0,
        // misunderstanding: 0 — нет, 1 — состояние непонимания.
        misunderstanding: 0,
        // doubtInDefaultAutomatism: 0 — нет, 1 — есть сомнение в штатном автоматизме.
        doubtInDefaultAutomatism: 0,
        // defense: 0 — нет, 1 — активен режим защиты.
        defense: 0,
        // fear: 0 — нет, 1 — страх активен.
        fear: 0,
        // aggression: 0 — нет, 1 — агрессия активна.
        aggression: 0,
        // highImportanceObject: 0 — нет, >0 — ID объекта высокой значимости.
        highImportanceObject: 0,
        // moodImproving: 0 — нет, >0 — величина улучшения настроения.
        moodImproving: 0,
        // imageNovelty: 0 — нет, >0 — уровень новизны образа.
        imageNovelty: 0,
        // highSemanticImportance: 0 — нет, >0 — величина высокой семантической значимости.
        highSemanticImportance: 0,
        // conflictingSemantics: 0 — нет, 1 — обнаружена противоречивая семантика.
        conflictingSemantics: 0,
        // hardProblem: 0 — нет, >0 — счётчик попыток/уровень трудности проблемы.
        hardProblem: 0,
        // positiveActionEffect: 0 — нет, >0 — величина последнего положительного эффекта.
        positiveActionEffect: 0,
        // negativeActionEffect: 0 — нет, <0 — величина последнего отрицательного эффекта.
        negativeActionEffect: 0,
        // noReactionToStimulus: 0 — нет, 1 — зафиксировано отсутствие реакции.
        noReactionToStimulus: 0,
        // operatorAnswerReceived: 0 — нет, 1 — ответ оператора получен.
        operatorAnswerReceived: 0,
        // isOperatorAnswerReceived: 0 — нет, 1 — ответ именно на реакцию после автоматизма ФО (в т.ч. для ур.2).
        isOperatorAnswerReceived: 0,
        // activeWaitingAnswer: 0 — нет, 1 — активное ожидание ответа.
        activeWaitingAnswer: 0,
        // seriesWithoutEffect: 0 — нет, >0 — длина последней серии эпизодов без эффекта.
        seriesWithoutEffect: 0,
        // lowAutomatismUsefulness: 0 — нет, <0 — уровень низкой полезности автоматизма.
        lowAutomatismUsefulness: 0,
        // foundSuitableAutomatism: 0 — нет, >0 — ID/признак найденного подходящего автоматизма.
        foundSuitableAutomatism: 0,
        // ImportantProblem: 0 — нет, 1 — «это важная проблема» (критические виталы); гистерезис внимания к стимулам, при 0 — облегчённый ОР/ФО.
        ImportantProblem: 0,
        // usedRule: 0 — реакция не по запомненному правилу; ≠0 — активно реагирование по правилу (флаг или id правила по договорённости вызывающего кода).
        usedRule: 0,
        // Сюжет фантазма: пополняемый массив снимков кадров ЭП (для ячейки UI); пополняется при target→passive и на каждом шаге info_fantasizming.
        fantasmPlotRules: [],
        // Кто «двигает» отображаемый ход мысли: external — реальный стимул; imagination — Info_updateFromStimulus(..., 'imagination'); fantasy — шаг info_fantasizming (пассивная цепочка).
        thinkingSource: 'external'
      };
      // Текущая цель (устанавливается на втором уровне осмысления).
      global.InfoPicture.currentGoalType = null;   // 'base' | 'life' | 'voluntary' | 'meaning' | null
      global.InfoPicture.currentGoalId = 0;       // id образа цели (life/voluntary)
      global.InfoPicture.currentGoalVitalId = 0;  // для базовой цели — ID витала
    } else {
      var pic = global.InfoPicture;
      if (pic.currentGoalType === undefined) pic.currentGoalType = null;
      if (pic.currentGoalId === undefined) pic.currentGoalId = 0;
      if (pic.currentGoalVitalId === undefined) pic.currentGoalVitalId = 0;
      if (pic.isDissatisfaction === undefined) pic.isDissatisfaction = 0;
      if (pic.ImportantProblem === undefined) pic.ImportantProblem = 0;
      if (pic.usedRule === undefined) pic.usedRule = 0;
      if (pic.isOperatorAnswerReceived === undefined) pic.isOperatorAnswerReceived = 0;
      if (pic.isPlayMode === undefined) pic.isPlayMode = 0;
      if (pic.isLearningMode === undefined) pic.isLearningMode = 0;
      if (pic.fantasmPlotRules === undefined || !Array.isArray(pic.fantasmPlotRules)) pic.fantasmPlotRules = [];
      if (pic.thinkingSource === undefined) pic.thinkingSource = 'external';
      if (pic.mode !== undefined) delete pic.mode;
    }
    return global.InfoPicture;
  }

  /** Снимки кадров ЭП как «правила» для сюжета фантазма / fantasizmArr (заглушка до финального алгоритма). */
  function snapshotEpisodicRulesForFantasm(maxN) {
    maxN = typeof maxN === 'number' && maxN > 0 ? maxN : 8;
    var out = [];
    var ep = global.Episodes;
    if (!Array.isArray(ep) || !ep.length) return out;
    for (var i = ep.length - 1; i >= 0 && out.length < maxN; i--) {
      var f = ep[i];
      if (!f) continue;
      out.push({
        perceptionNodeId: f.perceptionNodeId || 0,
        stimulusImageId: f.stimulusImageId || 0,
        situationId: f.situationId || 0,
        actionImageId: f.actionImageId != null ? f.actionImageId : null,
        effect: f.effect != null ? f.effect : null,
        responseStimulusImageId: f.responseStimulusImageId != null ? f.responseStimulusImageId : null
      });
    }
    return out;
  }

  /**
   * Переход инфокартины в пассивный режим (целевой → пассивный): заполнить сюжет фантазма.
   * TODO: заменить на целевой алгоритм подбора правил ЭП.
   */
  function Info_fillFantasmPlotOnPassiveMain() {
    var info = ensureInfoPicture();
    info.fantasmPlotRules = snapshotEpisodicRulesForFantasm(12);
  }

  /**
   * Первый шаг фонового цикла в глобальном пассивном режиме: заполнить fantasizmArr цикла.
   * TODO: заменить на целевой алгоритм.
   */
  function Info_fillFantasmPlotOnPassiveBackground(cycle) {
    if (!cycle) return;
    cycle.fantasizmArr = snapshotEpisodicRulesForFantasm(8);
  }

  function setByPath(obj, path, value) {
    if (!obj || !path) return;
    var parts = path.split('.');
    var cur = obj;
    for (var i = 0; i < parts.length - 1; i++) {
      var k = parts[i];
      if (!cur[k] || typeof cur[k] !== 'object') {
        cur[k] = {};
      }
      cur = cur[k];
    }
    cur[parts[parts.length - 1]] = value;
  }

  function getCell(id) {
    return global.document && global.document.getElementById(id);
  }

  /** Ссылка в show_alert: щелчок перезагружает диалог с детализацией по ID. */
  function infoAlertIdLink(handlerName, id) {
    var n = parseInt(id, 10);
    if (isNaN(n)) n = 0;
    return '<span style="cursor:pointer;color:#1976d2;text-decoration:underline" onclick="' + handlerName + '(' + n + ')">' + String(n) + '</span>';
  }

  /** Поля объектов Abstractions: обработчик детализации по имени ключа (для «своей» детализации ID). */
  var INFO_ABSTRACTION_FIELD_LINK = {
    perceptionNodeId: 'Info_showPerceptionNodeDetail',
    stimulusImageId: 'Info_showFinalImageStimulusDetail',
    actionImageId: 'Info_showActionImageDetail',
    sourceActionImageId: 'Info_showActionImageDetail',
    abstractPerceptionId: 'Info_showAbstractPerceptionImageDetail',
    abstractActionId: 'Info_showAbstractActionImageDetail',
    abstractionId: 'Info_showAbstractionDetail',
    mentalActionImageId: 'Info_showMentalActionImageDetail',
    themeId: 'Info_showThemeImageDetail',
    situationId: 'Info_showSituationImageDetail'
  };

  var INFO_ABSTRACTION_FIELD_LABEL = {
    perceptionNodeId: 'Узел ветки восприятия',
    stimulusImageId: 'Жёсткий стимул (клон с него)',
    actionImageId: 'Жёсткий образ действия (ОД)',
    sourceActionImageId: 'Исходный ОД',
    abstractPerceptionId: 'Клон восприятия (AbstractPerceptionImages)',
    abstractActionId: 'Клон действия (AbstractActionImages)',
    abstractionId: 'Символ Abstractions',
    mentalActionImageId: 'Ментальный ОД',
    themeId: 'Образ темы',
    situationId: 'Образ ситуации',
    meanImportance: 'Средняя значимость (уср.)',
    meanEffect: 'Средний эффект',
    count: 'Число усреднений',
    createdAt: 'Создан',
    lastUsedAt: 'Последнее использование',
    semanticStructure: 'Семантическая структура'
  };

  /** semanticStructure абстракции: кадры условий (ветка + ситуация) и правило ЭП / учительское. */
  function infoFormatAbstractSemanticStructureHtml(sem) {
    if (!sem || typeof sem !== 'object') return '<br><i>semanticStructure:</i> —';
    var frames = sem.frames;
    if (!Array.isArray(frames) || !frames.length) {
      return '<br><i>semanticStructure:</i> нет кадров (0 условий)';
    }
    var parts = ['<br><b>semanticStructure</b> — по условиям (узел восприятия + ситуация), ' + frames.length + ' кадр(ов):'];
    for (var si = 0; si < frames.length; si++) {
      var fr = frames[si];
      if (!fr) continue;
      var rk = fr.ruleKind || '—';
      parts.push('<br>— <b>' + rk + '</b>: узел ' + (fr.perceptionNodeId || 0) + ', ситуация ' + (fr.situationId || 0));
      parts.push('<br> &nbsp; стимул FinalImageId=' + (fr.stimulusImageId || 0) + ', ОД=' + (fr.actionImageId != null ? fr.actionImageId : '—'));
      if (rk === 'teacher' || (fr.responseStimulusImageId != null && fr.responseStimulusImageId > 0)) {
        parts.push(', ответ оператора FinalImageId=' + (fr.responseStimulusImageId || 0));
      }
      if (typeof fr.effect === 'number') {
        parts.push(', effect=' + fr.effect);
      }
    }
    return parts.join('');
  }

  function infoFormatAbstractionFieldValue(key, val) {
    if (key === 'abstractActionIds' && Array.isArray(val)) {
      if (!val.length) return '—';
      var parts = [];
      for (var ai = 0; ai < val.length; ai++) {
        if (ai) parts.push(', ');
        var ab = parseInt(val[ai], 10) || 0;
        parts.push(ab ? infoAlertIdLink('Info_showAbstractionDetail', ab) : '0');
      }
      return parts.join('');
    }
    if (val != null && typeof val === 'object') {
      try {
        return JSON.stringify(val);
      } catch (e) {
        return String(val);
      }
    }
    var handler = INFO_ABSTRACTION_FIELD_LINK[key];
    var n = typeof val === 'number' ? val : parseInt(val, 10);
    if (handler && !isNaN(n) && n > 0) {
      return infoAlertIdLink(handler, n);
    }
    if ((key === 'createdAt' || key === 'lastUsedAt') && typeof val === 'number' && val > 0) {
      try {
        return new Date(val).toLocaleString();
      } catch (e2) {
        return String(val);
      }
    }
    return String(val);
  }

  /**
   * Ссылка на образ ситуации: готовые (ready) обводятся синим бордером в списках детализации.
   * @param {{id:number, ready?:boolean}|null} sv
   */
  function infoSituationImageLinkFromRecord(sv) {
    if (!sv || typeof sv.id !== 'number') return '';
    var n = sv.id;
    var ready = sv.ready === true;
    var base = 'cursor:pointer;color:#1976d2;text-decoration:underline;';
    var box = ready
      ? 'border:2px solid #1976d2;border-radius:4px;padding:1px 5px;display:inline-block;margin:0 1px;vertical-align:baseline;'
      : '';
    return '<span style="' + base + box + '" onclick="Info_showSituationImageDetail(' + n + ')">' + String(n) + '</span>';
  }

  function infoSituationImageLinkById(sitId) {
    var n = parseInt(sitId, 10) || 0;
    if (!n) return '0';
    var sv = typeof global.SituationsTree_getSituationImage === 'function'
      ? global.SituationsTree_getSituationImage(n) : null;
    if (sv) return infoSituationImageLinkFromRecord(sv);
    return infoAlertIdLink('Info_showSituationImageDetail', n);
  }

  function Info_showFinalImageStimulusDetail(finalImageId) {
    if (typeof global.show_alert !== 'function') return;
    finalImageId = parseInt(finalImageId, 10) || 0;
    if (!finalImageId) {
      global.show_alert('FinalImageId = 0.', 0);
      return;
    }
    var names = '';
    if (typeof global.PerceptionTree_getStimulusNamesForFinalImageId === 'function') {
      names = global.PerceptionTree_getStimulusNamesForFinalImageId(finalImageId) || '';
    }
    var html = '<b>Конечный образ FinalImageId:</b> ' + infoAlertIdLink('Info_showFinalImageStimulusDetail', finalImageId) +
      '<br><b>Стимулы:</b> ' + (names && names !== '—' ? names : '—');
    if (typeof global.getSemanticObjectFast === 'function') {
      var well = global.BadNormWell || 0;
      var emotionId = 0;
      if (typeof global.Emotions_getOrCreateEmotionId === 'function' && Array.isArray(global.BasicContextsActived)) {
        emotionId = global.Emotions_getOrCreateEmotionId(global.BasicContextsActived) || 0;
      }
      var semObj = (well && emotionId) ? global.getSemanticObjectFast(well, emotionId, finalImageId) : null;
      if (semObj) {
        html += '<br><br><b>Семантика (текущие well/emotion):</b> z ≈ ' +
          (Math.round(semObj.meanImportance * 100) / 100) + ', обучений: ' + semObj.samplesCount;
      }
    }
    global.show_alert(html, 0);
  }

  function Info_showPerceptionNodeDetail(nodeId) {
    if (typeof global.show_alert !== 'function') return;
    nodeId = parseInt(nodeId, 10) || 0;
    if (!nodeId || typeof global.PerceptionTree_getNode !== 'function') {
      global.show_alert('Узел ветки #' + nodeId + ' не найден.', 0);
      return;
    }
    var node = global.PerceptionTree_getNode(nodeId);
    if (!node) {
      global.show_alert('Узел ветки #' + nodeId + ' не найден в дереве восприятия.', 0);
      return;
    }
    var actId = node.activityID || 0;
    var actDetail = '';
    if (actId && typeof global.PerceptionTree_getStimulusNamesForFinalImageId === 'function') {
      actDetail = global.PerceptionTree_getStimulusNamesForFinalImageId(actId) || '';
    }
    var html = '<b>Узел ветки (branchId) ' + infoAlertIdLink('Info_showPerceptionNodeDetail', nodeId) + '</b>' +
      '<br>BaseID: ' + (node.baseID || 0) +
      '<br>EmotionID: ' + (node.emotionID || 0) +
      '<br>ActivityID: ' + (actId ? infoAlertIdLink('Info_showFinalImageStimulusDetail', actId) : '0') +
      (actDetail && actDetail !== '—' ? '<br><i>Актуальный образ:</i> ' + actDetail : '') +
      '<br>ToneMoodID: ' + (node.toneMoodID || 0) +
      '<br>SimbolID: ' + (node.simbolID || 0) +
      '<br>PhraseID: ' + (node.phraseID || 0) +
      '<br>parentId: ' + (node.parentId != null ? node.parentId : '—');
    global.show_alert(html, 0);
  }

  function Info_showEmotionRecordDetail(emotionId) {
    if (typeof global.show_alert !== 'function') return;
    emotionId = parseInt(emotionId, 10) || 0;
    if (!emotionId) {
      global.show_alert('emotionId = 0.', 0);
      return;
    }
    var em = null;
    if (Array.isArray(global.Emotions)) {
      for (var ei = 0; ei < global.Emotions.length; ei++) {
        if (global.Emotions[ei] && global.Emotions[ei].id === emotionId) {
          em = global.Emotions[ei];
          break;
        }
      }
    }
    if (!em) {
      global.show_alert('Запись эмоции #' + emotionId + ' не найдена.', 0);
      return;
    }
    var parts = ['<b>Эмоция (emotionId) ' + infoAlertIdLink('Info_showEmotionRecordDetail', emotionId) + '</b>'];
    var emotionContexts = em.contextIds || [];
    if (emotionContexts.length && Array.isArray(global.BasicContexts)) {
      var names = [];
      for (var ci = 0; ci < emotionContexts.length; ci++) {
        var cid = emotionContexts[ci];
        var found = false;
        for (var bj = 0; bj < global.BasicContexts.length; bj++) {
          if (global.BasicContexts[bj] && global.BasicContexts[bj].id === cid) {
            names.push(global.BasicContexts[bj].name || ('Контекст ' + cid));
            found = true;
            break;
          }
        }
        if (!found) names.push('id ' + cid);
      }
      parts.push('<br><b>Базовые контексты:</b> ' + names.join(', '));
    } else {
      parts.push('<br>Контексты: —');
    }
    global.show_alert(parts.join(''), 0);
  }

  function Info_showCycleDetailById(cycleId) {
    if (typeof global.show_alert !== 'function') return;
    cycleId = parseInt(cycleId, 10);
    if (isNaN(cycleId) || cycleId <= 0) return;
    var getCycle = global.Consciousness_getCycle;
    var cycle = typeof getCycle === 'function' ? getCycle(cycleId) : null;
    if (!cycle) {
      global.show_alert('Цикл с ID ' + String(cycleId) + ' не найден в реестре.', 0);
      return;
    }
    var mainId = typeof global.ConsciousnessCurrentProcessId === 'number' ? global.ConsciousnessCurrentProcessId : 0;
    var prefix = (cycleId === mainId && mainId) ? 'Главный цикл' : ('Цикл №' + String(cycleId));
    global.show_alert(formatCycleOrStackInfo(cycle, prefix), 0);
  }

  var thinkingTimer = null;

  /**
   * Кратковременная индикация «ориентировочного эффекта» осмысления:
   * зажигает синюю лампочку рядом с заголовком «Информационная картина» на 0.5 секунды.
   */
  function Info_thinkingFlash() {
    if (!global.document) return;
    var el = getCell('infoThinkingIndicator');
    if (!el) return;
    el.classList.add('on');
    if (thinkingTimer !== null) {
      global.clearTimeout(thinkingTimer);
    }
    thinkingTimer = global.setTimeout(function () {
      el.classList.remove('on');
      thinkingTimer = null;
    }, 500);
  }

  /**
   * Обновить индикацию инфокартины на главной странице.
   * Вызывается автоматически при каждом изменении InfoPicture.
   */
  function Info_updateView() {
    var info = ensureInfoPicture();
    if (!global.document) return;

    var mainThinking = (typeof global.Consciousness_getMainCycleThinkingMode === 'function')
      ? global.Consciousness_getMainCycleThinkingMode()
      : 'target';
    if (info._fantasmPrevMainThinkingMode === undefined) {
      info._fantasmPrevMainThinkingMode = mainThinking;
    } else {
      if (mainThinking === 'passive' && info._fantasmPrevMainThinkingMode === 'target') {
        Info_fillFantasmPlotOnPassiveMain();
      }
      info._fantasmPrevMainThinkingMode = mainThinking;
    }

    var modeCell = getCell('infoModeCell');
    var themeCell = getCell('infoThemeCell');
    var situationCell = getCell('infoSituationCell');
    var problemCell = getCell('infoProblemCell');
    var stepCell = getCell('infoStepCell');
    var stimCell = getCell('infoStimulusCell');
    var baseCell = getCell('infoBaseCell');
    var emoCell = getCell('infoEmotionCell');
    var actCell = getCell('infoActivityCell');
    // Детекторные ячейки
    var detCriticalVital = getCell('infoDetCriticalVital');
    var detImportantProblem = getCell('infoDetImportantProblem');
    var detUsedRule = getCell('infoDetUsedRule');
    var detShockState = getCell('infoDetShockState');
    var detSuddenChange = getCell('infoDetSuddenChange');
    var detPlayMode = getCell('infoDetPlayMode');
    var detLearningMode = getCell('infoDetLearningMode');
    var detNegativeMotor = getCell('infoDetNegativeMotor');
    var detNegativeMental = getCell('infoDetNegativeMental');
    var detBadState = getCell('infoDetBadState');
    var detConsoleStimulus = getCell('infoDetConsoleStimulus');
    var detSearchInterest = getCell('infoDetSearchInterest');
    var detTeacherLearning = getCell('infoDetTeacherLearning');
    var detOperatorIgnoring = getCell('infoDetOperatorIgnoring');
    var detDissatisfaction = getCell('infoDetDissatisfaction');
    var detMisunderstanding = getCell('infoDetMisunderstanding');
    var detDoubtAuto = getCell('infoDetDoubtAuto');
    var detDefense = getCell('infoDetDefense');
    var detFear = getCell('infoDetFear');
    var detAggression = getCell('infoDetAggression');
    var detHighObj = getCell('infoDetHighObj');
    var detMoodImproving = getCell('infoDetMoodImproving');
    var detImageNovelty = getCell('infoDetImageNovelty');
    var detHighSem = getCell('infoDetHighSem');
    var detConfSem = getCell('infoDetConfSem');
    var detHardProblem = getCell('infoDetHardProblem');
    var detPosEffect = getCell('infoDetPosEffect');
    var detNegEffect = getCell('infoDetNegEffect');
    var detNoReaction = getCell('infoDetNoReaction');
    var detAnswer = getCell('infoDetAnswer');
    var detActiveWait = getCell('infoDetActiveWait');
    var detSeriesNoEffect = getCell('infoDetSeriesNoEffect');
    var detLowAutoUse = getCell('infoDetLowAutoUse');
    var detFoundAuto = getCell('infoDetFoundAuto');
    var bgCountLabel = getCell('infoBackgroundCountLabel');
    var interruptQueueLabel = getCell('infoInterruptQueueLabel');
    var bgStackIndicator = getCell('infoBackgroundStackIndicator');
    var motorAutoInd = getCell('infoMotorAutomatizmsIndicator');
    var mentalAutoInd = getCell('infoMentalAutomatizmsIndicator');
    var abstrInd = getCell('infoAbstractionsIndicator');
    var lifeGoalsInd = getCell('infoLifeGoalsIndicator');
    var situationImagesInd = getCell('infoSituationImagesIndicator');
    var mainProcessLabel = getCell('infoMainProcessLabel');

    if (modeCell) {
      var mt = (typeof global.Consciousness_getMainCycleThinkingMode === 'function')
        ? global.Consciousness_getMainCycleThinkingMode()
        : 'target';
      var modeTitle = (mt === 'target' ? 'Целевой (активный)' : 'Пассивный') + ' режим мышления (главный цикл)';
      modeCell.title = modeTitle;
      modeCell.classList.toggle('info-cell-active', true);
    }
    if (themeCell) {
      themeCell.title = info.themeId ? ('Тема #' + info.themeId) : 'Тема не активирована';
      themeCell.classList.toggle('info-cell-active', !!info.themeId);
    }
    if (situationCell) {
      situationCell.title = info.situationId ? ('Ситуация #' + info.situationId) : 'Ситуация не активирована';
      situationCell.classList.toggle('info-cell-active', !!info.situationId);
    }
    if (problemCell) {
      problemCell.title = info.problemFinalImageId
        ? ('Нерешённая проблема: FinalImageId=' + info.problemFinalImageId)
        : 'Нерешённая проблема отсутствует';
      problemCell.classList.toggle('info-cell-active', !!info.problemFinalImageId);
    }
    if (stepCell) {
      stepCell.title = 'Шаг осмысления: ' + String(info.step || 0);
      stepCell.classList.toggle('info-cell-active', info.step > 0);
    }
    if (stimCell) {
      stimCell.title = info.stimulus.finalImageId
        ? ('Актуальный стимул: FinalImageId=' + info.stimulus.finalImageId)
        : 'Актуальный стимул отсутствует';
      stimCell.classList.toggle('info-cell-active', !!info.stimulus.finalImageId);
    }
    if (baseCell || emoCell || actCell) {
      var treeTitle = 'Ветка дерева восприятия:\n' +
        'BaseID=' + (info.tree.baseID || 0) +
        ' → EmotionID=' + (info.tree.emotionID || 0) +
        ' → ActivityID=' + (info.tree.activityID || 0) +
        ' → ToneMoodID=' + (info.tree.toneMoodID || 0) +
        ' → SimbolID=' + (info.tree.simbolID || 0) +
        ' → PhraseID=' + (info.tree.phraseID || 0);
      if (baseCell) {
        baseCell.title = treeTitle;
        baseCell.classList.toggle('info-cell-active', !!info.tree.baseID);
      }
      if (emoCell) {
        emoCell.title = 'EmotionID=' + (info.tree.emotionID || 0) + '\n(щелчок — состав базовых контекстов)\n\n' + treeTitle;
        emoCell.classList.toggle('info-cell-active', !!info.tree.emotionID);
      }
      if (actCell) {
        var aId = info.tree.activityID || 0;
        var aNames = '';
        if (aId && typeof global.PerceptionTree_getStimulusNamesForFinalImageId === 'function') {
          aNames = global.PerceptionTree_getStimulusNamesForFinalImageId(aId) || '';
        }
        actCell.title = 'ActivityID=' + aId + (aNames ? ('\n' + aNames) : '') + '\n(щелчок — детализация активности)\n\n' + treeTitle;
        actCell.classList.toggle('info-cell-active', !!info.tree.activityID);
      }
    }

    // Индикаторы фоновых процессов и очереди прерываний.
    var bgCount = typeof global.Consciousness_getBackgroundCyclesCount === 'function'
      ? global.Consciousness_getBackgroundCyclesCount() : 0;
    var interruptQueueLen = Array.isArray(global.ConsciousnessBackgroundStack) ? global.ConsciousnessBackgroundStack.length : 0;
    if (bgCountLabel) {
      bgCountLabel.textContent = 'Чисто фоновых процессов: ' + String(bgCount);
    }
    if (interruptQueueLabel) {
      interruptQueueLabel.textContent = 'очередь прерываний: ' + String(interruptQueueLen);
      interruptQueueLabel.title = 'Число прерванных главных циклов в очереди на возврат (LIFO): ' + String(interruptQueueLen);
    }
    if (bgStackIndicator) {
      bgStackIndicator.textContent = 'фон: ' + String(bgCount);
      var title = 'Фоновые циклы осмысления (' + bgCount + '), по клику — детализация:';
      if (typeof global.Consciousness_getBackgroundCyclesList === 'function') {
        var list = global.Consciousness_getBackgroundCyclesList();
        for (var si = 0; si < list.length; si++) {
          var item = list[si];
          var ctx = item && item.context ? item.context : null;
          var stimId = ctx && typeof ctx.actual_stimul_ID === 'number' ? ctx.actual_stimul_ID : 0;
          title += '\nID ' + String(item && item.id != null ? item.id : '—') +
            ' — стимул FinalImageId=' + String(stimId) + ', значимость=' + String(item && typeof item.weight === 'number' ? item.weight : 0) +
            (item && item.expired ? ', expired' : '');
        }
      }
      bgStackIndicator.title = title;
    }

    var motorN = Array.isArray(global.Automatizms) ? global.Automatizms.length : 0;
    var mentalN = Array.isArray(global.MentalAutomatizms) ? global.MentalAutomatizms.length : 0;
    // «Клоны» из ЭП (abstract_images.js) — не путать с массивом Abstractions (символы mental_automatism.js).
    var apClones = Array.isArray(global.AbstractPerceptionImages) ? global.AbstractPerceptionImages.length : 0;
    var aaClones = Array.isArray(global.AbstractActionImages) ? global.AbstractActionImages.length : 0;
    var cloneAbstrN = apClones + aaClones;
    var mentalSymN = Array.isArray(global.Abstractions) ? global.Abstractions.length : 0;
    if (motorAutoInd) {
      motorAutoInd.textContent = 'авто: ' + String(motorN);
      motorAutoInd.title = 'Моторные автоматизмы (' + motorN + '), щелчок — список ID';
    }
    if (mentalAutoInd) {
      mentalAutoInd.textContent = 'м-авто: ' + String(mentalN);
      mentalAutoInd.title = 'Ментальные автоматизмы (' + mentalN + '), щелчок — список ID';
    }
    if (abstrInd) {
      var abstrLabel = String(cloneAbstrN);
      if (mentalSymN > 0) abstrLabel += '+' + String(mentalSymN);
      abstrInd.textContent = 'абстр: ' + abstrLabel;
      abstrInd.title = 'Три вида: клоны восприятия ' + apClones + ', клоны действия ' + aaClones
        + ' (abstract_images.js); символы Abstractions: ' + mentalSymN + ' (mental_automatism.js).'
        + ' Щелчок — сводка; в списке каждый ID ведёт в свою детализацию.';
    }
    var lifeGoalsArr = Array.isArray(global.GoalImagesLife) ? global.GoalImagesLife : [];
    var lifeGoalsN = 0;
    for (var gi = 0; gi < lifeGoalsArr.length; gi++) {
      if (lifeGoalsArr[gi] && typeof lifeGoalsArr[gi].id === 'number') lifeGoalsN += 1;
    }
    if (lifeGoalsInd) {
      lifeGoalsInd.textContent = 'цели: ' + String(lifeGoalsN);
      lifeGoalsInd.title = 'Образы целей жизненного опыта (GoalImagesLife), ' + lifeGoalsN + ' шт.; щелчок — список ID';
    }
    var sitImgN = 0;
    if (typeof global.SituationsTree_getAllSituationImages === 'function') {
      var sitArr = global.SituationsTree_getAllSituationImages() || [];
      sitImgN = sitArr.length;
    }
    if (situationImagesInd) {
      situationImagesInd.textContent = 'ситуации: ' + String(sitImgN);
      situationImagesInd.title = 'Образы ситуаций (SituationImages), ' + sitImgN + ' шт.; щелчок — список ID';
    }

    var gestaltInd = getCell('infoGestaltsIndicator');
    if (gestaltInd) {
      var gArr = Array.isArray(global.GestaltArr) ? global.GestaltArr : [];
      var gN = gArr.length;
      var rBuf = Array.isArray(global.GestaltResonanceBuffer) ? global.GestaltResonanceBuffer.length : 0;
      gestaltInd.textContent = 'гешт: ' + String(gN);
      gestaltInd.title = 'Гештальты (доминанты), записей: ' + gN
        + ', буфер резонанса (сигнатуры ЭП): ' + rBuf + '. Щелчок — список ID. См. beast/_9_Conscience/gestalt.js';
    }
    var fantasmInd = getCell('infoFantasmPlotIndicator');
    if (fantasmInd) {
      var fp = Array.isArray(info.fantasmPlotRules) ? info.fantasmPlotRules : [];
      var fpN = fp.length;
      fantasmInd.textContent = 'фант: ' + String(fpN);
      fantasmInd.title = 'Сюжет фантазма: правил ЭП в сюжете ' + fpN
        + '. Заполняется при переходе в пассивный режим (целевой→пассивный). Щелчок — детализация.';
    }
    var fantasmCell = getCell('infoFantasmPlotCell');
    if (fantasmCell) {
      var fp2 = Array.isArray(info.fantasmPlotRules) ? info.fantasmPlotRules : [];
      fantasmCell.title = 'Сюжет фантазма: ' + fp2.length + ' правил(а) снимков ЭП. Щелчок — список.';
      fantasmCell.classList.toggle('info-cell-active', fp2.length > 0);
    }

    // Индикатор текущего главного цикла осмысления (клик — детализация цикла).
    if (mainProcessLabel) {
      var mainId = typeof global.ConsciousnessCurrentProcessId === 'number'
        ? global.ConsciousnessCurrentProcessId
        : 0;
      var mainCyc = mainId && typeof global.Consciousness_getCycle === 'function'
        ? global.Consciousness_getCycle(mainId) : null;
      var mainExpired = !!(mainCyc && mainCyc.expired);
      mainProcessLabel.textContent = 'Главный цикл ID: ' + String(mainId) +
        (mainExpired ? ' · expired' : '');
      mainProcessLabel.title = 'Щелкните для детализации цикла' +
        (mainExpired ? '. Цикл помечен expired (отработан).' : '');
      mainProcessLabel.style.cursor = 'pointer';
      mainProcessLabel.onclick = function () {
        if (typeof global.Info_showMainCycleDetail === 'function') global.Info_showMainCycleDetail();
      };
    }

    // Детекторные индикаторы (желтая подсветка при активности)
    if (detCriticalVital) detCriticalVital.classList.toggle('info-cell-active', !!info.criticalVital);
    if (detImportantProblem) detImportantProblem.classList.toggle('info-cell-active', !!info.ImportantProblem);
    if (detUsedRule) {
      var urVal = typeof info.usedRule === 'number' ? info.usedRule : 0;
      var stArr = Array.isArray(global.Target_rule_stack) ? global.Target_rule_stack : [];
      var stTxt = stArr.length
        ? ('дно→верх: ' + stArr.map(function (x) { return String(x); }).join(', '))
        : 'стек пуст';
      detUsedRule.title = 'Реагирование по правилу (usedRule): ' + (urVal ? ('да (' + urVal + ')') : 'нет') +
        '\nTarget_rule_stack (до 3 ID цели): ' + stTxt;
      detUsedRule.classList.toggle('info-cell-active', !!urVal);
    }
    if (detShockState) detShockState.classList.toggle('info-cell-active', !!info.shockState);
    if (detSuddenChange) detSuddenChange.classList.toggle('info-cell-active', !!info.suddenChange);
    if (detPlayMode) detPlayMode.classList.toggle('info-cell-active', !!info.playMode);
    if (detLearningMode) detLearningMode.classList.toggle('info-cell-active', !!info.learningMode);
    if (detNegativeMotor) detNegativeMotor.classList.toggle('info-cell-active', !!info.negativeMotorEffect);
    if (detNegativeMental) detNegativeMental.classList.toggle('info-cell-active', !!info.negativeMentalEffect);
    if (detBadState) detBadState.classList.toggle('info-cell-active', !!info.badState);
    if (detConsoleStimulus) detConsoleStimulus.classList.toggle('info-cell-active', !!info.consoleStimulus);
    if (detSearchInterest) detSearchInterest.classList.toggle('info-cell-active', !!info.searchInterest);
    if (detTeacherLearning) detTeacherLearning.classList.toggle('info-cell-active', !!info.teacherLearning);
    if (detOperatorIgnoring) detOperatorIgnoring.classList.toggle('info-cell-active', !!info.operatorIgnoring);
    if (detDissatisfaction) detDissatisfaction.classList.toggle('info-cell-active', !!info.dissatisfaction);
    if (detMisunderstanding) detMisunderstanding.classList.toggle('info-cell-active', !!info.misunderstanding);
    if (detDoubtAuto) detDoubtAuto.classList.toggle('info-cell-active', !!info.doubtInDefaultAutomatism);
    if (detDefense) detDefense.classList.toggle('info-cell-active', !!info.defense);
    if (detFear) detFear.classList.toggle('info-cell-active', !!info.fear);
    if (detAggression) detAggression.classList.toggle('info-cell-active', !!info.aggression);
    if (detHighObj) detHighObj.classList.toggle('info-cell-active', !!info.highImportanceObject);
    if (detMoodImproving) detMoodImproving.classList.toggle('info-cell-active', !!info.moodImproving);
    if (detImageNovelty) detImageNovelty.classList.toggle('info-cell-active', !!info.imageNovelty);
    if (detHighSem) detHighSem.classList.toggle('info-cell-active', !!info.highSemanticImportance);
    if (detConfSem) detConfSem.classList.toggle('info-cell-active', !!info.conflictingSemantics);
    if (detHardProblem) detHardProblem.classList.toggle('info-cell-active', !!info.hardProblem);
    if (detPosEffect) detPosEffect.classList.toggle('info-cell-active', !!info.positiveActionEffect);
    if (detNegEffect) detNegEffect.classList.toggle('info-cell-active', !!info.negativeActionEffect);
    if (detNoReaction) detNoReaction.classList.toggle('info-cell-active', !!info.noReactionToStimulus);
    if (detAnswer) {
      detAnswer.classList.toggle('info-cell-active',
        !!(info.operatorAnswerReceived || info.isOperatorAnswerReceived));
    }
    if (detActiveWait) detActiveWait.classList.toggle('info-cell-active', !!info.activeWaitingAnswer);
    if (detSeriesNoEffect) detSeriesNoEffect.classList.toggle('info-cell-active', !!info.seriesWithoutEffect);
    if (detLowAutoUse) detLowAutoUse.classList.toggle('info-cell-active', !!info.lowAutomatismUsefulness);
    if (detFoundAuto) detFoundAuto.classList.toggle('info-cell-active', !!info.foundSuitableAutomatism);
  }

  function Info_setField(path, value) {
    var info = ensureInfoPicture();
    setByPath(info, path, value);
    Info_updateView();
  }

  /**
   * Режим мышления задаётся только у главного цикла ФО (thinkingMode), не полем инфокартины.
   */
  function Info_setMode(mode) {
    var passive = !(mode === 'target');
    if (typeof global.Consciousness_getMainCycle === 'function') {
      var mc = global.Consciousness_getMainCycle();
      if (mc) {
        mc.thinkingMode = passive ? 'passive' : 'target';
      }
    }
    if (typeof global.Info_updateView === 'function') {
      global.Info_updateView();
    }
  }

  var lastActiveBranchIdForSituations = null;

  function Info_updateFromPerceptionTree() {
    if (typeof global.PerceptionTree_getActiveTerminalNodeId !== 'function' ||
        typeof global.PerceptionTree_getPathByNodeId !== 'function') {
      return;
    }
    var nodeId = global.PerceptionTree_getActiveTerminalNodeId();
    if (!nodeId) return;
    var path = global.PerceptionTree_getPathByNodeId(nodeId);
    if (!Array.isArray(path) || path.length < 3) return;
    var info = ensureInfoPicture();
    info.tree.baseID = path[0] || 0;
    info.tree.emotionID = path[1] || 0;
    info.tree.activityID = path[2] || 0;
    info.tree.toneMoodID = path[3] || 0;
    info.tree.simbolID = path[4] || 0;
    info.tree.phraseID = path[5] || 0;
    Info_updateView();
    // Тему и ситуацию обновляем только при смене ID активной ветки дерева восприятия, а не по каждому пульсу.
    if (nodeId !== lastActiveBranchIdForSituations) {
      lastActiveBranchIdForSituations = nodeId;
      if (typeof global.SituationsTree_onPerceptionTreeActivated === 'function') {
        global.SituationsTree_onPerceptionTreeActivated();
      }
    }
  }

  function Info_updateFromStimulus(finalImageId, source) {
    var info = ensureInfoPicture();
    info.stimulus.finalImageId = finalImageId || 0;
    info.stimulus.source = source || 'external';
    Info_updateView();
  }

  function Info_setProblemFromUnsolved(finalImageId) {
    Info_setField('problemFinalImageId', finalImageId || 0);
  }

  function Info_incrementStep() {
    var info = ensureInfoPicture();
    info.step = (info.step || 0) + 1;
    Info_updateView();
  }

  /** Русские подписи детекторов ситуации (ключи как в SituationsTree_getSituationComponentName). */
  var SITUATION_DETECTOR_NAMES_RU = {
    criticalVital: 'критический витал',
    shockState: 'шоковое состояние',
    suddenChange: 'резкое изменение состояния',
    playMode: 'игровой режим',
    learningMode: 'режим обучения',
    negativeMotorEffect: 'негативный эффект моторного автоматизма',
    negativeMentalEffect: 'негативный эффект ментального автоматизма',
    badState: 'состояние «Плохо»',
    consoleStimulus: 'стимул с пульта',
    searchInterest: 'поисковый интерес',
    teacherLearning: 'обучение с учителем',
    operatorIgnoring: 'оператор игнорирует',
    dissatisfaction: 'неудовлетворённость',
    misunderstanding: 'непонимание',
    doubtInDefaultAutomatism: 'сомнение в штатном автоматизме',
    defense: 'защита',
    fear: 'страх',
    aggression: 'агрессия',
    highImportanceObject: 'объект высокой значимости',
    moodImproving: 'улучшение настроения',
    imageNovelty: 'новизна образа',
    highSemanticImportance: 'высокая семантическая значимость',
    conflictingSemantics: 'противоречивая семантика',
    hardProblem: 'трудная проблема',
    positiveActionEffect: 'положительный эффект действия',
    negativeActionEffect: 'отрицательный эффект действия',
    noReactionToStimulus: 'нет реакции на стимул',
    operatorAnswerReceived: 'ответ оператора получен',
    activeWaitingAnswer: 'активное ожидание ответа',
    seriesWithoutEffect: 'серия эпизодов без эффекта',
    lowAutomatismUsefulness: 'низкая полезность автоматизма',
    foundSuitableAutomatism: 'найден подходящий автоматизм',
    notFoundSuitableAutomatism: 'не найден подходящий автоматизм',
    usedRule: 'реагирование по правилу',
    peaceNormBaseline: 'норма виталов и покой'
  };

  function Info_formatSituationDetectorNames(sImg) {
    if (!sImg || !Array.isArray(sImg.componentIds) || !sImg.componentIds.length) {
      return '—';
    }
    var parts = [];
    for (var di = 0; di < sImg.componentIds.length; di++) {
      var cid = sImg.componentIds[di];
      var key = (typeof global.SituationsTree_getSituationComponentName === 'function')
        ? global.SituationsTree_getSituationComponentName(cid) : '';
      var label = (key && SITUATION_DETECTOR_NAMES_RU[key]) || key || ('id ' + String(cid));
      parts.push(label);
    }
    return parts.join(', ');
  }

  function Info_showDetail(key) {
    if (typeof global.show_alert !== 'function') return;
    var info = ensureInfoPicture();
    var html = '';
    if (key === 'mode') {
      var mtm = (typeof global.Consciousness_getMainCycleThinkingMode === 'function')
        ? global.Consciousness_getMainCycleThinkingMode()
        : 'target';
      html = '<b>Режим мышления (главный цикл ФО):</b> ' + (mtm === 'target' ? 'Целевой' : 'Пассивный');
    } else if (key === 'fantasmPlot') {
      var rules = Array.isArray(info.fantasmPlotRules) ? info.fantasmPlotRules : [];
      html = '<b>Сюжет фантазма</b> — пополняемый массив правил эпизодической памяти (снимки кадров).';
      html += '<br><small>При переходе режима целевой → пассивный выполняется заполнение (алгоритм будет задан отдельно; сейчас — последние кадры Episodes).</small>';
      html += '<br><br><b>Правил в сюжете:</b> ' + rules.length;
      for (var fpi = 0; fpi < rules.length; fpi++) {
        var rr = rules[fpi];
        if (!rr) continue;
        html += '<br>— узел ' + (rr.perceptionNodeId || 0) + ', ситуация ' + (rr.situationId || 0) +
          ', стимул ' + (rr.stimulusImageId || 0) + ', ОД=' + (rr.actionImageId != null ? rr.actionImageId : '—') +
          ', effect=' + (rr.effect != null ? rr.effect : '—');
      }
      if (!rules.length) html += '<br><i>пока пусто</i>';
    } else if (key === 'theme') {
      var thId = info.themeId || 0;
      html = '<b>Тема:</b> ' + (thId || 'нет');
      if (thId && typeof global.SituationsTree_getThemeImage === 'function') {
        var tImg = global.SituationsTree_getThemeImage(thId);
        if (tImg) {
          html += '<br><br><b>Детализация образа темы:</b>' +
            '<br>ID темы: ' + tImg.id +
            '<br>Режим: ' + (tImg.mode === 1 ? 'целевой' : 'пассивный') +
            '<br>Компоненты (BaseID, EmotionID, ActivityID): ' +
            (tImg.componentIds && tImg.componentIds.length ? tImg.componentIds.join(', ') : 'нет') +
            '<br>Число усреднений: ' + tImg.count +
            '<br>Готовый образ: ' + (tImg.ready ? 'да' : 'нет');
        }
      }
      if (typeof global.SituationsTree_getAllThemeImages === 'function') {
        var allT = global.SituationsTree_getAllThemeImages() || [];
        html += '<br><br><b>Всего тем:</b> ' + allT.length;
        if (allT.length) {
          html += '<br>ID тем (щелчок — детализация): ';
          for (var ti = 0; ti < allT.length; ti++) {
            if (ti > 0) html += ', ';
            html += infoAlertIdLink('Info_showThemeImageDetail', allT[ti].id);
          }
        }
      }
    } else if (key === 'situation') {
      var stId = info.situationId || 0;
      html = '<b>Ситуации</b> (образы из дерева ситуаций)';
      html += '<br><b>Активная сейчас:</b> ';
      if (stId && typeof global.SituationsTree_getSituationImage === 'function' &&
          global.SituationsTree_getSituationImage(stId)) {
        var actSit = global.SituationsTree_getSituationImage(stId);
        html += infoSituationImageLinkFromRecord(actSit);
        html += '<br><i>Детекторы:</i> ' + Info_formatSituationDetectorNames(actSit);
      } else {
        html += (stId ? ('ID ' + String(stId) + ' (образ не найден)') : 'нет');
      }
      if (typeof global.SituationsTree_getAllSituationImages !== 'function') {
        html += '<br><br>Списки ситуаций недоступны (SituationsTree).';
      } else {
        var allS = global.SituationsTree_getAllSituationImages() || [];
        var realized = [];
        var unrealized = [];
        for (var sx = 0; sx < allS.length; sx++) {
          var sv = allS[sx];
          if (!sv || typeof sv.id !== 'number') continue;
          if (sv.ready === true) {
            realized.push(sv);
          } else {
            unrealized.push(sv);
          }
        }
        realized.sort(function (a, b) { return (a.id || 0) - (b.id || 0); });
        unrealized.sort(function (a, b) {
          var ca = typeof a.count === 'number' ? a.count : 0;
          var cb = typeof b.count === 'number' ? b.count : 0;
          if (ca !== cb) return ca - cb;
          return (a.id || 0) - (b.id || 0);
        });
        html += '<br><br><b>Реализованные</b> (готовый образ, ready): ' + realized.length;
        html += '<br><small>Щелчок по ID — полная детализация</small>';
        if (realized.length) {
          for (var ri = 0; ri < realized.length; ri++) {
            html += '<br>• ' + infoSituationImageLinkFromRecord(realized[ri]) +
              ' — <i>' + Info_formatSituationDetectorNames(realized[ri]) + '</i>';
          }
        } else {
          html += '<br><i>пока нет</i>';
        }
        html += '<br><br><b>Нереализованные</b> (ещё усредняются, не ready): ' + unrealized.length;
        html += '<br><small>count — число усреднений</small>';
        if (unrealized.length) {
          for (var ui = 0; ui < unrealized.length; ui++) {
            var uc = typeof unrealized[ui].count === 'number' ? unrealized[ui].count : 0;
            html += '<br>• ' + infoSituationImageLinkFromRecord(unrealized[ui]) +
              ' <small>(' + String(uc) + ')</small> — <i>' + Info_formatSituationDetectorNames(unrealized[ui]) + '</i>';
          }
        } else {
          html += '<br><i>пока нет</i>';
        }
        html += '<br><br><small>Всего записей ситуаций: ' + String(allS.length) + '</small>';
      }
    } else if (key === 'problem') {
      html = '<b>Нерешённая проблема:</b> FinalImageId=' + (info.problemFinalImageId || 'нет');
    } else if (key === 'step') {
      html = '<b>Шаг осмысления:</b> ' + (info.step || 0);
    } else if (key === 'stimulus') {
      var fid = info.stimulus.finalImageId || 0;
      var stimDetail = '';
      if (fid && typeof global.PerceptionTree_getStimulusNamesForFinalImageId === 'function') {
        stimDetail = global.PerceptionTree_getStimulusNamesForFinalImageId(fid) || '';
      }
      html = '<b>Стимул:</b> ' + (stimDetail || ('FinalImageId=' + (fid || 'нет'))) +
        '<br><b>Источник:</b> ' + (info.stimulus.source === 'imagination' ? 'воображение' : 'внешний стимул');
      // Сравнение с "стимулом с пульта".
      var cId2 = info.consoleStimulus || 0;
      if (cId2) {
        html += '<br><b>Стимул с пульта (последний):</b> ' +
          infoAlertIdLink('Info_showFinalImageStimulusDetail', cId2) +
          (cId2 === fid ? ' (совпадает)' : ' (не совпадает)');
      } else {
        html += '<br><b>Стимул с пульта (последний):</b> 0';
      }
      // Семантика для этого стимула (если есть текущие well/emotion).
      if (fid && typeof global.getSemanticObjectFast === 'function') {
        var well = global.BadNormWell || 0;
        var emotionId = 0;
        if (typeof global.Emotions_getOrCreateEmotionId === 'function' && Array.isArray(global.BasicContextsActived)) {
          emotionId = global.Emotions_getOrCreateEmotionId(global.BasicContextsActived) || 0;
        }
        var semObj = (well && emotionId) ? global.getSemanticObjectFast(well, emotionId, fid) : null;
        if (semObj) {
          html += '<br><br><b>Семантика (в текущих условиях):</b>' +
            '<br>Средняя значимость z ≈ ' + (Math.round(semObj.meanImportance * 100) / 100) +
            '<br>Число обучений: ' + semObj.samplesCount;
        }
      }
    } else if (key === 'emotion') {
      var eId = info.tree.emotionID || 0;
      html = '<b>EmotionID:</b> ' + String(eId || 0);
      if (eId && Array.isArray(global.Emotions)) {
        var em = null;
        for (var eii = 0; eii < global.Emotions.length; eii++) {
          if (global.Emotions[eii] && global.Emotions[eii].id === eId) { em = global.Emotions[eii]; break; }
        }
        if (em) {
          var emotionContexts = em.contextIds || [];
          if (emotionContexts.length && Array.isArray(global.BasicContexts)) {
            var names = [];
            for (var ci = 0; ci < emotionContexts.length; ci++) {
              var cid = emotionContexts[ci];
              var found = false;
              for (var bj = 0; bj < global.BasicContexts.length; bj++) {
                if (global.BasicContexts[bj] && global.BasicContexts[bj].id === cid) {
                  names.push(global.BasicContexts[bj].name || ('Контекст ' + cid));
                  found = true;
                  break;
                }
              }
              if (!found) names.push('id ' + cid);
            }
            html += '<br><b>Базовые контексты:</b> ' + names.join(', ');
          } else {
            html += '<br><b>Базовые контексты:</b> —';
          }
        }
      }
      html += '<br><br><b>Полная ветка:</b><br>' +
        'BaseID=' + (info.tree.baseID || 0) +
        ' → EmotionID=' + (info.tree.emotionID || 0) +
        ' → ActivityID=' + (info.tree.activityID || 0);
    } else if (key === 'activity') {
      var actId2 = info.tree.activityID || 0;
      var actNames = '';
      if (actId2 && typeof global.PerceptionTree_getStimulusNamesForFinalImageId === 'function') {
        actNames = global.PerceptionTree_getStimulusNamesForFinalImageId(actId2) || '';
      }
      html = '<b>ActivityID:</b> ' + (actId2 ? infoAlertIdLink('Info_showFinalImageStimulusDetail', actId2) : '0');
      html += '<br><b>Актуальный образ стимула:</b> ' + (actNames && actNames !== '—' ? actNames : '—');
      if (actId2 && typeof global.getSemanticObjectFast === 'function') {
        var wellA = global.BadNormWell || 0;
        var emoA = info.tree.emotionID || 0;
        var semA = (wellA && emoA) ? global.getSemanticObjectFast(wellA, emoA, actId2) : null;
        if (semA) {
          html += '<br><br><b>Семантика (well=' + String(wellA) + ', emotionId=' + String(emoA) + '):</b>' +
            '<br>z ≈ ' + (Math.round(semA.meanImportance * 100) / 100) +
            '<br>обучений: ' + semA.samplesCount;
        }
      }
      html += '<br><br><b>Полная ветка:</b><br>' +
        'BaseID=' + (info.tree.baseID || 0) +
        ' → EmotionID=' + (info.tree.emotionID || 0) +
        ' → ActivityID=' + (info.tree.activityID || 0);
    } else if (key === 'tree') {
      // Base: Плохо / Норма / Хорошо
      var baseName = 'не определено';
      if (info.tree.baseID === 1) baseName = 'Плохо';
      else if (info.tree.baseID === 2) baseName = 'Норма';
      else if (info.tree.baseID === 3) baseName = 'Хорошо';

      // Emotion: состав базовых контекстов
      var emotionName = 'нет';
      var emotionContexts = [];
      if (info.tree.emotionID && Array.isArray(global.Emotions)) {
        for (var ei = 0; ei < global.Emotions.length; ei++) {
          if (global.Emotions[ei] && global.Emotions[ei].id === info.tree.emotionID) {
            emotionContexts = global.Emotions[ei].contextIds || [];
            break;
          }
        }
      }
      if (emotionContexts.length && Array.isArray(global.BasicContexts)) {
        var parts = [];
        for (var ci = 0; ci < emotionContexts.length; ci++) {
          var cid = emotionContexts[ci];
          for (var bj = 0; bj < global.BasicContexts.length; bj++) {
            if (global.BasicContexts[bj] && global.BasicContexts[bj].id === cid) {
              parts.push(global.BasicContexts[bj].name || ('Контекст ' + cid));
              break;
            }
          }
        }
        if (parts.length) {
          emotionName = parts.join(', ');
        }
      }

      // Activity: актуальный образ стимула + семантика
      var actId = info.tree.activityID || 0;
      var actDetail = '';
      if (actId && typeof global.PerceptionTree_getStimulusNamesForFinalImageId === 'function') {
        actDetail = global.PerceptionTree_getStimulusNamesForFinalImageId(actId) || '';
      }
      var actSem = '';
      if (actId && typeof global.getSemanticObjectFast === 'function') {
        var wellT = global.BadNormWell || 0;
        var emotionIdT = info.tree.emotionID || 0;
        var semObjT = (wellT && emotionIdT) ? global.getSemanticObjectFast(wellT, emotionIdT, actId) : null;
        if (semObjT) {
          actSem = 'Средняя значимость z ≈ ' + (Math.round(semObjT.meanImportance * 100) / 100) +
            ', число обучений: ' + semObjT.samplesCount;
        }
      }

      html = '<b>Base:</b> ' + baseName +
        '<br><b>EmotionID:</b> ' + (info.tree.emotionID || 0) +
        '<br><b>Эмоция (состав базовых контекстов):</b> ' + emotionName +
        '<br><br><b>ActivityID:</b> ' + (actId || 0) +
        '<br><b>Актуальный образ стимула:</b> ' + (actDetail || 'нет') +
        (actSem ? ('<br>' + actSem) : '') +
        '<br><br><b>Полная ветка дерева:</b><br>' +
        'BaseID=' + (info.tree.baseID || 0) +
        ' → EmotionID=' + (info.tree.emotionID || 0) +
        ' → ActivityID=' + (info.tree.activityID || 0) +
        ' → ToneMoodID=' + (info.tree.toneMoodID || 0) +
        ' → SimbolID=' + (info.tree.simbolID || 0) +
        ' → PhraseID=' + (info.tree.phraseID || 0);
    } else if (key === 'criticalVital') {
      html = '<b>Критический витал:</b> ' + (info.criticalVital ? 'активен' : 'нет');
    } else if (key === 'ImportantProblem') {
      html = '<b>Важная проблема:</b> ' + (info.ImportantProblem ? 'да (гистерезис внимания к стимулам)' : 'нет (облегчённый ОР/ФО)');
    } else if (key === 'usedRule') {
      var ur = typeof info.usedRule === 'number' ? info.usedRule : 0;
      var stk = Array.isArray(global.Target_rule_stack) ? global.Target_rule_stack.slice() : [];
      html = '<b>Реагирование по правилу</b> (usedRule): ' + (ur ? ('да, значение ' + ur) : 'нет (0)') +
        '<br><br><b>Стек целей Target_rule_stack</b> (LIFO, макс. 3 FinalImageId): ';
      if (!stk.length) {
        html += 'пусто.';
      } else {
        html += 'дно → вершина (последний добавленный справа):<br>';
        for (var si = 0; si < stk.length; si++) {
          if (si > 0) html += ' → ';
          html += infoAlertIdLink('Info_showFinalImageStimulusDetail', stk[si]);
        }
      }
    } else if (key === 'shockState') {
      html = '<b>Шоковое состояние:</b> ' + (info.shockState ? 'активно' : 'нет');
    } else if (key === 'suddenChange') {
      html = '<b>Стало резко хуже (переход в Плохо):</b> ' + (info.suddenChange ? 'да' : 'нет');
    } else if (key === 'playMode') {
      html = '<b>Игровой режим:</b> ' + (info.playMode ? 'активен' : 'нет');
    } else if (key === 'learningMode') {
      html = '<b>Режим обучения:</b> ' + (info.learningMode ? 'активен' : 'нет');
    } else if (key === 'negativeMotorEffect') {
      html = '<b>Негативный эффект моторного автоматизма:</b> ' + (info.negativeMotorEffect ? 'есть' : 'нет');
    } else if (key === 'negativeMentalEffect') {
      html = '<b>Негативный эффект ментального автоматизма:</b> ' + (info.negativeMentalEffect ? 'есть' : 'нет');
    } else if (key === 'badState') {
      html = '<b>Состояние Плохо:</b> ' + (info.badState ? 'да' : 'нет');
    } else if (key === 'consoleStimulus') {
      var cId = info.consoleStimulus || 0;
      var curId = info.stimulus && typeof info.stimulus.finalImageId === 'number' ? info.stimulus.finalImageId : 0;
      var cNames = '';
      if (cId && typeof global.PerceptionTree_getStimulusNamesForFinalImageId === 'function') {
        cNames = global.PerceptionTree_getStimulusNamesForFinalImageId(cId) || '';
      }
      html = '<b>Стимул с пульта</b> (consoleStimulus): ' + (cId ? infoAlertIdLink('Info_showFinalImageStimulusDetail', cId) : '0') +
        '<br><i>Смысл:</i> это ID конечного образа (FinalImageId) последнего стимула, пришедшего от оператора (пульта).' +
        '<br>Он может <b>не совпадать</b> с текущим стимулом осмысления.' +
        (cId ? ('<br><b>Имена стимулов:</b> ' + (cNames && cNames !== '—' ? cNames : '—')) : '') +
        '<br><br><b>Текущий стимул осмысления:</b> ' +
        (curId ? infoAlertIdLink('Info_showFinalImageStimulusDetail', curId) : '0') +
        (curId && info.stimulus && info.stimulus.source ? (' (' + (info.stimulus.source === 'imagination' ? 'воображение' : 'внешний') + ')') : '') +
        '<br><b>Совпадает?</b> ' + ((cId && curId && cId === curId) ? 'да' : 'нет');
    } else if (key === 'searchInterest') {
      html = '<b>Поисковый интерес:</b> ' + (info.searchInterest ? 'активен' : 'нет');
    } else if (key === 'teacherLearning') {
      html = '<b>Обучение с учителем:</b> ' + (info.teacherLearning ? 'идёт' : 'нет');
    } else if (key === 'operatorIgnoring') {
      html = '<b>Игнорирование оператором:</b> ' + (info.operatorIgnoring ? 'обнаружено' : 'нет');
    } else if (key === 'dissatisfaction') {
      html = '<b>Неудовлетворённость существующим:</b> ' + (info.dissatisfaction ? 'есть' : 'нет');
    } else if (key === 'misunderstanding') {
      html = '<b>Непонимание:</b> ' + (info.misunderstanding ? 'есть' : 'нет');
    } else if (key === 'doubtInDefaultAutomatism') {
      html = '<b>Сомнение в штатном автоматизме:</b> ' + (info.doubtInDefaultAutomatism ? 'есть' : 'нет');
    } else if (key === 'defense') {
      html = '<b>Защита:</b> ' + (info.defense ? 'активна' : 'нет');
    } else if (key === 'fear') {
      html = '<b>Страх:</b> ' + (info.fear ? 'активен' : 'нет');
    } else if (key === 'aggression') {
      html = '<b>Агрессия:</b> ' + (info.aggression ? 'активна' : 'нет');
    } else if (key === 'highImportanceObject') {
      var ho = typeof info.highImportanceObject === 'number' ? info.highImportanceObject : 0;
      var curStim = info.stimulus && typeof info.stimulus.finalImageId === 'number' ? info.stimulus.finalImageId : 0;
      html = '<b>Важный объект</b> (highImportanceObject): ' + String(ho || 0) +
        '<br><i>Суть:</i> это <b>ID конкретного объекта</b> (или уровень), который внешний код распознал как «особо значимый»' +
        ' в текущей ситуации и передал сюда.' +
        '<br>Это не «уровень семантики вообще», а <b>указание на найденный объект</b>.' +
        (ho ? '<br><br><b>Подсказка:</b> если это FinalImageId, можно открыть: ' + infoAlertIdLink('Info_showFinalImageStimulusDetail', ho) : '') +
        '<br><br><b>Текущий стимул осмысления:</b> ' + (curStim ? infoAlertIdLink('Info_showFinalImageStimulusDetail', curStim) : '0') +
        '<br><b>Совпадает с текущим стимулом?</b> ' + ((ho && curStim && ho === curStim) ? 'да' : 'нет');
    } else if (key === 'moodImproving') {
      html = '<b>Улучшение настроения:</b> ' + (info.moodImproving ? 'зафиксировано' : 'нет');
    } else if (key === 'imageNovelty') {
      html = '<b>Новизна образа:</b> ' + (info.imageNovelty ? 'высокая' : 'нет');
    } else if (key === 'highSemanticImportance') {
      var hs = typeof info.highSemanticImportance === 'number' ? info.highSemanticImportance : 0;
      var fidHs = info.stimulus && typeof info.stimulus.finalImageId === 'number' ? info.stimulus.finalImageId : 0;
      html = '<b>Выс. семантика</b> (highSemanticImportance): ' + String(hs || 0) +
        '<br><i>Суть:</i> это <b>численный уровень семантической значимости</b> текущего образа в данных условиях (обычно meanImportance).' +
        '<br>То есть «насколько значим стимул по семантике», а не «какой именно объект важен».' +
        '<br><br><b>Для текущего стимула:</b> ' + (fidHs ? infoAlertIdLink('Info_showFinalImageStimulusDetail', fidHs) : '0');
    } else if (key === 'conflictingSemantics') {
      html = '<b>Противоречивая семантика:</b> ' + (info.conflictingSemantics ? 'есть' : 'нет');
    } else if (key === 'hardProblem') {
      html = '<b>Трудная проблема:</b> ' + (info.hardProblem ? 'активна' : 'нет');
    } else if (key === 'positiveActionEffect') {
      html = '<b>Положительный эффект действия:</b> ' + (info.positiveActionEffect ? 'есть' : 'нет');
    } else if (key === 'negativeActionEffect') {
      html = '<b>Отрицательный эффект действия:</b> ' + (info.negativeActionEffect ? 'есть' : 'нет');
    } else if (key === 'noReactionToStimulus') {
      html = '<b>Нет реакции на стимул:</b> ' + (info.noReactionToStimulus ? 'зафиксировано' : 'нет');
    } else if (key === 'operatorAnswerReceived') {
      html = '<b>Ответ оператора получен</b> (operatorAnswerReceived): ' +
        (info.operatorAnswerReceived ? 'да' : 'нет') +
        '<br><b>Ответ на автоматизм ФО</b> (isOperatorAnswerReceived): ' +
        (info.isOperatorAnswerReceived ? 'да (обрабатывается ур.2 при необходимости)' : 'нет');
    } else if (key === 'activeWaitingAnswer') {
      html = '<b>Активное ожидание ответа:</b> ' + (info.activeWaitingAnswer ? 'идёт' : 'нет');
    } else if (key === 'seriesWithoutEffect') {
      html = '<b>Серия эпизодов без эффекта:</b> ' + (info.seriesWithoutEffect ? 'есть' : 'нет');
    } else if (key === 'lowAutomatismUsefulness') {
      html = '<b>Низкая полезность автоматизма:</b> ' + (info.lowAutomatismUsefulness ? 'обнаружена' : 'нет');
    } else if (key === 'foundSuitableAutomatism') {
      html = '<b>Пока найден подходящий автоматизм:</b> ' + (info.foundSuitableAutomatism ? 'да' : 'нет');
    }
    if (html) {
      global.show_alert(html, 0);
    }
  }

  global.Info_initIfNeeded = ensureInfoPicture;

  /** Пульс создания цикла: явное поле или первая запись лога (для старых циклов без birthPuls). */
  function resolveCycleBirthPuls(cycleOrItem, pulsNow) {
    if (cycleOrItem && typeof cycleOrItem.birthPuls === 'number') return cycleOrItem.birthPuls;
    var dl = cycleOrItem && cycleOrItem.debugLog;
    if (Array.isArray(dl) && dl.length && typeof dl[0].atPuls === 'number') return dl[0].atPuls;
    return pulsNow;
  }

  /**
   * Форматирует информацию о цикле или элементе стека фоновых в HTML для show_alert.
   * @param {Object} cycleOrItem - объект цикла (из реестра) или элемент стека { id, context, importance }
   * @param {string} prefix - подпись блока (например "Цикл" или "Фоновый #N")
   * @returns {string}
   */
  function formatCycleOrStackInfo(cycleOrItem, prefix) {
    if (!cycleOrItem) return '';
    var ctx = cycleOrItem.context || {};
    var actualId = ctx.actual_stimul_ID != null ? ctx.actual_stimul_ID : 0;
    var branchId = ctx.branchId != null ? ctx.branchId : 0;
    var well = ctx.well != null ? ctx.well : 0;
    var emotionId = ctx.emotionId != null ? ctx.emotionId : 0;
    var activityID = ctx.activityID != null ? ctx.activityID : actualId;
    var weight = cycleOrItem.weight != null ? cycleOrItem.weight : (cycleOrItem.importance != null ? cycleOrItem.importance : 0);
    var stimNames = '';
    if (typeof global.PerceptionTree_getStimulusNamesForFinalImageId === 'function' && actualId) {
      var names = global.PerceptionTree_getStimulusNamesForFinalImageId(actualId);
      if (names && names.length) stimNames = ' — ' + names;
    }
    var cycId = cycleOrItem.id != null ? cycleOrItem.id : 0;
    var idLine = 'ID: ' + (cycId ? infoAlertIdLink('Info_showCycleDetailById', cycId) : '—');
    var themeId = typeof cycleOrItem.createdThemeId === 'number' ? cycleOrItem.createdThemeId : 0;
    var themeLine = 'Тема при создании (createdThemeId): ' +
      (themeId ? infoAlertIdLink('Info_showThemeImageDetail', themeId) : '0');
    var sitId = typeof cycleOrItem.createdSituationId === 'number' ? cycleOrItem.createdSituationId : 0;
    var sitLine = 'Ситуация при создании (createdSituationId): ' +
      (sitId ? infoSituationImageLinkById(sitId) : '0');
    var goalImgId = typeof cycleOrItem.goalImageId === 'number' ? cycleOrItem.goalImageId : 0;
    var goalLine = 'Образ цели (goalImageId): ' + String(goalImgId || 0) +
      (goalImgId ? ' <small>(жизненный опыт, id записи)</small>' : ' <small>(пассивный режим или базовая цель без образа)</small>');
    var waitAutoId = typeof cycleOrItem.waitingFeedbackAutomatizmId === 'number' ? cycleOrItem.waitingFeedbackAutomatizmId : 0;
    var waitAutoLine = 'Ожидание оценки автоматизма (waitingFeedbackAutomatizmId): ' + String(waitAutoId || 0);
    var waitCycLine = 'Период ожидания после автоматизма: awaiting=' +
      (cycleOrItem.awaitingAutomatismEpisodeFeedback ? 'да' : 'нет') +
      ', ответ стимулом=' + (cycleOrItem.automatismOperatorAnswerReceived ? 'да' : 'нет') +
      ', effect кадра=' + (typeof cycleOrItem.lastAutomatismEpisodeEffect === 'number'
        ? String(cycleOrItem.lastAutomatismEpisodeEffect) : '—');
    var stimLine = 'Стимул FinalImageId: ' +
      (actualId ? infoAlertIdLink('Info_showFinalImageStimulusDetail', actualId) : '0') + stimNames;
    var branchLine = 'Ветка (branchId): ' +
      (branchId ? infoAlertIdLink('Info_showPerceptionNodeDetail', branchId) : '0');
    var emoLine = 'Эмоция (emotionId): ' +
      (emotionId ? infoAlertIdLink('Info_showEmotionRecordDetail', emotionId) : '0');
    var actLine = 'ActivityID: ' +
      (activityID ? infoAlertIdLink('Info_showFinalImageStimulusDetail', activityID) : '0');
    if (activityID && activityID === actualId) {
      actLine += ' (совпадает со стимулом)';
    }
    var effectiveState = (cycleOrItem && cycleOrItem.expired === true) ? 'expired' : 'running';
    var parts = [
      '<b>' + (prefix || 'Цикл') + '</b>',
      idLine,
      themeLine,
      sitLine,
      goalLine,
      waitAutoLine,
      waitCycLine,
      stimLine,
      branchLine,
      'Базовое состояние (well): ' + String(well) + (well === 1 ? ' (Плохо)' : well === 2 ? ' (Норма)' : well === 3 ? ' (Хорошо)' : ''),
      emoLine,
      actLine,
      'Значимость: ' + String(weight),
      'Состояние цикла: ' + effectiveState,
      'expired: ' + (cycleOrItem.expired === true
        ? 'да (отработан, остаётся в реестре)'
        : 'нет')
    ];
    if (cycleOrItem.passiveWorkAfterGestaltExpire === true) {
      parts.push('После expired (стагнация сразу после тика гештальта): инфокартина переведена в <b>пассивный режим работы</b>.');
    }
    if (typeof cycleOrItem.lastGestaltConsciencePuls === 'number' && cycleOrItem.lastGestaltConsciencePuls > 0) {
      parts.push('Последний тик ур.4/гештальта (пульс): ' + String(cycleOrItem.lastGestaltConsciencePuls));
    }
    if (cycleOrItem.status != null) {
      parts.push('Статус: ' + String(cycleOrItem.status));
    }
    if (typeof cycleOrItem.step === 'number') {
      parts.push('Шаг (уровень ФО): ' + String(cycleOrItem.step));
    }
    var pulsNow = typeof global.cpuls === 'number' ? global.cpuls : 0;
    var birthPuls = resolveCycleBirthPuls(cycleOrItem, pulsNow);
    parts.push('Пульс создания: ' + String(birthPuls));
    parts.push('Возраст цикла (пульсов с создания): ' + String(Math.max(0, pulsNow - birthPuls)));
    if (typeof cycleOrItem.count === 'number') {
      parts.push(
        'Шагов диспетчера (runOneStep): ' + String(cycleOrItem.count) +
          ' — тики dispetchConsciousnessThinking, не лимит остановки; у фонового цикла шаг реже (≈ раз в 5 пульсов).'
      );
    }
    if (typeof cycleOrItem.order === 'number') {
      parts.push('Порядок создания: ' + String(cycleOrItem.order));
    }
    if (Array.isArray(cycleOrItem.fantasizmArr)) {
      parts.push('fantasizmArr (правила ЭП, сюжет фонового цикла): ' + String(cycleOrItem.fantasizmArr.length) + ' шт.');
    }
    if (cycleOrItem.fantasizmPassiveFillStarted === true) {
      parts.push('Заполнение fantasizmArr при пассивном режиме: начато.');
    }
    // Лог цикла (если есть)
    if (Array.isArray(cycleOrItem.debugLog) && cycleOrItem.debugLog.length) {
      var from = Math.max(0, cycleOrItem.debugLog.length - 30);
      var lines = [];
      for (var i = from; i < cycleOrItem.debugLog.length; i++) {
        var e = cycleOrItem.debugLog[i];
        var p = (e && typeof e.atPuls === 'number') ? e.atPuls : 0;
        var t = e && e.text != null ? String(e.text) : '';
        lines.push('[' + String(p) + '] ' + t);
      }
      parts.push('<details style="margin-top:6px"><summary><b>Лог цикла</b> (последние ' + String(lines.length) + ')</summary>' +
        '<pre style="white-space:pre-wrap;margin:6px 0 0 0;font-size:10pt">' +
        lines.join('\n').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;') +
        '</pre></details>');
    }
    return parts.join('<br>');
  }

  /**
   * Показать информацию о текущем главном цикле осмысления.
   * Вызывается по щелчку на «Главный цикл ID: N».
   */
  function Info_showMainCycleDetail() {
    if (typeof global.show_alert !== 'function') return;
    var mainId = typeof global.ConsciousnessCurrentProcessId === 'number' ? global.ConsciousnessCurrentProcessId : 0;
    if (!mainId) {
      global.show_alert('Нет активного главного цикла (ID = 0).', 0);
      return;
    }
    var getCycle = global.Consciousness_getCycle;
    var cycle = typeof getCycle === 'function' ? getCycle(mainId) : null;
    if (!cycle) {
      global.show_alert('Цикл с ID ' + String(mainId) + ' не найден в реестре (уже завершён или удалён).', 0);
      return;
    }
    var html = formatCycleOrStackInfo(cycle, 'Главный цикл');
    global.show_alert(html, 0);
  }

  /**
   * Показать подробности фоновых циклов осмысления (из реестра, isMainCycle=false, status=running).
   * Вызывается по щелчку на индикаторе «фон: N». Для каждого цикла выводится та же детализация, что и для главного.
   */
  function Info_showBackgroundStack() {
    if (typeof global.show_alert !== 'function') return;
    var list = typeof global.Consciousness_getBackgroundCyclesList === 'function'
      ? global.Consciousness_getBackgroundCyclesList() : [];
    if (!list.length) {
      global.show_alert('Фоновых циклов осмысления нет.', 0);
      return;
    }
    var blocks = ['<b>Фоновые циклы осмысления</b> (по убыванию значимости). Щелчок по ID — полная детализация:'];
    for (var i = 0; i < list.length; i++) {
      var item = list[i];
      var cid = item && item.id != null ? item.id : 0;
      var w = item && typeof item.weight === 'number' ? item.weight : 0;
      var ctx = item && item.context ? item.context : {};
      var stim = ctx && typeof ctx.actual_stimul_ID === 'number' ? ctx.actual_stimul_ID : 0;
      blocks.push('<br>');
      blocks.push(cid ? infoAlertIdLink('Info_showBackgroundCycleDetail', cid) : '—');
      blocks.push(' — значимость ' + String(w) + ', стимул FinalImageId=');
      blocks.push(stim ? infoAlertIdLink('Info_showFinalImageStimulusDetail', stim) : '0');
      if (item && item.expired === true) {
        blocks.push(', <b>expired</b>');
      }
    }
    global.show_alert(blocks.join(''), 0);
  }

  function Info_showBackgroundCycleDetail(cycleId) {
    if (typeof global.show_alert !== 'function') return;
    cycleId = parseInt(cycleId, 10);
    if (isNaN(cycleId) || cycleId <= 0) return;
    var getCycle = global.Consciousness_getCycle;
    var cycle = typeof getCycle === 'function' ? getCycle(cycleId) : null;
    if (!cycle) {
      global.show_alert('Цикл с ID ' + String(cycleId) + ' не найден в реестре.', 0);
      return;
    }
    global.show_alert(formatCycleOrStackInfo(cycle, 'Фоновый цикл'), 0);
  }

  function Info_showThemeImageDetail(themeId) {
    if (typeof global.show_alert !== 'function') return;
    themeId = parseInt(themeId, 10) || 0;
    if (!themeId || typeof global.SituationsTree_getThemeImage !== 'function') {
      global.show_alert('Тема #' + themeId + ' не найдена.', 0);
      return;
    }
    var tImg = global.SituationsTree_getThemeImage(themeId);
    if (!tImg) {
      global.show_alert('Тема #' + themeId + ' не найдена.', 0);
      return;
    }
    var html = '<b>Образ темы #' + tImg.id + '</b>' +
      '<br>Режим: ' + (tImg.mode === 1 ? 'целевой' : 'пассивный') +
      '<br>Компоненты (BaseID, EmotionID, ActivityID): ' +
      (tImg.componentIds && tImg.componentIds.length ? tImg.componentIds.join(', ') : 'нет') +
      '<br>Число усреднений: ' + tImg.count +
      '<br>Готовый образ: ' + (tImg.ready ? 'да' : 'нет');
    global.show_alert(html, 0);
  }

  function Info_showSituationImageDetail(situationId) {
    if (typeof global.show_alert !== 'function') return;
    situationId = parseInt(situationId, 10) || 0;
    if (!situationId || typeof global.SituationsTree_getSituationImage !== 'function') {
      global.show_alert('Ситуация #' + situationId + ' не найдена.', 0);
      return;
    }
    var sImg = global.SituationsTree_getSituationImage(situationId);
    if (!sImg) {
      global.show_alert('Ситуация #' + situationId + ' не найдена.', 0);
      return;
    }
    var comp = '';
    if (sImg.componentIds && sImg.componentIds.length) {
      var partsS = [];
      for (var si = 0; si < sImg.componentIds.length; si++) {
        var cid = sImg.componentIds[si];
        var name = (typeof global.SituationsTree_getSituationComponentName === 'function')
          ? global.SituationsTree_getSituationComponentName(cid) : '';
        partsS.push(cid + (name ? ' (' + name + ')' : ''));
      }
      comp = partsS.join(', ');
    } else {
      comp = 'нет';
    }
    var inner = '<b>Образ ситуации #' + sImg.id + '</b>' +
      '<br><b>Детекторы (состав):</b> ' + Info_formatSituationDetectorNames(sImg) +
      '<br>Режим: ' + (sImg.mode === 1 ? 'целевой' : 'пассивный') +
      '<br>Компоненты (id, ключ): ' + comp +
      '<br>Число усреднений: ' + sImg.count +
      '<br>Готовый образ: ' + (sImg.ready ? 'да' : 'нет');
    var html = sImg.ready === true
      ? ('<div style="border:2px solid #1976d2;padding:10px 12px;border-radius:8px;box-sizing:border-box">' + inner + '</div>')
      : inner;
    global.show_alert(html, 0);
  }

  /**
   * Человекочитаемое описание ОД: цепочка стимулов конечного образа (как в ветке восприятия),
   * при отсутствии — названия действий.
   */
  function Info_formatActionImageReadableBlock(od) {
    if (!od) return '<b>Образ действия:</b><br>—';
    var stim = '';
    if (od.finalImageId && typeof global.PerceptionTree_getStimulusNamesForFinalImageId === 'function') {
      stim = global.PerceptionTree_getStimulusNamesForFinalImageId(od.finalImageId) || '';
    }
    if (stim === '—') stim = '';
    var actions = '';
    if (typeof global.PerceptionTree_getActionNamesForActionImage === 'function') {
      actions = global.PerceptionTree_getActionNamesForActionImage(od.id) || '';
    }
    if (actions === '—') actions = '';
    var body = stim || actions || '—';
    var extra = '';
    if (stim && actions) {
      extra = '<br><i>Действия:</i> ' + actions;
    }
    return '<b>Образ действия:</b><br>' + body + extra;
  }

  function Info_showActionImageDetail(odId) {
    if (typeof global.show_alert !== 'function') return;
    odId = parseInt(odId, 10) || 0;
    if (!odId || typeof global.ActionImages_getActionImage !== 'function') {
      global.show_alert('ОД #' + odId + ' не найден.', 0);
      return;
    }
    var od = global.ActionImages_getActionImage(odId);
    if (!od) {
      global.show_alert('ОД #' + odId + ' не найден.', 0);
      return;
    }
    var html = '<b>ОД #' + od.id + '</b><br>' +
      Info_formatActionImageReadableBlock(od) +
      '<br><br><b>Поля ОД:</b>' +
      '<br>finalImageId: ' + (od.finalImageId || 0) +
      '<br>actionIds: ' + (Array.isArray(od.actionIds) && od.actionIds.length ? od.actionIds.join(', ') : '—') +
      '<br>odSequence: ' + (od.odSequence || '—');
    global.show_alert(html, 0);
  }

  function Info_showMentalActionImageDetail(maiId) {
    if (typeof global.show_alert !== 'function') return;
    maiId = parseInt(maiId, 10) || 0;
    if (!maiId || typeof global.MentalActionImages_get !== 'function') {
      global.show_alert('Ментальный ОД #' + maiId + ' не найден.', 0);
      return;
    }
    var m = global.MentalActionImages_get(maiId);
    if (!m) {
      global.show_alert('Ментальный ОД #' + maiId + ' не найден.', 0);
      return;
    }
    var ids = Array.isArray(m.abstractActionIds) ? m.abstractActionIds : [];
    var absParts = [];
    for (var i = 0; i < ids.length; i++) {
      if (i > 0) absParts.push(', ');
      absParts.push(infoAlertIdLink('Info_showAbstractionDetail', ids[i]));
    }
    var srcLink = (m.sourceActionImageId || 0)
      ? infoAlertIdLink('Info_showActionImageDetail', m.sourceActionImageId)
      : '0';
    var html = '<b>Ментальный образ действия #' + m.id + '</b>' +
      '<br>Исходный ОД (моторный): ' + srcLink +
      '<br>Абстрактные действия (символы Abstractions, щелчок — детализация): ' +
      (absParts.length ? absParts.join('') : '—') +
      '<br>maSequence: ' + (m.maSequence || '—');
    global.show_alert(html, 0);
  }

  function Info_findAbstractPerceptionImage(id) {
    id = parseInt(id, 10) || 0;
    if (!id) return null;
    var ap = Array.isArray(global.AbstractPerceptionImages) ? global.AbstractPerceptionImages : [];
    for (var i = 0; i < ap.length; i++) {
      if (ap[i] && ap[i].id === id) return ap[i];
    }
    return null;
  }

  function Info_findAbstractActionImage(id) {
    id = parseInt(id, 10) || 0;
    if (!id) return null;
    var aa = Array.isArray(global.AbstractActionImages) ? global.AbstractActionImages : [];
    for (var j = 0; j < aa.length; j++) {
      if (aa[j] && aa[j].id === id) return aa[j];
    }
    return null;
  }

  function Info_showAbstractPerceptionImageDetail(recId) {
    if (typeof global.show_alert !== 'function') return;
    var o = Info_findAbstractPerceptionImage(recId);
    if (!o) {
      global.show_alert('Абстрактный клон восприятия #' + (parseInt(recId, 10) || 0) + ' не найден (AbstractPerceptionImages).', 0);
      return;
    }
    var stimNames = '';
    if (o.stimulusImageId && typeof global.PerceptionTree_getStimulusNamesForFinalImageId === 'function') {
      stimNames = global.PerceptionTree_getStimulusNamesForFinalImageId(o.stimulusImageId) || '';
    }
    var html = '<b>Клон восприятия #' + o.id + '</b> <small>(эпизод → abstract_images.js)</small>' +
      '<br>Узел ветки: ' + (o.perceptionNodeId ? infoAlertIdLink('Info_showPerceptionNodeDetail', o.perceptionNodeId) : '0') +
      '<br>Жёсткий стимул (FinalImageId): ' + (o.stimulusImageId ? infoAlertIdLink('Info_showFinalImageStimulusDetail', o.stimulusImageId) : '0') +
      (stimNames && stimNames !== '—' ? '<br><i>Стимул:</i> ' + stimNames : '') +
      '<br>Средняя значимость: ' + (typeof o.meanImportance === 'number' ? o.meanImportance : 0) +
      '<br>Число усреднений: ' + (typeof o.count === 'number' ? o.count : 0) +
      '<br>Создан: ' + infoFormatAbstractionFieldValue('createdAt', o.createdAt) +
      '<br>Последнее использование: ' + infoFormatAbstractionFieldValue('lastUsedAt', o.lastUsedAt) +
      infoFormatAbstractSemanticStructureHtml(o.semanticStructure);
    global.show_alert(html, 0);
  }

  function Info_showAbstractActionImageDetail(recId) {
    if (typeof global.show_alert !== 'function') return;
    var o = Info_findAbstractActionImage(recId);
    if (!o) {
      global.show_alert('Абстрактный клон действия #' + (parseInt(recId, 10) || 0) + ' не найден (AbstractActionImages).', 0);
      return;
    }
    var odBlock = '';
    if (o.actionImageId && typeof global.ActionImages_getActionImage === 'function') {
      var od = global.ActionImages_getActionImage(o.actionImageId);
      if (od) odBlock = '<br>' + Info_formatActionImageReadableBlock(od);
    }
    var html = '<b>Клон действия #' + o.id + '</b> <small>(эпизод → abstract_images.js)</small>' +
      '<br>Узел ветки: ' + (o.perceptionNodeId ? infoAlertIdLink('Info_showPerceptionNodeDetail', o.perceptionNodeId) : '0') +
      '<br>Жёсткий ОД: ' + (o.actionImageId ? infoAlertIdLink('Info_showActionImageDetail', o.actionImageId) : '0') +
      (odBlock || '') +
      '<br>Средняя значимость: ' + (typeof o.meanImportance === 'number' ? o.meanImportance : 0) +
      '<br>Число усреднений: ' + (typeof o.count === 'number' ? o.count : 0) +
      '<br>Создан: ' + infoFormatAbstractionFieldValue('createdAt', o.createdAt) +
      '<br>Последнее использование: ' + infoFormatAbstractionFieldValue('lastUsedAt', o.lastUsedAt) +
      infoFormatAbstractSemanticStructureHtml(o.semanticStructure);
    global.show_alert(html, 0);
  }

  function Info_showMotorAutomatizmsList() {
    if (typeof global.show_alert !== 'function') return;
    var arr = Array.isArray(global.Automatizms) ? global.Automatizms : [];
    if (!arr.length) {
      global.show_alert('Моторных автоматизмов нет.', 0);
      return;
    }
    var ids = [];
    for (var i = 0; i < arr.length; i++) {
      if (arr[i] && typeof arr[i].id === 'number') ids.push(arr[i].id);
    }
    ids.sort(function (a, b) { return a - b; });
    var parts = ['<b>Моторные автоматизмы</b> (' + ids.length + '). Щелчок по ID — детализация:<br><br>'];
    for (var j = 0; j < ids.length; j++) {
      if (j > 0) parts.push(' &nbsp; ');
      parts.push(infoAlertIdLink('Info_showMotorAutomatizmDetail', ids[j]));
    }
    global.show_alert(parts.join(''), 0);
  }

  function Info_showMotorAutomatizmDetail(id) {
    if (typeof global.show_alert !== 'function') return;
    id = parseInt(id, 10) || 0;
    var arr = Array.isArray(global.Automatizms) ? global.Automatizms : [];
    var a = null;
    for (var i = 0; i < arr.length; i++) {
      if (arr[i] && arr[i].id === id) { a = arr[i]; break; }
    }
    if (!a) {
      global.show_alert('Моторный автоматизм #' + id + ' не найден.', 0);
      return;
    }
    var odBlock = '';
    if (a.actionsImageId && typeof global.ActionImages_getActionImage === 'function') {
      var od = global.ActionImages_getActionImage(a.actionsImageId);
      if (od) {
        odBlock = '<br>' + Info_formatActionImageReadableBlock(od) +
          '<br><small>ОД ' + infoAlertIdLink('Info_showActionImageDetail', a.actionsImageId) +
          ' — все поля образа действия</small>';
      }
    }
    if (!odBlock) {
      odBlock = '<br><b>Образ действия:</b><br>—<br><small>ОД отсутствует</small>';
    }
    var html = '<b>Моторный автоматизм #' + a.id + '</b>' +
      '<br>branchId: ' + (a.branchId || 0) +
      odBlock +
      '<br>usefulness: ' + (typeof a.usefulness === 'number' ? a.usefulness : 0) +
      '<br>count: ' + (typeof a.count === 'number' ? a.count : 0) +
      '<br>штатный (isDefault): ' + (a.isDefault ? 'да' : 'нет');
    global.show_alert(html, 0);
  }

  function Info_showMentalAutomatizmsList() {
    if (typeof global.show_alert !== 'function') return;
    var arr = Array.isArray(global.MentalAutomatizms) ? global.MentalAutomatizms : [];
    if (!arr.length) {
      global.show_alert('Ментальных автоматизмов нет.', 0);
      return;
    }
    var ids = [];
    for (var i = 0; i < arr.length; i++) {
      if (arr[i] && typeof arr[i].id === 'number') ids.push(arr[i].id);
    }
    ids.sort(function (a, b) { return a - b; });
    var parts = ['<b>Ментальные автоматизмы</b> (' + ids.length + '). Щелчок по ID — детализация:<br><br>'];
    for (var j = 0; j < ids.length; j++) {
      if (j > 0) parts.push(' &nbsp; ');
      parts.push(infoAlertIdLink('Info_showMentalAutomatizmDetail', ids[j]));
    }
    global.show_alert(parts.join(''), 0);
  }

  function Info_showMentalAutomatizmDetail(id) {
    if (typeof global.show_alert !== 'function') return;
    id = parseInt(id, 10) || 0;
    var arr = Array.isArray(global.MentalAutomatizms) ? global.MentalAutomatizms : [];
    var a = null;
    for (var i = 0; i < arr.length; i++) {
      if (arr[i] && arr[i].id === id) { a = arr[i]; break; }
    }
    if (!a) {
      global.show_alert('Ментальный автоматизм #' + id + ' не найден.', 0);
      return;
    }
    var maiLink = (a.mentalActionImageId || 0)
      ? infoAlertIdLink('Info_showMentalActionImageDetail', a.mentalActionImageId)
      : '0';
    var html = '<b>Ментальный автоматизм #' + a.id + '</b>' +
      '<br>themeId: ' + (a.themeId || 0) +
      '<br>situationId: ' + (a.situationId || 0) +
      '<br>branchId: ' + (a.branchId || 0) +
      '<br>Ментальный ОД: ' + maiLink +
      '<br>usefulness: ' + (typeof a.usefulness === 'number' ? a.usefulness : 0) +
      '<br>count: ' + (typeof a.count === 'number' ? a.count : 0) +
      '<br>штатный (isDefault): ' + (a.isDefault ? 'да' : 'нет');
    global.show_alert(html, 0);
  }

  function Info_showAbstractionsList() {
    if (typeof global.show_alert !== 'function') return;
    var ap = Array.isArray(global.AbstractPerceptionImages) ? global.AbstractPerceptionImages : [];
    var aa = Array.isArray(global.AbstractActionImages) ? global.AbstractActionImages : [];
    var arr = Array.isArray(global.Abstractions) ? global.Abstractions : [];
    var blocks = [];
    blocks.push('<b>Абстракции: три разных хранилища</b> — у каждого свой тип ID; щелчок открывает <i>его</i> детализацию.');
    blocks.push('<br><br><b>1. Клоны восприятия</b> (AbstractPerceptionImages, abstract_images.js), всего ' + ap.length + ':');
    if (ap.length) {
      var apIds = [];
      for (var pi = 0; pi < ap.length; pi++) {
        if (ap[pi] && typeof ap[pi].id === 'number') apIds.push(ap[pi].id);
      }
      apIds.sort(function (a, b) { return a - b; });
      blocks.push('<br>');
      for (var pj = 0; pj < apIds.length; pj++) {
        if (pj > 0) blocks.push(' &nbsp; ');
        blocks.push(infoAlertIdLink('Info_showAbstractPerceptionImageDetail', apIds[pj]));
      }
    } else {
      blocks.push('<br><i>Нет. Появляются при <b>закрытии</b> кадра ЭП.</i>');
    }
    blocks.push('<br><br><b>2. Клоны действия</b> (AbstractActionImages), всего ' + aa.length + ':');
    if (aa.length) {
      var aaIds = [];
      for (var ai = 0; ai < aa.length; ai++) {
        if (aa[ai] && typeof aa[ai].id === 'number') aaIds.push(aa[ai].id);
      }
      aaIds.sort(function (a, b) { return a - b; });
      blocks.push('<br>');
      for (var aj = 0; aj < aaIds.length; aj++) {
        if (aj > 0) blocks.push(' &nbsp; ');
        blocks.push(infoAlertIdLink('Info_showAbstractActionImageDetail', aaIds[aj]));
      }
    } else {
      blocks.push('<br><i>Нет (или только восприятие — если в кадре не было ОД).</i>');
    }
    blocks.push('<br><br><b>3. Символы верхнего уровня</b> (Abstractions, mental_automatism.js), всего ' + arr.length + ':');
    if (!arr.length) {
      blocks.push('<br><i>Пока нет.</i>');
    } else {
      blocks.push('<br>');
      var ids = [];
      for (var i = 0; i < arr.length; i++) {
        if (arr[i] && typeof arr[i].id === 'number') ids.push(arr[i].id);
      }
      ids.sort(function (a, b) { return a - b; });
      for (var j = 0; j < ids.length; j++) {
        if (j > 0) blocks.push(' &nbsp; ');
        blocks.push(infoAlertIdLink('Info_showAbstractionDetail', ids[j]));
      }
    }
    global.show_alert(blocks.join(''), 0);
  }

  /** Человекочитаемое имя статуса гештальта (gestalt.js, GESTALT_STATUS). */
  function gestaltStatusLabel(st) {
    var n = parseInt(st, 10);
    if (isNaN(n)) return String(st);
    switch (n) {
      case 0: return '0 — новый';
      case 1: return '1 — начато';
      case 2: return '2 — частично';
      case 3: return '3 — закрыт (успех)';
      case 4: return '4 — архив';
      default: return String(n);
    }
  }

  /**
   * Список записей GestaltArr; щелчок по ID — Info_showGestaltDetail.
   * Данные живут в gestalt.js (подключается после informing.js; на момент клика уже загружены).
   */
  function Info_showGestaltsList() {
    if (typeof global.show_alert !== 'function') return;
    var arr = Array.isArray(global.GestaltArr) ? global.GestaltArr : [];
    var buf = Array.isArray(global.GestaltResonanceBuffer) ? global.GestaltResonanceBuffer : [];
    var head = '<b>Гештальты (доминанты нерешённых задач)</b><br><small>Записей: ' + arr.length
      + '. Буфер резонанса (FIFO сигнатур ЭП): ' + buf.length
      + '. Статусы: 0 новый, 1 начато, 2 частично, 3 закрыт, 4 архив.</small><br><br>';
    if (!arr.length) {
      global.show_alert(head + '<i>Записей гештальтов пока нет.</i>', 0);
      return;
    }
    var ids = [];
    for (var i = 0; i < arr.length; i++) {
      if (arr[i] && typeof arr[i].id === 'number') ids.push(arr[i].id);
    }
    ids.sort(function (a, b) { return a - b; });
    var parts = [head, 'ID: '];
    for (var j = 0; j < ids.length; j++) {
      if (j > 0) parts.push(' &nbsp; ');
      parts.push(infoAlertIdLink('Info_showGestaltDetail', ids[j]));
    }
    global.show_alert(parts.join(''), 0);
  }

  function Info_showGestaltDetail(id) {
    if (typeof global.show_alert !== 'function') return;
    id = parseInt(id, 10) || 0;
    var arr = Array.isArray(global.GestaltArr) ? global.GestaltArr : [];
    var g = null;
    for (var i = 0; i < arr.length; i++) {
      if (arr[i] && arr[i].id === id) {
        g = arr[i];
        break;
      }
    }
    if (!g) {
      global.show_alert('Гештальт #' + id + ' не найден.', 0);
      return;
    }
    var activeId = typeof global.Gestalt_activeGestaltId === 'number' ? global.Gestalt_activeGestaltId : 0;
    var masterCyc = typeof global.Gestalt_activeMasterCycleId === 'number' ? global.Gestalt_activeMasterCycleId : 0;
    var goalPart = g.goalImageId
      ? ('goalImageId: ' + infoAlertIdLink('Info_showLifeGoalDetail', g.goalImageId))
      : 'goalImageId: 0';
    var branchPart = g.problemTreeId
      ? ('ветка (problemTreeId): ' + infoAlertIdLink('Info_showPerceptionNodeDetail', g.problemTreeId))
      : ('ветка (problemTreeId): 0');
    var sitPart = g.situationId
      ? ('ситуация: ' + infoAlertIdLink('Info_showSituationImageDetail', g.situationId))
      : 'ситуация: 0';
    var autoIds = Array.isArray(g.automatismIds) ? g.automatismIds : [];
    var autoLine = 'опробованные автоматизмы: ';
    if (!autoIds.length) {
      autoLine += '—';
    } else {
      var bits = [];
      for (var a = 0; a < autoIds.length; a++) {
        bits.push(infoAlertIdLink('Info_showMotorAutomatizmDetail', autoIds[a]));
      }
      autoLine += bits.join(', ');
    }
    var pool = Array.isArray(g.analogyPool) ? g.analogyPool : [];
    var poolStr = pool.length ? ('<pre style="white-space:pre-wrap;font-size:9pt;margin:6px 0">' +
      String(JSON.stringify(pool, null, 2)) + '</pre>') : '<i>пусто</i>';
    var lines = [
      '<b>Гештальт #' + id + '</b>',
      '<br>' + goalPart,
      '<br>' + branchPart,
      '<br>' + sitPart,
      '<br>status: ' + gestaltStatusLabel(g.status),
      '<br>' + autoLine,
      '<br>lastInsightKind: ' + String(g.lastInsightKind || '—') + ', lastInsightPuls: ' + String(g.lastInsightPuls || 0)
        + ', insightChainCount: ' + String(g.insightChainCount || 0),
      '<br>ведущий сейчас: ' + (activeId === id ? 'да' : 'нет') + ' (Gestalt_activeGestaltId=' + activeId + ', цикл-хозяин=' + masterCyc + ')',
      '<br><b>analogyPool</b> (хвост аналогий):',
      poolStr
    ];
    global.show_alert(lines.join(''), 0);
  }

  function Info_showLifeGoalsList() {
    if (typeof global.show_alert !== 'function') return;
    var arr = Array.isArray(global.GoalImagesLife) ? global.GoalImagesLife : [];
    if (!arr.length) {
      global.show_alert('Образов целей жизненного опыта (GoalImagesLife) пока нет.', 0);
      return;
    }
    var ids = [];
    for (var i = 0; i < arr.length; i++) {
      if (arr[i] && typeof arr[i].id === 'number') ids.push(arr[i].id);
    }
    ids.sort(function (a, b) { return a - b; });
    var parts = ['<b>Образы целей (жизненный опыт)</b> (' + ids.length + '). Щелчок по ID — детализация:<br><br>'];
    for (var j = 0; j < ids.length; j++) {
      if (j > 0) parts.push(' &nbsp; ');
      parts.push(infoAlertIdLink('Info_showLifeGoalDetail', ids[j]));
    }
    global.show_alert(parts.join(''), 0);
  }

  function Info_showSituationImagesList() {
    if (typeof global.show_alert !== 'function') return;
    if (typeof global.SituationsTree_getAllSituationImages !== 'function') {
      global.show_alert('SituationsTree недоступен.', 0);
      return;
    }
    var arr = global.SituationsTree_getAllSituationImages() || [];
    if (!arr.length) {
      global.show_alert('Образов ситуаций (SituationImages) пока нет.', 0);
      return;
    }
    var ids = [];
    for (var i = 0; i < arr.length; i++) {
      if (arr[i] && typeof arr[i].id === 'number') ids.push(arr[i].id);
    }
    ids.sort(function (a, b) { return a - b; });
    var bySitId = {};
    for (var si = 0; si < arr.length; si++) {
      if (arr[si] && typeof arr[si].id === 'number') bySitId[arr[si].id] = arr[si];
    }
    var parts = ['<b>Образы ситуаций (SituationImages)</b> (' + ids.length + '). Щелчок по ID — детализация.<br><small>Готовые (ready) — синяя рамка.</small><br><br>'];
    for (var j = 0; j < ids.length; j++) {
      if (j > 0) parts.push(' &nbsp; ');
      var rec = bySitId[ids[j]];
      parts.push(rec ? infoSituationImageLinkFromRecord(rec) : infoAlertIdLink('Info_showSituationImageDetail', ids[j]));
    }
    global.show_alert(parts.join(''), 0);
  }

  function Info_showLifeGoalDetail(id) {
    if (typeof global.show_alert !== 'function') return;
    id = parseInt(id, 10) || 0;
    var g = typeof global.Goals_getGoalById === 'function' ? global.Goals_getGoalById(id) : null;
    if (!g) {
      global.show_alert('Образ цели #' + id + ' не найден.', 0);
      return;
    }
    var odLink = (g.actionImageId || 0)
      ? infoAlertIdLink('Info_showActionImageDetail', g.actionImageId)
      : '0';
    var lines = [
      '<b>Образ цели (жизненный опыт) #' + id + '</b>',
      '<br>perceptionNodeId: ' + (g.perceptionNodeId || 0),
      '<br>situationId: ' + (g.situationId || 0),
      '<br>stimulusImageId: ' + (g.stimulusImageId || 0),
      '<br>действие (ОД): ' + odLink,
      '<br>effect (уср.): ' + (typeof g.effect === 'number' ? g.effect : 0),
      '<br>count: ' + (typeof g.count === 'number' ? g.count : 0),
      '<br>usefulness: ' + (typeof g.usefulness === 'number' ? g.usefulness : 0),
      '<br>usefulnessCount: ' + (typeof g.usefulnessCount === 'number' ? g.usefulnessCount : 0)
    ];
    global.show_alert(lines.join(''), 0);
  }

  function Info_showAbstractionDetail(id) {
    if (typeof global.show_alert !== 'function') return;
    id = parseInt(id, 10) || 0;
    var arr = Array.isArray(global.Abstractions) ? global.Abstractions : [];
    var obj = null;
    for (var i = 0; i < arr.length; i++) {
      if (arr[i] && arr[i].id === id) { obj = arr[i]; break; }
    }
    if (!obj) {
      global.show_alert('Символ Abstractions #' + id + ' не найден.', 0);
      return;
    }
    var lines = [
      '<b>Символ Abstractions #' + id + '</b>',
      '<small>mental_automatism.js — щелчок по числу ниже ведёт в детализацию связанной сущности.</small>'
    ];
    var keys = Object.keys(obj).sort();
    for (var k = 0; k < keys.length; k++) {
      var key = keys[k];
      if (key === 'id') continue;
      var val = obj[key];
      var label = INFO_ABSTRACTION_FIELD_LABEL[key] || key;
      lines.push('<br><b>' + label + '</b> (' + key + '): ' + infoFormatAbstractionFieldValue(key, val));
    }
    global.show_alert(lines.join(''), 0);
  }

  function infoConfirmThenClear(ev, onOk) {
    if (ev && ev.stopPropagation) ev.stopPropagation();
    if (ev && ev.preventDefault) ev.preventDefault();
    var msg = 'Точно удалить?';
    if (typeof global.show_confirm === 'function') {
      global.show_confirm(msg, function (result) {
        if (result === 'OK') onOk();
      });
    } else if (typeof global.confirm === 'function' && global.confirm(msg)) {
      onOk();
    }
  }

  function Info_clearMotorAutomatizms(ev) {
    infoConfirmThenClear(ev, function () {
      if (typeof global.Automatizms_clearAll === 'function') global.Automatizms_clearAll();
    });
  }

  function Info_clearMentalAutomatizms(ev) {
    infoConfirmThenClear(ev, function () {
      if (typeof global.MentalAutomatizms_clearAll === 'function') global.MentalAutomatizms_clearAll();
    });
  }

  function Info_clearAbstractions(ev) {
    infoConfirmThenClear(ev, function () {
      if (typeof global.Abstractions_clearAll === 'function') global.Abstractions_clearAll();
    });
  }

  function Info_clearLifeGoals(ev) {
    infoConfirmThenClear(ev, function () {
      if (typeof global.Goals_clearAllLifeGoals === 'function') global.Goals_clearAllLifeGoals();
    });
  }

  function Info_clearSituationImages(ev) {
    infoConfirmThenClear(ev, function () {
      if (typeof global.SituationsTree_clearAllSituationImages === 'function') {
        global.SituationsTree_clearAllSituationImages();
      }
    });
  }

  global.Info_setField = Info_setField;
  global.Info_setMode = Info_setMode;
  global.Info_updateFromPerceptionTree = Info_updateFromPerceptionTree;
  global.Info_updateFromStimulus = Info_updateFromStimulus;
  global.Info_setProblemFromUnsolved = Info_setProblemFromUnsolved;
  global.Info_incrementStep = Info_incrementStep;
  global.Info_updateView = Info_updateView;
  global.Info_showBackgroundStack = Info_showBackgroundStack;
  global.Info_showBackgroundCycleDetail = Info_showBackgroundCycleDetail;
  global.Info_showCycleDetailById = Info_showCycleDetailById;
  global.Info_showFinalImageStimulusDetail = Info_showFinalImageStimulusDetail;
  global.Info_showPerceptionNodeDetail = Info_showPerceptionNodeDetail;
  global.Info_showEmotionRecordDetail = Info_showEmotionRecordDetail;
  global.Info_showThemeImageDetail = Info_showThemeImageDetail;
  global.Info_showSituationImageDetail = Info_showSituationImageDetail;
  global.Info_showActionImageDetail = Info_showActionImageDetail;
  global.Info_showMentalActionImageDetail = Info_showMentalActionImageDetail;
  global.Info_showMotorAutomatizmsList = Info_showMotorAutomatizmsList;
  global.Info_showMotorAutomatizmDetail = Info_showMotorAutomatizmDetail;
  global.Info_showMentalAutomatizmsList = Info_showMentalAutomatizmsList;
  global.Info_showMentalAutomatizmDetail = Info_showMentalAutomatizmDetail;
  global.Info_showAbstractionsList = Info_showAbstractionsList;
  global.Info_showAbstractionDetail = Info_showAbstractionDetail;
  global.Info_showAbstractPerceptionImageDetail = Info_showAbstractPerceptionImageDetail;
  global.Info_showAbstractActionImageDetail = Info_showAbstractActionImageDetail;
  global.Info_showLifeGoalsList = Info_showLifeGoalsList;
  global.Info_showLifeGoalDetail = Info_showLifeGoalDetail;
  global.Info_showGestaltsList = Info_showGestaltsList;
  global.Info_showGestaltDetail = Info_showGestaltDetail;
  global.Info_showMainCycleDetail = Info_showMainCycleDetail;
  global.Info_showDetail = Info_showDetail;
  global.Info_thinkingFlash = Info_thinkingFlash;
  global.Info_clearMotorAutomatizms = Info_clearMotorAutomatizms;
  global.Info_clearMentalAutomatizms = Info_clearMentalAutomatizms;
  global.Info_clearAbstractions = Info_clearAbstractions;
  global.Info_clearLifeGoals = Info_clearLifeGoals;
  global.Info_showSituationImagesList = Info_showSituationImagesList;
  global.Info_clearSituationImages = Info_clearSituationImages;
  global.Info_fillFantasmPlotOnPassiveMain = Info_fillFantasmPlotOnPassiveMain;
  global.Info_fillFantasmPlotOnPassiveBackground = Info_fillFantasmPlotOnPassiveBackground;

  function Info_showFantasmPlotDetail() {
    Info_showDetail('fantasmPlot');
  }
  global.Info_showFantasmPlotDetail = Info_showFantasmPlotDetail;

})(window);

