/* ==========================================================================
   Биокластер — интерфейсный слой дизайн-системы (UI-kit)
   --------------------------------------------------------------------------
   Надстройка над brand-assets/tokens/tokens.css.
   Брендбук интерфейс не описывает — см. DESIGN-SYSTEM.md §16, пункт 6 списка
   «запросить у правообладателя». Всё ниже — [решение ДС], выведенное из правил
   брендбука и не противоречащее им.

   Жёсткие правила, которые здесь соблюдены:
   · радиус 0 — базовая геометрия бренда без скруглений (--bk-radius)
   · на лайме текст только «тёмный лес» или чёрный; белый на лайме запрещён
   · лайм на белом запрещён
   · Река / Слива / Виноград на тёмном — только заливки, никогда текст
   · логотип не ложится на фото, калейдоскоп и паттерн → шапка всегда на плашке
   · в блоке не более 2–3 начертаний, ровно один акцент
   · motion: от центра, 400–600 мс, cubic-bezier(.22,.61,.36,1)
   ========================================================================== */

/* ?v=2 — метка версии файла шрифта, не украшение. 03.09.2026 сам файл
   переcобран: в присланном .otf у 51 глифа из 53 ширина внутри контура
   была нулевой, и на Windows все буквы слова ложились в одну точку.
   Имя файла не менялось, а `.htaccess` отдаёт шрифты с `Expires: 1 year` —
   без этой метки тот, кто уже был на сайте, ещё год получал бы сломанный
   файл из кэша. Пересобрали шрифт — увеличьте число.
   Сборка — build/build-bioklaster-webfont.py, разбор — в 2-РЕШЕНИЯ-И-ГРАБЛИ.md. */
@font-face {
  font-family: "Bioklaster 2.1";
  src: url("../brand-assets/typography/font/Bioklaster21-Regular.woff2?v=2") format("woff2"),
       url("../brand-assets/typography/font/Bioklaster21-Regular.woff?v=2") format("woff");
  font-weight: 400;
  font-display: swap;
  /* только прописная кириллица, цифры и пунктуация — латиницы и строчных в шрифте нет */
  unicode-range: U+0410-042F, U+0401, U+0030-0039, U+0021, U+0028-0029,
                 U+002C, U+002E, U+003A-003B, U+003F;
}

/* --------------------------------------------------------------------------
   1. Компонентные токены — третий слой поверх примитивов и семантики
   -------------------------------------------------------------------------- */
:root {
  /* шкала отступов, шаг 4, базовый ритм 8 */
  --bk-s-1:  4px;  --bk-s-2:  8px;  --bk-s-3: 12px;  --bk-s-4: 16px;
  --bk-s-5: 24px;  --bk-s-6: 32px;  --bk-s-7: 48px;  --bk-s-8: 64px;
  --bk-s-9: 96px;  --bk-s-10: 128px;

  /* вертикальный ритм секций */
  --bk-section-y: clamp(56px, 7vw, 128px);

  /* Плашка поверх фотографии: под текстом слайда и под управлением слайдера.
     Одно значение на оба места — разъехавшись, они сразу читаются как ошибка.
     0,80 — нижняя допустимая граница, посчитана по контрасту; почему именно
     столько, написано у .bk-showcase--photo .bk-showcase__body. */
  --bk-plate: rgba(19, 50, 43, .80);
  /* Высота свёрнутой плашки и плашки управления. Они стоят по краям одного
     нижнего края слайда и обязаны совпадать по высоте. Обе берут высоту
     из этого числа, а не из содержимого: круглая кнопка со стрелкой и кружок
     раскрытия оказались разной высоты на три пикселя, и плашки не сошлись. */
  --bk-plate-h: 76px;

  /* элементы управления */
  --bk-ctl-h-s: 40px;
  --bk-ctl-h:   48px;
  --bk-ctl-h-l: 56px;
  --bk-ctl-px:  24px;

  /* motion [ДС §17.4] */
  --bk-dur:      440ms;
  --bk-dur-fast: 180ms;
  --bk-ease:     cubic-bezier(.22, .61, .36, 1);

  /* состояния — выведены из палитры через color-mix, новых цветов не вводим */
  --bk-accent-hover:  color-mix(in srgb, var(--bk-juicy-lime) 88%, var(--bk-dark-forest));
  --bk-accent-active: color-mix(in srgb, var(--bk-juicy-lime) 76%, var(--bk-dark-forest));
  --bk-surface-hover: color-mix(in srgb, var(--bk-surface) 88%, var(--bk-juicy-lime));
  --bk-border-strong: rgba(208, 239, 54, .48);
  --bk-overlay:       rgba(9, 24, 20, .78);

  /* статусы. Рябина на тёмном = 2,84 — только плашки и крупный текст */
  --bk-danger:  var(--bk-rowan);
  --bk-success: var(--bk-juicy-lime);
  --bk-notice:  var(--bk-warm-sand);

  /* акценты шести направлений [ББ с.28–33, 46] */
  --bk-dir-buzzing-world:  var(--bk-orange);       /* Жужжащий мир */
  --bk-dir-dinosaur-world: var(--bk-fresh-grass);  /* Мир динозавров */
  --bk-dir-12-signs:       var(--bk-warm-sand);    /* 12 признаков живого */
  --bk-dir-greenhouse-lab: var(--bk-peony);        /* Оранжерея-Лаборатория */
  --bk-dir-floratopia:     var(--bk-rowan);        /* Флоратопия */
  --bk-dir-museum-of-life: var(--bk-grape);        /* Музей жизни */

  /* z-слои */
  --bk-z-header: 100;
  --bk-z-dropdown: 110;
  --bk-z-overlay: 200;
  --bk-z-modal: 210;
  --bk-z-tooltip: 300;
}

/* --------------------------------------------------------------------------
   2. База
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bk-bg);
  color: var(--bk-text);
  font-family: var(--bk-font-body);
  font-size: 17px;
  line-height: 1.3;
  -webkit-font-smoothing: antialiased;
}

img, svg { display: block; max-width: 100%; }
a { color: inherit; }

/* Фокус: единый для всего интерфейса. Лайм — --bk-focus из tokens.css */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--bk-focus);
  outline-offset: 2px;
}

::selection { background: var(--bk-accent); color: var(--bk-text-on-accent); }

/* Светлая секция — на ней меняются семантические токены, компоненты не трогаем */
.bk-on-light {
  background: var(--bk-bg-light);
  --bk-text: var(--bk-text-on-light);
  --bk-text-muted: rgba(19, 50, 43, .68);
  --bk-surface: #FFFFFF;
  --bk-border: rgba(19, 50, 43, .16);
  --bk-border-strong: rgba(19, 50, 43, .32);
  --bk-focus: var(--bk-dark-forest);
  color: var(--bk-text);
}

/* На светлой секции лайм текстом запрещён: контраст лайма на белом 1,31 [ДС §7.4].
   Семантические токены этого не ловят — --bk-accent остаётся лаймом, потому что
   заливки и рамки на светлом фоне лаймовыми быть могут, а текст нет. Поэтому
   акцентный ТЕКСТ переопределяем отдельно: он становится «тёмным лесом».
   Правило общее для всех компонентов, а не заплатка на один блок. */
.bk-on-light :is(.bk-overline, .bk-accent, .bk-ticket__price b, .bk-eventrow__day, .bk-cal__ev) {
  color: var(--bk-text-on-light);
}

/* --------------------------------------------------------------------------
   3. Сетка и раскладка [ДС §12.6]
   -------------------------------------------------------------------------- */
.bk-container {
  --bk-cols: 12;
  --bk-gutter-fluid: clamp(12px, 1.18vw, 24px);
  /* Поле вынесено в переменную не для красоты: элемент, лежащий в контейнере
     абсолютом, считает координаты от padding-box, то есть от края окна,
     а не от края текста. Без общего числа он встал бы по другой линии,
     чем всё остальное на странице, и разъехался бы при смене ширины. */
  --bk-pad: clamp(20px, 4.55vw, 120px);
  width: 100%;
  max-width: 1920px;
  margin-inline: auto;
  padding-inline: var(--bk-pad);
}

.bk-grid {
  display: grid;
  grid-template-columns: repeat(var(--bk-cols, 12), minmax(0, 1fr));
  column-gap: var(--bk-gutter-fluid, 24px);
  row-gap: var(--bk-s-6);
}

@media (max-width: 1023px) { .bk-container { --bk-cols: 8; } }
@media (max-width: 599px)  { .bk-container { --bk-cols: 4; } }

.bk-section { padding-block: var(--bk-section-y); }

/* автосетка карточек — минимальная ширина колонки задаётся --min */
.bk-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(var(--min, 300px), 100%), 1fr));
  gap: var(--bk-s-5);
}

/* Две колонки на телефоне — только там, где содержимое карточки это выдержит.
   Модификатор, а не общее правило для .bk-cards: у карточки павильона
   и события внутри фотография и описание, в половину экрана они превращаются
   в марку с обрезанным текстом. У билета внутри надзаголовок, название, цена
   и кнопка — четыре короткие строки, которые в 170 px читаются нормально.

   Порог 599 px, а не 767: между ними .bk-cards и так собирает две колонки
   из своих 280 px. */
@media (max-width: 599px) {
  .bk-cards--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--bk-s-4); }
  /* В половине экрана заголовок в 24 px рвётся на пять строк, а цена
     в 34 px не оставляет места кнопке. */
  .bk-cards--pair .bk-h3 { font-size: 17px; }
  .bk-cards--pair .bk-card__body { padding: var(--bk-s-4); gap: var(--bk-s-2); }
  .bk-cards--pair .bk-num { font-size: 26px; }
  .bk-cards--pair .bk-btn { padding-inline: var(--bk-s-3); font-size: 14px; }
}

.bk-stack   { display: flex; flex-direction: column; gap: var(--bk-s-4); }
.bk-row     { display: flex; flex-wrap: wrap; align-items: center; gap: var(--bk-s-3); }
.bk-spacer  { flex: 1 1 auto; }

/* --------------------------------------------------------------------------
   4. Типографика [ДС §8.4]
   -------------------------------------------------------------------------- */
.bk-display {
  font-family: var(--bk-font-display);
  font-size: clamp(40px, 7vw, 104px);
  line-height: .95;
  letter-spacing: .05em;
  text-transform: uppercase;   /* строчных в шрифте нет */
  font-weight: 400;
  margin: 0;
}

.bk-h1 { font-family: var(--bk-font-head); font-weight: 800; font-size: clamp(32px, 4vw, 56px); line-height: 1.05; letter-spacing: 0; margin: 0; }
.bk-h2 { font-family: var(--bk-font-head); font-weight: 800; font-size: clamp(26px, 3vw, 40px); line-height: 1.10; margin: 0; }
.bk-h3 { font-family: var(--bk-font-head); font-weight: 700; font-size: clamp(20px, 2vw, 28px); line-height: 1.10; margin: 0; }

.bk-body-l { font-size: clamp(18px, 1.4vw, 20px); line-height: 1.3; margin: 0; }
.bk-body   { font-size: clamp(16px, 1.1vw, 17px); line-height: 1.3; margin: 0; }

.bk-caption {
  font-family: var(--bk-font-mono);
  font-size: 14px; line-height: 1.3; letter-spacing: -.05em;
  color: var(--bk-text-muted); margin: 0;
}

.bk-overline {
  font-family: var(--bk-font-mono);
  font-weight: 500; font-size: 12px; line-height: 1.3;
  letter-spacing: -.05em; text-transform: uppercase;
  color: var(--bk-accent); margin: 0;
}

/* Подсказка по способу ввода. «Наведите» на телефоне — ложь, «нажмите»
   на десктопе — недосказанность. Различаем не по ширине экрана, а по наличию
   наведения: на планшете с мышью верна первая, на ноутбуке с сенсором вторая. */
.bk-ontap { display: none; }
@media (hover: none) {
  .bk-onhover { display: none; }
  .bk-ontap   { display: inline; }
}

.bk-muted  { color: var(--bk-text-muted); }
.bk-accent { color: var(--bk-accent); }
.bk-num    { font-family: var(--bk-font-mono); font-variant-numeric: tabular-nums; letter-spacing: -.05em; }

/* Текстовая ссылка внутри контента */
.bk-link {
  color: var(--bk-accent);
  text-decoration: underline;
  text-underline-offset: .22em;
  text-decoration-thickness: 1px;
  transition: text-decoration-color var(--bk-dur-fast) var(--bk-ease);
}
.bk-link:hover { text-decoration-color: transparent; }

/* --------------------------------------------------------------------------
   5. Иконки
   -------------------------------------------------------------------------- */
.bk-i {
  width: 24px; height: 24px;
  flex: none;
  fill: none;
  stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
.bk-i--s { width: 20px; height: 20px; }
.bk-i--l { width: 32px; height: 32px; stroke-width: 1.4; }

/* --------------------------------------------------------------------------
   6. Кнопки
   -------------------------------------------------------------------------- */
.bk-btn {
  --_bg: transparent;
  --_fg: var(--bk-text);
  --_bd: transparent;
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--bk-s-2);
  min-height: var(--bk-ctl-h);
  padding-inline: var(--bk-ctl-px);
  border: 1px solid var(--_bd);
  border-radius: var(--bk-radius);
  background: var(--_bg);
  color: var(--_fg);
  font-family: var(--bk-font-head);
  font-weight: 700;
  font-size: 16px;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--bk-dur-fast) var(--bk-ease),
              border-color var(--bk-dur-fast) var(--bk-ease),
              color var(--bk-dur-fast) var(--bk-ease);
}
.bk-btn:disabled, .bk-btn[aria-disabled="true"] {
  opacity: .4; cursor: not-allowed; pointer-events: none;
}

/* основная — лайм. Текст «тёмный лес»: белый на лайме запрещён (контраст 1,31) */
.bk-btn--primary { --_bg: var(--bk-accent); --_fg: var(--bk-text-on-accent); --_bd: var(--bk-accent); }
.bk-btn--primary:hover  { --_bg: var(--bk-accent-hover);  --_bd: var(--bk-accent-hover); }
.bk-btn--primary:active { --_bg: var(--bk-accent-active); --_bd: var(--bk-accent-active); }

/* вторичная — контур лаймом */
.bk-btn--secondary { --_bd: var(--bk-border-strong); --_fg: var(--bk-text); }
.bk-btn--secondary:hover  { --_bd: var(--bk-accent); --_fg: var(--bk-accent); }
.bk-btn--secondary:active { --_bg: rgba(208,239,54,.12); }
.bk-on-light .bk-btn--secondary:hover { --_fg: var(--bk-text-on-light); --_bd: var(--bk-dark-forest); }

/* призрачная — для третьестепенных действий */
.bk-btn--ghost { --_fg: var(--bk-text-muted); padding-inline: var(--bk-s-3); }
.bk-btn--ghost:hover { --_fg: var(--bk-accent); }
.bk-on-light .bk-btn--ghost:hover { --_fg: var(--bk-text-on-light); }

/* заглушка недоступного действия: цвет наследуется от контейнера,
   поэтому на лаймовой карточке текст остаётся тёмным, а не белым */
.bk-btn--muted { --_fg: currentColor; --_bd: currentColor; opacity: .55; cursor: default; }

/* размеры */
.bk-btn--s { min-height: var(--bk-ctl-h-s); padding-inline: var(--bk-s-4); font-size: 14px; }
.bk-btn--l { min-height: var(--bk-ctl-h-l); padding-inline: var(--bk-s-6); font-size: 18px; }
.bk-btn--block { display: flex; width: 100%; }

