function Features() {
  const [tab, setTab] = React.useState(0);
  const [isMobile, setIsMobile] = React.useState(
    typeof window !== 'undefined' && window.matchMedia('(max-width: 860px)').matches
  );
  const [paused, setPaused] = React.useState(false);
  // nonce — увеличивается при ручном выборе, чтобы useEffect и анимация
  // прогресс-бара точно перезапустились (даже если клик по уже активной вкладке).
  const [pickNonce, setPickNonce] = React.useState(0);

  React.useEffect(() => {
    if (typeof window === 'undefined') return;
    const mq = window.matchMedia('(max-width: 860px)');
    const handler = (e) => setIsMobile(e.matches);
    mq.addEventListener ? mq.addEventListener('change', handler) : mq.addListener(handler);
    return () => {
      mq.removeEventListener ? mq.removeEventListener('change', handler) : mq.removeListener(handler);
    };
  }, []);

  // JS-driven прогресс-бар: width 0→100% за 15s через CSS transition.
  // Это надёжнее CSS-анимаций при ре-маунте span в iOS Safari.
  const [pct, setPct] = React.useState(0);
  const [withTransition, setWithTransition] = React.useState(false);

  React.useEffect(() => {
    if (paused) return;
    // Шаг 1: мгновенно сбросить ширину на 0 БЕЗ transition
    setWithTransition(false);
    setPct(0);
    // Шаг 2: через 2 кадра включить transition и установить 100% — браузер
    // обработает интерполяцию width 0→100% за 15s.
    let f2 = null;
    const f1 = requestAnimationFrame(() => {
      f2 = requestAnimationFrame(() => {
        setWithTransition(true);
        setPct(100);
      });
    });
    // Шаг 3: через 15s переключить tab на следующий
    const id = setTimeout(() => setTab(t => (t + 1) % 4), 15000);
    return () => {
      cancelAnimationFrame(f1);
      if (f2) cancelAnimationFrame(f2);
      clearTimeout(id);
    };
  }, [tab, paused, pickNonce]);

  // Manual tab pick — гарантированный рестарт через pickNonce.
  const pickTab = (i) => {
    setPaused(false);
    setTab(i);
    setPickNonce(n => n + 1);
  };

  const tabs = [
    {
      key: 'collect',
      label: 'Получение отзывов',
      sub: 'Сбор сигналов',
      icon: 'inbox',
      title: 'Один канал для всех голосов',
      desc: 'Подключите 40+ источников за несколько кликов — от App Store и звонков в поддержку до закрытых каналов в Telegram и опросов после оплаты. Фидли нормализует язык, дедуплицирует ботов и сохраняет контекст: тариф, версию приложения, сегмент.',
      bullets: ['App Store, Google Play, RuStore', 'Zendesk, Intercom, Usedesk, Юздеск', 'Звонки и расшифровки (Asterisk, Mango)', 'Опросы NPS / CSAT / CES', 'Соцсети, отзовики, маркетплейсы'],
      mock: <CollectMock />,
    },
    {
      key: 'classify',
      label: 'Разметка и темы',
      sub: 'Авто-таксономия',
      icon: 'tag',
      title: 'Таксономия, которая обучается на ваших данных',
      desc: 'Никаких заранее заданных тегов. Фидли строит дерево тем из того, что клиенты говорят именно вам — и достраивает его, когда появляются новые продукты, регионы или сегменты. Качество разметки видно цифрой, а не на глаз.',
      bullets: ['Авто-таксономия за 48 часов', 'Эталонная точность F1 = 0.91', 'Свои правила и алиасы', 'Связь темы → JIRA / Linear / YouTrack', 'История изменений по каждой теме'],
      mock: <ClassifyMock />,
    },
    {
      key: 'analyze',
      label: 'Анализ и инсайты',
      sub: 'ИИ-обоснование',
      icon: 'spark',
      title: 'Спросите данные на русском',
      desc: 'Найдите всплески, копайте до конкретной цитаты, сравните сегменты. Фидли отвечает ссылками на исходные сообщения — никаких галлюцинаций без источника. Подписки на темы шлют алёрты в Slack или Mattermost.',
      bullets: ['ИИ-поиск с цитатами', 'Срезы по тарифу, городу, версии', 'Алёрты при росте темы >X%', 'Сравнение релизов и А/Б', 'Экспорт в Notion и Confluence'],
      mock: <AnalyzeMock />,
    },
    {
      key: 'act',
      label: 'Дашборды и действия',
      sub: 'От цифры — к тикету',
      icon: 'chart',
      title: 'Дашборды, которые приводят к решениям',
      desc: 'Красивые живые дашборды по темам, сегментам и релизам — с возможностью одним кликом превратить инсайт в задачу для продукта или бриф для маркетинга. Каждая задача несёт репрезентативные цитаты: продакт видит не цифру, а голоса клиентов.',
      bullets: ['Готовые дашборды: тон, темы, релизы', 'Срезы по тарифу, сегменту, городу', 'Двусторонняя синхронизация с JIRA', 'Шаблоны брифов для PM и CX', 'Еженедельный дайджест для CEO'],
      mock: <DashboardMock />,
    },
  ];
  const cur = tabs[tab];

  return (
    <section id="features" style={{
      padding: '110px 0',
      background: 'var(--ink)',
      color: 'var(--bg)',
      borderRadius: 0,
    }}>
      <style>{`
        @keyframes features-progress {
          from { width: 0%; }
          to   { width: 100%; }
        }
      `}</style>
      <div className="container">
        <div style={{ maxWidth: 920, marginBottom: 56 }}>
          <h2 className="display" style={{ fontSize: 56, color: '#fff', fontWeight: 600, lineHeight: 1.08 }}>
            <span style={{ whiteSpace: 'nowrap' }}>Четыре шага от сырого отзыва</span><br />
            <span style={{ color: 'rgba(255,255,255,0.55)' }}>до понятного действия</span>
          </h2>
        </div>

        {/* tabs: desktop = grid of 4 columns, mobile = horizontal accordion */}
        {isMobile ? (
          <div style={{
            display: 'flex', gap: 8, height: 140,
            marginTop: 4, marginBottom: 8,
          }}>
            {tabs.map((t, i) => {
              const active = tab === i;
              return (
                <button
                  key={t.key}
                  onClick={() => pickTab(i)}
                  style={{
                    flex: active ? '5 1 0' : '1 1 0',
                    minWidth: 0,
                    background: active ? 'rgba(122,96,255,0.10)' : 'rgba(245,243,238,0.04)',
                    border: '1px solid ' + (active ? 'rgba(122,96,255,0.5)' : 'rgba(245,243,238,0.12)'),
                    borderRadius: 14,
                    padding: active ? '16px 16px' : '14px 8px',
                    textAlign: 'left',
                    color: active ? '#fff' : 'rgba(245,243,238,0.55)',
                    transition: 'flex 0.5s cubic-bezier(0.4, 0, 0.2, 1), background 0.3s, border-color 0.3s, padding 0.3s',
                    overflow: 'hidden',
                    display: 'flex', flexDirection: 'column',
                    justifyContent: 'space-between',
                    alignItems: active ? 'flex-start' : 'center',
                    cursor: 'pointer',
                  }}
                >
                  <div style={{
                    display: 'flex', alignItems: 'center', gap: 8,
                    width: '100%',
                  }}>
                    <span className="mono" style={{
                      fontSize: 11,
                      color: active ? 'var(--accent)' : 'rgba(245,243,238,0.6)',
                      letterSpacing: '0.06em',
                    }}>0{i + 1}</span>
                    {active && (
                      <span style={{
                        flex: 1, height: 2, position: 'relative',
                        background: 'rgba(245,243,238,0.12)', borderRadius: 1, overflow: 'hidden',
                      }}>
                        <span
                          style={{
                            position: 'absolute', top: 0, left: 0, bottom: 0,
                            width: `${pct}%`,
                            background: 'linear-gradient(90deg, var(--accent), #b997ff)',
                            transition: withTransition ? 'width 15s linear' : 'none',
                          }}
                        />
                      </span>
                    )}
                    {active && <TabIcon name={t.icon} color="#fff" />}
                  </div>

                  {active ? (
                    <div style={{ width: '100%' }}>
                      <div className="display" style={{
                        fontSize: 18, fontWeight: 600, lineHeight: 1.15,
                        letterSpacing: '-0.01em', color: '#fff',
                        whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                      }}>{t.label}</div>
                      <div style={{
                        fontSize: 12, marginTop: 4,
                        color: 'rgba(255,255,255,0.6)',
                        whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                      }}>{t.sub}</div>
                    </div>
                  ) : (
                    <TabIcon name={t.icon} color="rgba(245,243,238,0.45)" />
                  )}
                </button>
              );
            })}
          </div>
        ) : (
          <div style={{
            display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)',
            borderTop: '1px solid rgba(245,243,238,0.18)',
            borderBottom: '1px solid rgba(245,243,238,0.18)',
          }}>
            {tabs.map((t, i) => {
              const active = tab === i;
              return (
                <button key={t.key} onClick={() => setTab(i)} style={{
                  padding: '22px 18px 22px 18px',
                  textAlign: 'left',
                  borderRight: i < 3 ? '1px solid rgba(245,243,238,0.18)' : 'none',
                  position: 'relative',
                  color: active ? 'var(--bg)' : 'rgba(245,243,238,0.55)',
                  background: active ? 'rgba(122,96,255,0.06)' : 'transparent',
                  transition: 'color 0.25s, background 0.25s',
                }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10 }}>
                    <div className="mono" style={{
                      fontSize: 11, opacity: active ? 1 : 0.6,
                      color: active ? 'var(--accent)' : 'inherit',
                      letterSpacing: '0.06em',
                    }}>0{i + 1}</div>
                    {active ? (
                      <span style={{
                        flex: 1, height: 2, position: 'relative',
                        background: 'rgba(245,243,238,0.12)', borderRadius: 1, overflow: 'hidden',
                      }}>
                        <span
                          style={{
                            position: 'absolute', top: 0, left: 0, bottom: 0,
                            width: `${pct}%`,
                            background: 'linear-gradient(90deg, var(--accent), #b997ff)',
                            transition: withTransition ? 'width 15s linear' : 'none',
                          }}
                        />
                      </span>
                    ) : (
                      <span style={{ flex: 1, height: 1, background: 'rgba(245,243,238,0.12)' }} />
                    )}
                    <TabIcon name={t.icon} color={active ? 'var(--bg)' : 'rgba(245,243,238,0.4)'} />
                  </div>
                  <div className="display" style={{
                    fontSize: 19, fontWeight: 600, lineHeight: 1.15,
                    letterSpacing: '-0.01em',
                    color: active ? '#fff' : 'rgba(255,255,255,0.55)',
                  }}>{t.label}</div>
                  <div style={{
                    fontSize: 12, marginTop: 6,
                    color: active ? 'rgba(255,255,255,0.7)' : 'rgba(255,255,255,0.4)',
                  }}>{t.sub}</div>
                  {active && <div style={{
                    position: 'absolute', left: 0, right: 0, bottom: -1, height: 2,
                    background: 'var(--accent)',
                  }} />}
                </button>
              );
            })}
          </div>
        )}

        <div style={{ display: 'grid', gridTemplateColumns: '0.85fr 1.15fr', gap: 64, padding: '56px 0 8px', alignItems: 'start' }}>
          <div>
            <h3 className="display" style={{ fontSize: 36, color: 'var(--bg)', fontWeight: 700, lineHeight: 1.1, marginBottom: 18 }}>
              {cur.title}
            </h3>
            <p style={{ fontSize: 16.5, color: 'rgba(245,243,238,0.72)', marginBottom: 28, lineHeight: 1.55 }}>
              {cur.desc}
            </p>
            <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 12 }}>
              {cur.bullets.map(b => (
                <li key={b} style={{ display: 'flex', gap: 12, alignItems: 'baseline', fontSize: 14.5, color: 'var(--bg-soft)' }}>
                  <svg width="10" height="10" viewBox="0 0 10 10" style={{ flexShrink: 0 }}><path d="M2 5 L5 7 L8 3" stroke="var(--accent)" strokeWidth="1.6" fill="none" strokeLinecap="round" strokeLinejoin="round" /></svg>
                  {b}
                </li>
              ))}
            </ul>
          </div>
          <div>{cur.mock}</div>
        </div>
      </div>
    </section>
  );
}

