<!doctype html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Life Balance Expert</title>
  <link rel="icon" type="image/png" href="{{ url_for('static', filename='brand-icon.png') }}">
  <link rel="shortcut icon" href="{{ url_for('static', filename='brand-icon.png') }}">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=Space+Grotesk:wght@500;700&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
  <div class="bg-shape bg-one"></div>
  <div class="bg-shape bg-two"></div>

  <header class="site-header app-shell-header">
    <div class="app-shell-row">
      <a class="brand" href="{{ url_for('landing') }}" aria-label="Навигатор качества жизни">
        <img src="{{ url_for('static', filename='brand-icon.png') }}" alt="Навигатор качества жизни" width="42" height="42">
        <span class="brand-text">
          <span>Навигатор качества жизни</span>
          <span>Life Balance Expert</span>
        </span>
      </a>
      <span class="header-badge">Бета-версия {{ version }}</span>
    </div>
  </header>

  <main class="app app-shell-main">
    {% for note in notices %}
      <section class="notice notice-{{ note.level }}">{{ note.text }}</section>
    {% endfor %}

    {% if mode == "welcome" %}
      <section class="panel">
        <p class="preline">{{ welcome_text }}</p>
        <form method="post" class="stack">
            <label class="consent-box" for="privacy-consent">
              <input id="privacy-consent" type="checkbox" name="privacy_consent" value="yes">
              <span>Согласен (согласна) с политикой обработки персональных данных</span>
            </label>
          {% if field_error_message and mode == "welcome" %}
            <p class="field-error">{{ field_error_message }}</p>
          {% endif %}
          <div class="row">
            <button id="start-yes-button" class="btn btn-primary" type="submit" name="action" value="start_yes" disabled>Да</button>
            <button class="btn btn-ghost" type="submit" name="action" value="start_no">Нет</button>
          </div>
        </form>
      </section>
    {% elif mode == "declined" %}
      <section class="panel">
        <p>Анкета остановлена.</p>
        <form method="post"><input type="hidden" name="action" value="start_over"><button class="btn btn-primary">Начать заново</button></form>
      </section>
    {% elif mode == "intro" and intro_question %}
      <section class="panel">
        <p class="step">Этап 1/3 • Общие вопросы {{ intro_step }}/{{ intro_total }}</p>
        <p class="preline">{{ intro_prompt }}</p>

        {% if intro_question.id == "pets" %}
          <form method="post" class="stack">
            <input type="hidden" name="action" value="intro_choice">
            <input type="hidden" name="qid" value="pets">
            <input type="hidden" name="value" value="0">
            <button class="btn btn-option" type="submit">Нет</button>
          </form>
          <form method="post" class="stack pet-form" data-pet-form>
            <input type="hidden" name="action" value="submit_pets">
            <template data-pet-option-template>
              {% for code, label in pet_options %}
                <option value="{{ code }}">{{ label }}</option>
              {% endfor %}
            </template>
            <div class="pet-rows" data-pet-rows>
              <div class="pet-row" data-pet-row>
                <select class="text-input pet-select" name="pet_type_1">
                  {% for code, label in pet_options %}
                    <option value="{{ code }}">{{ label }}</option>
                  {% endfor %}
                </select>
                <input class="text-input pet-count" type="number" name="pet_count_1" min="1" max="99" step="1" value="1" inputmode="numeric">
              </div>
            </div>
            <div class="row">
              <button class="btn btn-ghost" type="button" data-add-pet-row>+</button>
              <button class="btn btn-primary" type="submit">Сохранить</button>
            </div>
          </form>
        {% elif intro_options %}
          <div class="stack">
            {% for value, label in intro_options %}
              <form method="post" class="full">
                <input type="hidden" name="action" value="intro_choice">
                <input type="hidden" name="qid" value="{{ intro_question.id }}">
                <input type="hidden" name="value" value="{{ value }}">
                <button class="btn btn-option">{{ label }}</button>
              </form>
            {% endfor %}
          </div>
        {% else %}
          <form method="post" class="form-line">
            <input type="hidden" name="action" value="submit_answer">
            <input class="text-input{% if field_error_message and mode == 'intro' %} input-error{% endif %}" type="text" name="answer" value="{{ draft_answer }}" autocomplete="off"{% if intro_input_mode %} inputmode="{{ intro_input_mode }}"{% endif %}{% if intro_input_pattern %} pattern="{{ intro_input_pattern }}"{% endif %} required>
            <button class="btn btn-primary">Отправить</button>
          </form>
          {% if intro_hint %}
            <p class="field-hint"><em>{{ intro_hint }}</em></p>
          {% endif %}
          {% if field_error_message and mode == "intro" %}
            <p class="field-error">{{ field_error_message }}</p>
          {% endif %}
        {% endif %}

        <div class="stack nav">
          {% if intro_include_prev %}
            <form method="post"><input type="hidden" name="action" value="nav_prev"><button class="btn btn-nav">Изменить предыдущий ответ</button></form>
          {% endif %}
          <form method="post"><input type="hidden" name="action" value="nav_skip"><button class="btn btn-nav">Пропустить вопрос</button></form>
        </div>
      </section>
    {% elif mode == "intro_review" %}
      <section class="panel">
        <p class="summary-title">{{ intro_summary_title }}</p>
        <p class="preline">{{ intro_summary_body }}</p>
        <div class="stack">
          <form method="post"><input type="hidden" name="action" value="block_confirm_intro"><button class="btn btn-primary">Подтвердить и продолжить</button></form>
          <form method="post"><input type="hidden" name="action" value="block_restart_intro"><button class="btn btn-ghost">Пройти блок вопросов заново</button></form>
        </div>
      </section>
    {% elif mode == "weights" %}
      <section class="panel">
        <p class="step">Этап 2/3 • Весовые коэффициенты</p>
        {% if weight_intro_text %}
          <div class="weight-intro-banner">
            <p class="preline">{{ weight_intro_text }}</p>
          </div>
        {% endif %}
        <form method="post" class="stack" data-weights-review-form>
          <input type="hidden" name="action" value="submit_weights_table">
          <div class="weights-matrix" data-weights-table>
            {% for block in weights_blocks %}
              <section class="weights-block">
                <div class="weights-block-head">
                  <h3>Блок {{ block.block_id }}. {{ block.title }}</h3>
                  <strong><span data-block-weight="{{ block.block_id }}">{{ block.normalized_value }}</span>%</strong>
                </div>
                <div class="weights-rows">
                  {% for row in block.indicators %}
                    <div class="weight-row" data-weight-row data-block-id="{{ row.block_id }}">
                      <div class="weight-label">{{ row.indicator_id }}. {{ row.label }}</div>
                      <input
                        class="weight-slider"
                        type="range"
                        min="0"
                        max="10"
                        step="0.1"
                        value="{{ row.raw_dot_value }}"
                        data-weight-slider
                      >
                      <input
                        class="table-input weight-number{% if field_error_message and mode == 'weights' %} input-error{% endif %}"
                        type="text"
                        name="weight_{{ row.indicator_id }}"
                        value="{{ row.raw_value }}"
                        inputmode="decimal"
                        pattern="[0-9.,]*"
                        data-raw-weight-input
                      >
                      <div class="weight-normalized"><span data-normalized-weight>{{ row.normalized_value }}</span>%</div>
                    </div>
                  {% endfor %}
                </div>
              </section>
            {% endfor %}
          </div>
          <button class="btn btn-primary">Подтвердить веса</button>
        </form>
        {% if field_error_message and mode == "weights" %}
          <p class="field-error">{{ field_error_message }}</p>
        {% endif %}
      </section>
    {% elif mode == "values" %}
      <section class="panel">
        <p class="preline">{{ value_prompt }}</p>
        {% if value_control.type == "select" %}
          <form method="post" class="value-select-form">
            <input type="hidden" name="action" value="submit_answer">
            <select class="text-input value-select{% if field_error_message and mode == 'values' %} input-error{% endif %}" name="answer" required>
              {% for option in value_control.options %}
                <option value="{{ option.value }}"{% if option.selected %} selected{% endif %}>{{ option.label }}</option>
              {% endfor %}
            </select>
            <button class="btn btn-primary btn-nowrap btn-save-value">Сохранить значение</button>
          </form>
        {% elif value_control.type == "slider" %}
          <form method="post" class="value-control-form" data-value-control>
            <input type="hidden" name="action" value="submit_answer">
            <div class="value-control-row">
              <input
                class="value-slider"
                type="range"
                min="{{ value_control.min }}"
                max="{{ value_control.max }}"
                step="{{ value_control.step }}"
                value="{{ value_control.slider_value }}"
                data-value-slider
              >
              <input
                class="table-input value-number{% if field_error_message and mode == 'values' %} input-error{% endif %}"
                type="text"
                name="answer"
                value="{{ value_control.value }}"
                autocomplete="off"
                {% if value_control.mode %}inputmode="{{ value_control.mode }}"{% endif %}
                {% if value_control.pattern %}pattern="{{ value_control.pattern }}"{% endif %}
                data-value-input
                data-value-integer="{{ 1 if value_control.integer else 0 }}"
                required
              >
              <button class="btn btn-primary btn-nowrap btn-save-value">Сохранить значение</button>
            </div>
          </form>
        {% else %}
          <form method="post" class="form-line">
            <input type="hidden" name="action" value="submit_answer">
            <input class="text-input{% if field_error_message and mode == 'values' %} input-error{% endif %}" type="text" name="answer" value="{{ draft_answer }}" autocomplete="off"{% if value_input_mode %} inputmode="{{ value_input_mode }}"{% endif %}{% if value_input_pattern %} pattern="{{ value_input_pattern }}"{% endif %} required>
            <button class="btn btn-primary btn-nowrap btn-save-value">Сохранить значение</button>
          </form>
        {% endif %}
        {% if value_hint %}
          <p class="field-hint"><em>{{ value_hint }}</em></p>
        {% endif %}
        {% if field_error_message and mode == "values" %}
          <p class="field-error">{{ field_error_message }}</p>
        {% endif %}
        <div class="stack nav">
          <form method="post"><input type="hidden" name="action" value="nav_prev"><button class="btn btn-nav">Изменить предыдущий ответ</button></form>
          <form method="post"><input type="hidden" name="action" value="nav_skip"><button class="btn btn-nav">Пропустить вопрос</button></form>
        </div>
      </section>
    {% elif mode == "value_block_review" %}
      <section class="panel">
        <p class="preline">{{ value_block_summary }}</p>
        <div class="stack">
          <form method="post"><input type="hidden" name="action" value="block_confirm_value"><button class="btn btn-primary">Подтвердить и продолжить</button></form>
          <form method="post">
            <input type="hidden" name="action" value="block_restart_value">
            <input type="hidden" name="block_id" value="{{ value_block_id }}">
            <button class="btn btn-ghost">Пройти блок вопросов заново</button>
          </form>
        </div>
      </section>
    {% elif mode == "done" and result %}
      <section class="panel">
        <p class="summary-title">{{ result_view.title }}</p>
        <div class="result-metrics">
          <p class="result-line result-line-strong"><strong>Индекс качества жизни: <span data-result-metric="lqi">{{ result_view.lqi }}</span></strong></p>
          <p class="result-line">Сумма баллов: <span data-result-metric="sigma">{{ result_view.sigma }}</span></p>
          <p class="result-line">Итоговый множитель: <span data-result-metric="multi">{{ result_view.multi }}</span></p>
          <p class="result-line">Годовой доход: <span data-result-metric="annual_income">{{ result_view.annual_income }}</span></p>
          <p class="result-line">Расходы: <span data-result-metric="total_money">{{ result_view.total_money }}</span></p>
          <p class="result-line{% if result_view.rest_money_negative %} result-line-negative{% endif %}" data-result-rest-money-line>Остаток средств: <span data-result-metric="rest_money">{{ result_view.rest_money }}</span></p>
          <p class="result-note result-note-negative{% if not result_view.rest_money_negative %} hidden{% endif %}" data-result-rest-money-note>{{ result_view.rest_money_note }}</p>
          <p class="result-line">Затраты времени: <span data-result-metric="total_time">{{ result_view.total_time }}</span></p>
          <p class="result-line{% if result_view.rest_time_negative %} result-line-negative{% endif %}" data-result-rest-time-line>Остаток времени: <span data-result-metric="rest_time">{{ result_view.rest_time }}</span></p>
          <p class="result-note result-note-negative{% if not result_view.rest_time_negative %} hidden{% endif %}" data-result-rest-time-note>{{ result_view.rest_time_note }}</p>
        </div>
        <div class="media-grid">
          {% for media_name in media_names %}
            <article class="media-card">
              <img src="{{ url_for('media', flow_id=flow_id, filename=media_name, animated=1) if is_android_app and media_name.endswith('.gif') else url_for('media', flow_id=flow_id, filename=media_name) }}" alt="{{ media_name }}">
              <a class="btn btn-ghost media-download" href="{{ url_for('media', flow_id=flow_id, filename=media_name, download=1) }}">Скачать {{ media_name }}</a>
            </article>
          {% endfor %}
        </div>
        {% if result_rows %}
          <div class="stack">
            <p class="field-hint{% if not result_media_stale %} hidden{% endif %}" data-result-media-note><em>После изменения значений нажмите «Перестроить диаграммы», чтобы обновить графики.</em></p>
          </div>
          <div class="review-table-shell">
            <table class="review-table" data-result-table data-preview-url="{{ result_preview_url }}">
              <thead>
                <tr>
                  <th>Индикатор</th>
                  <th>Вес</th>
                  <th>Показатель (ед. изм.)</th>
                  <th>Значение показателя</th>
                  <th>Значение индикатора в баллах</th>
                </tr>
              </thead>
              <tbody>
                {% for row in result_rows %}
                  <tr>
                    <td>{{ row.indicator_id }}. {{ row.label }}</td>
                    <td data-result-weight="{{ row.indicator_id }}">{{ row.normalized_weight }}%</td>
                    <td>{{ row.measure }}</td>
                    <td>
                      <input
                        class="table-input"
                        type="text"
                        name="result_value_{{ row.indicator_id }}"
                        value="{{ row.value }}"
                        {% if row.input_mode %}inputmode="{{ row.input_mode }}"{% endif %}
                        {% if row.input_pattern %}pattern="{{ row.input_pattern }}"{% endif %}
                        data-result-value-input
                        data-indicator-id="{{ row.indicator_id }}"
                      >
                    </td>
                    <td><span data-result-score="{{ row.indicator_id }}">{{ row.score }}</span></td>
                  </tr>
                {% endfor %}
              </tbody>
            </table>
          </div>
          <p class="field-error hidden" data-result-preview-error></p>
          <details class="result-resource-details">
            <summary class="result-resource-summary">Подробнее о затратах времени и финансовых ресурсов</summary>
            <div class="result-resource-stack">
              <div>
                <p class="result-resource-title">Расходы по блокам</p>
                <div class="review-table-shell">
                  <table class="review-table review-table-compact">
                    <thead>
                      <tr>
                        <th>Блок</th>
                        <th>Расходы</th>
                      </tr>
                    </thead>
                    <tbody>
                      {% for row in result_money_rows %}
                        <tr>
                          <td>{{ row.label }}</td>
                          <td data-result-money-resource="{{ row.key }}">{{ row.value }}</td>
                        </tr>
                      {% endfor %}
                    </tbody>
                    <tfoot>
                      <tr>
                        <th>Общая сумма расходов по всем блокам</th>
                        <th data-result-money-total>{{ result_money_total }}</th>
                      </tr>
                    </tfoot>
                  </table>
                </div>
              </div>
              <div>
                <p class="result-resource-title">Затраты времени по блокам</p>
                <div class="review-table-shell">
                  <table class="review-table review-table-compact">
                    <thead>
                      <tr>
                        <th>Блок</th>
                        <th>Затраты времени</th>
                      </tr>
                    </thead>
                    <tbody>
                      {% for row in result_time_rows %}
                        <tr>
                          <td>{{ row.label }}</td>
                          <td data-result-time-resource="{{ row.key }}">{{ row.value }}</td>
                        </tr>
                      {% endfor %}
                    </tbody>
                    <tfoot>
                      <tr>
                        <th>Общая сумма затрат времени по всем блокам</th>
                        <th data-result-time-total>{{ result_time_total }}</th>
                      </tr>
                    </tfoot>
                  </table>
                </div>
              </div>
            </div>
          </details>
        {% endif %}
        <div class="stack">
          <form method="post"><input type="hidden" name="action" value="rebuild_result_media"><button class="btn btn-ghost">Перестроить диаграммы</button></form>
          {% if optimization_in_progress %}
          <form method="post"><button class="btn btn-primary" disabled>Запустить модель оптимизации</button></form>
          {% else %}
          <form method="post"><input type="hidden" name="action" value="optimize_stub"><button class="btn btn-primary">Запустить модель оптимизации</button></form>
          {% endif %}
          <form method="post"><input type="hidden" name="action" value="start_over"><button class="btn btn-ghost">Новый расчет</button></form>
        </div>
        {% if optimization_in_progress %}
          <div
            class="optimization-progress-card"
            data-optimization-progress
            data-progress-url="{{ url_for('optimization_progress') }}"
            data-poll-seconds="{{ optimization_poll_seconds }}"
            data-optimization-section
          >
            <p class="summary-title summary-title-large">Модель оптимизации работает</p>
            <p class="optimization-progress-stage" data-progress-stage>{{ optimization_progress.stage_label }}</p>
            <div class="optimization-progress-bar" aria-hidden="true">
              <div class="optimization-progress-fill" style="width: {{ optimization_progress.percent }}%;" data-progress-fill></div>
            </div>
            <div class="optimization-progress-meta">
              <span>Выполнено: <strong data-progress-percent>{{ optimization_progress.percent_text }}</strong></span>
              <span>Прошло: <strong data-progress-elapsed>{{ optimization_progress.elapsed_text }}</strong></span>
            </div>
          </div>
        {% endif %}
        {% if optimization_summary and not optimization_in_progress %}
          <div data-optimization-section>
          <div class="stack">
            <p class="summary-title summary-title-large">{{ optimization_summary_title }}</p>
            <p class="preline">{{ optimization_summary_body }}</p>
          </div>
          {% if optimization_rows %}
            <div class="review-table-shell">
              <table class="review-table">
                <thead>
                  <tr>
                    <th>Индикатор</th>
                    <th>Вес (%)</th>
                    <th>Балл - сейчас</th>
                    <th>Балл - модель</th>
                  </tr>
                </thead>
                <tbody>
                  {% for row in optimization_rows %}
                    <tr>
                      <td>{{ row.indicator_id }}. {{ row.label }}</td>
                      <td>{{ row.weight }}%</td>
                      <td>{{ row.current_score }}</td>
                      <td>{{ row.target_score }} <span class="{{ row.delta_class }}">({{ row.delta_score }})</span></td>
                    </tr>
                  {% endfor %}
                </tbody>
              </table>
            </div>
          {% endif %}
          <div class="media-grid">
            {% for media_name in optimization_media_names %}
              <article class="media-card">
                <img src="{{ url_for('media', flow_id=flow_id, filename=media_name, animated=1) if is_android_app and media_name.endswith('.gif') else url_for('media', flow_id=flow_id, filename=media_name) }}" alt="{{ media_name }}">
                <a class="btn btn-ghost media-download" href="{{ url_for('media', flow_id=flow_id, filename=media_name, download=1) }}">Скачать {{ media_name }}</a>
              </article>
            {% endfor %}
          </div>
          </div>
        {% endif %}
      </section>
    {% else %}
      <section class="panel">
        <p>Состояние анкеты не определено.</p>
        <form method="post"><input type="hidden" name="action" value="start_over"><button class="btn btn-primary">Начать заново</button></form>
      </section>
    {% endif %}
  </main>
  <script>
    const privacyConsent = document.getElementById('privacy-consent');
    const startYesButton = document.getElementById('start-yes-button');
    if (privacyConsent && startYesButton) {
      const syncStartButton = () => {
        startYesButton.disabled = !privacyConsent.checked;
      };
      privacyConsent.addEventListener('change', syncStartButton);
      syncStartButton();
    }

    const progressCard = document.querySelector('[data-optimization-progress]');
    if (progressCard) {
      const progressUrl = progressCard.dataset.progressUrl;
      const pollSeconds = Number(progressCard.dataset.pollSeconds || '5');
      const stageNode = progressCard.querySelector('[data-progress-stage]');
      const percentNode = progressCard.querySelector('[data-progress-percent]');
      const elapsedNode = progressCard.querySelector('[data-progress-elapsed]');
      const fillNode = progressCard.querySelector('[data-progress-fill]');
      let elapsedAnchorMs = null;

      const formatDuration = (secondsValue) => {
        const seconds = Math.max(0, Math.round(Number(secondsValue || 0)));
        const mins = Math.floor(seconds / 60);
        const secs = seconds % 60;
        return `${mins} мин ${String(secs).padStart(2, '0')} сек`;
      };

      const refreshElapsed = () => {
        if (!elapsedNode || elapsedAnchorMs === null) {
          return;
        }
        const elapsedNow = Math.max(0, (Date.now() - elapsedAnchorMs) / 1000);
        elapsedNode.textContent = formatDuration(elapsedNow);
      };

      const syncProgress = (payload) => {
        if (stageNode && typeof payload.stage_label === 'string') {
          stageNode.textContent = payload.stage_label;
        }
        if (percentNode && typeof payload.percent_text === 'string') {
          percentNode.textContent = payload.percent_text;
        }
        if (typeof payload.elapsed_seconds === 'number' && elapsedAnchorMs === null) {
          elapsedAnchorMs = Date.now() - payload.elapsed_seconds * 1000;
          refreshElapsed();
        }
        if (fillNode && typeof payload.percent === 'number') {
          fillNode.style.width = `${Math.max(0, Math.min(100, payload.percent))}%`;
        }
      };

      const pollProgress = async () => {
        try {
          const response = await fetch(`${progressUrl}?_=${Date.now()}`, { cache: 'no-store' });
          if (!response.ok) {
            return;
          }
          const payload = await response.json();
          syncProgress(payload);
          if (payload.status && payload.status !== 'running') {
            window.location.reload();
          }
        } catch (error) {
          console.warn('Optimization progress polling failed', error);
        }
      };

      window.setInterval(refreshElapsed, 1000);
      window.setInterval(pollProgress, Math.max(1000, pollSeconds * 1000));
      pollProgress();
    }

    const weightsReviewTable = document.querySelector('[data-weights-table]');
    if (weightsReviewTable) {
      const inputs = Array.from(weightsReviewTable.querySelectorAll('[data-raw-weight-input]'));
      const sliders = Array.from(weightsReviewTable.querySelectorAll('[data-weight-slider]'));
      const normalizedNodes = Array.from(weightsReviewTable.querySelectorAll('[data-normalized-weight]'));
      const parseWeight = (value) => {
        const normalized = String(value || '').trim().replace(',', '.');
        const parsed = Number.parseFloat(normalized);
        return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
      };
      const clampWeight = (value) => Math.max(0, Math.min(10, Math.round(Number(value || 0) * 10) / 10));
      const formatRawWeight = (value) => clampWeight(value).toFixed(1).replace('.', ',');
      const formatWeight = (value) => value.toFixed(2).replace('.', ',');
      const refreshNormalizedWeights = () => {
        const rawValues = inputs.map((input) => parseWeight(input.value));
        const total = rawValues.reduce((sum, value) => sum + value, 0);
        normalizedNodes.forEach((node, index) => {
          const percent = total > 0 ? (rawValues[index] / total) * 100 : 0;
          node.textContent = formatWeight(percent);
        });
        const blockTotals = new Map();
        inputs.forEach((input, index) => {
          const row = input.closest('[data-weight-row]');
          if (!row) {
            return;
          }
          const blockId = row.dataset.blockId;
          blockTotals.set(blockId, (blockTotals.get(blockId) || 0) + rawValues[index]);
        });
        document.querySelectorAll('[data-block-weight]').forEach((node) => {
          const rawTotal = blockTotals.get(node.dataset.blockWeight) || 0;
          const percent = total > 0 ? (rawTotal / total) * 100 : 0;
          node.textContent = formatWeight(percent);
        });
      };
      inputs.forEach((input, index) => {
        input.addEventListener('input', () => {
          const value = clampWeight(parseWeight(input.value));
          if (sliders[index]) {
            sliders[index].value = String(value);
          }
          refreshNormalizedWeights();
        });
        input.addEventListener('change', () => {
          const value = clampWeight(parseWeight(input.value));
          input.value = formatRawWeight(value);
          if (sliders[index]) {
            sliders[index].value = String(value);
          }
          refreshNormalizedWeights();
        });
      });
      sliders.forEach((slider, index) => {
        slider.addEventListener('input', () => {
          const value = clampWeight(slider.value);
          if (inputs[index]) {
            inputs[index].value = formatRawWeight(value);
          }
          refreshNormalizedWeights();
        });
      });
      refreshNormalizedWeights();
    }

    const valueControl = document.querySelector('[data-value-control]');
    if (valueControl) {
      const slider = valueControl.querySelector('[data-value-slider]');
      const input = valueControl.querySelector('[data-value-input]');
      if (slider && input) {
        const isInteger = input.dataset.valueInteger === '1';
        const minValue = Number.parseFloat(slider.min || '0');
        const maxValue = Number.parseFloat(slider.max || '10');
        const stepValue = Number.parseFloat(slider.step || '1');
        const parseValue = (value) => {
          const normalized = String(value || '').trim().replace(',', '.');
          const parsed = Number.parseFloat(normalized);
          return Number.isFinite(parsed) ? parsed : null;
        };
        const clampSliderValue = (value) => {
          let numeric = Number.isFinite(value) ? value : minValue;
          numeric = Math.max(minValue, Math.min(maxValue, numeric));
          if (stepValue > 0) {
            numeric = Math.round(numeric / stepValue) * stepValue;
          }
          if (isInteger) {
            numeric = Math.round(numeric);
          }
          return Math.max(minValue, Math.min(maxValue, numeric));
        };
        const formatValue = (value) => {
          const numeric = isInteger ? Math.round(value) : Math.round(value * 10) / 10;
          return String(numeric).replace('.', ',');
        };
        input.addEventListener('input', () => {
          input.classList.remove('input-error');
          const parsed = parseValue(input.value);
          if (parsed !== null) {
            slider.value = String(clampSliderValue(parsed));
          }
        });
        input.addEventListener('change', () => {
          const parsed = parseValue(input.value);
          if (parsed !== null && isInteger) {
            input.value = formatValue(parsed);
          }
        });
        slider.addEventListener('input', () => {
          input.value = formatValue(clampSliderValue(Number.parseFloat(slider.value)));
          input.classList.remove('input-error');
        });
      }
    }

    const petForm = document.querySelector('[data-pet-form]');
    if (petForm) {
      const rowsNode = petForm.querySelector('[data-pet-rows]');
      const addButton = petForm.querySelector('[data-add-pet-row]');
      const optionTemplate = petForm.querySelector('[data-pet-option-template]');
      const optionHtml = optionTemplate ? optionTemplate.innerHTML : '';
      let petRowIndex = 1;
      if (rowsNode && addButton) {
        addButton.addEventListener('click', () => {
          petRowIndex += 1;
          const row = document.createElement('div');
          row.className = 'pet-row';
          row.dataset.petRow = '';
          row.innerHTML = `
            <select class="text-input pet-select" name="pet_type_${petRowIndex}">${optionHtml}</select>
            <input class="text-input pet-count" type="number" name="pet_count_${petRowIndex}" min="1" max="99" step="1" value="1" inputmode="numeric">
          `;
          rowsNode.appendChild(row);
        });
      }
    }

    const resultTable = document.querySelector('[data-result-table]');
    if (resultTable) {
      const previewUrl = resultTable.dataset.previewUrl;
      const inputs = Array.from(resultTable.querySelectorAll('[data-result-value-input]'));
      const errorNode = document.querySelector('[data-result-preview-error]');
      const mediaNote = document.querySelector('[data-result-media-note]');
      let previewTimer = null;
      let requestCounter = 0;

      const clearResultErrors = () => {
        inputs.forEach((input) => input.classList.remove('input-error'));
        if (errorNode) {
          errorNode.textContent = '';
          errorNode.classList.add('hidden');
        }
      };

      const hideOptimizationSections = () => {
        document.querySelectorAll('[data-optimization-section]').forEach((node) => {
          node.classList.add('hidden');
        });
      };

      const setPreviewError = (fieldId, message) => {
        clearResultErrors();
        if (fieldId) {
          const field = resultTable.querySelector(`[data-indicator-id="${fieldId}"]`);
          if (field) {
            field.classList.add('input-error');
          }
        }
        if (errorNode) {
          errorNode.textContent = message || 'Введите корректное значение';
          errorNode.classList.remove('hidden');
        }
      };

      const applyPreviewPayload = (payload) => {
        const metrics = payload.result_view || {};
        Object.entries(metrics).forEach(([key, value]) => {
          const node = document.querySelector(`[data-result-metric="${key}"]`);
          if (node && typeof value === 'string') {
            node.textContent = value;
          }
        });

        const restMoneyLine = document.querySelector('[data-result-rest-money-line]');
        const restMoneyNote = document.querySelector('[data-result-rest-money-note]');
        if (restMoneyLine) {
          restMoneyLine.classList.toggle('result-line-negative', Boolean(metrics.rest_money_negative));
        }
        if (restMoneyNote) {
          restMoneyNote.classList.toggle('hidden', !metrics.rest_money_negative);
        }

        const restTimeLine = document.querySelector('[data-result-rest-time-line]');
        const restTimeNote = document.querySelector('[data-result-rest-time-note]');
        if (restTimeLine) {
          restTimeLine.classList.toggle('result-line-negative', Boolean(metrics.rest_time_negative));
        }
        if (restTimeNote) {
          restTimeNote.classList.toggle('hidden', !metrics.rest_time_negative);
        }

        (payload.rows || []).forEach((row) => {
          const valueInput = resultTable.querySelector(`[data-indicator-id="${row.indicator_id}"]`);
          const weightNode = resultTable.querySelector(`[data-result-weight="${row.indicator_id}"]`);
          const scoreNode = resultTable.querySelector(`[data-result-score="${row.indicator_id}"]`);
          if (valueInput) {
            valueInput.value = row.value;
          }
          if (weightNode) {
            weightNode.textContent = `${row.normalized_weight}%`;
          }
          if (scoreNode) {
            scoreNode.textContent = row.score;
          }
        });

        (payload.result_money_rows || []).forEach((row) => {
          const node = document.querySelector(`[data-result-money-resource="${row.key}"]`);
          if (node) {
            node.textContent = row.value;
          }
        });

        (payload.result_time_rows || []).forEach((row) => {
          const node = document.querySelector(`[data-result-time-resource="${row.key}"]`);
          if (node) {
            node.textContent = row.value;
          }
        });

        const moneyTotalNode = document.querySelector('[data-result-money-total]');
        if (moneyTotalNode && typeof payload.result_money_total === 'string') {
          moneyTotalNode.textContent = payload.result_money_total;
        }

        const timeTotalNode = document.querySelector('[data-result-time-total]');
        if (timeTotalNode && typeof payload.result_time_total === 'string') {
          timeTotalNode.textContent = payload.result_time_total;
        }

        if (mediaNote) {
          mediaNote.classList.toggle('hidden', !payload.result_media_stale);
        }
        clearResultErrors();
        hideOptimizationSections();
      };

      const triggerPreview = async () => {
        requestCounter += 1;
        const currentRequest = requestCounter;
        const formData = new FormData();
        inputs.forEach((input) => {
          formData.append(input.name, input.value);
        });

        try {
          const response = await fetch(previewUrl, {
            method: 'POST',
            body: formData,
            cache: 'no-store',
          });
          const payload = await response.json();
          if (currentRequest !== requestCounter) {
            return;
          }
          if (!response.ok || !payload.ok) {
            setPreviewError(payload.field_id, payload.message);
            return;
          }
          applyPreviewPayload(payload);
        } catch (error) {
          if (currentRequest !== requestCounter) {
            return;
          }
          setPreviewError('', 'Не удалось пересчитать результат');
        }
      };

      const schedulePreview = () => {
        if (previewTimer) {
          window.clearTimeout(previewTimer);
        }
        previewTimer = window.setTimeout(triggerPreview, 350);
      };

      inputs.forEach((input) => {
        input.addEventListener('input', () => {
          input.classList.remove('input-error');
          schedulePreview();
        });
      });
    }
  </script>
</body>
</html>
