// shared.jsx — Agent data, monograms, header/footer, page chrome.
// Loaded as a Babel script. Exports everything to window for cross-file access.

// ─────────────────────────────────────────────────────────────────────────────
// AGENT ROSTER — 9 curated specialists. Case-file numbered.
// ─────────────────────────────────────────────────────────────────────────────

const AGENTS = [
  {
    id: 'jurist',
    no: '01',
    title: 'Юрист',
    letter: 'Ю',
    speciality: 'Юриспруденция',
    grade: 'Старший',
    color: 'forest',
    swatch: '#1F3A36',
    headline: 'Проверяет договоры, готовит претензии, отвечает на вопросы по тексту.',
    summary: 'Анализирует риски в договорах, генерирует типовые документы по праву РФ, сверяет с актуальным законодательством.',
    skills: [
      'Анализ договора на риски с цитатами из текста',
      'Генерация НДА, оферт, договоров услуг',
      'Сверка с актуальным законодательством РФ',
      'Подготовка претензий, запросов, ответов',
      'Ответы на вопросы по тексту документа',
    ],
    audience: [
      { who: 'Собственник МСП', why: 'без штатного юриста, но 5–20 договоров в месяц' },
      { who: 'Закупщик', why: 'подписывает оферты от подрядчиков' },
      { who: 'Селлер маркетплейса', why: 'оферты, претензии, споры с площадкой' },
    ],
    samples: [
      { title: 'Анализ договора аренды', tag: 'PDF · 14 стр.', result: 'Нашёл 7 рисков, 2 критичных' },
      { title: 'Генерация НДА', tag: 'Запрос', result: 'Готовый документ за 40 сек.' },
      { title: 'Ответ на претензию', tag: 'Письмо', result: 'Аргументация со ссылками на ГК РФ' },
    ],
    price: 1900,
    priceOnce: 490,
    requests: '500 запросов/мес',
    integrations: ['Telegram', 'Веб-кабинет', 'API'],
    model: 'Закрытый LLM-стек премиум-класса с поддержкой длинного контекста для договоров на 100+ страниц. Перекрёстная проверка двумя моделями. RAG-индекс: ГК РФ, АПК РФ, актуальная судебная практика',
    safety: 'Документы хранятся в РФ. Не используются для дообучения.',
    available: true,
  },
  {
    id: 'accountant',
    no: '02',
    title: 'Бухгалтер',
    letter: 'Б',
    speciality: 'Финансы',
    grade: 'Старший',
    color: 'forest',
    swatch: '#2A4A6B',
    headline: 'Проверяет первичку, готовит ответы в налоговую, считает налоги по УСН/ОСН.',
    summary: 'Помогает в первичной бухгалтерии: проверяет акты и счета, готовит шаблоны ответов в налоговую, рассчитывает налоги.',
    skills: [
      'Проверка актов, счетов-фактур, УПД',
      'Расчёт налогов: УСН (6%, 15%), патент, ОСН',
      'Ответы на требования ФНС',
      'Сверка с контрагентами',
      'Подготовка к налоговой отчётности',
    ],
    audience: [
      { who: 'ИП на УСН', why: 'без бухгалтера, нужно понимать налоги' },
      { who: 'Малое ООО', why: 'аутсорс бухгалтер на тарифе, нужен быстрый ответ' },
    ],
    samples: [
      { title: 'Расчёт УСН 6% за квартал', tag: 'Запрос', result: 'Сумма + платёжное поручение' },
      { title: 'Проверка УПД', tag: 'PDF', result: '3 ошибки в реквизитах' },
    ],
    price: 2900,
    priceOnce: 590,
    requests: '500 запросов/мес',
    integrations: ['Telegram', 'Веб-кабинет', '1С', 'Эльба'],
    model: 'Специализированный LLM-стек с tool-use для точных расчётов (без галлюцинаций в числах). RAG: НК РФ, ПБУ, актуальные разъяснения ФНС',
    safety: 'Финансовые данные в защищённом контуре, серверы РФ.',
    available: true,
  },
  {
    id: 'marketer',
    no: '03',
    title: 'Маркетолог',
    letter: 'М',
    speciality: 'Маркетинг',
    grade: 'Стратегический',
    color: 'burgundy',
    swatch: '#6E2A2A',
    headline: 'Считает unit-экономику, ставит метрики, разбирает воронку и каналы.',
    summary: 'Старший маркетолог-стратег. Помогает с позиционированием, считает unit-экономику, строит план кампаний.',
    skills: [
      'Расчёт unit-экономики, LTV/CAC',
      'Позиционирование и УТП',
      'План контента и каналов',
      'Брифинг подрядчиков',
      'Разбор воронки и точек слива',
    ],
    audience: [
      { who: 'Собственник без CMO', why: 'нужна стратегия, а не агентство' },
      { who: 'Маркетолог 1', why: 'в команде 1 человек, нужно зеркало для решений' },
    ],
    samples: [
      { title: 'Unit-экономика клиники', tag: 'Запрос', result: 'CAC 2400₽, LTV 14k, окуп. 3 мес.' },
      { title: 'Бриф SMM-подрядчику', tag: 'Документ', result: 'Готовый бриф на 2 стр.' },
    ],
    price: 4900,
    priceOnce: 990,
    requests: '300 запросов/мес',
    integrations: ['Telegram', 'Веб-кабинет', 'Яндекс.Метрика'],
    model: 'Премиум LLM-стек: стратегические модели для позиционирования + аналитические для unit-экономики + рыночная аналитика. Контекст: 1000+ кейсов МСП РФ',
    safety: 'Серверы РФ, политика 152-ФЗ.',
    available: true,
  },
  {
    id: 'copywriter',
    no: '04',
    title: 'Копирайтер',
    letter: 'К',
    speciality: 'Контент',
    grade: 'Базовый',
    color: 'ochre',
    swatch: '#B88A3A',
    headline: 'Пишет тексты для сайта, рассылок и постов. Учится вашему тону.',
    summary: 'Промышленный копирайтинг: лендинги, email, посты, описания товаров. Запоминает голос бренда.',
    skills: [
      'Лендинг по брифу: H1, секции, CTA',
      'Email-рассылки и сценарии',
      'Посты в соцсетях по контент-плану',
      'Описания товаров для маркетплейсов',
      'Адаптация под голос бренда',
    ],
    audience: [
      { who: 'Селлер маркетплейса', why: '500+ карточек, нужны описания' },
      { who: 'Контент-маркетолог', why: 'нужен второй автор без найма' },
    ],
    samples: [
      { title: '50 описаний для WB', tag: 'XLSX', result: 'Готово за 1.5 часа' },
      { title: 'Email на 5 писем', tag: 'Запрос', result: 'Цепочка прогрева' },
    ],
    price: 1900,
    priceOnce: 290,
    requests: 'Безлимит',
    integrations: ['Telegram', 'Веб-кабинет'],
    model: 'Генеративный LLM-стек с памятью голоса бренда. Долгий контекст для лонгридов, быстрая модель для постов. Коллекция текстов 200+ российских брендов',
    safety: 'Брендбук в защищённой базе знаний, серверы РФ.',
    available: true,
  },
  {
    id: 'sales',
    no: '05',
    title: 'Продажник',
    letter: 'П',
    speciality: 'Продажи',
    grade: 'Старший',
    color: 'forest',
    swatch: '#1F3A36',
    headline: 'Готовит коммерческие, отрабатывает возражения, разбирает звонки.',
    summary: 'B2B-продажи: квалификация лидов, КП, скрипты, разбор звонков и переписок.',
    skills: [
      'Квалификация лида (BANT, MEDDIC)',
      'Коммерческое предложение под клиента',
      'Скрипт первого звонка / возражений',
      'Разбор записи звонка с обратной связью',
      'Письмо после встречи',
    ],
    audience: [
      { who: 'РОП в МСП', why: 'нужен помощник для разбора и тренировки команды' },
      { who: 'Самозанятый эксперт', why: 'делает продажи сам, нужен второй мозг' },
    ],
    samples: [
      { title: 'КП на услугу за 700к', tag: 'PDF', result: 'Структурированный документ' },
      { title: 'Разбор звонка 28 мин.', tag: 'Аудио', result: '6 точек роста, 2 ошибки' },
    ],
    price: 3900,
    priceOnce: 690,
    requests: '300 запросов/мес',
    integrations: ['Telegram', 'amoCRM', 'Битрикс24'],
    model: 'LLM-стек + распознавание речи 99%+ точности для расшифровки звонков и встреч. Методики SPIN / Challenger / MEDDIC',
    safety: 'Записи звонков обрабатываются в РФ, удаление через 30 дней.',
    available: true,
  },
  {
    id: 'hr',
    no: '06',
    title: 'HR',
    letter: 'Н',
    speciality: 'Кадры',
    grade: 'Базовый',
    color: 'burgundy',
    swatch: '#7A3838',
    headline: 'Пишет вакансии, сортирует резюме, готовит вопросы для собеседования.',
    summary: 'Полный цикл рекрутинга: текст вакансии, скрининг резюме, вопросы на интервью, оффер.',
    skills: [
      'Текст вакансии по описанию роли',
      'Скрининг 50+ резюме за раз',
      'Вопросы для технического / поведенческого интервью',
      'Шаблон оффера, отказа',
      'План онбординга',
    ],
    audience: [
      { who: 'Собственник 5–30 чел.', why: 'нанимает сам, нужно ускориться' },
      { who: 'HR-менеджер 1', why: 'нужен помощник на рутину' },
    ],
    samples: [
      { title: 'Скрининг 80 резюме', tag: 'PDF', result: 'Топ-10 ранжированы' },
      { title: 'Вакансия Senior Dev', tag: 'Запрос', result: 'Готовый текст' },
    ],
    price: 2900,
    priceOnce: 490,
    requests: '400 запросов/мес',
    integrations: ['Telegram', 'hh.ru', 'Веб-кабинет'],
    model: 'LLM-стек со скорингом резюме (релевантность + cultural fit) и генерацией вакансий по бренд-тону компании',
    safety: 'Резюме обрабатываются в РФ, не используются для обучения.',
    available: true,
  },
  {
    id: 'analyst',
    no: '07',
    title: 'Аналитик',
    letter: 'А',
    speciality: 'Данные',
    grade: 'Старший',
    color: 'forest',
    swatch: '#3A5C4F',
    headline: 'Читает таблицы и выгрузки, строит отчёты, ищет аномалии.',
    summary: 'Бизнес-аналитика по загруженным данным. Читает XLSX/CSV/выгрузки и отвечает на вопросы.',
    skills: [
      'Анализ XLSX/CSV/JSON: метрики, тренды, аномалии',
      'Когортный анализ по выгрузкам',
      'Сравнение периодов и каналов',
      'Графики и summary одним абзацем',
      'SQL по описанию (для самостоятельной выгрузки)',
    ],
    audience: [
      { who: 'Собственник', why: 'устал делать сводные руками' },
      { who: 'Финдир', why: 'нужны быстрые ответы на разовые вопросы' },
    ],
    samples: [
      { title: 'Продажи Q3 vs Q2', tag: 'XLSX 12k строк', result: '−18% по 3 SKU, причина' },
    ],
    price: 3900,
    priceOnce: 690,
    requests: '300 запросов/мес',
    integrations: ['Telegram', 'Веб-кабинет', 'Google Sheets'],
    model: 'Глубокий аналитический LLM-стек + Code Interpreter для расчётов на ваших таблицах. Перекрёстная проверка результатов между моделями',
    safety: 'Данные обрабатываются в защищённом контуре.',
    available: true,
  },
  {
    id: 'secretary',
    no: '08',
    title: 'Секретарь',
    letter: 'С',
    speciality: 'Операции',
    grade: 'Базовый',
    color: 'ochre',
    swatch: '#8A6F2A',
    headline: 'Резюмирует встречи, ведёт расписание, готовит письма и протоколы.',
    summary: 'Личный ассистент: транскрипты встреч, краткие резюме, шаблоны писем, протоколы.',
    skills: [
      'Транскрипт встречи (аудио / Zoom)',
      'Краткое резюме длинного письма / документа',
      'Шаблоны деловых писем',
      'Протокол с задачами и сроками',
      'Подготовка к встрече: контекст по контрагенту',
    ],
    audience: [
      { who: 'Руководитель', why: '4–8 встреч в день, нужны протоколы' },
      { who: 'Самозанятый эксперт', why: 'нет ассистента, есть встречи' },
    ],
    samples: [
      { title: 'Встреча 1ч 20мин', tag: 'Аудио', result: 'Протокол + 6 задач со сроками' },
    ],
    price: 1900,
    priceOnce: 290,
    requests: '500 запросов/мес',
    integrations: ['Telegram', 'Веб-кабинет', 'Zoom', 'Google Calendar'],
    model: 'LLM-стек + транскрипция аудио/видео с разметкой спикеров и таймкодами. Точность распознавания 99%+',
    safety: 'Аудио хранится 30 дней, потом удаляется.',
    available: true,
  },
  {
    id: 'designer',
    no: '09',
    title: 'Дизайнер',
    letter: 'Д',
    speciality: 'Дизайн',
    grade: 'Стратегический',
    color: 'plum',
    swatch: '#7A4B6F',
    headline: 'Брендбук, логотип, графика, 3D-мокапы и короткое видео по брифу.',
    summary: 'Полный визуальный цикл: от логотипа и фирменного стиля до баннеров, презентаций, 3D-визуализации товара и моушн-роликов для соцсетей.',
    skills: [
      'Логотип и фирменный стиль: 3 концепта, финальный SVG + PNG',
      'Брендбук: палитра, типографика, голос, правила применения',
      'Графика: посты для соцсетей, баннеры, обложки, инфографика',
      '3D-мокапы: товар в упаковке, на полке, в руке, на стенде',
      'Видео-ролик 15–60 сек: моушн, текст, переходы, музыка',
      'Иллюстрации в фирменном стиле: серии для статей и презентаций',
      'Презентации: pitch-deck, КП, шаблоны для команды',
      'Адаптация под маркетплейсы: карточки WB/Ozon, инфо-графика',
    ],
    audience: [
      { who: 'Собственник МСП', why: 'нужен фирменный стиль и регулярная графика без агентства' },
      { who: 'Маркетолог-1', why: 'делает контент сам, нужен подмастерье-дизайнер' },
      { who: 'Селлер маркетплейса', why: '20–500 карточек в месяц с фирменной инфо-графикой' },
      { who: 'Стартап на pre-launch', why: 'нужен логотип, лендинг-графика и брендбук за неделю' },
    ],
    samples: [
      { title: 'Логотип + 3 варианта', tag: 'Бриф', result: 'SVG + PNG + бренд-палитра за 2 часа' },
      { title: 'Брендбук на 12 страниц', tag: 'PDF', result: 'Готовый документ для команды' },
      { title: '50 карточек товаров WB', tag: 'XLSX + ассеты', result: 'Единый стиль, готовы к загрузке' },
      { title: '3D-мокап коробки', tag: 'Фото товара', result: '6 ракурсов + рендер на полке' },
      { title: 'Видео-ролик 30 сек', tag: 'Бриф + лого', result: 'MP4 1080p для Reels/Shorts' },
    ],
    price: 5900,
    priceOnce: 1490,
    requests: '200 запросов/мес',
    integrations: ['Telegram', 'Веб-кабинет', 'Figma', 'Яндекс.Диск'],
    model: 'Бренд-стратегический LLM-стек для брифов и текстов брендбука · ведущие image-генераторы премиум-класса для графики и логотипов · video-модели нового поколения для motion-роликов · 3D-стек для мокапов товара и упаковки',
    safety: 'Загруженные исходники (фото товара, бриф) хранятся в РФ. Сгенерированные ассеты — ваши, без водяных знаков.',
    available: true,
  },
];