/* круглая иконочная — единственное место, где допустим pill: это круглый модуль */
.bk-btn--icon {
  width: var(--bk-ctl-h); height: var(--bk-ctl-h);
  min-height: 0; padding: 0;
  border-radius: var(--bk-radius-pill);
  border-color: var(--bk-border-strong);
}
.bk-btn--icon:hover { --_fg: var(--bk-accent); border-color: var(--bk-accent); }
.bk-btn--icon.bk-btn--s { width: var(--bk-ctl-h-s); height: var(--bk-ctl-h-s); }

/* загрузка */
.bk-btn[data-loading="true"] { pointer-events: none; color: transparent; position: relative; }
.bk-btn[data-loading="true"]::after {
  content: ""; position: absolute; width: 18px; height: 18px;
  border: 2px solid currentColor; border-top-color: transparent;
  border-radius: 50%; color: var(--bk-text-on-accent);
  animation: bk-spin 700ms linear infinite;
}
@keyframes bk-spin { to { transform: rotate(360deg); } }

/* --------------------------------------------------------------------------
   7. Поля формы
   -------------------------------------------------------------------------- */
.bk-field { display: flex; flex-direction: column; gap: var(--bk-s-2); }

.bk-label {
  font-family: var(--bk-font-mono);
  font-size: 12px; letter-spacing: -.05em; text-transform: uppercase;
  color: var(--bk-text-muted);
}
.bk-label[data-required]::after { content: " *"; color: var(--bk-accent); }

.bk-input, .bk-textarea, .bk-select {
  width: 100%;
  min-height: var(--bk-ctl-h);
  padding: 12px var(--bk-s-4);
  border: 1px solid var(--bk-border);
  border-radius: var(--bk-radius);
  background: transparent;
  color: var(--bk-text);
  font-family: var(--bk-font-body);
  font-size: 17px; line-height: 1.3;
  transition: border-color var(--bk-dur-fast) var(--bk-ease),
              background-color var(--bk-dur-fast) var(--bk-ease);
}
.bk-input::placeholder, .bk-textarea::placeholder { color: var(--bk-text-muted); }
.bk-input:hover, .bk-textarea:hover, .bk-select:hover { border-color: var(--bk-border-strong); }
.bk-input:focus, .bk-textarea:focus, .bk-select:focus { border-color: var(--bk-accent); }
.bk-textarea { min-height: 128px; resize: vertical; }

.bk-select {
  appearance: none;
  padding-right: var(--bk-s-7);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 24px) 21px, calc(100% - 18px) 21px;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

.bk-field[data-state="error"] :is(.bk-input, .bk-textarea, .bk-select) { border-color: var(--bk-danger); }
.bk-field[data-state="success"] :is(.bk-input, .bk-textarea, .bk-select) { border-color: var(--bk-accent); }
.bk-input:disabled, .bk-textarea:disabled, .bk-select:disabled { opacity: .4; cursor: not-allowed; }

.bk-hint { font-family: var(--bk-font-mono); font-size: 12px; letter-spacing: -.05em; color: var(--bk-text-muted); }
.bk-error {
  display: flex; align-items: center; gap: var(--bk-s-2);
  font-family: var(--bk-font-mono); font-size: 12px; letter-spacing: -.05em;
  color: #F0A9A4;  /* рябина 40 % — на тёмном читается, чистая рябина даёт 2,84 */
}

/* чекбокс и радио — квадрат по геометрии бренда, круг только у радио */
.bk-check { display: flex; align-items: flex-start; gap: var(--bk-s-3); cursor: pointer; }
.bk-check input { position: absolute; opacity: 0; width: 0; height: 0; }
.bk-check__box {
  flex: none; width: 22px; height: 22px; margin-top: 1px;
  border: 1px solid var(--bk-border-strong);
  border-radius: var(--bk-radius);
  display: grid; place-items: center;
  transition: background-color var(--bk-dur-fast) var(--bk-ease),
              border-color var(--bk-dur-fast) var(--bk-ease);
}
.bk-check--radio .bk-check__box { border-radius: var(--bk-radius-pill); }
.bk-check__box svg { width: 14px; height: 14px; opacity: 0; stroke: var(--bk-text-on-accent); stroke-width: 2.4; }
.bk-check input:checked + .bk-check__box { background: var(--bk-accent); border-color: var(--bk-accent); }
.bk-check input:checked + .bk-check__box svg { opacity: 1; }
.bk-check input:focus-visible + .bk-check__box { outline: 2px solid var(--bk-focus); outline-offset: 2px; }
.bk-check__text { font-size: 15px; line-height: 1.35; color: var(--bk-text-muted); }

/* переключатель «для слабовидящих» и т.п. */
.bk-switch { display: inline-flex; align-items: center; gap: var(--bk-s-3); cursor: pointer; }
.bk-switch input { position: absolute; opacity: 0; }
.bk-switch__track {
  width: 46px; height: 26px; border-radius: var(--bk-radius-pill);
  border: 1px solid var(--bk-border-strong); position: relative;
  transition: background-color var(--bk-dur-fast) var(--bk-ease);
}
.bk-switch__track::after {
  content: ""; position: absolute; inset: 3px auto 3px 3px;
  width: 18px; border-radius: 50%; background: var(--bk-text);
  transition: transform var(--bk-dur-fast) var(--bk-ease), background-color var(--bk-dur-fast) var(--bk-ease);
}
.bk-switch input:checked + .bk-switch__track { background: var(--bk-accent); border-color: var(--bk-accent); }
.bk-switch input:checked + .bk-switch__track::after { transform: translateX(20px); background: var(--bk-text-on-accent); }
.bk-switch input:focus-visible + .bk-switch__track { outline: 2px solid var(--bk-focus); outline-offset: 2px; }

/* --------------------------------------------------------------------------
   8. Плашки, чипы, метки
   -------------------------------------------------------------------------- */
.bk-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px;
  border-radius: var(--bk-radius);
  background: var(--bk-accent); color: var(--bk-text-on-accent);
  font-family: var(--bk-font-mono); font-size: 12px; letter-spacing: -.05em;
  text-transform: uppercase; white-space: nowrap;
}
.bk-badge--outline { background: transparent; color: var(--bk-text); border: 1px solid var(--bk-border-strong); }
.bk-badge--age { background: transparent; border: 1px solid var(--bk-border-strong); color: var(--bk-text-muted); }
.bk-badge--free { background: var(--bk-accent); color: var(--bk-text-on-accent); }
.bk-badge--soon { background: var(--bk-warm-sand); color: var(--bk-dark-forest); }
.bk-badge--online { background: var(--bk-peony); color: var(--bk-dark-forest); }

/* чип-фильтр */
.bk-chip {
  display: inline-flex; align-items: center; gap: var(--bk-s-2);
  min-height: var(--bk-ctl-h-s); padding-inline: var(--bk-s-4);
  border: 1px solid var(--bk-border); border-radius: var(--bk-radius-pill);
  background: transparent; color: var(--bk-text);
  font-family: var(--bk-font-mono); font-size: 14px; letter-spacing: -.05em;
  cursor: pointer;
  text-decoration: none;   /* чип может быть ссылкой — подчёркивание тут лишнее */
  white-space: nowrap;
  transition: border-color var(--bk-dur-fast) var(--bk-ease),
              background-color var(--bk-dur-fast) var(--bk-ease),
              color var(--bk-dur-fast) var(--bk-ease);
}
.bk-chip:hover { border-color: var(--bk-accent); }
.bk-chip[aria-pressed="true"] { background: var(--bk-accent); border-color: var(--bk-accent); color: var(--bk-text-on-accent); }

/* точка направления — цвет темы павильона */
/* Точка направления. Кольцо обязательно: Виноград (#330072), Река и Слива дают
   на «тёмном лесу» контраст 1,10–1,45 [ДС §7.4] — заливкой они допустимы, но
   без обводки точка размером 10 px просто не видна, и строка выглядит пустой. */
.bk-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--bk-dir, var(--bk-accent)); flex: none;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .28);
}
.bk-on-light .bk-dot { box-shadow: 0 0 0 1px rgba(19, 50, 43, .28); }
/* Тема павильона ещё не выбрана: место под точку держим, но ничего не рисуем —
   пустое кольцо читается как невыбранный переключатель. */
.bk-dot--empty { background: none; box-shadow: none; }

/* --------------------------------------------------------------------------
   9. Карточки
   -------------------------------------------------------------------------- */
.bk-card {
  position: relative;
  display: flex; flex-direction: column;
  background: var(--bk-surface);
  border: 1px solid transparent;
  border-radius: var(--bk-radius);
  overflow: hidden;
  transition: background-color var(--bk-dur-fast) var(--bk-ease),
              border-color var(--bk-dur-fast) var(--bk-ease);
}
.bk-card__media {
  position: relative;
  aspect-ratio: var(--ratio, 4 / 3);
  background: var(--bk-bg-alt);
  overflow: hidden;
}
.bk-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--bk-dur) var(--bk-ease); }

/* Карточка без фотографии — не исключение, а норма: снимков событий у музея
   не будет почти никогда, а фото павильонов ещё не сняты. Пустое место ломает
   ритм сетки, поэтому в кадр встаёт фирменный паттерн — приглушённый и без
   текста поверх [ДС §9.4]. Высота ровно та же, что у карточки с фотографией:
   когда снимки приедут, сетка не поедет.
   --bk-pattern-pos сдвигает кадр, чтобы соседние карточки не выглядели копиями. */
.bk-card__media--pattern::before {
  content: ""; position: absolute; inset: 0;
  background-image: var(--bk-pattern, url("../brand-assets/patterns/svg/pattern-radial-dots.svg"));
  background-size: var(--bk-pattern-size, cover);
  background-position: var(--bk-pattern-pos, center);
  opacity: .38;
  transition: transform var(--bk-dur) var(--bk-ease);
}
.bk-card:hover .bk-card__media--pattern::before { transform: scale(1.03); }
.bk-card__body { display: flex; flex-direction: column; gap: var(--bk-s-3); padding: var(--bk-s-5); flex: 1; }
.bk-card__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--bk-s-2) var(--bk-s-4); }
.bk-card__foot { margin-top: auto; padding-top: var(--bk-s-2); }

/* полоса акцентного цвета направления — так Река/Слива/Виноград попадают
   в интерфейс заливкой, а не текстом */
.bk-card--dir::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 4px;
  background: var(--bk-dir, var(--bk-accent)); z-index: 1;
}

/* карточка целиком кликабельна: ссылка растягивается псевдоэлементом */
.bk-card__link { text-decoration: none; color: inherit; }
.bk-card__link::after { content: ""; position: absolute; inset: 0; }
.bk-card:hover { background: var(--bk-surface-hover); border-color: var(--bk-border); }
.bk-card:hover .bk-card__media img { transform: scale(1.03); }
.bk-card:focus-within { border-color: var(--bk-accent); }

/* Карточка билета. Цена — крупное моно, льготная отдельной строкой под ней:
   в одну строку они слипаются, а на узкой карточке сумма рвётся посередине. */
.bk-ticket__price { display: flex; flex-direction: column; gap: 4px; }
.bk-ticket__price b {
  font-family: var(--bk-font-mono); font-weight: 500; line-height: 1;
  font-size: clamp(28px, 3vw, 40px); letter-spacing: -.05em; color: var(--bk-accent);
  white-space: nowrap;
}
.bk-ticket__price span { white-space: nowrap; }

/* Комплексный билет — широкая плашка под сеткой, а не третья такая же карточка:
   он один, он дороже всех и он главный вывод блока. Плюс сетка билетов вырастет
   с двух карточек до пяти, когда клиент пришлёт цены по всем павильонам, —
   в общем ряду комплексный потерялся бы окончательно. */
.bk-ticket--wide { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
.bk-ticket--wide .bk-card__body { padding: clamp(24px, 3vw, 40px); }
.bk-ticket--wide .bk-ticket__aside {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--bk-s-4);
  padding: clamp(24px, 3vw, 40px); padding-left: 0; min-width: 260px;
}
@media (max-width: 767px) {
  .bk-ticket--wide { grid-template-columns: minmax(0, 1fr); }
  .bk-ticket--wide .bk-card__body { padding-bottom: 0; }
  .bk-ticket--wide .bk-ticket__aside { padding: var(--bk-s-5) clamp(24px, 3vw, 40px) clamp(24px, 3vw, 40px); }
}

/* сотрудник */
.bk-staff__photo { aspect-ratio: 1; border-radius: var(--bk-radius-pill); overflow: hidden; width: 88px; }
.bk-staff__photo img { width: 100%; height: 100%; object-fit: cover; }

/* --------------------------------------------------------------------------
   10. Шапка и навигация
   -------------------------------------------------------------------------- */
/* Шапка ВСЕГДА на сплошной заливке фирменного цвета: логотип не имеет права
   лежать на фотографии, калейдоскопе или паттерне [ББ с.10]. Прозрачная
   шапка поверх слайдера-витрины — прямое нарушение. */
.bk-header {
  position: sticky; top: 0; z-index: var(--bk-z-header);
  background: var(--bk-bg);
  border-bottom: 1px solid var(--bk-border);
}
.bk-header__inner { display: flex; align-items: center; gap: var(--bk-s-5); min-height: 76px; }

/* охранное поле в 1 модуль «О» [ББ с.6]; для горизонтальной версии X = высота знака */
/* max-width считает охранное поле: без него блок с логотипом шире контейнера
   ровно на два поля и распирает страницу по горизонтали на узком экране.
   Само поле при этом сохраняется, ужимается только знак. */
.bk-logo {
  --bk-logo-h: 28px; display: inline-block;
  padding: var(--bk-logo-h); margin: calc(var(--bk-logo-h) * -1);
  max-width: 100%;
}
/* высота задаётся через max-*, чтобы на 320 px знак ужимался пропорционально,
   а не искажался: при h=28 ширина ≈ 250 px, минимум по брендбуку — 120 px */
.bk-logo img { width: auto; height: auto; max-height: var(--bk-logo-h); max-width: 100%; }
/* Анимированный знак (motion/assets, собран Remotion в самодостаточный SVG).
   Охранное поле у него уже внутри файла: viewBox на 1X больше знака со всех
   сторон, потому что это ещё и сцена, с которой слетаются клетки. Поэтому
   padding контейнера убираем — иначе поле удвоится, — а отрицательный margin
   оставляем: он возвращает блок ровно в габариты статичного знака, и вёрстка
   не сдвигается ни на пиксель. Высота втрое больше --bk-logo-h по той же
   причине: 1X поля сверху + сам знак + 1X снизу. */
.bk-logo--motion { padding: 0; }
.bk-logo--motion img {
  /* height, а не max-height. У анимированного файла нет собственных размеров,
     только viewBox, и при height:auto внутри inline-block знак схлопывается
     в ноль — пропадает с экрана совсем. С max-height не рисуется вовсе,
     проверено. Высота втрое больше --bk-logo-h: поле + знак + поле. */
  height: calc(var(--bk-logo-h) * 3); width: auto; max-height: none;
  /* Страховка: если ширина упрётся в контейнер, знак уменьшится целиком,
     а не сожмётся по горизонтали. На наших брейкпоинтах не срабатывает —
     при h=20 ширина 219 px против 280 px контейнера, — но искажать знак
     нельзя ни при каких обстоятельствах [ББ с.9]. */
  object-fit: contain;
}

/* на телефоне знак мельче, но не ниже порога: при h=20 ширина ≈ 179px > 120px [ББ с.9] */
@media (max-width: 599px) { .bk-logo { --bk-logo-h: 20px; } .bk-header__inner { min-height: 64px; } }

