/* Карта — первый экран. Занимает всё, что осталось от чата. */
.map{flex:1 1 auto;position:relative;min-height:0;background:var(--sunk)}
#map{position:absolute;inset:0}
.maplibregl-map{font:inherit}
/* Зум — капсула, а не чужой прямоугольник (05.09.2026).
   Замер до правки, в движке Canvas: группа 48×92 со скруглением 4 px и рамкой
   `rgba(0,0,0,.2)`. Три беды сразу. Радиус 4 — единственная чужая геометрия на
   экране, где всё остальное скруглено на 8, 12 и 999. Рамка — сырой цвет мимо
   токенов, то есть в тёмной теме чёрная полупрозрачная линия на тёмном
   контроле. И главное: в MapLibre та же группа получала от нас радиус 10, а в
   Canvas оставалась на 4 — два движка выглядели по-разному, и расхождение
   видно ровно у той половины аудитории, ради которой второй движок заведён.
   Капсула, а не два круга: зум — ОДНА функция с двумя направлениями, и
   разорванный на две кнопки он читается как два разных действия.
   Кнопки чужие, поэтому правим их снаружи и с `!important`: у Leaflet свои
   правила на `.leaflet-touch` перебивают наши по весу селектора. */
.maplibregl-ctrl-group,.leaflet-touch .leaflet-bar,.leaflet-bar{
  border:1px solid var(--line) !important;
  border-radius:999px !important;
  background:var(--surface) !important;
  box-shadow:var(--shadow) !important;
  overflow:hidden
}
.maplibregl-ctrl-group button,.leaflet-bar a,.leaflet-touch .leaflet-bar a{
  width:44px !important;height:44px !important;line-height:44px !important;
  font-size:19px;font-weight:500;
  background:var(--surface) !important;color:var(--ink) !important;
  border:0 !important;border-radius:0 !important
}
/* Волосяная линия между ступенями — вместо рамки у каждой кнопки: так капсула
   остаётся одним контролом, а не двумя сложенными. */
.maplibregl-ctrl-group button+button,.leaflet-bar a+a{
  border-top:1px solid var(--line) !important
}
/* Наведения мышью в вебвью нет — отклик обязан быть на НАЖАТИЕ. */
.maplibregl-ctrl-group button:active,.leaflet-bar a:active{background:var(--sunk) !important}
.leaflet-bar a.leaflet-disabled{background:var(--surface-2) !important;color:var(--ink-3) !important}
/* Жёлоб у контролов тот же, что у всего экрана: он один на весь интерфейс. */
.maplibregl-ctrl-top-right,.leaflet-top.leaflet-right{top:var(--gut);right:var(--gut)}
.leaflet-top .leaflet-control,.maplibregl-ctrl-top-right .maplibregl-ctrl{margin:0 !important}
/* Атрибуция обязана быть видна (лицензия OSM), но низ карты занят слоями —
   поэтому она уезжает наверх вслед за зумом, а не спорит с ними за место.
   Отступ считается ОТ КАПСУЛЫ: при `top:96px` её верхние 6 px уходили под
   кнопки зума (замер 05.09.2026: зум 10…102, атрибуция 96…113, и обе справа).
   Лицензия, наполовину закрытая контролом, — это не мелочь оформления. */
.maplibregl-ctrl-attrib,.leaflet-control-attribution{font-size:9px}
.maplibregl-ctrl-bottom-right,.leaflet-bottom.leaflet-right{
  bottom:auto;top:calc(var(--gut) + 98px)
}
/* Пин и кластер — кнопки внутри маркера MapLibre: своя рамка не нужна. */
.maplibregl-marker{cursor:pointer}
/* Порядок меток по виду, а не по времени появления (17.09.2026). Пока маркеры
   пересоздавались целиком, порядок давала очередь: номера домов первыми, пины
   поверх. Стабильные метки живут, пока место в кадре, а новые встают в конец
   DOM — и номер дома, въехавший при сдвиге, ложился бы поверх цены. У Leaflet
   порядок и так задаёт он сам, по широте. */
.maplibregl-marker.addr{z-index:0}
.maplibregl-marker.dot{z-index:1}
.maplibregl-marker.pin{z-index:2}
/* Ориентир — выше всех: его подпись не смеет исчезать под пинами. Тот же
   порядок у Leaflet задаёт `markerLayer` (map-layout.js). */
.maplibregl-marker.lm{z-index:4}
/* Выбранная — над всеми, ориентиры в том числе (у Leaflet — `markerLayer`). */
.maplibregl-marker.sel{z-index:5}
/* `.dot{position:relative}` (площадь касания через ::after) подключается позже
   maplibre-gl.css и при равной специфичности перебивал его `position:absolute`:
   в WebGL кнопка-точка сама служит маркером и падала в обычный поток — i-я
   точка уезжала на 14·i px от своей координаты. Абсолютное позиционирование
   тоже задаёт containing block для ::after, так что касание не страдает. */
.maplibregl-marker.dot,.maplibregl-marker.lm{position:absolute}

/* Слои — главный контрол карты, поэтому они внизу, а не вверху: верхние 30 %
   экрана большим пальцем одной рукой не достаются. Над строкой атрибуции. */