// ─────────────────────────────────────────────────────────────────────────────
// MONOGRAM — case-file avatar. Number + big letter on tinted square.
// ─────────────────────────────────────────────────────────────────────────────

function Monogram({ agent, size = 64, style = 'default' }) {
  // sizes: render as a square with subtle border + number + letter
  const s = size;
  const fz = Math.round(s * 0.5);
  const bg = agent.swatch;
  const fg = '#F4F0E6';

  return (
    <div
      className="monogram"
      style={{
        width: s,
        height: s,
        background: bg,
        color: fg,
        borderRadius: 3,
        fontSize: fz,
        letterSpacing: '-0.02em',
        boxShadow: 'inset 0 0 0 1px rgba(255,255,255,0.06)',
      }}
    >
      <span className="mono-no" style={{ fontSize: Math.max(8, s * 0.12) }}>№&nbsp;{agent.no}</span>
      <span style={{ marginTop: s * 0.06 }}>{agent.letter}</span>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// HEADER — top nav bar
// ─────────────────────────────────────────────────────────────────────────────

function Header({ route, navigate, mode }) {
  const links = [
    { id: 'catalog', label: 'Картотека' },
    { id: 'dossier', label: 'Досье' },
    { id: 'chat', label: 'Кабинет' },
    { id: 'pricing', label: 'Условия' },
  ];
  return (
    <header className="app-nav">
      <div className="container-wide" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', height: 68 }}>
        <a
          onClick={() => navigate('landing')}
          style={{ display: 'flex', alignItems: 'baseline', gap: 10, cursor: 'pointer' }}
        >
          <span className="serif" style={{ fontSize: 26, fontWeight: 700, letterSpacing: '-0.02em', lineHeight: 1 }}>
            ДЕЛЕГАТ
          </span>
          <span className="mono" style={{ fontSize: 11, letterSpacing: '0.16em', color: 'var(--ink-3)', textTransform: 'uppercase' }}>
            Бюро ИИ-специалистов · est. 2026
          </span>
        </a>

        <nav style={{ display: 'flex', gap: 28 }}>
          {links.map((l) => (
            <a
              key={l.id}
              onClick={() => navigate(l.id)}
              style={{
                fontSize: 15,
                cursor: 'pointer',
                color: route === l.id ? 'var(--ink)' : 'var(--ink-2)',
                borderBottom: route === l.id ? '1px solid var(--ink)' : '1px solid transparent',
                paddingBottom: 4,
                transition: 'color 150ms, border-color 150ms',
              }}
            >
              {l.label}
            </a>
          ))}
        </nav>

        <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
          <a style={{ fontSize: 15, color: 'var(--ink-2)', cursor: 'pointer' }}>Войти</a>
          <button className="btn btn-primary btn-sm" onClick={() => navigate('chat')}>
            Открыть дело
            <span style={{ opacity: 0.7 }}>→</span>
          </button>
        </div>
      </div>
    </header>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// FOOTER
// ─────────────────────────────────────────────────────────────────────────────

function Footer() {
  return (
    <footer style={{ borderTop: '1px solid var(--rule)', marginTop: 80, padding: '48px 0 32px', background: 'var(--paper-2)' }}>
      <div className="container-wide">
        <div className="m-footer-grid" style={{ display: 'grid', gridTemplateColumns: '2fr 1fr 1fr 1fr', gap: 40, marginBottom: 48 }}>
          <div>
            <div className="serif" style={{ fontSize: 28, fontWeight: 700, letterSpacing: '-0.02em', lineHeight: 1 }}>
              ДЕЛЕГАТ
            </div>
            <div className="mono" style={{ fontSize: 11, letterSpacing: '0.16em', color: 'var(--ink-3)', textTransform: 'uppercase', marginTop: 6 }}>
              Бюро ИИ-специалистов
            </div>
            <p className="muted" style={{ fontSize: 14, marginTop: 16, maxWidth: 320, lineHeight: 1.6 }}>
              Кураторское бюро специализированных ИИ-агентов. Серверы в РФ. Документы по ФЗ-152.
            </p>
          </div>

          <div>
            <div className="eyebrow" style={{ marginBottom: 12 }}>Продукт</div>
            <div className="col gap-xs muted-2" style={{ fontSize: 14 }}>
              <a>Картотека агентов</a>
              <a>Условия и тарифы</a>
              <a>Как работает</a>
              <a>API для интеграций</a>
            </div>
          </div>

          <div>
            <div className="eyebrow" style={{ marginBottom: 12 }}>Делегат</div>
            <div className="col gap-xs muted-2" style={{ fontSize: 14 }}>
              <a>О нас</a>
              <a>Кейсы</a>
              <a>Блог</a>
              <a>Контакты</a>
            </div>
          </div>

          <div>
            <div className="eyebrow" style={{ marginBottom: 12 }}>Документы</div>
            <div className="col gap-xs muted-2" style={{ fontSize: 14 }}>
              <a href="/oferta.html" style={{ cursor: 'pointer' }}>Оферта</a>
              <a href="/privacy.html" style={{ cursor: 'pointer' }}>Политика 152-ФЗ</a>
              <a href="/cookies.html" style={{ cursor: 'pointer' }}>Cookies</a>
              <a href="mailto:info@delegat365.ru" style={{ cursor: 'pointer' }}>info@delegat365.ru</a>
            </div>
          </div>
        </div>

        <div className="rule" />
        <div className="m-row-stack mono" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 24, fontSize: 12, color: 'var(--ink-3)', gap: 12, flexWrap: 'wrap' }}>
          <span>© 2026 ИП Низамов Д.Ф. · ИНН 166109730543</span>
          <span>Онлайн по РФ · Серверы в РФ · ФЗ-152</span>
        </div>
      </div>
    </footer>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// SHARED PRIMITIVES
// ─────────────────────────────────────────────────────────────────────────────

function CaseHeading({ no, eyebrow, children, align = 'left' }) {
  return (
    <div style={{ textAlign: align }}>
      {no && (
        <div className="mono" style={{ fontSize: 12, letterSpacing: '0.14em', color: 'var(--ink-3)', marginBottom: 12, textTransform: 'uppercase' }}>
          {eyebrow ? <>{eyebrow} · </> : null}Раздел № {no}
        </div>
      )}
      <h2 style={{ maxWidth: 900, marginLeft: align === 'center' ? 'auto' : 0, marginRight: align === 'center' ? 'auto' : 0 }}>{children}</h2>
    </div>
  );
}

// Glyph icons — minimal line-art, no robots/brains
function Glyph({ name, size = 24, color = 'currentColor' }) {
  const sw = 1.4;
  const props = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: color, strokeWidth: sw, strokeLinecap: 'round', strokeLinejoin: 'round' };
  switch (name) {
    case 'scales':
      return <svg {...props}><path d="M12 3v18M5 21h14M7 8l-3 6h6zM17 8l-3 6h6zM7 8h10M4 6l8 2 8-2" /></svg>;
    case 'abacus':
      return <svg {...props}><rect x="3" y="4" width="18" height="16" rx="1"/><line x1="3" y1="10" x2="21" y2="10"/><line x1="3" y1="15" x2="21" y2="15"/><circle cx="9" cy="7" r="1" fill={color}/><circle cx="13" cy="12.5" r="1" fill={color}/><circle cx="17" cy="17.5" r="1" fill={color}/></svg>;
    case 'compass':
      return <svg {...props}><circle cx="12" cy="12" r="9"/><polygon points="14.5,9.5 12,14 9.5,14.5 12,10" fill={color} stroke="none"/></svg>;
    case 'pen':
      return <svg {...props}><path d="M14 4l6 6-10 10H4v-6L14 4z"/><path d="M14 4l6 6"/></svg>;
    case 'handshake':
      return <svg {...props}><path d="M2 13l4-4 5 5-2 2-3-3M22 13l-4-4-5 5 2 2 3-3"/><path d="M9 14l3 3M15 14l-3 3"/></svg>;
    case 'people':
      return <svg {...props}><circle cx="9" cy="8" r="3"/><circle cx="17" cy="9" r="2.5"/><path d="M3 20c0-3 3-5 6-5s6 2 6 5M13 19c0-2 2-4 4-4s4 2 4 4"/></svg>;
    case 'chart':
      return <svg {...props}><path d="M4 19h16M6 16V9M11 16V5M16 16v-7M21 16v-4"/></svg>;
    case 'clock':
      return <svg {...props}><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>;
    case 'doc':
      return <svg {...props}><path d="M6 3h9l4 4v14H6z"/><path d="M15 3v4h4"/><line x1="9" y1="12" x2="16" y2="12"/><line x1="9" y1="16" x2="14" y2="16"/></svg>;
    case 'shield':
      return <svg {...props}><path d="M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6z"/><path d="M9 12l2 2 4-4"/></svg>;
    case 'arrow':
      return <svg {...props}><line x1="4" y1="12" x2="20" y2="12"/><polyline points="14 6 20 12 14 18"/></svg>;
    case 'check':
      return <svg {...props}><polyline points="4 12 10 18 20 6"/></svg>;
    case 'plus':
      return <svg {...props}><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>;
    case 'search':
      return <svg {...props}><circle cx="11" cy="11" r="7"/><line x1="16" y1="16" x2="21" y2="21"/></svg>;
    case 'send':
      return <svg {...props}><path d="M21 3L3 11l7 3 3 7z"/><line x1="21" y1="3" x2="10" y2="14"/></svg>;
    case 'paperclip':
      return <svg {...props}><path d="M21 11l-9 9a5 5 0 01-7-7L14 4a3.5 3.5 0 015 5l-9 9a2 2 0 01-3-3l8-8"/></svg>;
    case 'tg':
      return <svg {...props}><path d="M3 11l18-7-3 17-7-4-4 4v-6l11-9-13 8z" fill="none"/></svg>;
    default:
      return null;
  }
}

// Tag chip — small inline label
function Tag({ children, color }) {
  return (
    <span
      className="mono"
      style={{
        fontSize: 11,
        letterSpacing: '0.08em',
        textTransform: 'uppercase',
        color: color || 'var(--ink-3)',
        padding: '3px 8px',
        border: `1px solid ${color || 'var(--rule)'}`,
        borderRadius: 2,
        whiteSpace: 'nowrap',
      }}
    >
      {children}
    </span>
  );
}

// Asterisk separator — typographic flourish
function Asterism() {
  return (
    <div style={{ textAlign: 'center', color: 'var(--ink-3)', letterSpacing: '0.4em', fontSize: 14, margin: '40px 0' }}>
      ✦ ✦ ✦
    </div>
  );
}

// Section number with rule
function SectionLabel({ no, label }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 28 }}>
      <span className="mono" style={{ fontSize: 12, letterSpacing: '0.14em', color: 'var(--ink-3)', textTransform: 'uppercase' }}>
        Раздел № {no}
      </span>
      <span style={{ flex: 1, height: 1, background: 'var(--rule)' }} />
      <span className="mono" style={{ fontSize: 12, letterSpacing: '0.14em', color: 'var(--ink-3)', textTransform: 'uppercase' }}>
        {label}
      </span>
    </div>
  );
}

// Format ruble price with thin space
function rub(n) {
  const s = String(n).replace(/\B(?=(\d{3})+(?!\d))/g, '\u202F');
  return s + '\u00A0₽';
}

Object.assign(window, {
  AGENTS,
  Monogram, Header, Footer, CaseHeading, Glyph, Tag, Asterism, SectionLabel, rub,
});