.bk-nav { display: flex; align-items: center; gap: var(--bk-s-2); margin-left: auto; }
.bk-nav__item {
  position: relative;
  display: inline-flex; align-items: center; gap: 6px;
  padding: var(--bk-s-3) var(--bk-s-3);
  color: var(--bk-text); text-decoration: none;
  font-family: var(--bk-font-head); font-weight: 600; font-size: 15px;
  background: none; border: 0; cursor: pointer;
  transition: color var(--bk-dur-fast) var(--bk-ease);
}
.bk-nav__item:hover, .bk-nav__item[aria-expanded="true"] { color: var(--bk-accent); }
.bk-nav__item[aria-current="page"]::after {
  content: ""; position: absolute; left: var(--bk-s-3); right: var(--bk-s-3); bottom: 6px;
  height: 2px; background: var(--bk-accent);
}

.bk-dropdown {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: var(--bk-z-dropdown);
  min-width: 240px; padding: var(--bk-s-2);
  background: var(--bk-bg-alt); border: 1px solid var(--bk-border);
  display: none; flex-direction: column;
}
.bk-dropdown[data-open="true"] { display: flex; }
.bk-dropdown a {
  padding: var(--bk-s-3) var(--bk-s-4); color: var(--bk-text); text-decoration: none;
  font-size: 15px; transition: background-color var(--bk-dur-fast) var(--bk-ease), color var(--bk-dur-fast) var(--bk-ease);
}
.bk-dropdown a:hover { background: rgba(208,239,54,.10); color: var(--bk-accent); }

.bk-burger { display: none; }
@media (max-width: 1199px) {
  .bk-nav { display: none; }
  .bk-burger { display: inline-flex; margin-left: auto; }
}

/* Мобильное меню.
   Раскрывается плашкой: панель наезжает сверху и проявляется, пункты следом
   поднимаются по очереди. До этого меню появлялось мгновенно, без перехода, —
   на телефоне такое читается как перезагрузка страницы, а не как раскрытие.

   Разделители — лаймовые линии между пунктами, тот же `--bk-border`, что
   и во всём интерфейсе. Раньше пункты стояли просто списком в 22 px и на семи
   строках сливались в стену текста. Кегль убавлен до 17: меню — навигация,
   а не заголовок, и семь пунктов должны читаться списком. */
.bk-mobilemenu {
  position: fixed; inset: 0; z-index: var(--bk-z-modal);
  background: var(--bk-bg); padding: var(--bk-s-5);
  display: flex; flex-direction: column; gap: 0;
  overflow-y: auto;
}
.bk-mobilemenu[hidden] { display: none; }
.bk-mobilemenu > .bk-row { margin-bottom: var(--bk-s-4); }

.bk-mobilemenu a {
  color: var(--bk-text); text-decoration: none;
  font-family: var(--bk-font-head); font-weight: 700; font-size: 17px;
  padding-block: var(--bk-s-4);
  border-bottom: 1px solid var(--bk-border);
}
/* Первый пункт отбивается сверху такой же линией: без неё список начинается
   «в воздухе», и верхний пункт визуально прилипает к строке с крестиком. */
.bk-mobilemenu a:first-of-type { border-top: 1px solid var(--bk-border); }
.bk-mobilemenu a:hover { color: var(--bk-accent); }
/* Кнопка покупки — не пункт списка: линий у неё нет, и она отбита от него. */
.bk-mobilemenu a.bk-btn { border: 1px solid var(--_bd); font-size: 16px; margin-top: var(--bk-s-5); padding-block: 0; }

@media (prefers-reduced-motion: no-preference) {
  .bk-mobilemenu:not([hidden]) { animation: bk-menu-in 260ms var(--bk-ease) both; }
  .bk-mobilemenu:not([hidden]) a { animation: bk-menu-item 300ms var(--bk-ease) both; }
  /* Задержки по номеру пункта: разметка у меню фиксированная, девять ссылок
     максимум, поэтому проще перечислить, чем заводить переменную в шаблоне. */
  .bk-mobilemenu:not([hidden]) a:nth-of-type(1) { animation-delay:  70ms; }
  .bk-mobilemenu:not([hidden]) a:nth-of-type(2) { animation-delay: 105ms; }
  .bk-mobilemenu:not([hidden]) a:nth-of-type(3) { animation-delay: 140ms; }
  .bk-mobilemenu:not([hidden]) a:nth-of-type(4) { animation-delay: 175ms; }
  .bk-mobilemenu:not([hidden]) a:nth-of-type(5) { animation-delay: 210ms; }
  .bk-mobilemenu:not([hidden]) a:nth-of-type(6) { animation-delay: 245ms; }
  .bk-mobilemenu:not([hidden]) a:nth-of-type(7) { animation-delay: 280ms; }
  .bk-mobilemenu:not([hidden]) a:nth-of-type(8) { animation-delay: 315ms; }
  .bk-mobilemenu:not([hidden]) a:nth-of-type(9) { animation-delay: 350ms; }
}
@keyframes bk-menu-in {
  from { opacity: 0; transform: translateY(-12px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes bk-menu-item {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* хлебные крошки */
.bk-crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: var(--bk-s-2); font-family: var(--bk-font-mono); font-size: 12px; letter-spacing: -.05em; }
.bk-crumbs a { color: var(--bk-text-muted); text-decoration: none; }
.bk-crumbs a:hover { color: var(--bk-accent); }
.bk-crumbs li { display: flex; align-items: center; gap: var(--bk-s-2); }
.bk-crumbs li + li::before { content: "/"; color: var(--bk-text-muted); opacity: .5; }
.bk-crumbs ol, .bk-crumbs ul { display: contents; list-style: none; margin: 0; padding: 0; }

/* пагинация */
.bk-pager { display: flex; align-items: center; gap: var(--bk-s-2); }
.bk-pager a, .bk-pager span {
  min-width: var(--bk-ctl-h-s); height: var(--bk-ctl-h-s);
  display: inline-grid; place-items: center; padding-inline: var(--bk-s-2);
  border: 1px solid transparent; color: var(--bk-text); text-decoration: none;
  font-family: var(--bk-font-mono); font-size: 14px; letter-spacing: -.05em;
}
.bk-pager a:hover { border-color: var(--bk-border-strong); }
.bk-pager [aria-current="page"] { background: var(--bk-accent); color: var(--bk-text-on-accent); }

/* --------------------------------------------------------------------------
   11. Табы, аккордеон, подсказка
   -------------------------------------------------------------------------- */
.bk-tabs { display: flex; gap: 0; border-bottom: 1px solid var(--bk-border); }
.bk-tab {
  appearance: none; background: none; border: 0; cursor: pointer;
  padding: var(--bk-s-3) var(--bk-s-5);
  color: var(--bk-text-muted);
  font-family: var(--bk-font-head); font-weight: 700; font-size: 15px;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color var(--bk-dur-fast) var(--bk-ease), border-color var(--bk-dur-fast) var(--bk-ease);
}
.bk-tab:hover { color: var(--bk-text); }
.bk-tab[aria-selected="true"] { color: var(--bk-accent); border-bottom-color: var(--bk-accent); }

.bk-accordion { border-top: 1px solid var(--bk-border); }
.bk-accordion details { border-bottom: 1px solid var(--bk-border); }
.bk-accordion summary {
  display: flex; align-items: center; gap: var(--bk-s-4);
  padding: var(--bk-s-5) 0; cursor: pointer; list-style: none;
  font-family: var(--bk-font-head); font-weight: 700; font-size: clamp(17px, 1.6vw, 20px);
  transition: color var(--bk-dur-fast) var(--bk-ease);
}
.bk-accordion summary::-webkit-details-marker { display: none; }
.bk-accordion summary:hover { color: var(--bk-accent); }
.bk-accordion summary .bk-i { margin-left: auto; transition: transform var(--bk-dur-fast) var(--bk-ease); }
.bk-accordion details[open] summary .bk-i { transform: rotate(180deg); }
.bk-accordion__body { padding-bottom: var(--bk-s-5); max-width: 72ch; color: var(--bk-text-muted); }

.bk-tip { position: relative; display: inline-flex; }
.bk-tip__bubble {
  position: absolute; bottom: calc(100% + 10px); left: 50%; translate: -50% 0;
  padding: var(--bk-s-2) var(--bk-s-3);
  background: var(--bk-accent); color: var(--bk-text-on-accent);
  font-family: var(--bk-font-mono); font-size: 12px; letter-spacing: -.05em; white-space: nowrap;
  opacity: 0; pointer-events: none;
  transition: opacity var(--bk-dur-fast) var(--bk-ease), translate var(--bk-dur-fast) var(--bk-ease);
  z-index: var(--bk-z-tooltip);
}
.bk-tip:hover .bk-tip__bubble, .bk-tip:focus-within .bk-tip__bubble { opacity: 1; translate: -50% -2px; }

/* --------------------------------------------------------------------------
   12. Календарь месяца
   -------------------------------------------------------------------------- */
.bk-cal { max-width: 460px; }

/* Афиша и календарь одной секцией: слева месяц, справа ближайшее событие.
   Календарю хватает четырёх колонок — он и так упирается в свои 460 px,
   а карточке события нужна ширина: внутри неё фотография и текст рядом.
   Ниже 1024 px контейнер переходит на 8 колонок, и блоки встают друг под друга:
   календарь в половину ширины выглядел бы обрезанным, а не компактным. */
.bk-agenda { row-gap: var(--bk-s-7); align-items: start; }
.bk-agenda__cal  { grid-column: span 4; }
.bk-agenda__lead { grid-column: span 8 / -1; }
@media (max-width: 1023px) {
  .bk-agenda__cal, .bk-agenda__lead { grid-column: 1 / -1; }
}
.bk-cal__head { display: flex; align-items: center; justify-content: space-between; gap: var(--bk-s-3); margin-bottom: var(--bk-s-5); }
.bk-cal__title { font-family: var(--bk-font-head); font-weight: 800; font-size: 20px; text-transform: capitalize; }
.bk-cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.bk-cal__dow {
  display: grid; place-items: center; height: 32px;
  font-family: var(--bk-font-mono); font-size: 12px; letter-spacing: -.05em;
  text-transform: uppercase; color: var(--bk-text-muted);
}
.bk-cal__day {
  position: relative; aspect-ratio: 1;
  display: grid; place-items: center;
  border: 1px solid transparent; border-radius: var(--bk-radius);
  background: none; color: var(--bk-text); text-decoration: none;
  font-family: var(--bk-font-mono); font-size: 15px; letter-spacing: -.05em;
  cursor: default;
  transition: background-color var(--bk-dur-fast) var(--bk-ease), border-color var(--bk-dur-fast) var(--bk-ease), color var(--bk-dur-fast) var(--bk-ease);
}
.bk-cal__day--out { color: transparent; pointer-events: none; }
.bk-cal__day--past { color: rgba(255,255,255,.28); }

/* День с событиями. Сама клетка — контейнер: внутри ссылка на афишу за этот
   день и карточка со списком. Ссылка не растянутая, а честно занимающая клетку:
   растянутая накрыла бы карточку, и ссылки в ней перестали бы нажиматься. */
.bk-cal__day--has { border-color: var(--bk-border-strong); padding: 0; }
.bk-cal__daylink {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  text-decoration: none; color: inherit; cursor: pointer;
}
.bk-cal__day--has:hover { background: rgba(208,239,54,.12); border-color: var(--bk-accent); }

/* По точке на мероприятие, до трёх. Точки под числом, а не поверх: клетка
   маленькая, и наложение читалось бы как дефект печати. */
.bk-cal__dots { display: flex; gap: 3px; height: 4px; }
.bk-cal__dots i { width: 4px; height: 4px; border-radius: 50%; background: var(--bk-accent); }
.bk-cal__day--past .bk-cal__dots i { background: rgba(255,255,255,.28); }

/* Карточка дня. На десктопе её открывает наведение, на телефоне — тап
   (скрипт ставит data-open). :focus-within добавлен ради клавиатуры:
   при табе на день карточка обязана открыться так же, как по наведению. */
.bk-cal__pop {
  position: absolute; bottom: calc(100% + 10px); left: 50%; translate: -50% 0;
  z-index: var(--bk-z-tooltip);
  width: max-content; max-width: 280px;
  padding: var(--bk-s-4);
  display: flex; flex-direction: column; gap: var(--bk-s-3);
  text-align: left;
  background: var(--bk-surface); border: 1px solid var(--bk-border-strong);
  box-shadow: 0 18px 48px rgba(9, 24, 20, .55);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity var(--bk-dur-fast) var(--bk-ease), visibility var(--bk-dur-fast);
}
/* Мостик до клетки: без него курсор теряет наведение в зазоре
   между днём и карточкой, и она закрывается на полпути. */
.bk-cal__pop::after { content: ""; position: absolute; top: 100%; left: 0; right: 0; height: 12px; }

.bk-cal__day--has:hover .bk-cal__pop,
.bk-cal__day--has:focus-within .bk-cal__pop,
.bk-cal__day--has[data-open="true"] .bk-cal__pop {
  opacity: 1; visibility: visible; pointer-events: auto;
}

/* У верхних двух недель карточка раскрывается ВНИЗ: вверх ей некуда — она
   вылезла бы над календарём в текст секции. Ряд считает шаблон и кладёт
   в data-row, поэтому обходимся без замеров скриптом. */
.bk-cal__day[data-row="0"] .bk-cal__pop,
.bk-cal__day[data-row="1"] .bk-cal__pop { top: calc(100% + 10px); bottom: auto; }
.bk-cal__day[data-row="0"] .bk-cal__pop::after,
.bk-cal__day[data-row="1"] .bk-cal__pop::after { top: auto; bottom: 100%; }

/* У края календаря карточку прижимаем внутрь кадра. Столбец недели считает
   шаблон и кладёт в data-col — скрипт для этого не нужен. */
.bk-cal__day[data-col="0"] .bk-cal__pop,
.bk-cal__day[data-col="1"] .bk-cal__pop { left: 0; translate: 0 0; }
.bk-cal__day[data-col="5"] .bk-cal__pop,
.bk-cal__day[data-col="6"] .bk-cal__pop { left: auto; right: 0; translate: 0 0; }

.bk-cal__poplist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--bk-s-3); }
.bk-cal__poplist li { display: flex; flex-direction: column; gap: 2px; }
.bk-cal__poplist a {
  font-family: var(--bk-font-head); font-weight: 700; font-size: 15px; line-height: 1.2;
  color: var(--bk-text); text-decoration: none;
}
.bk-cal__poplist a:hover { color: var(--bk-accent); }
.bk-cal__day--today { color: var(--bk-accent); font-weight: 700; }
.bk-cal__day[aria-pressed="true"] { background: var(--bk-accent); border-color: var(--bk-accent); color: var(--bk-text-on-accent); }
.bk-cal__day[aria-pressed="true"]::after { background: var(--bk-text-on-accent); }

/* --------------------------------------------------------------------------
   13. Слайдер-витрина
   -------------------------------------------------------------------------- */
.bk-slider { position: relative; }
.bk-slider__viewport { overflow: hidden; min-width: 0; }
/* Перелистывание вдвое медленнее общего --bk-dur (440 мс). Своё число, а не
   правка токена: --bk-dur держит темп всего интерфейса — кнопок, ссылок,
   раскрывашек, — и удвоение там замедлило бы весь сайт. */
.bk-slider__track { display: flex; transition: transform 880ms var(--bk-ease); }
.bk-slider__slide { flex: 0 0 100%; min-width: 0; }
.bk-slider__ctrl { display: flex; align-items: center; gap: var(--bk-s-3); margin-top: var(--bk-s-4); }
.bk-slider__dots { display: flex; gap: var(--bk-s-2); margin-inline: auto; }

/* Вариант с разнесённым управлением: точки и счётчик слева, стрелки справа.
   В базовом варианте точки растянуты `margin-inline:auto`, и на широком экране
   стрелки расходятся к краям страницы на полтора метра друг от друга. */
.bk-slider__ctrl--split { gap: var(--bk-s-5); flex-wrap: wrap; }
.bk-slider__ctrl--split .bk-slider__dots { margin-inline: 0; }
.bk-slider__ctrl--split .bk-slider__nav { display: flex; gap: var(--bk-s-2); margin-left: auto; }
.bk-slider__count { font-family: var(--bk-font-mono); font-size: 13px; letter-spacing: -.05em; color: var(--bk-text-muted); }
.bk-slider__count b { color: var(--bk-text); font-weight: 500; }
/* на 320 px точки, счётчик и стрелки в одну строку не помещаются: счётчик
   убираем — он дублирует то, что и так показывают точки */
@media (max-width: 599px) {
  .bk-slider__count { display: none; }
  .bk-slider__dot { width: 20px; }
}
.bk-slider__dot {
  width: 32px; height: 3px; padding: 0; border: 0; cursor: pointer;
  background: var(--bk-border); transition: background-color var(--bk-dur-fast) var(--bk-ease);
}
.bk-slider__dot[aria-selected="true"] { background: var(--bk-accent); }

/* Управление лежит НА слайде, в правом нижнем углу, на такой же плашке, как
   текст. Обе плашки прижаты к нижнему краю: слева подпись, справа управление —
   и между ними видна фотография.

   На телефоне оно тоже на кадре, но не в том же месте: там слайд разложен
   на два этажа, и низ слайда занимает текст на сплошной заливке. Управление
   садится на нижний край ВЕРХНЕГО этажа, то есть самой картинки, — правила
   ниже. Раньше оно уезжало под слайд отдельной строкой; клиент сказал, что
   оттуда неудобно нажимать, и был прав: строка узкая, стрелки мелкие, а палец
   при листании закрывает то, что листает. */
.bk-slider__ctrl--onslide { gap: var(--bk-s-4); }
.bk-slider__ctrl--onslide .bk-slider__dots { margin-inline: 0; }
.bk-slider__ctrl--onslide .bk-slider__nav { display: flex; gap: var(--bk-s-2); }
/* Общий --bk-text-muted (.72 белого) на плашке поверх фотографии даёт 4,4:1 —
   на волос ниже порога 4,5:1. Под плашкой светит кадр, а не сплошной фон
   секции, поэтому здесь приглушение слабее. */
.bk-slider__ctrl--onslide .bk-slider__count { color: rgba(255, 255, 255, .86); }

@media (min-width: 768px) {
  .bk-slider__ctrl--onslide {
    position: absolute; right: 0; bottom: 0; z-index: 2;
    margin-top: 0; min-height: var(--bk-plate-h);
    padding: var(--bk-s-3) clamp(20px, 3vw, 48px);
    background: var(--bk-plate);
  }
}

/* Телефон: управление садится на нижний край картинки.
   Высоту картинки приходится считать, а не спрашивать: управление лежит
   вне слайда (у вьюпорта overflow: hidden, он бы его обрезал), поэтому
   привязаться к низу кадра напрямую нечем. Картинка на телефоне — это
   aspect-ratio 4/3 во всю ширину слайда, а ширина слайда равна ширине
   контейнера. Отсюда: три четверти от (ширина окна минус два поля).
   translateY(-100%) сажает плашку НАД этой линией, а не под ней.

   Стрелки крупнее обычных: на кадре и под пальцем маленькая цель не нужна. */
@media (max-width: 767px) {
  .bk-slider__ctrl--onslide {
    position: absolute; z-index: 2; left: 0; right: 0;
    top: calc(.75 * (100vw - 2 * var(--bk-pad, 20px)));
    transform: translateY(-100%);
    margin-top: 0;
    padding: var(--bk-s-3) var(--bk-s-4);
    background: var(--bk-plate);
  }
  .bk-slider__ctrl--onslide .bk-slider__dots { margin-right: auto; }
  .bk-slider__ctrl--onslide .bk-btn--icon { width: 44px; height: 44px; }
}

/* Слайд-витрина: визуал, поверх — затемнение и текст.
   Логотипа тут нет и быть не может — он лёг бы на фотографию [ББ с.10].

   Главное решение этого компонента — ГЕОМЕТРИЯ ТЕКСТА ОДИНАКОВА В ОБОИХ РЕЖИМАХ.
   Фотографий павильонов от клиента ещё нет, вместо них стоят калейдоскопы, а это
   принципиально другая картинка: квадратная, симметричная, тёмная и очень плотная.
   Реальные снимки будут горизонтальными, светлее и с центром внимания сбоку.
   Слайд, построенный вокруг симметрии заглушки, при замене на фото развалится,
   поэтому текстовый блок стоит слева внизу и не двигается никогда. Меняется
   только правая часть кадра:

   · --photo   — фотография кроет весь слайд (ТЗ, блок 1: «крупное фото павильона»);
   · --kaleido — калейдоскоп стоит справа ЦЕЛИКОМ: вписан, не обрезан, не повёрнут
                 и не смещён с оси [ДС §10.3]. Кадрировать его нельзя — симметрия
                 у этого образа смысловая, а не декоративная. */
/* Высота задаётся от экрана, а не пропорцией. На ноутбуке 13″ слайд в 16:9
   занимает 736 px и вместе с шапкой и заголовком секции на экран не влезал.

   ГРАБЛИ: сделать это через `aspect-ratio: 16/9` + `max-height` нельзя.
   Chrome в этом случае пересчитывает по пропорции и ШИРИНУ: слайд стал
   1053 px внутри контейнера в 1336 px, и справа появилась пустота. Поэтому
   высота задана прямо, а пропорцию держит object-fit:cover на фотографии.

   svh, а не vh: на телефоне vh считается от экрана без адресной строки,
   и блок вылезает под неё. Строка с vh оставлена запасной для старых браузеров.

   Ограничение снимается на телефоне — там слайд раскладывается на два этажа
   и высоту задаёт содержимое. */
.bk-showcase {
  position: relative;
  /* 340px — это то, что стоит над слайдом: шапка 77, верхний отступ секции
     до 128, заголовок блока и просвет. Считаем от экрана, а не долей: доля
     на разных ноутбуках то помещается, то нет на десяток пикселей.
     640px — потолок, чтобы на большом мониторе слайд не разъезжался. */
  height: clamp(360px, calc(100vh - 340px), 640px);
  height: clamp(360px, calc(100svh - 340px), 640px);
  overflow: hidden; background: var(--bk-bg-alt);
}

.bk-showcase__visual { position: absolute; inset: 0; }
.bk-showcase__visual img { width: 100%; height: 100%; }

.bk-showcase--photo .bk-showcase__visual img { object-fit: cover; }

.bk-showcase--kaleido .bk-showcase__visual,
.bk-showcase--pattern .bk-showcase__visual {
  left: auto; width: 50%;
  display: grid; place-items: center;
  padding: clamp(12px, 2vw, 32px);
}
/* Калейдоскоп слайда мельче геройского: иначе витрина перебивает первый экран,
   а главный калейдоскоп в иерархии айдентики стоит выше тематических [ББ с.27]. */
.bk-showcase--kaleido .bk-showcase__visual img {
  width: auto; height: auto; max-width: 84%; max-height: 84%; object-fit: contain;
}

/* Павильон, у которого тема брендбука ещё не выбрана. Ставить сюда главный
   калейдоскоп нельзя: он уже занят первым экраном, и три слайда из пяти стали
   бы одинаковыми. Подставлять чужую тему — тем более: соответствие павильонов
   и направлений не согласовано, это открытый вопрос №1. Поэтому в кадре
   фирменный паттерн — нейтральная заглушка, которая ничего не утверждает. */
.bk-showcase--pattern .bk-showcase__visual::before {
  content: ""; position: absolute; inset: 0;
  background-image: var(--bk-pattern);
  /* крупнее и глуше, чем в карточке: здесь паттерн занимает половину экрана и
     на такой площади читается уже не как фактура, а как самостоятельная
     картинка — начинает спорить с калейдоскопом на первом экране */
  background-size: calc(var(--bk-pattern-size, 100%) * 1.6);
  background-position: var(--bk-pattern-pos, center);
  opacity: .2;
  /* растушёвка левого края: без неё паттерн обрывается по вертикали ровно
     посередине слайда и выглядит незакрытым слоем, а не фоном кадра */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 26%);
          mask-image: linear-gradient(90deg, transparent 0, #000 26%);
}

/* Плашка под текстом — функциональный элемент, а не декор: без неё белый
   текст на светлых участках фотографии нечитаем.

   Раньше здесь был градиент во весь кадр, и фотографию было почти не видно.
   Прямоугольник ограничен ровно текстом: он занимает X 0–36 %, Y 40–100 %
   слайда, остальные три четверти кадра остаются чистыми.

   Плотность 0,80 — не на глаз, а по замеру самих кадров. В светлых местах
   под текстом у «Геологии» светлота доходит до 0,98, у «Цветоводства»
   до 0,75: без плашки белый текст даёт там контраст 1,0:1, то есть пропадает
   совсем. При 0,80 получается 7,4:1 для белого и 5,7:1 для лаймового
   надзаголовка — с запасом от 4,5:1 по WCAG AA.

   Нижнюю границу задаёт лайм, а не белый: на белом фоне он даёт 1,3:1
   против 1,0:1 у белого, то есть отваливается первым. Делать плашку
   прозрачнее «чтобы фотографию было видно лучше» нельзя — сначала пропадёт
   надзаголовок. Ниже 0,80 не опускать.

   Значение лежит в --bk-plate рядом с остальными компонентными токенами:
   та же плашка стоит под управлением слайдера, а оно лежит ВНЕ .bk-showcase,
   и переменная, объявленная на самом слайде, до него не доставала. */
.bk-showcase--photo .bk-showcase__body { background: var(--bk-plate); }

.bk-showcase__body {
  position: absolute; inset: auto 0 0 0;
  padding: clamp(20px, 3vw, 48px);
  display: flex; flex-direction: column; gap: var(--bk-s-4);
  /* 48ch, а не 44ch: в раскрытом виде рядом с названием стоит кружок, и на
     колонку заголовка остаётся ширина плашки минус отступы, кружок и просвет.
     При 44ch «промышленность» (одно слово, разорвать негде) не помещалась
     в колонку и наезжала на кружок. */
  max-width: min(48%, 48ch);
  min-height: var(--bk-plate-h);
  justify-content: center;
  transition: max-width var(--bk-dur) var(--bk-ease),
              padding var(--bk-dur) var(--bk-ease),
              gap var(--bk-dur) var(--bk-ease);
}
.bk-showcase__title {
  /* Потолок 38, а не 44: у «Лесной промышленности» самое длинное слово
     не разрывается по слогам, и на 44 px оно шире своей колонки на 68 px —
     ровно настолько и наезжало на кружок. Замерено, а не подобрано.
     break-word — страховка на будущее: если музей когда-нибудь назовёт
     павильон ещё длиннее, слово перенесётся, а не ляжет поверх кнопки. */
  font-size: clamp(26px, 2.8vw, 38px);
  overflow-wrap: break-word;
  transition: font-size var(--bk-dur) var(--bk-ease);
}

/* --- Свёрнутое состояние ---------------------------------------------------
   Плашка сжимается до строки «название + кружок» и по высоте совпадает
   с плашкой управления справа. Ширина по содержимому, а не 44ch: пустая
   колонка справа от короткого названия выглядела бы обрезанной плашкой. */
.bk-showcase__body[data-open="false"] {
  /* Вертикальные отступы — как у плашки управления: 16 + кружок 40 + 16 = 72,
     ровно --bk-plate-h. Штатные clamp(20px,3vw,48px) дали бы 128 и плашки
     встали бы разной высоты.
     Шире обычной плашки (34rem против 44ch): в свёрнутом виде название должно
     помещаться в одну строку, иначе «Цветоводство и озеленение» переносится
     и высота опять расходится с управлением.
     width по содержимому НЕ ставим: max-content считается и по скрытым частям,
     и плашку распирало на всю длину описания. */
  max-width: min(60%, 34rem);
  padding-block: var(--bk-s-3);
  gap: 0;    /* иначе свёрнутая плашка держит 32 px пустоты между схлопнутыми частями */
}
.bk-showcase__body[data-open="false"] .bk-showcase__title { font-size: clamp(18px, 2vw, 26px); }

.bk-showcase__head { display: flex; align-items: center; gap: var(--bk-s-4); }

/* Текст плашки колонкой. До правки от 03.09.2026 в строке лежали только
   заголовок и кружок, и flex: 1 стоял прямо на заголовке. Теперь над ним
   всегда виден надзаголовок с номером павильона, а у закрытого павильона ещё
   и плашка «Откроется», — растягивается обёртка, а не заголовок.

   min-width: 0 обязателен и здесь: без него длинное название не даёт колонке
   сжаться, и кружок уезжает за край плашки. */
.bk-showcase__headtext { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--bk-s-2); }

