/* ============================================================
   screens.jsx — widgets + full screens. Depends on ui.jsx, data.jsx
   ============================================================ */
const { useState: useS, useEffect: useE, useMemo } = React;

const TYPE_LABEL = { A: 'Накопительный', B: 'Год к году', C: 'Каталог', D: 'Подписочный' };
const TYPE_SHORT = { A: 'Накопит.', B: 'Год/год', C: 'Каталог', D: 'Подписки' };

/* ===================== DASHBOARD WIDGETS (R13–R16) ===================== */

function WidgetA({ s, onOpen }) { // R13 накопительный · 12 мес · без сравнения
  return (
    <div className={'card card--accent' + (onOpen ? ' card--tap' : '')} onClick={onOpen}>
      <div className="wh">
        <div><h3 className="wh__name">{s.name}</h3><p className="wh__period">{s.period}</p></div>
        <span className="wh__type">A · {TYPE_SHORT.A}</span>
      </div>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 16, marginTop: 16 }}>
        <div className="metric">
          <span className="metric__value metric__value--violet">{fmt(s.orders)}</span>
          <span className="metric__caption">оплаченных заказов</span>
        </div>
        <MoneyStack sums={s.sums} small />
      </div>
      {onOpen && (
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 14, paddingTop: 12, borderTop: '1px solid var(--hairline)', color: 'var(--violet)', fontSize: 13, fontWeight: 700 }}>
          <span>Открыть список мероприятий</span>{I.chevR({ width: 18, height: 18 })}
        </div>
      )}
    </div>
  );
}

function WidgetB({ s, onOpen }) { // R14 серия год-к-году · 5 лет · текущий выделен · B-7 (a) — клик → список
  const max = Math.max(...s.years.map(y => y.orders));
  return (
    <div className={'card' + (onOpen ? ' card--tap' : '')} onClick={onOpen}>
      <div className="wh">
        <div><h3 className="wh__name">{s.name}</h3><p className="wh__period">{s.period}</p></div>
        <span className="wh__type">B · {TYPE_SHORT.B}</span>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 13, marginTop: 16 }}>
        {s.years.map(y => (
          <div key={y.year}>
            <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 10, marginBottom: 5 }}>
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 7 }}>
                <b style={{ fontSize: 14, fontWeight: 700, color: y.current ? 'var(--violet)' : 'var(--ink)', fontVariantNumeric: 'tabular-nums' }}>{y.year}</b>
                {y.current && <span style={{ fontSize: 9, fontWeight: 700, letterSpacing: '.08em', textTransform: 'uppercase', color: 'var(--violet)', background: 'rgba(139,127,240,.14)', borderRadius: 999, padding: '2px 7px' }}>сейчас</span>}
              </span>
              <span style={{ display: 'flex', alignItems: 'baseline', gap: 10 }}>
                <span style={{ fontSize: 13, fontWeight: 700, color: 'var(--violet)', fontVariantNumeric: 'tabular-nums' }}>{fmt(y.sums.rub)} ₽</span>
                {y.sums.eur != null && <span style={{ fontSize: 12, fontWeight: 700, color: 'var(--emerald)', fontVariantNumeric: 'tabular-nums' }}>{fmt(y.sums.eur)} €</span>}
              </span>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr auto', gap: 10, alignItems: 'center' }}>
              <span className="bar__track"><span className="bar__fill" style={{ width: (y.orders / max * 100) + '%', background: y.current ? 'var(--violet)' : 'var(--violet-4)' }}></span></span>
              <span style={{ fontSize: 11.5, color: 'var(--ink-3)', fontVariantNumeric: 'tabular-nums', minWidth: 56, textAlign: 'right' }}>{fmt(y.orders)} зак.</span>
            </div>
          </div>
        ))}
      </div>
      {onOpen && (
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 14, paddingTop: 12, borderTop: '1px solid var(--hairline)', color: 'var(--violet)', fontSize: 13, fontWeight: 700 }}>
          <span>Открыть список мероприятий</span>{I.chevR({ width: 18, height: 18 })}
        </div>
      )}
    </div>
  );
}

