/* ==========================================================================
   EstateAll — карточка объекта каталога (full-bleed).
   Натянуто на микроблок realty/tm58887_index_list_item.json.
   Подключается узлом type:"style" из realty/tm58887_index.json — только на
   страницах выдачи (/agency/realty/index, /agency/realty/my).
   @font-face houzez-iconfont и глифы icon-* здесь НЕ дублируются: они живут
   в /uploads/estateal/style.css.
   ========================================================================== */

:root {
  --brand-red: #be151b;
  --brand-orange: #f26921;
  --brand-yellow: #f7921e;

  --ea-ink: #1e1e1e;
  --ea-ink-muted: #6b6f76;
  --ea-surface: #ffffff;
  --ea-surface-sunken: #f8f7f5;
  --ea-page: #f4f2ef;
  --ea-line: #e7e4e0;

  --ea-radius-card: 20px;
  --ea-radius-tag: 999px;

  --ea-ease: cubic-bezier(0.32, 0.72, 0, 1);

  /* тени тонированы в тёплый бренд-оттенок, не «чёрный на N%» */
  --ea-shadow-rest: 0 1px 2px rgba(120, 72, 40, 0.06);
  --ea-shadow-lift: 0 18px 44px rgba(120, 72, 40, 0.18);
  --ea-shadow-focus: 0 0 0 4px rgba(242, 105, 33, 0.14),
    0 2px 8px rgba(120, 72, 40, 0.08);

  /* СВЕТЛОЕ стекло: белая основа с тёплым подмесом, плоская заливка.
     Плотность 0.76/0.84 подобрана так, чтобы тёмный текст #1E1E1E держал
     4.5:1 и на пересвеченном небе, и на тёмном интерьере. */
  --ea-glass-tint: rgba(255, 251, 246, 0.76);
  --ea-glass-tint-strong: rgba(255, 251, 246, 0.84);
  --ea-glass-edge: rgba(255, 255, 255, 0.92);
  /* контур-подпечатка: держит край светлой пилюли на белой стене */
  --ea-glass-hairline: rgba(74, 42, 18, 0.16);
}

/* ==========================================================================
   КАРТОЧКА — каркас
   ========================================================================== */

.item-wrap {
  /* обводка — единый класс из custom.css; здесь только ручки под геометрию карточки
     (радиус кольцо наследует от border-radius ниже) */
  --ea-sweep-z: 6;                 /* поверх снимка, пилюль и слайдера */
  position: relative;
  display: block;
  isolation: isolate;
  aspect-ratio: 3 / 4;
  min-height: 420px;
  border: 1px solid var(--ea-line);
  border-radius: var(--ea-radius-card);
  background: #2a1c12;
  box-shadow: var(--ea-shadow-rest);
  overflow: hidden;
  outline: none;

  /* темп развёртки — ручки канона (custom.css), остальное своё */
  transition:
    --ea-sweep var(--ea-sweep-dur) var(--ea-sweep-ease) var(--ea-sweep-delay),
    box-shadow 0.52s var(--ea-ease) 0.1s,
    transform 0.38s var(--ea-ease);
}

/* border-color на hover НЕ трогаем: сплошная оранжевая рамка появлялась за 0.2s
   раньше развёртки и читалась вместо неё — на форме такого перебоя нет. */
.item-wrap:hover,
.item-wrap:has(:focus-visible) {
  --ea-sweep: 360deg;
  box-shadow: var(--ea-shadow-focus), var(--ea-shadow-lift);
  transform: translateY(-4px);
}

/* Иконочный шрифт и глифы icon-* живут в /uploads/estateal/style.css, но кегль
   там не задан — внутри карточки иконки должны быть 14px, как в макете. */
.item-wrap .houzez-icon { display: inline-block; font-size: 14px; }

/* --- снимок: занимает всю карточку ---------------------------------------- */
.fb-photo { position: absolute; inset: 0; z-index: 0; display: block; perspective: 900px; }
/* .img-fluid из style.css темы навязывает height:auto и max-height:253px
   (`.listing-thumb .img-fluid`) — снимок переставал закрывать карточку, поэтому
   селектор с классом темы и явные max-* */
.fb-photo img,
.fb-photo img.img-fluid {
  width: 100%; height: 100%; max-width: none; max-height: none;
  object-fit: cover; display: block;
  /* Поворот за курсором — те же константы, что у карточек агентов на главной
     (home_cards.js: REACH_K 2.2, MAX 7deg + 10% = 7.7deg). Крутится ТОЛЬКО снимок, карточка стоит.
     Запас масштаба нужен, чтобы повёрнутый край не обнажал угол кадра. */
  transform: translateX(var(--base-x, 0px)) translateX(var(--pan-x, 0px))
             rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) scale(var(--ph-scale, 1.16));
  transition: transform 0.7s var(--ea-ease);
}
/* Пока курсор НА карточке, transform НЕ анимируется браузером: значение и так
   меняется каждый кадр из rAF, а короткий transition поверх этого давал вторую
   интерполяцию, которая перезапускалась на каждом новом значении — отсюда и
   шли рывки (замер при РОВНОЙ скорости курсора: разброс сдвига 1.5…6.3 px на
   кадр, вплоть до кадров с нулевым сдвигом; без transition разброс втрое
   меньше). Сглаживание считает JS (EASE в property-card.js). Класс снимается,
   как только курсор ушёл, и кадр возвращается к центру длинной мягкой кривой. */
.item-wrap.is-tilting .fb-photo img { transition: none; }

/* Горизонтальный снимок в вертикальной карточке шире окна: то, что не
   поместилось, показываем панорамированием за курсором (--pan-x в пикселях,
   считает JS по natural-размерам). Кадр показан в натуральной пропорции по
   высоте окна и центрирован --base-x, поэтому сдвиг — обычный composited
   transform: object-position перерисовывал бы весь снимок на каждом кадре и
   на крупных фото шёл рывками. У вертикального снимка запас нулевой и класса
   нет — двигать нечего. */