/* Кружок со стрелкой. z-index обязателен: растянутая ссылка слайда накрывает
   плашку целиком, и без него нажатие уходило бы на страницу павильона. */
.bk-showcase__toggle {
  position: relative; z-index: 1;
  flex: none; width: var(--bk-ctl-h-s); height: var(--bk-ctl-h-s); padding: 0;
  display: grid; place-items: center;
  background: none; color: var(--bk-accent);
  border: 1px solid var(--bk-accent); border-radius: var(--bk-radius-pill);
  cursor: pointer;
  transition: background-color var(--bk-dur-fast) var(--bk-ease),
              color var(--bk-dur-fast) var(--bk-ease),
              transform var(--bk-dur) var(--bk-ease);
}
.bk-showcase__toggle:hover { background: var(--bk-accent); color: var(--bk-text-on-accent); }
.bk-showcase__body[data-open="true"] .bk-showcase__toggle { transform: rotate(180deg); }

/* Раскрываемые части — над названием и под ним.

   Высота анимируется через grid-template-rows 0fr → 1fr. Это единственный
   способ доехать до «высоты по содержимому» без замера скриптом: max-height
   с запасом даёт рваную скорость, а точную высоту пришлось бы пересчитывать
   при каждой смене ширины.

   Отступы лежат ВНУТРИ раскрываемой части, а не в gap плашки: gap применяется
   между элементами независимо от их высоты, и в свёрнутом виде плашка
   получала бы 32 лишних пикселя пустоты. */
.bk-showcase__extra {
  display: grid; grid-template-rows: 0fr;
  /* ГРАБЛИ: без min-height:0 не сворачивается. Раскрываемая часть — это флекс-
     элемент плашки, а у флекс-элементов min-height по умолчанию auto, то есть
     «не ниже своего содержимого». Строка грида честно уходила в 0fr, а высота
     всё равно оставалась. Расстояние между частями держит gap плашки, а не
     отступы внутри: отступ входит в размер бокса и в свёрнутом виде остался бы
     висеть теми же пикселями. */
  min-height: 0;
  transition: grid-template-rows var(--bk-dur) var(--bk-ease);
}
.bk-showcase__extra > * {
  overflow: hidden;
  display: flex; flex-direction: column; gap: var(--bk-s-4);
}
.bk-showcase__body[data-open="true"] .bk-showcase__extra { grid-template-rows: 1fr; }

/* На телефоне наложение текста на картинку не выигрывает ничего: кадр становится
   вертикальным, фото сжимается, текст ложится на самую детальную его часть.
   Поэтому слайд раскладывается на два этажа — визуал сверху, текст под ним
   на сплошной заливке. Одинаково для фотографии и для калейдоскопа. */