function WidgetC({ s, onOpen }) { // R15 каталог · нажатие → список (R2)
  return (
    <div className="card card--accent-emerald card--tap" onClick={onOpen}>
      <div className="wh">
        <div><h3 className="wh__name">{s.name}</h3><p className="wh__period">{s.period}</p></div>
        <span className="wh__type">C · {TYPE_SHORT.C}</span>
      </div>
      <div style={{ display: 'flex', gap: 10, marginTop: 16, marginBottom: 14 }}>
        <div className="metric metric--boxed-soft" style={{ flex: 1 }}>
          <span className="metric__value" style={{ fontSize: 26 }}>{s.eventsCount}</span>
          <span className="metric__caption">мероприятий за период</span>
        </div>
        <div className="metric metric--boxed-soft" style={{ flex: 1 }}>
          <span className="metric__value metric__value--violet" style={{ fontSize: 26 }}>{fmt(s.orders)}</span>
          <span className="metric__caption">оплаченных заказов</span>
        </div>
      </div>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 12 }}>
        <div style={{ minWidth: 0, flex: '1 1 auto' }}>
          <div className="eyebrow" style={{ marginBottom: 4 }}>Последнее мероприятие</div>
          <div className="row__title" style={{ fontSize: 13, fontWeight: 600 }}>{s.lastEvent}</div>
        </div>
        <MoneyStack sums={s.sums} small />
      </div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 14, paddingTop: 12, borderTop: '1px solid var(--hairline)', color: 'var(--violet)', fontSize: 13, fontWeight: 700 }}>
        <span>Открыть список мероприятий</span>{I.chevR({ width: 18, height: 18 })}
      </div>
    </div>
  );
}

function WidgetD({ s, onOpen, deltaMode }) { // R16 подписочный + R17 две дельты
  let mom = s.deltas.mom, yoy = s.deltas.yoy;
  let activeSubs = s.activeSubs, monthOrders = s.monthOrders, monthSum = s.monthSum;
  if (deltaMode === 'dash') { mom = { na: true, base: 'к апрелю 2026' }; yoy = { na: true, base: 'к маю 2025' }; }
  if (deltaMode === 'zero') { mom = { fromZero: true, abs: 47, base: 'к апрелю 2026' }; yoy = { na: true, base: 'к маю 2025' }; }
  if (deltaMode === 'bothZero') {
    // R17 edge: обе метрики считаются, обе нулевые
    activeSubs = 0; monthOrders = 0; monthSum = { rub: 0, eur: null };
    mom = { bothZero: true, base: 'к апрелю 2026' };
    yoy = { bothZero: true, base: 'к маю 2025' };
  }
  return (
    <div className="card card--accent card--tap" onClick={onOpen}>
      <div className="wh">
        <div><h3 className="wh__name">{s.name}</h3><p className="wh__period">{s.period}</p></div>
        <span className="wh__type">D · {TYPE_SHORT.D}</span>
      </div>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 12, marginTop: 16 }}>
        <div className="metric">
          <span className="metric__value metric__value--violet">{fmt(activeSubs)}</span>
          <span className="metric__caption">активных подписок · сейчас</span>
        </div>
        <div style={{ textAlign: 'right', display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 2 }}>
          <div style={{ fontSize: 17, fontWeight: 700, color: 'var(--ink)', fontVariantNumeric: 'tabular-nums' }}>{fmt(monthOrders)} зак.</div>
          <div style={{ fontSize: 15, fontWeight: 700, color: 'var(--violet)', fontVariantNumeric: 'tabular-nums' }}>{fmt(monthSum.rub)} ₽</div>
          {monthSum.eur != null && (
            <div style={{ fontSize: 13.5, fontWeight: 700, color: 'var(--emerald)', fontVariantNumeric: 'tabular-nums' }}>{fmt(monthSum.eur)} €</div>
          )}
          <div style={{ fontSize: 10.5, color: 'var(--ink-3)' }}>за месяц</div>
        </div>
      </div>
      <div className="deltas">
        <Delta d={mom} /><Delta d={yoy} />
      </div>
    </div>
  );
}