/* Полоса слоёв. Прокрутки вбок НЕТ ВОВСЕ (решение владельца 05.09.2026):
   показывается ровно то, что влезло целиком, остальное считает «Ещё».
   Замер, на котором это решение стоит: доступно 366 px при экране 390; чип со
   словом занимает 105–185 px и помещается один-два из шести, чип-значок — 48,
   и помещается пять. Слова не пропали, они в листе за «Ещё», где на них есть
   место. Сколько значков показать, решает не число в настройке, а измеренная
   ширина: на 320 влезает три, на 430 — все шесть. */
.layers{
  position:absolute;left:0;right:0;bottom:20px;z-index:var(--z-map);
  /* Значки у ЛЕВОГО края, «Ещё» — у ПРАВОГО (решение владельца 06.09.2026,
     после короткой примерки полосы целиком справа). Значки держат ту же
     линию, что весь остальной интерфейс — жёлоб `--gut` один на экран;
     «Ещё» уходит в правый угол, самый доступный большому пальцу, и пустота
     между ними работает разделителем: слева состояние карты, справа вход в
     полный список. */
  display:flex;gap:8px;align-items:center;padding:0 var(--gut) 2px
}
/* Чип полосы — ЗНАЧОК со счётчиком, без подписи. Отступы сжаты до 10/8:
   владелец отдельно указал на «большие отступы», и на чипе без текста они
   действительно ничего не держат. */
.chip{
  flex:0 0 auto;display:inline-flex;align-items:center;gap:5px;height:44px;
  padding:0 10px;border-radius:999px;font-size:12px;font-weight:600;
  background:var(--surface);color:var(--ink-3);border:1px solid var(--line);
  box-shadow:var(--shadow);white-space:nowrap
}
.chip[hidden]{display:none}
/* Знак типа — эмодзи из справочника, а не цветная точка: «🍜» понятно без
   легенды, розовая точка — только тому, кто легенду уже выучил. Цвет типа
   никуда не делся, его держит счётчик и пин на карте. Выключенный слой
   обесцвечен: состояние читается формой, а не одной лишь яркостью. */
.chip .ico{
  width:22px;height:22px;border-radius:50%;flex:0 0 auto;
  display:grid;place-items:center;font-size:13px;line-height:1;
  background:var(--c-soft,var(--sunk));border:1px solid var(--c);
  filter:grayscale(1);opacity:.5
}
/* Без подписи состояние держится на ЦВЕТЕ КОЛЬЦА: оно и говорит «включено»,
   и называет, какой это слой. Одна серая обводка на всё различала бы только
   «нажато/нет» и не отличала бы жильё от еды. */
.chip[aria-pressed="true"]{color:var(--ink);border-color:var(--c,var(--line-2))}
.chip[aria-pressed="true"] .ico{filter:none;opacity:1}
.chip .cnt{font-size:11px;color:var(--ink-3);font-variant-numeric:tabular-nums}

/* Диагностика читается редко — ей место в самой недосягаемой зоне. */
/* Сообщение карты. Не подпись, а СОСТОЯНИЕ: пока всё хорошо, его нет вовсе.
   Две постоянные строки (зум и предупреждение разработки) забирали 68 px
   верха карты и не сообщали человеку ничего, что он не видел бы сам. */
.mapnote{
  position:absolute;left:var(--gut);top:var(--gut);z-index:calc(var(--z-map) - 100);
  max-width:62%;
  display:flex;align-items:center;gap:6px;padding:4px 9px;border-radius:999px;
  background:var(--surface);border:1px solid var(--line);box-shadow:var(--shadow);
  font-family:ui-monospace,monospace;font-size:10.5px;line-height:1.25;color:var(--ink-2)
}
/* `display:flex` перебивает браузерное `[hidden]{display:none}` по весу —
   спрятанный элемент остался бы видимой пустой пилюлей. Ровно та ловушка, о
   которой предупреждает frontend.md 7: состояние прячем через `hidden`, но
   тогда и правило под него обязано быть. */
.mapnote[hidden]{display:none}
.mapnote b{color:var(--ink);font-weight:500}
.mapnote.warn{color:var(--danger)}

/* Пины: цена — ДИАПАЗОН по району, не цена этого объявления */
.pin{
  display:flex;align-items:center;gap:5px;padding:3px 7px 3px 4px;border-radius:999px;
  background:var(--surface);border:1px solid var(--line);box-shadow:var(--shadow);
  font-size:11px;font-weight:700;white-space:nowrap;color:var(--ink)
}
/* Кружок остался — он держит цвет типа и отделяет знак от цены, — но внутри
   теперь эмодзи, а не заливка. Обводка цветная, фон светлый: эмодзи на
   насыщенной заливке не читается. */
.pin .ico{
  width:20px;height:20px;border-radius:50%;flex:0 0 auto;
  display:grid;place-items:center;font-size:12px;line-height:1;font-style:normal;
  background:var(--c-soft,var(--surface));border:1.5px solid var(--c)
}
.pin.bare{padding:3px}
/* Номера домов: подпись, а не элемент управления. Не кликаются, не мешают
   попадать по пинам, читаются за счёт ореола, а не подложки. */