@media (max-width: 767px) {
  .bk-showcase { height: auto; display: flex; flex-direction: column; }
  .bk-showcase__visual,
  .bk-showcase--kaleido .bk-showcase__visual,
  .bk-showcase--pattern .bk-showcase__visual { position: relative; inset: auto; width: 100%; aspect-ratio: 4 / 3; }
  .bk-showcase--kaleido .bk-showcase__visual { padding: var(--bk-s-4); }
  .bk-showcase--photo .bk-showcase__body { background: none; }   /* текст уже на сплошной заливке */
  .bk-showcase__body {
    position: relative; inset: auto; padding: var(--bk-s-5) var(--bk-s-5) var(--bk-s-6);
    min-height: 0; justify-content: flex-start;
  }
  /* Плашка сворачивается и на телефоне — правка от 26.08.2026.
     Раньше здесь стояло обратное: «сворачивать нечего, текст под кадром никому
     не мешает». На деле мешает: пять слайдов подряд, у каждого надзаголовок,
     название, описание и кнопка, и карусель растягивается на три экрана —
     листать её приходится вслепую. В свёрнутом виде видно название и стрелку,
     и все пять павильонов помещаются в один взгляд.

     Ширину плашки в свёрнутом виде НЕ ограничиваем, в отличие от десктопа:
     там она стоит на фотографии рядом с плашкой управления и обязана с ней
     совпасть по высоте, здесь она под кадром и занимает всю ширину. */
  .bk-showcase__body,
  .bk-showcase__body[data-open="false"] { width: auto; max-width: none; }
  /* Свёрнутое состояние бьёт мобильную раскладку по специфичности: селектор
     с атрибутом весомее простого класса, поэтому отступы задаются и здесь. */
  .bk-showcase__body[data-open="false"] {
    padding-block: var(--bk-s-4);
    gap: 0;   /* иначе свёрнутая плашка держит пустоту между схлопнутыми частями */
  }
  .bk-showcase__body[data-open="false"] .bk-showcase__title { font-size: 20px; }

  /* Вся плашка — цель нажатия, не только кружок: на телефоне попасть пальцем
     в кружок 40 px труднее, чем в строку во всю ширину. Обработчик в ui-kit.js;
     кружок при этом остаётся — он и подсказка о том, что плашка раскрывается,
     и единственная доступная с клавиатуры цель. */
  .bk-showcase__body { cursor: pointer; }

  /* Растянутая ссылка заголовка на телефоне отключена. Иначе она перехватывала
     бы любой тап по плашке и уводила на страницу павильона вместо раскрытия.
     Дорога на страницу остаётся кнопкой «Подробнее» внутри раскрытой части —
     она теперь настоящая ссылка. Плата: на телефоне фотография перестала быть
     ссылкой. */
  .bk-showcase__title .bk-card__link::after { content: none; }

  /* ГРАБЛИ, стоившие часа. На десктопе раскрывашка работает на
     grid-template-rows 0fr → 1fr, на телефоне этот механизм не работает
     ни в одну сторону, и заменить его на что-нибудь чисто-CSS не вышло:

     · overflow: hidden — строка при 1fr остаётся нулевой, плашка не растёт
       ни на пиксель, хотя data-open честно переключается;
     · overflow: clip — растёт, но перестаёт схлопываться обратно;
     · height: 0 → auto с interpolate-size — при переходе высота залипает
       на нуле; без перехода то же правило отрабатывает верно;
     · max-height: 0 → 16rem — части остаются нулевыми.

     Разница с десктопом в том, что там плашка позиционирована абсолютом
     и имеет определённую высоту, а здесь высоту задаёт содержимое, и вклад
     раскрываемой части считается нулевым.

     Поэтому высоту на телефоне выставляет скрипт, в пикселях (см. ui-kit.js,
     syncExtras). Переход между двумя числами браузер отрабатывает без всяких
     оговорок. Без JS плашка останется свёрнутой — ровно как и раньше:
     слайдер и так без JS показывает один слайд, а полное описание павильона
     лежит на его странице. */
  .bk-showcase__extra {
    display: block; height: 0; overflow: hidden;
    /* flex: none обязателен. Плашка — колоночный флекс, и раскрываемая часть
       в ней по умолчанию сжимаема: выставленную в пикселях высоту флекс
       ужимал обратно в ноль, и плашка не росла. */
    flex: none;
    transition: height var(--bk-dur) var(--bk-ease);
  }
  /* обрезает теперь сама раскрываемая часть, внутреннему блоку это не нужно */
  .bk-showcase__extra > * { overflow: visible; }
}

/* --------------------------------------------------------------------------
   14. Навигационный маркер направления [ДС §14.4]
   -------------------------------------------------------------------------- */
.bk-marker { display: inline-flex; flex-direction: column; align-items: center; gap: var(--bk-s-3); text-decoration: none; color: var(--bk-text); }
.bk-marker__ring { position: relative; width: var(--size, 128px); aspect-ratio: 1; }
.bk-marker__ring > img { position: absolute; inset: 0; width: 100%; height: 100%; }
/* в брендбуке объект КРУПНЕЕ кольца и выходит за его границы [ББ с.46] */
.bk-marker__obj {
  inset: -13% !important; width: 126% !important; height: 126% !important;
  object-fit: contain;
  transition: transform var(--bk-dur) var(--bk-ease);
}
.bk-marker:hover .bk-marker__obj { transform: scale(1.04); }   /* кольцо не вращается */
.bk-marker__label {
  font-family: var(--bk-font-display); text-transform: uppercase;
  font-size: 15px; letter-spacing: .05em; line-height: .95; text-align: center;
  transition: color var(--bk-dur-fast) var(--bk-ease);
}
.bk-marker:hover .bk-marker__label { color: var(--bk-dir, var(--bk-accent)); }

/* --------------------------------------------------------------------------
   15. Карта павильонов
   --------------------------------------------------------------------------
   Схема ВДНХ — светлая, у неё своя фирменная графика, и на «тёмном лесу» она
   неизбежно будет ярким пятном. Поэтому она подана как отдельный документ,
   положенный на страницу: рамка, тонкий кант, подпись под кадром. Спорить
   с ней тёмными плашками поверх бесполезно — выиграет она.

   Метки — настоящие кнопки, а не области на растре: получают фокус,
   озвучиваются скринридером и не разъезжаются при смене размера экрана,
   потому что позиция задана в процентах, а размер — в долях ширины кадра. */
.bk-map { position: relative; }

/* На узком экране схема не уменьшается до нечитаемости, а прокручивается вбок:
   подписи ВДНХ и так на пределе, а при ширине 390 px пропадут совсем.
   Про боковую прокрутку надо сказать словами: сама по себе она не видна. */
.bk-map__frame { overflow-x: auto; overscroll-behavior-x: contain; border: 1px solid var(--bk-border); }
.bk-map__hint { display: none; }
@media (max-width: 900px) { .bk-map__hint { display: inline; } }

.bk-map__canvas {
  position: relative;
  min-width: 860px;                 /* ниже этой ширины схему уже нельзя читать */
  container-type: inline-size;
  /* Метка уменьшена 24.08.2026. Схема ВДНХ плотно подписана, и кружок прежнего
     размера при любом положении задевал соседнюю подпись: под ним просто
     не оставалось свободного места. 26 px в самом узком случае — это ещё
     нажимаемая цель (минимум по WCAG 2.2 — 24 px). */
  --bk-pin: 36px;                   /* запасное значение, если cqw не поддержан */
  --bk-pin: clamp(26px, 2.6cqw, 44px);
  --bk-pin-fz: 13px;
  --bk-pin-fz: clamp(11px, .95cqw, 16px);
}
.bk-map__canvas > img { width: 100%; height: auto; display: block; }

.bk-map__pin {
  position: absolute; translate: -50% -50%;
  width: var(--bk-pin); height: var(--bk-pin); border-radius: 50%; padding: 0;
  display: grid; place-items: center; cursor: pointer;
  /* Заливка полупрозрачная: сквозь метку видно схему, и кружок читается как
     метка НА карте, а не как дырка в ней. 72 % — предел, ниже которого белая
     цифра на светлом участке схемы теряет контраст (на 72 % выходит 6,5:1).
     В наведённом и раскрытом состоянии заливка снова сплошная: это выделение,
     и оно должно быть однозначным. */
  background: color-mix(in srgb, var(--bk-bg) 72%, transparent);
  border: 2px solid var(--bk-dir, var(--bk-accent));
  color: var(--bk-text); font-family: var(--bk-font-mono); font-size: var(--bk-pin-fz); letter-spacing: -.05em;
  transition: transform var(--bk-dur-fast) var(--bk-ease), background-color var(--bk-dur-fast) var(--bk-ease), color var(--bk-dur-fast) var(--bk-ease);
}
/* Цвет надписи берётся из токена направления, а не подбирается по подстроке
   в атрибуте style: четыре цвета из шести светлые, белый на них не читается.
   Значение по умолчанию — «тёмный лес», потому что заливка по умолчанию лайм. */
.bk-map__pin:hover, .bk-map__pin:focus-visible, .bk-map__pin[aria-expanded="true"] {
  transform: scale(1.12);
  background: var(--bk-dir, var(--bk-accent));
  color: var(--bk-dir-text, var(--bk-text-on-accent));
}

/* Метка-ссылка. На схеме проезда карточек нет вовсе: там все метки ведут
   наружу — точка транспорта на Яндекс.Карты, павильон на свою страницу. */
a.bk-map__pin { text-decoration: none; }

/* Точка транспорта. Заливка сплошная лаймовая, а не полупрозрачная тёмная,
   как у павильонов: на одной схеме два разных смысла, и различать их только
   цифрой внутри нельзя — цифры павильонов (17, 28, 29, 31) и цифры остановок
   (1—4) человек читает одинаково. Плюс цифра тут не единственный признак:
   те же номера повторены в списке под схемой словами. */
.bk-map__pin--stop {
  background: var(--bk-accent);
  border-color: var(--bk-dark-forest);
  color: var(--bk-text-on-accent);
}
.bk-map__pin--stop:hover, .bk-map__pin--stop:focus-visible {
  background: var(--bk-dark-forest);
  color: var(--bk-accent);
}

/* Схема проезда, в отличие от схемы павильонов, НЕ прокручивается вбок,
   а вписывается в любую ширину целиком.
   Правило «не уменьшать, а прокручивать» придумано для тесной схемы, где
   содержание — подписи зданий: сжатые до нечитаемости, они бесполезны.
   Здесь содержание другое — четыре метки и то, как они расположены вокруг
   территории. Обрезанная схема отвечает на вопрос «как добраться» неверно:
   в кадр попадает один Хованский въезд, а метро не видно вовсе, и человек
   даже не знает, что пропустил три точки из четырёх. Подписи при этом
   не теряются: всё, что на схеме, повторено словами в списке под ней. */
.bk-map--route .bk-map__frame { overflow-x: visible; }
.bk-map--route .bk-map__canvas { min-width: 0; }
.bk-map--route .bk-map__hint { display: none; }   /* двигать вбок нечего */

/* Метки павильонов на узкой схеме прячутся, метки транспорта остаются.
   Причина арифметическая. Метка не уменьшается ниже 26 px — это нижняя
   граница нажимаемой цели по WCAG 2.2, — а расстояние между павильонами
   № 28 и № 29 составляет 4,79 % ширины кадра (3,96 % по горизонтали
   и 2,69 % по вертикали, с поправкой на пропорцию кадра). Кружки сходятся
   вплотную на 545 px и ниже; порог взят с запасом. Ниже него три метки
   превращаются в кляксу поверх той самой точки, до которой человеку идти.
   Точки транспорта разнесены по краям территории и не спорят ни между
   собой, ни с павильонами. Список павильонов при этом никуда не девается:
   он стоит текстом ниже на той же странице. */
@container (max-width: 620px) {
  .bk-map--route .bk-map__pin:not(.bk-map__pin--stop),
  .bk-map--route .bk-map__pin:not(.bk-map__pin--stop) + .bk-map__name { display: none; }
}

/* Блок проезда: схема слева, текст и точки справа.
   Та же раскладка, что у секции «Где это на ВДНХ» в «Мирах», и по той же
   причине: схема здесь иллюстрация к ответу, а ответ — текст и четыре точки.
   Во всю ширину схема требовала читать подписи, которых на широком кадре
   всё равно не разобрать, и отжимала список на второй экран.

   Колонки не равные: схеме нужна ширина, чтобы метки не слиплись, тексту —
   комфортная строка. 1,25fr против 1fr с полом в 320 px на правой колонке:
   ниже 320 строка «Метро «Ботанический сад»» переносится на три слова.

   Порог 1024 px — тот же, что у остальной раскладки страницы. Ниже одна
   колонка, и порядок в разметке (текст → схема → список) оказывается ровно
   тем, что нужен на телефоне: сначала ответ, потом картинка, потом точки
   с номерами, пока номера на схеме ещё перед глазами. */
.bk-route { display: grid; row-gap: var(--bk-s-6); }

@media (min-width: 1024px) {
  .bk-route {
    grid-template-columns: minmax(0, 1.25fr) minmax(320px, 1fr);
    column-gap: var(--bk-gutter-fluid, 24px);
    align-items: start;
  }
  /* Строк ровно две, и вторая забирает остаток высоты. Без этого схема,
     которая выше текста и списка вместе взятых, растягивала бы обе строки
     поровну — и между текстом и точками зияла бы дыра в полэкрана. */
  .bk-route { grid-template-rows: max-content 1fr; }
  /* Схема переезжает в первую колонку через grid-column, а не порядком
     в разметке: порядок для скринридера и для узкого экрана остаётся
     прежним. Тот же приём, что у .bk-worlds. */
  .bk-route__map   { grid-column: 1; grid-row: 1 / span 2; }
  .bk-route__lead  { grid-column: 2; grid-row: 1; }
  .bk-route__stops { grid-column: 2; grid-row: 2; align-self: start; margin-top: 0; }

  /* В правой колонке список всегда в одну колонку. Селектор с родителем
     обязателен: .bk-stops с его auto-fit по 260 px описан ниже по файлу
     и при равной специфичности побеждает — в колонке 420 px он собирал
     две колонки и рвал «Метро «Ботанический сад»» на три строки. */
  .bk-route .bk-route__stops { grid-template-columns: minmax(0, 1fr); }
}

/* Список остановок под схемой. Он же основная навигация: подсказку при
   наведении на телефоне не увидит никто, а схема там уезжает вбок. */
.bk-stops {
  margin: var(--bk-s-6) 0 0; padding: 0; list-style: none;
  display: grid; gap: var(--bk-s-4);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.bk-stops__item { display: flex; gap: var(--bk-s-3); align-items: flex-start; }
.bk-stops__num {
  flex: none; width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--bk-accent); color: var(--bk-text-on-accent);
  font-family: var(--bk-font-mono); font-size: 13px; letter-spacing: -.05em;
}
.bk-stops__text { display: flex; flex-direction: column; gap: 2px; }
/* Значок «откроется в новой вкладке» идёт по тексту, а не рядом с блоком
   текста: у .bk-i стоит display: block, и без этой строки он уезжает
   на строку ниже, а с inline-flex — вбок от всего названия и повисает
   в стороне, когда название переносится. */
.bk-stops__text a .bk-i { display: inline-block; vertical-align: -.15em; margin-left: 6px; }

/* Подсказка с названием при наведении — то, что просит ТЗ («при наведении
   появляется подсказка»). Только CSS: раскрытая карточка это уже клик. */
.bk-map__name {
  position: absolute; translate: -50% -50%; z-index: 2;
  padding: 6px 10px; white-space: nowrap; pointer-events: none;
  background: var(--bk-bg); border: 1px solid var(--bk-border-strong);
  font-family: var(--bk-font-mono); font-size: 12px; letter-spacing: -.05em; color: var(--bk-text);
  opacity: 0; transition: opacity var(--bk-dur-fast) var(--bk-ease);
}
.bk-map__pin:hover + .bk-map__name, .bk-map__pin:focus-visible + .bk-map__name { opacity: 1; }
.bk-map__pin[aria-expanded="true"] + .bk-map__name { opacity: 0; }   /* карточка уже открыта */

