/* [PV-SKIN 05.08] ВИД ПРОСМОТРЩИКА. Пара к css/dr-pv-layout.css (там геометрия, здесь краска).
   ═══════════════════════════════════════════════════════════════════════════════════════════
   Файл НИКУДА НЕ ПОДКЛЮЧЁН, живой просмотрщик его не видит.

   Раздельно с раскладкой намеренно: за сутки 04–05.08 четыре раза чинили посадку хрома правкой
   его вида и наоборот. Пока это один файл, каждая правка цвета трогает геометрию.

   ЗАПОЛНЯЕТСЯ ПО ФАЗАМ. Сейчас готов уровень «главная» (фаза 2). Уровни «страница отзывов»
   и «галерея квартиры» — фазы 3 и 4, их секции ниже пустые. */

/* ═══ ОБЩИЙ ЯЗЫК ТРЁХ УРОВНЕЙ ════════════════════════════════════════════════════════════
   У них общие значки, типографика, 44px под палец и кривая движения — но НЕ раскладка
   (спецификация, раздел 1). Всё, что ниже, обязано работать на любом уровне. */

.pv__btn {
  display: grid;
  place-items: center;
  width: 44px;                    /* палец, а не 40 как у Airbnb: у нас это правило проекта */
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  color: hsl(var(--ink, 220 14% 8%));
  background: hsl(var(--color-surface, 36 16% 97%) / 0.97);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 140ms var(--ease-standard, ease), transform 140ms var(--ease-standard, ease);
}
.pv__btn svg { width: 20px; height: 20px; }
/* [ARROW-36 10.08] СТРЕЛКИ МЕЛЬЧЕ ОСТАЛЬНОГО ХРОМА — 36 вместо 44.
   Правило «44 под палец» остаётся в силе для всего, чего касаются пальцем, и крестик его
   сохраняет. Но стрелки живут ровно там, где пальца нет: они уже погашены на таче и на
   экране уже 1024 (правила ниже по файлу), то есть их нажимают исключительно мышью, а
   мышь не требует тап-цели.
   Замер живого Airbnb 09.08 (1440, чёрный кадр объявления): у него кнопка листания 32×32.
   Наши 44 рядом со снимком читались тяжело. 36 — середина: мельче нашего хрома, но не
   мельче их, и остаётся заметной на светлых снимках.
   Глиф уменьшаем пропорционально, 20 → 18: в 36-пиксельном круге прежний глиф съедал поле
   и круг переставал читаться круглым.
   ОТКАТ: удалить этот блок — вернутся 44 и 20. */
