'use strict';
/* admin → overview (Phase 3 dashboard) — landing page "что требует внимания".
 * Lazy-init via AdminSections.overview.init(); reloads via .reload().
 */
(function () {
  'use strict';
  let inited = false;
  let _lastLoadTs = 0;
  let _tsInterval = null;

  /* ── one-time CSS injection (overview-specific bento layout) ────────── */
  function ensureOvStyles() {
    if (document.getElementById('ov-style')) return;
    const s = document.createElement('style');
    s.id = 'ov-style';
    s.textContent = `
      /* ── main grid ─────────────────────────────────────────────── */
      .ov-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 28px; }
      @media (min-width: 720px) {
        .ov-grid.ov-grid-main { grid-template-columns: 2fr 1fr 1fr 1fr; }
      }
      .ov-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); padding: 22px 20px; position: relative; overflow: hidden; }
      .ov-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: var(--ov-top, var(--violet)); opacity: 0.7; }
      .ov-card-icon { width: 38px; height: 38px; border-radius: 12px; display: flex; align-items: center; justify-content: center; margin-bottom: 12px; background: rgba(155,93,229,0.1); color: var(--violet); }
      .ov-card.hero .ov-card-icon { width: 52px; height: 52px; border-radius: 14px; }
      .ov-card-val { font-family: 'Unbounded', sans-serif; font-size: 1.9rem; font-weight: 800; line-height: 1.1; margin-bottom: 4px; }
      .ov-card.hero .ov-card-val { font-size: 2.6rem; }
      .ov-card-label { font-size: 0.82rem; color: var(--text-3); font-weight: 600; }
      .ov-card-spark { margin-top: 6px; opacity: 0.7; }
      .ov-zero { color: var(--text-3); opacity: 0.55; }
      .ov-card.warn { border-color: rgba(255,179,71,0.4); }
      .ov-card.warn::before { background: var(--amber); }
      .ov-card.warn .ov-card-icon { background: rgba(255,179,71,0.12); color: var(--amber); }
      .ov-card.danger { border-color: rgba(241,91,181,0.35); }
      .ov-card.danger::before { background: var(--pink); }
      .ov-card.danger .ov-card-icon { background: rgba(241,91,181,0.1); color: var(--pink); }
      /* ── section header ─────────────────────────────────────────── */
      .ov-section-title { font-family: 'Unbounded', sans-serif; font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-3); margin: 28px 0 12px; }
      .ov-header { display: flex; justify-content: space-between; align-items: center; margin: 28px 0 12px; }
      .ov-header .ov-section-title { margin: 0; }
      .ov-refresh { display: flex; align-items: center; gap: 8px; font-size: 0.78rem; color: var(--text-3); }
      .ov-refresh-btn { background: transparent; border: 1px solid var(--border); border-radius: 8px; width: 28px; height: 28px; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; color: var(--text-3); transition: color .12s, border-color .12s; }
      .ov-refresh-btn:hover { color: var(--violet); border-color: rgba(155,93,229,0.35); }
      /* ── banned / alert list ────────────────────────────────────── */
      .ov-banned-list { display: flex; flex-direction: column; gap: 6px; }
      .ov-banned-row { display: flex; align-items: center; gap: 10px; padding: 10px 14px; background: rgba(241,91,181,0.06); border: 1px solid rgba(241,91,181,0.18); border-radius: 10px; font-size: 0.86rem; }
      .ov-banned-row .ov-bn-name { font-weight: 600; }
      .ov-banned-row .ov-bn-email { color: var(--text-3); font-size: 0.78rem; }
      .ov-banned-row .ov-bn-date { margin-left: auto; color: var(--text-3); font-size: 0.76rem; }
      /* ── stuck-session list ─────────────────────────────────────── */
      .ov-stuck-list { display: flex; flex-direction: column; gap: 6px; }
      .ov-stuck-row { display: flex; align-items: center; gap: 10px; padding: 8px 12px; background: rgba(255,179,71,0.07); border: 1px solid rgba(255,179,71,0.22); border-radius: 10px; font-size: 0.84rem; }
      .ov-stuck-row .ov-st-name { font-weight: 600; flex: 1; }
      .ov-stuck-row .ov-st-subj { color: var(--text-3); font-size: 0.78rem; }
      .ov-stuck-row .ov-st-since { margin-left: auto; color: var(--text-3); font-size: 0.76rem; white-space: nowrap; }
      /* ── content inventory ──────────────────────────────────────── */
      .ov-inv-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 12px; margin-bottom: 28px; }
      .ov-inv-item { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 12px 16px; display: flex; flex-direction: column; gap: 2px; }
      .ov-inv-n { font-family: 'Unbounded', sans-serif; font-size: 1.4rem; font-weight: 800; color: var(--text); }
      .ov-inv-l { font-size: 0.76rem; color: var(--text-3); font-weight: 600; }
      /* ── subject distribution bar ───────────────────────────────── */
      .ov-subj-bar-track { height: 10px; border-radius: 5px; overflow: hidden; display: flex; margin-bottom: 10px; background: var(--border); }
      .ov-subj-seg { height: 100%; transition: width .3s; }
      .ov-subj-legend { display: flex; flex-wrap: wrap; gap: 8px 16px; font-size: 0.78rem; color: var(--text-3); }
      .ov-subj-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 4px; vertical-align: middle; }
      /* ── top/worst tables side by side ──────────────────────────── */
      .ov-results-grid { display: grid; grid-template-columns: 1fr; gap: 28px; }
      @media (min-width: 1100px) { .ov-results-grid { grid-template-columns: 1fr 1fr; } }
      .ov-top-table { width: 100%; border-collapse: collapse; }
      .ov-top-table th { text-align: left; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-3); font-weight: 700; padding: 8px 10px; border-bottom: 1px solid var(--border); }
      .ov-top-table td { padding: 10px; font-size: 0.86rem; border-bottom: 1px solid var(--border); }
      .ov-top-table tr:last-child td { border-bottom: none; }
      .ov-pct { font-family: 'Unbounded', sans-serif; font-weight: 700; }
      .ov-pct.hi  { color: var(--green); }
      .ov-pct.mid { color: var(--amber); }
      .ov-pct.lo  { color: var(--pink); }
      /* ── quick-nav ──────────────────────────────────────────────── */
      .ov-quick-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; }
      .ov-quick-btn { display: flex; align-items: center; gap: 10px; padding: 14px 16px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; cursor: pointer; font-family: inherit; font-size: 0.88rem; font-weight: 600; color: var(--text); text-align: left; transition: background .12s, border-color .12s, transform .12s; }
      .ov-quick-btn:hover { background: rgba(155,93,229,0.06); border-color: rgba(155,93,229,0.3); color: var(--violet); transform: translateY(-1px); }
      .ov-quick-btn svg { width: 16px; height: 16px; flex-shrink: 0; }
      /* ── avatar pills ───────────────────────────────────────────── */
      .ov-avatar { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 50%; font-size: 10px; font-weight: 700; color: #fff; margin-right: 6px; vertical-align: middle; flex-shrink: 0; }
      .ov-cell-user { display: flex; align-items: center; }
      /* ── skeleton loader ────────────────────────────────────────── */
      @keyframes ov-shimmer { 0%{background-position:-400px 0} 100%{background-position:400px 0} }
      .ov-skel-box { border-radius: 12px; background: linear-gradient(90deg,var(--border) 25%,var(--surface) 50%,var(--border) 75%); background-size: 400px 100%; animation: ov-shimmer 1.4s infinite linear; }
      .ov-skel-cards { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 16px; margin-bottom: 28px; }
      .ov-skel-card { height: 110px; }
      .ov-skel-rows { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
      .ov-skel-row { height: 38px; }
      /* ── misc ───────────────────────────────────────────────────── */
      .ov-empty { padding: 18px; text-align: center; color: var(--text-3); font-size: 0.85rem; }
      /* ── mobile breakpoints ─────────────────────────────────────── */
      @media (max-width: 640px) {
        .ov-grid.ov-grid-main { grid-template-columns: 1fr 1fr; }
        .ov-card.hero .ov-card-val { font-size: 1.9rem; }
        .ov-card.hero .ov-card-icon { width: 38px; height: 38px; border-radius: 12px; }
        .ov-results-grid { grid-template-columns: 1fr; }
        .ov-quick-grid { grid-template-columns: 1fr 1fr; }
        .ov-skel-cards { grid-template-columns: 1fr 1fr; }
      }
    `;
    document.head.appendChild(s);
  }

  /* ── sparkline renderer ──────────────────────────────────────────────── */
  /* Takes array of {d: 'YYYY-MM-DD', n: N}, fills 7-day window, returns SVG */
  function renderSparkline(rawData, color) {
    const W = 50, H = 18, PAD = 2;
    // Build date map for last 7 days
    const map = {};
    (rawData || []).forEach(function (r) { map[r.d] = r.n; });
    const points = [];
    for (let i = 6; i >= 0; i--) {
      const d = new Date();
      d.setDate(d.getDate() - i);
      const key = d.toISOString().slice(0, 10);
      points.push(map[key] || 0);
    }
    const max = Math.max.apply(null, points) || 1;
    const xs = points.map(function (_, i) { return PAD + (i / 6) * (W - 2 * PAD); });
    const ys = points.map(function (v) { return H - PAD - (v / max) * (H - 2 * PAD); });
    const polyline = xs.map(function (x, i) { return x.toFixed(1) + ',' + ys[i].toFixed(1); }).join(' ');
    return '<svg width="' + W + '" height="' + H + '" viewBox="0 0 ' + W + ' ' + H + '" xmlns="http://www.w3.org/2000/svg">' +
      '<polyline points="' + polyline + '" fill="none" stroke="' + color + '" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>' +
      '</svg>';
  }

  /* ── subject bar colors (hue cycle) ─────────────────────────────────── */
  var SUBJ_COLORS = [
    '#9B5DE5','#06D6E0','#06D664','#FFB347','#F15BB5',
    '#4FC3F7','#81C784','#FFD54F','#FF8A65','#BA68C8',
  ];

  function renderSubjectBar(subjects) {
    if (!subjects || !subjects.length) {
      return '<div class="ov-empty">Нет сессий за последние 24 часа</div>';
    }
    const total = subjects.reduce(function (s, r) { return s + r.n; }, 0) || 1;
    let segs = '', legend = '';
    subjects.forEach(function (r, i) {
      const pct = (r.n / total * 100).toFixed(1);
      const col = SUBJ_COLORS[i % SUBJ_COLORS.length];
      segs += '<div class="ov-subj-seg" style="width:' + pct + '%;background:' + col + '" title="' + r.name + ': ' + r.n + '"></div>';
      legend += '<span><span class="ov-subj-dot" style="background:' + col + '"></span>' + r.name + ' ' + r.n + '</span>';
    });
    return '<div class="ov-subj-bar-track">' + segs + '</div><div class="ov-subj-legend">' + legend + '</div>';
  }

  /* ── avatar helpers ─────────────────────────────────────────────────── */
  function initialsOf(name) {
    if (!name) return '?';
    return name.trim().split(/\s+/).slice(0, 2).map(function (w) { return w[0] ? w[0].toUpperCase() : ''; }).join('') || '?';
  }

  function hashHue(str) {
    var h = 0;
    for (var i = 0; i < (str || '').length; i++) {
      h = ((h << 5) - h + (str || '').charCodeAt(i)) | 0;
    }
    return Math.abs(h) % 360;
  }

  function avatarHtml(name) {
    var hue = hashHue(name);
    var bg = 'hsl(' + hue + ',55%,60%)';
    return '<span class="ov-avatar" style="background:' + bg + '">' + initialsOf(name) + '</span>';
  }

  /* ── skeleton loader ────────────────────────────────────────────────── */
  function renderSkeleton(el) {
    ensureOvStyles();
    el.innerHTML =
      '<div class="ov-skel-cards">' +
        '<div class="ov-skel-box ov-skel-card"></div>' +
        '<div class="ov-skel-box ov-skel-card"></div>' +
        '<div class="ov-skel-box ov-skel-card"></div>' +
        '<div class="ov-skel-box ov-skel-card"></div>' +
      '</div>' +
      '<div class="ov-skel-rows">' +
        '<div class="ov-skel-box ov-skel-row"></div>' +
        '<div class="ov-skel-box ov-skel-row"></div>' +
        '<div class="ov-skel-box ov-skel-row"></div>' +
        '<div class="ov-skel-box ov-skel-row"></div>' +
        '<div class="ov-skel-box ov-skel-row"></div>' +
      '</div>';
  }

  function pctClassNum(p) {
    if (p === null || p === undefined) return '';
    return p >= 75 ? 'hi' : p >= 50 ? 'mid' : 'lo';
  }

  function fmtNum(n) {
    if (n === null || n === undefined) return '—';
    if (n === 0) return '<span class="ov-zero">0</span>';
    return String(n);
  }

  function fmtBannedDate(s) {
    if (!s) return '';
    try {
      const d = new Date(s.replace(' ', 'T') + 'Z');
      return d.toLocaleDateString('ru', { day: 'numeric', month: 'short' });
    } catch (e) { return ''; }
  }

  function fmtFinished(s) {
    if (!s) return '—';
    try {
      const d = new Date(s.replace(' ', 'T') + 'Z');
      return d.toLocaleString('ru', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' });
    } catch (e) { return s; }
  }

  function fmtAgo(ms) {
    const sec = Math.floor((Date.now() - ms) / 1000);
    if (sec < 10) return 'только что';
    if (sec < 60) return sec + ' сек назад';
    const min = Math.floor(sec / 60);
    if (min < 60) return min + ' мин назад';
    const hr = Math.floor(min / 60);
    return hr + ' ч назад';
  }

  function startTsInterval() {
    if (_tsInterval) return;
    _tsInterval = setInterval(function () {
      const el = document.getElementById('ov-ts');
      if (el && _lastLoadTs) el.textContent = fmtAgo(_lastLoadTs);
    }, 30000);
  }

  function navigateTo(hash) {
    if (window.AdminRouter) AdminRouter.navigate(hash);
    else window.location.hash = hash;
  }

  function renderSessionRows(sessions, e) {
    return sessions.map(function (s) {
      var name = s.user_name || '—';
      return '<tr>' +
        '<td><span class="ov-cell-user">' + avatarHtml(name) + e(name) + '</span></td>' +
        '<td>' + e(s.subject_name || '—') + '</td>' +
        '<td>' + (s.score != null ? s.score : 0) + ' / ' + (s.total != null ? s.total : 0) + '</td>' +
        '<td><span class="ov-pct ' + pctClassNum(s.percent) + '">' + (s.percent != null ? s.percent : '—') + '%</span></td>' +
        '<td style="color:var(--text-3);font-size:0.8rem">' + fmtFinished(s.finished_at) + '</td>' +
        '</tr>';
    }).join('');
  }

  function render(data) {
    const el = document.getElementById('overview-content');
    if (!el) return;
    ensureOvStyles();

    const e = LS.esc;
    const bannedCount = Array.isArray(data.bannedThisWeek) ? data.bannedThisWeek.length : 0;
    const top = Array.isArray(data.topSessions24h) ? data.topSessions24h : [];
    const worst = Array.isArray(data.worstSessions24h) ? data.worstSessions24h : [];
    const stuck = Array.isArray(data.stuckSessions) ? data.stuckSessions : [];
    const abandoned = data.abandonedSessions24h || 0;
    const sparks = data.sparks || {};
    const inv = data.inventory || {};
    const subjects24h = Array.isArray(data.sessionsBySubject24h) ? data.sessionsBySubject24h : [];

    /* ── alerts section ────────────────────────────────────────── */
    let alertsHtml = '';
    const hasBanned = bannedCount > 0;
    const hasAbandoned = abandoned > 0;
    const hasStuck = stuck.length > 0;

    if (hasBanned || hasAbandoned || hasStuck) {
      const bannedCard = hasBanned ? `
        <div class="ov-card danger" style="grid-column: span 2; padding-bottom: 14px">
          <div class="ov-card-icon"><i data-lucide="user-x" style="width:18px;height:18px"></i></div>
          <div class="ov-card-val">${bannedCount}</div>
          <div class="ov-card-label" style="margin-bottom: 10px">Заблокированы за неделю</div>
          <div class="ov-banned-list">
            ${data.bannedThisWeek.map(function (u) {
              return '<div class="ov-banned-row">' +
                '<span class="ov-bn-name">' + e(u.name || '—') + '</span>' +
                '<span class="ov-bn-email">' + e(u.email || '') + '</span>' +
                '<span class="ov-bn-date">' + fmtBannedDate(u.banned_at) + '</span>' +
                '</div>';
            }).join('')}
          </div>
        </div>` : '';

      const abandonedCard = hasAbandoned ? `
        <div class="ov-card warn">
          <div class="ov-card-icon"><i data-lucide="alert-triangle" style="width:18px;height:18px"></i></div>
          <div class="ov-card-val">${abandoned}</div>
          <div class="ov-card-label">Брошено сессий за 24ч</div>
        </div>` : '';

      const stuckCard = hasStuck ? `
        <div class="ov-card warn" style="padding-bottom: 14px">
          <div class="ov-card-icon"><i data-lucide="clock-alert" style="width:18px;height:18px"></i></div>
          <div class="ov-card-val">${stuck.length}</div>
          <div class="ov-card-label" style="margin-bottom: 10px">Сессий висят &gt;1ч</div>
          <div class="ov-stuck-list">
            ${stuck.map(function (st) {
              return '<div class="ov-stuck-row">' +
                '<span class="ov-st-name">' + e(st.user_name || '—') + '</span>' +
                '<span class="ov-st-subj">' + e(st.subject_name || '—') + '</span>' +
                '<span class="ov-st-since">' + fmtFinished(st.started_at) + '</span>' +
                '</div>';
            }).join('')}
          </div>
        </div>` : '';

      alertsHtml = `
        <div class="ov-section-title">Требует внимания</div>
        <div class="ov-grid">${bannedCard}${abandonedCard}${stuckCard}</div>`;
    }

    /* ── inventory section ─────────────────────────────────────── */
    const invHtml = `
      <div class="ov-section-title">Контент проекта</div>
      <div class="ov-inv-grid">
        <div class="ov-inv-item"><span class="ov-inv-n">${inv.questions != null ? inv.questions : 0}</span><span class="ov-inv-l">вопросов</span></div>
        <div class="ov-inv-item"><span class="ov-inv-n">${inv.tests != null ? inv.tests : 0}</span><span class="ov-inv-l">тестов</span></div>
        <div class="ov-inv-item"><span class="ov-inv-n">${inv.courses != null ? inv.courses : 0}</span><span class="ov-inv-l">курсов</span></div>
        <div class="ov-inv-item"><span class="ov-inv-n">${inv.classes != null ? inv.classes : 0}</span><span class="ov-inv-l">классов</span></div>
      </div>`;

    /* ── subject bar ───────────────────────────────────────────── */
    const subjHtml = `
      <div class="ov-section-title">По предметам (24ч)</div>
      ${renderSubjectBar(subjects24h)}`;

    /* ── results tables ────────────────────────────────────────── */
    const topTableHtml = top.length
      ? `<table class="ov-top-table">
          <thead><tr><th>Ученик</th><th>Предмет</th><th>Счёт</th><th>%</th><th>Завершён</th></tr></thead>
          <tbody>${renderSessionRows(top, e)}</tbody>
        </table>`
      : '<div class="ov-empty">Нет завершённых сессий за 24ч</div>';

    const worstTableHtml = worst.length
      ? `<table class="ov-top-table">
          <thead><tr><th>Ученик</th><th>Предмет</th><th>Счёт</th><th>%</th><th>Завершён</th></tr></thead>
          <tbody>${renderSessionRows(worst, e)}</tbody>
        </table>`
      : '<div class="ov-empty">Нет завершённых сессий за 24ч</div>';

    const tsText = _lastLoadTs ? fmtAgo(_lastLoadTs) : 'только что';

    el.innerHTML = `
      <div class="ov-header">
        <div class="ov-section-title">Активность за 24 часа</div>
        <div class="ov-refresh">
          <span class="ov-refresh-ts" id="ov-ts">${tsText}</span>
          <button class="ov-refresh-btn" onclick="AdminSections.overview.reload()" title="Обновить">
            <i data-lucide="refresh-cw" style="width:14px;height:14px"></i>
          </button>
        </div>
      </div>
      <div class="ov-grid ov-grid-main">
        <div class="ov-card hero" style="--ov-top:var(--violet)">
          <div class="ov-card-icon" style="background:rgba(155,93,229,0.1);color:var(--violet)"><i data-lucide="play-circle" style="width:24px;height:24px"></i></div>
          <div class="ov-card-val" style="color:var(--violet)">${fmtNum(data.newSessions24h)}</div>
          <div class="ov-card-label">Сессий запущено</div>
          <div class="ov-card-spark">${renderSparkline(sparks.sessions, 'var(--violet)')}</div>
        </div>
        <div class="ov-card" style="--ov-top:var(--cyan)">
          <div class="ov-card-icon" style="background:rgba(6,214,224,0.1);color:var(--cyan)"><i data-lucide="user-plus" style="width:18px;height:18px"></i></div>
          <div class="ov-card-val" style="color:var(--cyan)">${fmtNum(data.newUsers24h)}</div>
          <div class="ov-card-label">Новых регистраций</div>
          <div class="ov-card-spark">${renderSparkline(sparks.users, 'var(--cyan)')}</div>
        </div>
        <div class="ov-card" style="--ov-top:var(--green)">
          <div class="ov-card-icon" style="background:rgba(6,214,100,0.1);color:var(--green)"><i data-lucide="activity" style="width:18px;height:18px"></i></div>
          <div class="ov-card-val" style="color:var(--green)">${fmtNum(data.activeUsers24h)}</div>
          <div class="ov-card-label">Активных юзеров</div>
          <div class="ov-card-spark">${renderSparkline(sparks.active, 'var(--green)')}</div>
        </div>
        <div class="ov-card" style="--ov-top:var(--amber)">
          <div class="ov-card-icon" style="background:rgba(255,179,71,0.12);color:var(--amber)"><i data-lucide="users" style="width:18px;height:18px"></i></div>
          <div class="ov-card-val" style="color:var(--amber)">${fmtNum(data.classesTotal)}</div>
          <div class="ov-card-label">Всего классов</div>
        </div>
      </div>

      ${alertsHtml}
      ${invHtml}
      ${subjHtml}

      <div class="ov-results-grid" style="margin-top: 28px">
        <div>
          <div class="ov-section-title" style="margin-top:0">Топ-5 сегодня</div>
          ${topTableHtml}
        </div>
        <div>
          <div class="ov-section-title" style="margin-top:0">Худшие 5 сегодня</div>
          ${worstTableHtml}
        </div>
      </div>

      <div class="ov-section-title">Быстрый переход</div>
      <div class="ov-quick-grid">
        <button class="ov-quick-btn" data-go="#users">
          <i data-lucide="users"></i> Все пользователи
        </button>
        <button class="ov-quick-btn" data-go="#sessions">
          <i data-lucide="clock"></i> Все сессии
        </button>
        <button class="ov-quick-btn" data-go="#tests">
          <i data-lucide="clipboard-list"></i> Создать тест
        </button>
        <button class="ov-quick-btn" data-go="#sublog">
          <i data-lucide="file-text"></i> Audit log
        </button>
      </div>
    `;

    /* ── wire quick-links via event delegation ───────────────── */
    el.querySelectorAll('.ov-quick-btn[data-go]').forEach(function (btn) {
      btn.addEventListener('click', function () { navigateTo(btn.dataset.go); });
    });

    if (window.lucide) lucide.createIcons({ nodes: [el] });
  }

  async function load() {
    const el = document.getElementById('overview-content');
    if (!el) return;
    renderSkeleton(el);
    try {
      const data = await LS.adminGetOverview();
      _lastLoadTs = Date.now();
      render(data);
      startTsInterval();
    } catch (e) {
      LS.state.error(el, e, () => load());
    }
  }

  window.AdminSections = window.AdminSections || {};
  window.AdminSections.overview = {
    init: async () => { if (inited) return; inited = true; await load(); },
    reload: load,
  };
})();