/* Карточка павильона поверх схемы. Открывается по клику, закрывается по клику
   вне, по Esc и по крестику; одновременно открыта не больше одной.
   --bk-dx выставляет скрипт, если карточка упирается в край кадра. */
.bk-map__popup {
  position: absolute; z-index: 3;
  width: min(300px, 68cqw);
  translate: calc(-50% + var(--bk-dx, 0px)) calc(var(--bk-pin) / 2 + 10px);
  background: var(--bk-surface); border: 1px solid var(--bk-border-strong);
  padding: var(--bk-s-5);
  display: flex; flex-direction: column; gap: var(--bk-s-3);
  box-shadow: 0 18px 48px rgba(9, 24, 20, .55);
}
.bk-map__popup[data-flip="up"] { translate: calc(-50% + var(--bk-dx, 0px)) calc(-100% - var(--bk-pin) / 2 - 10px); }
.bk-map__popup[hidden] { display: none; }
.bk-map__popup__close {
  position: absolute; top: 8px; right: 8px;
  width: 32px; height: 32px; border-radius: 50%; padding: 0;
  display: grid; place-items: center; cursor: pointer;
  background: none; border: 0; color: var(--bk-text-muted);
}
.bk-map__popup__close:hover { color: var(--bk-accent); }

/* Хвостик карточки — привязывает её к метке, иначе на плотной схеме
   непонятно, к какому кружку она относится. */
.bk-map__popup::before {
  content: ""; position: absolute; left: calc(50% - var(--bk-dx, 0px)); top: -7px; translate: -50% 0;
  width: 12px; height: 12px; rotate: 45deg;
  background: var(--bk-surface); border-left: 1px solid var(--bk-border-strong); border-top: 1px solid var(--bk-border-strong);
}
.bk-map__popup[data-flip="up"]::before {
  top: auto; bottom: -7px;
  border: 0; border-right: 1px solid var(--bk-border-strong); border-bottom: 1px solid var(--bk-border-strong);
}

/* --------------------------------------------------------------------------
   16. Уведомления и пустые состояния
   -------------------------------------------------------------------------- */
.bk-note {
  display: flex; gap: var(--bk-s-4); padding: var(--bk-s-5);
  border: 1px solid var(--bk-border); border-left: 3px solid var(--bk-accent);
  background: rgba(208,239,54,.06);
}
/* Колонка текста внутри уведомления обязана уметь сжиматься. По умолчанию
   flex-элемент не становится уже своего содержимого, и почта экскурсионного
   отдела DFKU-excursioncultur@culture.mos.ru на 320 px вылезала за рамку
   блока. Длинные адреса и ссылки внутри уведомления переносим по любому месту:
   разорванная почта читается, уехавшая за край — нет. */
.bk-note > * { min-width: 0; }
.bk-note a { overflow-wrap: anywhere; }
.bk-note--warn { border-left-color: var(--bk-notice); background: rgba(242,210,122,.06); }
.bk-note--danger { border-left-color: var(--bk-danger); background: rgba(218,41,28,.08); }

/* Список «подпись — значение»: практические сведения об экскурсии.
   Раньше это был .bk-row с подписью в 170 px, и на 320 px список разъезжался:
   короткое значение вставало в колонку справа от подписи, длинное переносилось
   под неё на всю ширину — половина строк выглядела выключенной вправо,
   половина влево. Сетка держит две колонки на широком экране и честно
   складывается в одну на узком. */
.bk-deflist { display: grid; grid-template-columns: 170px minmax(0, 1fr); gap: var(--bk-s-3) var(--bk-s-4); }
.bk-deflist dt, .bk-deflist dd { margin: 0; }
@media (max-width: 599px) {
  .bk-deflist { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .bk-deflist dd { margin-bottom: var(--bk-s-3); }
  .bk-deflist dd:last-child { margin-bottom: 0; }
}

/* --- Маскот Лука [ДС §11] ---------------------------------------------------

   Лука уместен в пустых состояниях, на 404, у неоткрытых павильонов, в правилах
   посещения и в подтверждениях. Не появляется в hero, ценах, шапке и подвале
   [ДС §11.6]: там работает калейдоскоп и фирменная графика.

   Композиция взята с брендбучного носителя [ББ с.34]: облако реплики сверху,
   хвостом вниз, персонаж под ним. Внутри облака пара «крупная реплика капсом +
   мягкое пояснение строчными» — это и есть тон голоса Луки.

   Облако залито «поверхностью», а не чистым «тёмным лесом», как на носителе.
   В брендбуке облако лежит на лаймовом поле, а фон сайта — сам тёмный лес
   #13322B: облако в цвет фона на нём просто исчезает. Поверхность #1B463C —
   уже принятая в системе адаптация тёмного леса для элементов на тёмном фоне,
   новых цветов не вводим.

   Скругление облака — законное исключение из правила «радиус 0 везде» [ДС §19.4]:
   это форма из брендбука, а не декоративное смягчение угла. Радиус в оригинале
   равен половине высоты тела облака, то есть чистая капсула, — поэтому 999px
   воспроизводит форму точно при любой длине реплики. */
.bk-luka { display: flex; flex-direction: column; align-items: center; gap: 0; margin: 0; }

.bk-luka__bubble {
  position: relative;
  background: var(--bk-surface);
  border-radius: 999px;
  padding: var(--bk-s-5) var(--bk-s-7);
  text-align: center;
  max-width: 34ch;
  /* Хвост торчит вниз на 18px и обязан попасть на макушку персонажа,
     а не висеть над ней в пустоте. */
  margin-bottom: 18px;
}

/* Хвост облака. В оригинале это капля, уходящая вниз и влево от центра;
   повёрнутый квадрат с одним скруглённым углом повторяет её силуэт и,
   в отличие от вставленного SVG, не растягивается вместе с репликой. */
.bk-luka__bubble::after {
  content: ""; position: absolute;
  left: 50%; bottom: -14px;
  width: 34px; height: 34px;
  background: var(--bk-surface);
  border-radius: 0 0 60% 0;
  transform: translateX(-70%) rotate(12deg);
}

.bk-luka__say {
  font-family: var(--bk-font-display);
  font-size: clamp(22px, 2.6vw, 34px);
  line-height: 1; letter-spacing: .05em;
  text-transform: uppercase;   /* строчных в шрифте нет */
  font-weight: 400;
  color: var(--bk-accent);
  margin: 0;
}

.bk-luka__note {
  font-family: var(--bk-font-head);
  font-size: clamp(14px, 1.1vw, 16px); line-height: 1.25;
  color: var(--bk-text);
  margin: 6px 0 0;
}

/* Ширину задаёт вызывающая сторона через --bk-luka-w: кадры сюжетов имеют
   разное соотношение сторон (600×660, 1115×729, 930×702), и одна ширина
   на всех дала бы персонажа то с ноготь, то во весь блок. */
.bk-luka__fig { width: min(var(--bk-luka-w, 260px), 62vw); height: auto; display: block; }

.bk-luka--s { --bk-luka-w: 170px; }
.bk-luka--l { --bk-luka-w: 420px; }

/* Реплика уже сказана словами в разметке, картинка декоративная (alt=""),
   поэтому при выключенной анимации ничего не теряется. «Дыхание» — та же
   амплитуда ±1 %, что у калейдоскопа в hero [ДС §17.4]. */
@media (prefers-reduced-motion: no-preference) {
  .bk-luka__fig { animation: bk-luka-breathe 5.2s var(--bk-ease) infinite; transform-origin: 50% 92%; }
}
@keyframes bk-luka-breathe {
  0%, 100% { transform: scale(1)      rotate(0deg); }
  50%      { transform: scale(1.012) rotate(-.6deg); }
}

/* Пустое состояние: Лука + заголовок + пояснение + действие.
   Реплика в облаке короткая и служебная, содержательный текст — в заголовке
   под фигурой. Это та же брендбучная пара «крупно + пояснение», просто
   пояснение вынесено из облака в разметку страницы. */
.bk-empty { display: flex; flex-direction: column; align-items: center; gap: var(--bk-s-4); text-align: center; padding-block: var(--bk-s-8); }
.bk-empty img { width: min(260px, 60vw); height: auto; }
.bk-empty .bk-luka { margin-bottom: var(--bk-s-2); }

/* Несколько сюжетов в ряд: правила посещения. Персонажи выравниваются по низу,
   а не по верху, — кадры разной высоты, и по верхнему краю Лука со шваброй
   повисал бы в воздухе рядом с тем, кто стоит на земле. */
.bk-lukas {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--bk-s-6); align-items: end; justify-items: center;
  margin-top: var(--bk-s-8);
}

/* --------------------------------------------------------------------------
   17. Подвал
   -------------------------------------------------------------------------- */
.bk-footer { background: var(--bk-bg-alt); border-top: 1px solid var(--bk-border); padding-block: var(--bk-s-8) var(--bk-s-6); }
.bk-footer__cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--bk-s-7); }
/* Та же причина, что и у .bk-note: в колонке контактов лежат почты длиной
   в 35 знаков, а колонка на узком экране всего 200 px. */
.bk-footer a { color: var(--bk-text-muted); text-decoration: none; font-size: 15px; overflow-wrap: anywhere; }
.bk-footer a:hover { color: var(--bk-accent); }
.bk-footer__legal { margin-top: var(--bk-s-7); padding-top: var(--bk-s-5); border-top: 1px solid var(--bk-border); }

/* соцсети: кольцо — базовый модуль системы (круг) [ББ с.19, 46] */
.bk-social { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--bk-border-strong); color: var(--bk-text); text-decoration: none; font-family: var(--bk-font-head); font-weight: 800; font-size: 13px; letter-spacing: .02em; transition: background-color var(--bk-dur-fast) var(--bk-ease), color var(--bk-dur-fast) var(--bk-ease), border-color var(--bk-dur-fast) var(--bk-ease); }
.bk-social:hover { background: var(--bk-accent); border-color: var(--bk-accent); color: var(--bk-text-on-accent); }

/* --------------------------------------------------------------------------
   18. Прочее
   -------------------------------------------------------------------------- */
.bk-divider { height: 1px; background: var(--bk-border); border: 0; margin: 0; }

/* паттерн-разделитель: под текст всегда 8–20 % [ДС §9.4] */
.bk-pattern {
  background-repeat: repeat; background-size: 280px;
  opacity: .12; height: 120px;
}

.bk-visually-hidden {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.bk-skiplink {
  position: absolute; left: var(--bk-s-4); top: -100px; z-index: 999;
  padding: var(--bk-s-3) var(--bk-s-4);
  background: var(--bk-accent); color: var(--bk-text-on-accent);
  font-family: var(--bk-font-head); font-weight: 700; text-decoration: none;
}
.bk-skiplink:focus { top: var(--bk-s-4); }

/* --------------------------------------------------------------------------
   19. Motion [ДС §17.4] — появление от центра, 400–600 мс
   -------------------------------------------------------------------------- */
@keyframes bk-emerge {
  from { opacity: 0; transform: scale(.96); }
  to   { opacity: 1; transform: scale(1); }
}
.bk-emerge { animation: bk-emerge var(--bk-dur) var(--bk-ease) both; }

/* калейдоскоп «дышит» ±1 %, 16 с. Вращение запрещено — нарушает симметрию образа */
@keyframes bk-breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.01); } }
.bk-breathe { animation: bk-breathe 16s ease-in-out infinite; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------------------------------
   20. Блоки страницы: hero, шапка секции, факты, строка события, список павильонов
   -------------------------------------------------------------------------- */

/* HERO. Единственная секция сайта с обязательной центральной симметрией
   [ДС §12.6] — здесь буквально воспроизведены три зоны композиции брендбука
   [ББ с.39]: сверху сообщение, в центре key visual, снизу информация.

   Калейдоскоп в hero — НЕ заглушка под будущую фотографию, а постоянный элемент
   айдентики (главный калейдоскоп, ББ с.27): он объединяет все направления и
   меняться на снимок не будет никогда. Поэтому строить композицию вокруг его
   симметрии безопасно. В слайдере ниже — ровно наоборот: там калейдоскоп стоит
   временно, и слайд собран так, чтобы пережить замену на горизонтальное фото. */
.bk-hero { position: relative; overflow: hidden; padding-block: clamp(28px, 4vh, 56px) clamp(32px, 4vh, 64px); }

/* Снизу поля нет: там стоит калейдоскоп, срезанный по нижней половине,
   и срез должен приходиться ровно на границу секции. С полем под ним
   оставалась полоса фона в 32 px, и картинка читалась не срезанной,
   а просто закончившейся. */
@media (max-width: 1023px) { .bk-hero { padding-bottom: 0; } }

/* ——————————————————————————————————————————————————————————————
   Первый экран. Композиция по референсу клиента (Shakuro, AdCentrl homepage),
   правка от 26.08.2026: слева сообщение, действие и Лука, справа калейдоскоп —
   крупный, в верхнем углу, обрезанный краями экрана, с довёрткой при прокрутке.

   Раскладка одна на все ширины. Сначала она была сделана только с 1024 px,
   а телефон оставался на прежней центрированной колонке — и это оказалось
   ошибкой: на телефоне человек видел совсем другой первый экран, без Луки
   и со старым калейдоскопом посередине. Меняются не правила, а числа.

   Это отход от брендбука, а не недосмотр: в ББ с.37 и с.39 калейдоскоп стоит
   в центре носителя и композиция строится вокруг него, а §10.3 дизайн-системы
   прямо запрещает его обрезать и поворачивать. Решение клиента, вопрос вынесен
   в 5-ЗАДАЧИ.md. На остальных экранах сайта центральная композиция сохранена.
   —————————————————————————————————————————————————————————————— */
.bk-hero__inner {
  /* положение Луки считается от этого контейнера */
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  column-gap: var(--bk-gutter-fluid, 24px);
  row-gap: clamp(16px, 2.4vh, 32px);
  /* Блок прижат к верху: в верхнем правом углу стоит Лука, и центрирование
     отодвигало бы текст от него вниз, оставляя над надзаголовком пустую
     полосу. С 1024 px центрирование возвращается. */
  align-content: start;
  justify-items: start;
  text-align: left;

  /* Геометрия угла — двумя числами в одном месте, потому что от них зависит
     и сам Лука, и ширина текста рядом с ним, и высота, ниже которой может
     начинаться лид. Держать их порознь уже пробовали: каждая правка одного
     ломала другое.

     Правкой от 26.08.2026 в углу стоит Лука, а не калейдоскоп. Поэтому здесь
     нет выноса за край: калейдоскоп можно обрезать краем экрана, персонажа —
     нельзя, обрезанный маскот читается как ошибка вёрстки. Лука стоит целиком,
     по той же правой линии, что и весь контент. */
  --bk-luka-w:    min(34vw, 190px);
  --bk-luka-h:    calc(1.07 * var(--bk-luka-w));    /* кадр 602×640 */
  /* свободная полоса слева от Луки */
  --bk-band:      calc(100vw - 2 * var(--bk-pad) - var(--bk-luka-w) - var(--bk-s-4));
}

/* На телефоне первый экран занимает столько, сколько занимает.
   Раньше здесь стояла та же min-height, что и на десктопе, — экран минус шапка,
   но не больше 720 px. На телефоне содержимое короче, и лишняя высота
   скапливалась внизу: 270 px пустоты перед «Мирами Биокластера». */
@media (min-width: 1024px) {
  .bk-hero__inner {
    /* первый экран должен помещаться в экран: слоган, калейдоскоп и — обязательно —
       кнопки. Если кнопки уезжают за сгиб, первый экран перестаёт работать. */
    min-height: min(calc(100svh - 76px - clamp(60px, 8vh, 120px)), 720px);
  }
}

/* Порядок на телефоне: надзаголовок и слоган (слева от Луки), лид, кнопки,
   факты, и последним — калейдоскоп, обрезанный нижней половиной.
   Раскладка задана поимённо, а не автопотоком: в разметке Лука и калейдоскоп
   стоят сразу после слогана, а показываются в других местах. */
.bk-hero__inner > .bk-overline { grid-row: 1; max-width: var(--bk-band); }
.bk-hero__slogan               { grid-row: 2;
                                 max-width: min(16ch, var(--bk-band));
                                 /* Всё, что идёт после слогана, обязано начинаться ниже Луки:
                                    лид во всю ширину иначе уехал бы ему под ноги. Высота
                                    считается от его низа за вычетом надзаголовка и отбивки. */
                                 min-height: calc(var(--bk-luka-h) - 36px);
                                 /* Кегль привязан к ширине полосы, а не только к ширине окна.
                                    `max-width` длинное слово не удерживает: «ПРОСТРАНСТВО,»
                                    не переносится внутри себя и вылезает за границу. Слово
                                    занимает ровно 7em при этом начертании и трекинге. */
                                 font-size: min(clamp(32px, 5.4vw, 80px), calc(var(--bk-band) / 7)); }
.bk-hero__lead                 { grid-row: 3; max-width: 58ch; }
.bk-hero__actions              { grid-row: 4; justify-self: stretch; }
.bk-hero__inner > .bk-facts    { grid-row: 5; justify-content: flex-start; }
.bk-hero__visual               { grid-row: 6; }

/* Лаймовая черта слева от лида — приём из референса. Заодно она отделяет
   пояснение от слогана: без центрирования два текстовых блока подряд
   у одного края сливаются в один. */
.bk-hero__lead {
  border-left: 2px solid var(--bk-accent);
  padding-left: var(--bk-s-4);
}

/* Кнопки первого экрана — в одну строку и одного размера.
   Грид, а не флекс: во флексе кнопка берёт ширину по подписи, и «Купить билет»
   выходит заметно уже «Миров Биокластера» — две кнопки одного веса читаются
   как главная и второстепенная. Две равные колонки уравнивают ширину, а
   растяжение по умолчанию — высоту, даже когда одна подпись переносится.

   Кегль и поля убавлены: в половине экрана кнопка на 18 px и с полями по 32
   оставляет подписи 60 px и рвёт её на три строки. */
.bk-hero__actions {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--bk-s-3);
  align-items: stretch;
  /* Потолок нужен для планшета: на телефоне две кнопки занимают всю ширину
     и это правильно, а на 1023 px без него они растягивались во весь экран
     и превращались в две плашки по полметра. */
  max-width: 560px;
}
.bk-hero__actions .bk-btn { width: 100%; font-size: 15px; padding-inline: var(--bk-s-3); text-align: center; }