function TabIcon({ name, color }) {
  const s = { stroke: color, strokeWidth: 1.5, fill: 'none', strokeLinecap: 'round', strokeLinejoin: 'round' };
  const icons = {
    inbox: <g {...s}><path d="M3 11 L3 17 H17 V11 L14 4 H6 Z M3 11 H7 L8 13 H12 L13 11 H17" /></g>,
    tag:   <g {...s}><path d="M4 4 H10 L17 11 L11 17 L4 10 Z" /><circle cx="7.5" cy="7.5" r="1.2" /></g>,
    spark: <g {...s}><path d="M10 3 L11.5 8 L17 9.5 L11.5 11 L10 16 L8.5 11 L3 9.5 L8.5 8 Z" /></g>,
    chart: <g {...s}><path d="M3 16 V8 M8 16 V5 M13 16 V11 M3 16 H17" /></g>,
  };
  return <svg width="20" height="20" viewBox="0 0 20 20">{icons[name] || icons.spark}</svg>;
}

// ——— Mocks ———

function MockShell({ children, label }) {
  return (
    <div style={{
      background: '#f5f3ee',
      color: 'var(--ink)',
      borderRadius: 12,
      border: '1px solid rgba(245,243,238,0.18)',
      overflow: 'hidden',
      boxShadow: '0 30px 60px -25px rgba(0,0,0,0.5)',
    }}>
      <div style={{
        padding: '10px 14px', borderBottom: '1px solid var(--line-2)',
        display: 'flex', alignItems: 'center', gap: 10, background: 'var(--bg-soft)',
      }}>
        <div style={{ display: 'flex', gap: 4 }}>
          {[0, 1, 2].map(i => <span key={i} style={{ width: 8, height: 8, borderRadius: '50%', background: '#d8d2c3' }} />)}
        </div>
        <span className="mono" style={{ fontSize: 11, color: 'var(--muted)' }}>{label}</span>
      </div>
      <div style={{ padding: 18 }}>{children}</div>
    </div>
  );
}

