/* ============================================================
   Фича «Отзывы» — карточка review-card (full/teaser) и общие
   стили для страницы отзывов /o-klinike/otzyvy/. Разметка —
   xslt/modules/catalog/review-card.xsl. 08.2026.
   ============================================================ */

/* ---------- Полная карточка (список на странице специалиста
   и на странице отзывов) — плитка на подложке #f1f3ee, ровно
   один отзыв в строке независимо от контейнера-списка. ---------- */
.review-card--full {
    display: block;
    width: 100%;
    box-sizing: border-box;
    background: #f1f3ee;
    border-radius: 12px;
    padding: 18px 20px;
    font-family: 'Inter', -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
    color: #1f241f;
}

.review-card__meta {
    margin: 0 0 8px;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px 10px;
}

.review-card__author {
    font-size: 15px;
    font-weight: 700;
    color: #1f241f;
    /* Ссылка на страницу отзыва теперь на имени автора (клиент), но
       оформление не должно выглядеть как ссылка — явно сбрасываем
       браузерные дефолты <a> (подчёркивание, курсор не трогаем, он и
       так pointer у <a>). */
    text-decoration: none;
}
a.review-card__author:hover,
a.review-card__author:focus-visible {
    color: #1f241f;
    text-decoration: none;
}
a.review-card__author:focus-visible {
    outline: 3px solid rgba(110, 156, 63, 0.5);
    outline-offset: 2px;
}

.review-card__date {
    font-size: 13px;
    color: #6d7368;
}

.review-card__text {
    margin: 0;
    font-size: 15px;
    line-height: 1.55;
    color: #40463e;
    /* Текст отзыва приходит из PHP уже плоским (strip_tags), но с
       сохранёнными переводами строк между абзацами (см. решение по
       переносам в отчёте) — без HTML-тегов и без disable-output-escaping.
       pre-line превращает эти \n в настоящие переносы строк, схлопывая
       при этом лишние пробелы внутри строки (как normal) — то, что нужно
       для многоабзацного отзыва. Клэмп ниже (.review-card__text--clamp,
       max-height: 6.2em) режет по пиксельной высоте вне зависимости от
       того, где пришлась граница строки — форсированный перенос просто
       занимает свою долю бюджета в 4 строки, как обычный перенос по словам. */
    white-space: pre-line;
}

/* Кламп ровно 4 строки через max-height (не -webkit-line-clamp —
   он не анимируется и не даёт места под градиент-затухание из
   UI-драфта). 6.2em = 4 строки * line-height 1.55 (.review-card__text);
   em относительно font-size элемента, поэтому при увеличении шрифта
   на мобильном (см. медиа-запрос ниже) те же 6.2em остаются ровно
   4 строками без отдельного переопределения.
   transition — на раскрытие: JS (review-card-clamp.js) выставляет
   inline max-height в scrollHeight и снимает клэмп после анимации.
   Без поддержки max-height/transition в очень старых браузерах текст
   просто не обрезается — осознанная деградация, текст всё равно есть
   в DOM целиком. Совсем без JS клэмп снимается целиком — правило в
   <noscript> в head-base-part (layouts/includes.xsl): иначе кнопку
   раскрытия некому показать и часть текста была бы недоступна. */
.review-card__text--clamp {
    position: relative;
    overflow: hidden;
    max-height: 6.2em;
    transition: max-height 0.25s ease;
}

/* Тот же паттерн, что у .sp-btn в css/specialists-cards.css: пользователю,
   который попросил меньше движения, раскрытие показываем сразу, без
   анимации высоты. JS это переживает — у него есть фолбэк-таймер на случай,
   если transitionend не долетит (review-card-clamp.js, finish()). */
@media (prefers-reduced-motion: reduce) {
    .review-card__text--clamp { transition: none; }
}

/* Градиентное затухание последней строки в цвет подложки карточки —
   вместо многоточия. Показываем только когда JS подтвердил реальную
   обрезку (класс --truncated от review-card-clamp.js), иначе у
   короткого отзыва под текстом была бы паразитная плашка на пустом
   месте. */