.fb-photo img.is-wide {
  width: auto; height: 100%; right: auto; left: 50%; --base-x: -50%;
  will-change: transform;
}

/* --- скримы: мягкие, глазом не читаются как плашка ------------------------
   Многоступенчатый градиент аппроксимирует ease-out: нет ни ленты, ни
   видимой границы, но контраст под текстом гарантирован. */
.fb-scrim { position: absolute; left: 0; right: 0; z-index: 1; pointer-events: none; }
.fb-scrim--top {
  top: 0; height: 46%;
  background: linear-gradient(to bottom,
    rgba(22, 12, 6, 0.62) 0%,
    rgba(22, 12, 6, 0.55) 12%,
    rgba(22, 12, 6, 0.42) 27%,
    rgba(22, 12, 6, 0.28) 44%,
    rgba(22, 12, 6, 0.15) 62%,
    rgba(22, 12, 6, 0.06) 80%,
    rgba(22, 12, 6, 0) 100%);
}
.fb-scrim--bottom {
  bottom: 0; height: 52%;
  background: linear-gradient(to top,
    rgba(18, 10, 5, 0.76) 0%,
    rgba(18, 10, 5, 0.66) 13%,
    rgba(18, 10, 5, 0.48) 28%,
    rgba(18, 10, 5, 0.30) 45%,
    rgba(18, 10, 5, 0.15) 63%,
    rgba(18, 10, 5, 0.05) 82%,
    rgba(18, 10, 5, 0) 100%);
}

/* --- слой контента -------------------------------------------------------- */
.fb-layer {
  position: absolute; inset: 0; z-index: 2;
  display: grid; grid-template-rows: auto 1fr auto;
  align-items: start;
  padding: 16px;
  gap: 12px;
}
.fb-head { grid-row: 1; min-width: 0; }

.fb-foot { grid-row: 3; align-self: end; min-width: 0; }

/* ==========================================================================
   ЗАГОЛОВОК — без подложки. Читаемость держат три слоя, ни один из них
   не является жирной обводкой:
   1) мягкий верхний скрим (выше);
   2) двойная тень-ореол — ближняя даёт край, дальняя гасит светлое небо;
   3) волосяной stroke 0.5px под заливкой (paint-order) — держит края букв
      на пересвеченном фоне, но толщиной не читается как контур.
   ========================================================================== */
.item-title {
  margin: 0 0 10px;
  font-size: 19px; font-weight: 700; line-height: 1.28; letter-spacing: -0.015em;
}
.item-title a {
  color: #fff; text-decoration: none;
  display: block;
  text-shadow:
    0 1px 1px rgba(20, 10, 4, 0.58),
    0 2px 10px rgba(20, 10, 4, 0.52),
    0 6px 26px rgba(20, 10, 4, 0.34);
  -webkit-text-stroke: 0.5px rgba(24, 12, 5, 0.42);
  paint-order: stroke fill;
  transition: color 0.2s var(--ea-ease);
}
/* Кнопки Details нет — кликабельна вся карточка: растянутый псевдоэлемент
   заголовочной ссылки. Точечные ссылки (статус, агент) поднимаются выше него. */
.item-title a::after { content: ""; position: absolute; inset: 0; z-index: 4; border-radius: var(--ea-radius-card); }
.labels-wrap a, .label-status, .item-author a, .fb-foot a { position: relative; z-index: 6; }
.item-wrap:hover .item-title a { color: #fff2e9; }
.item-title a:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
  border-radius: 6px;
}

/* Город живёт в одной строке с огоньком и бейджами: усечение обязательно,
   иначе длинное название сдвигает правую группу за край узкой карточки. */
.item-address {
  margin: 0;
  font-size: 12.5px; font-style: normal; font-weight: 600; letter-spacing: 0.015em;
  color: rgba(255, 255, 255, 0.96);
  display: flex; align-items: center; gap: 5px; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  text-shadow: 0 1px 2px rgba(18, 9, 3, 0.78), 0 2px 9px rgba(18, 9, 3, 0.6);
}
.item-address svg { flex: none; opacity: 0.85; }

/* ==========================================================================
   СВЕТЛЫЕ СТЕКЛЯННЫЕ ТЕГИ (Apple-glass, светлая трактовка)
   brightness(1.22) в backdrop-filter работает наоборот: он ПОДСВЕЧИВАЕТ фон
   под пилюлей, поэтому тёмный текст #1E1E1E держит 4.5:1 и на тёмном
   интерьере тоже. Заливка плоская, без блика-градиента.
   ========================================================================== */
.item-amenities {
  list-style: none; margin: 0; padding: 0;
  display: flex; justify-content: center; flex-wrap: wrap; gap: 7px;
}
.item-amenities li {
  display: inline-flex; align-items: center; gap: 6px;
  height: 30px; padding: 0 11px;
  border-radius: var(--ea-radius-tag);
  border: 1px solid var(--ea-glass-edge);
  background: rgba(255, 251, 246, 0.58);
  -webkit-backdrop-filter: blur(28px) saturate(200%) brightness(1.28);
  backdrop-filter: blur(28px) saturate(200%) brightness(1.28);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.95), inset 0 -1px 0 rgba(255,255,255,0.45), inset 0 0 0 1px var(--ea-glass-hairline), 0 4px 16px rgba(60, 36, 18, 0.18);
  color: var(--ea-ink);
  font-size: 12.5px; font-weight: 700; letter-spacing: 0.01em; line-height: 1;
  white-space: nowrap;
}
.item-amenities li svg { flex: none; color: var(--ea-ink); opacity: 0.72; }
.item-amenities .hz-figure { font-variant-numeric: tabular-nums; }
/* Спальни заполнены не у всех категорий (у Villa/Commercial параметра нет вовсе) —
   тег без цифры читается как поломка, поэтому прячем. «0» — валидное значение,
   :empty его не трогает. */