function CollectMock() {
  const sources = [
    { name: 'App Store', meta: '2 412 / нед', dot: '#0f7' },
    { name: 'Zendesk · поддержка', meta: '8 901 / нед', dot: '#0f7' },
    { name: 'Звонки · Mango', meta: '1 187 / нед', dot: '#0f7' },
    { name: 'Telegram · комьюнити', meta: '432 / нед', dot: '#fa3' },
    { name: 'NPS · после покупки', meta: '6 220 / нед', dot: '#0f7' },
    { name: 'Wildberries · отзывы', meta: 'настройка', dot: '#aaa' },
  ];
  return (
    <MockShell label="atlas / источники">
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
        {sources.map(s => (
          <div key={s.name} style={{
            border: '1px solid var(--line-2)', borderRadius: 8, padding: '12px 14px',
            display: 'flex', alignItems: 'center', justifyContent: 'space-between', background: 'var(--card)',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <span style={{ width: 6, height: 6, borderRadius: '50%', background: s.dot }} />
              <span style={{ fontSize: 13, fontWeight: 500 }}>{s.name}</span>
            </div>
            <span className="mono" style={{ fontSize: 11, color: 'var(--muted)' }}>{s.meta}</span>
          </div>
        ))}
      </div>
      <div style={{
        marginTop: 14, padding: '10px 14px', borderRadius: 8,
        background: 'var(--accent-soft)', color: 'var(--accent)',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between', fontSize: 12.5, fontWeight: 500,
      }}>
        <span>+ Подключить новый источник</span>
        <span className="mono">40 доступно</span>
      </div>
    </MockShell>
  );
}

function ClassifyMock() {
  const tree = [
    { n: 'Оплата', c: 1842, open: true, icon: 'card', tint: { bg: '#efebff', fg: '#7A60FF' }, sub: [
      { n: 'Apple Pay не проходит', c: 612, hot: true },
      { n: 'СБП — двойное списание', c: 287, hot: true },
      { n: 'Скидка не применилась', c: 196 },
    ]},
    { n: 'Доставка', c: 1244, open: true, icon: 'truck', tint: { bg: '#e6f5e6', fg: '#1f7a4c' }, sub: [
      { n: 'Курьер опоздал > 30 мин', c: 384 },
      { n: 'Перепутали заказ', c: 142 },
    ]},
    { n: 'Приложение', c: 962, open: false, icon: 'phone', tint: { bg: '#e6efff', fg: '#3b6dd3' }, sub: [] },
  ];

  const Glyph = ({ k, color }) => {
    const s = { stroke: color, strokeWidth: 1.6, fill: 'none', strokeLinecap: 'round', strokeLinejoin: 'round' };
    if (k === 'card')  return <svg width="16" height="16" viewBox="0 0 16 16"><rect x="2" y="4" width="12" height="9" rx="1.6" {...s} /><path d="M2 7 H14" {...s} /></svg>;
    if (k === 'truck') return <svg width="16" height="16" viewBox="0 0 16 16"><path d="M2 4 H9 V11 H2 Z M9 6 H12 L14 8 V11 H9 Z" {...s} /><circle cx="5" cy="12.2" r="1.1" fill={color} /><circle cx="11.5" cy="12.2" r="1.1" fill={color} /></svg>;
    if (k === 'phone') return <svg width="16" height="16" viewBox="0 0 16 16"><rect x="4.5" y="2" width="7" height="12" rx="1.4" {...s} /><circle cx="8" cy="11.5" r="0.6" fill={color} /></svg>;
    return null;
  };

  return (
    <MockShell label="atlas / таксономия">
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {tree.map(node => (
          <div key={node.n} style={{
            border: '1px solid var(--line-2)', borderRadius: 12,
            background: 'var(--card)', padding: '10px 12px',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <span style={{
                width: 22, height: 22, borderRadius: 6,
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                background: 'var(--bg-soft)', color: 'var(--muted)', flexShrink: 0,
              }}>
                <svg width="10" height="10" viewBox="0 0 10 10">
                  {node.open
                    ? <path d="M2 4 L5 7 L8 4" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round" />
                    : <path d="M4 2 L7 5 L4 8" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round" />}
                </svg>
              </span>
              <span style={{
                width: 26, height: 26, borderRadius: 7,
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                background: node.tint.bg, color: node.tint.fg, flexShrink: 0,
              }}>
                <Glyph k={node.icon} color={node.tint.fg} />
              </span>
              <span style={{ fontWeight: 700, fontSize: 14, color: 'var(--ink)' }}>{node.n}</span>
              <span className="mono" style={{ marginLeft: 'auto', fontSize: 11, color: 'var(--muted)' }}>
                {node.c.toLocaleString('ru-RU')} упоминаний
              </span>
            </div>

            {node.open && node.sub.length > 0 && (
              <div style={{ marginTop: 8, paddingLeft: 18, position: 'relative' }}>
                {node.sub.map((s, i) => (
                  <div key={s.n} style={{
                    display: 'flex', alignItems: 'center', gap: 8,
                    padding: '7px 6px 7px 16px', position: 'relative',
                    fontSize: 12.5,
                    borderTop: i === 0 ? '1px solid var(--line-2)' : 'none',
                  }}>
                    {/* L-connector */}
                    <svg width="10" height="20" viewBox="0 0 10 20" style={{
                      position: 'absolute', left: 0, top: 0, height: '100%',
                    }} preserveAspectRatio="none">
                      <path d="M2 0 V12 H9" stroke="var(--line)" strokeWidth="1" fill="none" />
                    </svg>
                    <span style={{ color: 'var(--ink-2)' }}>{s.n}</span>
                    {s.hot && (
                      <span className="mono" style={{
                        background: 'rgba(184,50,74,0.12)', color: 'var(--neg)',
                        padding: '2px 7px', borderRadius: 999,
                        fontSize: 9.5, fontWeight: 700, letterSpacing: '0.06em',
                      }}>HOT</span>
                    )}
                    <span className="mono" style={{ marginLeft: 'auto', fontSize: 11.5, color: 'var(--muted)' }}>
                      {s.c}
                    </span>
                  </div>
                ))}
              </div>
            )}
          </div>
        ))}
      </div>
    </MockShell>
  );
}

function AnalyzeMock() {
  const CASES = [
    {
      q: 'Что изменилось в жалобах на оплату после релиза 4.12?',
      body: (
        <React.Fragment>
          <p style={{ margin: '0 0 10px' }}>
            С 14 мая упоминания темы <b>«Apple Pay не проходит»</b> выросли на 112%.
            В 78% случаев — iOS 17.4 на iPhone 13/14. Появилась новая под-тема{' '}
            <span style={{ background: 'rgba(74,57,255,0.12)', padding: '1px 5px', borderRadius: 3 }}>
              «висит на 3-D Secure»
            </span>.
          </p>
          <div style={{
            padding: '10px 12px', background: 'var(--card)', borderLeft: '2px solid var(--accent)',
            fontSize: 12.5, color: 'var(--muted)', borderRadius: '0 6px 6px 0',
          }}>
            «Не могу оплатить третий день, висит на безопасной странице сбера и потом ошибка»<br />
            <span className="mono" style={{ fontSize: 10.5, marginTop: 4, display: 'inline-block' }}>
              App Store · iOS 17.4 · 16 мая
            </span>
          </div>
        </React.Fragment>
      ),
    },
    {
      q: 'Какие SKU потеряли долю в сетях ЦФО за последние 14 дней?',
      body: (
        <React.Fragment>
          <p style={{ margin: '0 0 10px' }}>
            3 SKU теряют долю полки. Драйвер — отзывы на новый рецепт и помятая упаковка на WB.
          </p>
          <div className="sku-list" style={{ display: 'flex', flexDirection: 'column', gap: 6, marginBottom: 12 }}>
            {[
              { n: 'Йогурт «Молочный лес» клубника', d: '−14% к LFL', tone: 'neg', why: 'кислый вкус · Юг + Поволжье' },
              { n: 'Хрустим XL 80 г',                d: '−8% к LFL',  tone: 'neg', why: 'OOS · 1 240 точек' },
              { n: 'Пицца «Пеппероне Лайт»',         d: '+38% к плану', tone: 'pos', why: 'word-of-mouth в TG' },
            ].map(r => (
              <div key={r.n} className="sku-row" style={{
                display: 'flex', alignItems: 'center', gap: 8,
                padding: '8px 12px', background: 'var(--card)',
                border: '1px solid var(--line-2)', borderRadius: 8,
                fontSize: 12.5,
              }}>
                <span className="sku-icon" style={{
                  width: 18, height: 18, borderRadius: 4, flexShrink: 0,
                  display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                  background: r.tone === 'pos' ? 'rgba(31,122,76,0.12)' : 'rgba(184,50,74,0.12)',
                  color: r.tone === 'pos' ? 'var(--pos)' : 'var(--neg)',
                }}>
                  <svg width="10" height="10" viewBox="0 0 10 10">
                    {r.tone === 'pos'
                      ? <path d="M5 8 V2 M2.5 4.5 L5 2 L7.5 4.5" stroke="currentColor" strokeWidth="1.6" fill="none" strokeLinecap="round" strokeLinejoin="round" />
                      : <path d="M5 2 V8 M2.5 5.5 L5 8 L7.5 5.5" stroke="currentColor" strokeWidth="1.6" fill="none" strokeLinecap="round" strokeLinejoin="round" />}
                  </svg>
                </span>
                <span className="sku-name" style={{ color: 'var(--ink-2)', flex: 1, minWidth: 0 }}>{r.n}</span>
                <span className="sku-delta mono" style={{
                  fontSize: 11, fontWeight: 600,
                  color: r.tone === 'pos' ? 'var(--pos)' : 'var(--neg)',
                  whiteSpace: 'nowrap',
                }}>{r.d}</span>
                <span className="sku-why" style={{ fontSize: 11, color: 'var(--muted)', whiteSpace: 'nowrap' }}>· {r.why}</span>
              </div>
            ))}
          </div>
          <style>{`
            @media (max-width: 860px) {
              .sku-row {
                display: grid !important;
                grid-template-columns: 18px 1fr auto;
                grid-template-rows: auto auto;
                align-items: center !important;
                column-gap: 8px !important;
                row-gap: 4px !important;
                padding: 10px 12px !important;
              }
              .sku-row .sku-icon  { grid-column: 1; grid-row: 1; }
              .sku-row .sku-name  {
                grid-column: 2; grid-row: 1;
                overflow: hidden !important;
                text-overflow: ellipsis !important;
                white-space: nowrap !important;
                font-weight: 500;
              }
              .sku-row .sku-delta { grid-column: 3; grid-row: 1; }
              .sku-row .sku-why   {
                grid-column: 2 / -1; grid-row: 2;
                white-space: normal !important;
                font-size: 10.5px !important;
                color: var(--muted) !important;
                padding-left: 0;
              }
            }
          `}</style>
          <div style={{
            padding: '10px 12px', background: 'var(--card)', borderLeft: '2px solid var(--accent)',
            fontSize: 12.5, color: 'var(--muted)', borderRadius: '0 6px 6px 0',
          }}>
            «Раньше брала клубничный, сейчас вкус кислый, ребёнок отказывается — больше не покупаю»<br />
            <span className="mono" style={{ fontSize: 10.5, marginTop: 4, display: 'inline-block' }}>
              Wildberries · 1★ · 18 мая
            </span>
          </div>
        </React.Fragment>
      ),
    },
    {
      q: 'Где упала чистота в магазинах и какие точки в риске?',
      body: (
        <React.Fragment>
          <p style={{ margin: '0 0 10px' }}>
            Негатив по чистоте вырос с 11% до 27% за квартал. Кластер — СЗАО Москвы,
            точка{' '}
            <span style={{ background: 'rgba(74,57,255,0.12)', padding: '1px 5px', borderRadius: 3 }}>
              «5×7» Дмитровское 142
            </span>{' '}
            держит 38% всех жалоб района.
          </p>
          <div style={{
            padding: '10px 12px', background: 'var(--card)', borderLeft: '2px solid var(--accent)',
            fontSize: 12.5, color: 'var(--muted)', borderRadius: '0 6px 6px 0',
          }}>
            «Грязно, корзинки кривые, на кассе никого. Стояла 20 минут, ушла без покупок»<br />
            <span className="mono" style={{ fontSize: 10.5, marginTop: 4, display: 'inline-block' }}>
              Я.Карты · 2★ · 16 мая
            </span>
          </div>
        </React.Fragment>
      ),
    },
  ];

  const [view, setView] = React.useState(0);
  const [paused, setPaused] = React.useState(false);

  React.useEffect(() => {
    if (paused) return;
    const id = setInterval(() => setView(v => (v + 1) % CASES.length), 5000);
    return () => clearInterval(id);
  }, [paused]);

  const go = (dir) => {
    setPaused(true);
    setView(v => (v + dir + CASES.length) % CASES.length);
  };

  const cur = CASES[view];

  return (
    <div
      style={{ position: 'relative' }}
      onMouseEnter={() => setPaused(true)}
      onMouseLeave={() => setPaused(false)}
    >
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        marginBottom: 10, gap: 10,
      }}>
        <div style={{
          fontSize: 11.5, color: 'rgba(245,243,238,0.55)',
          fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.06em',
        }}>
          {String(view + 1).padStart(2, '0')} / {String(CASES.length).padStart(2, '0')} · ЗАПРОС
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
          <button onClick={() => go(-1)} aria-label="prev" style={extArrowBtn}>
            <svg width="12" height="12" viewBox="0 0 12 12"><path d="M7.5 2.5 L3.5 6 L7.5 9.5" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round" /></svg>
          </button>
          <button onClick={() => go(1)} aria-label="next" style={extArrowBtn}>
            <svg width="12" height="12" viewBox="0 0 12 12"><path d="M4.5 2.5 L8.5 6 L4.5 9.5" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round" /></svg>
          </button>
        </div>
      </div>

      <MockShell label="atlas / запрос">
        <div style={{
          padding: '12px 14px', background: 'var(--bg-soft)',
          borderRadius: 8, border: '1px solid var(--line-2)', marginBottom: 14,
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <svg width="14" height="14" viewBox="0 0 14 14"><path d="M2 3 L12 3 L12 11 L2 11 Z M2 6 L12 6" stroke="var(--accent)" fill="none" strokeWidth="1.4" /></svg>
            <span className="mono" style={{ fontSize: 11, color: 'var(--muted)' }}>спросите Фидли</span>
          </div>
          <div style={{ fontSize: 14, marginTop: 6, fontWeight: 500 }}>
            {cur.q}
          </div>
        </div>

        <div key={view} style={{
          fontSize: 13.5, lineHeight: 1.6, color: 'var(--ink-2)',
          animation: 'analyze-fade 0.45s cubic-bezier(0.4, 0, 0.2, 1)',
        }}>
          {cur.body}
        </div>
      </MockShell>

      <style>{`
        @keyframes analyze-fade {
          from { opacity: 0; transform: translateY(4px); }
          to   { opacity: 1; transform: none; }
        }
      `}</style>
    </div>
  );
}

function DashboardMock() {
  const VIEWS = ['volume', 'themes', 'releases'];
  const [view, setView] = React.useState(0);
  const [paused, setPaused] = React.useState(false);

  const INDUSTRIES = ['SaaS', 'FMCG', 'Офлайн-бизнес'];
  const [industry, setIndustry] = React.useState(0);
  const [indOpen, setIndOpen] = React.useState(false);
  const indRef = React.useRef(null);
  React.useEffect(() => {
    if (!indOpen) return;
    const onDoc = (e) => { if (indRef.current && !indRef.current.contains(e.target)) setIndOpen(false); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [indOpen]);

  React.useEffect(() => {
    if (paused) return;
    const id = setInterval(() => setView(v => (v + 1) % VIEWS.length), 4500);
    return () => clearInterval(id);
  }, [paused]);

  React.useEffect(() => {
    if (paused) return;
    const id = setInterval(() => setIndustry(i => (i + 1) % INDUSTRIES.length), 5000);
    return () => clearInterval(id);
  }, [paused]);

  const go = (dir) => {
    setPaused(true);
    setView(v => (v + dir + VIEWS.length) % VIEWS.length);
  };

  const indName = INDUSTRIES[industry];
  // Сабтайтл/драйверы меняем под индустрию — чтобы видно было, какой кейс показываем.
  const subByIndustry = {
    'SaaS':          { volume: '12 недель · App Store + чаты', themes: 'по упоминаниям в чатах поддержки', releases: '4 последних релиза iOS' },
    'FMCG':          { volume: '12 недель · WB + Ozon + соцсети', themes: 'по упоминаниям в маркетплейсах', releases: '4 последних запуска SKU' },
    'Офлайн-бизнес': { volume: '12 недель · Я.Карты + 2GIS + чек', themes: 'по упоминаниям в локациях', releases: '4 последних смены графика' },
  };

  const labels = {
    volume:   { title: 'Голос клиента · нед',     sub: subByIndustry[indName].volume,   pill: '↑ 42% позитив', pillTone: 'pos' },
    themes:   { title: 'Топ-темы недели',         sub: subByIndustry[indName].themes,   pill: '3 спайка',      pillTone: 'neg' },
    releases: { title: 'Сентимент по релизам',    sub: subByIndustry[indName].releases, pill: '4.12 ↓ 18 пп',  pillTone: 'neg' },
  };
  const cur = labels[VIEWS[view]];
  const POS = '#1f7a4c', NEG = '#b8324a', NEU = '#b07a16', ACC = '#7A60FF';

  return (
    <div
      style={{ position: 'relative' }}
      onMouseEnter={() => setPaused(true)}
      onMouseLeave={() => setPaused(false)}
    >
      {/* External arrow controls — sit above the mock, outside the chart */}
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        marginBottom: 10, gap: 10,
      }}>
        <div style={{
          display: 'flex', alignItems: 'center', gap: 12,
          fontSize: 12.5, color: 'rgba(245,243,238,0.62)',
          fontFamily: "'Golos Text', 'Inter', sans-serif", letterSpacing: 0,
          fontWeight: 500,
        }}>
          <span>{view + 1} из {VIEWS.length} · дашборд</span>
          <span style={{ opacity: 0.4 }}>·</span>
          <span ref={indRef} style={{ position: 'relative', display: 'inline-block' }}>
            <button
              type="button"
              onClick={() => setIndOpen(o => !o)}
              style={{
                display: 'inline-flex', alignItems: 'center', gap: 6,
                padding: '3px 8px 3px 8px', borderRadius: 999,
                background: 'rgba(122,96,255,0.12)',
                border: '1px solid rgba(122,96,255,0.32)',
                color: '#cfc4ff',
                fontFamily: "'Golos Text', 'Inter', sans-serif",
                fontSize: 12.5, fontWeight: 500, letterSpacing: 0,
                cursor: 'pointer',
                transition: 'all 0.2s',
              }}
            >
              <span style={{
                width: 6, height: 6, borderRadius: '50%',
                background: '#b997ff', boxShadow: '0 0 6px #b997ff',
              }} />
              <span style={{ animation: `db-ind 0.45s cubic-bezier(0.4, 0, 0.2, 1)` }} key={indName}>Кейс · {indName}</span>
              <svg width="9" height="9" viewBox="0 0 9 9" style={{
                marginLeft: 2, opacity: 0.85,
                transition: 'transform 0.2s',
                transform: indOpen ? 'rotate(180deg)' : 'rotate(0)',
              }}>
                <path d="M2 3.5 L4.5 6 L7 3.5" stroke="currentColor" strokeWidth="1.3" fill="none" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </button>
            {indOpen && (
              <div style={{
                position: 'absolute', top: 'calc(100% + 6px)', left: 0,
                minWidth: 180, zIndex: 10,
                background: '#1a1a22',
                border: '1px solid rgba(122,96,255,0.32)',
                borderRadius: 10, padding: 4,
                boxShadow: '0 14px 40px -10px rgba(0,0,0,0.6)',
                animation: 'db-ind 0.18s cubic-bezier(0.4, 0, 0.2, 1)',
              }}>
                {INDUSTRIES.map((name, i) => {
                  const active = i === industry;
                  return (
                    <button
                      key={name}
                      type="button"
                      onClick={() => { setIndustry(i); setIndOpen(false); setPaused(true); }}
                      style={{
                        display: 'flex', alignItems: 'center', gap: 8,
                        width: '100%', padding: '8px 10px',
                        borderRadius: 7,
                        background: active ? 'rgba(122,96,255,0.18)' : 'transparent',
                        color: active ? '#fff' : 'rgba(245,243,238,0.78)',
                        fontFamily: "'Golos Text', 'Inter', sans-serif",
                        fontSize: 13, fontWeight: active ? 600 : 500,
                        letterSpacing: 0, textAlign: 'left',
                        cursor: 'pointer', border: 'none',
                        transition: 'background 0.15s',
                      }}
                      onMouseEnter={(e) => { if (!active) e.currentTarget.style.background = 'rgba(245,243,238,0.06)'; }}
                      onMouseLeave={(e) => { if (!active) e.currentTarget.style.background = 'transparent'; }}
                    >
                      <span style={{
                        width: 6, height: 6, borderRadius: '50%',
                        background: active ? '#b997ff' : 'rgba(245,243,238,0.3)',
                        boxShadow: active ? '0 0 6px #b997ff' : 'none',
                      }} />
                      {name}
                    </button>
                  );
                })}
              </div>
            )}
          </span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
          <button onClick={() => go(-1)} aria-label="prev" style={extArrowBtn}>
            <svg width="12" height="12" viewBox="0 0 12 12"><path d="M7.5 2.5 L3.5 6 L7.5 9.5" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round" /></svg>
          </button>
          <button onClick={() => go(1)} aria-label="next" style={extArrowBtn}>
            <svg width="12" height="12" viewBox="0 0 12 12"><path d="M4.5 2.5 L8.5 6 L4.5 9.5" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round" /></svg>
          </button>
        </div>
      </div>

      <MockShell label="atlas / дашборд">
        {/* Header row — title + sub + status pill */}
        <div style={{
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          marginBottom: 14, gap: 10,
        }}>
          <div style={{ minWidth: 0, flex: 1 }}>
            <div style={{ fontWeight: 600, fontSize: 14 }}>{cur.title}</div>
            <div style={{ fontSize: 11, color: 'var(--muted)', marginTop: 2 }}>{cur.sub}</div>
          </div>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 6,
            padding: '4px 10px', borderRadius: 999,
            background: cur.pillTone === 'pos' ? 'rgba(31,122,76,0.08)' : 'rgba(184,50,74,0.10)',
            color: cur.pillTone === 'pos' ? 'var(--pos)' : 'var(--neg)',
            fontSize: 11, fontWeight: 600, whiteSpace: 'nowrap',
          }}>{cur.pill}</div>
        </div>

        {/* Chart area — single fixed-height box, crossfade between views */}
        <div style={{ position: 'relative', height: 110 }}>
          {VIEWS.map((v, i) => (
            <div key={v} style={{
              position: 'absolute', inset: 0,
              opacity: view === i ? 1 : 0,
              pointerEvents: view === i ? 'auto' : 'none',
              transition: 'opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1)',
            }}>
              {v === 'volume'   && <ChartVolume   industry={indName} pos={POS} neg={NEG} neu={NEU} />}
              {v === 'themes'   && <ChartThemes   industry={indName} acc={ACC} neg={NEG} />}
              {v === 'releases' && <ChartReleases industry={indName} pos={POS} neg={NEG} acc={ACC} />}
            </div>
          ))}
        </div>

        <KPIRow view={VIEWS[view]} industry={indName} />
        <Insight view={VIEWS[view]} industry={indName} />

        {/* Action row — appears only on dashboards with a real problem to act on.
            Volume = позитивный тренд, действие не нужно. */}
        {VIEWS[view] === 'themes' && (
          <ActionRow {...ACTION_BY_INDUSTRY[indName].themes} />
        )}
        {VIEWS[view] === 'releases' && (
          <ActionRow {...ACTION_BY_INDUSTRY[indName].releases} />
        )}
        {VIEWS[view] === 'volume' && (
          <div style={{
            marginTop: 12, padding: '10px 12px',
            border: '1px dashed var(--line)', borderRadius: 8,
            fontSize: 12, color: 'var(--muted)', textAlign: 'center',
          }}>
            Тренд устойчивый — действие не требуется
          </div>
        )}

        {/* Dot pager */}
        <div style={{ display: 'flex', justifyContent: 'center', gap: 6, marginTop: 14 }}>
          {VIEWS.map((_, i) => (
            <button key={i} onClick={() => { setPaused(true); setView(i); }} aria-label={`view ${i + 1}`}
              style={{
                width: view === i ? 18 : 6, height: 6, borderRadius: 3,
                background: view === i ? 'var(--ink)' : 'var(--line)',
                transition: 'all 0.3s', border: 'none', cursor: 'pointer',
              }}
            />
          ))}
        </div>
      </MockShell>

      <style>{`
        @keyframes db-ind {
          from { opacity: 0; transform: translateY(-2px); }
          to   { opacity: 1; transform: translateY(0); }
        }
      `}</style>
    </div>
  );
}

const extArrowBtn = {
  width: 32, height: 32, borderRadius: '50%',
  border: '1px solid rgba(245,243,238,0.22)',
  background: 'transparent',
  display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
  cursor: 'pointer', color: 'var(--bg)',
  transition: 'all 0.15s',
};

const arrowBtn = {
  width: 26, height: 26, borderRadius: '50%',
  border: '1px solid var(--line)', background: 'var(--card)',
  display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
  cursor: 'pointer', color: 'var(--ink-2)',
};

function ChartVolume({ industry, pos, neg, neu }) {
  const W = 320, H = 110;
  const VOLUME_BY_INDUSTRY = {
    'SaaS': {
      pos: [10, 18, 22, 26, 30, 36, 42, 48, 55, 62, 58, 64],
      neg: [44, 40, 36, 30, 28, 24, 22, 20, 18, 16, 18, 14],
      neu: [22, 24, 28, 30, 32, 30, 28, 26, 24, 24, 26, 28],
    },
    'FMCG': {
      pos: [28, 32, 36, 40, 46, 50, 55, 58, 56, 60, 62, 60],
      neg: [38, 36, 32, 30, 26, 24, 22, 20, 22, 18, 16, 18],
      neu: [18, 20, 22, 22, 24, 26, 24, 24, 22, 22, 22, 22],
    },
    'Офлайн-бизнес': {
      pos: [16, 18, 20, 24, 28, 30, 34, 38, 40, 44, 48, 52],
      neg: [52, 48, 46, 42, 40, 36, 32, 28, 24, 22, 20, 18],
      neu: [20, 22, 22, 24, 24, 26, 28, 28, 26, 26, 24, 24],
    },
  };
  const series = VOLUME_BY_INDUSTRY[industry] || VOLUME_BY_INDUSTRY['SaaS'];
  const maxY = 70;
  const toPath = (arr) => arr.map((v, i) => {
    const x = (i / (arr.length - 1)) * W;
    const y = H - (v / maxY) * H;
    return `${i === 0 ? 'M' : 'L'} ${x.toFixed(1)} ${y.toFixed(1)}`;
  }).join(' ');
  const toArea = (arr) => `${toPath(arr)} L ${W} ${H} L 0 ${H} Z`;

  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height="100%" preserveAspectRatio="none"
         style={{ display: 'block', borderRadius: 8, background: 'var(--card)' }}>
      <defs>
        <linearGradient id="cvPos" x1="0" x2="0" y1="0" y2="1"><stop offset="0" stopColor={pos} stopOpacity="0.32" /><stop offset="1" stopColor={pos} stopOpacity="0" /></linearGradient>
        <linearGradient id="cvNeu" x1="0" x2="0" y1="0" y2="1"><stop offset="0" stopColor={neu} stopOpacity="0.22" /><stop offset="1" stopColor={neu} stopOpacity="0" /></linearGradient>
        <linearGradient id="cvNeg" x1="0" x2="0" y1="0" y2="1"><stop offset="0" stopColor={neg} stopOpacity="0.22" /><stop offset="1" stopColor={neg} stopOpacity="0" /></linearGradient>
      </defs>
      {[0.25, 0.5, 0.75].map(g => <line key={g} x1="0" x2={W} y1={H * g} y2={H * g} stroke="var(--line-2)" strokeWidth="0.5" strokeDasharray="2 3" />)}
      <path d={toArea(series.neg)} fill="url(#cvNeg)" />
      <path d={toArea(series.neu)} fill="url(#cvNeu)" />
      <path d={toArea(series.pos)} fill="url(#cvPos)" />
      <path d={toPath(series.neg)} stroke={neg} strokeWidth="1.6" fill="none" />
      <path d={toPath(series.neu)} stroke={neu} strokeWidth="1.6" fill="none" />
      <path d={toPath(series.pos)} stroke={pos} strokeWidth="2" fill="none" />
      <circle cx={W} cy={H - (series.pos[series.pos.length - 1] / 70) * H} r="3" fill={pos} />
    </svg>
  );
}

function ChartThemes({ industry, acc, neg }) {
  const THEMES_BY_INDUSTRY = {
    'SaaS': [
      { n: 'Apple Pay не проходит',     v: 612, hot: true },
      { n: 'Разлогин на iOS',           v: 480 },
      { n: 'Долгое ожидание поддержки', v: 384 },
      { n: 'Тёмная тема (запрос)',      v: 320 },
      { n: 'Падение конверсии оплаты',  v: 287, hot: true },
    ],
    'FMCG': [
      { n: 'Сладость во "вкусе 12"',   v: 540, hot: true },
      { n: 'Помятая упаковка WB',       v: 412 },
      { n: 'Не такой вкус, как раньше', v: 368, hot: true },
      { n: 'Цена выросла',              v: 295 },
      { n: 'Нет в наличии',             v: 240 },
    ],
    'Офлайн-бизнес': [
      { n: 'Очередь в час пик',         v: 218, hot: true },
      { n: 'Грязно в зале',             v: 184 },
      { n: 'Парковка переполнена',      v: 152 },
      { n: 'Цены на ценниках расходятся', v: 128, hot: true },
      { n: 'Долго ждали кассира',       v: 104 },
    ],
  };
  const MAX_BY_INDUSTRY = { 'SaaS': 700, 'FMCG': 620, 'Офлайн-бизнес': 260 };
  const themes = THEMES_BY_INDUSTRY[industry] || THEMES_BY_INDUSTRY['SaaS'];
  const max = MAX_BY_INDUSTRY[industry] || 700;
  return (
    <div style={{
      height: '100%', padding: '10px 12px', borderRadius: 8,
      background: 'var(--card)', display: 'flex', flexDirection: 'column', gap: 6,
      overflow: 'hidden',
    }}>
      {themes.map(t => (
        <div key={t.n} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 11 }}>
          <span style={{ flex: '0 0 130px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', color: 'var(--ink-2)', fontWeight: 500 }}>
            {t.n}
          </span>
          <div style={{ flex: 1, height: 8, background: 'var(--line-2)', borderRadius: 4, position: 'relative' }}>
            <div style={{
              width: `${(t.v / max) * 100}%`, height: '100%',
              background: t.hot ? neg : acc, borderRadius: 4,
            }} />
          </div>
          <span className="mono" style={{ fontSize: 10.5, color: 'var(--muted)', minWidth: 30, textAlign: 'right' }}>{t.v}</span>
        </div>
      ))}
    </div>
  );
}