.addr{
  background:none;border:0;box-shadow:none;padding:0;pointer-events:none;
  font-size:10px;font-weight:600;color:var(--map-muted);white-space:nowrap;
  text-shadow:0 0 2px var(--map-label-halo), 0 0 2px var(--map-label-halo),
              0 0 3px var(--map-label-halo);
}
/* Дальний зум (выбор владельца 17.09.2026, макет docs/design/map-far-zoom):
   пятно плотности рисует сам движок (слой стиля / холст), маркерами живут
   только ориентиры. Соты и пилюли районов сняты. Геометрия сверена с
   map-layout.js — правишь размеры, правь и там. */

/* Ориентир — капсула метки места (выбор владельца 17.09.2026, макет
   docs/design/map-far-zoom, «эмодзи»): элемент несёт `pin says` и берёт у
   пина всю геометрию — кружок .ico с кольцом цвета слоя слева, название
   ВНУТРИ на --surface (ink/surface, контраст как у цены). Значок — СВОЙ
   (place.landmark_emoji: 🐉 мосту, ✈️ аэропорту), откат на эмодзи типа даёт
   сервер. Не влезла капсула — `lm pin says bare`, один кружок. Размеры
   сверены с map-layout.js — правишь их, правь и там. Своё у ориентира —
   слой выше пинов и касание, дотянутое до 44 px по высоте (frontend.md 10). */
.lm{position:relative;-webkit-tap-highlight-color:transparent}
.lm::after{content:"";position:absolute;inset:-8px 0;border-radius:999px}
.lm.bare::after{inset:-8px}
.lm:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* Карточка занимает ВСЮ область карты и становится главным модулем: её
   пришли смотреть (решение владельца 04.09.2026, разворот прежнего «карта
   обязана оставаться видимой»). Чат под ней никуда не девается, поэтому из
   приложения человек не выпадает, а «Закрыть» возвращает ровно тот же вид
   карты — её никто не двигал. */
.card{
  /* z-index выше всего, что рисует карта. У двух движков он РАЗНЫЙ: у MapLibre
     контролы лежат на 2, у Leaflet — на 1000, а пины на 600. Карточка на 600
     оказывалась поверх кнопок в Chrome и ПОД ними в вебвью без WebGL — то есть
     ровно у той половины аудитории, ради которой второй движок и заведён. */
  position:absolute;inset:0;z-index:var(--z-card);display:flex;flex-direction:column;
  background:var(--surface);border-top:1px solid var(--line)
}
/* Пока карточка открыта, контролы карты не нужны: под непрозрачной карточкой
   карты нет, значит нечего масштабировать и нечего атрибутировать. Это и
   снимает весь класс расхождений между движками, а не только этот случай. */
.map.has-card .maplibregl-control-container,
.map.has-card .leaflet-control-container{display:none}
/* Тот же принцип для клавиатуры: она схлопывает карту в ноль, но слои и бэйдж
   лежат `absolute` и остаются висеть. Замер 04.09.2026 поймал полосу слоёв на
   y = −13 — поверх шапки и наполовину за верхним краем экрана. Карты нет —
   контролов карты нет. */
body.kbd .layers,
body.kbd .mapnote{display:none}

.card-body{flex:1 1 auto;min-height:0;overflow-y:auto;display:flex;flex-direction:column;
  padding:12px var(--gut) 8px;-webkit-overflow-scrolling:touch}
/* «Ниже есть ещё» показываем затуханием у нижнего края — тем же приёмом, что
   у полосы слоёв. Без него обрезанная строка читается как поломка, а не как
   приглашение прокрутить. */