.item-amenities li:has(.hz-figure:empty) { display: none; }
.item-amenities /* Постфикс площади: в разметке стоит настоящий символ m² (U+00B2) —
   надстрочная двойка приходит из шрифта, а не рисуется псевдоэлементами.
   Так строка остаётся одним словом для скринридера («m²», не «m m2 2»).
   На боевом микроблоке потребуется та же правка строки вывода. */
.area_postfix { font-weight: 500; color: inherit; font-size: 11.5px; letter-spacing: 0.01em; }

/* Спальни в выдаче приходят пустыми, но оригинал ВЫВОДИТ иконку и при пустом
   значении — тег не скрываем, иначе теряется элемент карточки. */

/* тип объекта — единственный тег с бренд-подмесом: он классифицирует,
   а не измеряет, поэтому отделён цветом, а не размером */
.labels-right .h-type {
  display: inline-flex; align-items: center; gap: 6px;
  height: 28px; padding: 0 12px;
  border-radius: var(--ea-radius-tag);
  border: 1px solid var(--ea-glass-edge);
  background: rgba(255, 251, 246, 0.58);
  -webkit-backdrop-filter: blur(28px) saturate(200%) brightness(1.28);
  backdrop-filter: blur(28px) saturate(200%) brightness(1.28);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.95), inset 0 -1px 0 rgba(255,255,255,0.45), inset 0 0 0 1px var(--ea-glass-hairline), 0 4px 16px rgba(60, 36, 18, 0.18);
  color: var(--ea-ink); text-decoration: none;
  text-transform: uppercase; font-size: 11px; font-weight: 700; letter-spacing: 0.07em;
}
.labels-right .h-type svg { flex: none; color: var(--ea-ink); opacity: 0.72; }

/* ==========================================================================
   ВЕРХНЯЯ ПОЛОСА: огонёк + статус сделки
   ========================================================================== */
.item-header { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.labels-wrap { display: flex; align-items: center; gap: 8px; }
.labels-left { min-width: 0; flex: 1 1 auto; }
.labels-right { flex: none; }

.label-status {
  display: inline-flex; align-items: center; height: 28px; padding: 0 12px;
  border-radius: var(--ea-radius-tag);
  border: 1px solid rgba(255,255,255,0.34);
  background: var(--brand-orange);
  
  box-shadow: 0 0 0 1.5px rgba(255,255,255,0.80), inset 0 1px 0 rgba(255,255,255,0.30), 0 4px 14px rgba(190, 21, 27, 0.28);
  color: #fff; text-decoration: none;
  font-size: 11px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase;
  white-space: nowrap;
  transition: border-color 0.2s var(--ea-ease), box-shadow 0.52s var(--ea-ease) 0.1s, color 0.2s var(--ea-ease);
}
.label-status:hover,
.label-status:focus-visible {
  border-color: var(--brand-orange);
  color: var(--brand-red);
  box-shadow: var(--ea-shadow-focus);
  outline: none;
}

/* --- ОГОНЁК: живое пламя -------------------------------------------------
   Анимируются только transform и opacity. Размытие ореола статическое
   (filter не анимируется) — на выдаче из 12+ карточек это не грузит CPU. */
.fb-hot {
  position: relative;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  flex: none;
}
.fb-hot__glow {
  /* плоская бренд-заливка + blur: тот же мягкий ореол,
     собранный размытием, а не переходом цвета */
  position: absolute; inset: -2px;
  border-radius: 50%;
  background: rgba(242, 105, 33, 0.62);
  filter: blur(7px);
  animation: fb-glow 2.15s ease-in-out infinite;
}
.fb-hot svg { position: relative; width: 26px; height: 30px; overflow: visible; }
.fb-flame-outer {
  transform-origin: 50% 96%;
  animation: fb-flame-outer 1.45s ease-in-out infinite;
}
.fb-flame-core {
  transform-origin: 50% 96%;
  animation: fb-flame-core 0.92s ease-in-out infinite;
}
.fb-spark {
  transform-origin: 50% 100%;
  animation: fb-spark 2.6s ease-out infinite;
}
.fb-spark--b { animation-duration: 3.1s; animation-delay: 1.1s; }

/* Огонёк живёт только у карточек в кадре: класс is-offscreen ставит
   IntersectionObserver в property-card.js. Пауза, а не выключение, —
   вернувшись в кадр, пламя продолжается с той же фазы, глаз разрыва не видит.
   Замер: 14 огоньков x 4 анимации вне кадра стоили ~30% времени кадра при скролле. */
.item-wrap.is-offscreen .fb-hot__glow,
.item-wrap.is-offscreen .fb-flame-outer,
.item-wrap.is-offscreen .fb-flame-core,
.item-wrap.is-offscreen .fb-spark { animation-play-state: paused; }

@keyframes fb-flame-outer {
  0%, 100% { transform: scale(1, 1) translateY(0) rotate(0deg); }
  28%      { transform: scale(0.94, 1.07) translateY(-0.6px) rotate(-2.4deg); }
  55%      { transform: scale(1.05, 0.95) translateY(0.3px) rotate(1.8deg); }
  78%      { transform: scale(0.97, 1.04) translateY(-0.3px) rotate(-1deg); }
}
@keyframes fb-flame-core {
  0%, 100% { transform: scale(1, 1) translateY(0); opacity: 0.95; }
  33%      { transform: scale(0.88, 1.12) translateY(-0.5px); opacity: 1; }
  66%      { transform: scale(1.08, 0.9) translateY(0.4px); opacity: 0.86; }
}
@keyframes fb-glow {
  0%, 100% { opacity: 0.72; transform: scale(1); }
  22%      { opacity: 0.95; transform: scale(1.07); }
  48%      { opacity: 0.63; transform: scale(0.96); }
  71%      { opacity: 0.88; transform: scale(1.03); }
}
@keyframes fb-spark {
  0%       { opacity: 0; transform: translateY(0) scale(0.6); }
  12%      { opacity: 0.9; }
  100%     { opacity: 0; transform: translateY(-14px) scale(0.25); }
}

/* ==========================================================================
   НИЗ: цена — главная доминанта карточки
   ========================================================================== */
.fb-bottom { display: flex; align-items: center; justify-content: space-between; gap: 14px; }

.item-price-wrap { list-style: none; margin: 0; padding: 0; min-width: 0; flex: 0 0 auto; }
/* Стрелка изменения цены (оригинал: li.result-change + /uploads/price_[du].png).
   Живёт в верхней строке рядом с типом жилья и статусом — тем же стеклом. */
.labels-right .result-change {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0; width: 28px; height: 28px; border-radius: 50%;
  line-height: 0; flex: none;
  border: 1px solid var(--ea-glass-edge);
  background: rgba(255, 251, 246, 0.58);
  -webkit-backdrop-filter: blur(28px) saturate(200%) brightness(1.28);
  backdrop-filter: blur(28px) saturate(200%) brightness(1.28);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.95), inset 0 -1px 0 rgba(255,255,255,0.45), inset 0 0 0 1px var(--ea-glass-hairline), 0 4px 16px rgba(60, 36, 18, 0.18);
  transition: transform 0.42s var(--ea-ease) 0.02s, background-color 0.42s var(--ea-ease);
}
.item-wrap:hover .labels-right .result-change,
.item-wrap:has(:focus-visible) .labels-right .result-change { transform: translateY(2px); }
.labels-right .result-change img {
  width: 13px; height: auto; display: block;
}
.item-price { white-space: nowrap; }
.item-price {
  font-size: 30px; font-weight: 700; line-height: 1.02; letter-spacing: -0.028em;
  color: #fff;
  font-variant-numeric: tabular-nums;
  text-shadow:
    0 1px 1px rgba(16, 8, 3, 0.55),
    0 2px 12px rgba(16, 8, 3, 0.55),
    0 8px 30px rgba(16, 8, 3, 0.38);
  -webkit-text-stroke: 0.5px rgba(20, 10, 4, 0.38);
  paint-order: stroke fill;
  transition: transform 0.38s var(--ea-ease);
}
.item-sub-price {
  margin-top: 4px;
  font-size: 15px; font-weight: 700; letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.80);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 2px rgba(16, 8, 3, 0.62), 0 2px 8px rgba(16, 8, 3, 0.45);
}
.item-sub-price:empty { display: none; }
.item-sub-price .fb-unit { opacity: 0.68; margin-left: 0.28em; }