function ChartReleases({ industry, pos, neg, acc }) {
  const W = 320, H = 110;
  const RELEASES_BY_INDUSTRY = {
    'SaaS':          { rels: [{ n: '4.09', v: 32 }, { n: '4.10', v: 38 }, { n: '4.11', v: 41 }, { n: '4.12', v: 23 }], maxV: 50 },
    'FMCG':          { rels: [{ n: 'SKU-09', v: 28 }, { n: 'SKU-10', v: 34 }, { n: 'SKU-11', v: 40 }, { n: 'SKU-12', v: 22 }], maxV: 50 },
    'Офлайн-бизнес': { rels: [{ n: 'Пн', v: 36 }, { n: 'Ср', v: 38 }, { n: 'Пт', v: 32 }, { n: 'Сб', v: 20 }], maxV: 50 },
  };
  const { rels, maxV } = RELEASES_BY_INDUSTRY[industry] || RELEASES_BY_INDUSTRY['SaaS'];
  const bw = 36, gap = 22, startX = 30;
  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height="100%" preserveAspectRatio="none"
         style={{ display: 'block', borderRadius: 8, background: 'var(--card)' }}>
      {[0.25, 0.5, 0.75].map(g => <line key={g} x1="0" x2={W} y1={H * g} y2={H * g} stroke="var(--line-2)" strokeWidth="0.5" strokeDasharray="2 3" />)}
      {rels.map((r, i) => {
        const x = startX + i * (bw + gap);
        const barH = (r.v / maxV) * (H - 30);
        const y = H - 18 - barH;
        const isDrop = i === rels.length - 1;
        return (
          <g key={r.n}>
            <rect x={x} y={y} width={bw} height={barH} rx="3" fill={isDrop ? neg : pos} opacity={isDrop ? 0.85 : 0.7} />
            <text x={x + bw / 2} y={y - 4} textAnchor="middle" fontSize="9" fill={isDrop ? neg : pos} fontWeight="600">+{r.v}</text>
            <text x={x + bw / 2} y={H - 4} textAnchor="middle" fontSize="9" fill="var(--muted)" fontFamily="JetBrains Mono">{r.n}</text>
          </g>
        );
      })}
      {/* trend arrow */}
      <path d={`M ${startX + 3 * (bw + gap) - 10} ${H - 60} l 10 18`} stroke={neg} strokeWidth="1.5" fill="none" markerEnd="url(#cra)" />
      <defs>
        <marker id="cra" viewBox="0 0 6 6" refX="3" refY="3" markerWidth="5" markerHeight="5" orient="auto">
          <path d="M0 0 L6 3 L0 6 Z" fill={neg} />
        </marker>
      </defs>
    </svg>
  );
}