/* Калейдоскоп внизу первого экрана: во всю ширину окна, нижняя половина
   срезана краем секции.

   Во всю ширину — значит наружу из полей контейнера, отсюда отрицательные
   поля. Срез — это бокс 2:1 с обрезкой: картинка квадратная, при ширине бокса
   её высота вдвое больше, и нижняя половина уходит под обрезку. object-fit
   тут не годится — он бы вписал картинку целиком и просто уменьшил её. */
.bk-hero__visual {
  justify-self: stretch;
  margin-inline: calc(-1 * var(--bk-pad));
  aspect-ratio: 2 / 1;
  overflow: hidden;
}
.bk-hero__visual img { width: 100%; height: auto; display: block; }

/* Лука в верхнем правом углу — на месте, где раньше стоял калейдоскоп.
   Абсолютом, поэтому не участвует в колонке: текст, кнопки и факты
   выстроены так, как были бы без него. */
.bk-hero__luka {
  position: absolute; z-index: 1;
  top: 0; right: var(--bk-pad, 20px);
  width: var(--bk-luka-w); height: auto;
}

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .bk-hero__luka { animation: bk-luka-breathe 5.2s var(--bk-ease) infinite; transform-origin: 50% 92%; }
}

/* ——————————————————————————————————————————————————————————————
   С 1024 px возвращается композиция по референсу клиента (Shakuro, AdCentrl):
   слева сообщение, действие и Лука, справа калейдоскоп — крупный, в верхнем
   углу, обрезанный краями экрана, с довёрткой при прокрутке.

   Это отход от брендбука, а не недосмотр: в ББ с.37 и с.39 калейдоскоп стоит
   в центре носителя и композиция строится вокруг него, а §10.3 дизайн-системы
   прямо запрещает его обрезать и поворачивать. Решение клиента, вопрос вынесен
   в 5-ЗАДАЧИ.md. На остальных экранах сайта центральная композиция сохранена.
   —————————————————————————————————————————————————————————————— */
@media (min-width: 1024px) {
  .bk-hero__inner {
    /* Третья колонка — поле под калейдоскоп, чтобы текст не уезжал под него. */
    grid-template-columns: minmax(0, 1fr) auto minmax(0, .55fr);
    align-content: center;
  }
  .bk-hero__inner > .bk-overline { grid-column: 1 / 3; max-width: none; }
  .bk-hero__slogan               { grid-column: 1 / 3; grid-row: 2; max-width: 18ch; min-height: 0;
                                   font-size: clamp(32px, 5.4vw, 80px); }
  .bk-hero__lead                 { grid-column: 1 / 3; grid-row: 3; max-width: 46ch; }

  /* Кнопки возвращаются к ширине по подписи: места хватает, и растянутые
     на полколонки они выглядели бы плашками, а не кнопками. */
  .bk-hero__actions {
    grid-column: 1; grid-row: 4; justify-self: start;
    display: flex; flex-wrap: wrap; gap: var(--bk-s-3);
    /* У .bk-btn задана только min-height, поэтому кнопка охотно растягивается.
       В одной строке грида с Лукой высоту строки задаёт он, и без этих двух
       строк кнопки вырастали в блоки по 140 px. */
    align-self: end; align-items: center;
  }
  .bk-hero__actions .bk-btn { width: auto; font-size: 18px; padding-inline: var(--bk-s-6); }

  /* Строка фактов идёт во всю ширину, иначе «Ср — вс, 11:00—19:00» уезжает
     на вторую строку. А вот её линия во всю ширину прочерчивалась прямо
     по калейдоскопу и читалась царапиной поверх картинки — поэтому линия
     не border, а градиент, который гаснет, не доходя до него. */
  .bk-hero__inner > .bk-facts {
    grid-column: 1 / -1; grid-row: 5;
    border-top: 0;
    background-image: linear-gradient(to right, var(--bk-border) 0 52%, transparent 72%);
    background-size: 100% 1px;
    background-repeat: no-repeat;
    background-position: left top;
  }

  /* Калейдоскоп снова вынут из потока в правый верхний угол и обрезан краями
     секции (у .bk-hero стоит overflow: hidden).

     z-index не отрицательный: у .bk-hero нет своего фона, и с -1 калейдоскоп
     уехал бы за фон страницы и пропал совсем. */
  .bk-hero__visual {
    position: absolute; z-index: 0; grid-row: auto;
    justify-self: auto; margin-inline: 0; overflow: visible;
    top: -22%; right: -13%;
    width: clamp(460px, 52vw, 1000px); height: auto; aspect-ratio: 1;
  }
  .bk-hero__visual img { width: 100%; height: 100%; object-fit: contain; }

  /* Лука уходит из угла во вторую колонку, в одну строку с кнопками. */
  .bk-hero__luka {
    position: static; grid-column: 2; grid-row: 4;
    align-self: end; justify-self: end;
    width: min(22vh, 220px, 18vw);
  }
}

/* Довёртка калейдоскопа при прокрутке — то, что просит референс.
   Сделана на CSS-таймлайне прокрутки, без единой строки JS: браузер считает
   её вне основного потока и не дёргает страницу.

   @supports обязателен. Где таймлайна нет, правило не применяется, и кадр
   остаётся с «дыханием» ±1 % от .bk-breathe — то есть деградация не в статику,
   а в прежнее поведение.

   Поворот на 28° выбран по симметрии самого калейдоскопа: у главного кадра
   она восьмилучевая, и на 45° он вернулся бы в исходное положение, а движение
   стало бы незаметным. */
@keyframes bk-hero-turn {
  from { transform: rotate(0deg)  scale(1); }
  to   { transform: rotate(28deg) scale(1.16); }
}

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .bk-hero__visual img {
      animation: bk-hero-turn linear both;
      animation-timeline: scroll(root block);
      animation-range: 0 100svh;
      transform-origin: 50% 50%;
    }
  }
}

/* Лука в левом поле первого экрана, на уровне слогана.
   Правкой от 26.08.2026 он переехал сюда от калейдоскопа. Рядом с калейдоскопом
   он спорил с ним за центр внимания, сдвигая смысловой центр экрана влево,
   а широкое поле слева от слогана всё это время пустовало. В новом положении
   калейдоскоп снова один на оси — центральная симметрия первого экрана
   [ДС §12.6] восстановлена, а Лука работает как приветствие сбоку.

   Лежит абсолютом в .bk-hero__inner и потому не участвует в колонке: слоган,
   калейдоскоп, лид и кнопки центрированы ровно так же, как были бы без него.

   left считается от --bk-pad, а не от нуля: контейнер для абсолютного
   потомка — это padding-box, то есть край окна. С нулём Лука прилип бы
   к самому краю, мимо той линии, по которой выровнена вся страница.

   Ширина — тройной минимум, и каждое число закрывает свой отказ:
     22vh   — на ноутбуке 1440×800 первый экран обязан вместить кнопки,
              и Лука в фиксированных пикселях выталкивал бы их за сгиб;
     250px  — потолок на больших мониторах, иначе он перерастает калейдоскоп;
     16vw   — защита от портрета планшета. Там 22vh даёт 300 px при поле
              слева всего в 222: Лука наезжал бы на слоган. Проверять это
              надо в высоком окне (1024×1366), а не в широком.

   До 1024 px Луки нет: ниже слоган занимает почти всю ширину, свободного
   поля слева не остаётся, и Луку либо резало бы (у .bk-hero стоит
   overflow: hidden — молча), либо он лёг бы на текст. */
/* «Дыхание» то же, что у Луки в пустых состояниях, — общий keyframes ниже.
   Своё у калейдоскопа: 16 s и ровно ±1 %, без наклона [ДС §17.4]. */
@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .bk-hero__luka { animation: bk-luka-breathe 5.2s var(--bk-ease) infinite; transform-origin: 50% 92%; }
}

/* Нижняя зона композиции — адрес, режим, состав комплекса. Моно, как вся
   служебная информация [ББ с.16]. */
.bk-facts {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--bk-s-3) var(--bk-s-6);
  width: 100%; margin: 0; padding: var(--bk-s-5) 0 0; list-style: none;
  border-top: 1px solid var(--bk-border);
}
.bk-facts li { display: flex; align-items: center; gap: var(--bk-s-3); }
.bk-facts li::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--bk-accent); flex: none; }

/* Шапка секции: надзаголовок, H2, лид и действие справа. Один повторяющийся
   ритм на всех секциях — иерархия строится отступами и кеглем, а не цветом. */
.bk-sectionhead {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end;
  gap: var(--bk-s-4) var(--bk-s-6); margin-bottom: clamp(28px, 3vw, 48px);
}
.bk-sectionhead__text { display: flex; flex-direction: column; gap: var(--bk-s-3); max-width: 62ch; }
@media (max-width: 599px) {
  .bk-sectionhead { grid-template-columns: minmax(0, 1fr); align-items: start; }
}

/* Главное событие афиши — карточка в разворот: кадр слева, текст справа.
   Вертикальная карточка на семь колонок вырастала до шестисот пикселей и
   оставляла рядом пустую колонку — событий в афише почти никогда не бывает
   столько, чтобы её заполнить. */
.bk-card--split { display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); align-items: stretch; }
.bk-card--split .bk-card__media { aspect-ratio: auto; height: 100%; min-height: 260px; }
.bk-card--split .bk-card__body { padding: clamp(24px, 3vw, 48px); justify-content: center; }
@media (max-width: 767px) { .bk-card--split { grid-template-columns: minmax(0, 1fr); } .bk-card--split .bk-card__media { aspect-ratio: 3 / 2; height: auto; min-height: 0; } }

/* Строка события — компактное представление афиши рядом с главным событием.
   Событию без фотографии карточка не нужна: строка честнее и плотнее, а дата
   в ней читается лучше, чем в сетке одинаковых плиток. */
.bk-eventrow {
  position: relative; display: grid; grid-template-columns: 4.5rem minmax(0, 1fr);
  gap: var(--bk-s-4); padding-block: var(--bk-s-5);
  /* линия сверху, а не снизу: строки раскладываются в две колонки, и при нижней
     границе последние строки колонок оказываются подчёркнуты, а первые нет */
  border-top: 1px solid var(--bk-border);
  transition: background-color var(--bk-dur-fast) var(--bk-ease);
}
.bk-eventrow:hover { background: rgba(208, 239, 54, .06); }
.bk-eventrow__date { display: flex; flex-direction: column; gap: 2px; font-family: var(--bk-font-mono); letter-spacing: -.05em; }
.bk-eventrow__day { font-size: 26px; line-height: 1; color: var(--bk-accent); }
.bk-eventrow__month { font-size: 12px; text-transform: uppercase; color: var(--bk-text-muted); }
.bk-eventrow__body { display: flex; flex-direction: column; gap: var(--bk-s-2); min-width: 0; }
.bk-eventrow__title { font-family: var(--bk-font-head); font-weight: 700; font-size: 18px; line-height: 1.2; }
.bk-eventrow:hover .bk-eventrow__title { color: var(--bk-accent); }

/* Календарь на всю ширину — вариант A компоновки блока 4 (ТЗ: «попробовать
   2 варианта»). Это не растянутый компактный календарь: смысл варианта в том,
   что в широкую клетку помещается само название события, а не только точка. */
/* Широкий календарь удалён 21.08.2026 вместе с отдельной секцией «Календарь
   событий»: календарь переехал в колонку рядом с афишей и снова стал
   компактным. Заодно ушла горизонтальная прокрутка главной на телефоне —
   её давал именно широкий вариант: семь колонок по 68 px минимум не влезали
   в 350 px экрана. */
.bk-cal__ev {
  font-family: var(--bk-font-body); font-size: 13px; line-height: 1.25; letter-spacing: 0;
  color: var(--bk-accent);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.bk-cal__more { font-family: var(--bk-font-mono); font-size: 11px; letter-spacing: -.05em; color: var(--bk-text-muted); }

/* Список павильонов. На телефоне он заменяет схему ВДНХ, а пока схемы нет —
   работает основной навигацией блока 5. Поэтому это не «дублёр мелким шрифтом»,
   а полноценный компонент: строка ростом с элемент управления, номер моноширинным,
   точка направления слева (прозрачная, если тема павильона ещё не согласована —
   иначе строки без темы съезжают влево). */
.bk-pavlist { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--bk-border); }
.bk-pavlist__link {
  position: relative; display: grid; align-items: center;
  grid-template-columns: 10px 5.5ch minmax(0, 1fr) auto; gap: var(--bk-s-4);
  padding: var(--bk-s-5) var(--bk-s-3); text-decoration: none;
  border-bottom: 1px solid var(--bk-border);
  transition: background-color var(--bk-dur-fast) var(--bk-ease), color var(--bk-dur-fast) var(--bk-ease);
}
.bk-pavlist__link:hover { background: rgba(208, 239, 54, .06); color: var(--bk-accent); }
.bk-pavlist__link .bk-i { opacity: 0; transition: opacity var(--bk-dur-fast) var(--bk-ease), transform var(--bk-dur-fast) var(--bk-ease); }
.bk-pavlist__link:hover .bk-i, .bk-pavlist__link:focus-visible .bk-i { opacity: 1; transform: translateX(4px); }
.bk-pavlist__title { font-family: var(--bk-font-head); font-weight: 700; font-size: clamp(17px, 1.5vw, 20px); }
@media (max-width: 599px) {
  .bk-pavlist__link { grid-template-columns: 10px minmax(0, 1fr) auto; }
  .bk-pavlist__num { display: none; }
}

