/* ============================================================================
   ELYQO · VenueCard — карточка салона в общей выдаче.
   Один файл на всю платформу: его подключают и витрина (index.html), и кабинет
   владельца (business.html) для предпросмотра. Правите здесь — меняется везде,
   предпросмотр в кабинете остаётся честным, а не «похожим».
   Палитра берётся из токенов страницы, а если их нет — из значений по умолчанию
   в var(..., fallback), поэтому карточка одинаково выглядит на обеих страницах.
   ============================================================================ */

/* Телефон: страница не ездит вбок.
   Найдено обходом кликами 26.09.2026 — после раскрытия фильтров на главной
   появлялась пустая горизонтальная прокрутка в 15 px. Настоящие
   горизонтальные ленты (категории, «ближайшее время») прокручиваются сами,
   у них свой overflow-x, и clip на body им не мешает. */
@media(max-width:720px){
  /* Именно html: полосой горизонтальной прокрутки страницы заведует
     documentElement, и clip на одном body её не убирает. */
  html,body{overflow-x:clip}
}

/* ======================================================================
     Размеры карточки салона — вся геометрия задаётся здесь, в одном месте.
     Меняете токен — меняются все карточки сразу, ничего не разъезжается:
     высота карточки считается из этих же значений через calc().
       --card-min-w      ширина колонки, от которой сетка решает, сколько карточек в ряд
       --card-gap        расстояние между карточками
       --card-banner-h   высота обложки
       --card-*-rows     сколько строк отведено блоку (заголовок, теги, слоты…)
     Готовые пресеты: <body data-card-size="s|m|l">, либо elyqoCardSize('s').
     ====================================================================== */
  :root{
    --card-min-w:300px;
    --card-max-w:1fr;
    --card-gap:20px;

    --card-banner-h:158px;
    --card-pad-x:16px;
    --card-pad-t:14px;
    --card-pad-b:16px;
    --card-row-gap:7px;

    --card-title-fs:16px;
    --card-title-lh:1.28;
    --card-title-lines:2;
  }
  /* Пресеты оставлены: ими пользуется кабинет (elyqoCardSize) и запомненный
     выбор в localStorage (index-app.js:12-31). Высоту они больше не считают —
     только ширину колонки, обложку и воздух. */
  body[data-card-size="s"]{ --card-min-w:252px; --card-gap:16px; --card-banner-h:128px; --card-title-lines:1 }
  body[data-card-size="l"]{ --card-min-w:352px; --card-gap:24px; --card-banner-h:192px;
    --card-pad-x:18px; --card-pad-t:16px; --card-pad-b:18px; --card-row-gap:8px }

  /* ---- VenueCard ---- */
  .card{position:relative;background:#FFFFFF;border:1px solid #ECEBF2;border-radius:var(--r-card,20px);overflow:hidden;
    box-shadow:var(--sh-card,0 8px 30px rgba(40,35,90,.06));display:flex;flex-direction:column;transition:transform .14s ease,box-shadow .14s ease,border-color .14s ease;
    scroll-margin-top:150px;cursor:pointer}
  /* Наведение — ТОЛЬКО там, где есть курсор. На телефоне незакрытый :hover
     съедал первое касание: палец «наводил» карточку, она подпрыгивала, а
     нажатие не срабатывало — открывалось со второго раза. То же било и по
     кольцу сторис: оно внутри карточки. Жалоба 28.10. */
  @media(hover:hover){
    .card:hover{transform:translateY(-3px);border-color:#E0DAF6;box-shadow:0 16px 40px rgba(70,55,160,.10)}
  }
  .card:focus-within{border-color:var(--elyqo-violet,#5B4CFF);box-shadow:0 0 0 2px var(--elyqo-violet,#5B4CFF),var(--sh-md,0 8px 28px rgba(32,28,70,.07))}
  .card.is-active{border-color:var(--elyqo-violet,#5B4CFF);box-shadow:0 0 0 1.5px var(--elyqo-violet,#5B4CFF),var(--sh-md,0 8px 28px rgba(32,28,70,.07))}
  .banner{height:var(--card-banner-h);flex:0 0 var(--card-banner-h);position:relative;overflow:hidden;
    display:flex;align-items:flex-end;padding:12px}
  .banner .art{position:absolute;inset:0}
  /* лёгкая «точечная» фактура поверх фирменного градиента; на фото-обложке
     кабинет отключает её через --art-dots:none */
  /* Точки поверх баннера живут только на ЗАГЛУШКАХ: настоящая обложка
     гасит их через --art-dots:none (data.js · bannerArtCSS, обе ветки).
     Но mix-blend-mode:overlay гасился не вместе с ними, и на карточке с
     настоящим снимком оставался слой смешивания, которому нечего смешивать.
     Любое значение, кроме normal, заставляет браузер завести под элемент
     отдельный проход композитора — а здесь он ещё и внутри скруглённого
     overflow:hidden. Замер на проде: 24 из 24 карточек на экране несли
     пустой слой (--art-dots:none, background-image:none, overlay).
     Теперь режим смешивания гасится тем же местом, что и сами точки. */
  .banner .art::after{content:"";position:absolute;inset:0;
    background-image:var(--art-dots,radial-gradient(rgba(255,255,255,.10) 1px,transparent 1.4px));
    background-size:15px 15px;mix-blend-mode:var(--art-blend,overlay)}
  .banner .motif{position:absolute;top:-14px;right:-14px;width:128px;height:128px;color:#fff;opacity:.16}
  .banner .scrim{position:absolute;left:0;right:0;bottom:0;height:62%;background:linear-gradient(to top,rgba(10,8,30,.34),transparent)}
  /* Фирменная заглушка вместо фото (mascots.js): персонаж вертикали крупным
     планом на градиенте категории — голова у верхней кромки, корпус уходит под
     нижнюю. Затемнение низа тут слабее, чем на фото: под ним не текст, а сам
     персонаж, но белым логотипу и «Verified» нужна хоть какая-то подложка. */
  .banner.fb .scrim{height:52%;background:linear-gradient(to top,rgba(10,8,30,.20),transparent)}
  /* мастер теперь фигура целиком, а не верхние 80 %, поэтому кадр выше
     прежнего в 1/0.8 раза: поясной план в карточке от этого не меняется */
  .banner .elq-mascot{--elq-mascot-h:147%;--elq-mascot-t:3%}
  /* компактный пресет: баннер ниже, персонажу оставляем ту же голову */
  body[data-card-size="s"] .banner .elq-mascot{--elq-mascot-h:155%}
  body[data-card-size="l"] .banner .elq-mascot{--elq-mascot-h:142%}
  .logo-badge{position:relative;width:46px;height:46px;border-radius:13px;background:#FFFFFF;border:2px solid rgba(255,255,255,.9);
    display:grid;place-items:center;font-weight:800;font-size:16px;color:var(--elyqo-text,#111224);box-shadow:0 6px 18px rgba(20,16,50,.28);
    overflow:hidden}
  .logo-badge img{display:block;width:100%;height:100%;object-fit:cover}
  /* ---------- метка сторис на плитке логотипа (ТЗ «Stories» §3.4) ----------
     Кольцо добавляется СНАРУЖИ: логотип остаётся 46 px, плитка становится
     56 px. Движение здесь короче, чем на карточке бизнеса: там кольцо одно
     на экран и зовёт три раза, а в ленте карточек двадцать — зовущие разом
     кольца читались бы как рябь. Поэтому волна проходит ОДИН раз, у соседей
     со сдвигом (--st-delay), и дальше обод просто горит. */
  .st-cat{position:relative;display:block;width:max-content;border-radius:20px;z-index:2;
    color:inherit;text-decoration:none;-webkit-tap-highlight-color:transparent}
  a.st-cat{cursor:pointer}
  @media(hover:hover){ a.st-cat:hover .st-pad{transform:scale(1.03)} }
  .st-cat .st-pad{transition:transform .16s ease}
  a.st-cat:focus-visible{outline:2px solid #5B4CFF;outline-offset:3px}
  .st-cat::before{content:"";position:absolute;inset:0;border-radius:20px;
    background:conic-gradient(from 160deg,
      #5B4CFF 0deg,#7B55FF 48deg,#9C5CFF 96deg,#C94FE4 144deg,#F05DC7 196deg,
      #FF7E9D 244deg,#FF9A6C 292deg,#C94FE4 330deg,#5B4CFF 360deg)}
  .st-cat.seen::before{background:#D8D4E6}
  .st-cat .st-pad{position:relative;z-index:1;display:block;margin:3px;padding:2px;
    border-radius:17px;background:#fff}
  .st-cat .logo-badge{border-width:0;box-shadow:none}
  .st-cat .st-wave{position:absolute;inset:0;border-radius:20px;pointer-events:none}
  .st-cat:not(.seen) .st-wave::before,.st-cat:not(.seen) .st-wave::after{content:"";
    position:absolute;inset:0;border-radius:20px;border:2px solid rgba(201,79,228,.6);opacity:0;
    animation:st-cat-wave 2.6s cubic-bezier(.16,.84,.44,1) 1;animation-delay:var(--st-delay,0s)}
  .st-cat:not(.seen) .st-wave::after{border-color:rgba(91,76,255,.5);
    animation-delay:calc(var(--st-delay,0s) + .34s)}
  @keyframes st-cat-wave{
    0%{transform:scale(1);opacity:.8}
    34%{transform:scale(1.42);opacity:0}
    100%{transform:scale(1.42);opacity:0}
  }
  /* Слово — состояние «есть непросмотренное», а не анимация: стоит, пока
     кадры не посмотрели. Всплывает один раз, чтобы не возникать ниоткуда. */
  .st-cat .st-word{position:absolute;left:50%;bottom:-9px;transform:translateX(-50%);z-index:4;
    font-size:9.5px;font-weight:700;letter-spacing:.03em;white-space:nowrap;pointer-events:none;
    padding:2.5px 8px;border-radius:999px;color:#fff;
    background:linear-gradient(92deg,#5B4CFF,#F05DC7);box-shadow:0 4px 12px -5px rgba(91,76,255,.9);
    /* Сдвиг --st-delay сюда НЕ идёт: он для волны, а слово — состояние.
       С ним карточка в середине ленты показывала обод сразу, а подпись
       через пару секунд, будто догоняла. */
    animation:st-cat-word .42s cubic-bezier(.2,.8,.3,1) both}
  @keyframes st-cat-word{
    from{opacity:0;transform:translate(-50%,6px) scale(.92)}
    to{opacity:1;transform:translate(-50%,0) scale(1)}
  }
  @media(prefers-reduced-motion:reduce){
    /* Зов убираем, слово оставляем: это надпись, а не движение. */
    .st-cat .st-wave::before,.st-cat .st-wave::after{display:none}
    .st-cat .st-word{animation:none}
  }

  .tagband{position:absolute;top:10px;left:10px;display:flex;gap:6px;flex-wrap:wrap;max-width:75%}
  .rib{font-size:10.5px;font-weight:800;letter-spacing:.03em;padding:4px 9px;border-radius:999px;text-transform:uppercase;color:#fff;
    background:rgba(10,8,30,.5);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
  .rib.promo{background:var(--accent,#E0603F)}.rib.editors{background:#C98A5A}.rib.popular{background:#5B4CFF}.rib.newbiz{background:#745CFF}
  .fav{position:absolute;top:10px;right:10px;width:34px;height:34px;border-radius:50%;border:1px solid rgba(255,255,255,.5);
    background:rgba(255,255,255,.85);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);display:grid;place-items:center;color:var(--elyqo-muted,#9697AA);box-shadow:var(--sh-base,0 4px 16px rgba(32,28,70,.05));z-index:3}
  .fav.on{color:var(--accent,#E0603F);border-color:var(--accent,#E0603F)}
  @media(hover:hover){
    .fav:hover{color:var(--accent,#E0603F);border-color:var(--accent,#E0603F)}
  }
  .verified{position:absolute;right:10px;bottom:10px;background:rgba(255,255,255,.9);backdrop-filter:blur(6px);border:1px solid var(--elyqo-border,#E8E2FF);
    color:#4636C4;font-size:11px;font-weight:800;padding:4px 9px 4px 7px;border-radius:999px;display:flex;align-items:center;gap:4px}
  .card-body{padding:var(--card-pad-t) var(--card-pad-x) var(--card-pad-b);
    display:flex;flex-direction:column;gap:var(--card-row-gap);flex:1;min-width:0}
  /* Имя занимает ДВЕ строки всегда — и когда их две, и когда одна. Без этого
     карточка с длинным названием выше соседки, а в сетке стоит
     align-items:start (index.html:382) и ряд не выравнивается. Резерв дешевле
     растяжки: он держит одинаковый рост и между рядами, а не только внутри. */
  .card h3{font-size:var(--card-title-fs);letter-spacing:-.014em;line-height:var(--card-title-lh);font-weight:650;
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:var(--card-title-lines);overflow:hidden;
    min-height:calc(var(--card-title-lines) * var(--card-title-lh) * var(--card-title-fs))}
  /* печать проверенного бизнеса переехала с обложки к имени: на снимке она
     отъедала угол, а нужна ровно тогда, когда читают название */
  .card h3 .ver{display:inline-block;width:14px;height:14px;vertical-align:-2px;margin-left:5px;color:#3B82D9}
  .meta{display:flex;align-items:center;gap:7px;font-size:12.5px;line-height:19px;
    color:var(--elyqo-muted,#9697AA);flex-wrap:wrap}
  .rating{display:flex;align-items:center;gap:3px;font-weight:700;color:var(--elyqo-text,#111224)}
  .rating svg{color:var(--star,#E8A100)}
  /* чипы (категория, «Otwarte», языки, оплата) с карточки сняты 28.10 */
  /* цена, вилка и кружки мастеров с карточки сняты 28.10; .rating и .price ниже оставлены — ими держится всплывашка карты (index-app.js:982-983) и шапка салона */
  /* цитата отзыва мертва с 14.09.2026 (b.review=null у всех) */
  /* окна времени и подвал с кнопкой сняты 28.10: карточка ничего не бронирует */


  /* ══════════════════════════════════════════════════════════════════════
     Карточка-справка (28.10.2026): снимок, имя с печатью, оценка, адрес.
     ══════════════════════════════════════════════════════════════════════ */

  /* ── оценка ───────────────────────────────────────────────────────────
     Своей строкой под именем, прижата влево — так читается как часть блока
     имени. Справа, одна посреди пустой строки, она выглядела висящей.
     Строка всегда одна и не переносится, поэтому оценка стоит на одной
     высоте во всех карточках ряда; рядом с именем она скакала бы, имя берёт
     то одну строку, то две.
     Звезда #BD8200, а не фирменная --star #E8A100: подписи «Ocena» рядом
     нет, звезда осталась единственной приметой, что это оценка, — значит
     обязана быть видна. Замер: #E8A100 на белом даёт 2,20:1 и порога 3:1
     для знака не берёт, #BD8200 — 3,30:1, самый светлый золотой, который берёт. */
  .card .rate{display:flex;align-items:center;gap:5px;margin-top:1px}
  .card .rate svg{width:14px;height:14px;flex:none;color:#BD8200}
  .card .rate b{font-size:14px;font-weight:700;letter-spacing:-.015em;color:var(--elyqo-text,#111224);line-height:1;
    font-variant-numeric:tabular-nums}

  /* ── адрес: район · расстояние · улица ────────────────────────────────
     Разделители нарисованы через ::before на самих подписях, а не вставлены
     в текст: расстояние перерисовывается на месте (geo.js меняет содержимое
     .dist), и разделитель-сосед остался бы висеть точкой в пустоте.
     Пока геопозиции нет, .dist пуст — и точка перед ним не рождается. */
  .card .addr{display:flex;align-items:flex-start;gap:9px;font-size:13px;line-height:1.4;
    color:var(--elyqo-text-secondary,#6B6C82);min-width:0}
  /* .addr-pin, а НЕ .pin: класс .pin занят булавками карты (index.html:407) —
     они белые, круглые и абсолютные, и значок адреса унаследовал всё это,
     превратившись в белый овал поверх оценки. Жалоба 28.10. */
  .card .addr .addr-pin{width:15px;height:15px;flex:none;color:var(--elyqo-muted,#8A8B9C);margin-top:1px}
  /* адрес — тоже ровно две строки, по той же причине */
  .card .addr .addr-t{min-width:0;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;
    min-height:calc(2 * 1.4 * 13px)}
  .card .addr .dist:empty{display:none}
  .card .addr .addr-s:empty{display:none}
  .card .addr .dist::before,.card .addr .addr-s::before{content:" · ";color:#C9C9D6}
  .card .addr .dist{font-weight:650;color:var(--elyqo-text-secondary,#6B6C82)}

  /* Карусель обложки снята 28.10: карточка показывает один снимок всё время.
     Вместе с ней ушли слои кадров, точки и пять наборов keyframes. */

  /* узкий экран: карточка во всю ширину */
  @media (max-width:900px){
    /* карточка во всю ширину: сужаем только колонку и обложку — число строк
       оставляем прежним, иначе теги и слоты не помещаются и обрезаются */
    :root{--card-min-w:100%;--card-gap:14px;--card-banner-h:172px}
  }
  /* touch targets ≥44px на мобильном (§23 ТЗ): избранное и «Записаться» —
     единственные изолированные тапы на карточке, остальное — плотные ряды чипов */
  @media (max-width:767px){
    .fav{width:40px;height:40px}
  }

  /* На телефоне карточка занимала 527 px при экране 844 — на первый экран
     помещалась одна с хвостиком, и каталог читался как лента по одному салону.
     Ужимаем не содержимое, а воздух: обложка ниже на 18 px, поля и промежутки
     плотнее, слоты умещаются в одну строку — подпись «Ближайшее:» на телефоне
     не нужна, три чипа со временем и так понятны. Карточка 447 px: на экран
     заходит почти две. Ничего не спрятано и не обрезано — проверено на 360,
     390 и 430 px. */
  @media (max-width:767px){
    :root{
      /* 51.5vw − 20px ≈ ширина карточки ÷ 1.94 — та же пропорция, что в
         браузере и в предпросмотре кабинета (замер 21.09.2026) */
      --card-banner-h:calc(51.5vw - 20px);
      --card-pad-t:12px; --card-pad-b:12px; --card-row-gap:6px;
    }
  }