const KPI_BY_INDUSTRY = {
  'SaaS': {
    volume:   [{ l: 'NPS',           v: '+47',    d: '↑ 8 пп · мес',     dTone: 'pos' },
               { l: 'Тикеты / нед',   v: '12 480', d: '↑ 4% · нед',       dTone: 'neg' }],
    themes:   [{ l: 'Активных тем',   v: '162',    d: '+12 за нед',       dTone: 'pos' },
               { l: 'HOT-тем',        v: '7',      d: '+3 за нед',        dTone: 'neg' }],
    releases: [{ l: 'Релиз 4.12',     v: '+23',    d: '↓ 18 пп',          dTone: 'neg' },
               { l: 'Откатить?',      v: 'P0',     d: 'ИИ-рекомендация',  dTone: 'neg' }],
  },
  'FMCG': {
    volume:   [{ l: 'Рейтинг WB',     v: '4.6 ★',  d: '↑ 0.2 · мес',      dTone: 'pos' },
               { l: 'Отзывы / нед',   v: '8 920',  d: '↑ 11% · нед',      dTone: 'pos' }],
    themes:   [{ l: 'Активных тем',   v: '94',     d: '+6 за нед',        dTone: 'pos' },
               { l: 'HOT-тем',        v: '4',      d: 'упаковка / вкус',  dTone: 'neg' }],
    releases: [{ l: 'SKU «вкус 12»',  v: '+18',    d: '↓ 9 пп vs SKU-11', dTone: 'neg' },
               { l: 'Решение',        v: 'Стоп',   d: 'снять с полки',    dTone: 'neg' }],
  },
  'Офлайн-бизнес': {
    volume:   [{ l: 'Я.Карты',        v: '4.4 ★',  d: '↑ 0.1 · мес',      dTone: 'pos' },
               { l: 'Жалоб / нед',    v: '342',    d: '↓ 18% · нед',      dTone: 'pos' }],
    themes:   [{ l: 'Активных тем',   v: '38',     d: 'по 7 локациям',    dTone: 'pos' },
               { l: 'HOT-тем',        v: '3',      d: 'очередь / чистота',dTone: 'neg' }],
    releases: [{ l: 'Смена · веч.',   v: '+12',    d: '↓ 14 пп за нед',   dTone: 'neg' },
               { l: 'Решение',        v: 'P1',     d: '+1 кассир',        dTone: 'neg' }],
  },
};

