<?php
// index.php
// ВАЖНО: я не менял адресов получения данных/логику — frontend делает запрос к 'api/latest.php' как и раньше.
// Этот файл — современный фронтенд-обёртка (Tailwind + ApexCharts + Alpine.js).
?>
<!doctype html>
<html lang="ru" x-data="avatiahApp()" :class="dark ? 'dark' : ''">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>Avatiah Security Index — Израиль</title>
  <meta name="description" content="Мониторинг индекса Avatiah: главный индекс напряженности и 10 факторов в реальном времени. Интерактивные графики, исторический контекст, новости и источники." />
  <meta name="keywords" content="Индекс напряженности Израиль, Avatiah, геополитический риск, OSINT индекс, мониторинг ситуации" />
  <!-- OpenGraph -->
  <meta property="og:title" content="Avatiah Security Index — Израиль" />
  <meta property="og:description" content="Интерактивный мониторинг индекса Avatiah и 10 факторов риска. История, новости и анализ." />
  <meta property="og:type" content="website" />

  <!-- Tailwind CSS (CDN build for demo; в продакшн - собрать локально) -->
  <script src="https://cdn.tailwindcss.com"></script>

  <!-- Alpine.js for interactivity -->
  <script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>

  <!-- ApexCharts for charts -->
  <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>

  <!-- Optional: Font Awesome icons (CDN) -->
  <script src="https://kit.fontawesome.com/your_kit_id.js" crossorigin="anonymous"></script>

  <!-- Keep existing Chart.js include (не мешает, сохраняю совместимость) -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>

  <style>
    /* Доп. стили для плавных анимаций и мини-кастомизации */
    :root{
      --danger:#ff4d4f; --warning:#ffb020; --safe:#27ae60; --bg-dark:#0b1220; --muted:rgba(255,255,255,0.65);
    }
    html,body { height:100%; }
    body.dark { background: linear-gradient(180deg,#071018,#08121b); color: #e6eef6; }
    body { background: #f8fafc; color: #0f172a; font-family: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial; }

    /* Главный индекс - эффект масштабирования */
    .main-index {
      transition: transform .45s cubic-bezier(.2,.9,.3,1);
    }
    .main-index:hover { transform: translateY(-6px) scale(1.02); }

    /* карточки показателей */
    .indicator-card { transition: box-shadow .25s, transform .25s; }
    .indicator-card:hover { transform: translateY(-6px); box-shadow: 0 10px 30px rgba(2,6,23,.35); }

    /* мини-график в карточке */
    .sparkline { height: 48px; }

    /* адаптивный горизонтальный слайдер (простейший) */
    .horizontal-scroll { overflow-x:auto; -webkit-overflow-scrolling:touch; scroll-behavior:smooth; }
    .horizontal-scroll > .card { display:inline-block; vertical-align:top; margin-right:1rem; }
    /* scrollbar for modern browsers */
    .horizontal-scroll::-webkit-scrollbar { height: 8px; }
    .horizontal-scroll::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.12); border-radius: 999px; }

    /* маленькая подсветка тренда */
    .trend-up { color: var(--safe); }
    .trend-down { color: var(--danger); }
    .trend-flat { color: var(--warning); }

    /* modal */
    .overlay { background: rgba(3,7,18,0.6); backdrop-filter: blur(3px); }
  </style>

  <!-- Schema.org Dataset (минимальная) -->
  <script type="application/ld+json">
  {
    "@context":"https://schema.org",
    "@type":"Dataset",
    "name":"Avatiah Security Index — Israel",
    "description":"Индекс напряженности Avatiah по Израилю: главный индекс и 10 факторов в реальном времени.",
    "url": "<?php echo (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; ?>",
    "license":"https://example.com/license",
    "keywords":["Avatiah","индекс","Израиль","геополитика","риск"]
  }
  </script>
</head>

<body class="antialiased">
  <div class="max-w-[1200px] mx-auto p-4 md:p-6">
    <!-- header -->
    <header class="flex items-center justify-between gap-4 mb-6">
      <div class="flex items-center gap-4">
        <div class="w-12 h-12 rounded-lg bg-gradient-to-br from-indigo-600 to-cyan-400 flex items-center justify-center shadow-lg">
          <svg width="28" height="28" viewBox="0 0 24 24" fill="none" aria-hidden>
            <path d="M12 2L19 8v8l-7 6-7-6V8l7-6z" fill="white" opacity=".9"/>
          </svg>
        </div>
        <div>
          <h1 class="text-xl md:text-2xl font-semibold">Avatiah Security Index — Израиль</h1>
          <p class="text-sm text-slate-500 dark:text-slate-300">Интерактивный мониторинг: 10 факторов + главный индекс в реальном времени</p>
        </div>
      </div>

      <div class="flex items-center gap-3">
        <div class="text-sm text-slate-500 dark:text-slate-300 mr-2">Тема</div>
        <button @click="toggleDark()" class="px-3 py-2 rounded-lg bg-slate-100 dark:bg-slate-800 border dark:border-slate-700">
          <template x-if="dark"><i class="fas fa-moon"></i></template>
          <template x-if="!dark"><i class="fas fa-sun"></i></template>
        </button>

        <div class="ml-2">
          <button @click="refresh()" class="px-3 py-2 rounded-lg bg-indigo-600 text-white hover:bg-indigo-500">
            Обновить
          </button>
        </div>
      </div>
    </header>

    <!-- MAIN -->
    <main class="grid grid-cols-1 lg:grid-cols-3 gap-6">
      <!-- Left: Главный индекс + короткая справка -->
      <section class="col-span-1 lg:col-span-2">
        <div class="bg-white dark:bg-[#071426] rounded-xl p-6 shadow-sm">
          <div class="flex items-center justify-between gap-6">
            <div class="flex items-center gap-6">
              <!-- Главный индекс большой -->
              <div class="main-index p-6 rounded-xl bg-gradient-to-br from-slate-50 to-white dark:from-[#071a2a] dark:to-[#071426] shadow-sm border dark:border-slate-700 flex items-center gap-6">
                <div>
                  <div class="text-sm text-slate-500 dark:text-slate-300">Главный индекс (Risk Score)</div>
                  <div class="mt-2 flex items-center gap-4">
                    <div id="mainIndexValue" class="text-5xl font-extrabold" x-text="displayMainIndex"></div>
                    <div class="flex flex-col">
                      <div class="index-label-big text-sm text-slate-500 dark:text-slate-300">Сейчас</div>
                      <div class="index-status rounded-xl px-3 py-1 text-sm" :class="mainIndexColorClass" x-text="mainIndexLabel"></div>
                    </div>
                  </div>

                  <div class="mt-4 w-[420px] max-w-full">
                    <div class="h-3 rounded-full overflow-hidden bg-slate-100 dark:bg-slate-700">
                      <div :style="`width:${mainIndexPercent}%`" class="h-full transition-all" :class="mainIndexColorBar"></div>
                    </div>
                    <div class="flex items-center justify-between text-xs text-slate-400 dark:text-slate-400 mt-2">
                      <span>0</span><span>5</span><span>10</span>
                    </div>
                  </div>
                </div>

                <!-- маленький мини-график для главного индекса -->
                <div class="w-48 h-24">
                  <div id="mainSparkline"></div>
                </div>
              </div>

              <!-- краткая карточка метрик -->
              <div class="ml-4">
                <div class="text-xs text-slate-500 dark:text-slate-300">Обновлено:</div>
                <div class="mt-1 text-sm font-medium" x-text="lastUpdatedReadable">—</div>
                <div class="mt-3 text-sm text-slate-500 dark:text-slate-400">Источники: <a class="underline" href="#" @click.prevent="openSources()">API / Open Sources</a></div>
              </div>
            </div>

            <div class="hidden lg:block w-48">
              <!-- Быстрые действия / фильтры -->
              <div class="text-sm text-slate-500 dark:text-slate-400 mb-2">Фильтр периода</div>
              <div class="grid grid-cols-2 gap-2">
                <button :class="selectedPeriod==='24h'? 'bg-indigo-600 text-white' : 'bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300'" @click="setGlobalPeriod('24h')">24 часа</button>
                <button :class="selectedPeriod==='week'? 'bg-indigo-600 text-white' : 'bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300'" @click="setGlobalPeriod('week')">Неделя</button>
                <button :class="selectedPeriod==='month'? 'bg-indigo-600 text-white' : 'bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300'" @click="setGlobalPeriod('month')">Месяц</button>
                <button :class="selectedPeriod==='year'? 'bg-indigo-600 text-white' : 'bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300'" @click="setGlobalPeriod('year')">Год</button>
              </div>
              <div class="mt-4 text-xs text-slate-400">Уровень тревоги</div>
              <div class="mt-2 flex items-center gap-2">
                <div class="w-2 h-6 rounded bg-green-500"></div>
                <div class="w-2 h-6 rounded bg-yellow-400"></div>
                <div class="w-2 h-6 rounded bg-red-500"></div>
              </div>
            </div>
          </div>

          <!-- короткое пояснение -->
          <div class="mt-6 text-sm text-slate-600 dark:text-slate-300">
            <strong>Что это значит?</strong> Главный индекс — агрегированный показатель на основе 10 факторов. Нажмите на любой фактор внизу, чтобы увидеть подробный анализ, исторический график и источники.
          </div>
        </div>

        <!-- Indicators grid / mobile horizontal -->
        <div class="mt-6">
          <div class="mb-3 flex items-center justify-between">
            <h2 class="text-lg font-semibold">10 факторов индекса</h2>
            <div class="text-sm text-slate-500 dark:text-slate-300">Наведите или нажмите карточку — подробности</div>
          </div>

          <!-- desktop grid -->
          <div class="hidden md:grid grid-cols-2 lg:grid-cols-3 gap-4">
            <template x-for="(ind, idx) in indicators" :key="ind.id">
              <div class="indicator-card card bg-white dark:bg-[#071426] rounded-xl p-4 border dark:border-slate-700" @mouseenter="hoverIndicator(ind)" @mouseleave="leaveIndicator(ind)">
                <div class="flex items-start justify-between gap-2">
                  <div class="flex items-center gap-3">
                    <div class="w-11 h-11 rounded-lg flex items-center justify-center bg-slate-100 dark:bg-slate-800">
                      <i class="fas fa-shield-alt"></i>
                    </div>
                    <div>
                      <div class="text-sm font-medium" x-text="ind.name"></div>
                      <div class="text-xs text-slate-400 dark:text-slate-400" x-text="ind.short || ''"></div>
                    </div>
                  </div>

                  <div class="text-right">
                    <div class="text-lg font-semibold" x-text="formatValue(ind.value)"></div>
                    <div class="text-xs mt-1" :class="ind.trend>0 ? 'trend-up' : (ind.trend<0 ? 'trend-down' : 'trend-flat')" x-text="trendLabel(ind.trend)"></div>
                  </div>
                </div>

                <div class="mt-3 flex items-center justify-between gap-3">
                  <div class="w-36 h-12 sparkline" :id="'spark-'+ind.id"></div>
                  <div class="text-xs text-slate-500 dark:text-slate-300 text-right">
                    <div x-text="ind.lastChangeText"></div>
                    <div class="mt-1"><button @click="openDetail(ind)" class="text-indigo-600 dark:text-indigo-400 text-xs">Подробнее →</button></div>
                  </div>
                </div>
              </div>
            </template>
          </div>

          <!-- mobile horizontal scroll -->
          <div class="md:hidden mt-3 horizontal-scroll">
            <template x-for="ind in indicators" :key="ind.id">
              <div class="card w-64 bg-white dark:bg-[#071426] rounded-xl p-4 inline-block">
                <div class="flex items-center justify-between">
                  <div>
                    <div class="text-sm font-medium" x-text="ind.name"></div>
                    <div class="text-xs text-slate-400 dark:text-slate-300" x-text="formatValue(ind.value)"></div>
                  </div>
                  <div>
                    <div class="w-12 h-12 rounded-lg bg-slate-100 dark:bg-slate-800 flex items-center justify-center">
                      <i class="fas fa-shield-alt"></i>
                    </div>
                  </div>
                </div>
                <div class="mt-3">
                  <div class="h-12 sparkline" :id="'spark-mobile-'+ind.id"></div>
                </div>
                <div class="mt-3 text-xs">
                  <button @click="openDetail(ind)" class="text-indigo-600 dark:text-indigo-400">Подробнее</button>
                </div>
              </div>
            </template>
          </div>

        </div>
      </section>

      <!-- Right sidebar: новости / события / карточки знаний -->
      <aside class="col-span-1">
        <div class="bg-white dark:bg-[#071426] rounded-xl p-4 mb-4 border dark:border-slate-700">
          <div class="flex items-center justify-between">
            <div>
              <div class="text-sm text-slate-500 dark:text-slate-300">Новости, влияющие на индекс</div>
              <div class="mt-2 text-sm font-medium" x-text="news.length + ' записей'">—</div>
            </div>
            <div>
              <button @click="openNews()" class="px-2 py-1 text-xs rounded bg-indigo-600 text-white">Открыть ленту</button>
            </div>
          </div>

          <template x-if="news.length==0">
            <div class="mt-3 text-xs text-slate-500 dark:text-slate-300">Новостей пока нет — данные подгрузятся из API.</div>
          </template>
          <template x-for="n in news.slice(0,3)" :key="n.id">
            <div class="mt-3 border-t pt-3 text-xs text-slate-500 dark:text-slate-300">
              <div class="font-medium" x-text="n.title">Заголовок</div>
              <div class="mt-1" x-text="n.summary">Краткое описание</div>
              <div class="mt-2 text-[11px] text-slate-400 dark:text-slate-400">Затрагивает: <span x-text="n.affected || '—'"></span></div>
            </div>
          </template>
        </div>

        <div class="bg-white dark:bg-[#071426] rounded-xl p-4 border dark:border-slate-700">
          <div class="text-sm text-slate-500 dark:text-slate-300">Карточки знаний</div>
          <div class="mt-3">
            <template x-for="(k, idx) in knowledge.slice(0,3)" :key="idx">
              <div class="mt-2">
                <div class="font-medium" x-text="k.title">Название</div>
                <div class="mt-1 text-xs text-slate-400" x-text="k.excerpt">Короткое описание</div>
                <div class="mt-2"><button @click="openKnowledge(k)" class="text-indigo-600 dark:text-indigo-400 text-xs">Читать</button></div>
              </div>
            </template>
          </div>
        </div>
      </aside>
    </main>

    <!-- Footer / disclaimer -->
    <footer class="mt-8 text-center text-xs text-slate-500 dark:text-slate-400">
      <div>Данные обновляются автоматически из API. Avatiah — инструмент мониторинга. Не является официальным предупреждением.</div>
    </footer>
  </div>

  <!-- Detail modal -->
  <div x-show="detailOpen" x-transition class="fixed inset-0 z-50 flex items-center justify-center" style="display:none;">
    <div class="absolute inset-0 overlay" @click="closeDetail()"></div>
    <div class="relative max-w-4xl w-full mx-4">
      <div class="bg-white dark:bg-[#071426] rounded-xl p-6 border dark:border-slate-700 shadow-xl">
        <div class="flex items-start justify-between gap-4">
          <div>
            <h3 class="text-xl font-semibold" x-text="selectedIndicator.name">Название показателя</h3>
            <div class="text-sm text-slate-500 dark:text-slate-300" x-text="selectedIndicator.description || ''"></div>
          </div>
          <div>
            <button @click="closeDetail()" class="px-3 py-2 rounded bg-slate-100 dark:bg-slate-800">Закрыть</button>
          </div>
        </div>

        <div class="mt-4">
          <div id="detailChart"></div>
        </div>

        <div class="mt-4 grid grid-cols-1 md:grid-cols-3 gap-4 text-sm">
          <div>
            <div class="text-xs text-slate-500 dark:text-slate-300">Что сейчас влияет</div>
            <ul class="mt-2 text-sm" x-html="formatInfluences(selectedIndicator.influences)"></ul>
          </div>

          <div>
            <div class="text-xs text-slate-500 dark:text-slate-300">Исторический контекст</div>
            <div class="mt-2 text-sm" x-text="selectedIndicator.historyContext || '—'"></div>
          </div>

          <div>
            <div class="text-xs text-slate-500 dark:text-slate-300">Источники</div>
            <div class="mt-2 text-sm">
              <template x-for="s in (selectedIndicator.sources || [])" :key="s">
                <div><a :href="s" target="_blank" class="underline text-indigo-600 dark:text-indigo-400 text-sm" x-text="s"></a></div>
              </template>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- News modal -->
  <div x-show="newsOpen" x-transition class="fixed inset-0 z-40" style="display:none;">
    <div class="absolute inset-0 overlay" @click="newsOpen=false"></div>
    <div class="relative max-w-3xl mx-auto mt-12 p-4">
      <div class="bg-white dark:bg-[#071426] p-4 rounded-xl border dark:border-slate-700">
        <div class="flex items-center justify-between">
          <h3 class="text-lg font-semibold">Лента новостей</h3>
          <button @click="newsOpen=false" class="px-3 py-2 rounded bg-slate-100 dark:bg-slate-800">Закрыть</button>
        </div>
        <div class="mt-4">
          <template x-for="n in news" :key="n.id">
            <div class="border-t py-3">
              <div class="font-medium" x-text="n.title"></div>
              <div class="text-xs text-slate-500 mt-1" x-text="n.date"></div>
              <div class="mt-2" x-text="n.summary"></div>
              <div class="mt-2 text-[12px] text-slate-400">Затрагивает: <span x-text="n.affected"></span></div>
            </div>
          </template>
        </div>
      </div>
    </div>
  </div>

  <!-- Knowledge modal -->
  <div x-show="knowledgeOpen" x-transition class="fixed inset-0 z-40" style="display:none;">
    <div class="absolute inset-0 overlay" @click="knowledgeOpen=false"></div>
    <div class="relative max-w-3xl mx-auto mt-12 p-4">
      <div class="bg-white dark:bg-[#071426] p-4 rounded-xl border dark:border-slate-700">
        <div class="flex items-center justify-between">
          <h3 class="text-lg font-semibold" x-text="knowledgeSelected.title">Заголовок</h3>
          <button @click="knowledgeOpen=false" class="px-3 py-2 rounded bg-slate-100 dark:bg-slate-800">Закрыть</button>
        </div>
        <div class="mt-4 text-sm" x-html="knowledgeSelected.content"></div>
      </div>
    </div>
  </div>

  <script>
    function avatiahApp(){
      return {
        dark: true,
        indicators: [],       // массив показателей
        mainIndex: null,      // число
        mainHistory: [],      // массив {t, v}
        news: [],
        knowledge: [],
        lastUpdated: null,
        selectedPeriod: '24h',
        detailOpen: false,
        selectedIndicator: {},
        newsOpen: false,
        knowledgeOpen: false,
        knowledgeSelected: {},
        // --- computed / helper ---
        get displayMainIndex(){
          return (this.mainIndex !== null) ? this.mainIndex.toFixed(1) : '—';
        },
        get mainIndexPercent(){
          // если шкала 0-10
          if (this.mainIndex === null) return 0;
          return Math.max(0, Math.min(100, (this.mainIndex/10)*100));
        },
        get mainIndexLabel(){
          if (this.mainIndex===null) return '—';
          if (this.mainIndex >= 7) return 'Высокая угроза';
          if (this.mainIndex >= 4) return 'Средняя';
          return 'Низкая';
        },
        get lastUpdatedReadable(){
          if (!this.lastUpdated) return '—';
          return new Date(this.lastUpdated).toLocaleString();
        },
        mainIndexColorClass(){
          if (this.mainIndex >= 7) return 'bg-red-600 text-white';
          if (this.mainIndex >= 4) return 'bg-yellow-500 text-black';
          return 'bg-green-600 text-white';
        },
        mainIndexColorBar(){
          if (this.mainIndex >= 7) return 'bg-red-500';
          if (this.mainIndex >= 4) return 'bg-yellow-400';
          return 'bg-green-500';
        },

        // init
        init() {
          // сразу загрузим данные
          this.fetchData();

          // инициализация интервала автообновления (например, 60 сек)
          this._autoRefresh = setInterval(()=> this.fetchData(false), 60*1000);
        },

        async fetchData(withSparklines=true) {
          try {
            // Сохранено точное название endpoint — НЕ МЕНЯЕМ.
            const res = await fetch('api/latest.php');
            if (!res.ok) throw new Error('Ошибка сети ' + res.status);
            const data = await res.json();

            // Ожидаем структуру — подстраховка:
            // data.mainIndex, data.mainHistory, data.indicators (массив из 10), data.news, data.knowledge, data.updated
            this.mainIndex = data.mainIndex ?? (data.main_index ?? null);
            this.mainHistory = data.mainHistory ?? data.main_history ?? (data.history ?? []);
            this.indicators = (data.indicators ?? data.factors ?? []).map((i, idx) => {
              // гарантируем поля id, name, value, trend, history, sources
              return {
                id: i.id ?? i.key ?? ('ind-'+idx),
                name: i.name ?? i.title ?? ('Показатель '+(idx+1)),
                value: (i.value ?? i.v ?? 0),
                trend: (i.trend ?? i.change ?? 0),
                history: (i.history ?? i.series ?? []),
                sources: (i.sources ?? i.links ?? []),
                short: i.short ?? '',
                description: i.description ?? '',
                lastChangeText: i.lastChangeText ?? (i.changeText ?? ''),
                influences: i.influences ?? [],
                historyContext: i.historyContext ?? ''
              };
            });

            this.news = data.news ?? data.events ?? [];
            this.knowledge = data.knowledge ?? [];
            this.lastUpdated = data.updated ?? new Date().toISOString();

            // отрисовать мини-графики (sparklines)
            if (withSparklines) {
              this.renderSparklines();
              this.renderMainSpark();
            }
          } catch (e){
            console.error('fetchData error', e);
          }
        },

        // render small charts and main chart
        renderSparklines(){
          // для каждого индикатора рендерим маленький ApexCharts area без легенды
          this.indicators.forEach(ind => {
            const elId = 'spark-' + ind.id;
            const elMobile = 'spark-mobile-' + ind.id;
            const series = (ind.history && ind.history.length) ? ind.history.map(p => ({x: p.t || p[0], y: p.v ?? p[1] ?? p})) : [];
            const values = series.map(s => typeof s==='object' ? s.y : s);

            // destroy existing chart if exists
            try { if (window['spark_'+elId]) window['spark_'+elId].destroy(); } catch(e){}
            try { if (document.getElementById(elId)) {
              const options = {
                chart: { type: 'area', height: 48, sparkline: { enabled: true } },
                series: [{ data: values }],
                stroke: { curve: 'smooth', width: 2 },
                fill: { opacity: 0.08 },
                tooltip: { enabled: false }
              };
              window['spark_'+elId] = new ApexCharts(document.getElementById(elId), options);
              window['spark_'+elId].render();
            }}

            catch(e){ /*console.warn(e)*/ }

            try { if (window['spark_'+elMobile]) window['spark_'+elMobile].destroy(); } catch(e){}
            try { if (document.getElementById(elMobile)) {
              const options2 = {
                chart: { type: 'area', height: 48, sparkline: { enabled: true } },
                series: [{ data: values }],
                stroke: { curve: 'smooth', width: 2 },
                fill: { opacity: 0.06 },
                tooltip: { enabled: false }
              };
              window['spark_'+elMobile] = new ApexCharts(document.getElementById(elMobile), options2);
              window['spark_'+elMobile].render();
            }}

            catch(e){}
          });
        },

        renderMainSpark(){
          // простой spark с mainHistory
          try { if (window.mainSpark) window.mainSpark.destroy(); } catch(e){}
          const vals = (this.mainHistory || []).map(p => (p.v ?? (Array.isArray(p)? p[1] : p)));
          const options = {
            chart: { type: 'area', height: 60, sparkline: { enabled: true } },
            series: [{ data: vals }],
            stroke: { curve: 'smooth', width: 2 },
            fill: { opacity: 0.06 },
            tooltip: { enabled: false }
          };
          if (document.getElementById('mainSparkline')) {
            window.mainSpark = new ApexCharts(document.getElementById('mainSparkline'), options);
            window.mainSpark.render();
          }
        },

        // open detail modal
        openDetail(ind){
          this.selectedIndicator = ind;
          this.detailOpen = true;
          this.$nextTick(()=> this.renderDetailChart());
        },
        closeDetail(){
          this.detailOpen = false;
          try { if (window.detailChart) window.detailChart.destroy(); } catch(e){}
        },

        // render big detail chart
        renderDetailChart(period=this.selectedPeriod){
          try { if (window.detailChart) window.detailChart.destroy(); } catch(e){}
          const ind = this.selectedIndicator;
          const raw = (ind.history && ind.history.length) ? ind.history : [];
          // фильтр по периоду (если есть временные метки)
          let data = raw;
          if (period && raw.length && raw[0].t) {
            const now = Date.now();
            let cutoff = 0;
            if (period==='24h') cutoff = now - 24*3600*1000;
            if (period==='week') cutoff = now - 7*24*3600*1000;
            if (period==='month') cutoff = now - 30*24*3600*1000;
            if (period==='year') cutoff = now - 365*24*3600*1000;
            data = raw.filter(p => (new Date(p.t).getTime() >= cutoff));
          }

          const series = [{ name: ind.name, data: (data.map(p => ({x: p.t || p[0], y: p.v ?? p[1] ?? p}))) }];

          const options = {
            chart: { type: 'area', height: 320, zoom: { enabled: true } },
            series,
            xaxis: { type: 'datetime' },
            stroke: { curve: 'smooth' },
            tooltip: { x: { format: 'dd MMM yyyy HH:mm' } },
            colors: [ this.mainIndex >=7 ? '#ff4d4f' : (this.mainIndex>=4? '#ffb020' : '#27ae60') ]
          };
          const el = document.getElementById('detailChart');
          if (el) {
            window.detailChart = new ApexCharts(el, options);
            window.detailChart.render();
          }
        },

        openSources(){
          window.open('https://example.com/sources','_blank');
        },

        hoverIndicator(ind){
          // можно показать краткий tooltip или подсветку — пока оставляем
        },
        leaveIndicator(ind){},

        openNews(){ this.newsOpen = true; },
        openKnowledge(k){ this.knowledgeSelected = k; this.knowledgeOpen = true; },

        openKnowledge(k){ this.knowledgeSelected = k; this.knowledgeOpen = true; },

        setGlobalPeriod(p){
          this.selectedPeriod = p;
          // если открыт detail, перерисуем
          if (this.detailOpen) this.renderDetailChart(p);
          // можно также применить к sparkline/главному графику — здесь оставлено для расширения
        },

        refresh(){ this.fetchData(true); },

        formatValue(v){
          if (v===null || v===undefined) return '—';
          if (typeof v === 'number') return v.toFixed(1);
          return v;
        },

        trendLabel(t){
          if (t>0) return '↑ +' + (typeof t==='number'? t.toFixed(2): t);
          if (t<0) return '↓ ' + (typeof t==='number'? t.toFixed(2): t);
          return '—';
        },

        formatInfluences(arr){
          if (!arr || !arr.length) return '<em>Нет данных</em>';
          return '<ul class="list-disc ml-4">'+arr.map(x => '<li>'+x+'</li>').join('')+'</ul>';
        },

        toggleDark(){
          this.dark = !this.dark;
        }
      };
    }

    // Alpine init
    document.addEventListener('alpine:init', () => {
      // nothing extra
    });

    // mount app
    document.addEventListener('DOMContentLoaded', () => {
      // Alpine will instantiate via x-data on <html>
      // but ensure init method is called:
      setTimeout(()=>{
        if (document.documentElement.__x) {
          const app = document.documentElement.__x.$data;
          if (app && typeof app.init === 'function') app.init();
        }
      }, 50);
    });
  </script>

</body>
</html>