/* ===================== DASHBOARD SCREEN (R1) ===================== */
function Dashboard({ scenario, nav }) {
  if (scenario === 'loading') return <div className="scroll"><div className="section-head"><h2>Разделы</h2></div><SkelCard /><div style={{ height: 14 }} /><SkelCard /></div>;
  if (scenario === 'emptySections')
    return <div className="scroll"><EmptyState title="Нет активных разделов" text="Разделы появятся, как только в каталоге зарегистрируются мероприятия с заполненными свойствами (суточный цикл)." /></div>;

  const stale = scenario === 'sourceError';
  const deltaMode = scenario === 'deltaDash' ? 'dash' : scenario === 'deltaZero' ? 'zero' : scenario === 'deltaBothZero' ? 'bothZero' : null;
  // R10 edge: виджет раздела с нулями (нет оплат в периоде) — не скрывается
  const widgetZero = scenario === 'widgetZero';
  const sectionA = widgetZero
    ? { ...SECTIONS[0], orders: 0, sums: { rub: 0, eur: null } }
    : SECTIONS[0];
  return (
    <div className="scroll">
      {stale && <Banner onRetry={() => {}}>Источник недоступен. Показаны <b>последние имеющиеся данные</b> от 12.06. </Banner>}
      {widgetZero && <Banner>Виджет раздела <b>Радаст Кипр</b> показан с нулями: за последние 12 месяцев оплаченных заказов нет (R10). Раздел не скрывается.</Banner>}
      <div className="section-head"><h2>Разделы</h2><span className="section-head__meta">в фикс. порядке</span></div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <WidgetA s={sectionA} onOpen={() => nav.toEvents(SECTIONS[0])} />
        <WidgetB s={SECTIONS[1]} onOpen={() => nav.toEvents(SECTIONS[1])} />
        <WidgetC s={SECTIONS[2]} onOpen={() => nav.toEvents(SECTIONS[2])} />
        <WidgetD s={SECTIONS[3]} deltaMode={deltaMode} onOpen={() => nav.toTab('subs')} />
      </div>
    </div>
  );
}

/* ===================== EVENTS LIST (R2 + R20 + R21) ===================== */
const PAGE = 20; // R21 default порция

function EventRow({ ev, onOpen, showSection }) {
  const multi = ev.sums.eur != null; // colour-code: includes € (EU layer) = emerald, ₽-only = violet
  const accent = multi ? 'var(--emerald)' : 'var(--violet)';
  const d = (s) => { const [y, m, day] = s.split('-'); return `${day}.${m}.${y.slice(2)}`; };
  return (
    <div className="row row--tap" style={{ '--accent': accent }} onClick={onOpen}>
      <div className="row__main">
        {showSection && ev.sectionName && <span className="row__section">{ev.sectionName}</span>}
        <p className="row__title">{ev.name}</p>
        <p className="row__sub">{d(ev.from)} — {d(ev.to)} · {ev.site}</p>
      </div>
      <div className="row__right">
        <span className="row__num row__num--count">{fmt(ev.orders)} зак.</span>
        <span className="row__num row__num--rub">{fmt(ev.sums.rub)} ₽</span>
        {/* B-6: резерв высоты — если € нет, отрисовать невидимый плейсхолдер той же высоты */}
        {multi
          ? <span className="row__num row__num--eur">{fmt(ev.sums.eur)} €</span>
          : <span className="row__num row__num--eur" style={{ visibility: 'hidden' }} aria-hidden="true">0 €</span>}
      </div>
    </div>
  );
}