/* --- подвал: агент + возраст. Живёт волосяной строкой у самого низа,
   на площадь снимка почти не претендует. -------------------------------- */
/* Подвал — правая колонка строки цены: [имя / дата] и круглый аватар
   у самого края. По вертикали центрируется относительно блока цены. */
.item-footer {
  display: flex; align-items: center; gap: 9px; flex: none;
  font-size: 11.5px; letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.80);
  text-shadow: 0 1px 3px rgba(16, 8, 3, 0.66);
}
/* Весь блок агента (имя + дата + аватар) — одна ссылка на агента */
.fb-agent-link {
  /* потолок ширины: длинное имя агента + «Date DD.MM.YYYY» не должны ломать цену */
  display: flex; align-items: center; gap: 9px; min-width: 0;
  flex: 1 1 auto; justify-content: flex-end;
  color: inherit; text-decoration: none; border-radius: 999px;
  transition: color 0.2s var(--ea-ease);
}
.fb-agent-link:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.9), 0 0 0 4px rgba(242, 105, 33, 0.55);
}
.fb-agent { display: flex; flex-direction: column; align-items: flex-end; gap: 0; min-width: 0; text-align: right; line-height: 1.18; }

/* Статусы Sold / Reserve — ветки микроблока state_id 8 / 12. Оранжевый бейдж
   остаётся у активных (For Sale / For Rent), снятые с продажи гасятся. */
