(function (global) {
  'use strict';

  var ROW_ID = 'stimulsRow';

  /**
   * Есть ли среди кнопок стимулов хотя бы один с семантикой, достаточной для старта ОР
   * (тот же критерий, что «Участвует в ориентировочном рефлексe»: remainingActivations === 0).
   * Полный обход — на 2-м пульсе (puls.js); далее флаг поднимается точечно при обновлении семантики.
   * Используется диспетчером: авто-show_alert лога первого цикла после загрузки страницы.
   */
  if (typeof global.OrientationReflex_anyStimulusReadyForOr !== 'boolean') {
    global.OrientationReflex_anyStimulusReadyForOr = false;
  }

  /** Ключ контекста для «готовности к ОР»: well|emotionId|ветка дерева — при смене нужен полный пересчёт бордеров. */
  var lastStimulusReadinessContextKey = null;

  function sleepBlocksStimulus(rowId, localStimId) {
    if (typeof global.SleepMode_shouldBlockStimulusInteraction !== 'function') return false;
    return global.SleepMode_shouldBlockStimulusInteraction(rowId, localStimId);
  }

  /**
   * Разрешённые в сне стимулы: первый клик будит (SleepMode_exit без флага сновидений), затем тот же клик идёт в обычную логику стимула.
   */
  function tryExitSleepOnAllowedStimulusActivation(rowId, localStimId, willActivate) {
    if (!willActivate) return;
    if (typeof global.SleepMode_isActive !== 'function' || !global.SleepMode_isActive()) return;
    if (typeof global.SleepMode_shouldBlockStimulusInteraction === 'function' &&
        global.SleepMode_shouldBlockStimulusInteraction(rowId, localStimId)) {
      return;
    }
    if (typeof global.SleepMode_exit === 'function') {
      global.SleepMode_exit();
    }
  }

  /** Игровой режим / обучение на инфокартине ↔ isGameMode, isAuthoritarianEducation. */
  function syncInfoPlayLearningDetectors() {
    if (typeof global.InfoDet_updatePlayMode === 'function') {
      global.InfoDet_updatePlayMode(global.BasicContextsActived || []);
    }
    if (typeof global.InfoDet_updateLearningAndSearch === 'function') {
      global.InfoDet_updateLearningAndSearch(global.BasicContextsActived || [], global.VitalsArr || []);
    }
    if (typeof global.InfoDet_updateOperatorIgnoringFromStimulus === 'function') {
      global.InfoDet_updateOperatorIgnoringFromStimulus();
    }
  }

  /**
   * Краткая подсветка кнопки на один пульс при запуске ОР/ФО.
   * Сияние добавляется сверху и снизу по 15px.
   */
  function flashStimulusButtonForOnePulse(button) {
    if (!button) return;
    var pulseNow = (typeof global.Cur_puls_val === 'number') ? global.Cur_puls_val : 0;
    var untilPulse = pulseNow + 1;
    var glow = '0 -15px 12px -4px rgba(80, 170, 255, 0.9), 0 15px 12px -4px rgba(80, 170, 255, 0.9)';
    var prevShadow = button.style.boxShadow || '';
    button.dataset.orGlowPrevShadow = prevShadow;
    button.dataset.orGlowUntilPulse = String(untilPulse);
    button.style.boxShadow = prevShadow ? (prevShadow + ', ' + glow) : glow;

    if (button._orGlowTimer) {
      global.clearInterval(button._orGlowTimer);
    }
    button._orGlowTimer = global.setInterval(function () {
      var curPulse = (typeof global.Cur_puls_val === 'number') ? global.Cur_puls_val : 0;
      if (curPulse < untilPulse) return;
      if (button._orGlowTimer) {
        global.clearInterval(button._orGlowTimer);
        button._orGlowTimer = null;
      }
      var restore = button.dataset.orGlowPrevShadow || '';
      button.style.boxShadow = restore;
      delete button.dataset.orGlowPrevShadow;
      delete button.dataset.orGlowUntilPulse;
    }, 50);
  }

  /**
   * Обновить видимость «готовых к ОР» кнопок без наведения мыши.
   * Готовая кнопка = `remainingActivations === 0` для её (условного) FinalImageId.
   *
   * Зависит от:
   * - SemanticMemoryIndex (для samplesCount)
   * - BadNormWell и BasicContextsActived (для well/emotionId)
   *
   * Полный обход — при смене базового состояния/эмоции/ID активной ветки дерева восприятия
   * (см. `scheduleStimulusReadinessRefreshIfNeeded` из `puls.js`); иначе бордеры залипают
   * после смены виталов или ветки. Точечно — при изменении семантики
   * (см. `updateStimulusButtonsReadinessViewForFinalImageId`).
   *
   * Важно: обработчики `mouseenter`/`mouseleave` обновляют только `title`, не бордер.
   */
  function updateStimulusButtonsReadinessView() {
    if (!global.document) return;
    if (typeof global.OrientationReflex_getOrReadinessForFinalImageId !== 'function') return;
    if (typeof global.StimulusGlobalId_toGlobal !== 'function') return;
    if (typeof global.StimulusGlobalId_getTypeFromRowId !== 'function') return;
    if (typeof global.FinalImages_findFinalImageId !== 'function') return;

    var anyOrReady = false;
    var sawNumericReadiness = false;
    var rowIds = [ROW_ID, 'stimulsRowPositiv', 'stimulsRowNegative', 'stimulsRowNeutral'];
    for (var r = 0; r < rowIds.length; r++) {
      var rowId = rowIds[r];
      var row = global.document.getElementById(rowId);
      if (!row) continue;
      var buttons = row.querySelectorAll('button[data-stim-id]');
      for (var i = 0; i < buttons.length; i++) {
        var btn = buttons[i];
        var stimId = parseInt(btn.dataset.stimId, 10);
        if (!stimId) continue;

        var baseTitle = btn.dataset.baseTitle || btn.title || '';
        if (!baseTitle) baseTitle = String(btn.textContent || '');

        var type = global.StimulusGlobalId_getTypeFromRowId(rowId);
        var globalStimId = global.StimulusGlobalId_toGlobal(type, stimId);
        if (!globalStimId) {
          btn.style.border = '1px solid #888';
          btn.title = baseTitle;
          continue;
        }

        var cachedFinalImageId = parseInt(btn.dataset.readinessFinalImageId, 10);
        var finalImageId = (cachedFinalImageId && cachedFinalImageId > 0)
          ? cachedFinalImageId
          : (global.FinalImages_findFinalImageId([globalStimId]) || 0);
        // Если finalImageId ещё не найден (0), будем продолжать пытаться на следующих пульсах.
        btn.dataset.readinessFinalImageId = String(finalImageId);
        var readiness = global.OrientationReflex_getOrReadinessForFinalImageId(finalImageId);

        if (readiness && typeof readiness.remainingActivations === 'number') {
          sawNumericReadiness = true;
          if (readiness.remainingActivations === 0) {
            anyOrReady = true;
            btn.style.border = '2px solid #888';
            btn.title = baseTitle + '\nУчаствует в ориентировочном рефлексе';
          } else {
            btn.style.border = '1px solid #888';
            btn.title = baseTitle + '\nУровень готовности для ОР: ' + String(readiness.remainingActivations) + ' активаций осталось';
          }
        } else {
          btn.style.border = '1px solid #888';
          btn.title = baseTitle + '\nУровень готовности для ОР: неизвестно (контексты ещё не определены)';
        }
      }
    }
    if (!anyOrReady) {
      if (Array.isArray(global.ActiveMotivationStimuls) &&
          (global.ActiveMotivationStimuls.indexOf(1) !== -1 || global.ActiveMotivationStimuls.indexOf(2) !== -1)) {
        anyOrReady = true;
      }
    }
    if (!anyOrReady) {
      var bnw = typeof global.BadNormWell === 'number' ? global.BadNormWell : 0;
      if (bnw === 1) {
        anyOrReady = true;
      } else if (!sawNumericReadiness) {
        // На раннем 2-м пульсе emotionId/well часто ещё не дают числовой готовности (null у всех
        // кнопок) — иначе блокировался бы стартовый лог первого цикла на 3-м пульсе.
        anyOrReady = true;
      }
    }
    global.OrientationReflex_anyStimulusReadyForOr = anyOrReady;
  }

  /**
   * Вызов из пульса: если изменились BadNormWell, эмоция (BasicContexts) или ID активной ветки
   * дерева восприятия — заново прогоняем `updateStimulusButtonsReadinessView`.
   */
  function scheduleStimulusReadinessRefreshIfNeeded() {
    var well = typeof global.BadNormWell === 'number' ? global.BadNormWell : 0;
    var emotionId = 0;
    if (typeof global.Emotions_getOrCreateEmotionId === 'function' && Array.isArray(global.BasicContextsActived)) {
      emotionId = global.Emotions_getOrCreateEmotionId(global.BasicContextsActived) || 0;
    }
    var branchId = 0;
    if (typeof global.PerceptionTree_getActiveTerminalNodeId === 'function') {
      branchId = global.PerceptionTree_getActiveTerminalNodeId() || 0;
    }
    var key = String(well) + '|' + String(emotionId) + '|' + String(branchId);
    if (key === lastStimulusReadinessContextKey) return;
    lastStimulusReadinessContextKey = key;
    updateStimulusButtonsReadinessView();
  }

  /**
   * Точечно обновить готовность для кнопок, относящихся к конкретному finalImageId.
   * Вызывается при изменении семантики (registerSemanticSample) после добавления нового образца.
   *
   * Так мы избегаем перерасчёта для всех кнопок на каждом пульсе.
   * @param {number} finalImageId
   */
  function updateStimulusButtonsReadinessViewForFinalImageId(finalImageId) {
    finalImageId = parseInt(finalImageId, 10);
    if (!finalImageId) return;
    if (!global.document) return;
    if (typeof global.OrientationReflex_getOrReadinessForFinalImageId !== 'function') return;
    if (typeof global.StimulusGlobalId_toGlobal !== 'function') return;
    if (typeof global.StimulusGlobalId_getTypeFromRowId !== 'function') return;
    if (typeof global.FinalImages_findFinalImageId !== 'function') return;

    var baseReadiness = global.OrientationReflex_getOrReadinessForFinalImageId(finalImageId);

    var rowIds = [ROW_ID, 'stimulsRowPositiv', 'stimulsRowNegative', 'stimulsRowNeutral'];
    for (var r = 0; r < rowIds.length; r++) {
      var rowId = rowIds[r];
      var row = global.document.getElementById(rowId);
      if (!row) continue;
      var buttons = row.querySelectorAll('button[data-stim-id]');
      for (var i = 0; i < buttons.length; i++) {
        var btn = buttons[i];
        var stimId = parseInt(btn.dataset.stimId, 10);
        if (!stimId) continue;

        var cachedFinalImageId = parseInt(btn.dataset.readinessFinalImageId, 10) || 0;
        if (cachedFinalImageId && cachedFinalImageId !== finalImageId) continue;

        var type = global.StimulusGlobalId_getTypeFromRowId(rowId);
        var globalStimId = global.StimulusGlobalId_toGlobal(type, stimId);
        if (!globalStimId) continue;
        var computedFinalImageId = global.FinalImages_findFinalImageId([globalStimId]) || 0;
        if (computedFinalImageId !== finalImageId) continue;

        btn.dataset.readinessFinalImageId = String(computedFinalImageId);
        var baseTitle = btn.dataset.baseTitle || btn.title || '';
        if (!baseTitle) baseTitle = String(btn.textContent || '');

        if (baseReadiness && typeof baseReadiness.remainingActivations === 'number') {
          if (baseReadiness.remainingActivations === 0) {
            btn.style.border = '2px solid #888';
            btn.title = baseTitle + '\nУчаствует в ориентировочном рефлексе';
          } else {
            btn.style.border = '1px solid #888';
            btn.title = baseTitle + '\nУровень готовности для ОР: ' +
              String(baseReadiness.remainingActivations) + ' активаций осталось';
          }
        } else {
          btn.style.border = '1px solid #888';
          btn.title = baseTitle + '\nУровень готовности для ОР: неизвестно (контексты ещё не определены)';
        }
      }
    }
    if (baseReadiness && baseReadiness.remainingActivations === 0) {
      global.OrientationReflex_anyStimulusReadyForOr = true;
    }
    if (typeof global.SleepMode_refreshStimulusButtonVisuals === 'function') {
      global.SleepMode_refreshStimulusButtonVisuals();
    }
  }

  function clearStimRow(rowId) {
    if (typeof global.SleepMode_isActive === 'function' && global.SleepMode_isActive()) {
      return;
    }
    var activeKey = null;
    if (rowId === ROW_ID) {
      activeKey = 'ActiveMotivationStimuls';
      // Сброс режимов Играть / Учить
      global.isGameMode = false;
      global.isAuthoritarianEducation = false;
    } else if (rowId === 'stimulsRowPositiv') {
      activeKey = 'ActivePositivStimuls';
    } else if (rowId === 'stimulsRowNegative') {
      activeKey = 'ActiveNegativeStimuls';
    } else if (rowId === 'stimulsRowNeutral') {
      activeKey = 'ActiveNeutralStimuls';
    }

    if (activeKey && Array.isArray(global[activeKey])) {
      global[activeKey] = [];
    }

    var row = global.document.getElementById(rowId);
    if (!row) return;

    var buttons = row.querySelectorAll('button');
    for (var i = 0; i < buttons.length; i++) {
      var btn = buttons[i];
      var baseBg = btn.dataset.baseBg || '#f8f8f8';
      btn.style.backgroundColor = baseBg;
      btn.style.boxShadow = 'none';
    }

    if (rowId === ROW_ID && typeof updateMotivationButtonsView === 'function') {
      updateMotivationButtonsView();
    }
    if (rowId === ROW_ID) {
      syncInfoPlayLearningDetectors();
    }
  }

  /** Дезактивировать все стимулы всех видов (мотивирующие, позитивные, негативные, нейтральные). */
  function clearAllStimuli() {
    if (typeof global.SleepMode_isActive === 'function' && global.SleepMode_isActive()) {
      return;
    }
    var rowIds = [ROW_ID, 'stimulsRowPositiv', 'stimulsRowNegative', 'stimulsRowNeutral'];
    for (var r = 0; r < rowIds.length; r++) {
      clearStimRow(rowIds[r]);
    }
    if (typeof global.update_vitals_view === 'function') {
      global.update_vitals_view();
    }
    syncInfoPlayLearningDetectors();
  }

  function updateMotivationButtonsView() {
    var row = global.document.getElementById(ROW_ID);
    if (!row || !global.StimulMotivarion) return;
    var buttons = row.querySelectorAll('button[data-stim-id]');
    for (var i = 0; i < buttons.length; i++) {
      var btn = buttons[i];
      var id = parseInt(btn.dataset.stimId, 10);
      if (!id) continue;
      var stim = null;
      for (var j = 0; j < global.StimulMotivarion.length; j++) {
        if (global.StimulMotivarion[j].Id === id) {
          stim = global.StimulMotivarion[j];
          break;
        }
      }
      if (!stim) continue;

      // Цвета по полю bg: 1 - розовый, 2 - белый, 3 - светло-зелёный
      var bgType = stim.bg || 2;
      var baseBg = '#f8f8f8';
      var activeBg = '#ffe4b5';
      var shadowColor = 'rgba(200, 160, 80, 0.8)';
      if (bgType === 1) {
        baseBg = '#ffe6f0';
        activeBg = '#ffccd9';
        shadowColor = 'rgba(255, 140, 180, 0.8)';
      } else if (bgType === 3) {
        baseBg = '#e0f8e0';
        activeBg = '#c8f0c8';
        shadowColor = 'rgba(80, 200, 120, 0.8)';
      }
      btn.dataset.baseBg = baseBg;

      var active = false;
      if (stim.vitalID === 11) {
        active = !!global.isGameMode;
      } else if (stim.vitalID === 12) {
        active = !!global.isAuthoritarianEducation;
      } else {
        active = isStimActive(stim.Id);
      }

      if (active) {
        btn.style.backgroundColor = activeBg;
        btn.style.boxShadow = '0 0 8px 2px ' + shadowColor;
      } else {
        btn.style.backgroundColor = baseBg;
        btn.style.boxShadow = 'none';
      }
    }
  }

  function ensureStimulRow(rowId, labelText, insertAfterId) {
    var row = global.document.getElementById(rowId);
    if (row) {
      return row;
    }
    var content = global.document.querySelector('.beast-content');
    if (!content) {
      return null;
    }
    var label = global.document.createElement('div');
    label.style.display = 'flex';
    label.style.alignItems = 'center';
    label.style.justifyContent = 'space-between';
    label.style.fontSize = '10pt';
    label.style.marginTop = '4px';
    label.style.marginBottom = '2px';

    var labelTextSpan = global.document.createElement('span');
    labelTextSpan.textContent = labelText;
    label.appendChild(labelTextSpan);

    var clearBtn = global.document.createElement('button');
    clearBtn.type = 'button';
    clearBtn.textContent = '×';
    clearBtn.title = 'Сбросить все стимулы этой строки\nСброс всех видов стимулов - по двойному клику на любом стимуле';
    clearBtn.style.width = '18px';
    clearBtn.style.height = '18px';
    clearBtn.style.borderRadius = '50%';
    clearBtn.style.border = '1px solid #aaa';
    clearBtn.style.backgroundColor = '#f0f0f0';
    clearBtn.style.color = '#666';
    clearBtn.style.cursor = 'pointer';
    clearBtn.style.padding = '0';
    clearBtn.style.fontSize = '11px';
    clearBtn.style.lineHeight = '16px';
    clearBtn.setAttribute('data-stim-row-clear', rowId);
    clearBtn.addEventListener('click', function () {
      clearStimRow(rowId);
    });
    label.appendChild(clearBtn);

    row = global.document.createElement('div');
    row.id = rowId;
    row.style.display = 'flex';
    row.style.flexWrap = 'wrap';
    row.style.gap = '4px';
    row.style.marginBottom = '10px';
    row.style.marginTop = '6px';

    var ref = global.document.getElementById(insertAfterId);
    if (ref && ref.parentNode === content) {
      content.insertBefore(label, ref.nextSibling);
      content.insertBefore(row, label.nextSibling);
    } else {
      content.appendChild(label);
      content.appendChild(row);
    }
    return row;
  }

  function ensureRow() {
    return ensureStimulRow(ROW_ID, 'Мотивирующие стимулы:', 'basicContextsRow');
  }

  function isStimActive(id) {
    if (!Array.isArray(global.ActiveMotivationStimuls)) return false;
    return global.ActiveMotivationStimuls.indexOf(id) !== -1;
  }

  function toggleStimActive(id) {
    if (!Array.isArray(global.ActiveMotivationStimuls)) {
      global.ActiveMotivationStimuls = [];
    }
    var idx = global.ActiveMotivationStimuls.indexOf(id);
    if (idx === -1) {
      global.ActiveMotivationStimuls.push(id);
    } else {
      global.ActiveMotivationStimuls.splice(idx, 1);
    }
  }

  function applyVitalDelta(vitalID, delta) {
    if (!global.VitalsArr || delta === 0 || vitalID <= 0 || vitalID > 10) return;
    for (var i = 0; i < global.VitalsArr.length; i++) {
      if (global.VitalsArr[i].Id === vitalID) {
        var v = global.VitalsArr[i];
        var newVal = v.value + delta;
        if (newVal < 0) newVal = 0;
        if (newVal > 100) newVal = 100;
        v.value = newVal;
        if (typeof global.saveVitalsToStorage === 'function') global.saveVitalsToStorage();
        if (typeof global.update_vitals_view === 'function') global.update_vitals_view();
        break;
      }
    }
  }

  function applyVital7Delta(delta) {
    applyVitalDelta(7, delta);
  }

  function applyMotivationEffects(stimId) {
    if (!global.StimulMotivarion_EffectsToBContexts) return;
    var effects = global.StimulMotivarion_EffectsToBContexts[stimId];
    if (!effects || !effects.length) return;
    for (var i = 0; i < effects.length; i++) {
      var eff = effects[i];
      if (!eff) continue;
      var vitalID = eff.vitalID;
      var delta = eff.delta || 0;
      if (vitalID >= 1 && vitalID <= 10) {
        applyVitalDelta(vitalID, delta);
      } else if (vitalID === 101) {
        if (typeof global.SetWellForHolding === 'function') {
          global.SetWellForHolding();
        }
      } else if (vitalID === 102) {
        if (typeof global.SetBadForHolding === 'function') {
          global.SetBadForHolding();
        }
      } else if (vitalID === 103) {
        var makeActiveGame = true;
        global.isGameMode = makeActiveGame;
        if (makeActiveGame) {
          global.isAuthoritarianEducation = false;
          // сбросить подсветку кнопки «Учить» (Id 20)
          var teachBtn = global.document.querySelector('#' + ROW_ID + ' button[data-stim-id=\"20\"]');
          if (teachBtn) {
            teachBtn.style.backgroundColor = teachBtn.dataset.baseBg || '#f8f8f8';
            teachBtn.style.boxShadow = 'none';
          }
        }
        if (typeof global.update_vitals_view === 'function') {
          global.update_vitals_view();
        }
        syncInfoPlayLearningDetectors();
      } else if (vitalID === 104) {
        var makeActiveEdu = true;
        global.isAuthoritarianEducation = makeActiveEdu;
        if (makeActiveEdu) {
          global.isGameMode = false;
          // сбросить подсветку кнопки «Играть» (Id 19)
          var playBtn = global.document.querySelector('#' + ROW_ID + ' button[data-stim-id=\"19\"]');
          if (playBtn) {
            playBtn.style.backgroundColor = playBtn.dataset.baseBg || '#f8f8f8';
            playBtn.style.boxShadow = 'none';
          }
        }
        if (typeof global.update_vitals_view === 'function') {
          global.update_vitals_view();
        }
        syncInfoPlayLearningDetectors();
      }
    }
  }

  function applyPerceptionContextEffects(rowId, stimId) {
    var map = null;
    if (rowId === 'stimulsRowPositiv') {
      map = global.StimulPositiv_EffectsToBContexts;
    } else if (rowId === 'stimulsRowNegative') {
      map = global.StimulNegative_EffectsToBContexts;
    }
    if (!map) return;
    var codes = map[stimId];
    if (!codes || !codes.length) return;

    var contextIds = [];
    for (var i = 0; i < codes.length; i++) {
      var code = codes[i];
      if (typeof code !== 'number') continue;
      if (code >= 1 && code <= 20) {
        contextIds.push(code);
      } else if (code === 101) {
        if (typeof global.SetWellForHolding === 'function') {
          global.SetWellForHolding();
        }
      } else if (code === 102) {
        if (typeof global.SetBadForHolding === 'function') {
          global.SetBadForHolding();
        }
      } else if (code === 103) {
        global.isGameMode = true;
        global.isAuthoritarianEducation = false;
      } else if (code === 104) {
        global.isAuthoritarianEducation = true;
        global.isGameMode = false;
      }
    }
    syncInfoPlayLearningDetectors();
    if (contextIds.length && typeof global.ActivateBasicContextsForHolding === 'function') {
      global.ActivateBasicContextsForHolding(contextIds);
    }
  }

  function isSimpleStimActive(activeKey, id) {
    if (!Array.isArray(global[activeKey])) return false;
    return global[activeKey].indexOf(id) !== -1;
  }

  function toggleSimpleStim(activeKey, id) {
    if (!Array.isArray(global[activeKey])) {
      global[activeKey] = [];
    }
    var idx = global[activeKey].indexOf(id);
    if (idx === -1) {
      global[activeKey].push(id);
    } else {
      global[activeKey].splice(idx, 1);
    }
  }

  function showStimulusUnderstanding(stimId, sourceType, frameIndex) {
    if (typeof global.show_alert !== 'function') {
      return;
    }
    var name = '';
    var arr = null;
    if (sourceType === 'motivation') {
      arr = global.StimulMotivarion;
    } else if (sourceType === 'positive') {
      arr = global.StimulPositiv;
    } else if (sourceType === 'negative') {
      arr = global.StimulNegative;
    } else if (sourceType === 'neutral') {
      arr = global.StimulNeutral;
    }
    if (arr && Array.isArray(arr)) {
      for (var i = 0; i < arr.length; i++) {
        if (arr[i] && arr[i].Id === stimId) {
          name = arr[i].name || '';
          break;
        }
      }
    }

    if (typeof global.FinalImages_getOrCreateFinalImageId !== 'function' ||
        typeof global.getImageUnderstandingModel !== 'function') {
      global.show_alert('Модель понимания для стимула ' + name + ' пока недоступна.');
      return;
    }

    // Глобальный id стимула (type*1000+localId), чтобы образ восприятия однозначно соответствовал типу стимула.
    var globalStimId = stimId;
    if (typeof global.StimulusGlobalId_toGlobal === 'function' && typeof global.StimulusGlobalId_getTypeFromSourceType === 'function') {
      var type = global.StimulusGlobalId_getTypeFromSourceType(sourceType);
      globalStimId = global.StimulusGlobalId_toGlobal(type, stimId);
    }
    var finalImageId = global.FinalImages_getOrCreateFinalImageId([globalStimId]);
    if (!finalImageId) {
      global.show_alert('Для стимула ' + name + ' ещё нет семантических данных.');
      return;
    }

    // Пересборка модели из текущей SemanticMemory, чтобы число обучений и значимость всегда были актуальными.
    if (typeof global.buildImageUnderstandingModel === 'function') {
      global.buildImageUnderstandingModel(finalImageId);
    }
    var model = global.getImageUnderstandingModel(finalImageId) || [];
    if (!model.length) {
      global.show_alert('Для стимула ' + name + ' ещё нет семантических данных.');
      return;
    }

    function wellLabel(w) {
      if (w === 1) return 'Плохо';
      if (w === 2) return 'Норма';
      if (w === 3) return 'Хорошо';
      return String(w);
    }

    function emotionContexts(emotionId) {
      if (!Array.isArray(global.Emotions) || !Array.isArray(global.BasicContexts)) {
        return '';
      }
      var ctxIds = null;
      for (var i = 0; i < global.Emotions.length; i++) {
        if (global.Emotions[i] && global.Emotions[i].id === emotionId) {
          ctxIds = global.Emotions[i].contextIds || [];
          break;
        }
      }
      if (!ctxIds || !ctxIds.length) return '';
      var names = [];
      for (var j = 0; j < ctxIds.length; j++) {
        var cid = ctxIds[j];
        for (var k = 0; k < global.BasicContexts.length; k++) {
          if (global.BasicContexts[k] && global.BasicContexts[k].id === cid) {
            names.push(global.BasicContexts[k].name || '');
            break;
          }
        }
      }
      return names.filter(Boolean).join(', ');
    }

    // Вспомогательная функция для поиска названия стимула по Id
    function findStimulusNameById(id) {
      var groups = [global.StimulMotivarion, global.StimulPositiv, global.StimulNegative, global.StimulNeutral];
      for (var g = 0; g < groups.length; g++) {
        var arrG = groups[g];
        if (!arrG || !Array.isArray(arrG)) continue;
        for (var h = 0; h < arrG.length; h++) {
          if (arrG[h] && arrG[h].Id === id) {
            return arrG[h].name || '';
          }
        }
      }
      return '';
    }

    // Если запрошен конкретный кадр модели — показываем детализацию по нему
    if (typeof frameIndex === 'number' && frameIndex >= 0 && frameIndex < model.length) {
      var r = model[frameIndex];
      var htmlDetail = '<b>Модель понимания стимула ' + (name || ('Id ' + stimId)) + '</b><br>' +
        '<b>Кадр памяти #' + (frameIndex + 1) + '</b><br><br>' +
        '<b>Состояние:</b> ' + wellLabel(r.wellNormaBad) + '<br>' +
        '<b>EmotionId:</b> ' + r.emotionId + '<br>' +
        '<b>Эмоциональные контексты:</b> ' + (emotionContexts(r.emotionId) || '—') + '<br><br>' +
        '<b>Статистика значимости:</b><br>' +
        'mean z = ' + (r.meanImportance || 0).toFixed(3) + '<br>' +
        'last z = ' + (r.lastImportance || 0).toFixed(3) + '<br>' +
        'эпизодов = ' + (r.samplesCount || 0) + '<br><br>';

      // Компоненты конечного образа (FinalImage)
      var components = [];
      if (Array.isArray(global.FinalImages)) {
        for (var fi = 0; fi < global.FinalImages.length; fi++) {
          var fiItem = global.FinalImages[fi];
          if (fiItem && fiItem.id === finalImageId && Array.isArray(fiItem.stimulIds)) {
            for (var si = 0; si < fiItem.stimulIds.length; si++) {
              var sid = fiItem.stimulIds[si];
              var sName = findStimulusNameById(sid);
              components.push(sName || ('Id ' + sid));
            }
            break;
          }
        }
      }
      htmlDetail += '<b>Компоненты конечного образа (FinalImageId ' + finalImageId + '):</b><br>' +
        (components.length ? components.join(', ') : '—') + '<br>';

      global.show_alert(htmlDetail);
      return;
    }

    // Иначе показываем сводную модель по всем кадрам с кликабельными значениями last z
    var totalSamples = 0;
    var sumWeighted = 0;
    for (var m = 0; m < model.length; m++) {
      var it = model[m];
      var cnt = it.samplesCount || 0;
      totalSamples += cnt;
      sumWeighted += (it.meanImportance || 0) * cnt;
    }
    var overallMean = totalSamples > 0 ? (sumWeighted / totalSamples) : 0;

    var html = '<b>Модель понимания стимула ' + (name || ('Id ' + stimId)) + '</b><br>' +
      'Средняя семантическая значимость z ~ ' + overallMean.toFixed(2) + '<br>' +
      'Число обучений: ' + totalSamples + '<br>' +
      '<br><b>Кадры памяти:</b> ';

    for (var n = 0; n < model.length; n++) {
      var r2 = model[n];
      var zLast = (r2.lastImportance || 0).toFixed(1);
      html += '<span data-frame-idx="' + n + '" ' +
        'style="cursor:pointer;text-decoration:underline;color:#1565C0;margin-right:6px;">' +
        zLast + '</span>';
    }
    html += '<br>';

    global.show_alert(html);

    // После показа диалога навешиваем обработчики на числа z
    global.setTimeout(function () {
      var container = global.document.querySelector('.alert-dialog .alert-message');
      if (!container) return;
      var nodes = container.querySelectorAll('[data-frame-idx]');
      for (var i2 = 0; i2 < nodes.length; i2++) {
        (function (el) {
          el.addEventListener('click', function (ev) {
            ev.preventDefault();
            ev.stopPropagation();
            var idx = parseInt(el.getAttribute('data-frame-idx'), 10);
            if (!isNaN(idx)) {
              if (typeof global.close_alert === 'function') {
                global.close_alert();
              }
              // Перезапускаем диалог уже для одного кадра
              showStimulusUnderstanding(stimId, sourceType, idx);
            }
          });
        })(nodes[i2]);
      }
    }, 0);
  }

  function attachInfoIcon(button, stimId, sourceType) {
    button.style.position = 'relative';
    button.style.borderTopRightRadius = '0';
    button.style.paddingRight = '16px';

    var info = global.document.createElement('span');
    info.textContent = 'i';
    info.title = 'Показать модель понимания стимула';
    info.style.position = 'absolute';
    info.style.top = '-3px';
    info.style.right = '-3px';
    info.style.width = '10px';
    info.style.height = '10px';
    info.style.fontSize = '8pt';
    info.style.lineHeight = '10px';
    info.style.textAlign = 'center';
    info.style.borderRadius = '2px';
    info.style.border = '1px solid #555';
    info.style.backgroundColor = '#fff';
    info.style.cursor = 'pointer';
    info.style.padding = '0';

    info.addEventListener('click', function (ev) {
      ev.stopPropagation();
      ev.preventDefault();
      showStimulusUnderstanding(stimId, sourceType);
    });

    button.appendChild(info);
  }

  function buildRowForSimpleStimuls(rowId, labelText, stimulArray, activeKey, deltaVital7, insertAfterId) {
    var row = ensureStimulRow(rowId, labelText, insertAfterId);
    if (!row || !Array.isArray(stimulArray) || stimulArray.length === 0) return;
    row.innerHTML = '';
    var baseBg = deltaVital7 > 0 ? '#ffe6f0' : (deltaVital7 < 0 ? '#e0f8e0' : '#f0f0f0');
    var activeBg = deltaVital7 > 0 ? '#ffccd9' : (deltaVital7 < 0 ? '#c8f0c8' : '#e8e8e8');
    var shadowColor = deltaVital7 > 0 ? 'rgba(255, 140, 180, 0.8)' : (deltaVital7 < 0 ? 'rgba(80, 200, 120, 0.8)' : 'rgba(120, 120, 120, 0.5)');
    for (var i = 0; i < stimulArray.length; i++) {
      var stim = stimulArray[i];
      var btn = global.document.createElement('button');
      btn.type = 'button';
      btn.textContent = stim.name || ('S' + stim.Id);
      btn.title = stim.title || stim.name || '';
      btn.dataset.baseTitle = btn.title;
      btn.dataset.stimId = String(stim.Id);
      btn.style.padding = '2px 8px';
      btn.style.fontSize = '9pt';
      btn.style.borderRadius = '10px';
      btn.style.border = '1px solid #888';
      btn.style.cursor = 'pointer';
      btn.style.color = '#000';
      btn.style.backgroundColor = baseBg;
      btn.dataset.baseBg = baseBg;
      attachInfoIcon(
        btn,
        stim.Id,
        rowId === 'stimulsRowPositiv'
          ? 'positive'
          : rowId === 'stimulsRowNegative'
            ? 'negative'
            : 'neutral'
      );

      // Наведение мыши: в подсказке показываем «готовность для старта ОР».
      // Бордер управляется обновлением из `updateStimulusButtonsReadinessView*`,
      // а не hover-логикой (иначе визуальный индикатор "скачет").
      // (сколько активаций осталось до порога OR_well_known).
      (function (sLocal, buttonLocal, rowIdLocal) {
        var baseTitle = sLocal && (sLocal.title || sLocal.name) ? (sLocal.title || sLocal.name) : ('S' + (sLocal ? sLocal.Id : ''));
        buttonLocal.addEventListener('mouseenter', function () {
          if (typeof global.OrientationReflex_getOrReadinessForFinalImageId !== 'function' ||
              typeof global.StimulusGlobalId_toGlobal !== 'function' ||
              typeof global.StimulusGlobalId_getTypeFromRowId !== 'function' ||
              typeof global.FinalImages_findFinalImageId !== 'function') {
            buttonLocal.title = baseTitle;
            return;
          }

          var type = global.StimulusGlobalId_getTypeFromRowId(rowIdLocal);
          var globalStimId = global.StimulusGlobalId_toGlobal(type, sLocal.Id);
          if (!globalStimId) {
            buttonLocal.title = baseTitle;
            return;
          }
          var finalImageId = global.FinalImages_findFinalImageId([globalStimId]) || 0;
          var readiness = global.OrientationReflex_getOrReadinessForFinalImageId(finalImageId);
          var remaining = readiness && typeof readiness.remainingActivations === 'number'
            ? readiness.remainingActivations
            : '';
          if (typeof readiness.remainingActivations === 'number') {
            if (readiness.remainingActivations === 0) {
              buttonLocal.title = baseTitle + '\nУчаствует в ориентировочном рефлексе';
            } else {
              buttonLocal.title = baseTitle + '\nУровень готовности для ОР: ' + String(remaining) + ' активаций осталось';
            }
          } else {
            buttonLocal.title = baseTitle + '\nУровень готовности для ОР: неизвестно (контексты ещё не определены)';
          }
        });
        buttonLocal.addEventListener('mouseleave', function () {
          buttonLocal.title = baseTitle;
        });
      })(stim, btn, rowId);

      (function (s, button, rowKey) {
        button.addEventListener('dblclick', function () {
          clearAllStimuli();
        });
        button.addEventListener('click', function () {
          var willActivateSimple = !isSimpleStimActive(activeKey, s.Id);
          tryExitSleepOnAllowedStimulusActivation(rowKey, s.Id, willActivateSimple);
          if (sleepBlocksStimulus(rowKey, s.Id)) return;
          if (typeof global.getDiffImportance === 'function') {
            // Базовая фиксация значимости ДО действий Beast
            global.getDiffImportance();
          }
          toggleSimpleStim(activeKey, s.Id);
          var active = isSimpleStimActive(activeKey, s.Id);
          if (active) {
            button.style.backgroundColor = activeBg;
            button.style.boxShadow = '0 0 8px 2px ' + shadowColor;
            // Позитивные/негативные стимулы воздействуют на базовые контексты,
            // а не напрямую на витал 7
            if (rowKey === 'stimulsRowPositiv' || rowKey === 'stimulsRowNegative') {
              if (typeof applyPerceptionContextEffects === 'function') {
                applyPerceptionContextEffects(rowKey, s.Id);
              }
            }
          } else {
            button.style.backgroundColor = button.dataset.baseBg || baseBg;
            button.style.boxShadow = 'none';
          }
          if (typeof global.update_vitals_view === 'function') {
            global.update_vitals_view();
          }
          if (typeof global.OrientationReflex_runOnStimulusActivation === 'function') {
            var startedFoSimple = global.OrientationReflex_runOnStimulusActivation();
            if (startedFoSimple) {
              flashStimulusButtonForOnePulse(button);
            }
          }
        });
      })(stim, btn, rowId);
      row.appendChild(btn);
    }
  }

  function buildButtons() {
    var row = ensureRow();
    if (!row || !global.StimulMotivarion) {
      return;
    }
    row.innerHTML = '';
    for (var i = 0; i < global.StimulMotivarion.length; i++) {
      var stim = global.StimulMotivarion[i];
      var btn = global.document.createElement('button');
      btn.type = 'button';
      btn.textContent = stim.name || ('S' + stim.Id);
      btn.title = stim.title || stim.name || '';
      btn.dataset.baseTitle = btn.title;
      btn.dataset.stimId = String(stim.Id);
      btn.dataset.vitalId = String(stim.vitalID);
      btn.style.padding = '2px 8px';
      btn.style.fontSize = '9pt';
      btn.style.borderRadius = '10px';
      btn.style.border = '1px solid #888';
      btn.style.cursor = 'pointer';
      btn.style.color = '#000';

      // Цвета по полю bg: 1 - розовый, 2 - белый, 3 - светло-зелёный
      var bgType = stim.bg || 2;
      var baseBg = '#f8f8f8';
      if (bgType === 1) {
        baseBg = '#ffe6f0'; // светло-розовый
      } else if (bgType === 3) {
        baseBg = '#e0f8e0'; // светло-зелёный
      }
      btn.style.backgroundColor = baseBg;
      btn.dataset.baseBg = baseBg;
      attachInfoIcon(btn, stim.Id, 'motivation');

      (function (s, button, bgTypeLocal) {
        // Наведение мыши: подсказка с готовностью для старта ОР
        var baseTitle = (s && (s.title || s.name)) ? (s.title || s.name) : ('S' + (s ? s.Id : ''));
        button.addEventListener('mouseenter', function () {
          if (typeof global.OrientationReflex_getOrReadinessForFinalImageId !== 'function' ||
              typeof global.StimulusGlobalId_toGlobal !== 'function' ||
              typeof global.StimulusGlobalId_getTypeFromRowId !== 'function' ||
              typeof global.FinalImages_findFinalImageId !== 'function') {
            button.title = baseTitle;
            return;
          }

          var type = global.StimulusGlobalId_getTypeFromRowId(ROW_ID);
          var globalStimId = global.StimulusGlobalId_toGlobal(type, s.Id);
          if (!globalStimId) {
            button.title = baseTitle;
            return;
          }

          var finalImageId = global.FinalImages_findFinalImageId([globalStimId]) || 0;
          var readiness = global.OrientationReflex_getOrReadinessForFinalImageId(finalImageId);
          var remaining = readiness && typeof readiness.remainingActivations === 'number'
            ? readiness.remainingActivations
            : '';
          if (typeof readiness.remainingActivations === 'number') {
            if (readiness.remainingActivations === 0) {
              button.title = baseTitle + '\nУчаствует в ориентировочном рефлексе';
            } else {
              button.title = baseTitle + '\nУровень готовности для ОР: ' + String(remaining) + ' активаций осталось';
            }
          } else {
            button.title = baseTitle + '\nУровень готовности для ОР: неизвестно (контексты ещё не определены)';
          }
        });
        button.addEventListener('mouseleave', function () {
          button.title = baseTitle;
        });

        button.addEventListener('dblclick', function () {
          clearAllStimuli();
        });
        button.addEventListener('click', function () {
          // Особый случай: Играть / Учить — завязаны на глобальных режимах,
          // а не на массиве ActiveMotivationStimuls
          if (s.vitalID === 11 || s.vitalID === 12) {
            var makeActive;
            if (s.vitalID === 11) {
              makeActive = !global.isGameMode;
              global.isGameMode = makeActive;
              if (makeActive) {
                global.isAuthoritarianEducation = false;
                // сбросить подсветку кнопки «Учить» (Id 20)
                var teachBtn = global.document.querySelector('#' + ROW_ID + ' button[data-stim-id="20"]');
                if (teachBtn) {
                  teachBtn.style.backgroundColor = teachBtn.dataset.baseBg || '#f8f8f8';
                  teachBtn.style.boxShadow = 'none';
                }
              }
            } else {
              makeActive = !global.isAuthoritarianEducation;
              global.isAuthoritarianEducation = makeActive;
              if (makeActive) {
                global.isGameMode = false;
                // сбросить подсветку кнопки «Играть» (Id 19)
                var playBtn = global.document.querySelector('#' + ROW_ID + ' button[data-stim-id="19"]');
                if (playBtn) {
                  playBtn.style.backgroundColor = playBtn.dataset.baseBg || '#f8f8f8';
                  playBtn.style.boxShadow = 'none';
                }
              }
            }

            tryExitSleepOnAllowedStimulusActivation(ROW_ID, s.Id, makeActive);
            if (sleepBlocksStimulus(ROW_ID, s.Id)) return;

            // визуальная подсветка для самой кнопки по bg
            if (makeActive) {
              if (bgTypeLocal === 1) {
                button.style.backgroundColor = '#ffccd9';
                button.style.boxShadow = '0 0 8px 2px rgba(255, 140, 180, 0.8)';
              } else if (bgTypeLocal === 3) {
                button.style.backgroundColor = '#c8f0c8';
                button.style.boxShadow = '0 0 8px 2px rgba(80, 200, 120, 0.8)';
              } else {
                button.style.backgroundColor = '#ffe4b5';
                button.style.boxShadow = '0 0 8px 2px rgba(200, 160, 80, 0.8)';
              }
            } else {
              button.style.backgroundColor = button.dataset.baseBg || '#f8f8f8';
              button.style.boxShadow = 'none';
            }

            // разовые эффекты мотивационного стимула — только при активации
            if (makeActive) {
              applyMotivationEffects(s.Id);
            }

            if (typeof global.update_vitals_view === 'function') {
              global.update_vitals_view();
            }
            if (typeof global.OrientationReflex_runOnStimulusActivation === 'function') {
              var startedFoMode = global.OrientationReflex_runOnStimulusActivation();
              if (startedFoMode) {
                flashStimulusButtonForOnePulse(button);
              }
            }
            syncInfoPlayLearningDetectors();
            return;
          }

          var willActivateMot = !isStimActive(s.Id);
          tryExitSleepOnAllowedStimulusActivation(ROW_ID, s.Id, willActivateMot);
          if (sleepBlocksStimulus(ROW_ID, s.Id)) return;

          // Обычные мотивирующие стимулы: сначала фиксируем базовую значимость,
          // затем переключаем активность в массиве
          if (typeof global.getDiffImportance === 'function') {
            global.getDiffImportance();
          }
          toggleStimActive(s.Id);
          var active = isStimActive(s.Id);
          syncInfoPlayLearningDetectors();

          // визуальная подсветка
          if (active) {
            if (bgTypeLocal === 1) {
              button.style.backgroundColor = '#ffccd9'; // более насыщённый розовый
              button.style.boxShadow = '0 0 8px 2px rgba(255, 140, 180, 0.8)';
            } else if (bgTypeLocal === 3) {
              button.style.backgroundColor = '#c8f0c8'; // более насыщённый зелёный
              button.style.boxShadow = '0 0 8px 2px rgba(80, 200, 120, 0.8)';
            } else {
              button.style.backgroundColor = '#ffe4b5';
              button.style.boxShadow = '0 0 8px 2px rgba(200, 160, 80, 0.8)';
            }
          } else {
            button.style.backgroundColor = button.dataset.baseBg || '#f8f8f8';
            button.style.boxShadow = 'none';
          }

          // разовые эффекты стимула по новой схеме: только при активации
          if (active) {
            applyMotivationEffects(s.Id);
            if (s.Id === 1 || s.Id === 2) {
              if (global.automatismRanForBranchIds && typeof global.automatismRanForBranchIds === 'object') {
                global.automatismRanForBranchIds = {};
              }
            }
          }
          if (typeof global.OrientationReflex_runOnStimulusActivation === 'function') {
            var startedFoMotivation = global.OrientationReflex_runOnStimulusActivation();
            if (startedFoMotivation) {
              flashStimulusButtonForOnePulse(button);
            }
          }
        });
      })(stim, btn, bgType);
      row.appendChild(btn);
    }
    updateMotivationButtonsView();
  }

  function init() {
    buildButtons();
    if (!Array.isArray(global.ActivePositivStimuls)) global.ActivePositivStimuls = [];
    if (!Array.isArray(global.ActiveNegativeStimuls)) global.ActiveNegativeStimuls = [];
    if (!Array.isArray(global.ActiveNeutralStimuls)) global.ActiveNeutralStimuls = [];
    // Позитивные: зелёный фон, воздействие через StimulPositiv_EffectsToBContexts
    buildRowForSimpleStimuls('stimulsRowPositiv', 'Позитивные стимулы:', global.StimulPositiv, 'ActivePositivStimuls', -1, ROW_ID);
    // Негативные: розовый фон, воздействие через StimulNegative_EffectsToBContexts
    buildRowForSimpleStimuls('stimulsRowNegative', 'Негативные стимулы:', global.StimulNegative, 'ActiveNegativeStimuls', 1, 'stimulsRowPositiv');
    // Дополнительная красная кнопка «Тест» после негативных стимулов — жёсткий запуск прерывания осмысления.
    var negRow = global.document && global.document.getElementById('stimulsRowNegative');
    if (negRow && typeof global.runTestNegativeInterrupt === 'function') {
      var btn = global.document.createElement('button');
      btn.textContent = 'Тест';
      btn.title = 'Тестовый стимул с максимально негативной значимостью для вызова прерывания цикла осмысления';
      btn.style.backgroundColor = '#ff4444';
      btn.style.color = '#ffffff';
      btn.style.border = '1px solid #aa0000';
      btn.style.marginLeft = '8px';
      btn.style.cursor = 'pointer';
      btn.addEventListener('click', function () {
        if (typeof global.SleepMode_isActive === 'function' && global.SleepMode_isActive()) {
          return;
        }
        global.runTestNegativeInterrupt();
      });
      negRow.appendChild(btn);
    }
    buildRowForSimpleStimuls('stimulsRowNeutral', 'Нейтральные стимулы:', global.StimulNeutral, 'ActiveNeutralStimuls', 0, 'stimulsRowNegative');
    if (typeof global.SleepMode_refreshStimulusButtonVisuals === 'function') {
      global.SleepMode_refreshStimulusButtonVisuals();
    }
  }

  if (global.document.readyState === 'loading') {
    global.document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }

  /**
   * Включить стимул по записи window.BasicMirrorActions (Id): тот же смысл, что нажатие соответствующей кнопки оператора.
   * Если стимул уже активен — состояние и разовые эффекты не дублируются; вызывается OrientationReflex_runOnStimulusActivation.
   *
   * @param {number} basicMirrorActionId — поле Id из BasicMirrorActions
   * @returns {boolean}
   */
  function activateStimulusForBasicMirrorActionId(basicMirrorActionId) {
    var mid = parseInt(basicMirrorActionId, 10);
    if (!mid) return false;
    var list = global.BasicMirrorActions;
    if (!Array.isArray(list)) return false;
    var rec = null;
    for (var mi = 0; mi < list.length; mi++) {
      if (list[mi] && list[mi].Id === mid) {
        rec = list[mi];
        break;
      }
    }
    if (!rec || rec.mirrorParentId == null) return false;
    var parts = String(rec.mirrorParentId).split('_');
    var typeNum = parseInt(parts[0], 10);
    var stimId = parseInt(parts[1], 10);
    if (!typeNum || !stimId) return false;

    var mirrorRowId = ROW_ID;
    if (typeNum === 2) mirrorRowId = 'stimulsRowPositiv';
    else if (typeNum === 3) mirrorRowId = 'stimulsRowNegative';
    else if (typeNum === 4) mirrorRowId = 'stimulsRowNeutral';

    var willActivateMirror = false;
    if (typeNum === 1) {
      var stimObjPre = null;
      if (global.StimulMotivarion) {
        for (var mp = 0; mp < global.StimulMotivarion.length; mp++) {
          if (global.StimulMotivarion[mp] && global.StimulMotivarion[mp].Id === stimId) {
            stimObjPre = global.StimulMotivarion[mp];
            break;
          }
        }
      }
      if (stimObjPre && (stimObjPre.vitalID === 11 || stimObjPre.vitalID === 12)) {
        var wantG = stimObjPre.vitalID === 11;
        var alreadyG = wantG ? !!global.isGameMode : !!global.isAuthoritarianEducation;
        willActivateMirror = !alreadyG;
      } else {
        willActivateMirror = !isStimActive(stimId);
      }
    } else {
      var ak = typeNum === 2 ? 'ActivePositivStimuls' : (typeNum === 3 ? 'ActiveNegativeStimuls' : 'ActiveNeutralStimuls');
      willActivateMirror = !isSimpleStimActive(ak, stimId);
    }
    tryExitSleepOnAllowedStimulusActivation(mirrorRowId, stimId, willActivateMirror);
    if (sleepBlocksStimulus(mirrorRowId, stimId)) return false;

    if (typeof global.getDiffImportance === 'function') {
      global.getDiffImportance();
    }

    if (typeNum === 1) {
      var stimObj = null;
      if (global.StimulMotivarion) {
        for (var mj = 0; mj < global.StimulMotivarion.length; mj++) {
          if (global.StimulMotivarion[mj] && global.StimulMotivarion[mj].Id === stimId) {
            stimObj = global.StimulMotivarion[mj];
            break;
          }
        }
      }
      if (stimObj && (stimObj.vitalID === 11 || stimObj.vitalID === 12)) {
        var wantGame = stimObj.vitalID === 11;
        var already = wantGame ? !!global.isGameMode : !!global.isAuthoritarianEducation;
        if (!already) {
          if (wantGame) {
            global.isGameMode = true;
            global.isAuthoritarianEducation = false;
          } else {
            global.isAuthoritarianEducation = true;
            global.isGameMode = false;
          }
          applyMotivationEffects(stimId);
        }
        if (typeof global.update_vitals_view === 'function') {
          global.update_vitals_view();
        }
        updateMotivationButtonsView();
        if (typeof global.OrientationReflex_runOnStimulusActivation === 'function') {
          global.OrientationReflex_runOnStimulusActivation();
        }
        syncInfoPlayLearningDetectors();
        return true;
      }
      if (!isStimActive(stimId)) {
        toggleStimActive(stimId);
        applyMotivationEffects(stimId);
      }
      syncInfoPlayLearningDetectors();
      if (typeof global.update_vitals_view === 'function') {
        global.update_vitals_view();
      }
      updateMotivationButtonsView();
      if (typeof global.OrientationReflex_runOnStimulusActivation === 'function') {
        global.OrientationReflex_runOnStimulusActivation();
      }
      return true;
    }

    var activeKey = null;
    var rowId = null;
    if (typeNum === 2) {
      rowId = 'stimulsRowPositiv';
      activeKey = 'ActivePositivStimuls';
    } else if (typeNum === 3) {
      rowId = 'stimulsRowNegative';
      activeKey = 'ActiveNegativeStimuls';
    } else if (typeNum === 4) {
      rowId = 'stimulsRowNeutral';
      activeKey = 'ActiveNeutralStimuls';
    } else {
      return false;
    }

    if (!isSimpleStimActive(activeKey, stimId)) {
      toggleSimpleStim(activeKey, stimId);
      if (rowId === 'stimulsRowPositiv' || rowId === 'stimulsRowNegative') {
        applyPerceptionContextEffects(rowId, stimId);
      }
    }
    if (typeof global.update_vitals_view === 'function') {
      global.update_vitals_view();
    }
    if (typeof global.OrientationReflex_runOnStimulusActivation === 'function') {
      global.OrientationReflex_runOnStimulusActivation();
    }
    return true;
  }

  // Экспортируем обновление «готовности к ОР» для вызова из puls.js.
  global.updateStimulusButtonsReadinessView = updateStimulusButtonsReadinessView;
  global.scheduleStimulusReadinessRefreshIfNeeded = scheduleStimulusReadinessRefreshIfNeeded;
  global.updateStimulusButtonsReadinessViewForFinalImageId = updateStimulusButtonsReadinessViewForFinalImageId;
  global.activateStimulusForBasicMirrorActionId = activateStimulusForBasicMirrorActionId;
})(window);

