/* Каталог площадок — публичный лендинг платформы, и страница «для бизнеса».
   Цвета — CSS-переменные в :root, тёмная тема через prefers-color-scheme. */

:root {
  --brand-violet: #8742EE;
  --brand-violet-light: #A970FF;
  --brand-violet-soft: #EFE8FB;
  --brand-violet-bg: #F2EBFD;
  --ink: #22123A;
  --ink-2: #312740;
  /* Затемнено относительно исходного #766C8B (4.31:1 на новом --surface -
     не проходит AA для обычного текста) - см. docs-project/theme-tokens/
     LIGHT_THEME_REPORT.md, раздел про контраст. */
  --muted: #655C7A;
  /* Не чистый белый - иначе неотличим от --card-bg (#fff), карточки
     "теряются" на фоне (задание светлой темы, п.2). Едва заметный
     фиолетовый оттенок в сторону --brand-violet-bg, не серый нейтральный -
     чтобы не спорить с брендом каталога. */
  --surface: #F2EFF7;
  --brand-blue: #007AFF;
  --dark-bg: #181818;
  --dark-surface: #1D1D1D;
  --dark-surface-2: #2A2A2A;
  --dark-ink: #E4E4E4;
  --dark-border: rgba(255, 255, 255, 0.08);

  /* Общий акцент интерфейса — янтарный (был сине-фиолетовый градиент старого
     бренда). Второй стоп — тот же янтарь с прозрачностью, без нового оттенка. */
  --gradient-brand: linear-gradient(90deg, var(--cat-event) 0%, rgba(245, 165, 36, .75) 100%);
  --gradient-violet: linear-gradient(90deg, #8742EE 0%, #A970FF 100%);

  /* Градиентный редизайн лендинга/каталога (docs-project/design-web3/
     max-haven-gradient.html, вариант «C · Весь фон») - подробности и
     цифры контраста в docs-project/theme-tokens/TOKENS.md. Эти два имени
     объявлены здесь (в общем :root) просто как значения - они ничего не
     красят сами по себе, пока их не использует конкретный селектор, и
     используются только в scope-блоках body.catalog-dark/
     body.landing-gradient ниже, поэтому reward_home.html/for_business.html
     (тоже catalog.css, но без этих классов) не задеты.
     --gradient-cta - заливка главных кнопок/активного чипа: тот же
     градиент, но синий и бирюзовый стопы затемнены так, чтобы БЕЛЫЙ текст
     поверх давал не ниже 4.5:1 в любой точке градиента (проверено
     сэмплированием 5000 точек вдоль пути, не только на стопах). Без
     затемнения синий стоп сам по себе даёт 4.4988:1 (не проходит),
     бирюзовый - 2.16:1. Итог: фиолетовый 5.19:1, синий 5.56:1, бирюзовый
     5.06:1, минимум по всему пути - 5.06:1. */
  --gradient-brand-mesh: linear-gradient(120deg, #8742EE 0%, #2F6BFF 55%, #12C2D9 100%);
  --gradient-cta: linear-gradient(120deg, #8742EE 0%, #2A5EE0 55%, #0B7A88 100%);

  /* Палитра градиентного редизайна (этап 0 общей задачи "гостевые экраны") -
     каждое значение объявлено ровно один раз здесь, а не в каждом
     scope-блоке (body.catalog-dark/.catalog-light-preview/landing-gradient
     ниже — раньше эти же hex-значения были продублированы по 2 раза на
     тему). Сами блоки ниже теперь только присваивают --mesh-*, --glass-*
     и --gradient-text из этих --gh-*-dark/-light по своим правилам (когда
     светлая/тёмная — правила остаются как были, значения не менялись).
     Общее место специально в :root (а не в отдельном файле) — это тот же
     файл catalog.css, который уже участвует в reward_home.html/
     for_business.html без применения этих токенов (не используются, пока
     конкретный body-класс их не запросит), и будущие гостевые экраны
     (витрины, /max/app/) берут отсюда же, без третьего дубля значений. */
  --gh-mesh-a-dark: #3B1D78; --gh-mesh-b-dark: #15317A; --gh-mesh-c-dark: #0B5563; --gh-mesh-o-dark: #5A2A08;
  --gh-mesh-page-base-dark: #0D0B1C;
  --gh-glass-bg-dark: rgba(23, 20, 43, .55);
  --gh-glass-bg-fallback-dark: rgba(23, 20, 43, .92);
  --gh-glass-border-dark: rgba(255, 255, 255, .10);
  --gh-gradient-text-dark: linear-gradient(120deg, #CFB3F8 0%, #A5BFFF 55%, #4BD1E2 100%);

  --gh-mesh-a-light: #E9DEFF; --gh-mesh-b-light: #D6E4FF; --gh-mesh-c-light: #CFF3F8; --gh-mesh-o-light: #FFE3C9;
  --gh-mesh-page-base-light: #FBFAFD;
  --gh-glass-bg-light: rgba(255, 255, 255, .62);
  --gh-glass-bg-fallback-light: rgba(255, 255, 255, .92);
  --gh-glass-border-light: rgba(255, 255, 255, .7);
  --gh-gradient-text-light: linear-gradient(120deg, #7C3DDB 0%, #285AD7 55%, #0A6E7B 100%);

  /* Текст на стекле (ink/ink2) и статусные пары (ok/warn/err) — те же
     hex, что уже использует мастер первого запуска (onboarding_wizard.html)
     и прототип (onboarding-prototype.html, docs-project/onboarding/), там
     были объявлены локально в <style> каждой страницы. Здесь — то же
     значение, просто под общим именем, для редизайна портала (block 1,
     docs-project/portal-redesign/) и любых будущих страниц на этой же
     сетке/стекле. Контраст текста: ink2 на mesh-page-base светлый
     6.21:1, тёмный >7:1 (см. отчёт задачи в docs-project/portal-redesign/
     block1/); ok/warn/err — те же пары уже проходят как текст err-banner/
     warn-banner мастера (14px, обычный текст, в контуре 4.5:1). */
  --gh-ink-dark: #F1EEFA; --gh-ink2-dark: #B3AECB; --gh-line-dark: #2B2745; --gh-chip-dark: #221E3A;
  --gh-ink-light: #17142A; --gh-ink2-light: #5B5873; --gh-line-light: #DDD8EA; --gh-chip-light: #F0ECF8;
  --gh-ok-dark: #6FE0AE; --gh-ok-bg-dark: rgba(111, 224, 174, .14);
  --gh-ok-light: #0E7A4E; --gh-ok-bg-light: #DDF5EA;
  --gh-warn-dark: #FFC46B; --gh-warn-bg-dark: rgba(255, 196, 107, .14);
  --gh-warn-light: #8A5300; --gh-warn-bg-light: #FFF0D6;
  --gh-err-dark: #FF8A80; --gh-err-bg-dark: rgba(255, 138, 128, .14);
  --gh-err-light: #B3261E; --gh-err-bg-light: #FBE9E7;
  /* "Заблокировано" — фиксированные цвета вне темы (тот же приём, что
     .demo-badge в showcase.html: не зависит от --gh-*, чтобы явно выделяться
     в обеих темах). Белый текст на #7A1E17 — 10.4:1. */
  --gh-blocked-bg: #7A1E17; --gh-blocked-text: #ffffff;

  /* Цвета категорий каталога — используются картой, бейджами и легендой.
     --cat-service затемнён с исходного #007AFF (шаг theme-guest, этап 1):
     на исходном значении и белый, и тёмный (--ink) текст бейджа/чипа не
     проходили 4.5:1 (4.02:1 и 4.30:1 соответственно) — единственная
     категория, где не проходил ни один вариант текста. Новое значение
     даёт 6.13:1 с белым текстом, тот же синий оттенок, только темнее. */
  --cat-hotel: #8742EE;
  --cat-service: #0060BF;
  --cat-tour: #17A34A;
  --cat-event: #F5A524;
  --cat-cafe: #B45309;

  /* Иконки категорий — свой инлайновый SVG (без внешних наборов), маска:
     форма берётся из data-URI, цвет — из background-color элемента. */
  --icon-hotel: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='3' y='11' width='18' height='6' rx='2' fill='black'/%3E%3Crect x='5' y='8' width='6' height='4' rx='1.5' fill='black'/%3E%3Crect x='4' y='17' width='2' height='3' fill='black'/%3E%3Crect x='18' y='17' width='2' height='3' fill='black'/%3E%3C/svg%3E");
  --icon-service: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='6' cy='12' r='3.2' fill='none' stroke='black' stroke-width='2.6' stroke-dasharray='14 6' stroke-dashoffset='3'/%3E%3Ccircle cx='18' cy='12' r='3.2' fill='none' stroke='black' stroke-width='2.6' stroke-dasharray='14 6' stroke-dashoffset='13'/%3E%3Crect x='8.2' y='10.6' width='7.6' height='2.8' rx='1.2' fill='black'/%3E%3C/svg%3E");
  --icon-tour: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M2 19 L8 7 L12 13 L16 7 L22 19 Z' fill='black'/%3E%3C/svg%3E");
  --icon-event: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='3.5' y='7.5' width='17' height='9' rx='2.5' fill='none' stroke='black' stroke-width='2'/%3E%3Cline x1='12' y1='7.5' x2='12' y2='16.5' stroke='black' stroke-width='2' stroke-dasharray='2.4 2.4'/%3E%3C/svg%3E");
  --icon-cafe: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 3.5c0 .9-1.2 1-1.2 2s1.2 1.1 1.2 2' stroke='black' stroke-width='1.5' stroke-linecap='round' fill='none'/%3E%3Cpath d='M13 3.5c0 .9-1.2 1-1.2 2s1.2 1.1 1.2 2' stroke='black' stroke-width='1.5' stroke-linecap='round' fill='none'/%3E%3Cpath d='M5 10h11v5a4 4 0 01-4 4H9a4 4 0 01-4-4v-5z' fill='black'/%3E%3Cpath d='M16 11.5h1.5a2 2 0 110 4H16' stroke='black' stroke-width='2' fill='none'/%3E%3Crect x='4' y='19' width='14' height='2' rx='1' fill='black'/%3E%3C/svg%3E");

  --bg: var(--surface);
  --text: var(--ink);
  --text-2: var(--ink-2);
  --text-muted: var(--muted);
  --card-bg: #ffffff;
  /* Граница с 0.08 до 0.14 - на светлом фоне тонкая граница едва читалась
     (задание светлой темы, п.2: "границы на светлом заметны сильнее - брать
     легче"). --chip-border уже была на этом уровне (.14), теперь совпадают. */
  --card-border: rgba(34, 18, 58, 0.14);
  --header-bg: rgba(242, 239, 247, 0.72);
  --chip-bg: #ffffff;
  --chip-border: rgba(34, 18, 58, 0.14);
  --chip-bg-hover: rgba(34, 18, 58, 0.05);
  --chip-border-hover: rgba(245, 165, 36, 0.4);
  --chip-text: var(--ink-2);
  --hero-bg: linear-gradient(180deg, var(--brand-violet-bg) 0%, var(--surface) 62%);
  --shadow-card: 0 1px 2px rgba(34, 18, 58, .06), 0 10px 24px rgba(34, 18, 58, .08);
  --shadow-card-hover: 0 4px 10px rgba(34, 18, 58, .10), 0 18px 34px rgba(34, 18, 58, .14);
  --map-empty-bg: rgba(242, 239, 247, .94);
  color-scheme: light;

  /* Задел под тему: те же имена по назначению, что в base.html портала и
     showcase.html витрины - здесь просто алиасы на уже существующие выше
     переменные catalog.css, значения не меняются. */
  --color-bg: var(--bg);
  --color-surface: var(--card-bg);
  --color-text: var(--text);
  --color-text-muted: var(--text-muted);
  --color-border: var(--card-border);
  --color-accent: var(--cat-event);
  /* Тёмная карточка "награды дня" в шапке каталога - та же, что в
     showcase.html (общий бренд программы лояльности, не тема страницы). */
  --color-reward-panel-from-rgb: 30 41 59;  /* #1e293b */
  --color-reward-panel-to-rgb: 15 23 42;    /* #0f172a */
  --color-reward-text-rgb: 226 232 240;     /* #e2e8f0 */
  --color-overlay-rgb: 255 255 255;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: var(--dark-bg);
    --text: var(--dark-ink);
    --text-2: var(--dark-ink);
    --text-muted: #9b98a3;
    --card-bg: var(--dark-surface);
    --card-border: var(--dark-border);
    --header-bg: rgba(24, 24, 24, .72);
    --chip-bg: var(--dark-surface-2);
    --chip-border: var(--dark-border);
    --chip-bg-hover: #333333;
    --chip-border-hover: rgba(245, 165, 36, 0.4);
    --chip-text: var(--dark-ink);
    --hero-bg: linear-gradient(180deg, rgba(135, 66, 238, .16) 0%, var(--dark-bg) 62%);
    --shadow-card: 0 1px 2px rgba(0, 0, 0, .4), 0 10px 24px rgba(0, 0, 0, .35);
    --shadow-card-hover: 0 4px 12px rgba(0, 0, 0, .5), 0 18px 36px rgba(0, 0, 0, .45);
    --map-empty-bg: rgba(29, 29, 29, .92);
    color-scheme: dark;
  }
}

/* Каталог (/catalog/) — всегда тёмная тема, независимо от системной темы
   телефона (MAX Haven — тёмный бренд, гость не должен видеть светлую
   страницу внутри тёмного мини-аппа/шапки MAX). Скоуп через класс на body
   catalog.html, а НЕ правка @media (prefers-color-scheme) выше — тот общий
   для всего catalog.css (тем же файлом стилизуются for_business.html и
   landing.html, которые в этой задаче не трогаем и которые должны
   остаться адаптивными). Значения — те же самые, что уже в @media выше,
   просто без условия на системную тему. */
body.catalog-dark {
  --bg: var(--dark-bg);
  --text: var(--dark-ink);
  --text-2: var(--dark-ink);
  /* Было #9b98a3 (2.97:1 на самом ярком пятне фона-сетки - не проходит
     4.5:1, см. TOKENS.md) - для body.catalog-dark это теперь не только
     карточки поверх --card-bg, но и текст прямо поверх сетки (hero-support/
     hero-subtitle, .section-lead и т.п. в градиентном редизайне), поэтому
     поднято до значения приглушённого текста тёмной карточки "Награда дня"
     (5.25:1 на том же самом ярком пятне). Внутри стеклянных карточек это
     значение тоже проходит (было 4.78:1 на composite - с запасом теперь). */
  --text-muted: #CFC8EA;
  --card-bg: var(--dark-surface);
  --card-border: var(--dark-border);
  --header-bg: rgba(24, 24, 24, .72);
  --chip-bg: var(--dark-surface-2);
  --chip-border: var(--dark-border);
  --chip-bg-hover: #333333;
  --chip-border-hover: rgba(245, 165, 36, 0.4);
  --chip-text: var(--dark-ink);
  --hero-bg: linear-gradient(180deg, rgba(135, 66, 238, .16) 0%, var(--dark-bg) 62%);
  --shadow-card: 0 1px 2px rgba(0, 0, 0, .4), 0 10px 24px rgba(0, 0, 0, .35);
  --shadow-card-hover: 0 4px 12px rgba(0, 0, 0, .5), 0 18px 36px rgba(0, 0, 0, .45);
  --map-empty-bg: rgba(29, 29, 29, .92);
  color-scheme: dark;

  /* Градиентный редизайн - фон-сетка/стекло/градиентный текст, тёмная
     тема. Цифры контраста - docs-project/theme-tokens/TOKENS.md. */
  --mesh-a: var(--gh-mesh-a-dark); --mesh-b: var(--gh-mesh-b-dark); --mesh-c: var(--gh-mesh-c-dark); --mesh-o: var(--gh-mesh-o-dark);
  --mesh-page-base: var(--gh-mesh-page-base-dark);
  --glass-bg: var(--gh-glass-bg-dark);
  --glass-bg-fallback: var(--gh-glass-bg-fallback-dark);
  --glass-border: var(--gh-glass-border-dark);
  /* Текст ПОВЕРХ градиента (акцентное слово в заголовке) - не то же самое,
     что --gradient-cta (тому нужен контраст БЕЛОГО текста НА себе, этому -
     контраст своего цвета к фону-сетке под ним). Осветлено до 4.5:1+ на
     самом ярком пятне тёмной сетки (мин. 4.53:1 по всему пути градиента,
     проверено сэмплированием). */
  --gradient-text: var(--gh-gradient-text-dark);
}

/* Временный просмотр светлой темы каталога до переключателя (шаг 2 из 3,
   docs-project/theme-tokens/LIGHT_THEME_REPORT.md). ?theme=light в адресе ->
   catalog.html/catalog_category.html добавляют класс инлайн-скриптом в
   <body> (ничего не сохраняют, работают только пока параметр есть в URL).
   Значения продублированы, а не просто "снять .catalog-dark" - нужно
   перебить и media (prefers-color-scheme: dark) выше, который иначе
   вернул бы тёмную тему на телефоне с системной тёмной темой. Двойной
   класс даёт специфичность выше одиночного .catalog-dark. */
body.catalog-dark.catalog-light-preview {
  --bg: var(--surface);
  --text: var(--ink);
  --text-2: var(--ink-2);
  --text-muted: var(--muted);
  --card-bg: #ffffff;
  --card-border: rgba(34, 18, 58, 0.14);
  --header-bg: rgba(242, 239, 247, 0.72);
  --chip-bg: #ffffff;
  --chip-border: rgba(34, 18, 58, 0.14);
  --chip-bg-hover: rgba(34, 18, 58, 0.05);
  --chip-border-hover: rgba(245, 165, 36, 0.4);
  --chip-text: var(--ink-2);
  --hero-bg: linear-gradient(180deg, var(--brand-violet-bg) 0%, var(--surface) 62%);
  --shadow-card: 0 1px 2px rgba(34, 18, 58, .06), 0 10px 24px rgba(34, 18, 58, .08);
  --shadow-card-hover: 0 4px 10px rgba(34, 18, 58, .10), 0 18px 34px rgba(34, 18, 58, .14);
  --map-empty-bg: rgba(242, 239, 247, .94);
  color-scheme: light;

  /* Градиентный редизайн - фон-сетка/стекло/градиентный текст, светлая
     тема (просмотр). Цифры контраста - docs-project/theme-tokens/TOKENS.md. */
  --mesh-a: var(--gh-mesh-a-light); --mesh-b: var(--gh-mesh-b-light); --mesh-c: var(--gh-mesh-c-light); --mesh-o: var(--gh-mesh-o-light);
  --mesh-page-base: var(--gh-mesh-page-base-light);
  --glass-bg: var(--gh-glass-bg-light);
  --glass-bg-fallback: var(--gh-glass-bg-fallback-light);
  --glass-border: var(--gh-glass-border-light);
  /* Затемнено до 4.5:1+ на самом светлом пятне светлой сетки (мин. 4.60:1
     по всему пути градиента). */
  --gradient-text: var(--gh-gradient-text-light);
}

/* Те же токены градиентного редизайна для лендинга (body.landing-gradient,
   см. landing.html) - отдельный scope, не body.catalog-dark, т.к. у
   лендинга нет принудительной тёмной темы/переключателя ("как сейчас" -
   только системная тема через prefers-color-scheme, см. CLAUDE.md-задачу).
   Светлая - значения по умолчанию здесь, тёмная - переопределение ниже
   в @media(prefers-color-scheme:dark). Раздельный класс, а не правка
   бэйр :root/media(dark) выше - там же reward_home.html/for_business.html,
   их трогать нельзя (см. docs-project/theme-tokens/TOKENS.md). */
body.landing-gradient {
  --mesh-a: var(--gh-mesh-a-light); --mesh-b: var(--gh-mesh-b-light); --mesh-c: var(--gh-mesh-c-light); --mesh-o: var(--gh-mesh-o-light);
  --mesh-page-base: var(--gh-mesh-page-base-light);
  --glass-bg: var(--gh-glass-bg-light);
  --glass-bg-fallback: var(--gh-glass-bg-fallback-light);
  --glass-border: var(--gh-glass-border-light);
  --gradient-text: var(--gh-gradient-text-light);
}
@media (prefers-color-scheme: dark) {
  body.landing-gradient {
    --mesh-a: var(--gh-mesh-a-dark); --mesh-b: var(--gh-mesh-b-dark); --mesh-c: var(--gh-mesh-c-dark); --mesh-o: var(--gh-mesh-o-dark);
    --mesh-page-base: var(--gh-mesh-page-base-dark);
    --glass-bg: var(--gh-glass-bg-dark);
    --glass-bg-fallback: var(--gh-glass-bg-fallback-dark);
    --glass-border: var(--gh-glass-border-dark);
    --gradient-text: var(--gh-gradient-text-dark);
    /* Тот же фикс, что у --text-muted в body.catalog-dark выше (2.97:1 на
       самом ярком пятне тёмной сетки не проходит 4.5:1) - на лендинге
       приглушённый текст (.transition-subtitle, .section-lead, .stat-label
       и т.п.) местами лежит прямо на сетке, а не на стекле. */
    --text-muted: #CFC8EA;
  }
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img { max-width: 100%; }
a { color: inherit; }
.wrap { max-width: 1240px; margin: 0 auto; padding: 0 20px; }

/* ------------------------------------------------------------------ */
/* Градиентный редизайн (docs-project/design-web3/max-haven-gradient.html, */
/* вариант «C · Весь фон») - фон-сетка на весь экран, стекло для карточек/ */
/* чипов/кнопок-иконок, градиентная заливка главных кнопок/активного      */
/* чипа, градиентный текст акцентного слова. Область действия -           */
/* body.catalog-dark (catalog.html/catalog_category.html) и               */
/* body.landing-gradient (landing.html) - см. токены выше и в             */
/* docs-project/theme-tokens/TOKENS.md. reward_home.html/for_business.html */
/* тоже используют catalog.css, но ни один из этих классов не получают -  */
/* не задеты. */

/* Шрифты редизайна (Unbounded для заголовков, Manrope для остального
   текста) - подключены только в catalog.html/catalog_category.html/
   landing.html (<link> с family=Unbounded:wght@500;700&family=Manrope:
   wght@400;500;600;700&display=swap, тот же набор весов, что в эталоне).
   font-display:swap - в самом URL шрифта, задержки отрисовки не будет
   (текст рисуется запасным шрифтом сразу, подменяется после загрузки).
   Область действия та же, что у фон-сетки ниже - body.catalog-dark/
   body.landing-gradient, reward_home.html/for_business.html не задеты. */
body.catalog-dark, body.landing-gradient, body.gh-guest-mesh {
  font-family: 'Manrope', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
body.catalog-dark .hero-headline,
body.catalog-dark .cat-row-title,
body.catalog-dark .cat-page-title,
body.catalog-dark .hero-wordmark,
body.landing-gradient .transition-title,
body.landing-gradient .section-title,
body.landing-gradient .cta-title,
body.gh-guest-mesh .gh-heading {
  font-family: 'Unbounded', 'Manrope', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* Фон-сетка - раньше background-attachment:fixed прямо на body. Часть
   мобильных браузеров/WebView историческ хуже поддерживают fixed-attachment
   на скроллящемся элементе, чем десктопный Chromium (headless-эмуляция
   этого не показывает - см. AUDIT.md, риск №5), а сам приём "фон не
   скроллится вместе с контентом" гораздо надёжнее кросс-браузерно
   достигается обычным position:fixed на отдельном элементе. Поэтому сетка
   вынесена в псевдоэлемент ::before (position:fixed, за контентом через
   z-index:-1), а на самом body остаётся только сплошная заливка
   var(--mesh-page-base) - тот же тон, что база сетки, поэтому если по
   какой-то причине псевдоэлемент не отрисуется, под текстом останется
   фон нужной темы (тёмный/светлый), а не белый по умолчанию браузера. */
body.catalog-dark, body.landing-gradient, body.gh-guest-mesh {
  background: var(--mesh-page-base);
}
body.catalog-dark::before,
body.landing-gradient::before,
body.gh-guest-mesh::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(95% 60% at 12% 6%, var(--mesh-a), transparent 72%),
    radial-gradient(90% 65% at 92% 20%, var(--mesh-b), transparent 72%),
    radial-gradient(95% 65% at 22% 90%, var(--mesh-c), transparent 72%),
    radial-gradient(70% 55% at 92% 96%, var(--mesh-o), transparent 72%);
  background-size: 130% 130%;
}
/* Движение фона - только на лендинге и главном экране каталога
   (body.catalog-home, см. catalog.html), НЕ на странице категории
   (catalog_category.html - тот же body.catalog-dark, но без .catalog-home,
   фон статичный). opt-in внутри no-preference (MOTION_LANGUAGE.md, п.6/10) -
   при reduce фон остаётся на начальном кадре (0% 0%), без анимации. */
@media (prefers-reduced-motion: no-preference) {
  body.catalog-home::before, body.landing-gradient::before {
    animation: mh-mesh-drift 22s ease-in-out infinite alternate;
  }
}
@keyframes mh-mesh-drift {
  0% { background-position: 0% 0%; }
  50% { background-position: 100% 40%; }
  100% { background-position: 30% 100%; }
}

/* Стекло для карточек/чипов/кнопок-иконок каталога. Запасной почти
   непрозрачный фон по умолчанию (--glass-bg-fallback) - для браузеров без
   backdrop-filter, поверх - @supports с настоящим стеклом+блюром. */
body.catalog-dark .poi-card,
body.catalog-dark .chip,
body.catalog-dark .hero-chip,
body.catalog-dark .map-legend-toggle,
body.catalog-dark .map-legend-list,
body.catalog-dark .cat-row-count,
body.catalog-dark .empty-panel,
body.catalog-dark .search-suggest,
body.catalog-dark .search-input,
body.catalog-dark .catalog-map-wrap,
body.catalog-dark .cat-row-placeholder {
  background: var(--glass-bg-fallback);
  border-color: var(--glass-border);
}
body.landing-gradient .step-card,
body.landing-gradient .benefit-tile,
body.landing-gradient .lead-card,
body.landing-gradient .faq-item {
  background: var(--glass-bg-fallback);
  border-color: var(--glass-border);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  body.catalog-dark .poi-card,
  body.catalog-dark .chip,
  body.catalog-dark .hero-chip,
  body.catalog-dark .map-legend-toggle,
  body.catalog-dark .map-legend-list,
  body.catalog-dark .cat-row-count,
  body.catalog-dark .empty-panel,
  body.catalog-dark .search-suggest,
  body.catalog-dark .search-input,
  body.catalog-dark .cat-row-placeholder,
  body.landing-gradient .step-card,
  body.landing-gradient .benefit-tile,
  body.landing-gradient .lead-card,
  body.landing-gradient .faq-item {
    background: var(--glass-bg);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
  }
}

/* ------------------------------------------------------------------ */
/* Общий хук + утилитные классы для остальных гостевых экранов (витрины,
   /max/app/ и т.п., этап 0/1 задачи "гостевые экраны на градиентном
   редизайне") - catalog.css остаётся общим местом для значений токенов
   (--gh-*-dark/-light выше), а конкретная страница со своими именами
   классов компонентов (не .poi-card/.chip и т.п. из каталога) вешает
   body.gh-guest-mesh + СВОЙ класс тёмной темы (см. showcase.html
   body.theme-dark) и берёт готовые .gh-glass/.gh-gradient-cta-bg/
   .gh-gradient-text вместо того, чтобы catalog.css знал имена чужих
   классов. Палитра по умолчанию здесь - светлая (переопределяется
   темой конкретной страницы, как body.landing-gradient переопределяет
   через @media(prefers-color-scheme:dark) выше). Фон-сетка статичная
   (не входит в @media(prefers-reduced-motion) с анимацией выше) - по
   заданию у витрин/мини-аппа фон-сетка неподвижная, как у
   catalog_category.html. */
body.gh-guest-mesh {
  --mesh-a: var(--gh-mesh-a-light); --mesh-b: var(--gh-mesh-b-light); --mesh-c: var(--gh-mesh-c-light); --mesh-o: var(--gh-mesh-o-light);
  --mesh-page-base: var(--gh-mesh-page-base-light);
  --glass-bg: var(--gh-glass-bg-light);
  --glass-bg-fallback: var(--gh-glass-bg-fallback-light);
  --glass-border: var(--gh-glass-border-light);
  --gradient-text: var(--gh-gradient-text-light);
}
.gh-glass {
  background: var(--glass-bg-fallback);
  border-color: var(--glass-border);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .gh-glass {
    background: var(--glass-bg);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
  }
}
.gh-gradient-cta-bg {
  background: var(--gradient-cta);
  color: #fff;
  border-color: transparent;
}
.gh-gradient-text {
  background: var(--gradient-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Баннер "Играй и копи монеты" в каталоге (#reward-open-btn, catalog.html) -
   переведён на фиолетово-синее стекло эталона (design-web3/max-haven-
   gradient.html, вариант "C · Весь фон", блок "Награда дня"). НЕ переиспользует
   --color-reward-panel-*-rgb из :root выше - те же переменные читает
   scratch-card.css, который грузит и reward_home.html (/reward/, трогать
   нельзя), поэтому у баннера свои значения, независимые от темы каталога
   (карта бренда программы лояльности, а не тема страницы - так же было
   с исходным чёрным фоном). border-color на var(--glass-border) - тот же
   токен, что у остальных стеклянных элементов каталога, значение уже
   переключается по body.catalog-dark/.catalog-light-preview. Контраст текста
   проверен на реальном composite (просвечивает фон-сетка под 85%-прозрачным
   градиентом) - самое тёмное и самое светлое пятно, см. LOG_2026-09-20. */
.reward-banner {
  background: rgba(30, 20, 62, .98);
  border: 1px solid var(--glass-border);
  border-radius: 14px;
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .reward-banner {
    background: linear-gradient(120deg, rgba(42, 23, 96, .85), rgba(18, 48, 95, .85));
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
  }
}
.reward-banner-icon {
  display: block;
  flex: none;
  width: 44px;
  height: 44px;
  padding: 6px;
  box-sizing: border-box;
  border-radius: 12px;
  background: var(--gradient-cta);
}
.reward-banner-cta {
  color: #A5BFFF;
}

/* .stat-tile (счётчики "сейчас в каталоге") никогда не было карточкой
   (нет фона/рамки) - оставлено как есть, текст лежит прямо на сетке, не на
   стекле, поэтому .stat-label (--text-muted) должен проходить контраст
   именно к сетке - см. правку --text-muted в body.landing-gradient выше. */
/* Активный чип категории (было - заливка цветом самой категории, см.
   .chip.is-active ниже по файлу) и главные кнопки/sticky-cta - теперь общий
   градиент бренда, белый текст (см. --gradient-cta выше, контраст к белому
   не ниже 4.5:1 в любой точке пути). */
body.catalog-dark .chip.is-active,
body.landing-gradient .btn-primary,
body.catalog-dark .sticky-cta {
  background: var(--gradient-cta);
  color: #fff;
  border-color: transparent;
}

/* hero — гибридный блок v2 (2026-09): строка "знак + инлайн-поиск" (словесный
   знак сюда не помещается — при 26px знаке и поле поиска реальный замер на
   360px даёт только ~292px под поле, полное слово "MAX Haven" туда не влезает
   вместе с читаемым полем, поэтому в этой строке — только монограмма из
   brand/v2), крупный заголовок с янтарным акцентным словом, приглушённая
   строка поддержки, быстрые подсказки.
   Раньше (до theme-guest, этап 1) блок был форсированно тёмным независимо от
   темы страницы - это и есть "шапка не светлеет" из задачи. Переведено на
   темы: --dark-surface/--dark-bg -> --card-bg/--bg, --dark-ink -> --text,
   хардкод #9b98a3 -> --text-muted (то же самое значение в тёмной теме -
   value совпадает буква в букву, см. --text-muted в body.catalog-dark, так
   что тёмный рендер не сдвигается ни на пиксель). --cat-event (amber) как
   акцент не трогаем - он не про тему, а про бренд, одинаков в обеих темах. */
.hero {
  padding: 18px 0 14px;
  background:
    radial-gradient(120% 90% at 12% 0%, rgba(245, 165, 36, .10) 0%, rgba(245, 165, 36, 0) 55%),
    linear-gradient(180deg, var(--card-bg) 0%, var(--bg) 100%);
}
/* Вариант «C · Весь фон»: у шапки нет своего фона - сквозь неё видна
   фон-сетка страницы (body.catalog-dark, см. выше), а не отдельная
   амбер-подложка. */
body.catalog-dark .hero { background: transparent; }
.hero-inner { display: flex; flex-direction: column; align-items: flex-start; width: 100%; }
.hero-topline { display: flex; align-items: center; gap: 10px; width: 100%; margin-bottom: 14px; }
.hero-lockup { display: inline-flex; align-items: center; gap: 9px; text-decoration: none; flex: none; }
.hero-mark { display: block; width: 26px; height: 26px; flex: none; }
.hero-wordmark { font-weight: 800; font-size: 1rem; letter-spacing: -.01em; color: var(--text); }
.hero-headline { margin: 0 0 6px; font-weight: 800; letter-spacing: -.015em; line-height: 1.2; font-size: 1.15rem; color: var(--text); max-width: 620px; }
.hero-headline .accent { color: var(--cat-event); }
/* Акцентное слово - градиентный текст (см. --gradient-text выше, цвета
   подобраны под контраст 4.5:1+ к самой светлой/тёмной точке сетки под
   ним, отдельно от --gradient-cta, который считался под белый текст НА
   градиенте, а не под сам градиент КАК текст). */
body.catalog-dark .hero-headline .accent {
  background: var(--gradient-text); -webkit-background-clip: text; background-clip: text; color: transparent;
}
.hero-support { margin: 0 0 12px; color: var(--text-muted); font-size: .82rem; line-height: 1.35; max-width: 560px; }
.hero-subtitle { margin: 0 0 12px; color: var(--text-muted); font-size: .86rem; line-height: 1.35; max-width: 560px; }
.search-box { position: relative; flex: 1; min-width: 0; }
/* Вариант «C · Весь фон»: поле поиска - стекло, как .ic/чипы в эталоне
   (не янтарная рамка старого стиля) - фон/рамка задаются общим блоком
   стекла выше (body.catalog-dark .search-input). Иконка - нейтральный
   приглушённый цвет, как у .ic в эталоне (там тоже не крашена акцентом);
   акцент в шапке несёт градиентное слово в заголовке (.hero-headline
   .accent), не сама иконка поиска. */
.search-box svg { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 17px; height: 17px; color: var(--text-muted); }
.search-input {
  width: 100%; min-height: 44px; padding: 10px 12px 10px 36px; border-radius: 12px; border: 1.5px solid var(--card-border);
  background: var(--chip-bg); color: var(--text); font-size: .86rem;
}
.search-input::placeholder { color: var(--text-muted); }
.search-input:focus { outline: 2px solid var(--cat-event); outline-offset: 1px; }
/* Фокус - тот же язык акцента, что у активных элементов редизайна
   (градиент, не янтарь): кольцо в цвете первого стопа --gradient-cta. */
body.catalog-dark .search-input:focus { outline-color: var(--brand-violet-light); }

/* Подсказки поиска (площадки/города) — та же тёмная стилистика, радиусы и
   тень, что у остальных всплывающих панелей каталога (см. .map-legend-list),
   но позиционируется относительно .search-box (position:relative), а не
   через fixed+расчёт координат в JS — панель всегда той же ширины, что и
   поле, и не требует пересчёта при скролле/ресайзе. */
.search-suggest {
  position: absolute; z-index: 1400; left: 0; right: 0; top: calc(100% + 6px);
  max-height: 320px; overflow-y: auto;
  background: var(--chip-bg); border: 1px solid var(--card-border); border-radius: 14px;
  padding: 6px; box-shadow: var(--shadow-card-hover);
}
.search-suggest[hidden] { display: none; }
.search-suggest-group-title {
  font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); padding: 8px 8px 4px;
}
.search-suggest-item {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px; width: 100%; text-align: left;
  border: none; background: transparent; color: var(--text); font: inherit; padding: 8px;
  border-radius: 8px; cursor: pointer;
}
.search-suggest-item:focus-visible { background: rgba(245, 165, 36, .14); }
.search-suggest-item-name { font-weight: 700; font-size: .84rem; color: var(--text); }
.search-suggest-item-meta { font-size: .74rem; color: var(--text-muted); }
.search-suggest-empty { font-size: .8rem; color: var(--text-muted); padding: 10px 8px; max-width: 260px; }

.hero-suggestions { display: flex; gap: 8px; overflow-x: auto; }
.hero-chip {
  flex: none; display: inline-flex; align-items: center; gap: 5px; padding: 7px 13px; border-radius: 999px;
  background: var(--chip-bg); border: 1px solid var(--card-border); color: var(--text);
  font-size: .78rem; font-weight: 600; font: inherit; cursor: pointer;
}

/* Баннер "Играй и копи монеты" (catalog.html, #reward-open-btn) - фон и текст
   инлайновые в разметке, намеренно всегда тёмные независимо от темы страницы
   (общий бренд программы лояльности, не тема страницы - см. TOKENS.md/
   LIGHT_THEME_REPORT.md, полный светлый ремейк модуля - отдельная кратно
   большая задача). Заголовок/подзаголовок/"Открыть" на своём фиксированном
   тёмном фоне проходят контраст всегда (7.2-11.9:1) - не трогаем. Только
   рамка: без акцента тёмная карточка на светлой странице читалась как
   забытая тёмная заплатка (задача theme-guest, этап 1, "выглядит
   недоделкой"). Янтарное кольцо + мягкая тень оформляют её как приём
   (акцентная premium-карточка), а не как баг. Тёмная тема не меняется (та
   же rgba(255,255,255,.08), что раньше жила в инлайн-style).
   Найдено при этапе 3 ("общий язык взаимодействия"): третья строка
   ("Доступно в приложении MAX", inline color:#64748b в catalog.html) не
   проходила совсем - 3.07:1 в покое, ещё ниже под :active filter. Заявленные
   ранее "14.48:1 для всего текста" считались не по этой строке - реальный
   порог не проверялся для неё отдельно. Цвет заменён на #8e9bae (та же
   slate-подача, светлее) - 5.19:1 в покое, 4.64:1 под :active. */
#reward-open-btn { border: 1px solid rgb(var(--color-overlay-rgb) / .08); }
body.catalog-dark.catalog-light-preview #reward-open-btn {
  border-color: rgba(245, 165, 36, .35);
  box-shadow: 0 10px 24px rgba(34, 18, 58, .12), 0 0 0 1px rgba(245, 165, 36, .12);
}
/* Наведение/нажатие - общий язык взаимодействия каталога (MOTION_LANGUAGE.md
   §5: scale(0.96/0.97), --motion-instant/--ease-out, filter вместо анимации
   box-shadow по кадрам). Фон/текст банера тёмные независимо от темы (см.
   выше) - тут только форма отклика, не цвет, контраст не меняется. */
#reward-open-btn:active { filter: brightness(0.92); }
@media (prefers-reduced-motion: no-preference) {
  #reward-open-btn { transition: transform 100ms cubic-bezier(0, 0, .2, 1); }
  #reward-open-btn:active { transform: scale(0.97); }
}

/* category chips */
.chip-row { display: flex; gap: 8px; overflow-x: auto; padding: 14px 0 14px; scrollbar-width: none; }
.chip-row::-webkit-scrollbar { display: none; }
.chip {
  flex: none; border: 1px solid var(--chip-border); background: var(--chip-bg); color: var(--chip-text);
  padding: 9px 16px; border-radius: 999px; font-size: .85rem; font-weight: 600; cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.chip[data-category="hotel"] { --chip-accent: var(--cat-hotel); }
.chip[data-category="service"] { --chip-accent: var(--cat-service); }
.chip[data-category="tour"] { --chip-accent: var(--cat-tour); }
.chip[data-category="event"] { --chip-accent: var(--cat-event); }
.chip[data-category="cafe"] { --chip-accent: var(--cat-cafe); }
.chip[data-category="all"] { --chip-accent: var(--cat-event); }
.chip.is-active { background: var(--chip-accent, var(--cat-event)); border-color: transparent; color: #fff; }
/* Амбер (--cat-event, 2.04:1) и зелёный (--cat-tour, 3.29:1) как активный
   фон не проходят 4.5:1 с белым текстом — на них ink (8.46:1 и 5.24:1
   соответственно). Остальные категории (hotel 5.19:1, service 6.13:1 после
   затемнения выше, cafe 5.02:1) проходят с белым по умолчанию, не трогаем. */
.chip[data-category="all"].is-active, .chip[data-category="event"].is-active, .chip[data-category="tour"].is-active { color: var(--ink); }
/* Нажатие - лёгкое затемнение/сжатие, безопасно и для мыши (:active), и
   для тач (тап), т.к. :active снимается сам по отпускании/уходу пальца и
   не может "залипнуть" так, как залипает :hover после тапа. Наведение -
   отдельно, ниже, в общем touch-safe блоке (см. коммент там же). */
.chip:active { filter: brightness(0.92); }
@media (prefers-reduced-motion: no-preference) {
  .chip { transition: background .15s ease, color .15s ease, border-color .15s ease, transform 100ms cubic-bezier(0, 0, .2, 1); }
  .chip:active { transform: scale(0.97); }
}

/* Наведение (:hover) для всего каталога/витрины - в одном месте, одним
   условием. На тач-экране нет курсора: после тапа браузер может оставить
   элемент в состоянии :hover до следующего тапа в стороне ("залипание").
   (hover: hover) matches только там, где ввод действительно умеет наводить
   указатель без нажатия (мышь/трекпад) - тот же признак, которым в
   catalog.js уже отличают десктоп от тач для попапа карты (см. HOVER_CAPABLE,
   matchMedia('(hover: hover) and (pointer: fine)')). Все touch-небезопасные
   :hover-правила каталога собраны здесь, а не разбросаны по каждому
   компоненту - один и тот же приём применяется одинаково везде. */
@media (hover: hover) and (pointer: fine) {
  .hero-chip:hover { color: var(--cat-event); }
  .chip:hover:not(.is-active) { background: var(--chip-bg-hover); border-color: var(--chip-border-hover); }
  .search-suggest-item:hover { background: rgba(245, 165, 36, .14); }
  .cat-row-head-link:hover .cat-row-title { color: var(--cat-event); }
  .cat-row-head-link:hover .cat-row-arrow { color: var(--cat-event); }
  .poi-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-card-hover); border-color: rgba(245, 165, 36, .55); }
  .poi-cta:hover { text-decoration: underline; }
  #reward-open-btn:hover { box-shadow: 0 10px 24px rgba(34, 18, 58, .18), 0 0 0 1px rgba(245, 165, 36, .3); }
  .sticky-cta:hover { box-shadow: 0 14px 30px rgba(34, 18, 58, .22); }
  .map-legend-toggle:hover { border-color: rgba(245, 165, 36, .55); box-shadow: var(--shadow-card-hover); }
}

/* category icons — общие для бейджей, маркеров, попапа, легенды и рядов */
.cat-glyph {
  display: inline-block; flex: none;
  background-color: #fff;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
}
.cat-glyph[data-category="hotel"] { -webkit-mask-image: var(--icon-hotel); mask-image: var(--icon-hotel); }
.cat-glyph[data-category="service"] { -webkit-mask-image: var(--icon-service); mask-image: var(--icon-service); }
.cat-glyph[data-category="tour"] { -webkit-mask-image: var(--icon-tour); mask-image: var(--icon-tour); }
.cat-glyph[data-category="event"] { -webkit-mask-image: var(--icon-event); mask-image: var(--icon-event); }
.cat-glyph[data-category="cafe"] { -webkit-mask-image: var(--icon-cafe); mask-image: var(--icon-cafe); }

.cat-icon-circle {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  border-radius: 50%; background: var(--cat-event);
}
.cat-icon-circle[data-category="hotel"] { background: var(--cat-hotel); }
.cat-icon-circle[data-category="service"] { background: var(--cat-service); }
.cat-icon-circle[data-category="tour"] { background: var(--cat-tour); }
.cat-icon-circle[data-category="event"] { background: var(--cat-event); }
.cat-icon-circle[data-category="cafe"] { background: var(--cat-cafe); }

/* rows + map layout — карта слева (sticky), ряды категорий справа */
.catalog-layout { display: grid; grid-template-columns: minmax(320px, 420px) minmax(0, 1fr); gap: 24px; align-items: start; padding-bottom: 48px; }
.catalog-rows { display: flex; flex-direction: column; gap: 22px; min-width: 0; }
.catalog-map-wrap {
  position: sticky; top: 16px; height: calc(100vh - 40px); min-height: 360px;
  border-radius: 20px; overflow: hidden; border: 1px solid var(--card-border); box-shadow: var(--shadow-card);
}
#catalog-map { width: 100%; height: 100%; background: var(--card-bg); }
.map-empty-hint {
  position: absolute; z-index: 500; left: 50%; top: 14px; transform: translateX(-50%);
  background: var(--map-empty-bg); border: 1px solid var(--card-border); color: var(--text);
  padding: 8px 14px; border-radius: 12px; font-size: .8rem; max-width: 88%; text-align: center;
  box-shadow: var(--shadow-card); pointer-events: none;
}

.map-legend { position: absolute; z-index: 500; left: 10px; bottom: 10px; }
.map-legend-toggle {
  display: none; align-items: center; gap: 6px; border: 1px solid var(--card-border);
  background: var(--card-bg); color: var(--text); font-size: .78rem; font-weight: 700;
  padding: 8px 12px; border-radius: 999px; box-shadow: var(--shadow-card); cursor: pointer;
}
/* Наведение/нажатие - общий язык взаимодействия каталога (см. #reward-open-btn
   выше и общий hover-блок ниже), кнопка - scale(0.96), не 0.97 (крупные
   карточки). Фон/текст - var(--card-bg)/var(--text), тот же контраст, что и
   в покое - filter/scale не меняют цвет. */
.map-legend-toggle:active { filter: brightness(0.92); }
@media (prefers-reduced-motion: no-preference) {
  .map-legend-toggle { transition: transform 100ms cubic-bezier(0, 0, .2, 1), background .15s ease, border-color .15s ease; }
  .map-legend-toggle:active { transform: scale(0.96); }
}
.map-legend-list {
  display: flex; flex-direction: column; gap: 6px; background: var(--card-bg);
  border: 1px solid var(--card-border); border-radius: 12px; padding: 8px 10px;
  box-shadow: var(--shadow-card);
}
.map-legend-item { display: flex; align-items: center; gap: 6px; font-size: .72rem; color: var(--text); white-space: nowrap; }
.map-legend-item .cat-icon-circle { width: 18px; height: 18px; }
.map-legend-item .cat-glyph { width: 10px; height: 10px; }

@media (max-width: 640px) {
  .map-legend-toggle { display: inline-flex; }
  .map-legend-list { display: none; position: absolute; left: 0; bottom: calc(100% + 8px); min-width: 168px; }
  .map-legend.is-open .map-legend-list { display: flex; }
}

@media (max-width: 900px) {
  .catalog-layout { grid-template-columns: 1fr; }
  .catalog-map-wrap { position: relative; top: auto; height: 280px; }
  /* Решение владельца (пробуем) - на телефоне карта ниже разделов с
     площадками, а не сверху. Только order (не перестановка в разметке) -
     на десктопе (>900px, разметка не тронута) карта остаётся слева, DOM-
     порядок для скринридеров тоже не меняется. */
  .catalog-map-wrap { order: 2; }
  .catalog-rows { order: 1; }
}

/* category rows — заголовок ряда + горизонтальный слайдер карточек */
.cat-row-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.cat-row-title { display: flex; align-items: center; gap: 8px; margin: 0; font-size: 1.05rem; font-weight: 800; color: var(--text); letter-spacing: -.01em; }
.cat-row-title .cat-icon-circle { width: 26px; height: 26px; }
.cat-row-title .cat-glyph { width: 13px; height: 13px; }
.cat-row-count { font-size: .78rem; font-weight: 700; color: var(--text-muted); background: var(--chip-bg); border: 1px solid var(--chip-border); border-radius: 999px; padding: 3px 10px; flex: none; }

/* заголовок ряда - ссылка на страницу категории; область нажатия во всю
   ширину строки (сама .cat-row-head), стрелка - тот же svg-шеврон, что и
   у кнопки "Открыть" выше в catalog.html. Отклик на нажатие - по
   docs-project/MOTION_LANGUAGE.md, п.5 (scale(0.97) для крупных
   тап-целей, 100мс, ease-out), opt-in через prefers-reduced-motion (п.6). */
.cat-row-head-link { text-decoration: none; color: inherit; border-radius: 12px; }
.cat-row-head-right { display: flex; align-items: center; gap: 8px; flex: none; }
.cat-row-arrow { color: var(--text-muted); flex: none; }
@media (prefers-reduced-motion: no-preference) {
  .cat-row-head-link { transition: transform 100ms cubic-bezier(0, 0, .2, 1); }
  .cat-row-head-link:active { transform: scale(0.97); }
}

.cat-row { position: relative; }
.cat-row.is-hidden { display: none; }
/* Подсказка прокрутки - раньше была отдельным ::after-прямоугольником,
   залитым --glass-bg-fallback (сплошной, почти непрозрачный токен) поверх
   фон-сетки (составные radial-gradient, не сплошной цвет) - на границе
   получался виден жёсткий прямоугольник другого тона, а сама высота
   псевдоэлемента (top:30px/bottom:12px) не совпадала с высотой карточек,
   давая ещё и "ступеньку" снизу. Теперь без заливки вообще: mask-image
   прямо на скролл-контейнере плавно доводит альфа-канал САМИХ карточек до
   0 у правого края - виден настоящий фон под ними, каким бы он ни был, а
   высота маски равна высоте .cat-row-track (= высоте карточек), без
   выхода за их пределы. */
.cat-row-track {
  display: flex; gap: 14px; overflow-x: auto; scroll-snap-type: x proximity;
  padding: 2px 2px 12px; margin: 0 -2px; -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 34px), transparent 100%);
  mask-image: linear-gradient(to right, #000 calc(100% - 34px), transparent 100%);
}
.cat-row-track .poi-card.is-hidden { display: none; }

/* заглушка для категории без площадок — не прячем, показываем "в разработке".
   opacity на всём блоке раньше приглушала и подпись .cat-row-placeholder-caption
   вместе с фоном - из-за смешивания с --bg под ней эффективный контраст падал
   до 4.44:1 в тёмной теме и 4.18:1 в светлой (обе ниже 4.5:1). Приглушённость
   даёт пунктирная граница + сам --text-muted, opacity на блоке убран; на
   иконке (.cat-row-placeholder-icon) opacity остаётся - это декоративная
   картинка, не текст. */
.cat-row-placeholder {
  display: flex; align-items: center; gap: 14px; background: var(--card-bg); border: 1px dashed var(--card-border);
  border-radius: 16px; padding: 16px;
}
.cat-row-placeholder-icon { width: 40px; height: 40px; opacity: .7; }
.cat-row-placeholder-icon .cat-glyph { width: 20px; height: 20px; }
.cat-row-placeholder-title { font-weight: 700; font-size: .92rem; color: var(--text); }
.cat-row-placeholder-caption { font-size: .8rem; color: var(--text-muted); margin-top: 2px; }

/* cards — фиксированная ширина плитки для горизонтального ряда */
.poi-card {
  display: flex; gap: 14px; background: var(--card-bg); border: 1px solid var(--card-border);
  border-radius: 16px; padding: 12px; box-shadow: var(--shadow-card);
  flex: 0 0 280px; scroll-snap-align: start; cursor: pointer;
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
/* .is-active - тот же визуальный "подъём", что и hover, но ставится JS при
   выборе площадки на карте (highlightCard, catalog.js) - не связано с
   курсором/тапом, поэтому вне touch-safe блока ниже. */
.poi-card.is-active { transform: translateY(-3px); box-shadow: var(--shadow-card-hover); border-color: rgba(245, 165, 36, .55); }
.poi-card:focus-visible { outline: 2px solid var(--cat-event); outline-offset: 2px; }
.poi-cover { width: 88px; height: 88px; flex: none; border-radius: 12px; object-fit: cover; background: var(--chip-bg); }
.poi-cover-placeholder {
  width: 88px; height: 88px; flex: none; border-radius: 12px; display: flex; align-items: center;
  justify-content: center; font-weight: 700; font-size: 1.6rem; color: var(--ink); background: var(--gradient-brand);
}
.poi-body { min-width: 0; display: flex; flex-direction: column; gap: 4px; flex: 1; }
.poi-badge {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 4px;
  font-size: .7rem; font-weight: 700; padding: 3px 9px 3px 7px; border-radius: 999px;
  color: var(--ink); background: var(--cat-event);
}
.poi-badge .cat-glyph, .popup-badge .cat-glyph { width: 10px; height: 10px; }
.poi-badge[data-category="hotel"] { background: var(--cat-hotel); }
.poi-badge[data-category="service"] { background: var(--cat-service); }
.poi-badge[data-category="tour"] { background: var(--cat-tour); }
.poi-badge[data-category="event"] { background: var(--cat-event); }
.poi-badge[data-category="cafe"] { background: var(--cat-cafe); }
/* Бейдж по умолчанию кладёт ink (тёмный) текст на фон категории - на hotel
   (3.33:1), cafe (3.44:1) и старом service это не проходило 4.5:1 (см.
   контраст выше и в docs-project/theme-tokens/LIGHT_THEME_REPORT.md). На
   этих трёх фонах белый текст проходит (5.19:1 / 5.02:1 / 6.13:1), на
   tour/event остаётся ink (5.24:1 / 8.46:1) - значение не меняется. */
.poi-badge[data-category="hotel"], .poi-badge[data-category="service"], .poi-badge[data-category="cafe"] { color: #fff; }
.poi-name { font-weight: 700; font-size: .95rem; color: var(--text); }
.poi-meta { font-size: .78rem; color: var(--text-muted); }
.poi-desc { font-size: .8rem; color: var(--text-muted); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* Каталог теперь всегда тёмный (body.catalog-dark) — амбер-текст на
   --card-bg (var(--dark-surface)) даёт ~8:1, безопасно (было адаптивным
   var(--text-2), т.к. в светлой теме амбер-текст на белом давал ~2:1). */
.poi-cta { align-self: flex-start; margin-top: 4px; font-size: .8rem; font-weight: 700; color: var(--cat-event); text-decoration: none; }
/* На светлом card-bg (#fff) амбер-текст --cat-event даёт 2.04:1 - не проходит.
   Тёмное значение (8.46:1 на --dark-surface) не трогаем - правим только под
   .catalog-light-preview точечно, тёмный рендер не задет. #9A6400 - тот же
   оттенок темнее, 5.00:1 на белом. */
body.catalog-dark.catalog-light-preview .poi-cta { color: #9A6400; }

/* leaflet markers/popups */
.poi-marker-wrap { display: flex; align-items: center; justify-content: center; }
.poi-marker {
  width: 36px; height: 36px; border: 2px solid #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .35), 0 1px 3px rgba(0, 0, 0, .25);
  transition: width .15s ease, height .15s ease, box-shadow .15s ease;
}
.poi-marker .cat-glyph { width: 56%; height: 56%; }
.poi-marker.is-active {
  width: 44px; height: 44px;
  box-shadow: 0 5px 16px rgba(0, 0, 0, .5), 0 2px 6px rgba(0, 0, 0, .3);
}

.poi-popup .leaflet-popup-content-wrapper { border-radius: 14px; box-shadow: var(--shadow-card-hover); background: var(--card-bg); color: var(--text); }
.poi-popup .leaflet-popup-content { margin: 12px 14px; }
.poi-popup .leaflet-popup-tip { background: var(--card-bg); }
.popup-head { display: flex; align-items: center; gap: 9px; margin-bottom: 6px; }
.popup-icon { width: 32px; height: 32px; flex: none; }
.popup-icon-logo { border-radius: 50%; overflow: hidden; background: var(--chip-bg); border: 1px solid var(--chip-border); }
.popup-icon-logo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.popup-title { font-weight: 700; font-size: .9rem; color: var(--text); min-width: 0; }
.popup-badge { display: inline-flex; align-items: center; gap: 4px; font-size: .65rem; font-weight: 700; padding: 3px 8px; border-radius: 999px; color: var(--ink); background: var(--cat-event); }
.popup-badge[data-category="hotel"] { background: var(--cat-hotel); }
.popup-badge[data-category="service"] { background: var(--cat-service); }
.popup-badge[data-category="tour"] { background: var(--cat-tour); }
.popup-badge[data-category="event"] { background: var(--cat-event); }
.popup-badge[data-category="cafe"] { background: var(--cat-cafe); }
/* Тот же разбор текста, что у .poi-badge выше. */
.popup-badge[data-category="hotel"], .popup-badge[data-category="service"], .popup-badge[data-category="cafe"] { color: #fff; }
.popup-meta { font-size: .75rem; color: var(--text-muted); margin: 6px 0 0; }
.popup-desc { font-size: .75rem; color: var(--text-muted); margin: 4px 0 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.popup-cta { display: inline-block; background: var(--cat-event); color: var(--ink); font-weight: 700; font-size: .75rem; padding: 7px 12px; border-radius: 9px; text-decoration: none; }

/* empty states */
.empty-panel { background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 16px; padding: 40px 20px; text-align: center; color: var(--text-muted); }

/* ------------------------------------------------------------------ */
/* Страница одной категории (/catalog/<category>/) - вертикальный      */
/* список карточек .poi-card на всю ширину, вместо горизонтального     */
/* ряда .cat-row-track. Карточка и её внутренняя разметка не меняются. */
/* ------------------------------------------------------------------ */
.cat-page { padding: 20px 20px 48px; }
.cat-page-back { margin: 0 0 18px; }
.cat-page-title { display: flex; align-items: center; gap: 10px; margin: 0 0 20px; font-size: 1.25rem; font-weight: 800; color: var(--text); letter-spacing: -.01em; }
.cat-page-title .cat-icon-circle { width: 32px; height: 32px; }
.cat-page-title .cat-glyph { width: 16px; height: 16px; }
.cat-page-list { display: flex; flex-direction: column; gap: 14px; }
/* сбрасываем фиксированную ширину/высоту карточки из горизонтального ряда
   (.poi-card { flex: 0 0 280px }) - в колонке flex-basis работает по
   высоте, а не по ширине, поэтому без сброса карточки станут 280px в
   высоту с пустым местом. */
.cat-page-list .poi-card { flex: 0 0 auto; width: 100%; }

@media (max-width: 480px) {
  .poi-card { flex-basis: 240px; }
  .poi-cover, .poi-cover-placeholder { width: 72px; height: 72px; }
}

/* sticky mobile CTA — единственное, что осталось от продающего блока на главной.
   z-index значительно выше максимума, который использует сам Leaflet
   (.leaflet-top/.leaflet-bottom — 1000, попапы — 700, маркеры — 600), чтобы
   кнопка гарантированно принимала клик, даже если маркер или попап карты
   окажется в той же точке экрана. pointer-events не завязан на .is-visible:
   .sticky-cta — position:fixed с явным z-index, поэтому document.elementFromPoint
   в её точке экрана и так возвращал бы саму кнопку, а не карту под ней (тайлы
   карты — z-index:auto, ниже любого явного z-index на этом уровне контекста);
   но раньше pointer-events:none до появления класса is-visible снимал кнопку
   с hit-testing целиком, и в её координатах "нащупывался" элемент карты под
   ней — ровно то, что не пропускало обычный (не force/JS) клик.  */
/* Ссылка на канал MAX в подвале каталога (задача "канал в MAX", 23.09.2026) -
   спокойная, малозаметная, не главное действие страницы. Цвета - через
   --text/--text-muted, уже переключаются темой (body.catalog-dark/
   .catalog-light-preview, см. :root выше). */
.catalog-footer { padding: 18px 0 96px; text-align: center; }
.catalog-footer-max-link {
  font-size: .8rem; color: var(--text-muted); text-decoration: none;
  border-bottom: 1px solid transparent;
}
.catalog-footer-max-link:hover, .catalog-footer-max-link:focus-visible {
  color: var(--text); border-bottom-color: currentColor;
}
@media (max-width: 640px) {
  /* sticky-cta на этой ширине - left+right:16px, bottom:16px, поверх
     контента (см. комментарий у .sticky-cta ниже) - запас снизу, чтобы
     ссылка не пряталась под кнопкой, когда гость долистал до низа. */
  .catalog-footer { padding-bottom: 108px; }
}

.sticky-cta {
  display: block;
  position: fixed; right: 24px; bottom: 24px; z-index: 1200;
  background: var(--gradient-brand); color: var(--ink); text-align: center;
  padding: 15px 28px; border-radius: 14px; font-weight: 700; font-size: .9rem; text-decoration: none;
  box-shadow: var(--shadow-card-hover);
  opacity: 0; transform: translateY(12px); transition: opacity .2s ease, transform .2s ease;
}
/* Выше 640px left не задан - fixed-блок с одним заданным offset (right) и
   width:auto считается по содержимому (shrink-to-fit), кнопка не тянется
   на всю ширину экрана (см. п.1 задачи - "ширина по содержимому"). */
.sticky-cta.is-visible { opacity: 1; transform: translateY(0); }
/* Наведение/нажатие - общий язык взаимодействия каталога (см. #reward-open-btn
   выше). Кнопка - scale(0.96). Нажатие комбинируется с translateY(0) появления
   (.is-visible), а не заменяет его - иначе scale перебивает transform появления
   и кнопка на миг "прыгает" на 12px. --ink на --gradient-brand не меняется -
   контраст тот же, что и в покое. */
.sticky-cta:active { filter: brightness(0.92); }
@media (prefers-reduced-motion: no-preference) {
  .sticky-cta.is-visible:active { transform: translateY(0) scale(0.96); }
}
@media (max-width: 640px) {
  .sticky-cta { left: 16px; right: 16px; bottom: 16px; padding: 15px; }
  /* На этой ширине sticky-cta растягивается на всю ширину (left+right:16px) и
     перекрывает низ страницы, включая карту с картой каталога и её кнопку
     «Легенда» (карта на мобильной ширине - последний блок перед этой
     кнопкой, order:2, см. .catalog-map-wrap выше). Отступ ниже - с запасом
     не меньше высоты самой кнопки (padding 15px сверху/снизу + строка
     текста ~50px) + её bottom-offset (16px) + обязательный видимый зазор
     (16px), плюс safe-area на устройствах с "домашней полосой" снизу -
     чтобы при прокрутке до конца карта и «Легенда» были полностью видны
     над кнопкой. */
  .catalog-layout { padding-bottom: calc(16px + 56px + 24px + env(safe-area-inset-bottom)); }
}

/* ------------------------------------------------------------------ */
/* Страница «для бизнеса» — продающая часть, вынесенная с главной      */
/* ------------------------------------------------------------------ */

.fb-header {
  position: sticky; top: 0; z-index: 60; background: var(--header-bg);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--card-border);
}
.fb-header-inner { padding: 12px 20px; }
.fb-back {
  display: inline-flex; align-items: center; gap: 8px; text-decoration: none;
  font-weight: 700; font-size: .88rem; color: var(--text-2);
}
.fb-back svg { width: 18px; height: 18px; }
.fb-back:hover { color: var(--text); }

.section { padding: 56px 0; }
.section-title { margin: 0 0 28px; font-size: clamp(1.3rem, 3vw, 1.8rem); font-weight: 800; letter-spacing: -.01em; color: var(--text); }
.section-lead { margin: 8px 0 0; color: var(--text-muted); font-size: .95rem; max-width: 480px; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; white-space: nowrap;
  border-radius: 12px; padding: 13px 22px; font-weight: 700; font-size: .9rem;
  text-decoration: none; border: none; cursor: pointer; flex: none;
}
.btn-primary { background: var(--gradient-brand); color: var(--ink); box-shadow: var(--shadow-card); }
.btn-large { padding: 16px 30px; font-size: 1rem; border-radius: 14px; }
/* Наведение/нажатие - тот же общий язык взаимодействия, что и у остальных
   кнопок каталога/витрины (см. .chip/.map-legend-toggle выше): :active
   безопасен и для мыши, и для тача, :hover - только там, где есть настоящий
   указатель. */
.btn:active { filter: brightness(0.92); }
@media (prefers-reduced-motion: no-preference) {
  .btn { transition: transform 100ms cubic-bezier(0, 0, .2, 1), box-shadow .15s ease; }
  .btn:active { transform: scale(0.97); }
}
@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover { box-shadow: var(--shadow-card-hover); }
}

/* Кнопки-примеров на лендинге ("Отель"/"Кафе / ресторан" и т.п.,
   BusinessUnit.is_demo) - оборачиваются на узкой ширине, не растягивают
   .demo-inner горизонтально (390px, без горизонтальной прокрутки). */
.demo-buttons { display: flex; flex-wrap: wrap; gap: 12px; }

/* transition */
.business-transition {
  background: var(--gradient-brand); color: var(--ink); text-align: center; padding: 48px 0;
}
/* Вариант «C · Весь фон»: секция без своей заливки - сквозь неё видна
   фон-сетка body.landing-gradient (см. выше), поэтому текст возвращается
   на обычные токены страницы (--text/--text-muted) вместо ink-на-цвете. */
body.landing-gradient .business-transition { background: transparent; color: var(--text); }
body.landing-gradient .transition-subtitle { opacity: 1; color: var(--text-muted); }
.transition-eyebrow { margin: 0 0 8px; font-size: .8rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; opacity: .85; }
.transition-title { margin: 0 0 10px; font-size: clamp(1.5rem, 4vw, 2.1rem); font-weight: 800; letter-spacing: -.01em; }
.transition-subtitle { margin: 0 auto; max-width: 560px; font-size: .95rem; opacity: .92; }
/* Акцентное слово заголовка лендинга ("внутри MAX") - тот же градиентный
   текст, что "город" в каталоге (см. .hero-headline .accent выше). */
body.landing-gradient .transition-title .accent {
  background: var(--gradient-text); -webkit-background-clip: text; background-clip: text; color: transparent;
}

/* demo */
.demo-inner { display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap; }

/* steps */
.steps-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.step-card {
  background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 16px;
  padding: 22px; box-shadow: var(--shadow-card);
}
.step-icon {
  display: flex; align-items: center; justify-content: center; width: 44px; height: 44px;
  border-radius: 12px; background: rgba(245, 165, 36, .14); color: var(--text); margin-bottom: 14px;
}
.step-icon svg { width: 22px; height: 22px; }
.step-title { font-weight: 700; font-size: 1rem; color: var(--text); margin-bottom: 6px; }
.step-text { margin: 0 0 10px; font-size: .85rem; color: var(--text-muted); line-height: 1.5; }
.step-time { font-size: .75rem; font-weight: 700; color: var(--text-2); }

/* benefits */
.benefits-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
.benefit-tile {
  background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 16px;
  padding: 20px; box-shadow: var(--shadow-card);
}
.benefit-icon {
  display: flex; align-items: center; justify-content: center; width: 40px; height: 40px;
  border-radius: 10px; background: rgba(245, 165, 36, .14); color: var(--text); margin-bottom: 12px;
}
.benefit-icon svg { width: 20px; height: 20px; }
.benefit-title { font-weight: 700; font-size: .92rem; color: var(--text); margin-bottom: 4px; }
.benefit-text { margin: 0; font-size: .82rem; color: var(--text-muted); line-height: 1.5; }

/* stats */
.stats-row { display: flex; gap: 40px; flex-wrap: wrap; }
.stat-tile { display: flex; flex-direction: column; gap: 2px; }
.stat-number { font-size: clamp(2rem, 5vw, 2.6rem); font-weight: 800; letter-spacing: -.02em; color: var(--text); }
.stat-label { font-size: .85rem; color: var(--text-muted); font-weight: 600; }

/* cta */
.cta-section { text-align: center; }
.cta-inner { display: flex; flex-direction: column; align-items: center; gap: 20px; }
.cta-title { margin: 0; font-size: clamp(1.3rem, 3.4vw, 1.9rem); font-weight: 800; letter-spacing: -.01em; color: var(--text); max-width: 620px; }

/* faq */
.faq-list { display: flex; flex-direction: column; gap: 10px; max-width: 760px; }
.faq-item {
  background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 14px;
  padding: 4px 18px; box-shadow: var(--shadow-card);
}
.faq-item summary {
  cursor: pointer; padding: 14px 0; font-weight: 700; font-size: .92rem; color: var(--text);
  list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: "+"; float: right; font-weight: 700; color: var(--text-2); }
.faq-item[open] summary::after { content: "−"; }
.faq-item p { margin: 0 0 16px; font-size: .85rem; color: var(--text-muted); line-height: 1.55; }

/* тарифы - онбординг блок Б, этап 2 (/landing/, блок "Тарифы") */
.plans-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; align-items: stretch; }
.plan-card {
  display: flex; flex-direction: column; gap: 10px;
  background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 16px;
  padding: 24px; box-shadow: var(--shadow-card); position: relative;
}
.plan-card--popular { border: 2px solid transparent; background: linear-gradient(var(--card-bg), var(--card-bg)) padding-box, var(--gradient-cta) border-box; }
.plan-badge {
  align-self: flex-start; font-size: .68rem; font-weight: 700; color: #fff;
  background: var(--gradient-cta); border-radius: 999px; padding: 3px 10px;
}
.plan-name { font-weight: 800; font-size: 1.05rem; color: var(--text); margin: 0; }
.plan-price { font-weight: 700; font-size: 1.3rem; color: var(--text); }
.plan-price--tbd { font-size: .95rem; font-weight: 600; color: var(--text-muted); }
.plan-features { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.plan-features li { font-size: .85rem; color: var(--text-muted); padding-left: 18px; position: relative; }
.plan-features li::before { content: "✓"; position: absolute; left: 0; color: var(--text); font-weight: 700; }
.plan-cta { margin-top: 8px; text-align: center; }

@media (max-width: 900px) {
  .plans-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
  .plans-grid { grid-template-columns: 1fr; }
}

/* footer страницы «для бизнеса» — всегда тёмный, независимо от темы */
.site-footer { background: var(--dark-bg); color: var(--dark-ink); padding: 26px 0; }
.footer-inner { max-width: 1240px; margin: 0 auto; padding: 0 20px; display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: space-between; font-size: .825rem; }
.footer-inner a { color: var(--dark-ink); font-weight: 600; text-decoration: underline; }

/* lead-форма — перенесена с прежнего отдельного /landing/ (2026-09), теперь
   низ страницы «для бизнеса». Поля формы/имена/honeypot не менялись —
   только внешний вид, под общую стилистику страницы (адаптивная тема,
   как остальные секции выше). */
.lead-card {
  background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 20px;
  padding: 28px; box-shadow: var(--shadow-card); max-width: 640px; margin: 0 auto;
}
.lead-alert { margin: 16px 0 0; padding: 14px 16px; border-radius: 14px; border: 1px solid var(--card-border); }
.lead-alert--ok { border-color: rgba(23, 163, 74, .35); background: rgba(23, 163, 74, .08); }
.lead-alert--error { border-color: rgba(220, 38, 38, .35); background: rgba(220, 38, 38, .08); }
.lead-alert-title { font-weight: 700; color: var(--text); }
.lead-alert-text { font-size: .85rem; color: var(--text-muted); margin-top: 4px; }
.lead-form { margin-top: 18px; display: flex; flex-direction: column; gap: 14px; }
.lead-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.lead-field { display: flex; flex-direction: column; gap: 6px; }
.lead-field label { font-size: .78rem; font-weight: 600; color: var(--text-muted); }
.lead-field input, .lead-field select, .lead-field textarea {
  border-radius: 12px; border: 1px solid var(--card-border); background: var(--bg); color: var(--text);
  padding: 11px 14px; font-size: .92rem; font-family: inherit;
}
.lead-field input:focus, .lead-field select:focus, .lead-field textarea:focus { outline: 2px solid var(--cat-event); outline-offset: 1px; }
.lead-submit { width: 100%; }
.lead-consent { margin: 0; font-size: .75rem; color: var(--text-muted); line-height: 1.5; }

@media (max-width: 900px) {
  .steps-row { grid-template-columns: 1fr; }
  .benefits-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 560px) {
  .lead-row { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .demo-inner { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 480px) {
  .benefits-grid { grid-template-columns: 1fr; }
  .section { padding: 40px 0; }
}