@media (hover: hover) and (min-width: 1024px) {
  .pv__btn.pv__on--left, .pv__btn.pv__on--right { width: 36px; height: 36px; }
  .pv__btn.pv__on--left svg, .pv__btn.pv__on--right svg { width: 18px; height: 18px; }
}
@media (hover: hover) { .pv__btn:hover { background: #fff; } }
.pv__btn:active { transform: scale(0.94); }
.pv__btn:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* Счётчик. Числа моноширинные — иначе «1 / 6» и «10 / 6» разной ширины, и таблетка дёргается
   при каждом свайпе. */
.pv__count {
  padding: 4px 12px;
  border-radius: 999px;
  background: rgba(34, 34, 34, 0.66);
  color: #fff;
  /* ⚠ ПОЙМАНО ВЛАДЕЛЬЦЕМ 08.08 НА СНИМКЕ ЭКРАНА: таблетка была раздавлена в 8px, цифры
     вылезали за подложку. Здесь стояла краткая запись `font: 500 var(--s-13,12px)/1.2
     var(--font-sans, inherit)`. Слово `inherit` внутри var() как запасное значение делает
     ВСЮ краткую запись недействительной при вычислении — а недействительная краткая запись
     сбрасывает и интерлиньяж тоже. Рамка задаёт `line-height: 0` (чтобы снимок не тащил
     лишние пиксели), таблетка его унаследовала, и высота строки стала нулевой.
     Правило на будущее: в краткой записи `font` не подставлять var() с `inherit` внутри —
     писать свойства по отдельности. Замер после правки: 51×26 при цифрах 17px. */
  font-weight: 500;
  font-size: var(--s-13, 13px);
  line-height: 1.25;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  pointer-events: none;           /* это подпись, а не контрол — палец сквозь неё закрывает слой */
}

/* Всплывающая строка ответа («ссылка скопирована»). Живёт на всех уровнях. */
.pv__toast {
  position: fixed;
  z-index: 5;
  left: 50%;
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  transform: translate(-50%, 8px);
  padding: 8px 16px;
  border-radius: 999px;
  background: rgba(24, 26, 30, 0.94);
  color: #fff;
  font-size: var(--s-13, 13px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 160ms var(--ease-standard, ease), transform 160ms var(--ease-standard, ease);
}
.pv__toast.is-on { opacity: 1; transform: translate(-50%, 0); }

@media (prefers-reduced-motion: reduce) {
  .pv__btn, .pv__toast { transition: none; }
}

/* ПЛАВАЮЩИЙ ХРОМ СТРАНИЦЫ УХОДИТ, ПОКА СЛОЙ ОТКРЫТ. Перенесено 09.08 из css/dr-photoviewer.css
   при подключении нового движка — правило старое и рабочее, теряться ему нельзя: шапка и нижний
   бар прибиты к экрану и иначе висели бы поверх затемнения, а на «главной» слой полупрозрачный,
   и сквозь него они читаются мусором. Класс тот же (`dr-pv-open`, ставит движок), поэтому
   страницам, которые уже на него ссылались, править нечего. */
.dr-pv-open .site-header,
.dr-pv-open .bottombar,
.dr-pv-open .mobile-bar { visibility: hidden; pointer-events: none; }

/* ВЫХОД БЕЗ ПРЫЖКА [12.08]. Метку `dr-pv-closing` движок держит два кадра при закрытии слоя.
   Зачем: пока слой открыт, хром только спрятан, а положение у него прежнее; на закрытии движок
   шапки пересчитывает состояние и УВОЗИТ её переходом на глазах у гостя — замер дал 0 → −64 за
   четырнадцать кадров, владелец назвал это «попрыгивает менюшка». Без перехода хром просто
   оказывается там, где ему положено.
   `transition: none` перечисляет разом все свойства — это то самое требование проекта
   «переопределяя переход в состоянии, перечисляй ВСЕ», выполненное самым коротким способом. */
.dr-pv-closing .site-header,
.dr-pv-closing .bottombar,
.dr-pv-closing .mobile-bar { transition: none !important; visibility: hidden; }

/* ═══ УРОВЕНЬ «ГЛАВНАЯ» — фаза 2 ═════════════════════════════════════════════════════════
   Спецификация, строка 1: просто фото поверх страницы · лёгкое затемнение 40% · закрыть
   кружком НА фото справа сверху · счётчик НА фото в правом низу · листание свайпом.

   ⚠ «ПОДЕЛИТЬСЯ» СНЯТО 08.08 — вердикт владельца, вариант 2 из двенадцати раскладок
   (стенд `_qa/pv-12-variantov-08-08.html`): «на маленьком снимке гостя делиться нечем».
   На кадре осталось ровно два предмета: крестик и счётчик. Не возвращать без нового слова.

   ⚠ ПОЛНЫЙ ЭКРАН ЗДЕСЬ ОТВЕРГНУТ ВЛАДЕЛЬЦЕМ ДОСЛОВНО: «человек хочет просто быстро глянуть
   фотку, красить весь экран незачем». Не возвращать ни фон во весь экран, ни панель отзыва:
   отзыв стоит прямо за слоем, пересказывать его поверх самого себя незачем. */

.pv--home {
  /* 40% — число из спецификации. Размытия НЕТ: оно съедает страницу под слоем, а весь смысл
     окна в том, что видно, откуда ты его открыл. */
  background: hsl(220 24% 8% / 0.40);
  --pv-inset: 12px;               /* отступ хрома от края снимка — замер Airbnb */
}

/* Тень отделяет светлый снимок от светлой страницы: без неё кадр на кремовой бумаге
   растворяется краями и перестаёт читаться отдельным предметом. */
.pv--home .pv__frame {
  box-shadow: 0 18px 48px -18px hsl(220 30% 12% / 0.55), 0 2px 8px hsl(220 30% 12% / 0.16);
  /* Заливка окна [10.08]. Видна там, где вписанный кадр не занял всю высоту, и в шве между
     соседями на свайпе. Это ТОТ ЖЕ цвет, что у затемнения страницы (`.pv--home` выше), только
     без прозрачности: поля читаются как сплошная тень вокруг снимка, а не как чужая полоса. */
  background: hsl(220 24% 8%);
}
.pv--home .pv__peek { background: hsl(220 24% 8%); }

/* Кадр — предмет, по которому ведут пальцем. Системное выделение и «сохранить картинку»
   долгим нажатием тут только мешают листанию. */
.pv--home .pv__img {
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

/* СТРЕЛКИ — ТОЛЬКО ТАМ, ГДЕ ЕСТЬ МЫШЬ, И ТОЛЬКО ЗА КАДРОМ (доведено 09.08).
   В спецификации листание записано одним словом — «свайп», и на телефоне так и есть: стрелок
   нет. Но на десктопе свайпа не существует, и без стрелок листать можно только клавишами —
   а про клавиши гость не знает. Поэтому стрелки живут ровно там, где нет пальца.
   ПЕРЕЗАМЕР 08.08 поправил ГДЕ им стоять: в полноэкранном кадре стрелки есть у всех трёх
   площадок, и у всех — ВНЕ снимка. Раньше наши лежали на фотографии; теперь они на затемнении,
   вплотную к кромке кадра (геометрия в `css/dr-pv-layout.css`, раздел 3).

   [ШИРИНА ТОЖЕ 09.08] Одного `hover:none` мало. Владелец прислал кадр из СУЖЕННОГО окна на
   маке: там мышь есть, правило молчит, и на 390 приезжают десктопные стрелки. Замер трёх сред
   подтвердил (`_qa/pv-strelki-tach-09-08.js`): 390 с тачем — стрелок нет, 390 с мышью — есть.
   Как у других: Airbnb на 390 отдаёт ДРУГОЙ экран целиком — белый «Фототур» секциями, без
   чёрного кадра и без стрелок; на 1440 с мышью — чёрный кадр, кружок ~32px за кадром, счётчик
   «1 / 41» сверху (кадры в `_qa/кадры-стрелки-09-08/`). То есть у них решает ШИРИНА, а не мышь.
   Порог 1024 — тот же, на котором стоит вся раскладка просмотрщика (`dr-pv-layout.css`).
   Booking боту страницу не отдал, Суточно глазами не сверен — на них не ссылаемся.
   ОТКАТ: убрать `, (max-width: 1023.98px)` из двух правил ниже. */
@media (hover: none), (max-width: 1023.98px) {
  .pv--home [data-pv="prev"], .pv--home [data-pv="next"] { display: none; }
}
/* Нажатие не должно стирать центровку: у боковых слотов transform уже занят. */
.pv__on--left:active  { transform: translateY(-50%) scale(0.94); }
.pv__on--right:active { transform: translateY(-50%) scale(0.94); }

/* ═══ УРОВЕНЬ «СТРАНИЦА ОТЗЫВОВ» — фаза 3 ════════════════════════════════════════════════
   Спецификация, строка 2: полный экран · фон ЧЁРНЫЙ · закрыть голым знаком в полосе сверху
   слева · счётчик в полосе по центру без подложки · свайп + зум · поделиться справа в полосе.

   ПОЧЕМУ ХРОМ УХОДИТ С КАДРА, а на главной сидит на нём. Правило Airbnb, снятое живьём 04.08,
   и оно же здравый смысл: владеешь фоном — убирай подложки и уводи хром с кадра; не владеешь —
   сажай хром на кадр с подложкой. На главной фон чужой (страница), поэтому кружок с заливкой.
   Здесь фон наш и чёрный — подкладывать не подо что, знаки читаются голыми.

   ЧЁРНЫЙ, А НЕ ПОЛУПРОЗРАЧНЫЙ. У живого просмотрщика тут 46% с размытием, и это компромисс
   от старой раскладки. Гость на странице отзывов пришёл смотреть — за кадром ему ничего не
   нужно, а чёрный честнее показывает цвет самой фотографии. */

.pv--full { background: #000; }

/* Голый знак в полосе: ни круга, ни заливки — только глиф. 44px под палец берём паддингом,
   поэтому визуально знак остаётся тихим, а зона нажатия полноразмерная. */
.pv__glyph {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: #fff;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 140ms var(--ease-standard, ease);
}
.pv__glyph svg { width: 22px; height: 22px; }
@media (hover: hover) { .pv__glyph:hover { opacity: 0.7; } }
.pv__glyph:active { opacity: 0.55; }
.pv__glyph:focus-visible { outline: 2px solid #fff; outline-offset: 2px; border-radius: 8px; }

/* Счётчик в полосе — белый текст без подложки. ⚠ У живого просмотрщика он серый и даёт
   контраст 2.1:1 при норме 4.5 (наш замер 05.08) — то есть его просто не видно. Белый на
   чёрном закрывает этот долг заодно. */
.pv__count--bare {
  padding: 0;
  border-radius: 0;
  background: none;
  color: #fff;
  font-size: var(--s-15, 15px);
  font-variant-numeric: tabular-nums;
}
.pv__count--bare[hidden] { display: none; }

/* Стрелки — та же логика, что на главной: мышь И ширина от 1024 (обоснование и замеры —
   у правила на главной выше по файлу). При увеличенном кадре они уходят: рука в этот момент
   двигает снимок, и стрелка под пальцем — ложная цель. */
@media (hover: none), (max-width: 1023.98px) {
  .pv--full [data-pv="prev"], .pv--full [data-pv="next"] { display: none; }
}
.pv.is-zoomed [data-pv="prev"], .pv.is-zoomed [data-pv="next"] { opacity: 0; pointer-events: none; }

/* Кадр без тени и без скругления: на чёрном отделять нечего, а скруглённый угол на
   полноэкранном снимке читается обрезкой кадра. */
.pv--full .pv__frame { box-shadow: none; }
.pv--full .pv__img {
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  touch-action: none;             /* жесты забирает зум, иначе браузер начнёт свою прокрутку */
}

/* ═══ ПОДПИСЬ ПОД СНИМКОМ (шторка отзыва) — перенесена 09.08 ══════════════════════════════
   Вид взят у прежней панели один в один: белый текст на чёрном разными тонами, ответ хозяев
   врезкой с полоской слева, площадка и адрес квартиры — ссылками. Геометрия в
   css/dr-pv-layout.css, раздел 7.

   ПОЧЕМУ ТОНАМИ, А НЕ ПОДЛОЖКАМИ. Фон здесь наш и чёрный (правило уровня «полный экран»):
   подкладывать не подо что, иерархию держит тон — оценка полная, подпись тише, текст между. */
.pv--note .pv__note { background: #000; }
.pv__note.is-open { background: #000; box-shadow: 0 -18px 40px -20px #000; }

/* Грабер — тот же, что у плиты меню: полоска 44×4, тянут за неё, а не за край. */
.pv__grab {
  flex: none; align-self: center;
  width: 100%; padding: 16px 0 12px;
  border: 0; background: none; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.pv__grab i {
  display: block; width: 44px; height: 4px; margin: 0 auto;
  border-radius: 999px; background: hsl(0 0% 100% / 0.55);
}
@media (hover: hover) { .pv__grab:hover i { background: hsl(0 0% 100% / 0.5); } }
.pv__grab:active i { background: hsl(0 0% 100% / 0.6); }
.pv__grab:focus-visible { outline: 2px solid #fff; outline-offset: -4px; border-radius: 8px; }

/* [КОМПОНОВКА 12.08] ИЕРАРХИЯ БЫЛА ПЕРЕВЁРНУТА. Замер: оценка шла 15px весом 600 чистым белым,
   а имя гостя — 13px обычного веса при 60% прозрачности. Площадка звучала громче человека, хотя
   снимок принадлежит человеку, и именно за ним гость сюда пришёл. Меняю их местами по громкости,
   не по размеру: оценка уходит в служебный тон, имя выходит вперёд. Кегли не трогаю — шкала
   проекта 13/15 остаётся, двигается только вес и прозрачность. */
.pv__note-rate {
  margin: 0 0 4px;
  display: flex; align-items: baseline; gap: 4px;
  color: hsl(0 0% 100% / 0.62); font-size: var(--s-13, 13px); font-weight: 400;
  font-variant-numeric: tabular-nums;
}
.pv__note-rate[hidden] { display: none; }
/* Само число лежит в `<b>` и берёт жирность от тега: правило выше на нём не сработало, замер
   показал вес 700 там, где заказан служебный тон. Гасим адресно, а не меняем разметку. */
.pv__note-num { font-weight: 500; }
.pv__note-star { color: var(--color-star, #E0A32E); margin-right: 4px; }
.pv__note-of { color: hsl(0 0% 100% / 0.6); font-weight: 400; }
.pv__note-plat { color: hsl(0 0% 100% / 0.62); font-weight: 400; }
/* [ТОЧКИ 12.08] Строка авторства без единого знака-разделителя: части разводит зазор и тон.
   Зазор 10px — вдвое шире обычного пробела на этом кегле, чтобы пауза читалась и без запятой,
   и вчетверо уже отступа между строками, чтобы строка не рассыпалась на три куска. */
.pv__note-cap {
  margin: 0 0 8px;
  display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 12px; row-gap: 4px;
  font-size: var(--s-15, 15px); font-weight: 600; color: hsl(0 0% 100% / 0.95);
}
.pv__note-who { color: #fff; }
.pv__note-when { font-weight: 400; color: hsl(0 0% 100% / 0.55); }

/* Ссылки в подписи: подчёркивание в покое — они стоят внутри текста, и по правилу проекта
   ссылка в тексте обязана быть видна ДО наведения. */
.pv__note-link {
  color: hsl(0 0% 100% / 0.86);
  text-decoration: underline;
  text-decoration-color: hsl(0 0% 100% / 0.4);
  text-underline-offset: 3px;
}
@media (hover: hover) { .pv__note-link:hover { color: #fff; text-decoration-color: hsl(0 0% 100% / 0.8); } }
.pv__note-arr { width: 11px; height: 11px; margin-left: 4px; vertical-align: -1px; stroke: currentColor; stroke-width: 2; }

.pv__note-text {
  margin: 0;
  font-size: var(--s-15, 15px); line-height: 1.55;
  color: hsl(0 0% 100% / 0.82);
}
/* Свёрнутая шторка — ровно ДВЕ строки и многоточие. Страховка поверх обрезки по слову в
   скрипте: у длинного слова или узкого экрана текст всё равно кончится целой строкой, а не
   срезом посередине. */
.pv__note:not(.is-open) .pv__note-text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Обрезанный текст обещает продолжение, поэтому он же и ведёт в ленту — палец на нём не зря. */
.pv.has-trim .pv__note-text { cursor: pointer; }
.pv.has-trim .pv__note-text:active { opacity: 0.72; }

.pv__note-reply {
  margin-top: 10px; padding-left: 12px;
  border-left: 2px solid hsl(0 0% 100% / 0.22);
}
.pv__note-reply[hidden] { display: none; }
.pv__note-reply-by {
  display: block; margin-bottom: 4px;
  font-size: var(--s-13, 13px); color: hsl(0 0% 100% / 0.55);
}
.pv__note-reply p { margin: 0; font-size: var(--s-15, 15px); line-height: 1.5; color: hsl(0 0% 100% / 0.8); }

/* Переход в ленту — единственная кнопка-действие в слое, поэтому она светлая и заметная.
   [КОМПОНОВКА 12.08] КНОПКА ВО ВСЮ ШИРИНУ БЛОКА, А НЕ ПО ЦЕНТРУ. Замер на 390: оценка, имя и
   текст стоят от левого края на 12, а кнопка стояла по центру, её левый край на 114. Один блок
   и две оси выравнивания — это и читается как «криво-косо» (вердикт владельца 12.08), хотя
   поля вокруг фотографии равны, по 56 сверху и снизу, и вины у них нет.
   Растянутая кнопка заодно даёт шторке основание: нижняя граница блока совпадает с левой и
   правой. Откат — вернуть `align-self: center` и убрать `stretch`. */
.pv__note-goto {
  flex: none; align-self: stretch;
  margin: 12px 0 4px; padding: 12px 16px;
  border: 0; border-radius: 999px;
  background: hsl(0 0% 100% / 0.94); color: hsl(var(--ink, 220 14% 8%));
  font-size: var(--s-13, 13px); font-weight: 600; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 140ms var(--ease-standard, ease), transform 140ms var(--ease-standard, ease);
}
@media (hover: hover) { .pv__note-goto:hover { background: #fff; } }
.pv__note-goto:active { transform: scale(0.97); }
.pv__note-goto:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) { .pv__note-goto { transition: none; } }

/* ═══ УРОВЕНЬ «ГАЛЕРЕЯ КВАРТИРЫ» — фаза 4 ═════════════════════════════════════════════════
   Спецификация, строка 3: сетка всех фото → тап → полный экран · сетка СВЕТЛАЯ, кадр чёрный ·
   закрыть шевроном слева сверху · счётчик только в полноэкранном · сетка листается вниз,
   кадр свайпом · поделиться справа в полосе.

   ⚠ ЭТОГО ШАГА НА САЙТЕ НЕТ ВООБЩЕ. Сегодня из галереи квартиры нельзя открыть отдельное фото —
   дефект не новый, он записан в замерах 05.08. Здесь он и закрывается: сетка это выбор, кадр
   это рассматривание, и одно ведёт в другое.

   ПОЧЕМУ СЕТКА СВЕТЛАЯ, А КАДР ЧЁРНЫЙ. Сетка — продолжение страницы, гость в ней ВЫБИРАЕТ;
   светлая бумага держит его в контексте квартиры. Кадр — рассматривание одной фотографии,
   и там чёрный убирает всё лишнее. То же различие, что у Airbnb, и та же логика, по которой
   на главной окно, а не полный экран. */

.pv--grid {
  background: hsl(var(--paper, 36 30% 97%));
  --pv-barh: 56px;
}
.pv--grid .pv__bar { background: hsl(var(--paper, 36 30% 97%)); }
/* В светлой полосе знаки чернильные, а не белые: на бумаге белое не читается. */
.pv--grid .pv__glyph { color: hsl(var(--ink, 220 14% 8%)); }
.pv--grid .pv__glyph:focus-visible { outline-color: hsl(var(--ink, 220 14% 8%)); }

.pv__grid { padding: 4px var(--pv-gx) calc(20px + env(safe-area-inset-bottom, 0px)); }
.pv__grid-in {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  margin: 0 auto;
  max-width: 1180px;
}
@media (min-width: 768px)  { .pv__grid-in { grid-template-columns: repeat(3, 1fr); gap: 12px; } }
@media (min-width: 1200px) { .pv__grid-in { grid-template-columns: repeat(4, 1fr); } }

/* Плитка = кнопка. Аспект 4:3 — тот же, что у карточек квартир на сайте с 17.07: ряд читается
   ровным, и ни один снимок не важнее соседа. */
.pv__tile {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  padding: 0;
  border: 0;
  border-radius: var(--radius-md, 14px);
  overflow: hidden;
  background: hsl(36 14% 88%);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.pv__tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pv__tile:active { transform: scale(0.985); }
@media (hover: hover) { .pv__tile:hover img { opacity: 0.92; } }
.pv__tile:focus-visible { outline: 2px solid hsl(var(--ink, 220 14% 8%)); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) { .pv__tile:active { transform: none; } }
