/* Правки поверх вёрстки-образца. Раскладку и цвета НЕ трогаем: правило Андрея 18.08 —
   «в дизайне и вёрстке ничего не меняем». Здесь только то, что связано с брендом. */

/* Логотип у образца — svg-шрифтом на всю ширину блока; наш растровый нужно вписать
   в ту же коробку, иначе он растягивается на пол-шапки. */
#logo img,
.trv-header__logo img{max-height:34px;width:auto;object-fit:contain}

/* Логотип-картинка вместо символа образца: вписываем в ту же высоту, что и у него
   (28px, замерено на снимке главной), и держим шапку той же высоты — 66px. Без этого
   после удаления его вкладок и «Входа» шапка стала ниже, и вся страница поехала вверх. */
.trv-logo-img{display:block;height:28px;width:auto;object-fit:contain}
.trv-header__upper{min-height:66px}

/* Флажок страны: у образца это фон-картинка. Когда картинки нет и стоит эмодзи,
   элементу нужен обычный поток — иначе символ не виден в блоке фиксированного размера. */
.TVCountryFlags{display:inline-block;vertical-align:middle}
.TVComplexListItemContent .TVCountryFlags{margin-right:8px;font-size:15px;line-height:1}

/* ── Панели формы ──────────────────────────────────────────────────────────────
   🔴 Лишнее прячем СТИЛЯМИ, а не вырезанием узлов из разметки. Прошлая попытка
   вырезать ряд вкладок регулярками съела закрывающие теги: браузер «починил» разметку
   по-своему, корень панели развалился, и панели перестали открываться вовсе. */

/* Вкладки стран в панели города вылета: оживить нечем — в справочнике у города
   хранится только название, принадлежности к стране нет, и подсвеченная вкладка
   противоречила списку под ней (замечание Андрея 18.08). */
.TVDepartureTableHeader,
.TVDepartureTableNationControl{display:none !important}

/* Ширина панели стран: у снимка она зашита с чужого экрана и режет длинные названия. */
.TVCountrySelectTooltip{width:560px !important;max-width:calc(100vw - 32px)}

/* ══ Не обговорено с клиентом — отключено 19.08 ═══════════════════════════════════
   Витрина собрана на вёрстке копии Турвизора, и вместе с ней в страницу приехали его
   собственные разделы, тексты и кнопки. Показывать их клиенту нельзя: часть ведёт в
   никуда, часть рассказывает про чужой сервис. Гасим стилями, узлы остаются на месте,
   вернуть можно удалением строки. Против каждой группы написано, чем и когда вернётся. */

/* ── Чужая обвязка сайта: возврата не будет ─────────────────────────────────────── */

/* Верхняя строка шапки: вкладки «Туристам / Турагентствам», «Вход», «Помощь»,
   соцсети и переключатель страны. Ни одного нашего раздела, все ссылки чужие.
   Логотип (.trv-header__logo) остаётся, он наш. */
.trv-header__tabs,
.trv-header__add-menu,
.trv-header__socials,
.trv-header__language,
/* Синее меню разделов Турвизора: «Выбрать турагентство», «О нас», «Турстатистика»,
   «Расписание чартеров», «Блог». Таких страниц у нас нет. */
.trv-header__lower,
/* Мобильное меню и бургер, который его открывает: внутри те же чужие разделы плюс
   «Бот для вашего турагентства» и «Интеграция с CRM». */
.trv-mobile-menu,
.trv-header__mobile-burger,
/* Модалка «Вход для турагентств» с регистрацией в их кабинете. */
.trv-login-tour-agents-modal,
/* Подвал: их разделы, Дзен и YouTube, юридические страницы, чужой копирайт. */
.trv-footer,
/* «Сегодня в системе: 120 913 пользователей, 2280 офисов…» — статистика Турвизора. */
.trv-search-module__statistic,
/* Промо-обвязка на странице выдачи (замечание Андрея 19.08): «Поиск туров по всем
   туроператорам», карточки преимуществ и баннер «Приложение всегда под рукой» с
   App Store и RuStore. Приложения не существует, а в макетах внутри баннера чужие
   цены «из Москвы» — Россия, Тиват, Абхазия. */