.label-status--sold {
  background: #4A4744; color: #fff;
  box-shadow: 0 0 0 1.5px rgba(255,255,255,0.80), inset 0 1px 0 rgba(255,255,255,0.22), 0 4px 14px rgba(28,20,14,0.34);
}
.label-status--reserve {
  background: var(--brand-yellow); color: #3A2408;
  box-shadow: 0 0 0 1.5px rgba(255,255,255,0.88), inset 0 1px 0 rgba(255,255,255,0.42), 0 4px 14px rgba(190,120,20,0.30);
}
/* Агент без фото (users.image_small пуст) — оригинальная иконка темы в круге */
.fb-avatar--empty { font-size: 15px; }
.fb-avatar--empty .houzez-icon { font-size: 15px; color: #fff; }

/* Аватар — реальное фото агента (users.image_small) */
.fb-avatar {
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  /* Генератор превью умеет только ЦЕНТРАЛЬНЫЙ кроп, а лицо на портрете живёт выше
     центра (Haar по 12 фото агентов: cy 0.21–0.41). Превью просим портретным 2:3,
     кружок берём с якорем 8% — при этом центр лица у всех 12 попадает внутрь круга
     (0.28–0.57 диаметра); центр (50%) резал макушки у половины. */
  object-fit: cover; object-position: 50% 8%;
  background: var(--brand-orange); color: #fff;
  font-size: 11.5px; font-weight: 700; text-shadow: none;
  box-shadow: 0 0 0 1.5px rgba(255,255,255,0.80), 0 4px 12px rgba(120, 72, 40, 0.30);
  transition: transform 0.4s var(--ea-ease), box-shadow 0.4s var(--ea-ease);
}

.fb-avatar-wrap { display: contents; }

/* Индивидуальный кадр на агента: макушка у верхнего края кружка. Значения посчитаны
   детекцией лица по оригиналу (Haar + запас 0.38*высоты бокса на волосы). Ключ — id
   пользователя в классе (`ava-<id>`), потому что src после ресайза становится хэшем
   и имени файла в себе не несёт. Новый агент без строки здесь получает дефолт выше. */
.ava-1 .fb-avatar { object-position: 50% 3.3%; }
.ava-5 .fb-avatar { object-position: 50% 39.2%; }
.ava-14 .fb-avatar { object-position: 50% 12.5%; }
.ava-15 .fb-avatar { object-position: 50% 30.9%; }
.ava-23 .fb-avatar { object-position: 50% 5.7%; }
.ava-33 .fb-avatar { object-position: 50% 7.5%; }
.ava-37 .fb-avatar { object-position: 50% 8.4%; }
.ava-38 .fb-avatar { object-position: 50% 0%; }
.ava-42 .fb-avatar { object-position: 50% 3.7%; }
.ava-44 .fb-avatar { object-position: 50% 0%; }
.ava-45 .fb-avatar { object-position: 50% 9.8%; }
.ava-46 .fb-avatar { object-position: 50% 12.9%; }

.item-wrap:hover .fb-avatar, .item-wrap:has(:focus-visible) .fb-avatar {
  transform: scale(1.06);
  box-shadow: 0 0 0 2px rgba(255,255,255,0.92), 0 6px 16px rgba(190, 21, 27, 0.32);
}
.item-author {
  display: block; min-width: 0; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  border-bottom: 1px solid transparent;
  transition: color 0.2s var(--ea-ease), border-color 0.2s var(--ea-ease);
}
.fb-agent-link:hover .item-author, .fb-agent-link:focus-visible .item-author {
  color: var(--brand-orange); border-bottom-color: rgba(242, 105, 33, 0.7);
}
.fb-agent-link:hover .fb-avatar, .fb-agent-link:focus-visible .fb-avatar {
  transform: scale(1.12);
  box-shadow: 0 0 0 2px rgba(255,255,255,0.96), 0 8px 20px rgba(190, 21, 27, 0.38);
}
.item-date { flex: none; opacity: 0.78; font-variant-numeric: tabular-nums; white-space: nowrap; }


/* --- 1. «Пояс»: теги строкой у нижнего края, прямо над ценой.
   Верх отдан заголовку, весь центр карточки — чистый снимок. ------------- */
/* Теги живут в подвале, НИЖЕ цены. Отступ задан здесь, после базового
   правила .item-amenities с margin:0 — иначе оно его перебивает. */
.item-amenities { margin-top: 11px; }

/* ==========================================================================
   АДАПТИВ. Карточка меряет СВОЮ ширину (container query), поэтому в
   4-колоночной выдаче и в рамке 390px она ведёт себя одинаково честно.
   ========================================================================== */
.item-listing-wrap { container-type: inline-size; min-width: 0; }

@container (max-width: 330px) {
  .item-title { font-size: 16.5px; }
  .item-price { font-size: 25px; }
  .item-amenities li { height: 27px; padding: 0 9px; font-size: 11.5px; }
  .fb-layer { padding: 13px; }
}

@media (max-width: 560px) {
  .item-wrap { aspect-ratio: 4 / 5; }
}

/* ==========================================================================
   ДОСТУПНОСТЬ
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .item-wrap,
  .item-wrap::after,
  .fb-photo img,
  .item-price,
  /* пламя замирает в открытой фазе, ореол остаётся — метка не «гаснет» */
  .fb-hot__glow,
  .fb-flame-outer,
  .fb-flame-core { animation: none !important; }
  .fb-spark { animation: none !important; opacity: 0 !important; }

  .item-wrap:hover, .item-wrap:has(:focus-visible) { transform: none; }
  .fb-photo img { transform: none !important; }
}

/* без backdrop-filter стекло обязано остаться читаемым: плотная заливка */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .item-amenities li,
  .label-status { background: var(--brand-orange); }
  .item-amenities .h-type { background: var(--brand-orange); }
}
@media (prefers-reduced-transparency: reduce) {
  .item-amenities li,
  .label-status {
    background: #fffbf6;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  .item-amenities .h-type { background: var(--brand-orange); }
}


/* ==========================================================================
   HOVER-АНИМАЦИЯ КАРТОЧКИ — одна волна снизу вверх
   Порядок и задержки подобраны так, чтобы движение читалось как единый
   отклик, а не как несколько независимых дёрганий:
     0ms   фото подаётся вперёд (медленно, оно фон — не должно опережать)
     40ms+ теги всплывают каскадом по 45ms друг за другом
     170ms цена подаётся последней — она финальный акцент
   Всё на общем --ea-ease, том же, что у обводки и у формы Sell your property.
   :has(:focus-visible) даёт ровно то же с клавиатуры. Именно focus-VISIBLE, а не
   :focus-within: после клика мышью по стрелке слайдера фокус остаётся на кнопке,
   и карточка залипала в ховер-состоянии (обводка и стрелки не гасли, даже когда
   курсор ушёл на соседнюю).
   ========================================================================== */

/* Фото на hover не наезжает: масштаб постоянный (см. --ph-scale выше) — это не
   эффект, а запас под поворот, чтобы ушедший край не обнажал угол кадра. */

/* Теги — всплытие каскадом + стекло становится плотнее и светлее */
.item-amenities li,
.labels-right .h-type {
  transition:
    transform 0.44s var(--ea-ease),
    box-shadow 0.44s var(--ea-ease),
    background-color 0.3s var(--ea-ease);
  will-change: transform;
}
.item-wrap:hover .item-amenities li,
.item-wrap:has(:focus-visible) .item-amenities li {
  transform: translateY(-4px);
  background-color: rgba(255, 251, 246, 0.78);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.95),
    inset 0 -1px 0 rgba(255,255,255,0.45),
    inset 0 0 0 1px var(--ea-glass-hairline),
    0 8px 22px rgba(60, 36, 18, 0.28);
}
/* Каскад: каждый следующий тег стартует на 45ms позже предыдущего */
.item-wrap:hover .item-amenities li:nth-child(1),
.item-wrap:has(:focus-visible) .item-amenities li:nth-child(1) { transition-delay: 0.04s; }
.item-wrap:hover .item-amenities li:nth-child(2),
.item-wrap:has(:focus-visible) .item-amenities li:nth-child(2) { transition-delay: 0.085s; }
.item-wrap:hover .item-amenities li:nth-child(3),
.item-wrap:has(:focus-visible) .item-amenities li:nth-child(3) { transition-delay: 0.13s; }
.item-wrap:hover .item-amenities li:nth-child(4),
.item-wrap:has(:focus-visible) .item-amenities li:nth-child(4) { transition-delay: 0.175s; }
/* Уход курсора — без каскада, всё возвращается разом: задержка на возврате
   читается как залипание. */
