/* Оформление приложения панели.
 *
 * ── Из чего считались размеры ───────────────────────────────────────────────
 *
 * Целевое устройство по ТЗ: сенсорная панель 3840×2160, горизонтальная
 * ориентация. При диагонали 65 дюймов это полотно 1440×810 мм, то есть
 * 2,67 пикселя на миллиметр.
 *
 * 1. Расстояние взаимодействия. Посетитель не рассматривает панель издалека —
 *    он её касается, а значит стоит на расстоянии вытянутой руки, 45–70 см.
 *    Верстать «чтобы читалось с двух метров» здесь неправильно: текст
 *    раздувается, на экран перестаёт помещаться содержимое, и интерфейс
 *    выглядит как презентация, а не как справочник.
 *    Базовый кегль: 17 px на макете 1920 и 26 px на панели 3840 — при 2,67 px/мм
 *    это около 10 мм высоты строки, комфортно для чтения с полуметра.
 *
 * 2. Размер сенсорной цели. ISO 9241-400 и практика публичных киосков:
 *    не меньше 9–10 мм, для терминалов общего доступа — от 15 мм.
 *    15 мм × 2,67 = 40 px на панели. Отсюда --цель: 2.4rem, что при кегле 26 px
 *    даёт 62 px (23 мм) — с запасом, включая пользователей в перчатках зимой.
 *
 * 3. Зона досягаемости. Панель такого размера ставят так, что её верхняя
 *    кромка оказывается примерно на 180 см от пола. Дотянуться туда, не задирая
 *    руку, нельзя, а для человека в коляске недосягаема и верхняя половина
 *    (ГОСТ Р 51671: органы управления до 120 см). Поэтому вся навигация
 *    вынесена в нижнюю панель — «пульт», а верх экрана только показывает.
 *
 * 4. Контраст. WCAG 2.1 AA (ГОСТ Р 52872-2019): не ниже 4.5:1 для основного
 *    текста. Фирменная палитра портала это выдерживает: --текст на --фон
 *    даёт 16:1, --текст-2 на --фон — 4,9:1, белый на фирменном красном — 5:1.
 */

/* ── Шрифт ────────────────────────────────────────────────────────────────────
 *
 * Golos Text, лицензия SIL Open Font License 1.1 (файл шрифты/OFL.txt),
 * авторы Александра Королькова и Виталий Кузьмин. Гарнитура сделана
 * для интерфейсов и имеет родную кириллицу.
 *
 * Раньше здесь стоял Segoe UI, то есть шрифт операционной системы. Это плохо
 * по трём причинам сразу. Он проприетарный, лицензия Microsoft разрешает его
 * только внутри Windows — передать заказчику дизайн, построенный на нём,
 * нельзя. На панели под Android его нет вовсе, и та же самая вёрстка выглядит
 * там иначе: другая ширина букв, другие переносы, поехавшие подписи на плитках.
 * И, наконец, техническое задание требует, чтобы концептуальный дизайн задавал,
 * «какие шрифты, цвета и графические решения следует использовать», — шрифт,
 * который выбирает за нас устройство, такому требованию не отвечает.
 *
 * Файлы лежат рядом, а не тянутся с внешнего сервера: панель обязана работать
 * без интернета, и подгружаемый шрифт при пропаже сети подменился бы системным
 * посреди работы. Наборы разделены по unicode-range — при русском тексте
 * латинский файл не загружается вовсе.
 */