.trv-search-benefits,
.trv-search-banner-mobile,
.trv-mobile-app-banner,
.trv-mobile-app-banner-modal,
/* FAQ «Как найти подходящий тур»: чужие ответы про онлайн-оплату и бронирование на
   сайте — у клиента подбор идёт звонком менеджера. */
.trv-qa,
/* «Загружаем ещё» — подгрузка следующей страницы ВЫДАЧИ модулем образца; у нас
   показываются лучшие 30, догрузки нет. */
.TVResultListViewMore,
/* Подзаголовок под названием: «Агрегатор туров для туристов и турагентов». Заголовок
   в этом же блоке остаётся, гасим только строку под ним. */
.trv-search-module__desc p,
/* Серая часть главной целиком: «Почему нам доверяют миллионы», баннер мобильного
   приложения, которого нет, и SEO-тексты, где прямым текстом рассказано про Турвизор. */
.trv-grey{display:none !important}

/* ── Выдача: функции, которых у нас нет ────────────────────────────────────────────── */

/* «Раскрыть/скрыть все туры»: раскрытие карточки тянет цены по номерам отдельным
   поиском, до двадцати секунд на отель. Разом по всей выдаче это не запустить. */
.TVResultToolbarShowTours,
/* Список туроператоров в тулбаре: туристу операторов не показываем, условие клиента.
   Менеджеру они видны после входа по коду на /office. */
.TVResultToolbarOperatorsWrapper,
/* Та же причина у колонки операторов в форме: без данных она висела пустой рамкой. */
.TVOperatorListFilter,
/* «Гарантия мест в отеле»: у Турвизора это признак оператора, в нашем доступе к API
   его нет. */
.TVInstantConfirmationFilter,
/* Кнопки на пустой выдаче «Выбрать другие даты» и «Найти больше туров»: сам текст
   «предложений не найдено» остаётся, кнопки не подключены. */
.TVResultHelpFormButtons,
/* Кнопка-тумблер «Комментарий» в мобильной заявке: у копии она раскрывает скрытое
   поле комментария, у нас поле показано сразу, и кнопка читалась вторым «Комментарий»
   под ним. Промокод рядом уже скрыт разметкой. */
.TVUserFormCommentButton{display:none !important}

/* «Найти больше туров» — кнопка подвала списка туров ОДНОГО отеля, клиент просил её
   отдельным пунктом (пункт 5 списка 04.09), и с 07.09 она подключена. ⚠️ Узлов с этим
   классом в разметке восемь: подвал есть у слоя категорий, у плоского списка и у групп
   внутри, плюс сам донор, из которого карточки клонируются. Показываем ровно тот, что
   витрина пометила живым (см. paintToursMore в v2search.js), остальные гасим — иначе
   нажатие на чужой уходит наверх и открывает окно тура. */
.TVResultToursShowMoreButton:not(.v2-live){display:none !important}

/* ── Ждут своей очереди по плану 19.08 ──────────────────────────────────────────── */

/* Избранное включено 19.08: сердце на карточке, счётчик в тулбаре и плашка в углу.
   Плашку и счётчик показывает V2Fav, когда в подборке что-то есть. */



/* ── Сравнение отелей: единственная раскладка, придуманная нами ─────────────────
   У Турвизора сравнения нет, образца не существует. Элементы внутри окна его:
   шапка, звёзды, плашка оценки, цена, плашка в углу. Здесь только сетка колонок и
   положение второй плашки, чтобы она не легла на избранное. */

.TVCompareStickyButton{bottom:96px}

.TVCompareWindow{background-color:#fff;border-radius:5px;box-shadow:0 0 20px rgba(0,0,0,.3);
  font-family:var(--tv-font-theme2);width:min(1100px,94vw)}
.TVCompareWindow .TVToursCartHeader{align-items:center;display:flex;height:50px;padding:0 20px}
.TVCompareWindow .TVCartMenuTitle{font-size:18px;font-weight:700}
.TVCompareWindow .TVCartControl{padding:0 20px 20px}

.TVCompareTable{display:flex;flex-direction:column}
.TVCompareRow{align-items:center;border-top:1px solid #edf2f5;
  display:grid;grid-template-columns:150px repeat(var(--compare-columns,2),1fr);
  gap:15px;padding:12px 0}