/* --------------------------------------------------------------------------
   21. Страница павильона: шапка, галерея, карта
   -------------------------------------------------------------------------- */

/* Шапка павильона. Крупный кадр во всю ширину контейнера, текст поверх слева
   внизу — та же композиция, что и в витрине на главной [ДС §12.2]: человек
   приходит сюда кликом по слайду и должен узнать кадр, а не увидеть другую
   страницу. Логотипа на кадре нет и быть не может, шапка сайта выше остаётся
   на сплошной заливке [ББ с.10].

   Акцент направления идёт полосой над кадром и в точку у названия выставки —
   именно он и делает страницы павильонов разными. Текстом акцент не работает
   никогда: Виноград даёт на тёмном контраст 1,10 [ДС §7.4]. */
.bk-pavhero { position: relative; overflow: hidden; background: var(--bk-bg-alt); }
.bk-pavhero::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 4px; z-index: 2;
  background: var(--bk-dir, var(--bk-accent));
}
.bk-pavhero__visual { position: absolute; inset: 0; }
.bk-pavhero__visual img { width: 100%; height: 100%; object-fit: cover; }

/* Калейдоскоп темы вместо фотографии: он квадратный и обрезать его нельзя
   [ДС §10.3], поэтому вписывается целиком и уходит вправо, освобождая текст. */
.bk-pavhero--kaleido .bk-pavhero__visual {
  display: flex; justify-content: flex-end; padding: var(--bk-s-6);
}
.bk-pavhero--kaleido .bk-pavhero__visual img { width: auto; height: 100%; object-fit: contain; }

.bk-pavhero__veil {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(90deg, rgba(13,35,30,.94) 0%, rgba(13,35,30,.82) 40%, rgba(13,35,30,.18) 100%);
}
.bk-pavhero--kaleido .bk-pavhero__veil { background: none; }

.bk-pavhero__body {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; gap: var(--bk-s-4);
  max-width: 46ch;
  padding-block: clamp(56px, 8vw, 128px);
}
.bk-pavhero__title { font-size: clamp(30px, 4.4vw, 60px); }

@media (max-width: 899px) {
  /* На узком экране текст поверх фотографии перестаёт читаться: кадр и текст
     встают друг под другом, как в витрине на главной. */
  .bk-pavhero { display: flex; flex-direction: column; }
  .bk-pavhero__visual,
  .bk-pavhero--kaleido .bk-pavhero__visual {
    position: relative; inset: auto; display: block;
    width: 100%; aspect-ratio: 4 / 3; padding: 0;
  }
  .bk-pavhero--kaleido .bk-pavhero__visual { padding: var(--bk-s-5); }
  .bk-pavhero--kaleido .bk-pavhero__visual img { width: 100%; height: auto; margin-inline: auto; }
  .bk-pavhero__veil { display: none; }
  .bk-pavhero__body { max-width: none; padding-block: var(--bk-s-6) var(--bk-s-7); }
}

/* Описание и визитка. Разводятся по колонкам только там, где на визитку
   хватает ширины. На планшете контейнер переходит на 8 колонок, и «span 4/-1»
   ставил визитку в правую половину под текстом — она читалась как обрывок
   раскладки, а не как отдельный блок. Ниже 1024 px оба блока во всю ширину. */
.bk-pavgrid__text  { grid-column: span 7; }
.bk-pavgrid__aside { grid-column: span 4 / -1; }
@media (max-width: 1023px) {
  .bk-pavgrid__text, .bk-pavgrid__aside { grid-column: 1 / -1; }
}

/* Визитка павильона: часы, адрес, цена и кнопка покупки одним блоком.
   Держится у верхнего края экрана при прокрутке длинного описания —
   «Купить билет» не должна уезжать вместе с текстом. */
.bk-pavcard {
  background: var(--bk-surface);
  border-top: 4px solid var(--bk-dir, var(--bk-accent));
  padding: var(--bk-s-5);
  display: flex; flex-direction: column; gap: var(--bk-s-5);
}
/* 77px — высота липкой шапки: min-height 76 плюс её нижняя граница. Держим
   числом, а не токеном: токен пришлось бы синхронизировать вручную с .bk-header,
   и он разъехался бы при первой же правке шапки, никого не предупредив. */
@media (min-width: 1024px) { .bk-pavcard { position: sticky; top: calc(77px + var(--bk-s-5)); } }
.bk-pavcard__row { display: flex; flex-direction: column; gap: var(--bk-s-2); }
.bk-pavcard__price {
  font-family: var(--bk-font-mono); font-weight: 500; line-height: 1;
  font-size: clamp(28px, 3vw, 36px); letter-spacing: -.05em; color: var(--bk-accent);
  white-space: nowrap;
}

/* --- Страница экскурсии: кадр слева, текст справа --- */

/* Пропорция 4/5, а не 3/2: колонка узкая, и горизонтальный кадр в ней
   становится полоской в 250 точек высотой рядом с текстом на полтора экрана.
   Но и не 5/7: вся присланная съёмка горизонтальная, а object-fit: cover
   режет симметрично от центра — чем вертикальнее рамка, тем больше сюжета
   уезжает за края. 4/5 держит вес левой половины и оставляет от кадра
   примерно половину ширины.

   position: sticky — кадр остаётся на экране, пока читают описание. У самых
   длинных программ («От прялки до микроскопа» — 1575 знаков) текст уезжает
   на полтора экрана, и без залипания вторая половина страницы остаётся
   с пустой левой колонкой. */
.bk-excursion {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
  column-gap: var(--bk-gutter-fluid, 24px);
  row-gap: var(--bk-s-5);
  align-items: start;
  margin-top: var(--bk-s-6);
}

.bk-excursion__media {
  position: sticky;
  top: var(--bk-s-6);
  aspect-ratio: 4 / 5;
  background: var(--bk-bg-alt);
  overflow: hidden;
}
.bk-excursion__media img { width: 100%; height: 100%; object-fit: cover; }

/* Мера строки задаётся один раз и на колонку, а не на каждый блок внутри.
   Раньше max-width: 62ch стоял отдельно на лиде, списке фактов и описании —
   три одинаковых числа в трёх местах. Без неё правая колонка на 1440 даёт
   строку в 110 знаков: столько глаз не держит, взгляд теряет начало
   следующей строки [ДС §8.5]. */
.bk-excursion__text { max-width: 62ch; }

/* На планшете и уже кадр встаёт над текстом и становится горизонтальным:
   вертикальный на всю ширину съедает первый экран целиком, и заголовок
   программы уходит за сгиб. Залипание там же выключается — липкий блок
   в одноколоночной раскладке просто закрывает собой текст. */
@media (max-width: 1023px) {
  .bk-excursion { grid-template-columns: minmax(0, 1fr); }
  .bk-excursion__media { position: static; aspect-ratio: 3 / 2; }
}

/* --- Галерея: крупный кадр и лента превью --- */
.bk-gallery { display: flex; flex-direction: column; gap: var(--bk-s-4); }
.bk-gallery__stage { position: relative; aspect-ratio: 3 / 2; background: var(--bk-bg-alt); overflow: hidden; }
.bk-gallery__stage img { width: 100%; height: 100%; object-fit: cover; }

.bk-gallery__bar { display: flex; align-items: center; gap: var(--bk-s-3); min-width: 0; }

/* Лента прокручивается пальцем и колесом, стрелки листают крупный кадр.
   scrollbar прячем: полоса под миниатюрами выглядит как часть композиции
   и на 320 px съедает высоту ряда. */
.bk-gallery__strip {
  display: flex; gap: var(--bk-s-2);
  overflow-x: auto; scroll-behavior: smooth;
  scrollbar-width: none; min-width: 0; flex: 1;
}
.bk-gallery__strip::-webkit-scrollbar { display: none; }

.bk-gallery__thumb {
  appearance: none; padding: 0; cursor: pointer;
  flex: 0 0 clamp(88px, 12vw, 132px);
  aspect-ratio: 3 / 2; overflow: hidden;
  background: var(--bk-bg-alt);
  border: 1px solid transparent;
  opacity: .55;
  transition: opacity var(--bk-dur-fast) var(--bk-ease), border-color var(--bk-dur-fast) var(--bk-ease);
}
.bk-gallery__thumb img { width: 100%; height: 100%; object-fit: cover; }
.bk-gallery__thumb:hover { opacity: .85; }
.bk-gallery__thumb[aria-selected="true"] { opacity: 1; border-color: var(--bk-accent); }

/* --- Виджет Яндекс.Карт --- */
.bk-geo { position: relative; aspect-ratio: 16 / 9; background: var(--bk-bg-alt); overflow: hidden; }
@media (max-width: 599px) { .bk-geo { aspect-ratio: 4 / 3; } }
.bk-geo__frame { width: 100%; height: 100%; border: 0; display: block; }

/* Заглушка до нажатия. Паттерн, а не серый прямоугольник: пустое место
   на месте карты читается как сломанный блок [ДС §9.4].

   Плотность здесь своя, а не карточная. Блок 16:9 во всю ширину контейнера
   раз в десять крупнее карточки, и та же плотность превращает фон в главный
   объект страницы: паттерн начинает спорить с фотографиями павильона,
   которые стоят прямо над ним. Поэтому мельче и вдесятеро бледнее —
   это подложка, а не иллюстрация [ДС §9.4]. */
.bk-geo__cover {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--bk-s-4); padding: var(--bk-s-5); text-align: center;
}
.bk-geo__cover::before {
  content: ""; position: absolute; inset: 0;
  background-image: var(--bk-pattern);
  background-size: 340px;
  background-position: var(--bk-pattern-pos, center);
  opacity: .12;
}
.bk-geo__cover > * { position: relative; }

/* --------------------------------------------------------------------------
   22. Шапка раздела и компактная схема ВДНХ
   -------------------------------------------------------------------------- */

/* Шапка страницы раздела. Без картинки намеренно: главный калейдоскоп занят
   первым экраном главной [ББ с.27], фотография одного павильона на обложке
   раздела о четырёх — враньё, а паттерн во всю ширину спорит с фотографиями
   карточек, которые идут сразу под ним. Работает типографика и воздух. */
.bk-sectionhero { padding-block: clamp(48px, 6vw, 104px) clamp(28px, 3vw, 44px); }
.bk-sectionhero__title { font-size: clamp(34px, 5vw, 68px); margin-top: var(--bk-s-3); }
.bk-sectionhero__lead { max-width: 62ch; margin-top: var(--bk-s-5); }

/* Полоса из акцентов павильонов: четыре темы брендбука одной строкой.
   Это единственный способ показать «миров четыре» до того, как посетитель
   доскроллит до карточек, — и способ законный: акцентные цвета работают
   заливкой, а не текстом [ДС §7.4]. */
.bk-dirbar { display: flex; height: 6px; margin-top: var(--bk-s-6); }
.bk-dirbar > span { flex: 1; background: var(--bk-dir, var(--bk-accent)); }

/* Компактная схема — для страницы раздела, где карточки уже всё рассказали
   и схема отвечает только на вопрос «где это на территории».

   Ширина ровно 860 px, и это не круглое число из головы: столько стоит
   в min-width у холста как предел читаемости подписей ВДНХ. Уже — и кадр
   получает вечную боковую прокрутку на десктопе, а подписи всё равно
   не читаются. Плюс два пикселя на кант рамки: без них кадр на два пикселя
   уже холста, и прокрутка появляется на ровном месте.

   По площади это 43 % прежнего кадра во всю ширину контейнера — то самое
   «в два раза меньше», но не ценой работоспособности схемы. */
.bk-map--compact { max-width: calc(860px + 2px); }

/* Карточка-строка: фотография слева, текст справа.
   Живёт в узкой колонке рядом со схемой, поэтому кадр берёт фиксированную
   долю ширины, а не пропорцию: при 4/3 в колонке 400 px фотография съела бы
   половину карточки и текст остался бы в 200 px. */
.bk-card--row { display: grid; grid-template-columns: clamp(130px, 30%, 260px) minmax(0, 1fr); }
.bk-card--row .bk-card__media { aspect-ratio: auto; height: 100%; }
.bk-card--row .bk-card__body { padding: var(--bk-s-4) var(--bk-s-5); gap: var(--bk-s-2); }
.bk-card--row .bk-h3 { font-size: clamp(18px, 1.4vw, 22px); overflow-wrap: break-word; }

/* Акцент направления у строки идёт вертикальной полосой слева, а не
   горизонтальной сверху: сверху он лёг бы поперёк фотографии и обрезал её. */
.bk-card--row.bk-card--dir::before { inset: 0 auto 0 0; width: 4px; height: auto; }

/* Описание — две строки. Полный абзац в узкой колонке растягивает карточку
   втрое, и четыре карточки перестают помещаться рядом со схемой. */
.bk-card--row .bk-card__excerpt {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* Раскладка страницы раздела: схема слева, колонка карточек справа.

   Колонка схемы задана числом, а не долей контейнера. Доля 8/12 давала бы
   схеме нужные 862 px только начиная с 1440 px ширины окна — на 1280 и 1366
   кадр уходил бы в вечную боковую прокрутку. Фиксированная колонка означает,
   что схема либо показана целиком и читаемой, либо раскладка вообще
   не включается.

   Порог 1360 px — это 862 на схему, гаттер и минимум 340 px на карточку-строку,
   пересчитанные обратно в ширину окна. Ниже порога — одна колонка: карточки,
   под ними схема во всю ширину.

   В разметке карточки идут ПЕРВЫМИ, а схема второй: на телефоне сначала нужны
   миры, а не карта территории. Слева схема оказывается через grid-column,
   не меняя порядок для скринридера и для узкого экрана. */
@media (min-width: 1360px) {
  .bk-worlds { display: grid; grid-template-columns: calc(860px + 2px) minmax(0, 1fr);
               column-gap: var(--bk-gutter-fluid, 24px); align-items: start; }
  .bk-worlds__map   { grid-column: 1; grid-row: 1; position: sticky; top: calc(77px + var(--bk-s-5)); }
  .bk-worlds__cards { grid-column: 2; grid-row: 1; }
}

.bk-worlds__cards { display: flex; flex-direction: column; gap: var(--bk-s-4); }
@media (max-width: 1359px) { .bk-worlds__map { margin-top: var(--bk-s-8); } }

/* Ниже порога карточки идут во всю ширину, и доля кадра из узкой колонки
   делает фотографию марочкой в углу. Здесь кадру можно дать больше. */
@media (min-width: 600px) and (max-width: 1359px) {
  .bk-worlds__cards .bk-card--row { grid-template-columns: clamp(140px, 24%, 300px) minmax(0, 1fr); }
  .bk-worlds__cards .bk-card__excerpt { -webkit-line-clamp: 3; }
}

/* На телефоне строка не собирается вовсе: при ширине карточки 280 px на текст
   остаётся 112 px, и «Лесная промышленность» вылезала за край. Кадр уходит
   наверх, карточка снова становится обычной — заодно фотография видна целиком,
   а описание перестаёт обрезаться на третьем слове. */
@media (max-width: 599px) {
  .bk-card--row { grid-template-columns: minmax(0, 1fr); }
  .bk-card--row .bk-card__media { aspect-ratio: 4 / 3; height: auto; }
  .bk-card--row .bk-card__body { padding: var(--bk-s-5); gap: var(--bk-s-3); }
  .bk-card--row.bk-card--dir::before { inset: 0 0 auto 0; width: auto; height: 4px; }
  .bk-card--row .bk-card__excerpt { -webkit-line-clamp: initial; overflow: visible; }
}