.review-card__text--clamp.review-card__text--truncated::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 32px;
    background: linear-gradient(rgba(241, 243, 238, 0), rgba(241, 243, 238, 1));
    pointer-events: none;
}

/* «Показать целиком» — это <button>, сбрасываем нативные стили
   и делаем визуально жирной кликабельной ссылкой. */
.review-card__expand {
    position: relative; /* якорь для тап-зоны на мобильном, см. ::after ниже */
    display: inline-block;
    margin: 8px 0 0;
    padding: 0;
    border: 0;
    background: none;
    font-family: inherit;
    font-size: 14px;
    font-weight: 700;
    color: #6e9c3f;
    text-decoration: underline;
    cursor: pointer;
}
.review-card__expand:hover { color: #5f8836; }
.review-card__expand:focus-visible { outline: 3px solid rgba(110, 156, 63, 0.5); outline-offset: 2px; }
/* атрибут hidden — подстраховка для старых браузеров без
   дефолтового user-agent правила [hidden] { display: none } */
.review-card__expand[hidden] { display: none; }

/* Ссылка на площадку-источник — в одной строке с датой (клиент), а не
   отдельной строкой внизу карточки; цвет чёрный, а не серый. */
.review-card__source {
    font-size: 13px;
    font-weight: 600;
    color: #1f241f;
    text-decoration: none;
}
.review-card__source:hover { text-decoration: underline; }
.review-card__source:focus-visible { outline: 3px solid rgba(110, 156, 63, 0.5); outline-offset: 2px; }

/* ---------- Teaser (цитата в карточке специалиста) — карточка
   целиком кликабельна (сам review-card--teaser это <a>), без
   подложки. Кламп общий с полной карточкой — 4 строки. ---------- */
.review-card--teaser {
    display: flex;
    flex-direction: column;
    gap: 6px;
    text-decoration: none;
    color: inherit;
    font-family: 'Inter', -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
}
.review-card--teaser:hover { text-decoration: none; }
.review-card--teaser:hover .review-card__author { color: #6e9c3f; }
.review-card--teaser:focus-visible { outline: 3px solid rgba(110, 156, 63, 0.5); outline-offset: 2px; }

.review-card--teaser .review-card__author { color: #1f241f; }

.review-card--teaser .review-card__text {
    margin: 0;
    font-size: 14px;
    line-height: 1.5;
    color: #40463e;
}
/* line-height teaser'а (1.5) отличается от полной карточки (1.55) —
   пересчитываем max-height под свои 4 строки: 4 * 1.5 = 6em. */
.review-card--teaser .review-card__text--clamp { max-height: 6em; }
/* У teaser'а нет собственной подложки (карточка специалиста может стоять на
   любом фоне) — правильный цвет градиента отсюда неизвестен. Единственный
   потребитель тизера, карточка специалиста (modules/catalog/category-view.xsl),
   подмешивает свой класс .sp-card__quote-clamp и рисует градиент в цвет своей
   плашки сам (css/specialists-cards.css). Соответственно и модификатор
   обрезки review-card-clamp.js ставит там свой — sp-card__quote-clamp--truncated,
   а не review-card__text--truncated, так что глушить здесь ::after нечего:
   правило .review-card--teaser .review-card__text--truncated::after ни на чём
   не срабатывало и удалено. */

/* ---------- Список отзывов — один отзыв в строке ---------- */
.reviews-list {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

/* «Показать ещё отзывы» под списком на /o-klinike/otzyvy/
   (js-reviews-more, см. reviews-list-reveal.js) — тот же визуальный
   паттерн, что и у .sp-reviews__more (specialists-cards.css) для
   одноимённого действия на странице специалиста: паддинг 14px даёт
   тап-зону ~47px без отдельного мобильного переопределения. */
/* margin-bottom добавлен (клиент: «отступ снизу») — раньше блок вплотную
   упирался в следующий элемент страницы. */
.js-reviews-more-wrap { margin: 24px 0 32px; text-align: center; }

.js-reviews-more {
    display: inline-block;
    padding: 14px 28px;
    border: 0;
    border-radius: 8px;
    box-shadow: inset 0 0 0 1.5px #c9cec5;
    background: #fff;
    /* Явный сан-сериф вместо font-family: inherit (клиент: «шрифт без
       засечек») — у <button> в некоторых браузерах свой дефолтный шрифт
       формы, а не унаследованный от .post/.text. */
    font-family: 'Inter', -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
    font-size: 16px;
    font-weight: 600;
    color: #1f241f;
    cursor: pointer;
}
.js-reviews-more:hover { box-shadow: inset 0 0 0 1.5px #6e9c3f; color: #6e9c3f; }
.js-reviews-more:focus-visible { outline: 3px solid rgba(110, 156, 63, 0.5); outline-offset: 2px; }

/* Состояние загрузки очередной AJAX-порции (aria-busy ставит
   reviews-list-reveal.js на время запроса) — курсор и приглушение вместо
   исчезновения кнопки, чтобы не дёргать раскладку. */
.js-reviews-more[aria-busy="true"] { opacity: .65; cursor: wait; }

/* Сеть/сервер недоступны — кнопка не пропадает молча, а явно предлагает
   повторить (reviews-list-reveal.js меняет текст и вешает этот класс). */
.js-reviews-more.js-reviews-more--error {
    box-shadow: inset 0 0 0 1.5px #c0392b;
    color: #c0392b;
}
.js-reviews-more.js-reviews-more--error:hover { box-shadow: inset 0 0 0 1.5px #a93226; color: #a93226; }

@media (max-width: 767px) {
    .review-card--full { padding: 16px 18px; }
    .review-card__text { font-size: 16px; }
    .review-card--teaser .review-card__text { font-size: 15px; }
    .review-card__author { font-size: 16px; }
    .review-card__date { font-size: 14px; }
    .review-card__expand { font-size: 15px; }

    /* Тап-зона «Показать целиком» ≥44px без изменения видимого размера
       кнопки: невидимый расширитель через ::after, position: absolute
       не участвует в потоке — соседние элементы не сдвигаются. Кнопка
       сама остаётся 20-22px, как в утверждённом дизайне. */
    .review-card__expand::after {
        content: '';
        position: absolute;
        top: 50%;
        left: -8px;
        right: -8px;
        min-height: 44px;
        transform: translateY(-50%);
    }
}

/* ---------- Страница отзывов (layouts/reviews.xsl) и отдельная страница
   отзыва (layouts/review.xsl) — обе используют обёртку .testimonials-all.
   ---------- */

/* H1 и вводный текст шрифтом Inter (клиент) — по умолчанию h1 страницы
   на museo_sans_cyrl500, а .post p на Pragmatica-Book (main.css). Селектор
   .testimonials-all .text заодно накрывает и <p class="text"> на странице
   отдельного отзыва («Отзыв о враче…», «Ко всем отзывам») — та же просьба
   про шрифт без засечек, см. review-specialist-note ниже. */
.testimonials-all h1,
.testimonials-all .text,
.testimonials-all .text p {
    font-family: 'Inter', -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
}

/* Блок рейтинга партнёров на странице отзывов (без модификатора --footer,
   см. css/rating-partners.css) — тень уже убрана общим правилом, здесь
   только равномерный отступ сверху/снизу (клиент): 40px снизу — столько
   же, сколько .testimonials-all .text даёт сверху за счёт своего
   padding-bottom. Выравнивание по левому краю не трогаем — оно и так
   flex-start по умолчанию. */
.testimonials-all .rating-partners {
    margin: 0 0 40px;
}

/* Строка «Отзыв о враче: …» на отдельной странице отзыва — отступ сверху
   (клиент), шрифт без засечек уже даёт правило .testimonials-all .text
   выше. */
.review-specialist-note {
    margin-top: 20px;
}

/* Область объявлений о догрузке для скринридеров (создаёт
   reviews-list-reveal.js). Именно clip-техника, а не display: none /
   visibility: hidden: скрытые этими способами live-области скринридеры
   не читают. Ср. .visually-hidden-seo в css/additional.css — тот же приём
   для SEO-H1. */
.js-reviews-status {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