.TVCompareRow.TVCompareHead{align-items:start;border-top:none}
.TVCompareRowTitle{color:#5c6672;font-size:13px;font-weight:600}
.TVCompareCell{color:#333;font-size:13px;min-width:0}
.TVComparePhoto{background-position:50%;background-size:cover;border-radius:6px;height:110px;
  margin-bottom:8px;width:100%}
.TVCompareRemove{color:#027ad0;cursor:pointer;font-size:13px;margin-top:6px}
.TVCompareStars{display:flex;gap:2px}
.TVCompareCell .TVHotelInfoRating{position:static;display:inline-block}
.TVCompareCell .TVResultItemPriceValue{font-size:16px;font-weight:700}

@media (max-width: 900px){
  /* На телефоне колонки не помещаются: таблица едет вбок целиком. */
  .TVCompareWindow .TVCartControl{overflow-x:auto}
  .TVCompareTable{min-width:600px}
}

/* Окно «Следить за ценой»: обёртка и шапка его же, ширина под форму из двух полей. */
.TVWatchWindow{background-color:#fff;border-radius:5px;box-shadow:0 0 20px rgba(0,0,0,.3);
  font-family:var(--tv-font-theme2);width:min(560px,94vw)}
.TVWatchWindow .TVToursCartHeader{align-items:center;display:flex;height:50px;padding:0 20px}
.TVWatchWindow .TVCartMenuTitle{font-size:18px;font-weight:700}
.TVWatchWindow .TVCartControl{padding:0 20px 20px}

/* Мобильная выдача переехала под синий блок формы (см. v2search.js): дальше у образца
   идёт светлая часть страницы с воздухом сверху, добавляем такой же. */
#v2-results-mobile{padding-top:20px}

/* Заголовок страницы выдачи. Строка ровно по высоте текста (46px при шрифте 38px), и
   хвосты у «р», «у», «ц» уходили под следующий блок — он непрозрачный, поэтому буквы
   выглядели срезанными (видно и в исходном синем виде). Даём строке воздух снизу;
   размер шрифта и положение не трогаем. */
.trv-search-module__desc h1,
.trv-search-page-module h1,
.trv-search-page-header h1 {
  line-height: 1.3;
  padding-bottom: 10px;
  /* Соседние блоки с фоном ложатся поверх строки и срезают буквы сверху и снизу —
     поднимаем заголовок над ними. */
  position: relative;
  z-index: 2;
}

/* На телефоне заголовок выдачи «Туры в Турцию из Алматы» при 28px не влезает в строку,
   переносится и уходит под переключатель режимов: высота блока у образца рассчитана
   ровно на одну строку и менять её нельзя — форма внутри него позиционируется. Поэтому
   уменьшаем сам заголовок, чтобы он снова помещался в одну строку. */
@media (max-width: 900px) {
  .trv-search-page-header h1 {
    font-size: 20px;
    line-height: 1.25;
    padding-bottom: 4px;
  }
}


/* ── Шторка бюджета на широком экране ──────────────────────────────────────────────
   Ячейка «Бюджет» на выдаче открывает ту же шторку, что и мобильная панель фильтров:
   второй разметки для неё у образца нет. Во всю ширину десктопа она смотрится чужой,
   поэтому здесь только ограничиваем ширину и ставим по центру — содержимое его. */
@media (min-width: 901px) {
  .TVTourBudgetControl.TVTooltipBudget {
    max-width: 520px;
    margin: 0 auto;
    border-radius: 16px 16px 0 0;
  }
}


/* ── Переключатель режимов на телефоне ────────────────────────────────────────────
   Плашка выбранного пункта белая, значит подпись на ней должна быть тёмной. В снимке
   этот цвет стоял инлайном у «Туры», поэтому выбранные «Отели» и «Горящие» читались
   белым по белому. Задаём по состоянию, а не по месту в списке. */
/* Белая плашка-бегунок под выбранным пунктом: у образца её двигал его собственный
   модуль, у нас она оставалась на первом месте — при выборе «Отели» слева висел
   пустой белый прямоугольник, а подпись «Туры» пропадала на нём. Выбранный пункт и
   без неё получает белый фон, поэтому бегунок убираем. */
.TVSearchFormMode .TVToggleSwitchSelection { display: none; }

.TVSearchFormMode .TVToggleSwitchItem { color: #ffffff; }
.TVSearchFormMode .TVToggleSwitchItem.TVActive { color: #027ad0; }


/* ── Двойная прокрутка страницы ────────────────────────────────────────────────────
   У копии `.trv-body` — собственный контейнер прокрутки (`overflow-y:auto`, высота в
   экран), внутри которого лежит вся страница. Получается два скролла: сначала палец
   двигает внутренний контейнер, а запаса у него всего сотня пикселей, и дальше
   страница просто стоит. В Safari на iPhone это читается как «залипла» (замечание
   Андрея 19.08): свайп по форме не прокручивает ничего. Прокрутка должна быть одна —
   у самой страницы. */
.trv-body {
  overflow: visible !important;
  height: auto !important;
  max-height: none !important;
}

/* Тот же случай этажом выше: у копии `body` задан `height:100%`, то есть ровно в
   экран, а содержимое длиннее — прокручивается ещё и он. Высоту отдаём содержимому,
   прокрутка остаётся одна, у страницы.
   ⚠️ overflow тут НЕ трогаем: под открытой панелью его выключает JS инлайном
   (`lockPage`), а правило с !important такую блокировку бы отменило. */
html, body { height: auto !important; }


/* ── Окно отеля на широком экране ──────────────────────────────────────────────────
   Разметка та же, что у мобильного экрана Турвизора (своей десктопной карточки в
   снимках копии нет). На узкой колонке она рассчитана на одну колонку, поэтому здесь
   только раскладка: фото крупнее, номера в две колонки, поля пошире. Раньше клик по
   отелю уводил на старую страницу /hotel — прежний дизайн, который клиенту больше не
   показываем (замечание 21.08). */
/* Высота по содержимому: мобильная разметка тянется на весь экран, и в окне под
   коротким отелем оставалась пустая белая половина. */
.v2-hotel-window,
.v2-hotel-window > * { height: auto !important; min-height: 0 !important; }

.v2-hotel-window .TVPhotoGalleryImage { height: 360px !important; }

/* Контейнер галереи в мобильной разметке ростом ровно под один кадр и с обрезкой,
   поэтому лента превью под фото уходила «под нож». */
/* ⚠️ Галерее — ЖЁСТКАЯ высота ровно под кадр, и принудительно в поток. С height:auto
   контейнеры копии (внутри них кадр выложен абсолютно) схлопывались, фото на 360px
   вываливалось из них и накрывало собой название, звёзды и «На карте» — клиент увидел
   «только картинку, карточки нет» (23.08). Регрессия моя: правило position:static
   ушло вместе с удалённой лентой превью. */
.v2-hotel-window .TVAreaGalleryContainer,
.v2-hotel-window .TVGallContainer {
  position: static !important;
  display: block !important;
  height: 360px !important;
  max-height: none !important;
  overflow: hidden !important;
  transform: none !important;
}

/* ⚠️ Ленту кадров из правила выше ВЫНЕСЛИ. Там ей запрещались флекс и сдвиг, и из-за
   этого листалка в окне отеля не работала: код честно ставил `transform`, а CSS его
   гасил `!important`, кадры лежали стопкой и стрелки ничего не двигали. Обрезка лишних
   кадров осталась на родителе (`overflow: hidden` выше), поэтому за край ничего не
   вылезет, а высота и `position: static` сохранены — именно они чинили регрессию 23.08,
   когда фото накрывало собой название и звёзды. */
.v2-hotel-window .TVGallList {
  position: static !important;
  display: flex !important;
  height: 360px !important;
  max-height: none !important;
}
.v2-hotel-window .TVGallList > .TVPhotoGalleryImage { flex: 0 0 100% !important; }


.v2-hotel-window .TVHotelCardToursBuilder {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

@media (max-width: 900px) {
  .v2-hotel-window .TVHotelCardToursBuilder { grid-template-columns: 1fr; }
}

/* Шапка экрана прилипает: список номеров длинный, а закрыть окно нужно с любого места. */
.v2-hotel-window .TVMobilePanelHeader,
.v2-hotel-window .TVResultPageCaption {
  position: sticky;
  top: 0;
  z-index: 2;
  background: #ffffff;
}


/* ── «Нет оценок» ──────────────────────────────────────────────────────────────────
   У Турвизора оценка есть не у всех отелей: по Турции у 27 из 30, по Кыргызстану у 14
   из 30 (замер 21.08). Пустое место на месте плашки читалось как сбой сайта, поэтому
   ставим серую плашку с прямой надписью. Цвет намеренно нейтральный: это не «плохая
   оценка», а её отсутствие. */
.TVHotelInfoRating.v2-rating-none,
.TVMHotelInfoRating.v2-rating-none {
  background: #eef1f4 !important;
  color: #8a94a0 !important;
  font-size: 12px !important;
  font-weight: 500;
  white-space: nowrap;
  /* Ширина фиксирована: под неё отступ первой строки описания, иначе плашка съедала
     первую букву («…ансионат в живописном месте»). */
  width: 88px !important;
  padding: 0 !important;
  text-align: center;
}


/* ── Вставка на сайт клиента (?embed=1) ───────────────────────────────────────────
   В рамке нужна только форма: остальное на его странице уже есть, а высота рамки
   должна быть минимальной. Прячем всё, кроме блока с формой, и снимаем у героя фон и
   отступы — фон задаёт секция на его сайте. */
.v2-embed .trv-header,
.v2-embed .trv-footer,
.v2-embed .trv-recommendation,
.v2-embed .trv-grey,
.v2-embed .trv-qa,
.v2-embed .trv-search-benefits,
.v2-embed .trv-search-module__desc,
.v2-embed .trv-search-module__statistic { display: none !important; }

.v2-embed .trv-search-module,
.v2-embed .trv-search-module__inner-wrapper {
  padding: 0 !important;
  margin: 0 !important;
  background: transparent !important;
  min-height: 0 !important;
}

.v2-embed .trv-page-content,
.v2-embed .trv-main,
.v2-embed .trv-body { background: transparent !important; }

/* Форма внутри рамки прижата к краям: рамку по ширине растягивает сам сайт. */
.v2-embed .trv-container { max-width: none !important; padding: 0 !important; }


/* Панели внутри рамки не должны выходить за её правый край: рамка шириной с колонку
   сайта, а календарь у образца двухмесячный и широкий. Держим его в пределах окна. */
.v2-embed .TVTooltip,
.v2-embed [class*=Tooltip],
.v2-embed .TVCalendarControl {
  max-width: calc(100vw - 16px) !important;
  box-sizing: border-box;
}


/* Шторка внутри рамки: содержимое календаря выше, чем разумная высота блока на чужой
   странице, поэтому листается внутри шторки, а не растягивает рамку до бесконечности. */
.v2-embed .TVActionSheetBody {
  max-height: 78vh !important;
  overflow-y: auto !important;
}


/* Скидка горящего тура: мелкой строкой над ценой, старая цена зачёркнута. */
.v2-hot-discount {
  font-size: 12px;
  font-weight: 600;
  color: #e02b2b;
  white-space: nowrap;
  text-align: right;
}
.v2-hot-discount::first-line { text-decoration: none; }


/* ── Режим карты ───────────────────────────────────────────────────────────────────
   Переключатель «Списком / На карте» и контейнер под карту у образца в разметке уже
   были, пустые. Заполняем своей картой: отели выдачи метками с ценой. */
.TVResultNavigationMapContent { padding: 0; }

#v2-map {
  width: 100%;
  height: 620px;
  border-radius: 14px;
  overflow: hidden;
  background: #eef1f4;
}

@media (max-width: 900px) {
  #v2-map { height: 70vh; border-radius: 10px; }
}

/* Метка отеля: цена прямо на карте, чтобы не тыкать в каждую. */
.v2-pin {
  background: #ffffff;
  border: 1px solid #dde4ee;
  border-radius: 14px;
  padding: 3px 8px;
  font-size: 13px;
  font-weight: 600;
  color: #1b2733;
  white-space: nowrap;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .18);
}
.v2-pin.v2-pin-active { background: #00a873; color: #ffffff; border-color: #00a873; }

.v2-map-card { font: 14px/1.4 inherit; min-width: 190px; }
.v2-map-card b { display: block; margin-bottom: 2px; }
.v2-map-card .v2-map-price { color: #00a873; font-weight: 700; font-size: 16px; }
.v2-map-card button {
  margin-top: 8px; width: 100%; cursor: pointer;
  background: #fddd02; border: 0; border-radius: 10px; padding: 7px 10px; font-weight: 600;
}


/* Строка навигации образца на телефоне (TVResultMobileNavigationPanel) со своими
   пунктами: карта и календарь. Все её правила — в копии tourvisor.css, здесь только
   выравнивание по левому краю: у образца в строке четыре пункта и они разнесены по
   ширине, у нас их два. */
.v2-mnav { justify-content: flex-start; }


/* Кластер меток: зелёный кружок-плашка с числом отелей и ценой «от». */
.v2-pin.v2-pin-cluster {
  background: #00a873;
  color: #ffffff;
  border-color: #00a873;
}
.v2-pin.v2-pin-cluster span { font-weight: 400; opacity: .9; }


/* Крестик окна номера: у образца зона клика ровно с иконку, промах на пару пикселей
   ничего не закрывал и читался как «не работает». Расширяем зону, иконку не трогаем. */
.TVRoomWindow .TVClosePopUp {
  padding: 14px;
  margin: -14px;
  cursor: pointer;
  z-index: 3;
}

/* Блок перелёта в карточке отеля. Своя разметка, а не классы копии: у образца
   .TVTourFlight* рассчитаны на его собственную структуру с иконками, а одна из
   картинок (baggage.svg) при снятии копии потеряла хост и не грузится. Поэтому
   багаж и ручная кладь подписаны словами, а вид выдержан в том же спокойном стиле,
   что и список номеров рядом. */
.v2-flight {
  margin: 14px 16px 4px;
  padding: 12px 14px;
  border: 1px solid #e6e9ed;
  border-radius: 10px;
  background: #fafbfc;
}
.v2-flight-title { font-size: 15px; font-weight: 600; margin-bottom: 8px; color: #22262b; }
.v2-flight-wait { font-size: 13px; color: #7b848d; }
.v2-flight-group { margin-bottom: 8px; }
.v2-flight-group:last-child { margin-bottom: 0; }
.v2-flight-dir {
  font-size: 11.5px; text-transform: uppercase; letter-spacing: .4px;
  color: #8a939c; margin-bottom: 3px;
}
.v2-flight-row {
  display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline;
  padding: 5px 0; font-size: 13.5px; color: #2b3138;
  border-bottom: 1px dashed #e9edf1;
}
.v2-flight-row:last-child { border-bottom: 0; }
.v2-flight-air { font-weight: 600; }
.v2-flight-num { color: #6b747d; }
.v2-flight-route { font-variant-numeric: tabular-nums; }
.v2-flight-when { color: #4a525a; font-variant-numeric: tabular-nums; }
.v2-flight-extra { color: #7b848d; font-size: 12.5px; }
@media (max-width: 640px) {
  .v2-flight { margin: 12px 10px 4px; padding: 10px 12px; }
  .v2-flight-row { font-size: 13px; }
}

/* Блок «Об отеле»: удобства, расстояния, фотографии и отзывы из отельной базы.
   Стоит рядом с блоком перелёта и выдержан так же: своя разметка, спокойный вид,
   ничего из копии не трогаем. */
.v2-hinfo {
  margin: 12px 16px 4px;
  padding: 12px 14px;
  border: 1px solid #e6e9ed;
  border-radius: 10px;
  background: #fff;
}
.v2-hinfo-wait { font-size: 13px; color: #7b848d; }
.v2-hinfo-title {
  font-size: 15px; font-weight: 600; margin: 10px 0 7px; color: #22262b;
}
.v2-hinfo-title:first-child { margin-top: 0; }
.v2-hinfo-facts { font-size: 13.5px; color: #3b4149; margin-bottom: 6px; }
.v2-hinfo-rate { font-size: 13px; color: #0f766e; margin-bottom: 8px; }
.v2-hinfo-fac { display: flex; gap: 8px; font-size: 13px; padding: 3px 0; }
.v2-hinfo-fac-title { flex: 0 0 34%; color: #7b848d; }
.v2-hinfo-fac-items { flex: 1 1 auto; color: #2b3138; }
.v2-hinfo-shots {
  display: flex; gap: 6px; overflow-x: auto; padding-bottom: 4px; margin-bottom: 6px;
}
.v2-hinfo-shot {
  flex: 0 0 96px; height: 68px; border-radius: 6px; cursor: pointer;
  background-size: cover; background-position: center; background-color: #eef1f4;
}
.v2-review {
  border-top: 1px solid #eef1f4; padding: 8px 0; font-size: 13px; line-height: 1.45;
}
.v2-review-date { color: #8a939c; font-size: 12px; margin-bottom: 3px; }
.v2-review-plus { color: #2b3138; }
.v2-review-plus:before { content: '+ '; color: #16a34a; font-weight: 600; }
.v2-review-minus { color: #2b3138; margin-top: 4px; }
.v2-review-minus:before { content: '− '; color: #dc2626; font-weight: 600; }
@media (max-width: 640px) {
  .v2-hinfo { margin: 10px 10px 4px; padding: 10px 12px; }
  .v2-hinfo-fac { flex-direction: column; gap: 1px; }
  .v2-hinfo-fac-title { flex: none; }
}

/* «Календарь туров»: кнопка в выдаче и окно с диаграммой. Разметка и стили самого
   календаря — образца (их css/calendar.css целиком лежит в нашей копии
   tourvisor.css). Здесь только ширина окна и место кнопки.
   Ширину задаём сами, как и окну «Следить за ценой»: у панели календаря своей
   ширины нет, она рассчитана на узкий контейнер сбоку, а нам нужен месяц целиком —
   31 столбик по 28 px плюс поля. */
.TVCalendarPanel.v2-cal-window { width: min(960px, 94vw); border-radius: 5px;
  box-shadow: 0 0 20px rgba(0, 0, 0, .3); overflow: hidden; }
.v2-cal-wait { font-size: 13px; color: #7b848d; padding: 20px 0; text-align: center; }
.v2-cal-btn { display: inline-flex; }
@media (max-width: 900px) {
  /* На телефоне тулбара выдачи нет, кнопка встаёт над списком карточек рядом со
     счётчиком найденных отелей. */
  .v2-cal-btn { display: flex; padding: 0 14px 8px; }
}

/* Пометка «без перелёта» в строке тура режима «Отели». Без неё цена втрое ниже
   обычной выглядит как ошибка поиска. */
.v2-stay-mark {
  display: inline-block; margin-left: 6px; padding: 1px 6px;
  border-radius: 4px; background: #eef4fb; color: #2563eb;
  font-size: 11.5px; white-space: nowrap;
}

/* Подписи в карточке выдачи: «без перелёта», выгода горящего тура и близкий вылет.
   Все три говорят туристу то, чего не видно по одной цене. */
.v2-badge {
  display: inline-block; margin: 4px 6px 0 0; padding: 1px 7px;
  border-radius: 4px; font-size: 11.5px; white-space: nowrap;
}
.v2-stay-mark { background: #eef4fb; color: #2563eb; }
.v2-hot-mark { background: #eaf7ee; color: #16a34a; font-weight: 600; }
.v2-soon-mark { background: #fdf2e9; color: #c2410c; }

/* Место под кнопки Qui-Quo (галочка и карандаш турагента). Расширение вставляет их
   внутрь элемента само, а до тех пор контейнер стоит пустым.

   ⚠️ Пустой контейнер обязан быть невидимым для вёрстки. Он лежит в блоке цены и в
   строке номера, а там раскладка тесная: лишний блок нулевой высоты всё равно способен
   добавить отступ или перенос. Расширение у клиента ещё не подключено и может быть не
   подключено неделями, поэтому карточки всё это время должны выглядеть ровно так же,
   как до разметки. Как только Qui-Quo положит внутрь свои кнопки, `:empty` перестанет
   совпадать и блок покажется сам. */
.qq-btn-place:empty { display: none; }

/* 04.09: Qui-Quo подключился и пожаловался, что его галочки не в одной линии с
   ценой. Их кнопки — наши гости внутри контейнера, разметку под них мы не пишем, но
   сам контейнер можем поставить строчным флексом по центру — это выравнивает ЛЮБОЕ
   их содержимое по вертикали с соседним текстом, ничего не может сломать при
   расширении, которое ещё не подключено (см. правило :empty выше). Если после этого
   всё ещё не встанет ровно — нужен свежий скриншот их разметки, вслепую точнее не
   подогнать. */
.qq-btn-place:not(:empty) {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  gap: 4px;
  /* Отступ от цены слева, чтобы галочка не липла к сумме. Внутри строки номера
     плашка — флекс, поэтому автоотступ прижимает блок к правому краю. */
  margin-left: 8px;
  flex: 0 0 auto;
}
.TVTourResultByRoomItemContent > .qq-btn-place:not(:empty) { margin-right: 8px; }

/* История поиска: карточки не сжимать.
   Лента у образца — флекс с горизонтальной прокруткой (`TVSliderViewList`,
   overflow: auto hidden), но карточки в ней остались сжимаемыми. Пока запросов мало,
   они помещаются и всё выглядит правильно. Когда история набирается (у Андрея 30.08 их
   было десять), флекс вместо прокрутки давит карточки: ширина падает с 218 до 103 px,
   а строка дат стоит nowrap и уезжает за край — в карточке остаётся «6 сен–16 сен 7-».
   Прокрутка у ленты уже есть, ей просто не давали работать. */
.TVHistorySearchItemControl { flex-shrink: 0; }

/* Цена дня под числом в календаре выбора дат рисуется узлом образца
   (TVCalendarFlyAvailablePrice): цвет, размер и место в ячейке берутся из его же
   правил, своих здесь больше нет. Ровные цифры — единственное, что добавляем. */
.TVCalendarFlyAvailablePrice { font-variant-numeric: tabular-nums; }

/* Пустая подборка «Самые низкие цены»: молчаливая пустота читается как поломка. */
.v2-mp-empty {
  padding: 14px 2px; font-size: 13.5px; line-height: 19px; color: #7b848d;
}

/* Заглушки карточек на время поиска. Показываем ровно там, где появятся отели: пустое
   поле под тулбаром читается как «ничего не нашлось», особенно на горящих, где холодный
   запрос к источнику занимает до двадцати секунд. */
.v2-skeleton {
  display: flex; gap: 14px; align-items: stretch;
  padding: 14px; margin-bottom: 10px;
  border: 1px solid #e9edf1; border-radius: 12px; background: #fff;
}
.v2-skeleton-photo { flex: 0 0 168px; height: 116px; border-radius: 8px; }
.v2-skeleton-lines { flex: 1 1 auto; display: flex; flex-direction: column; gap: 9px; padding-top: 4px; }
.v2-skeleton-line { height: 12px; border-radius: 6px; }
.v2-skeleton-line--title { width: 52%; height: 15px; }
.v2-skeleton-line--sub { width: 34%; }
.v2-skeleton-line--text { width: 76%; }
.v2-skeleton-price { flex: 0 0 108px; height: 34px; border-radius: 8px; align-self: flex-end; }
.v2-skeleton-photo, .v2-skeleton-line, .v2-skeleton-price {
  background: linear-gradient(90deg, #eef1f4 25%, #f6f8fa 37%, #eef1f4 63%);
  background-size: 400% 100%;
  animation: v2-skeleton-shine 1.3s ease-in-out infinite;
}
@keyframes v2-skeleton-shine {
  0% { background-position: 100% 0; }
  100% { background-position: 0 0; }
}
@media (max-width: 640px) {
  .v2-skeleton-photo { flex-basis: 96px; height: 84px; }
  .v2-skeleton-price { flex-basis: 76px; }
}

/* ── Окно тура образца (v2tourcard.html, openTourCard) ────────────────────────────
   Заголовки групп удобств у образца зашиты в CSS по классу (.TVHotelBeach:before
   {content:"Пляж"}). Наши группы приходят с названиями источника; незнакомой группе
   название пишем атрибутом, правило то же — его :before в левой колонке. */
.TVHotelDescriptionControl .v2-desc-group:before { content: attr(data-title); }
/* Слой отзывов: разметки списка в снимке образца нет, строим своей теми же классами,
   что на экране отеля телефона (.v2-review). */
.TVTourCardWindow .v2-reviews-view { padding: 10px 0; }
.TVTourCardWindow .TVMapContainer { border-radius: 6px; overflow: hidden; }
/* Название оператора вместо его логотипа в шапке окна (только менеджеру). */
.TVTourCardWindow .TVTourCardOperatorControlName { font-size: 13px; color: #5c6672; }