.card.more-below .card-body{
  -webkit-mask-image:linear-gradient(to bottom,#000 0,#000 calc(100% - 28px),transparent 100%);
  mask-image:linear-gradient(to bottom,#000 0,#000 calc(100% - 28px),transparent 100%)
}
/* Действия липнут ко дну: прокручивать карточку до кнопок значит терять их. */
.card-foot{flex:0 0 auto;display:flex;flex-direction:column;gap:8px;
  padding:8px var(--gut) 10px;border-top:1px solid var(--line);background:var(--surface)}
/* safe-area — ТОЛЬКО когда карточка полноэкранная (чат скрыт): тогда действия
   у дна экрана и уходят под home-indicator. В сплит-режиме («Спросить в чате»)
   чат снизу, а карточка сверху — inset здесь добавлял бы пустую полосу между
   кнопками и чатом (потеря высоты). Инсет низа несёт сам чат/композер. */
body.card-solo .card-foot{padding-bottom:calc(10px + env(safe-area-inset-bottom))}
.card-foot .foot-row{display:flex;gap:8px}
/* Дверь в разговор о месте стоит НАД действиями и прибита ко дну вместе с
   ними. В теле карточки она уезжала под сгиб — единственный вход в обсуждение
   видели только те, кто доскроллил. Тон тише главного действия: заливка в
   зоне одна, и она у «Спросить в чате». */
.card-foot .thread{display:flex;align-items:center;gap:8px;width:100%;min-height:44px;
  padding:0 12px;border:1px solid var(--line-2);border-radius:var(--radius-sm);
  background:var(--surface-2);color:var(--ink);font-size:13px;font-weight:600;text-align:left}
/* Знаки по краям несут то, чего не говорит подпись: 💬 слева — что внутри
   разговор, а не описание; ↓ справа — что он ниже, в чате. Стрелка слева
   читалась как «свернуть» — там её место занял знак содержимого. */
.card-foot .thread .ta{flex:0 0 auto;font-size:15px;line-height:1}
.card-foot .thread .tg{flex:0 0 auto;color:var(--accent-ink);font-weight:700;
  margin-left:-2px}
.card-foot .thread .tt{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.card-foot .thread b{flex:0 0 auto;color:var(--ink-3);font-variant-numeric:tabular-nums}
/* Заливка в переходной зоне ровно одна — у главного действия, а оно с
   17.09.2026 «Маршрут» (было «Спросить в чате»). «Спросить» — тоном двери в
   разговор (обе ведут в чат), «Закрыть» — отмена, тише всех.
   Ширина — замер canvas 17.09.2026 (Noto Sans, 600 13.5px, 🧭 17 px, поля
   10, зазоры 8): три кнопки со словами на 390 занимают 288–330 из 350, на
   320 — те же 288–330 из 280, не влезают ни на одном языке. Поэтому на узком
   экране «Закрыть» — значок ✕ (44 px) и поля 6: ru 273, en 261 — в строку,
   vi 303 — «Hỏi trong trò chuyện» переносится в две строки (~39 px) внутри
   тех же 44 px, а не вылезает за край. */
.card-foot .foot-row>*{flex:1 1 auto;min-width:0;min-height:44px;padding:4px 10px;
  display:flex;align-items:center;justify-content:center;gap:6px;text-align:center;
  line-height:1.15;border-radius:var(--radius-sm);font-size:13.5px;font-weight:600;
  text-decoration:none;-webkit-tap-highlight-color:transparent}
.card-foot .foot-row .route{flex:0 0 auto;white-space:nowrap;
  background:var(--accent);color:var(--on-accent)}
.card-foot .foot-row .route:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.card-foot .foot-row .quiet{border:1px solid var(--line-2);background:var(--surface-2);color:var(--ink)}
.card-foot .foot-row .ghost{flex:0 1 auto;background:none;color:var(--ink-2);font-weight:500}
.card-foot .foot-row .cl-i{display:none;font-size:17px;line-height:1}
@media (max-width:359px){
  .card-foot .foot-row>*{padding:4px 6px}
  .card-foot .foot-row .ghost{flex:0 0 44px;padding:0}
  .card-foot .foot-row .cl-t{display:none}
  .card-foot .foot-row .cl-i{display:inline}
}

/* Голова: тип — строчными и с точкой цвета слоя, а не капсовой плашкой над
   заголовком. Капсовый эйбрау над каждым блоком — вернейший признак вёрстки
   «по шаблону», и он ничего не сообщает сверх самого слова. */
.card .head{display:block}
/* Крестик ушёл из шапки наверх карточки: цена теперь стоит перед названием, и
   в шапке ему больше не место. Поверх снимка — с подложкой: фотография бывает
   любой, и тонкий значок на светлом кадре исчезает. */
.card .close{position:absolute;top:8px;right:8px;z-index:5}
.card.has-photo .close{background:rgba(18,33,31,.6);border-radius:50%;color:#fff}
/* Бейдж типа лежит НА снимке и не тратит строку в теле. Подложка тёмная и
   непрозрачная: фотография бывает любой, и белый текст на светлом кадре
   исчезает — проверять придётся на живых снимках, а не на этих заглушках. */
.card .gkind{position:absolute;left:8px;bottom:8px;z-index:3;pointer-events:none;
  display:flex;align-items:center;gap:5px;padding:3px 9px;border-radius:999px;
  background:rgba(18,33,31,.66);color:#fff;font-size:11.5px;font-weight:600}
/* Знак типа в строке названия — тот же, что на пине. Он в разметке всегда, а
   прячется ровно там, где виден бейдж на снимке: карточка со снимком в полный
   рост. В сжатой форме галереи нет, и знак возвращается сам — иначе тип
   пропадал бы совсем именно тогда, когда от карточки осталась одна шапка. */
.card .hsign{font-size:15px;font-style:normal}
.card.has-photo:not(.compact) .hsign{display:none}
.card h3{margin:8px 0 0;font-size:18px;line-height:1.2;letter-spacing:-.01em;
  padding-right:36px}
.card .close{width:44px;height:44px;display:grid;place-items:center;
  color:var(--ink-3);font-size:17px}

/* Единственное громкое место карточки — цена: она и есть ответ на вопрос,
   с которым сюда приходят. Всё остальное держится тише. */
.card .price{margin:10px 0 0}
.card .pv{font-family:ui-monospace,SFMono-Regular,monospace;font-size:22px;line-height:1.1;
  font-variant-numeric:tabular-nums;letter-spacing:-.02em;color:var(--ink)}
.card .pn{margin-top:3px;font-size:11px;line-height:1.3;color:var(--ink-3);max-width:44ch}

.card .about{margin:11px 0 0;font-size:13px;line-height:1.45;color:var(--ink-2);max-width:46ch}

/* Галерея. Фото — первое, что видит человек: у Airbnb порядок «фото → название
   → цена», у Google Maps снимки в шапке места. Высота фиксированная (200 px),
   а не по пропорциям снимка: иначе карточка прыгает на каждой загрузке, и
   вертикальное фото съедает пол-экрана.
   Блока нет вовсе, когда снимков нет, — пустой серый прямоугольник и есть та
   «нерациональная» пустота, ради которой карточку и переделывали. */
/* `overflow:hidden` здесь НЕ косметика: кадры сдвигаются `transform`-ом и без
   обрезки вылезают за карточку — тело получало горизонтальную прокрутку и
   уезжало вбок вместе с текстом. Прежняя версия галереи пряталась сама
   (`overflow-x:auto`), новая обязана прятаться здесь. */
/* Высоту держит САМА галерея, а лента и кадры тянутся за ней. Когда высота
   стояла на ленте, увеличенный кадр не растягивался: галерея становилась
   431 px, а снимок оставался 200 и под ним висела белая полоса. */
.card .gal{position:relative;margin:-12px calc(-1 * var(--gut)) 0;flex:0 0 auto;
  height:200px;overflow:hidden;transition:height .22s ease}
@media (prefers-reduced-motion: reduce){.card .gal{transition:none}}
/* Раскрытый кадр — половина экрана: «захотел — приблизил», как в инсте.
   Половина, а не весь экран: подпись места и цена обязаны оставаться на виду,
   иначе человек смотрит снимок неизвестно чего. */
.card .gal.zoom{height:50vh}
/* Лента кадров ДВИГАЕТСЯ, а не прокручивается: горизонтальный свайп оставлен
   будущему переходу между местами (так же разведены жесты в тиндере, где
   свайп занят действием над карточкой). */
.card .gstrip{
  display:flex;height:100%;background:var(--sunk);
  transition:transform .22s ease
}
@media (prefers-reduced-motion: reduce){.card .gstrip{transition:none}}
.card .gslide{
  flex:0 0 100%;margin:0;height:100%;
  display:grid;place-items:center;overflow:hidden;background:var(--sunk)
}
.card .gslide img{width:100%;height:100%;object-fit:cover;display:block}
/* Снимок не доехал — говорим об этом, а не показываем пустоту (frontend.md 6). */
.card .gslide.failed::after{content:"снимок не загрузился";font-size:11px;color:var(--ink-3)}
/* Сегменты вместо счётчика «1/5»: сколько кадров и где ты — видно, а не
   читается. Подсказка из сторис, там же и выучена аудиторией. */
.card .gbars{
  position:absolute;left:8px;right:8px;top:8px;display:flex;gap:4px;pointer-events:none
}
.card .gbars i{
  flex:1 1 0;height:3px;border-radius:2px;background:rgba(255,255,255,.42);
  box-shadow:0 0 2px rgba(18,33,31,.35)
}
.card .gbars i.on{background:#fff}

/* Три зоны тапа: края листают, СЕРЕДИНА увеличивает кадр. Раньше правая зона
   занимала 70% и середины не оставалось вовсе — увеличить было нечем.
   Левая уже правой: вперёд листают чаще. */
.card .gtap{
  position:absolute;top:0;bottom:0;background:none;border:0;padding:0;
  -webkit-tap-highlight-color:transparent
}
.card .gtap.prev{left:0;width:26%}
.card .gtap.next{right:0;width:32%}
.card .gtap.zoom{left:26%;right:32%;width:auto}
/* Единственная одиночная фотография листаться не может — увеличить её можно
   тапом в любое место кадра. */
.card .gal.single .gtap.zoom{left:0;right:0}
.card .gtap:focus-visible{outline:2px solid var(--accent);outline-offset:-3px}

/* «Открыто сейчас» — состояние, и стоит оно у названия, а не среди фактов:
   это первое, что хочет знать человек, который собирается идти. Цветом здесь
   различаются не «хорошо/плохо», а «можно идти сейчас / нельзя», поэтому
   цвет не единственный носитель: слово говорит то же самое. Состояния нет
   вовсе, когда расписание не разобрано, — молчание дешевле вранья. */
.card .onow{display:inline-block;margin-top:4px;font-size:12px;font-weight:600}
.card .onow.on{color:var(--ok)}
.card .onow.off{color:var(--ink-3)}

/* Признаки — плотная строка подписей без значков. Шесть значков с подписями
   на ширину телефона не влезают, а подписи здесь и есть содержание: «веган» и
   «терраса» словом понятны сразу, знаком — нет. */
.card .ams{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}
.card .am{padding:3px 8px;border:1px solid var(--line);border-radius:999px;
  font-size:11.5px;color:var(--ink-2)}

/* Факты — «метка → значение». Структура здесь несёт смысл: видно и что о месте
   известно, и чего о нём неизвестно. */
.card .facts{margin:10px 0 0;border-top:1px solid var(--line)}
.card .fact{display:flex;align-items:baseline;gap:10px;min-height:32px;padding:5px 0;
  border-bottom:1px solid var(--line);font-size:13px;text-decoration:none}
/* 44 px — только там, где нажимают. «Район» ничего не открывает, и полная
   высота на нём была бы платой ни за что. */
.card .fact.link,.card .fact:has(.fa){min-height:44px}
.card .fk{flex:0 0 84px;font-size:12px;color:var(--ink-3)}
.card .fv{flex:1;min-width:0;color:var(--ink);user-select:text;-webkit-user-select:text}
.card .fa{flex:0 0 auto;align-self:center;min-height:44px;padding:0 2px;
  font-size:11.5px;font-weight:600;color:var(--accent-ink)}
.card .fc{flex:0 0 auto;color:var(--ink-3);font-size:17px}
.card .link .fv{color:var(--accent-ink);font-weight:600}

/* Честность — отдельное поле внизу, а не два серых абзаца в воздухе.
   `margin-top:auto` прижимает его к низу, когда о месте известно мало: пустота
   в карточке тогда оказывается НАД служебным полем, а не под содержанием. */
.card .honest{margin:12px 0 0;padding:8px 10px;border-radius:var(--radius-sm);
  background:var(--sunk)}
/* `margin-top:auto` убран 05.09.2026: он прижимал блок ко дну, когда о месте
   известно мало, — на карточке в 525 px это закрывало дыру, а на 762 дыра
   стала вдвое больше и читается как поломка. Пусть блок стоит сразу за
   описанием: пустота внизу честнее пустоты посередине. */
.card .hl{font-size:11.5px;line-height:1.4;color:var(--ink-2)}
/* На подложке `sunk` тихий тон проваливается ниже порога — та же грабля, что
   с языками в полосе. Оговорку и надо читать, а не угадывать. */
.card .hw{margin-top:5px;font-size:11px;line-height:1.4;color:var(--ink-2)}

/* Сжатая форма: чат поднят, карте досталась полоса. Оставляем то, по чему
   человек понимает, о чём читает. Остальное вернётся, когда чат опустят. */
.card.compact .card-body{padding-bottom:6px}
/* Описание в сжатой форме ОСТАЁТСЯ: замер 05.09.2026 показал 94 px контента
   в 161 — сорок процентов полосы пустовало, пока чат читали. Двух строк
   хватает, чтобы понять, о чём место, и они не спорят с лентой за внимание:
   больше — уже чтение, а читают в этот момент чат. */
.card.compact .about{margin-top:6px;font-size:12.5px;line-height:1.35;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.card.compact .facts,
.card.compact .ams,
.card.compact .onow,
.card.compact .honest,
/* Галерея в сжатой форме не показывается: 200 px снимка превратили бы шапку
   в ту же карточку, ради сжатия которой её и сжимали. */
.card.compact .gal,
.card.compact .card-foot{display:none}
.card.compact .pn{display:none}
.card.compact h3{font-size:17px}
.card.compact .price{margin-top:8px}
.card.compact .pv{font-size:20px}
/* Сжатая карточка — сама себе кнопка «развернуть»: тап опускает чат обратно. */
.card.compact{cursor:pointer}
.card.compact::after{
  content:"⌄";position:absolute;left:50%;bottom:-2px;transform:translateX(-50%);
  font-size:15px;line-height:1;color:var(--ink-3);pointer-events:none
}

/* ---- Слои: быстрые кнопки на карте и «Ещё» ---- */
/* Полоса больше не растёт с числом типов: на карте живут только те слои, что
   помечены быстрыми (`place_type.is_quick`), и не больше `map.quick_layers_max`.
   Всё остальное — за одной кнопкой. Замер до правки: 804 px чипов при полосе
   390, видно два слоя из шести, за краем 414 px. */
.more{
  /* `margin-left:auto` — именно этим «Ещё» прижимается вправо, а не
     `justify-content` у полосы: тот развёл бы и сами значки, а они обязаны
     стоять плотной группой у левого края. */
  flex:0 0 auto;margin-left:auto;
  display:inline-flex;align-items:center;gap:6px;height:44px;padding:0 12px;
  border-radius:999px;font-size:12.5px;font-weight:600;white-space:nowrap;
  background:var(--surface);color:var(--ink-3);border:1px solid var(--line);
  box-shadow:var(--shadow)
}
/* Среди скрытых что-то включено — кнопка обязана это показывать, иначе слой
   работает, а признака его существования на экране нет. */
.more.on{background:var(--accent-soft);color:var(--accent-ink);border-color:var(--accent)}
.more b{font-weight:700;font-variant-numeric:tabular-nums}
.more[hidden]{display:none}

/* ---- Лист выбора слоёв ---- */
/* `flex:0 0 auto` — не украшение. По умолчанию flex-элемент СЖИМАЕТСЯ, и
   список, требующий места, выдавливал строку наборов с 50 px до 33: чипы
   высотой 34 обрезались по горизонтали пополам. Замер на живом экране:
   высота 33 при нужных 50. Выглядело это как «баг вёрстки», а было
   поведением flex по умолчанию. */
.lpresets{flex:0 0 auto;display:flex;gap:8px;padding:8px;flex-wrap:wrap;
  border-bottom:1px solid var(--line)}
.lclear{flex:0 0 auto;height:44px;padding:0 12px;font-size:12.5px;font-weight:600;
  color:var(--accent-ink)}
.lpreset{flex:0 0 auto;height:34px;padding:0 12px;border-radius:999px;font-size:12.5px;
  font-weight:600;background:var(--surface);border:1px solid var(--line);color:var(--ink-3);
  white-space:nowrap}
.lpreset.on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-ink)}
.lgroup{padding:2px 0 6px}
.lrow{display:flex;align-items:center;gap:10px;width:100%;min-height:48px;padding:4px 10px;
  border-radius:var(--radius-sm);text-align:left;color:var(--ink)}
.lrow:active{background:var(--sunk)}
/* Подкатегория сдвинута, а не подписана: отступ показывает подчинение
   молча и не тратит строку на заголовок. */
.lrow:not(.grp){padding-left:34px}
.lrow:not(.grp) .lname{font-size:13.5px;color:var(--ink-2)}
.lrow.grp .lname{font-size:14.5px;font-weight:600}
.lico{width:26px;height:26px;border-radius:50%;flex:0 0 auto;display:grid;place-items:center;
  font-size:13px;background:var(--c-soft,var(--sunk));border:1px solid var(--c,var(--line-2))}
.lname{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lcnt{font-family:ui-monospace,monospace;font-size:11.5px;color:var(--ink-3)}
/* Переключатель, а не галочка: слой либо рисуется на карте, либо нет — это
   состояние, а не выбор из списка. */
.lsw{width:40px;height:24px;border-radius:999px;background:var(--sunk);position:relative;
  flex:0 0 auto;border:1px solid var(--line-2)}
.lsw i{position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;
  background:var(--surface);box-shadow:var(--shadow);transition:left .14s ease}
@media (prefers-reduced-motion: reduce){.lsw i{transition:none}}
.lsw.on{background:var(--accent);border-color:var(--accent)}
.lsw.on i{left:18px}
/* Третье состояние группы: часть детей включена. Показывать его обязательно —
   «всё включено» на половине включённых это неправда. */
.lsw.part{background:var(--accent-soft);border-color:var(--accent)}
.lsw.part i{left:9px}
/* Те же грабли, что у наборов: без явного `0 0 auto` строку сожмёт список. */
.gsearch{flex:0 0 auto}
.lfoot{flex:0 0 auto;padding:8px;border-top:1px solid var(--line);background:var(--surface)}
.ldone{width:100%;height:46px;border-radius:999px;background:var(--accent);
  color:var(--on-accent);font-size:14px;font-weight:600}

/* Источники описания — свёрнуты. Текст выше НАШ, но проверяемость обязана
   быть под рукой: «не выдавать непроверенное за проверенное» — обещание
   продукта. Читают этот список единицы, поэтому он не занимает высоту, пока
   его не раскрыли (frontend.md 8). */
.card .srcs{margin-top:6px;font-size:11.5px;color:var(--ink-3)}
.card .srcs summary{min-height:32px;display:flex;align-items:center;cursor:pointer}
.card .srcs a{display:block;padding:3px 0;color:var(--accent-ink);text-decoration:none;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Подпись источника снимка. Обязательна там, где кадр взят со страницы
   заведения: показ чужой фотографии без имени источника — присвоение, а не
   иллюстрация. Поверх кадра в углу, а не строкой под галереей: снимки бывают
   из разных мест, и одна подпись на всех приписала бы фото не тому.
   Тень под текстом, потому что фон — произвольная фотография: подпись обязана
   читаться и на белой витрине, и на тёмном интерьере. */
.card .gslide{position:relative}
.card .gsrc{
  position:absolute;right:6px;bottom:6px;z-index:1;
  padding:2px 6px;border-radius:999px;
  background:rgba(0,0,0,.55);color:#fff;
  font-size:10px;line-height:1.3;letter-spacing:.02em;
  pointer-events:none
}

/* Значок с ОТВЕТОМ и точка — две ступени одной лестницы (07.09.2026).
   Замер, на котором это стоит: на z14 сто пинов давали 641 наложение и
   закрывали треть экрана, отличаясь друг от друга только эмодзи. Теперь
   полноценный значок достаётся тем, кому есть что сказать, а остальным —
   точка: «есть, но внимания не просит», а не «скрыто». */
.pin .say{
  font-size:11px;font-weight:700;letter-spacing:.01em;white-space:nowrap;
  color:var(--c,var(--ink))
}
/* Кольцо у говорящего значка заметнее: он и должен притягивать взгляд
   первым — ради него всё и затевалось. */
.pin.says{border-color:var(--c,var(--line));box-shadow:var(--shadow-lift)}

/* Точка держит ЦВЕТ СЛОЯ: по ней видно, что это, даже без подписи. Размер
   14 px — видимая часть; площадь касания растёт до 44 через ::after, не
   сдвигая ни пикселя вёрстки (frontend.md 10). */
.dot{
  width:14px;height:14px;padding:0;border-radius:50%;position:relative;
  background:var(--c,var(--accent));border:2px solid var(--surface);
  box-shadow:0 1px 3px rgba(18,33,31,.28);
  -webkit-tap-highlight-color:transparent
}
.dot::after{content:"";position:absolute;inset:-15px}
.dot:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ---- Состояния метки (решение владельца 17.09.2026, макет
   docs/design/map-marker-states). Цвета состояния подставляет map.js в --c и
   --c-soft: движки пишут их строкой стиля, и класс их не перебил бы. Здесь —
   только то, что цветом не выразить. На метке одно состояние: выбранная
   перекрывает просмотренную ещё в map.js. */

/* ВЫБРАННАЯ, вариант А: заливка тёмным тоном слоя (--c = --l-*-strong), текст
   инвертирован. Размер и позиция прежние — якорь раскладки не сдвигается, а
   соседей она накрывает ровно тем же прямоугольником, что и до выделения.
   Кольцо кружка уходит в --surface: на заливке цвета слоя кольцо того же
   цвета пропало бы, а эмодзи остаётся на мягкой подложке и читается.
   Контраст текста --on-layer на заливке: светлая 4,59…5,85, тёмная
   5,63…8,36 (tokens.css). */
.pin.sel{background:var(--c);border-color:var(--c);color:var(--on-layer);box-shadow:var(--shadow-lift)}
.pin.sel .say{color:var(--on-layer)}
.pin.sel .ico{border-color:var(--surface)}
/* Просмотренная метка: цвет КАТЕГОРИИ сохранён (--c свой), лишь приглушена
   прозрачностью — «был здесь», а не «закрыто». Серый читался как недоступное
   (владелец 18.09.2026). Выбранная перебивает просмотренную (идёт после). */
.pin.seen, .dot.seen, .lm.seen{opacity:.5}
/* Точкой выбранная бывает редко (раскладка ставит её первой), но бывает —
   если её место занял ориентир. Заливка у точки и так цветом слоя, поэтому
   выделяет её обводка цветом слоя через зазор. */
.dot.sel{box-shadow:0 0 0 2px var(--c),var(--shadow-lift)}

/* ПРОСМОТРЕННАЯ, вариант 2: цвет слоя заменён на --ink-3 (map.js), эмодзи
   серое. Бледность (opacity) отвергнута замером: точка на квартале падала
   ниже 3:1, «был здесь» превращался в «почти не видно». --ink-3 к подложке:
   светлая 3,9 (худшая — здание), тёмная 4,6. Тень — обычная: подъём
   `.says` у просмотренной не нужен, её уже смотрели. */
.seen .ico{filter:grayscale(1)}
.pin.says.seen{box-shadow:var(--shadow)}

/* «Как тут на самом деле?» — дверь к снимкам и отзывам посетителей в Google
   (решение владельца 17.09.2026). Во ВСЕХ карточках и в липкой зоне над
   разговором и действиями: большим пальцем туда дотягиваются, а при прокрутке
   она не уезжает. Одна ссылка целиком. Картинки нет: фон — градиент мягкого
   тона слоя к поверхности, эмодзи типа — ТЕКСТ, приглушённый, у правого края.
   Высота 56, а не 88 прежней полосы на месте галереи: две строки и воздух
   вокруг них, касание с запасом над 44. Зазор 8 до соседей даёт `gap` зоны.
   Рамка того же тона, что у кнопки разговора: зона держит одну геометрию.
   Цена в высоте названа: липкая зона выросла на 64 px (56 + зазор 8), на
   экране 390×844 тело карточки 646 → 582 px с разговором, 698 → 634 без.
   Строки — в одну линию и на 320 px: доступно 242 (320 − жёлоб 24 − рамка 2
   − поле 12 − место под эмодзи 40). Замер canvas measureText, жирный взят
   для обеих строк — с запасом: заголовок 14 px ru 172 · en 110 · vi 106
   (Noto Sans, ширина близка к Roboto); подзаголовок при 12 px давал 245 и не
   влезал на ru и vi, поэтому 11,5: ru 235 · en 210 · vi 235. Шрифт шире
   (DejaVu, десктопный Linux) — многоточие, а не перенос.
   Контраст: заголовок --ink на градиенте ≥13,4 (светлая) / ≥11,6 (тёмная),
   подзаголовок --accent ≥4,86 / ≥5,50 в худшей точке градиента. */
.card-foot .ggl{
  position:relative;flex:0 0 auto;height:56px;overflow:hidden;
  display:flex;flex-direction:column;justify-content:center;gap:2px;
  padding:0 40px 0 12px;border:1px solid var(--line-2);border-radius:var(--radius-sm);
  background:linear-gradient(100deg,var(--c-soft,var(--sunk)) 0%,var(--surface) 100%);
  text-decoration:none;-webkit-tap-highlight-color:transparent
}
.card-foot .ggl:active{background:var(--c-soft,var(--sunk))}
.card-foot .ggl:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.card-foot .ggt,.card-foot .ggs{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.card-foot .ggt{font-size:14px;line-height:1.25;font-weight:700;color:var(--ink)}
.card-foot .ggs{font-size:11.5px;line-height:1.3;font-weight:600;color:var(--accent-ink)}
.card-foot .gge{
  position:absolute;right:10px;top:50%;transform:translateY(-50%);
  font-size:22px;line-height:1;font-style:normal;opacity:.45;pointer-events:none
}