const INSIGHT_BY_INDUSTRY = {
  'SaaS':          { volume: 'Позитив ×6 за 12 нед — драйвер: «Поиск 2.0»', themes: 'Тема «Apple Pay не проходит» — P0', releases: 'Релиз 4.12 уронил сентимент на 18 пп' },
  'FMCG':          { volume: 'Рост позитива в Ozon — драйвер: новый дизайн упаковки', themes: 'Жалобы на сладость во «вкусе 12» — спайк', releases: 'SKU-12 в минусе vs SKU-11 — снять с полки' },
  'Офлайн-бизнес': { volume: 'Жалобы упали на 18% после ремонта вытяжки', themes: 'Очередь в час пик — 3 локации', releases: 'Вечерняя смена просела по чистоте — +1 кассир' },
};

const ACTION_BY_INDUSTRY = {
  'SaaS': {
    themes:   { primary: 'Создать тикет в JIRA · «Apple Pay не проходит»', sub: 'Подставит цитаты и метрики · команда «Касса»' },
    releases: { primary: 'Откатить релиз 4.12 → JIRA',                     sub: 'Apple Pay уронил сентимент на 18 пп — рекомендация ИИ' },
  },
  'FMCG': {
    themes:   { primary: 'Бриф R&D · ребаланс рецептуры «вкуса 12»',        sub: '64% негатива — переслащено по отзывам WB и Ozon' },
    releases: { primary: 'Стоп-продажи SKU-12 → задача в Pyrus',            sub: 'Сентимент −9 пп vs SKU-11 за 2 недели' },
  },
  'Офлайн-бизнес': {
    themes:   { primary: 'Задача для управляющего · «Очередь в 13:00–14:00»', sub: '+1 кассир в 3 локациях · экономия −12 жалоб / нед' },
    releases: { primary: 'Скорректировать график вечерней смены',             sub: 'Чистота / скорость просели на 14 пп — рекомендация ИИ' },
  },
};