.item-amenities li { transition-delay: 0s; }

/* Тип объекта наверху — тот же отклик, но вниз (он у верхнего края) */
.item-wrap:hover .labels-right .h-type,
.item-wrap:has(:focus-visible) .labels-right .h-type {
  transform: translateY(2px);
  background-color: rgba(255, 251, 246, 0.78);
}

/* Статус сделки — лёгкий подъём и усиление белого канта */
.label-status { transition: transform 0.4s var(--ea-ease), box-shadow 0.4s var(--ea-ease); }
.item-wrap:hover .label-status,
.item-wrap:has(:focus-visible) .label-status {
  transform: translateY(2px);
  box-shadow:
    0 0 0 2px rgba(255,255,255,0.92),
    inset 0 1px 0 rgba(255,255,255,0.30),
    0 6px 18px rgba(190, 21, 27, 0.34);
}

/* Цена — финальный акцент волны. Масштаб от левого нижнего угла, чтобы
   число росло «из своего места» и не сдвигало соседей; font-size не трогаем,
   иначе перекладывается layout всей строки. */
.item-price {
  transform-origin: left bottom;
  transition: transform 0.46s var(--ea-ease), text-shadow 0.46s var(--ea-ease);
  will-change: transform;
}
.item-wrap:hover .item-price,
.item-wrap:has(:focus-visible) .item-price {
  transform: scale(1.055) translateY(-2px);
  transition-delay: 0.17s;
  text-shadow:
    0 1px 1px rgba(16, 8, 3, 0.60),
    0 3px 14px rgba(16, 8, 3, 0.60),
    0 10px 34px rgba(242, 105, 33, 0.28);
}
.item-price { transition-delay: 0s; }

/* Цена за м² — подтягивается за ценой, выходит из полутона в полный белый */
.item-sub-price {
  transition: transform 0.46s var(--ea-ease), color 0.34s var(--ea-ease);
}
.item-wrap:hover .item-sub-price,
.item-wrap:has(:focus-visible) .item-sub-price {
  transform: translateY(-2px);
  color: #fff;
  transition-delay: 0.2s;
}
.item-sub-price { transition-delay: 0s; }