function EventsList({ scenario, section, nav }) {
  const forceEmptySearch = scenario === 'emptySearch';
  const [q, setQ] = useS(forceEmptySearch ? 'квартет' : '');
  const [showFilter, setShowFilter] = useS(false);
  const [from, setFrom] = useS('');
  const [to, setTo] = useS('');
  const [shown, setShown] = useS(PAGE);

  // reset pagination when filter/search changes (R20 edge)
  useE(() => { setShown(PAGE); }, [q, from, to]);

  // B-7 (a) + общий список: источник определяется секцией; без секции — все мероприятия
  const all = !section
    ? ALL_EVENTS
    : section.id === 'radast-tv' ? RADAST_TV_EVENTS
    : section.id === 'radast-kipr' ? RADAST_KIPR_EVENTS
    : section.id === 'ozariny' ? OZARINY_EVENTS
    : ALL_EVENTS;
  const showSection = !section; // подпись раздела видна только в общем списке
  const filtered = useMemo(() => all.filter(ev => {
    if (q.trim() && !ev.name.toLowerCase().includes(q.trim().toLowerCase())) return false;
    if (from && ev.from < from) return false;
    if (to && ev.from > to) return false;
    return true;
  }), [q, from, to]);

  const hasFilter = q.trim() || from || to;

  if (scenario === 'loading')
    return <div className="scroll">{[0, 1, 2, 3, 4].map(i => <div key={i} className="row" style={{ '--accent': 'var(--surface-2)' }}><div style={{ flex: 1 }}><div className="skel skel-line" style={{ width: '70%' }} /><div className="skel skel-line" style={{ width: '40%', marginTop: 8 }} /></div></div>)}</div>;
  if (scenario === 'emptyEvents')
    return <div className="scroll"><EmptyState title="Нет мероприятий" text="В этом разделе пока нет мероприятий. Они появятся, как только в каталоге зарегистрируются товары с заполненными свойствами." /></div>;

  const visible = filtered.slice(0, shown);
  const remaining = filtered.length - shown;
  const nextChunk = Math.min(PAGE, remaining);

  return (
    <div className="scroll">
      {/* search + filter (R20) */}
      <div className="search-wrap">
        <div className="searchbar">
          {I.search()}
          <input value={q} onChange={e => setQ(e.target.value)} placeholder="Поиск по названию…" />
          {q && <button className="searchbar__clear" onClick={() => setQ('')}>{I.x()}</button>}
        </div>
        <button className={'filter-toggle' + (showFilter || from || to ? ' is-on' : '')} onClick={() => setShowFilter(v => !v)}>
          {I.sliders()} Фильтр по датам {(from || to) ? '· активен' : ''}
        </button>
        {showFilter && (
          <div className="filter-panel">
            <div className="field"><label>Дата от</label><input type="date" value={from} onChange={e => setFrom(e.target.value)} /></div>
            <div className="field"><label>Дата до</label><input type="date" value={to} onChange={e => setTo(e.target.value)} /></div>
          </div>
        )}
        {hasFilter && (
          <div className="applied-chips">
            {q.trim() && <span className="chip">«{q.trim()}»<button onClick={() => setQ('')}>{I.x()}</button></span>}
            {from && <span className="chip">от {from}<button onClick={() => setFrom('')}>{I.x()}</button></span>}
            {to && <span className="chip">до {to}<button onClick={() => setTo('')}>{I.x()}</button></span>}
          </div>
        )}
      </div>

      <div className="section-head">
        <h2>{hasFilter ? 'Результаты' : 'Все мероприятия'}</h2>
        <span className="section-head__meta">{filtered.length} мероприятий · свежие сверху</span>
      </div>

      {filtered.length === 0
        ? <EmptyState title="Ничего не найдено" text="По заданным условиям поиска и фильтра мероприятий нет. Измените запрос или диапазон дат." />
        : <>
            <div>{visible.map(ev => <EventRow key={ev.id} ev={ev} onOpen={() => nav.toCard(ev)} showSection={showSection} />)}</div>
            {remaining > 0 && (
              <button className="show-more" onClick={() => setShown(s => s + PAGE)}>
                <span className="show-more__main">Показать ещё {nextChunk}</span>
                <span className="show-more__count">показано {visible.length} из {filtered.length}</span>
              </button>
            )}
          </>}
    </div>
  );
}