function KPIRow({ view, industry }) {
  const items = (KPI_BY_INDUSTRY[industry] || KPI_BY_INDUSTRY['SaaS'])[view];
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginTop: 14 }}>
      {items.map(s => (
        <div key={s.l} style={{
          padding: '10px 12px', border: '1px solid var(--line-2)',
          borderRadius: 8, background: 'var(--card)',
        }}>
          <div style={{ fontSize: 10.5, color: 'var(--muted)' }}>{s.l}</div>
          <div className="display" style={{ fontSize: 22, fontWeight: 700, color: 'var(--ink)' }}>{s.v}</div>
          <div style={{ fontSize: 10.5, color: s.dTone === 'pos' ? 'var(--pos)' : 'var(--neg)', marginTop: 2 }}>{s.d}</div>
        </div>
      ))}
    </div>
  );
}

function ActionRow({ primary, sub }) {
  return (
    <div style={{ marginTop: 12, display: 'flex', gap: 8 }}>
      <button style={{
        flex: 1, padding: '12px 14px', background: 'var(--ink)', color: 'var(--bg)',
        borderRadius: 8, fontSize: 13, fontWeight: 600,
        display: 'flex', alignItems: 'center', gap: 10, textAlign: 'left',
        cursor: 'pointer', border: 'none',
      }}>
        <span style={{
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          width: 22, height: 22, borderRadius: 4,
          background: '#2684ff', color: '#fff', fontSize: 12, fontWeight: 800,
          fontFamily: 'Manrope, sans-serif', flexShrink: 0,
        }}>J</span>
        <span style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', minWidth: 0, flex: 1 }}>
          <span style={{ fontWeight: 600 }}>{primary}</span>
          {sub && <span style={{
            fontSize: 11, fontWeight: 400,
            color: 'rgba(245,243,238,0.6)', marginTop: 2,
            overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '100%',
          }}>{sub}</span>}
        </span>
        <svg width="12" height="12" viewBox="0 0 12 12" style={{ flexShrink: 0 }}>
          <path d="M3 6 L9 6 M6 3 L9 6 L6 9" stroke="currentColor" strokeWidth="1.6" fill="none" />
        </svg>
      </button>
    </div>
  );
}

function Insight({ view, industry }) {
  const text = (INSIGHT_BY_INDUSTRY[industry] || INSIGHT_BY_INDUSTRY['SaaS'])[view];
  return (
    <div style={{
      marginTop: 12, padding: '10px 12px',
      background: 'var(--ink)', color: 'var(--bg)',
      borderRadius: 8,
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      fontSize: 12.5, gap: 12,
    }}>
      <span style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 }}>
        <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--accent)', flexShrink: 0 }} />
        <span style={{
          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          animation: 'analyze-fade 0.4s cubic-bezier(0.4, 0, 0.2, 1)',
        }} key={`${view}-${industry}`}>{text}</span>
      </span>
      <span style={{
        fontFamily: "'Golos Text', sans-serif",
        fontSize: 11, fontWeight: 500, color: 'rgba(245,243,238,0.6)', flexShrink: 0,
      }}>инсайт</span>
    </div>
  );
}