@font-face {
  font-family: 'Голос'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('/шрифты/golos-400-cyr.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Голос'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('/шрифты/golos-400-lat.woff2') format('woff2');
}
@font-face {
  font-family: 'Голос'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('/шрифты/golos-500-cyr.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Голос'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('/шрифты/golos-500-lat.woff2') format('woff2');
}
@font-face {
  font-family: 'Голос'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('/шрифты/golos-600-cyr.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Голос'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('/шрифты/golos-600-lat.woff2') format('woff2');
}
@font-face {
  font-family: 'Голос'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('/шрифты/golos-700-cyr.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Голос'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('/шрифты/golos-700-lat.woff2') format('woff2');
}

/* ── Цвета ────────────────────────────────────────────────────────────────────
 *
 * Зелёный — цвет логотипа и карты на туристическом портале республики
 * и один из трёх цветов флага Башкортостана; золотой штрих — цвет цветка курая
 * на том же флаге. Основной цвет один: он и фон шапки, и цвет кнопок, поэтому
 * весь интерфейс читается как одно целое, а не как набор акцентов.
 *
 * Светлая тема выбрана для зала: днём в помещении со стеклянными витринами
 * тёмный экран работает зеркалом. Белый текст на основном зелёном держит
 * контраст 5,3 : 1 (норма для крупного и обычного текста — не ниже 4,5 : 1).
 */
:root {
  --фон: #f4f5f7;          /* полотно под карточками */
  --фон-2: #ffffff;        /* шапка, пульт, карточки */
  --карточка: #ffffff;
  --акцент: #0a7f5a;       /* основной зелёный */
  --акцент-2: #07553c;     /* он же в нажатом состоянии */
  --акцент-светлый: #d6efe4;
  --золото: #f2b705;       /* цветок курая: тонкая полоска под шапкой */
  --текст: #131313;
  --текст-2: #727272;
  --граница: #e2e5e9;
  --радиус: .8rem;
  /* Радиус кнопок держим отдельной величиной и заметно меньше карточного.
     Прежде он считался как половина высоты, то есть кнопка была полной
     таблеткой — той же формы, что счётчик «24 из 262» в шапке, метки и
     чипы, которые не нажимаются. Одинаковая форма у кнопки и у подписи
     стирает границу между «нажми» и «прочти». Прямоугольник с малым
     скруглением эту границу возвращает и заодно совпадает с тем, как
     сегодня рисуют кнопки в интерфейсах. */
  --радиус-кнопки: .6rem;

  /* Минимальная сторона сенсорной цели — см. пункт 2 выше */
  --цель: 2.4rem;
  --поле: 1.6rem;          /* поля экрана */
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* Атрибут hidden прячет элемент через display:none из стилей браузера,
   а любое наше правило с display перебивает его по специфичности.
   Восстанавливаем приоритет явно. */
[hidden] { display: none !important; }

html {
  /* 17 px при ширине 1920, 26 px при 3840 — линейно между ними */
  font-size: clamp(15px, 0.47vw + 8px, 26px);
}

body {
  /* Запасные — только на случай, если файл шрифта не отдался: панель должна
     показать текст в любом случае, пусть и не той гарнитурой. */
  font-family: 'Голос', 'Segoe UI', Roboto, sans-serif;
  background: var(--фон);
  color: var(--текст);
  height: 100vh;
  overflow: hidden;
  /* Панель — не сайт: выделять текст и вызывать меню посетитель не должен */
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* ── Каркас экрана ────────────────────────────────────────────────────────── */

.экран {
  display: none;
  position: fixed; inset: 0;
  grid-template-rows: auto 1fr auto;   /* шапка · полотно · пульт */
  animation: появление .18s ease;
}
.экран.активен { display: grid; }

@keyframes появление {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.полотно { overflow-y: auto; overscroll-behavior: contain; }

/* ── Заставка ─────────────────────────────────────────────────────────────── */

/* Единственный экран, который смотрят издалека: он должен позвать человека
   через зал. Здесь крупный кегль оправдан. */
.заставка { align-items: center; justify-content: center; text-align: center; cursor: pointer; }
.заставка.активен { display: flex; }

.заставка-фон {
  position: absolute; inset: 0;
  background: linear-gradient(160deg, #06402e 0%, var(--акцент) 55%, #0c6b4c 100%);
  background-size: cover; background-position: center;
}
.заставка-фон::after {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(ellipse at center, transparent 30%, rgba(4,28,20,.72) 100%);
  z-index: 1;                       /* затемнение поверх кадров, но под текстом */
}

/* Материалы загрузочного экрана: кадры слайд-шоу и видеоряд. */
.заставка-фон-медиа { background: #06150f; }

/* Поверх снимков надписям нужно затемнение: у заказчика много светлых
   кадров (снег, белые соборы, небо), и белая подсказка на них теряется.
   Притенение трёх слоёв: лёгкое по всему кадру, широкое мягкое к центру,
   где стоят надписи, и прежняя виньетка по краям. Пятно, привязанное
   к самому тексту, пробовали — на белом соборе оно читалось как грязный
   овал с краем. Размеры заданы долями экрана: шрифт заставки растёт
   вместе с шириной экрана, поэтому надписи всегда внутри тёмной части. */
.заставка-фон-медиа::after {
  /* Первая редакция (.5 в центре) на проде читалась плохо — владелец
     10.10 попросил темнее именно под буквами, с расхождением от них. */
  background:
    radial-gradient(ellipse 34% 22% at 50% 49%,
      rgba(4,20,14,.78), rgba(4,20,14,.62) 45%, rgba(4,20,14,0)),
    radial-gradient(ellipse 70% 55% at 50% 49%,
      rgba(4,20,14,.35), rgba(4,20,14,0)),
    radial-gradient(ellipse at center, transparent 45%, rgba(4,22,16,.5) 100%);
  background-color: rgba(4,22,16,.12);
}
.заставка-фон img, .заставка-фон video {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}
/* Кадры сменяются мягко: резкая подмена на большом экране бьёт по глазам. */
.кадр-заставки { opacity: 0; transition: opacity 1.2s ease; }
.кадр-заставки.виден { opacity: 1; }

.заставка-текст { position: relative; z-index: 1; padding: 2rem; }
.заставка-текст { color: #fff; }
.заставка-текст h1 {
  font-size: 4rem; font-weight: 700; letter-spacing: -0.02em;
  margin-bottom: 1rem; text-shadow: 0 2px 20px rgba(0,0,0,.4);
}
.заставка-текст p { font-size: 1.7rem; color: rgba(255,255,255,.9); margin-bottom: 2.5rem; }

.заставка-фон-медиа ~ .заставка-текст p {
  color: #fff; font-weight: 600;
  text-shadow: 0 2px 4px rgba(0,0,0,.7), 0 0 24px rgba(0,0,0,.6);
}

.кнопка-старт {
  font: inherit; font-size: 1.8rem; font-weight: 600;
  padding: 1.2rem 4rem; min-height: calc(var(--цель) * 1.6);
  color: #fff; background: var(--акцент);
  /* Кнопка заставки крупнее прочих, поэтому радиус ей нужен больше: при
     одинаковом скруглении мелкая кнопка кажется круглее большой. */
  border: none; border-radius: 1rem; cursor: pointer;
  box-shadow: 0 8px 30px rgba(10,127,90,.35);
  animation: пульс 2.4s ease-in-out infinite;
}
@keyframes пульс {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.04); }
}

/* ── Шапка: только сведения, ничего нажимаемого ───────────────────────────── */

/* Шапка: зелёное поле, слева знак (цветок курая в кольце из бусин), дальше
   название. Тонкая золотая линия снизу отделяет шапку от содержимого и
   повторяет жёлтый цвет курая на флаге республики. */
.шапка {
  display: flex; align-items: center; gap: 1rem;
  padding: .9rem var(--поле);
  background: var(--акцент);
  border-bottom: .22rem solid var(--золото);
  color: #fff;
}

/* Знак нарисован белым по прозрачному фону — на зелёном поле шапки он и
   задуман. Держим его квадратным: знак круглый, и любое растяжение по одной
   оси сразу заметно. Размер 4.4rem подобран по тонким линиям лепестков: при
   меньшем они сливаются. */
.шапка-знак {
  width: 4.4rem; height: 4.4rem; flex-shrink: 0;
  background-image: url('/знак.svg');
  background-size: contain; background-repeat: no-repeat; background-position: center;
}
.шапка-название { font-size: 1.5rem; font-weight: 600; flex: 1; color: #fff; }
.шапка-погода { font-size: 1rem; color: rgba(255,255,255,.85); }
.шапка-счёт {
  font-size: 1rem; font-weight: 600; color: #fff;
  padding: .3rem .9rem; border-radius: 2rem; background: rgba(255,255,255,.18);
  white-space: nowrap;
}

/* Пояснение о том, что действие сейчас недоступно. Разворачиваем в несколько
   строк: одной строкой такой текст в шапку не помещается. */
.шапка-счёт.предупреждение {
  color: #fff; background: rgba(0,0,0,.28);
  white-space: normal; max-width: 26rem; font-weight: 500; line-height: 1.3;
}

/* ── Пульт: всё управление у нижней кромки, в зоне досягаемости ───────────── */

.пульт {
  display: flex; align-items: center; gap: .8rem;
  padding: .9rem var(--поле);
  background: var(--фон-2);
  border-top: 1px solid var(--граница);
  box-shadow: 0 -2px 12px rgba(0,0,0,.05);
}
.пульт-разрыв { flex: 1; }

.кнопка {
  font: inherit; font-size: 1.05rem; cursor: pointer;
  min-height: var(--цель);
  padding: 0 1.4rem;
  display: inline-flex; align-items: center; gap: .4rem;
  color: var(--текст); background: #eef0f3;
  border: none; border-radius: var(--радиус-кнопки);
  white-space: nowrap;
  transition: transform .1s ease, background .1s ease;
}
.кнопка:active { transform: scale(.97); background: #e2e5e9; }
/* Кнопка действия — как на портале: красная заливка, белая надпись */
.кнопка-основная { background: var(--акцент); color: #fff; font-weight: 600; }
.кнопка-основная:active { background: var(--акцент-2); }
.кнопка-основная:disabled { background: #d7dbe0; color: var(--текст-2); }

/* Кнопка, которой пока нечего делать: выглядит приглушённо, но нажатие
   принимает и объясняет, чего не хватает. Полностью отключённая кнопка
   на киоске молчит в ответ на палец, и человек считает панель сломанной. */
.кнопка-основная.кнопка-ждёт { background: #d7dbe0; color: var(--текст-2); }
.кнопка-фильтр { background: var(--акцент-светлый); color: var(--акцент-2); font-weight: 600; }
.кнопка-сброса {
  background: transparent; color: var(--акцент);
  border: 1px solid var(--акцент);
}

/* ── Плитки главного меню ─────────────────────────────────────────────────── */

/* Разделов тринадцать. На панели они должны помещаться на один экран целиком:
   меню, которое приходится прокручивать, посетитель у киоска просто
   не пролистает — он уйдёт.
 *
 * Раскладка — гибкий ряд, а не грид с автозаполнением. Причина в последнем
 * ряду: тринадцать на пять не делится, и грид прижимал остаток к левому краю,
 * оставляя справа пустое место шириной в две плитки. Ряд с выключкой по центру
 * ставит остаток посередине, и меню выглядит собранным.
 *
 * Плитки все одного размера. Раньше отдельные разделы занимали две клетки —
 * задумка была «выделить главный», а на экране получалась мешанина из широких
 * и узких прямоугольников без всякой системы. */
/* Сетка стоит по центру полотна, а не жмётся кверху: баннер над ней выключен,
   и при верхней выключке весь свободный запас собирался внизу одной пустой
   полосой в треть экрана. */
.плитки {
  /* Промежуток и ширина плитки считаются от одной величины. Пока они жили
     порознь, правка gap на десятую долю rem ломала раскладку: пять плиток
     переставали помещаться в ряд, и последняя уезжала под нижнюю кромку. */
  --промежуток: 1rem;
  display: flex; flex-wrap: wrap; justify-content: center; align-content: center;
  gap: var(--промежуток);
  padding: var(--поле);
  min-height: 100%;
}

/* Знак и подпись стоят одной группой по центру.
 *
 * Прежде знак был прижат к верхнему краю, подпись — к нижнему, а между ними
 * пустовала половина плитки. Глаз читал их как два независимых элемента:
 * плитка выглядела не кнопкой, а карточкой, у которой в углах что-то лежит.
 * Собранная группа возвращает плитке смысл цели: смотришь в одну точку. */
.плитка {
  position: relative;
  /* Пять в ряд: сто процентов ширины минус четыре промежутка между ними */
  flex: 0 0 calc((100% - var(--промежуток) * 4) / 5);
  /* Высота считается от высоты экрана, а не только от кегля.
   *
   * Кегль подобран под физику панели: 26 px при 3840 — это около 10 мм строки,
   * комфортных для чтения с полуметра, и увеличивать его нельзя. Но пока
   * высота плитки задавалась в rem, она была привязана к кеглю: на панели
   * 65 дюймов три ряда занимали половину полотна, а сверху и снизу оставались
   * пустые поля в треть экрана. Доля высоты экрана растёт вместе с ним. */
  min-height: clamp(11rem, 22vh, 26rem);
  padding: 1.2rem;
  background: var(--карточка);
  border-radius: var(--радиус);
  border: 1px solid var(--граница);
  box-shadow: 0 2px 8px rgba(19,19,19,.06);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: .9rem;
  text-align: center;
  cursor: pointer; overflow: hidden;
  transition: transform .1s ease, box-shadow .1s ease;
}

/* На узких экранах пять плиток в ряд превращаются в марки: держим
   их крупными, уменьшая число в ряду. */
@media (max-width: 1400px) {
  .плитка { flex-basis: calc((100% - var(--промежуток) * 3) / 4); }
}
@media (max-width: 1000px) {
  .плитка { flex-basis: calc((100% - var(--промежуток) * 2) / 3); }
}
@media (max-width: 700px) {
  .плитка { flex-basis: calc((100% - var(--промежуток)) / 2); }
}
.плитка:active { transform: scale(.98); box-shadow: 0 1px 4px rgba(19,19,19,.08); }
.плитка-название { font-size: 1.25rem; font-weight: 600; color: var(--текст); }

/* Значок раздела: наш векторный знак, загруженное изображение или символ,
   вписанный в CMS. Крупный — на плитке он опознавательный знак, а не
   украшение. Цвет знака задаётся здесь: файлы нарисованы currentColor,
   поэтому меняются вместе с темой, а не остаются намертво белыми.
 *
 * Знак сидит на своей подложке, и это единственное место, где плитка
 * окрашена. Раньше акцент держала красная планка в 4 пикселя по верхней
 * кромке — приём панелей Bootstrap и первого Material, от которого те же
 * авторы отказались десятью годами позже. Полоса ничего не сообщала, а
 * тринадцать полосок в сетке рябили и спорили с границей карточки.
 * Подложка под знаком делает обратное: собирает взгляд в одну точку,
 * с которой посетитель и опознаёт раздел через зал. */
.плитка-значок {
  font-size: 2.4rem; line-height: 1;
  /* Тёмный оттенок, а не основной красный: на розовой подложке основной
     даёт 3,4:1 — на грани различимости, и с двух метров знак выцветает.
     Тёмный держит 5,6:1 и читается через зал. */
  color: var(--акцент-2);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;                      /* подложка держит размер, а не жмётся под подпись */
  width: 4.6rem; height: 4.6rem;
  border-radius: var(--радиус);
  background: var(--акцент-светлый);
}
.плитка-значок img { width: 2.8rem; height: 2.8rem; object-fit: contain; display: block; }

/* Рисованный знак раздела: без подложки и крупнее схематичного.
 *
 * Размер выбран по читаемости, а не по вкусу: в наборе кружевная штриховка,
 * и на 45 пикселях — там, где стоял векторный знак, — она сминалась в пятно.
 * С 7rem орнамент различим, ради него набор и рисовался. */
.плитка-значок-картинка {
  width: auto; height: auto; background: none; border-radius: 0;
}
/* Знак растёт вместе с плиткой — иначе на панели он превращается в марку
   посреди пустого белого поля. */
.плитка-значок-картинка img {
  width: clamp(5.5rem, 11vh, 13rem);
  height: clamp(5.5rem, 11vh, 13rem);
}
.плитка-значок .знак {
  display: block; width: 2.8rem; height: 2.8rem;
  background: currentColor;
  mask: var(--файл) center / contain no-repeat;
  -webkit-mask: var(--файл) center / contain no-repeat;
}

/* ── Баннер главного экрана ───────────────────────────────────────────────── */

.баннер {
  margin: var(--поле) var(--поле) 0;
  padding: 1.6rem 1.8rem;
  border-radius: var(--радиус);
  background: linear-gradient(120deg, var(--акцент) 0%, #0c6b4c 100%);
  background-size: cover; background-position: center;
  position: relative; overflow: hidden;
}
/* С фоновым снимком текст читается только по затемнению — иначе заголовок
   теряется на светлых участках кадра. */
.баннер-с-фоном::before {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(4,28,20,.85) 0%, rgba(4,28,20,.4) 100%);
}
/* Баннер всегда на плотной подложке — своём красном поле или затемнённом
   снимке, — поэтому текст в нём белый. Наследовать общий тёмный цвет текста
   нельзя: на фирменном красном он читается едва-едва (2,9:1 при норме 4,5). */
.баннер-текст { position: relative; color: #fff; }
.баннер-заголовок { font-size: 1.7rem; font-weight: 700; color: #fff; }
.баннер-подпись {
  font-size: 1.05rem; color: rgba(255,255,255,.92);
  margin-top: .4rem; max-width: 46rem;
}
/* Когда заголовок баннера снят как повтор шапки, подпись остаётся одна:
   прежним кеглем она выглядит подрисовкой к пустому полю. */
.баннер-подпись-одна { font-size: 1.35rem; margin-top: 0; max-width: 68rem; }

/* ── Карточки материалов ──────────────────────────────────────────────────── */

/* Карточки вертикальные — под пропорции снимков портала (см. .карточка-фото).
   Ширина задана так, чтобы на панели 3840 вставало семь столбцов, а на
   ноутбуке заказчика (1920) — шесть: снимок остаётся размером с открытку,
   и на экран помещается больше одного ряда. */
.карточки {
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(15.5rem, 1fr));
  grid-auto-rows: min-content;   /* без этого overflow:hidden схлопывает строки */
  padding: var(--поле);
  align-content: start;
}

/* ── Вкладки внутри раздела ───────────────────────────────────────────────────
   Нужны там, где в одном разделе живут разные сущности: экскурсии, на которые
   записываются, и экскурсоводы, у которых смотрят контакты. Высота выдержана
   по сенсорной цели — на панели в них попадают пальцем, а не курсором. */
.вкладки {
  display: flex; gap: .6rem;
  padding: 0 var(--поле) 1.2rem;
}
.вкладка {
  font: inherit; font-size: 1.05rem;
  min-height: var(--цель); padding: .7rem 1.4rem;
  border: 2px solid var(--граница); border-radius: var(--радиус-кнопки);
  background: var(--фон-2); color: var(--текст-2);
  cursor: pointer;
}
.вкладка.выбрана {
  background: var(--акцент); border-color: var(--акцент); color: #fff;
}

/* Отборы прямо в полотне раздела — в отличие от подбора объектов, который
   выдвигается панелью сбоку. Экскурсоводов сорок пять: без отбора по городу
   и языку список листается впустую, а прятать его в выдвижную панель значит
   спрятать главное. */
.отборы {
  display: flex; flex-wrap: wrap; gap: .6rem;
  padding: 0 var(--поле) 1.2rem;
}

/* Карточка экскурсовода. Фотографии людей портал отдаёт разного кадрирования,
   поэтому квадрат вместо принятого для объектов 4:5 — портретный снимок в нём
   не обрезается по подбородку, а горизонтальный не оставляет пустых полей.
   Точка кадрирования у верхнего края: лицо всегда в верхней части кадра. */
/* Двойной класс — чтобы перебить .карточка-с-описанием .карточка-фото {3/2},
   которое стоит ниже по файлу и иначе зажимало вертикальный снимок в горизонт.
   4/5 — портрет: фото людей у портала вертикальные, точка кадрирования сверху,
   лицо не обрезается. */
.карточка.карточка-гид .карточка-фото { aspect-ratio: 4 / 5; object-position: center top; }
.карточка-гид { cursor: pointer; }
/* Карточки экскурсий: снимки на портале вертикальные, как у объектов, — общий
   формат 3/2 «карточек с описанием» (он нужен роликам, там кадр 16:9) их
   обрезал в горизонт. Экскурсиям — тот же вертикальный 4/5, что и гидам. */
.карточка.карточка-экскурсия .карточка-фото { aspect-ratio: 4 / 5; object-position: center top; }
/* Описание экскурсии лежит в подписи поверх снимка: белым на затемнении,
   две строки — выбор делается по снимку и первым фразам. Затемнение начинается
   выше, чем у объектов: строк в подписи больше. */
.карточка-экскурсия .карточка-подпись { padding-top: 3.4rem; }
.карточка-экскурсия .карточка-подпись .карточка-анонс {
  color: rgba(255, 255, 255, .92); text-shadow: 0 1px 3px rgba(0, 0, 0, .55);
  -webkit-line-clamp: 2; margin-top: .35rem;
}
/* Кнопка записи в детальном виде экскурсии. */
.материал-действие { display: block; margin: 1.6rem auto 0; min-width: 16rem; }
/* Описания у гидов длинные — по три-четыре абзаца. На карточке показываем
   начало, обрывая по строкам: полный текст незачем, выбор делается по лицу,
   городу и первым фразам. */
.карточка-гид .карточка-анонс {
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;
  overflow: hidden;
}
.гид-телефон {
  margin-top: .7rem; font-size: 1.15rem; font-weight: 600;
  color: var(--акцент); letter-spacing: .01em;
}
.гид-телефон:empty { display: none; }

/* Карточка туристической компании — без фотографии: логотипов портал не отдаёт,
   а серый прямоугольник вместо снимка хуже, чем его отсутствие. Поэтому колонки
   шире обычных: текст в узкой колонке без картинки читается плохо. */
.карточки-текстовые { grid-template-columns: repeat(auto-fill, minmax(24rem, 1fr)); }
.карточка-текстовая { cursor: default; }
/* Детальный вид экскурсовода: вертикальный снимок целиком, по центру. */
.фото-гида-крупно {
  display: block; margin: 0 auto 1.4rem;
  width: auto; max-width: min(100%, 24rem); max-height: 62vh;
  object-fit: contain; border-radius: 14px; background: #e8ebee;
}
.гид-телефон-крупно {
  margin-top: 1.2rem; font-size: 1.6rem; font-weight: 700;
  color: var(--акцент); letter-spacing: .01em;
}
.карточка-текстовая .карточка-тело { padding: 1.2rem 1.3rem; }
.карточка-текстовая .карточка-метка { color: var(--текст-2); }
.карточка-текстовая .карточка-анонс {
  display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Экскурсия без расписания: запись ведёт организатор, поэтому поля формы
   и кнопка «Записаться» прячутся — заполнять их некуда, а уведомление
   отправлять некому. Остаётся описание и телефон организатора. */
.форма.без-записи > h3,
.форма.без-записи > .поля,
.форма.без-записи > .подсказка,
.форма.без-записи > .согласие,
.форма.без-записи > .уведомление-пд { display: none; }

/* Пустое состояние обычно выравнивается по центру — но когда в нём лежит
   описание экскурсии в несколько абзацев, читать такой текст неудобно. */
#экран-запись.без-записи #записаться { display: none; }

.пусто-слева { text-align: left; padding: 0 0 1rem; }
.пусто-слева p { margin: 0 0 .9rem; }

.карточка {
  background: var(--фон-2);
  border-radius: var(--радиус);
  overflow: hidden;
  cursor: pointer;
  border: 2px solid transparent;
  transition: transform .1s ease, border-color .1s ease;
}
.карточка:active { transform: scale(.985); }
.карточка.выбрана { border-color: var(--акцент); }
.карточка.недоступна { opacity: .5; cursor: default; }

/* Кадрирование.
 *
 * Замер шестидесяти случайных снимков портала: 87 % из них вертикальные,
 * типовой размер 865×1200. Горизонтальная карточка под такие фотографии
 * не годится — при кадре 3:2 выбрасывалось 46 % снимка, при 4:3 — 41 %.
 * Соотношение 4:5 оставляет за кадром 9 %.
 *
 * Точка кадрирования — у верхнего края. При любом другом значении избыток
 * делится между верхом и низом, и у вертикальных фотографий срезается
 * верхушка: памятники оставались без голов, у церквей пропадали купола.
 * Со значением top верх не обрезается никогда, а низ у таких снимков почти
 * всегда занят газоном, асфальтом или оградой. */
.карточка-фото {
  width: 100%; aspect-ratio: 4 / 5;
  object-fit: cover; object-position: center top;
  display: block; background: #e8ebee;
}
/* Подпись поверх снимка.
 *
 * Затемнение снизу обязательно: белый текст на светлом кадре — это не
 * «немного бледно», а нечитаемо, и на панели 65 дюймов, где смотрят под
 * углом, ещё хуже. Градиент внизу плотный (до 92% непрозрачности), поэтому
 * контраст держится и на снежных, и на небесных снимках.
 *
 * Карточка при этом остаётся ровным прямоугольником: подпись лежит внутри,
 * а не добавляет высоту. */
.карточка { position: relative; }

/* Цвет задаётся здесь, на самом слое с затемнением, а не на заголовке:
   разметка кладёт подпись поверх снимка только в этом блоке, а карточки
   с описанием и разделы используют .карточка-тело на белом фоне. Пока
   цвет стоял на .карточка-заголовок, он наследовал тёмный --текст
   светлой темы и пропадал на градиенте. */
.карточка-подпись {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 2.5rem .9rem .8rem;
  color: #fff;
  background: linear-gradient(to top,
    rgba(9, 17, 28, .92) 0%,
    rgba(9, 17, 28, .78) 40%,
    rgba(9, 17, 28, .35) 72%,
    rgba(9, 17, 28, 0) 100%);
  pointer-events: none;                 /* нажатие принимает сама карточка */
}

.карточка-заголовок {
  font-size: 1.05rem; font-weight: 600; line-height: 1.3;
  /* Длинные названия обрезаем двумя строками: третья строка съедает снимок,
     ради которого карточка и существует. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .55);
}
.карточка-метка {
  /* Фирменный красный держится только на белом; на снимке он тонет
     в затемнении, поэтому здесь метка светлая, а на белых подписях
     ниже возвращается акцентной. */
  font-size: .85rem; color: rgba(255, 255, 255, .85); margin-top: .2rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .55);
}

/* Карточки экскурсий и роликов: подпись под снимком, с описанием. Они ведут
   не к странице объекта, а сразу к записи или плееру — прочитать, о чём речь,
   больше будет негде. */
.карточка-с-описанием .карточка-фото { aspect-ratio: 3 / 2; }
.карточка-тело { padding: .8rem .9rem 1rem; }
.карточка-с-описанием .карточка-заголовок { text-shadow: none; -webkit-line-clamp: 3; }
.карточка-с-описанием .карточка-метка { text-shadow: none; color: var(--акцент); }
.карточка-анонс {
  font-size: .9rem; color: var(--текст-2); margin-top: .4rem; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}

/* ── Подбор: выдвижная панель снизу ───────────────────────────────────────── */

/* Отборы жили в потоке над карточками и занимали половину экрана: двенадцать
   городов и десяток видов переносились на пять строк, а до самих карточек
   очередь доходила уже за нижней кромкой. Выдвижная панель открывается по
   кнопке, накрывает содержимое и закрывается — на экране остаётся то, за чем
   посетитель пришёл. */
.штора {
  position: fixed; inset: 0; z-index: 40;
  background: rgba(9, 17, 28, .6);
  animation: появление .15s ease;
}

.подбор {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 41;
  max-height: 62vh;
  display: flex; flex-direction: column;
  background: var(--фон-2);
  border-top: 1px solid var(--граница);
  border-radius: 1.2rem 1.2rem 0 0;
  box-shadow: 0 -12px 40px rgba(0,0,0,.45);
  animation: выдвижение .2s ease;
}
@keyframes выдвижение {
  from { transform: translateY(100%); }
  to   { transform: none; }
}

.подбор-шапка {
  display: flex; align-items: center; gap: 1rem;
  padding: 1rem var(--поле);
  border-bottom: 1px solid var(--граница);
}
.подбор-название { font-size: 1.2rem; font-weight: 600; flex: 1; }
.подбор-тело { overflow-y: auto; padding: 1.2rem var(--поле) var(--поле); display: grid; gap: 1.2rem; }

.отбор-группа { display: grid; gap: .6rem; }
.отбор-подпись { font-size: .95rem; color: var(--текст-2); }
.отбор-кнопки { display: flex; flex-wrap: wrap; gap: .6rem; }
.отбор-кнопка {
  font: inherit; font-size: 1rem; cursor: pointer;
  min-height: var(--цель); padding: 0 1.2rem;
  color: var(--текст); background: #eef0f3;
  border: 2px solid transparent; border-radius: var(--радиус-кнопки);
  white-space: nowrap;
}
.отбор-кнопка.выбран { border-color: var(--акцент); color: var(--акцент-2); background: var(--акцент-светлый); }
.отбор-кнопка:active { transform: scale(.97); }

/* ── Карточка объекта ─────────────────────────────────────────────────────── */

/* Колонка стоит по центру экрана и ограничена по ширине.
 *
 * Прежде содержимое прижималось к левому краю, и на панели 65 дюймов две трети
 * ширины пустовали, а строка описания растягивалась знаков на сто сорок. Читать
 * такую строку тяжело: глаз теряет начало следующей. 46rem дают около
 * восьмидесяти знаков — верх нормы для беглого чтения у киоска. */
.материал { padding: var(--поле); max-width: 46rem; margin: 0 auto; }
/* На самой карточке объекта фотографию не обрезаем вовсе: место есть, а объект
   посетитель уже выбрал — он пришёл его рассмотреть. Ограничиваем высоту,
   чтобы снимок не выталкивал описание за пределы экрана, а ширину отдаём
   пропорциям: снимки портала вертикальные, и растянутый на всю колонку
   вертикальный кадр выглядел бы полосой с пустыми полями по бокам. */
.материал > img {
  max-height: 46vh; max-width: 100%; width: auto;
  display: block; margin: 0 auto;       /* вертикальный кадр — по центру колонки */
  border-radius: var(--радиус); background: #fff;
}
.материал h2 { font-size: 1.7rem; margin: 0 0 .6rem; }
.материал h3 { font-size: 1.2rem; margin: 1.4rem 0 .7rem; }
.материал p { font-size: 1.05rem; line-height: 1.6; color: var(--текст-2); margin-bottom: .8rem; }

.материал-шапка { margin: 1.2rem 0 1rem; }
.материал-шапка:empty { margin: 0; }     /* без меток блок не должен давать пустой отступ */

/* Перечисления, вынутые из сплошного текста: способ добраться, длительность,
   цены. Ответ — то, что стоит после двоеточия, — выделен: за ним и тянется
   глаз, всё остальное человек у панели просматривает бегло. */
.разбор-список {
  list-style: none; margin: 0 0 1rem;
  display: grid; gap: .5rem;
}
.разбор-список li {
  font-size: 1.05rem; line-height: 1.5; color: var(--текст-2);
  padding-left: 1.3rem; position: relative;
}
.разбор-список li::before {
  content: ''; position: absolute; left: .3rem; top: .62em;
  width: .35rem; height: .35rem; border-radius: 50%; background: var(--акцент);
}
.разбор-список b { color: var(--текст); font-weight: 600; }
.материал-метки { display: flex; flex-wrap: wrap; gap: .5rem; }
.метка {
  font-size: .9rem; padding: .3rem .9rem; border-radius: 2rem;
  background: var(--акцент-светлый); color: var(--акцент-2);
}

.удобства {
  list-style: none; display: grid; gap: .45rem 1.4rem;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
}
.удобства li { font-size: 1rem; color: var(--текст-2); padding-left: 1.4rem; position: relative; }
.удобства li::before { content: '✓'; position: absolute; left: 0; color: var(--акцент); }

.контакты {
  margin-top: 1.4rem; padding: 1.1rem 1.3rem;
  background: var(--фон-2); border-radius: var(--радиус);
  display: grid; gap: .6rem;
}
.контакт { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; }
/* Кнопка «Открыть на телефоне» стоит в строке контакта — ниже нормы касания
   она быть не может, поэтому высоту держим прежней, уменьшая только поля. */
.кнопка-мелкая-действие { font-size: .95rem; padding: 0 1rem; min-height: var(--цель); }

/* Ссылки на сторонние ресурсы из текста: группа ВКонтакте, сайт фестиваля.
   Кнопки в ряд с переносом — их бывает и одна, и пять. */
.ссылки { display: flex; flex-wrap: wrap; gap: .7rem; }
.кнопка-ссылка { font-size: 1rem; padding: 0 1.2rem; }
.контакт-подпись { font-size: .9rem; color: var(--текст-2); min-width: 6rem; flex-shrink: 0; }
.контакт-значение { font-size: 1.05rem; }

.галерея {
  display: grid; gap: .7rem;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
}
.галерея img {
  width: 100%; aspect-ratio: 4 / 5; object-fit: cover; object-position: center top;
  border-radius: .6rem; background: #eef0f3;
}

/* ── Экран с QR-кодом ─────────────────────────────────────────────────────── */

.qr-обёртка {
  min-height: 100%; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 1.2rem; padding: var(--поле);
}
.qr-подпись { font-size: 1.15rem; color: var(--текст-2); }
#qr {
  background: #fff; padding: 1rem; border-radius: var(--радиус);
  display: flex; align-items: center; justify-content: center;
}
/* Код рисуется по одному пикселю на модуль и растягивается до нужного размера.
   Сглаживание при растяжении размывает границы модулей — для камеры это шум,
   поэтому оно отключено. Размер задан с запасом: у маршрута из десяти точек
   сетка кода мельче, чем у короткой ссылки, а читаться он обязан одинаково. */
#qr img, #qr canvas {
  display: block; width: 18rem; height: 18rem;
  image-rendering: pixelated;
}
/* Ссылку показываем и текстом: если камера не срабатывает, короткий адрес
   можно набрать руками — ради этого он и короткий. */
.qr-ссылка { font-size: 1.2rem; font-weight: 600; letter-spacing: .04em; color: var(--акцент-2); }
.qr-точки { font-size: .95rem; color: var(--текст-2); text-align: center; }

/* Порядок обхода под кодом. Читают его стоя, поэтому список набран крупнее
   обычной подписи, а номера вынесены в кружки — так видно, что это
   последовательность, а не просто перечисление выбранного. */
.порядок-заголовок {
  font-size: 1.05rem; font-weight: 600; color: var(--акцент-2);
  margin-bottom: .6rem;
}
.порядок {
  list-style: none; counter-reset: шаг;
  display: flex; flex-direction: column; gap: .45rem;
  max-width: 34rem; margin: 0 auto; padding: 0; text-align: left;
}
.порядок li {
  counter-increment: шаг;
  display: flex; align-items: baseline; gap: .7rem;
  font-size: 1.05rem; color: var(--текст);
}
.порядок li::before {
  content: counter(шаг);
  flex: 0 0 1.7rem; height: 1.7rem; line-height: 1.7rem;
  border-radius: 50%; text-align: center;
  background: var(--акцент-светлый); color: var(--акцент-2);
  font-size: .9rem; font-weight: 600;
}

/* ── Просмотр стороннего сайта ────────────────────────────────────────────── */

/* Сайт слева, код для телефона справа: посетитель видит страницу и сразу
   понимает, как забрать её с собой, не отходя от панели. */
.сайт-полоса { display: flex; gap: var(--поле); padding: var(--поле); height: 100%; }
.сайт-рамка {
  /* min-width обязателен: без него на узком экране рамка схлопывается в ноль,
     уступая всю ширину панели с QR-кодом, — и сайт просто не виден.
     На панели 3840 места хватает с избытком, но проверять вёрстку приходится
     и в окне поменьше. */
  flex: 1 1 auto; min-width: 22rem; min-height: 60vh;
  background: #fff; border-radius: var(--радиус); overflow: hidden;
}
.сайт-окно { width: 100%; height: 100%; border: none; display: block; }

.сайт-код {
  width: 20rem; flex-shrink: 0;
  display: flex; flex-direction: column; align-items: center; gap: 1rem;
  padding: 1.4rem; background: var(--фон-2); border-radius: var(--радиус);
  text-align: center;
}
.сайт-код-подпись { font-size: 1rem; color: var(--текст-2); line-height: 1.45; }
#сайт-qr { background: #fff; padding: .8rem; border-radius: var(--радиус); }
#сайт-qr canvas { display: block; width: 14rem; height: 14rem; image-rendering: pixelated; }
.сайт-код-адрес { font-size: .9rem; color: var(--акцент-2); word-break: break-all; }

/* Снимок сайта на месте рамки. Показываем его целиком, вписывая по ширине:
   обрезать первую страницу нельзя — именно она и объясняет, что за место. */
.сайт-снимок {
  height: 100%; display: flex; flex-direction: column;
  background: #fff;
}
.сайт-снимок img {
  flex: 1 1 auto; min-height: 0;
  width: 100%; object-fit: contain; object-position: center top;
  display: block;
}
.сайт-снимок-подпись {
  flex: 0 0 auto;
  padding: .8rem 1.2rem;
  font-size: .95rem; line-height: 1.4; color: #4a5c70;
  background: #eef2f6; border-top: 1px solid #d7dee6;
}

/* Сайт запретил показ в рамке, а снимка ещё нет — тогда объяснение. */
.сайт-нельзя {
  height: 100%; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: .8rem;
  padding: 2rem; text-align: center; color: #4a5c70;
}
.сайт-нельзя-заголовок { font-size: 1.3rem; font-weight: 600; color: #22344a; }
.сайт-нельзя-текст { font-size: 1.05rem; max-width: 32rem; line-height: 1.5; }

/* ── Просмотр документа ───────────────────────────────────────────────────── */

/* Просмотрщик занимает всё полотно: документ на панели читают, а не
   разглядывают в углу экрана. */
.документ { height: 100%; padding: var(--поле); }
.документ-просмотр {
  width: 100%; height: 100%; min-height: 60vh;
  border: none; border-radius: var(--радиус); background: #fff;
}
.кнопка-документа { margin-top: 1.4rem; }

/* ── Календарь мероприятий ────────────────────────────────────────────────── */

.календарь { padding: var(--поле); max-width: 62rem; }
.календарь-шапка { display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem; }
.календарь-месяц { font-size: 1.4rem; font-weight: 600; flex: 1; text-align: center; }

.дни-недели, .сетка-дней { display: grid; grid-template-columns: repeat(7, 1fr); gap: .5rem; }
.дни-недели { font-size: .95rem; color: var(--текст-2); text-align: center; margin-bottom: .4rem; }

.день {
  min-height: var(--цель); padding: .5rem;
  background: var(--фон-2); border-radius: .6rem;
  border: 2px solid transparent;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  color: var(--текст-2);
}
.пусто-день { background: transparent; }
/* День с событиями — единственный, по которому есть смысл нажимать,
   поэтому он и выглядит нажимаемым. */
.день.есть-события { color: var(--акцент); cursor: pointer; background: var(--акцент-светлый); font-weight: 600; }
.день.есть-события:active { transform: scale(.96); }
.день.сегодня { border-color: var(--текст-2); }
.день.выбран { border-color: var(--акцент); }
.день-число { font-size: 1.1rem; font-weight: 600; }
.день-счёт { font-size: .8rem; color: var(--акцент); }

.события-дня { margin-top: 1.2rem; color: var(--текст-2); font-size: 1.05rem; }
.события-дня-заголовок { font-size: 1.2rem; font-weight: 600; color: var(--текст); margin-bottom: .8rem; }
.событие-строка {
  padding: .8rem 1rem; margin-bottom: .6rem;
  background: var(--фон-2); border-radius: var(--радиус); cursor: pointer;
  border-left: 3px solid var(--акцент);
}
.событие-строка:active { transform: scale(.99); }
.событие-название { font-size: 1.05rem; color: var(--текст); }
.событие-место { font-size: .9rem; color: var(--текст-2); margin-top: .2rem; }

/* ── Поиск и экранная клавиатура ──────────────────────────────────────────── */

.поиск-строка { padding: var(--поле) var(--поле) 0; }
.поиск-поле {
  min-height: calc(var(--цель) * 1.2);
  padding: .7rem 1.1rem;
  font-size: 1.5rem; letter-spacing: .01em;
  background: var(--фон-2); border: 2px solid var(--акцент);
  border-radius: var(--радиус);
  display: flex; align-items: center;
}
/* Мигающая черта на месте набора: поле не системное, и без неё непонятно,
   куда попадают буквы. */
.поиск-курсор {
  display: inline-block; width: 2px; height: 1.4em;
  background: var(--акцент); animation: мигание 1s step-end infinite;
}
@keyframes мигание { 50% { opacity: 0; } }

.клавиатура {
  flex-shrink: 0; padding: .6rem var(--поле);
  background: var(--фон-2); border-top: 1px solid var(--граница);
  display: grid; gap: .4rem;
}
.клавиатура-ряд { display: flex; gap: .4rem; justify-content: center; }
.клавиша {
  font: inherit; font-size: 1.15rem; cursor: pointer;
  min-width: var(--цель); min-height: var(--цель);
  flex: 1; max-width: 4.5rem;
  color: var(--текст); background: #eef0f3;
  border: none; border-radius: .5rem;
}
.клавиша:active { background: var(--акцент); color: #fff; }
.клавиша-пробел { max-width: 22rem; flex: 4; font-size: 1rem; color: var(--текст-2); }
.клавиша-стереть { max-width: 6rem; flex: 1.5; }

/* Найденный раздел в поиске — карточка без снимка, поэтому подпись у неё
   обычная, под текстом, а не поверх фотографии. */
.карточка-раздел {
  border: 2px solid var(--акцент);
  display: flex; align-items: center; min-height: 7rem;
}
.карточка-раздел .карточка-заголовок { text-shadow: none; }
.карточка-раздел .карточка-метка { text-shadow: none; color: var(--акцент); }

/* ── Формы ────────────────────────────────────────────────────────────────── */

.форма { padding: var(--поле); max-width: 56rem; }
.форма h3 { font-size: 1.2rem; margin: 1.2rem 0 .8rem; }
.форма h3:first-child { margin-top: 0; }

/* Поля в два столбца: на широком экране колонка ввода во всю ширину панели
   выглядит нелепо и заставляет вести взгляд через полтора метра. */
.поля { display: grid; gap: .9rem; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }

.поле { display: block; margin-bottom: .9rem; }
.поле > span { display: block; font-size: .95rem; color: var(--текст-2); margin-bottom: .35rem; }
.поле > span em { color: var(--акцент); font-style: normal; }
.поле input, .поле textarea {
  font: inherit; font-size: 1.05rem; width: 100%;
  min-height: var(--цель); padding: .6rem .9rem;
  color: var(--текст); background: var(--фон-2);
  border: 2px solid var(--граница); border-radius: .6rem;
  resize: none;
}
.поле input:focus, .поле textarea:focus { outline: none; border-color: var(--акцент); }
.поле input::placeholder, .поле textarea::placeholder { color: #5d7086; }

.подсказка { font-size: .95rem; color: var(--текст-2); margin-bottom: 1rem; line-height: 1.45; }

.согласие {
  display: flex; gap: .9rem; align-items: flex-start;
  padding: 1rem 1.2rem; margin-bottom: 1rem;
  background: var(--фон-2); border-radius: var(--радиус);
  font-size: .95rem; line-height: 1.45; color: var(--текст-2);
  cursor: pointer;
}
.согласие input { width: 1.5rem; height: 1.5rem; flex-shrink: 0; accent-color: var(--акцент); }

/* Уведомление об обработке персональных данных. Стоит над согласием и набрано
   мельче основного текста: посетителю оно нужно один раз, перед отправкой,
   и не должно спорить за внимание с полями формы. Абзацы разделены отступом —
   сплошной блок юридического текста на экране не читают вовсе. */
.уведомление-пд {
  padding: 1rem 1.2rem; margin-bottom: .8rem;
  border-left: 3px solid var(--акцент);
  background: var(--фон-2); border-radius: var(--радиус);
  font-size: .85rem; line-height: 1.5; color: var(--текст-2);
}
.уведомление-пд p { margin: 0 0 .6rem; }
.уведомление-пд p:last-child { margin-bottom: 0; }

.сообщение { font-size: 1rem; color: var(--текст-2); min-height: 1.4em; }
.сообщение.успех { color: #7dd08f; }
.сообщение.ошибка { color: #f0a0a0; }

.слоты {
  display: grid; gap: .7rem;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  margin-bottom: 1.2rem;
}
.слот {
  font: inherit; text-align: left; cursor: pointer;
  min-height: var(--цель); padding: .7rem 1rem;
  color: var(--текст); background: var(--фон-2);
  border: 2px solid transparent; border-radius: var(--радиус);
  display: grid; gap: .2rem;
}
.слот.выбран { border-color: var(--акцент); }
.слот:disabled { opacity: .45; cursor: default; }
.слот-время { font-size: 1.05rem; font-weight: 600; }
.слот-детали { font-size: .9rem; color: var(--текст-2); }

/* ── Детский раздел ───────────────────────────────────────────────────────── */

.плеер { position: relative; height: 100%; display: flex; flex-direction: column; padding: var(--поле); gap: 1rem; }

/* Заставка между роликами маршрута. Лежит поверх плеера, а не заменяет его:
   видео под ней уже грузится, и следующий ролик стартует без чёрного провала. */
.переход-маршрута {
  position: absolute; inset: 0; z-index: 3;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1.5rem; background: var(--фон); border-radius: var(--радиус);
}
.переход-подпись { font-size: 2rem; color: var(--текст-2); letter-spacing: .04em; }
.переход-название { font-size: 3.4rem; font-weight: 600; color: var(--акцент); text-align: center; padding: 0 var(--поле); }
.шапка-счётчик { margin-left: auto; padding-left: 1.5rem; font-size: 1.6rem; color: var(--текст-2); white-space: nowrap; }
.плеер video { width: 100%; flex: 1; min-height: 0; background: #000; border-radius: var(--радиус); }
.ролик-описание { font-size: 1.05rem; color: var(--текст-2); }

/* ── Погода ───────────────────────────────────────────────────────────────── */

/* Раздел «Погода».
 *
 * ТЗ требует показывать текущую температуру, краткое описание и время
 * обновления — это необходимый минимум, но не потолок: сторонний сервис отдаёт
 * прогноз тем же запросом. Турист у панели решает не «сколько сейчас градусов»,
 * а «ехать ли сегодня в Кириллов и брать ли зонт», поэтому под текущей погодой
 * идут часы вперёд и неделя. Обязательные по ТЗ поля стоят первыми и крупно. */
.погода-обёртка { min-height: 100%; padding: var(--поле); display: flex; justify-content: center; }
.погода-карточка { width: 100%; max-width: 52rem; }

.погода-сейчас {
  text-align: center; padding: 1.8rem 2rem;
  background: var(--фон-2); border-radius: var(--радиус);
}
.погода-город { font-size: 1.3rem; color: var(--текст-2); }
.погода-градусы { font-size: 4rem; font-weight: 300; line-height: 1.1; margin: .4rem 0; }
.погода-описание { font-size: 1.3rem; }
.погода-детали {
  display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem 1.4rem;
  margin-top: .9rem; font-size: 1rem; color: var(--текст-2);
}

/* Часы: ряд отметок с шагом в три часа. Прокрутка вбок на киоске неудобна,
   поэтому восемь клеток растягиваются по ширине карточки. */
.погода-часы {
  display: grid; grid-template-columns: repeat(8, 1fr); gap: .5rem;
  margin-top: 1rem;
}
.погода-час {
  text-align: center; padding: .8rem .3rem;
  background: var(--фон-2); border-radius: var(--радиус);
}
.погода-час-время { font-size: .95rem; color: var(--текст-2); }
.погода-час-градус { font-size: 1.35rem; font-weight: 600; margin: .25rem 0; }
.погода-час-описание {
  font-size: .8rem; color: var(--текст-2); line-height: 1.2;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* Дни: строкой, чтобы взгляд шёл сверху вниз по датам, а температура
   выстроилась в один столбец и её можно было сравнивать. */
.погода-дни { margin-top: 1rem; display: grid; gap: .4rem; }
.погода-день {
  display: grid; grid-template-columns: 8rem 1fr auto auto; align-items: center; gap: 1rem;
  padding: .8rem 1.2rem; background: var(--фон-2); border-radius: var(--радиус);
}
.погода-день-дата { font-size: 1.05rem; font-weight: 600; }
.погода-день-описание { font-size: 1rem; color: var(--текст-2); }
.погода-день-осадки { font-size: .95rem; color: var(--акцент-2); white-space: nowrap; }
.погода-день-градусы { font-size: 1.1rem; white-space: nowrap; }
.погода-день-градусы b { font-weight: 600; }
.погода-день-градусы span { color: var(--текст-2); }

.погода-обновлено { font-size: .9rem; color: var(--текст-2); margin-top: 1.1rem; text-align: center; }

/* ── Служебное ────────────────────────────────────────────────────────────── */

/* Сообщение о пустом разделе, подсказка поиска, «мультфильмы скоро появятся».
   Такой блок часто оказывается внутри сетки карточек, и как её элемент он
   попадал в одну ячейку первой колонки: на панели 3840 текст вжимался в узкую
   полосу у левого края и читался как сломанная вёрстка. Растягиваем на все
   колонки и центрируем — на макетах 4K это стало видно сразу. */
.пусто {
  grid-column: 1 / -1;
  padding: 4rem var(--поле);
  text-align: center;
  font-size: 1.05rem;
  color: var(--текст-2);
}

/* Область скрытого выхода: невидимый угол, срабатывает на удержание 5 секунд. */
.угол-выхода { position: fixed; top: 0; right: 0; width: 5rem; height: 5rem; z-index: 100; opacity: 0; }

/* Служебный вход в CMS: различим, только если знаешь, где искать. Размер
   меньше сенсорной нормы намеренно — посетитель не должен попадать по нему
   случайно, а сотрудник нажмёт прицельно.
 *
 * Угол выбран левый верхний: там шапка, в которой нет ни одной нажимаемой
 * области. Внизу иконка стояла бы вплотную к кнопке «Назад» на пульте,
 * и промах по ней уводил бы посетителя в панель управления. */
.вход-в-cms {
  position: fixed; left: .25rem; top: .25rem; z-index: 101;
  width: 1.2rem; height: 1.2rem; padding: 0;
  font: inherit; font-size: .75rem; line-height: 1;
  color: var(--текст-2); background: transparent;
  border: none; border-radius: 50%; cursor: pointer;
  opacity: .16;
}
.вход-в-cms:active { opacity: .7; }

/* Признак отсутствия связи */
body.нет-связи .шапка-погода::before { content: '⚠ '; color: var(--акцент); }

::-webkit-scrollbar { width: .5rem; }
::-webkit-scrollbar-thumb { background: #c9ced5; border-radius: 1rem; }

/* ── Экранная клавиатура ──────────────────────────────────────────────────── */

/* Лежит поверх пульта: пока человек печатает, кнопки «Назад» и «Записаться»
   ему не нужны, а вот промах по ним стоил бы набранного текста. */
.клава {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
  display: flex; flex-direction: column; align-items: center; gap: .5rem;
  padding: .8rem 1rem 1.1rem;
  background: var(--фон-2);
  border-top: 1px solid var(--граница);
  box-shadow: 0 -8px 28px rgba(0,0,0,.14);
  animation: клава-въезд .16s ease;
}
@keyframes клава-въезд {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}

.клава-ряд { display: flex; gap: .45rem; width: 100%; max-width: 66rem; justify-content: center; }
/* Цифровой блок телефона узкий: тянуть десять цифр на всю панель незачем,
   номер набирают одной рукой. */
.клава-ряд-цифры { max-width: 26rem; }

/* Клавиши тянутся, но не сверх меры: на панели 65 дюймов ряд во всю ширину
   превращает буквы в мишени по ладони величиной, и попадать по ним
   приходится с размаху. */
.клава-кл {
  font: inherit; font-size: 1.3rem;
  flex: 1 1 3.6rem; max-width: 5.4rem; min-width: 0;
  min-height: 3.5rem;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--текст); background: #fff;
  border: 1px solid var(--граница); border-radius: var(--радиус-кнопки);
  cursor: pointer; user-select: none;
  transition: transform .08s ease, background .08s ease;
}
.клава-кл:active { transform: scale(.94); background: #eef0f3; }
.клава-кл-крупная { font-size: 1.6rem; min-height: 4rem; max-width: 7rem; }
.клава-кл-служебная { background: #eef0f3; font-size: 1.1rem; }
/* Shift: однократный подсвечен, залипший — залит акцентом, иначе после
   двойного нажатия непонятно, почему всё печатается заглавными. */
.клава-кл-нажата { background: var(--акцент-светлый); color: var(--акцент-2); }
.клава-кл-держит { background: var(--акцент); color: #fff; border-color: var(--акцент); }
.клава-пробел { flex: 4 1 12rem; max-width: none; color: var(--текст-2); font-size: 1rem; }
.клава-готово {
  flex: 1 1 8rem; max-width: 11rem;
  background: var(--акцент); color: #fff; font-weight: 600; border-color: var(--акцент);
}
.клава-готово:active { background: var(--акцент-2); }