/* Заголовок — только цвет: движение здесь спорило бы с ценой */
.item-wrap:hover .item-title a,
.item-wrap:has(:focus-visible) .item-title a { color: #ffe9d8; }

/* Огонёк на hover разгорается чуть ярче */
.item-wrap:hover .fb-hot__glow,
.item-wrap:has(:focus-visible) .fb-hot__glow { opacity: 1; transform: scale(1.15); }
.fb-hot__glow { transition: opacity 0.4s var(--ea-ease), transform 0.4s var(--ea-ease); }

@media (prefers-reduced-motion: reduce) {
  .item-wrap:hover .fb-photo img,
  .item-wrap:hover .item-amenities li,
  .item-wrap:hover .labels-right .h-type,
  .item-wrap:hover .label-status,
  .item-wrap:hover .item-price,
  .item-wrap:hover .item-sub-price,
  .item-wrap:hover .fb-hot__glow,
  .item-wrap:has(:focus-visible) .fb-photo img,
  .item-wrap:has(:focus-visible) .item-amenities li,
  .item-wrap:has(:focus-visible) .labels-right .h-type,
  .item-wrap:has(:focus-visible) .label-status,
  .item-wrap:has(:focus-visible) .item-price,
  .item-wrap:has(:focus-visible) .item-sub-price,
  .item-wrap:has(:focus-visible) .fb-hot__glow {
    transform: none !important;
    transition: none !important;
    transition-delay: 0s !important;
  }
  /* Кадр меняется мгновенно: JS всё равно снимет translate по таймеру. */
  .fb-photo img.is-sliding { transition: none !important; }
}

/* ==========================================================================
   ПЕРЕБИВКА ТЕМЫ.
   Лист грузится последним (узел view_data → Html.css в block 'customCss',
   realty/tm58887_index.json), но часть правил темы специфичнее одного класса
   (`.grid-view .item-wrap`, `.item-price-wrap .item-price`) либо задаёт то,
   чего в макете не было вовсе (макет жил без style.css темы: `.item-footer`
   padding, `.item-author` цвет, `white-space: nowrap` у заголовка).
   Поэтому селекторы здесь подняты префиксом `.item-listing-wrap` — 0-2-0,
   как у темы, но позже по порядку. !important не используется.
   ========================================================================== */

/* базовые наследуемые значения: в макете их давал body, здесь — корень карточки */
.item-listing-wrap .item-wrap {
  font-size: 16px; font-weight: 400; color: var(--ea-ink);
  border-radius: var(--ea-radius-card);
  /* горизонталь забирает свайп слайдера, вертикаль остаётся прокрутке страницы */
  touch-action: pan-y;
}
.item-listing-wrap .fb-photo { font-size: 16px; font-weight: 400; }
.item-listing-wrap .labels-wrap { position: static; font-size: 16px; font-weight: 400; color: var(--ea-ink); }
.item-listing-wrap .fb-hot { font-size: 16px; font-weight: 400; color: var(--ea-ink); }

.item-listing-wrap .item-title { white-space: normal; text-transform: none; }
.item-listing-wrap .item-address { white-space: nowrap; }
.item-listing-wrap .labels-right .h-type { white-space: normal; }

.item-listing-wrap .item-price { font-size: 30px; }
.item-listing-wrap .item-sub-price { font-size: 15px; }

.item-listing-wrap .item-amenities { font-size: 16px; font-weight: 400; color: var(--ea-ink); }

.item-listing-wrap .item-footer { padding: 0; border-radius: 0; font-weight: 400; }
.item-listing-wrap .fb-agent-link { font-weight: 400; }
.item-listing-wrap .item-author,
.item-listing-wrap .item-date { font-size: 13px; font-weight: 500; color: rgba(255, 255, 255, 0.86); line-height: 1.18; }

/* Флекс-раскладка подвала: цена по контенту, блок агента забирает остаток
   и прижимается вправо; имя усекается многоточием, а не ломает строку. */
.item-listing-wrap .item-price-wrap { flex: 0 0 auto; margin: 0; padding: 0; }
.item-listing-wrap .item-footer { flex: 1 1 auto; min-width: 0; }
.item-listing-wrap .fb-agent-link { flex: 1 1 auto; min-width: 0; justify-content: flex-end; }
.item-listing-wrap .item-author {
  display: block; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Тема вынимает подвал из потока: `.item-price-wrap{position:absolute;left:20px;bottom:20px}`
   (цена ложилась поверх тегов), `.item-footer{border-top:1px}` (белая линия над агентом),
   `.item-author{float:left}` / `.item-date{float:right}` (строка агента схлопывалась, имя
   обрезалось до «Vita…»). Возвращаем в поток — макет строит подвал на flex. */
.item-listing-wrap .item-price-wrap {
  position: static; left: auto; right: auto; top: auto; bottom: auto;
  z-index: auto; display: block;
}
/* `.grid-view .item-footer{width:100%}` растягивал подвал на всю строку — блок агента
   вылезал за правый край карточки (right 560 при 481). В макете подвал по контенту. */
.item-listing-wrap .item-footer { border: 0; width: auto; }
.item-listing-wrap .item-author,
.item-listing-wrap .item-date { float: none; }
/* тема бьёт селектором 0-3-0 (`.grid-view .item-footer .item-author{max-width:50%}`) */
.item-listing-wrap .item-footer .item-author { max-width: 100%; }

/* ==========================================================================
   СЛАЙДЕР СНИМКОВ
   Кадры лежат стопкой; видим только .is-current. Стрелки и счётчик появляются
   на ховере и держат z-index выше растянутой ссылки заголовка (z-index 4).
   ========================================================================== */
.fb-photo img { position: absolute; inset: 0; opacity: 0; }
.fb-photo img.is-current { opacity: 1; }
/* Кадры едут по горизонтали ОТДЕЛЬНЫМ свойством translate, а не transform:
   transform у той же картинки занят ховер-зумом и tilt'ом — слайд бы их стёр.
   .is-leaving держит уходящий кадр видимым, пока он не доехал до края. */
.fb-photo img.is-leaving { opacity: 1; }
/* Селектор с .item-wrap не для красоты: правило tilt'а (.item-wrap.is-tilting
   .fb-photo img) задаёт transition ЦЕЛИКОМ и при движущейся мыши затирало
   translate — слайд был виден только при неподвижном курсоре, то есть почти
   никогда. Здесь специфичность та же, но правило идёт ниже и выигрывает. */
.item-wrap .fb-photo img.is-sliding {
  transition: translate 0.42s var(--ea-ease);      /* transform ведёт rAF, анимировать его нельзя */
}

.fb-nav { position: absolute; inset: 0; z-index: 7; pointer-events: none; }
.fb-nav__btn {
  position: absolute; top: 50%; transform: translateY(-50%) scale(0.9);
  width: 44px; height: 44px; padding: 0; border: 1px solid var(--ea-glass-edge);
  border-radius: 50%; cursor: pointer;
  background: rgba(255, 251, 246, 0.58);
  backdrop-filter: blur(28px) saturate(200%) brightness(1.28);
  -webkit-backdrop-filter: blur(28px) saturate(200%) brightness(1.28);
  opacity: 0; pointer-events: none;
  transition: opacity 0.24s var(--ea-ease), transform 0.24s var(--ea-ease),
              background-color 0.2s var(--ea-ease);
}
.fb-nav__btn::before {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 10px; height: 10px; margin: -5px 0 0 -4px;
  border-right: 2px solid var(--ea-ink); border-bottom: 2px solid var(--ea-ink);
}
.fb-nav__btn--prev { left: 12px; }
.fb-nav__btn--prev::before { transform: rotate(135deg); margin-left: -6px; }
.fb-nav__btn--next { right: 12px; }
.fb-nav__btn--next::before { transform: rotate(-45deg); }
.fb-nav__btn:hover { background: rgba(255, 251, 246, 0.86); }
.fb-nav__btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }


.item-wrap:hover .fb-nav__btn,
.item-wrap:has(:focus-visible) .fb-nav__btn {
  opacity: 1; pointer-events: auto; transform: translateY(-50%) scale(1);
}

/* Лоадер на время подгрузки кадра */
.item-wrap.is-loading::before {
  content: ""; position: absolute; z-index: 8;
  top: 50%; left: 50%; width: 32px; height: 32px; margin: -16px 0 0 -16px;
  border: 2.5px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff; border-radius: 50%;
  animation: fb-spin 0.7s linear infinite;
}
@keyframes fb-spin { to { transform: rotate(360deg); } }

/* Пока кадр грузится, управление слайдером заблокировано: клики всё равно
   отбрасывались (флаг busy), но живые на вид кнопки читались как зависшие.
   pointer-events здесь НЕ снимаем: без них клик проваливается сквозь кнопку
   на ссылку карточки и повторное нажатие уводит на страницу объекта. Кнопка
   остаётся мишенью и молча съедает клик (обработчик слайдера). */
.item-wrap.is-loading .fb-nav__btn,
.item-wrap.is-loading .fb-dot {
  opacity: 0.45;
  cursor: wait;
}

/* Точки слайдера — счётчик кадров и переход к любому из них. Живут последним
   ребёнком .fb-foot, под строкой тегов: там есть свободное поле, а центр
   фото не загромождается. Появляются вместе со стрелками, чтобы в покое
   карточка оставалась чистой. */
.fb-dots {
  display: flex; justify-content: center; align-items: center; gap: 6px;
  margin: 8px 0 0;
  position: relative; z-index: 6;
  opacity: 0; pointer-events: none;
  transition: opacity 0.22s var(--ea-ease);
}
.fb-dot {
  width: 7px; height: 7px; padding: 0; border: 0; border-radius: 50%;
  background: rgba(255, 255, 255, 0.42);
  box-shadow: 0 1px 3px rgba(18, 10, 5, 0.45);
  cursor: pointer;
  transition: background 0.2s var(--ea-ease), width 0.2s var(--ea-ease);
}
.fb-dot.is-active { width: 18px; border-radius: 4px; background: #fff; }
.fb-dot:hover { background: rgba(255, 255, 255, 0.8); }
.fb-dot:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

.item-wrap:hover .fb-dots,
.item-wrap:has(:focus-visible) .fb-dots { opacity: 1; pointer-events: auto; }

/* На тач-экранах ховера нет — стрелки и точки показываем всегда */
@media (hover: none) {
  .fb-nav__btn { opacity: 1; pointer-events: auto; transform: translateY(-50%) scale(1); }
  .fb-dots { opacity: 1; pointer-events: auto; }
}

/* ==========================================================================
   ТУЛТИП СТРЕЛКИ ИЗМЕНЕНИЯ ЦЕНЫ
   Текст живёт в data-name (микроблочный whitelist атрибутов; title рендерер
   не пропускает). Без библиотеки: tippy на фронте не подключён, а поведение
   нужно ровно одно — показать строку. На тач-экранах ховера нет, поэтому
   элемент фокусируемый и подсказка держится на :focus (тап = фокус).
   ========================================================================== */
.fb-tip { position: relative; }
.fb-tip::after {
  content: attr(data-name);
  position: absolute; bottom: calc(100% + 9px); right: 0;
  z-index: 9;
  padding: 6px 10px; border-radius: 10px;
  font-size: 11.5px; font-weight: 600; line-height: 1.3; white-space: nowrap;
  color: var(--ea-ink); background: rgba(255, 251, 246, 0.94);
  border: 1px solid var(--ea-glass-edge);
  box-shadow: 0 8px 22px rgba(120, 72, 40, 0.26);
  opacity: 0; transform: translateY(4px); pointer-events: none;
  transition: opacity 0.18s var(--ea-ease), transform 0.18s var(--ea-ease);
}
/* хвостик — тот же цвет заливки, поэтому граница подсказки его не пересекает */
.fb-tip::before {
  content: ""; position: absolute; bottom: calc(100% + 4px); right: 12px;
  z-index: 10; width: 9px; height: 9px;
  background: rgba(255, 251, 246, 0.94);
  border-right: 1px solid var(--ea-glass-edge);
  border-bottom: 1px solid var(--ea-glass-edge);
  transform: rotate(45deg) translateY(4px);
  opacity: 0; pointer-events: none;
  transition: opacity 0.18s var(--ea-ease), transform 0.18s var(--ea-ease);
}
.fb-tip:hover::after, .fb-tip:focus-visible::after, .fb-tip:focus::after { opacity: 1; transform: translateY(0); }
.fb-tip:hover::before, .fb-tip:focus-visible::before, .fb-tip:focus::before { opacity: 1; transform: rotate(45deg) translateY(0); }
.fb-tip:focus { outline: none; }

/* ==========================================================================
   ПРАВАЯ КОЛОНКА ВЫДАЧИ — КАРТА
   Между колонками карточек 30px (padding ячеек 15 + 15), а до карты выходило
   15: колонка карты своего внутреннего отступа не имеет. Добиваем зазор до тех
   же 30 и приводим карту к геометрии карточек (радиус + скрытый оверфлоу).
   Высота — по экрану: карта прилипает под шапку нативным sticky (ниже).
   ========================================================================== */
#ya-map-block,
#map-list {
  border-radius: var(--ea-radius-card);
  overflow: hidden;
  box-shadow: var(--ea-shadow-rest);
  border: 1px solid var(--ea-line);
}
@media (min-width: 992px) {
  .cell-md-4 > #ya-map-block,
  .cell-md-4 > #map-list {
    margin-left: 15px;
    /* Нативный sticky вместо theia-sticky-sidebar: тот переключал колонку
       static <-> fixed из scroll-обработчика, и переключение отставало от
       прокрутки на кадр — видимый рывок в момент прилипания. Sticky считает
       композитор, JS на скролле не работает вовсе.
       76 = 64 (шапка в залипшем состоянии) + 12 (зазор); высота — по экрану
       минус шапка и оба зазора. */
    /* !important: скрипт карты пишет position: relative инлайном */
    position: sticky !important;
    top: 76px;
    height: calc(100vh - 64px - 24px) !important;
  }
}

/* Кнопка «в избранное» вне карточки (избранное, «мои объекты», страница агента):
   карточка своего места под неё не держит, поэтому слот кладёт звезду поверх угла. */
.fb-card-slot { position: relative; }
.fb-card-slot > .favorite-link {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 7;
  margin: 0;
}