function OldDashboardMock_unused() {
  // Original sparkline data — weekly volume of feedback by sentiment
  const W = 320, H = 110;
  const series = {
    pos: [10, 18, 22, 26, 30, 36, 42, 48, 55, 62, 58, 64],
    neg: [44, 40, 36, 30, 28, 24, 22, 20, 18, 16, 18, 14],
    neu: [22, 24, 28, 30, 32, 30, 28, 26, 24, 24, 26, 28],
  };
  const maxY = 70;
  const toPath = (arr) => {
    const n = arr.length;
    return arr.map((v, i) => {
      const x = (i / (n - 1)) * W;
      const y = H - (v / maxY) * H;
      return `${i === 0 ? 'M' : 'L'} ${x.toFixed(1)} ${y.toFixed(1)}`;
    }).join(' ');
  };
  const toArea = (arr) => `${toPath(arr)} L ${W} ${H} L 0 ${H} Z`;

  const POS = '#1f7a4c';
  const NEG = '#b8324a';
  const NEU = '#b07a16';

  // donut data
  const sentTotal = 100;
  const sentPos = 64, sentNeu = 22, sentNeg = 14;
  const R = 26, C = 2 * Math.PI * R;
  const segs = [
    { c: POS, frac: sentPos / sentTotal, off: 0 },
    { c: NEU, frac: sentNeu / sentTotal, off: sentPos },
    { c: NEG, frac: sentNeg / sentTotal, off: sentPos + sentNeu },
  ];

  return (
    <MockShell label="atlas / дашборд">
      {/* Header row */}
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        marginBottom: 14,
      }}>
        <div>
          <div style={{ fontWeight: 600, fontSize: 14 }}>Голос клиента · нед</div>
          <div style={{ fontSize: 11, color: 'var(--muted)', marginTop: 2 }}>12 недель · все источники</div>
        </div>
        <div style={{
          display: 'flex', alignItems: 'center', gap: 6,
          padding: '4px 10px', borderRadius: 999,
          background: 'rgba(31,122,76,0.08)', color: 'var(--pos)',
          fontSize: 11, fontWeight: 600,
        }}>
          ↑ 42% позитив
        </div>
      </div>

      {/* Stacked area chart */}
      <svg viewBox={`0 0 ${W} ${H}`} width="100%" preserveAspectRatio="none" style={{ display: 'block', borderRadius: 8, background: 'var(--card)' }}>
        <defs>
          <linearGradient id="dashPos" x1="0" x2="0" y1="0" y2="1">
            <stop offset="0" stopColor={POS} stopOpacity="0.32" />
            <stop offset="1" stopColor={POS} stopOpacity="0" />
          </linearGradient>
          <linearGradient id="dashNeu" x1="0" x2="0" y1="0" y2="1">
            <stop offset="0" stopColor={NEU} stopOpacity="0.22" />
            <stop offset="1" stopColor={NEU} stopOpacity="0" />
          </linearGradient>
          <linearGradient id="dashNeg" x1="0" x2="0" y1="0" y2="1">
            <stop offset="0" stopColor={NEG} stopOpacity="0.22" />
            <stop offset="1" stopColor={NEG} stopOpacity="0" />
          </linearGradient>
        </defs>
        {/* grid lines */}
        {[0.25, 0.5, 0.75].map(g => (
          <line key={g} x1="0" x2={W} y1={H * g} y2={H * g} stroke="var(--line-2)" strokeWidth="0.5" strokeDasharray="2 3" />
        ))}
        {/* areas */}
        <path d={toArea(series.neg)} fill="url(#dashNeg)" />
        <path d={toArea(series.neu)} fill="url(#dashNeu)" />
        <path d={toArea(series.pos)} fill="url(#dashPos)" />
        {/* lines */}
        <path d={toPath(series.neg)} stroke={NEG} strokeWidth="1.6" fill="none" />
        <path d={toPath(series.neu)} stroke={NEU} strokeWidth="1.6" fill="none" />
        <path d={toPath(series.pos)} stroke={POS} strokeWidth="2" fill="none" />
        {/* end dot on pos */}
        <circle cx={W} cy={H - (series.pos[series.pos.length - 1] / maxY) * H} r="3" fill={POS} />
      </svg>

      {/* KPI + sentiment donut row */}
      <div style={{
        display: 'grid', gridTemplateColumns: '1fr 1fr 110px',
        gap: 10, marginTop: 14,
      }}>
        <div style={{
          padding: '10px 12px', border: '1px solid var(--line-2)',
          borderRadius: 8, background: 'var(--card)',
        }}>
          <div style={{ fontSize: 10.5, color: 'var(--muted)' }}>NPS</div>
          <div className="display" style={{ fontSize: 22, fontWeight: 700, color: 'var(--ink)' }}>+47</div>
          <div style={{ fontSize: 10.5, color: 'var(--pos)', marginTop: 2 }}>↑ 8 пп · мес</div>
        </div>
        <div style={{
          padding: '10px 12px', border: '1px solid var(--line-2)',
          borderRadius: 8, background: 'var(--card)',
        }}>
          <div style={{ fontSize: 10.5, color: 'var(--muted)' }}>Тикеты / нед</div>
          <div className="display" style={{ fontSize: 22, fontWeight: 700, color: 'var(--ink)' }}>12 480</div>
          <div style={{ fontSize: 10.5, color: 'var(--neg)', marginTop: 2 }}>↑ 4% · нед</div>
        </div>
        <div style={{
          padding: '8px', border: '1px solid var(--line-2)',
          borderRadius: 8, background: 'var(--card)',
          display: 'flex', alignItems: 'center', gap: 8,
        }}>
          <svg width="64" height="64" viewBox="0 0 64 64">
            <circle cx="32" cy="32" r={R} fill="none" stroke="var(--line-2)" strokeWidth="8" />
            {segs.map((s, i) => (
              <circle
                key={i}
                cx="32" cy="32" r={R} fill="none"
                stroke={s.c} strokeWidth="8"
                strokeDasharray={`${C * s.frac} ${C}`}
                strokeDashoffset={-C * s.off / sentTotal}
                transform="rotate(-90 32 32)"
              />
            ))}
            <text x="32" y="36" textAnchor="middle" fontSize="13" fontWeight="700" fill="var(--ink)">64%</text>
          </svg>
        </div>
      </div>

      {/* Action row */}
      <div style={{
        marginTop: 12, padding: '10px 12px',
        background: 'var(--ink)', color: 'var(--bg)',
        borderRadius: 8,
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        fontSize: 12.5,
      }}>
        <span style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--accent)' }} />
          Topика «Apple Pay не проходит» — P0
        </span>
        <span style={{ fontWeight: 600 }}>→ Создать тикет</span>
      </div>
    </MockShell>
  );
}

function ActMock() {
  return (
    <MockShell label="atlas / действие">
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '0 0 12px', borderBottom: '1px solid var(--line-2)', marginBottom: 12,
      }}>
        <span style={{ fontWeight: 600, fontSize: 14 }}>Apple Pay — 3-D Secure</span>
        <span className="mono" style={{ fontSize: 10.5, padding: '3px 8px', background: 'rgba(184,50,74,0.1)', color: 'var(--neg)', borderRadius: 4, fontWeight: 600 }}>
          PRIORITY P0
        </span>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginBottom: 14 }}>
        {[
          { l: 'Затронуто клиентов', v: '~ 3 200' },
          { l: 'Возможный отток', v: '₽ 1.8 млн / мес' },
          { l: 'Связано с релизом', v: 'iOS 4.12.0' },
          { l: 'Ответственный', v: 'Команда «Касса»' },
        ].map(s => (
          <div key={s.l} style={{ border: '1px solid var(--line-2)', borderRadius: 6, padding: '8px 10px' }}>
            <div style={{ fontSize: 10.5, color: 'var(--muted)', marginBottom: 2 }}>{s.l}</div>
            <div className="mono" style={{ fontSize: 13, fontWeight: 500 }}>{s.v}</div>
          </div>
        ))}
      </div>

      <div style={{ display: 'flex', gap: 8 }}>
        <button style={{
          flex: 1, padding: '10px', background: 'var(--ink)', color: 'var(--bg)',
          borderRadius: 6, fontSize: 13, fontWeight: 600,
        }}>
          → Создать тикет в JIRA
        </button>
        <button style={{
          padding: '10px 14px', background: 'transparent', border: '1px solid var(--line)',
          borderRadius: 6, fontSize: 13, fontWeight: 500,
        }}>
          Slack
        </button>
      </div>
    </MockShell>
  );
}

window.Features = Features;