/* ===================== EVENT CARD (R3) ===================== */
function BdRow({ seg, dotColor }) {
  const zero = seg.count === 0;
  const isEur = seg.cur === 'eur';
  const sumVal = isEur ? seg.sum.eur : seg.sum.rub;
  return (
    <div className="bd__row">
      <div className="bd__seg">
        <span className="bd__dot" style={{ background: dotColor }}></span>
        <span className="bd__seg__text">
          <span className="bd__name">{seg.name}{seg.retired && <span style={{ fontSize: 9, fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--amber)', background: 'rgba(224,166,89,.14)', borderRadius: 999, padding: '2px 6px', marginLeft: 7 }}>снят</span>}</span>
          {seg.site && <span className="bd__site" style={{ display: 'block' }}>{seg.site}</span>}
          {seg.retired && <span className="bd__site" style={{ display: 'block', color: 'var(--amber)' }}>снят с продажи · исторические оплаты</span>}
        </span>
      </div>
      <div className="bd__count">{fmt(seg.count)}<span className="bd__count-cap">зак.</span></div>
      <div className={'bd__sum ' + (zero ? 'bd__sum--zero' : isEur ? 'bd__sum--eur' : 'bd__sum--rub')}>
        {fmt(sumVal || 0)} {isEur ? '€' : '₽'}
      </div>
    </div>
  );
}

function EventCard({ scenario, event, nav }) {
  if (scenario === 'loading')
    return <div className="scroll"><SkelCard /><div style={{ height: 14 }} /><SkelCard /></div>;

  const ev = scenario === 'cardNoOrders' ? EVENT_CARD_EMPTY : (event && event.id === EVENT_CARD.id ? EVENT_CARD : EVENT_CARD);
  const noOrders = ev.totals.orders === 0;
  const violetTints = ['var(--violet)', 'var(--violet-2)', 'var(--violet-3)'];

  return (
    <div className="scroll">
      {/* full name — wraps, never truncated (DQ-5) */}
      <div style={{ padding: '4px 2px 14px' }}>
        <div className="eyebrow eyebrow--emerald" style={{ marginBottom: 8 }}>{ev.section}</div>
        <h2 style={{ fontSize: 20, fontWeight: 700, letterSpacing: '-.01em', lineHeight: 1.28, margin: '0 0 8px', color: 'var(--ink)' }}>{ev.name}</h2>
        <div style={{ fontSize: 12.5, color: 'var(--ink-3)', fontFamily: 'var(--font-mono)' }}>{ev.range}</div>
      </div>

      {noOrders && <Banner>Оплаченных заказов пока нет — все разрезы показаны нулями (R10). Карточка остаётся доступной.</Banner>}

      {/* totals — two currencies STACKED (R3, DQ-4: стопкой, без колонок) */}
      <div className="section-head"><h2>Итог</h2><span className="section-head__meta">валюты раздельно, стопкой (DQ-4)</span></div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        <div className="metric metric--boxed-soft" style={{ width: '100%' }}>
          <span className="metric__value" style={{ fontSize: 22, color: 'var(--ink)' }}>{fmt(ev.totals.orders)}</span>
          <span className="metric__caption">оплаченных заказов</span>
        </div>
        <div className="metric metric--boxed" style={{ width: '100%', borderLeft: '3px solid var(--violet)' }}>
          <span className="metric__value metric__value--violet" style={{ fontSize: 24 }}>{fmt(ev.totals.rub)} ₽</span>
          <span className="metric__caption">Всего · рубли</span>
        </div>
        {ev.totals.eur != null && (
          <div className="metric metric--boxed" style={{ width: '100%', borderLeft: '3px solid var(--emerald)', background: 'var(--mint)' }}>
            <span className="metric__value metric__value--emerald" style={{ fontSize: 24 }}>{fmt(ev.totals.eur)} €</span>
            <span className="metric__caption">Всего · евро</span>
          </div>
        )}
      </div>

      {/* breakdown: by sector */}
      <div className="section-head"><h2>По ценовому сектору</h2></div>
      <div className="bd">
        <div className="bd__head"><span className="eyebrow eyebrow--violet">Сектор</span><span className="eyebrow" style={{ fontSize: 9 }}>заказы · сумма</span></div>
        {ev.bySector.map((seg, i) => <BdRow key={i} seg={seg} dotColor={violetTints[i % 3]} />)}
      </div>

      {/* breakdown: by day — для многодневных мероприятий (R3) */}
      {ev.byDay && ev.byDay.length > 0 && (
        <>
          <div className="section-head"><h2>По дням</h2><span className="section-head__meta">участники по билету «на день»</span></div>
          <div className="bd">
            <div className="bd__head"><span className="eyebrow eyebrow--violet">День</span><span className="eyebrow" style={{ fontSize: 9 }}>участников</span></div>
            {ev.byDay.map((d, i) => (
              <div className="bd__row" key={d.date} style={{ gridTemplateColumns: 'minmax(0, 1fr) auto' }}>
                <div className="bd__seg">
                  <span className="bd__dot" style={{ background: 'var(--violet)' }}></span>
                  <span className="bd__seg__text">
                    <span className="bd__name">{d.label}</span>
                  </span>
                </div>
                <div className="bd__count">{fmt(d.participants)}<span className="bd__count-cap">уч.</span></div>
              </div>
            ))}
          </div>
        </>
      )}

      {/* breakdown: by site (mixed currency) */}
      <div className="section-head"><h2>По сайту</h2></div>
      <div className="bd">
        <div className="bd__head"><span className="eyebrow eyebrow--violet">Сайт</span><span className="eyebrow" style={{ fontSize: 9 }}>заказы · сумма</span></div>
        {ev.bySite.map((seg, i) => <BdRow key={i} seg={seg} dotColor={seg.cur === 'eur' ? 'var(--emerald)' : violetTints[i % 3]} />)}
        <div className="bd__row bd__row--total">
          <div className="bd__total-label">Всего</div>
          <div className="bd__count">{fmt(ev.totals.orders)}<span className="bd__count-cap">зак.</span></div>
          <div style={{ textAlign: 'right' }}>
            <div className="bd__sum bd__sum--rub">{fmt(ev.totals.rub)} ₽</div>
            {ev.totals.eur != null && <div className="bd__sum bd__sum--eur" style={{ marginTop: 2 }}>{fmt(ev.totals.eur)} €</div>}
          </div>
        </div>
      </div>

      <Conclusion lead="Разрез:" neutral={noOrders}>
        {noOrders
          ? 'товары привязаны, продаж ещё нет. Цифры появятся после первой оплаты — пересчёт в суточном цикле.'
          : 'рубли (ИП + РТВ) и евро (Озаригн-Глобал) показаны раздельно. Снятый с продажи товар остаётся в разрезе с историческими цифрами (R3).'}
      </Conclusion>
    </div>
  );
}

/* ===================== SUBSCRIPTIONS (R18 + R17) ===================== */
function TariffRow({ t }) {
  return (
    <div className="bd__row" style={{ gridTemplateColumns: '1fr auto auto auto' }}>
      <div className="bd__seg" style={{ flexDirection: 'column', alignItems: 'flex-start', gap: 2 }}>
        <span className="bd__name" style={{ whiteSpace: 'normal' }}>
          {t.name}
          {t.retired && <span style={{ fontSize: 9, fontWeight: 700, letterSpacing: '.06em', textTransform: 'uppercase', color: 'var(--ink-3)', background: 'var(--surface-2)', borderRadius: 999, padding: '2px 6px', marginLeft: 7 }}>снят</span>}
        </span>
        <span className="bd__site">{t.price}</span>
      </div>
      <div className="bd__count" style={{ minWidth: 46 }}>{fmt(t.active)}<span className="bd__count-cap">активн.</span></div>
      <div className="bd__count" style={{ minWidth: 40 }}>{fmt(t.orders)}<span className="bd__count-cap">зак./мес</span></div>
      <div style={{ minWidth: 90, textAlign: 'right', display: 'flex', flexDirection: 'column', gap: 2, alignItems: 'flex-end' }}>
        <div className={'bd__sum ' + (t.sum.rub === 0 ? 'bd__sum--zero' : 'bd__sum--rub')}>{fmt(t.sum.rub)} ₽</div>
        {t.sum.eur != null && <div className="bd__sum bd__sum--eur">{fmt(t.sum.eur)} €</div>}
      </div>
    </div>
  );
}

function Subscriptions({ scenario, nav }) {
  if (scenario === 'loading') return <div className="scroll"><SkelCard /><div style={{ height: 14 }} /><SkelCard /></div>;
  const s = SECTIONS[3];
  const deltaMode = scenario === 'deltaDash' ? 'dash' : scenario === 'deltaZero' ? 'zero' : scenario === 'deltaBothZero' ? 'bothZero' : null;
  const stale = scenario === 'sourceError';
  return (
    <div className="scroll">
      {stale && <Banner onRetry={() => {}}>Источник недоступен. Показаны <b>последние имеющиеся данные</b>.</Banner>}
      <div className="section-head"><h2>Подписочные разделы</h2><span className="section-head__meta">тип D</span></div>
      <WidgetD s={s} deltaMode={deltaMode} onOpen={() => {}} />

      <div className="section-head"><h2>Разбивка по тарифам</h2><span className="section-head__meta">май 2026</span></div>
      <div className="bd">
        <div className="bd__head"><span className="eyebrow eyebrow--violet">Тариф</span><span className="eyebrow" style={{ fontSize: 9 }}>подписки · заказы · сумма</span></div>
        {TARIFFS.map(t => <TariffRow key={t.id} t={t} />)}
        <div className="bd__row bd__row--total" style={{ gridTemplateColumns: '1fr auto auto auto' }}>
          <div className="bd__total-label">Всего</div>
          <div className="bd__count" style={{ minWidth: 46 }}>{fmt(TARIFFS_TOTAL.active)}<span className="bd__count-cap">активн.</span></div>
          <div className="bd__count" style={{ minWidth: 40 }}>{fmt(TARIFFS_TOTAL.orders)}<span className="bd__count-cap">зак./мес</span></div>
          <div style={{ minWidth: 90, textAlign: 'right', display: 'flex', flexDirection: 'column', gap: 2, alignItems: 'flex-end' }}>
            <div className="bd__sum bd__sum--rub">{fmt(TARIFFS_TOTAL.sum.rub)} ₽</div>
            {TARIFFS_TOTAL.sum.eur != null && <div className="bd__sum bd__sum--eur">{fmt(TARIFFS_TOTAL.sum.eur)} €</div>}
          </div>
        </div>
      </div>
      <Conclusion lead="Каталог зафиксирован:" neutral>
        новые тарифы добавляются вручную (R18). Снятый тариф «На 3 месяца» остаётся в списке, пока есть активные подписки.
      </Conclusion>
    </div>
  );
}

/* ===================== MENU ===================== */
function Menu({ notif }) {
  return (
    <div className="scroll">
      <div className="menu-profile">
        <div className="menu-avatar">АС</div>
        <div>
          <div style={{ fontSize: 16, fontWeight: 700 }}>Алексей Соколов</div>
          <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>Собственник · группа «Статистика»</div>
        </div>
      </div>
      <div className="menu-card">
        <a className="menu-item menu-item--link" href="https://example.bitrix.local/bitrix/admin/iblock_list_admin.php?IBLOCK_ID=stats_mapping" target="_blank" rel="noopener">
          {I.bell()}<span className="menu-item__txt">Требуют сверки</span>
          {notif ? <span className="tab__badge" style={{ position: 'static', transform: 'none' }}>{notif}</span> : <span className="menu-item__val">нет</span>}
          {I.chevR({ width: 16, height: 16, style: { color: 'var(--ink-3)' } })}
        </a>
        <div className="menu-item">{I.user()}<span className="menu-item__txt">Профиль и доступ</span>{I.chevR({ width: 16, height: 16, style: { color: 'var(--ink-3)' } })}</div>
        <div className="menu-item">{I.info()}<span className="menu-item__txt">Версия приложения</span><span className="menu-item__val">v1.0 · build 26.06</span></div>
        <div className="menu-item" style={{ color: 'var(--rose)' }}>{I.out({ style: { color: 'var(--rose)' } })}<span className="menu-item__txt">Выйти</span></div>
      </div>
      <Conclusion lead="Уведомления R22:" neutral>
        «Требуют сверки» — ссылка в админку Битрикса, на список товаров, требующих ручного маппинга. Отдельного интерфейса в PWA нет.
      </Conclusion>
      <MadeIn />
    </div>
  );
}

/* ===================== ACCESS DENIED (R8) ===================== */
function AccessDenied() {
  return (
    <div className="denied">
      <div className="denied__badge">{I.lock()}</div>
      <h2 className="denied__title">Доступ закрыт</h2>
      <p className="denied__text">Ваша учётная запись не входит ни в одну из групп, которым разрешён доступ к статистике. Цифры не отдаются.</p>
      <p className="denied__text" style={{ color: 'var(--ink-3)', fontSize: 12.5 }}>Если доступ нужен — обратитесь к администратору, чтобы вас добавили в разрешённую группу Битрикса. Доступ появится при следующем входе.</p>
      <p className="denied__meta">проверка группы · при авторизации · R8</p>
    </div>
  );
}

Object.assign(window, { Dashboard, EventsList, EventCard, Subscriptions, Menu, AccessDenied, TYPE_LABEL });
