/* ============================================================
   YAZME ПЕРСОНЫ · БАЗОВЫЕ КОМПОНЕНТЫ · ревизия 2026-08-b
   Все значения — из tokens.css, а тот выведен из темы сайта (--yz-*).
   Глубину даёт связка «поверхность + тень темы»: в тёмных темах работает
   светлота (s0 → s5), в светлой «Cloud Dancer» — тень, иначе белая карточка
   на светлом фоне не читается вовсе.

   Правила ревизии:
   1. Каждый интерактивный элемент имеет 6 состояний:
      default / :hover(только hover-устройства) / :active / :focus-visible /
      [disabled] / [data-loading].
   2. Хит-зона любого интерактивного элемента ≥ 44×44 (SC 2.5.5).
      Если визуально меньше — добираем .pv-hit (::after, inset отрицательный).
   3. touch-action:manipulation везде — убирает 300ms double-tap-zoom.
   4. Движение: позиция/размер — пружина (--e-spring), прозрачность/цвет —
      --e-effect. Смешивать нельзя: мигающая прозрачность с отскоком = баг.
   ============================================================ */

/* ---------- базис ---------- */
.pv-body{
  margin:0; min-height:100dvh;
  background:var(--s0); color:var(--t1);
  font-family:var(--f-ui); font-size:var(--fs-body); line-height:var(--lh-body);
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
  -webkit-text-size-adjust:100%; text-size-adjust:100%;
}
/* ============================================================
   ГРАНИЦЫ ВНУТРЬ

   По умолчанию width не включает отступы и рамку. Из-за этого width:100%
   у кнопки с padding давало ширину БОЛЬШЕ контейнера: «Поговорить» вылезала
   из карточки на 22px, а на телефоне — за край экрана. В коде это чинили
   точечно (.pv-btn.wide, поля ввода, карточки колоды) — то есть каждый раз,
   когда натыкались. Правило одно на весь раздел, чтобы не натыкаться больше.
   ============================================================ */
*, *::before, *::after{ box-sizing:border-box; }

.pv-shell{ max-width:var(--col); margin:0 auto; padding:0 var(--sp4); }
/* Широкая колонка — для страниц с раскладкой в две колонки (витрина, профиль).
   Класс .wide в разметке стоял, а правила под него не было вовсе: профиль
   пытался разложить сетку «содержимое + действия» внутри 660px, и левая
   колонка сжималась до 290px — имя переносилось по слогам. */
.pv-shell.wide{ max-width:var(--wide); }
.pv-hidden{ display:none !important; }
a.pv-plain{ color:inherit; text-decoration:none; }
.pv-hair-top{ border-top:1px solid var(--hair); }

/* якорь прокрутки не должен уезжать под липкую шапку/подвал (SC 2.4.11) */
html{ scroll-padding-top:calc(var(--ctl-lg) + var(--sat)); scroll-padding-bottom:var(--sp8); }

/* один общий сброс для всего кликабельного */
.pv-btn, .pv-iconbtn, .pv-seg button, .pv-chip, .pv-act, .pv-switch,
.pv-tab, .pv-sheet-close, .pv-toast-act{
  touch-action:manipulation;
  -webkit-tap-highlight-color:transparent;
  user-select:none; -webkit-user-select:none;
  font-family:var(--f-ui);
}

/* единое фокус-кольцо. :focus-visible, а не :focus — иначе кольцо ловится пальцем */
.pv-btn:focus-visible, .pv-iconbtn:focus-visible, .pv-seg button:focus-visible,
.pv-chip:focus-visible, .pv-act:focus-visible, .pv-switch:focus-visible,
.pv-input:focus-visible, .pv-tab:focus-visible, a.pv-plain:focus-visible,
.pv-sheet-close:focus-visible, .pv-toast-act:focus-visible, [data-focusring]:focus-visible{
  outline:var(--focus-w) solid var(--focus);
  outline-offset:var(--focus-off);
  border-radius:var(--r-sm);
}
.pv-input:focus-visible{ border-radius:var(--r-md); }
.pv-btn:focus-visible, .pv-iconbtn:focus-visible, .pv-chip:focus-visible{ border-radius:var(--r-full); }

/* расширитель хит-зоны: визуально элемент маленький, палец попадает в 44px */
.pv-hit{ position:relative; }
.pv-hit::after{
  content:''; position:absolute; left:50%; top:50%;
  width:max(100%, var(--ctl)); height:max(100%, var(--ctl));
  transform:translate(-50%, -50%);
}

/* ---------- типографика ---------- */
.pv-over{
  font:600 var(--fs-over)/1 var(--f-display); letter-spacing:var(--ls-over);
  text-transform:uppercase; color:var(--t3);
}
/* Заголовки и имена — Source Serif 4 (сайт уже его использует).
   Unbounded оставлен там, где он силён: надзаголовки капсом и числа. */
.pv-hero-title{
  font:700 var(--fs-hero)/var(--lh-tight) var(--f-serif);
  color:var(--t1); margin:0; text-wrap:balance;
}
.pv-title{
  font:600 var(--fs-title)/var(--lh-tight) var(--f-serif);
  color:var(--t1); margin:0; text-wrap:balance;
}
.pv-dim{ color:var(--t2); }
.pv-faint{ color:var(--t3); }
.pv-small{ font-size:var(--fs-small); }
.pv-hand{ font:500 var(--fs-hand)/1.3 var(--f-hand); color:var(--t2); }
.pv-num{ font-family:var(--f-num); font-weight:600; font-variant-numeric:tabular-nums; }
.pv-prose{ text-wrap:pretty; }

/* только для скринридера */
.pv-sr{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

/* ---------- кнопки ---------- */
.pv-btn{
  position:relative;
  display:inline-flex; align-items:center; justify-content:center; gap:var(--sp2);
  min-height:var(--ctl); padding:0 var(--sp5);
  border:0; border-radius:var(--r-full); cursor:pointer;
  background:var(--hero); color:var(--on-hero);
  font:600 var(--fs-body)/1 var(--f-ui);
  transition:transform var(--d-micro) var(--e-spring-soft),
             opacity var(--d-micro) var(--e-effect),
             background var(--d-micro) var(--e-effect),
             filter var(--d-micro) var(--e-effect);
  text-decoration:none; white-space:nowrap;
}
@media (hover:hover){
  .pv-btn:hover:not(:disabled):not([data-loading]){ filter:brightness(1.08); }
}
.pv-btn:active:not(:disabled):not([data-loading]){ transform:scale(.97); filter:brightness(1.14); }
/* Свечение — только у главной кнопки экрана. На сетке из пяти карточек
   пять светящихся кнопок превращаются в кашу. */
.pv-btn.lg:not(.ghost):not(.line):not(.quiet):not(.soft):not(.danger){ box-shadow:var(--sh-hero); }
.pv-btn.lg{ min-height:var(--ctl-lg); padding:0 var(--sp7); font-size:var(--fs-body); }
.pv-btn.sm{ min-height:var(--ctl); padding:0 var(--sp4); font-size:var(--fs-small); }
.pv-btn.ghost{ background:var(--s3); color:var(--t1); }
.pv-btn.soft{ background:var(--hero-lo); color:var(--t1); border:1px solid var(--hair2); }
.pv-btn.line{ background:transparent; color:var(--t2); border:1px solid var(--hair2); }
.pv-btn.quiet{ background:transparent; color:var(--t2); }
.pv-btn.danger{ background:transparent; color:var(--lose); border:1px solid var(--hair2); }
.pv-btn.wide{ width:100%; }
.pv-btn .pv-ic{ flex:none; }

/* disabled: контраст ≥3:1 сохраняем, серую кашу не делаем */
.pv-btn:disabled, .pv-btn[aria-disabled="true"]{
  opacity:.45; cursor:not-allowed; transform:none; filter:none;
}

/* loading: ширина НЕ схлопывается (иначе CLS), лейбл прячется visibility */
.pv-btn[data-loading]{ cursor:progress; color:transparent; }
.pv-btn[data-loading] > *{ visibility:hidden; }
.pv-btn[data-loading]::after{
  content:''; position:absolute; left:50%; top:50%;
  width:18px; height:18px; margin:-9px 0 0 -9px;
  border:2px solid currentColor; border-top-color:transparent;
  border-radius:var(--r-full);
  color:var(--on-hero);
  animation:pvSpin 640ms linear infinite;
  visibility:visible;
}
.pv-btn.ghost[data-loading]::after,
.pv-btn.line[data-loading]::after,
.pv-btn.quiet[data-loading]::after,
.pv-btn.soft[data-loading]::after{ color:var(--t1); }
@keyframes pvSpin{ to{ transform:rotate(360deg); } }

/* pvBusy применяется не только к .pv-btn (например, к чипу «Особый ход» и к
   текстовым ссылкам-кнопкам). Универсальный запасной вид: без него нажатие
   выглядело полностью проигнорированным, пока идёт запрос. */
[data-loading]:not(.pv-btn){ opacity:.5; cursor:progress; pointer-events:none; }
button:disabled:not(.pv-btn):not(.swb):not(.pv-iconbtn){ opacity:.5; cursor:not-allowed; }

/* иконочная кнопка */
.pv-iconbtn{
  width:var(--ctl); height:var(--ctl); flex:none;
  display:grid; place-items:center;
  border:0; border-radius:var(--r-full); cursor:pointer;
  background:transparent; color:var(--t2);
  transition:transform var(--d-micro) var(--e-spring-soft),
             background var(--d-micro) var(--e-effect),
             color var(--d-micro) var(--e-effect);
}
@media (hover:hover){ .pv-iconbtn:hover:not(:disabled){ background:var(--s2); color:var(--t1); } }
.pv-iconbtn:active:not(:disabled){ transform:scale(.92); }
.pv-iconbtn.solid{ background:var(--s3); color:var(--t1); }
/* Золотая — только для награды (кубок Язми Спора). Цвет из общего токена
   сайта: своё значение в светлой теме даст жёлтое пятно вместо золота. */
.pv-iconbtn.gold{
  color:var(--mark);
  background:
    radial-gradient(circle at 50% 28%, color-mix(in srgb, var(--mark) 22%, transparent), transparent 72%),
    var(--s3);
  box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--mark) 34%, transparent);
}
@media (hover:hover){ .pv-iconbtn.gold:hover:not(:disabled){ color:var(--mark); background:
    radial-gradient(circle at 50% 28%, color-mix(in srgb, var(--mark) 30%, transparent), transparent 72%),
    var(--s3); } }
.pv-iconbtn.on{ background:var(--hero-lo); color:var(--hero); }
.pv-iconbtn:disabled{ opacity:.4; cursor:not-allowed; }

/* ---------- иконки ---------- */
.pv-ic{ width:20px; height:20px; display:block; }
.pv-ic.sm{ width:16px; height:16px; }
.pv-ic.lg{ width:24px; height:24px; }

/* ---------- карточка ---------- */
.pv-card{
  background:var(--s2); border:1px solid var(--hair);
  border-radius:var(--r-md); padding:var(--sp5);
  box-shadow:var(--sh-sm);
}
.pv-card.deep{ background:var(--s1); box-shadow:none; }
.pv-card.raised{ background:var(--s3); }
.pv-card.flat{ background:transparent; }

/* ---------- монограмма ---------- */
.pv-mono{
  width:var(--mono); height:var(--mono); flex:none;
  display:grid; place-items:center;
  background:var(--s3); border:1px solid var(--hair2);
  border-radius:var(--r-full);
  font-family:var(--f-serif); font-weight:700; color:var(--t1);
  font-size:calc(var(--mono) * .42);
  overflow:hidden; user-select:none;
}
.pv-mono.own{ border-color:var(--hero); }
.pv-mono.lg{ width:var(--mono-lg); height:var(--mono-lg); font-size:calc(var(--mono-lg) * .42); }
.pv-mono.sm{ width:var(--mono-sm); height:var(--mono-sm); font-size:calc(var(--mono-sm) * .46); }
.pv-mono img{ width:100%; height:100%; object-fit:cover; display:block; }

/* ---------- сегмент-переключатель ---------- */
.pv-seg{
  display:inline-flex; gap:var(--sp1); padding:var(--sp1);
  background:var(--s1); border:1px solid var(--hair);
  border-radius:var(--r-full);
}
.pv-seg button{
  position:relative;
  border:0; cursor:pointer; background:transparent; color:var(--t2);
  min-height:var(--ctl-vis);
  padding:0 var(--sp4); border-radius:var(--r-full);
  font:600 var(--fs-small)/1 var(--f-ui);
  display:inline-flex; align-items:center; justify-content:center; gap:var(--sp2);
  transition:transform var(--d-micro) var(--e-spring-soft),
             background var(--d-micro) var(--e-effect),
             color var(--d-micro) var(--e-effect);
}
/* хит-зона сегмента добирается до 44px, визуально он остаётся 36px */
.pv-seg button::after{
  content:''; position:absolute; left:0; right:0; top:50%;
  height:var(--ctl); transform:translateY(-50%);
}
.pv-seg button:active{ transform:scale(.96); }
.pv-seg button.on, .pv-seg button[aria-selected="true"]{ background:var(--s4); color:var(--t1); }

/* ---------- чип ---------- */
.pv-chip{
  position:relative;
  display:inline-flex; align-items:center; gap:var(--sp2);
  min-height:var(--ctl-vis); padding:0 var(--sp4);
  border-radius:var(--r-full); cursor:pointer;
  background:var(--s2); border:1px solid var(--hair); color:var(--t2);
  font:600 var(--fs-small)/1 var(--f-ui);
  transition:transform var(--d-micro) var(--e-spring-soft),
             background var(--d-micro) var(--e-effect),
             color var(--d-micro) var(--e-effect),
             border-color var(--d-micro) var(--e-effect);
}
.pv-chip::after{
  content:''; position:absolute; left:0; right:0; top:50%;
  height:var(--ctl); transform:translateY(-50%);
}
@media (hover:hover){ .pv-chip:hover{ border-color:var(--hair2); color:var(--t1); } }
.pv-chip:active{ transform:scale(.96); }
.pv-chip.on, .pv-chip[aria-pressed="true"]{ background:var(--s4); border-color:var(--hair3); color:var(--t1); }

/* некликабельная метка-тег (в карточке персоны) */
.pv-tag{
  display:inline-flex; align-items:center;
  padding:0 var(--sp3); min-height:var(--sp6);
  border-radius:var(--r-full); background:var(--s3); border:1px solid var(--hair);
  color:var(--t2); font:600 var(--fs-over)/1 var(--f-ui);
  letter-spacing:var(--ls-over); text-transform:uppercase; white-space:nowrap;
}
.pv-tag.hero{ background:var(--hero-lo); border-color:var(--hero); color:var(--hero); }
.pv-tag.mark{ color:var(--mark); border-color:var(--hair2); }

/* ---------- переключатель (настоящий switch, а не кнопка «Вкл») ---------- */
.pv-switch{
  position:relative; flex:none;
  width:52px; height:var(--ctl-vis);
  border-radius:var(--r-full); border:1px solid var(--hair2);
  background:var(--s1); cursor:pointer; padding:0;
  transition:background var(--d-std) var(--e-effect), border-color var(--d-std) var(--e-effect);
}
.pv-switch::before{
  content:''; position:absolute; top:50%; left:3px;
  width:calc(var(--ctl-vis) - 8px); height:calc(var(--ctl-vis) - 8px);
  border-radius:var(--r-full); background:var(--t2);
  transform:translateY(-50%);
  transition:transform var(--d-std) var(--e-spring), background var(--d-std) var(--e-effect);
}
.pv-switch::after{
  content:''; position:absolute; left:0; right:0; top:50%;
  height:var(--ctl); transform:translateY(-50%);
}
.pv-switch[aria-checked="true"]{ background:var(--hero); border-color:var(--hero); }
.pv-switch[aria-checked="true"]::before{
  background:var(--on-hero);
  /* ход = ширина − размер кнопки − отступы с обеих сторон:
     52 − (--ctl-vis − 8) − 6. Раньше кнопка не доезжала до края
     и «включено» читалось как «где-то посередине». */
  transform:translateY(-50%) translateX(calc(52px - var(--ctl-vis) + 2px));
}
.pv-switch:disabled{ opacity:.45; cursor:not-allowed; }

/* ---------- шкала (близость, память, лимит) ---------- */
.pv-bar{
  height:var(--sp2); border-radius:var(--r-full);
  background:var(--s3); overflow:hidden;
}
.pv-bar > i{
  display:block; height:100%; width:0;
  background:var(--hero); border-radius:var(--r-full);
  transition:width var(--d-spring) var(--e-spring);
}
.pv-bar.mark > i{ background:var(--mark); }
.pv-bar.warn > i{ background:var(--lose); }

/* ---------- верхняя панель ---------- */
.pv-top{
  position:sticky; top:0; z-index:40;
  display:flex; align-items:center; gap:var(--sp2);
  min-height:var(--ctl-lg);
  padding:var(--sp2) var(--sp3);
  padding-top:calc(var(--sp2) + var(--sat));
  padding-left:calc(var(--sp3) + var(--sal));
  padding-right:calc(var(--sp3) + var(--sar));
  background:var(--s0);
  border-bottom:1px solid var(--hair);
}
.pv-top .grow{ flex:1; min-width:0; }
.pv-top-name{
  font:700 var(--fs-body)/var(--lh-tight) var(--f-serif);
  color:var(--t1); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.pv-top-sub{
  font-size:var(--fs-over); letter-spacing:var(--ls-over); text-transform:uppercase; color:var(--t3);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
/* полупрозрачная шапка — только там, где под ней реально что-то скроллится */
.pv-top.glass{ background:var(--glass); }
@supports (backdrop-filter: blur(1px)){
  .pv-top.glass{ backdrop-filter:blur(16px) saturate(140%); -webkit-backdrop-filter:blur(16px) saturate(140%); }
}
@media (prefers-reduced-transparency: reduce){
  .pv-top.glass{ background:var(--s0); backdrop-filter:none; -webkit-backdrop-filter:none; }
}

/* ---------- поля ввода ---------- */
.pv-input{
  width:100%; box-sizing:border-box;
  min-height:var(--ctl);
  background:var(--s1); border:1px solid var(--hair2);
  border-radius:var(--r-md); color:var(--t1);
  /* 16px минимум, иначе iOS зумит при фокусе — считаем от --fs-body */
  font:400 max(16px, var(--fs-body))/var(--lh-body) var(--f-ui);
  padding:var(--sp3) var(--sp4); outline:none; resize:none;
  transition:border-color var(--d-micro) var(--e-effect);
}
.pv-input::placeholder{ color:var(--t3); }
.pv-input:focus{ border-color:var(--hero); }
.pv-input:disabled{ opacity:.5; }
.pv-input[aria-invalid="true"]{ border-color:var(--lose); }
.pv-label{
  display:block; margin:0 0 var(--sp2);
  font:600 var(--fs-over)/1 var(--f-ui); letter-spacing:var(--ls-over);
  text-transform:uppercase; color:var(--t3);
}
.pv-field{ margin-bottom:var(--sp5); }
.pv-hint{ margin-top:var(--sp2); font-size:var(--fs-small); color:var(--t3); }
.pv-hint.err{ color:var(--lose); }
/* счётчик символов в углу поля */
.pv-count{
  display:block; margin-top:var(--sp1); text-align:right;
  font:600 var(--fs-over)/1 var(--f-num); color:var(--t3);
}
.pv-count.near{ color:var(--mark); }
.pv-count.over{ color:var(--lose); }

/* ---------- строки списков ---------- */
.pv-row{
  display:flex; align-items:center; gap:var(--sp3);
  padding:var(--sp3) 0;
}
.pv-row + .pv-row{ border-top:1px solid var(--hair); }
.pv-row .grow{ flex:1; min-width:0; }

/* ---------- инлайн-плашка (лимит, ошибка, апселл) ---------- */
.pv-banner{
  display:flex; gap:var(--sp3); align-items:flex-start;
  padding:var(--sp4); margin:var(--sp4) 0;
  background:var(--s1); border:1px solid var(--hair2); border-radius:var(--r-md);
}
.pv-banner .pv-ic{ flex:none; margin-top:2px; color:var(--t3); }
.pv-banner .grow{ flex:1; min-width:0; }
.pv-banner b{ display:block; font:600 var(--fs-body)/1.3 var(--f-ui); color:var(--t1); margin-bottom:var(--sp1); }
.pv-banner p{ margin:0; color:var(--t2); font-size:var(--fs-small); line-height:var(--lh-body); }
.pv-banner .pv-btn{ margin-top:var(--sp3); }
.pv-banner.mark{ border-color:var(--mark); background:color-mix(in srgb, var(--mark) 8%, var(--s1)); }
.pv-banner.mark .pv-ic{ color:var(--mark); }
.pv-banner.err{ border-color:var(--lose); background:color-mix(in srgb, var(--lose) 8%, var(--s1)); }
.pv-banner.err .pv-ic{ color:var(--lose); }

/* ---------- шторка ---------- */
.pv-veil{
  position:fixed; inset:0; z-index:80;
  background:var(--overlay); opacity:0; pointer-events:none;
  transition:opacity var(--d-exit-sheet) var(--e-effect);
}
.pv-veil.show{ opacity:1; pointer-events:auto; transition-duration:var(--d-sheet); }
.pv-sheet{
  position:fixed; left:0; right:0; bottom:0; z-index:90;
  max-width:var(--col); margin:0 auto;
  background:var(--s2); border:1px solid var(--hair2); border-bottom:0;
  box-shadow:var(--sh-lg);
  border-radius:var(--r-md) var(--r-md) 0 0;
  padding:var(--sp2) var(--sp5) calc(var(--sp5) + var(--sab));
  padding-bottom:calc(var(--sp5) + max(var(--sab), var(--kb)));
  transform:translateY(101%);
  /* visibility снимаем ПОСЛЕ анимации ухода, иначе шторка исчезает мгновенно
     и уезжания вниз никто не видит */
  transition:transform var(--d-exit-sheet) var(--e-in),
             visibility 0s linear var(--d-exit-sheet);
  /* клавиатура не должна прятать содержимое шторки */
  max-height:calc(88dvh - var(--kb));
  overflow:auto; overscroll-behavior:contain;
  visibility:hidden;
}
.pv-sheet.show{
  transform:translateY(0); visibility:visible;
  transition:transform var(--d-sheet) var(--e-spring-soft), visibility 0s;
}
/* ручка: видимая 36×4, касаемая — 44 по высоте (SC 2.5.5 + альтернатива драгу — SC 2.5.7) */
.pv-sheet-grip{
  position:relative;
  width:var(--sp7); height:var(--sp1); border-radius:var(--r-full);
  background:var(--hair3); margin:var(--sp2) auto var(--sp4);
}
.pv-sheet-grip::after{
  content:''; position:absolute; left:-40px; right:-40px; top:50%;
  height:var(--ctl); transform:translateY(-50%);
}
.pv-sheet-head{
  display:flex; align-items:center; gap:var(--sp3);
  margin-bottom:var(--sp4);
}
.pv-sheet-head .grow{ flex:1; min-width:0; }
.pv-sheet-close{
  width:var(--ctl); height:var(--ctl); flex:none;
  display:grid; place-items:center; border:0; border-radius:var(--r-full);
  background:var(--s3); color:var(--t2); cursor:pointer;
}
.pv-sheet-close:active{ transform:scale(.92); }

/* ---------- диалог подтверждения (замена window.confirm) ---------- */
.pv-dialog{
  position:fixed; left:50%; top:50%; z-index:95;
  width:min(calc(100vw - var(--sp8)), calc(var(--col) * .66));
  transform:translate(-50%, -50%) scale(.94);
  background:var(--s2); border:1px solid var(--hair2); border-radius:var(--r-md);
  padding:var(--sp6); box-shadow:var(--sh-lg);
  opacity:0; visibility:hidden;
  transition:opacity var(--d-exit-std) var(--e-effect),
             transform var(--d-exit-std) var(--e-in),
             visibility 0s linear var(--d-exit-std);
}
.pv-dialog.show{
  opacity:1; visibility:visible; transform:translate(-50%, -50%) scale(1);
  transition:opacity var(--d-std) var(--e-effect),
             transform var(--d-std) var(--e-spring-soft),
             visibility 0s;
}
.pv-dialog h3{ margin:0 0 var(--sp3); font:700 var(--fs-title)/var(--lh-tight) var(--f-serif); color:var(--t1); }
.pv-dialog p{ margin:0 0 var(--sp5); color:var(--t2); font-size:var(--fs-small); line-height:var(--lh-body); text-wrap:pretty; }
/* «Отмена» — заметная, деструктив — тихая рамка. Разнос ≥ sp4, чтобы не промахнуться */
.pv-dialog-acts{ display:flex; flex-direction:column; gap:var(--sp3); }
.pv-dialog-acts .pv-btn{ width:100%; }

/* ---------- отказ модерации ----------
   Отказ длиннее подтверждения: причина, что делать и основание. Поэтому
   окно шире, текст крупнее обычного диалогового (его читают, а не
   пробегают), а на низком экране содержимое прокручивается — иначе кнопки
   уезжают за край и выхода из окна не видно вовсе. */
.pv-dialog.refuse{
  width:min(calc(100vw - var(--sp6)), calc(var(--col) * .92));
  max-height:calc(100dvh - var(--sp8)); overflow-y:auto;
}
.pv-dialog.refuse p#pvDlgD{ font-size:var(--fs-body); color:var(--t1); margin-bottom:var(--sp4); }
/* Подсказка — единственная строка, ради которой человек остаётся: выделяем
   её плашкой, а не курсивом, чтобы не потерялась под основным текстом. */
.pv-refuse-hint{
  margin:0 0 var(--sp4); padding:var(--sp3) var(--sp4);
  background:var(--s3); border-radius:var(--r-sm);
  color:var(--t1); font-size:var(--fs-small); line-height:var(--lh-body);
  text-wrap:pretty;
}
.pv-refuse-law{ margin:0 0 var(--sp5); color:var(--t3); font-size:var(--fs-small); }

/* ---------- появление блоков ---------- */
.pv-enter{ opacity:0; transform:scale(.96); }
.pv-enter.in{
  opacity:1; transform:scale(1);
  transition:opacity var(--d-std) var(--e-effect), transform var(--d-spring) var(--e-spring);
}
.pv-rise{ opacity:0; transform:translateY(var(--sp3)); }
.pv-rise.in{
  opacity:1; transform:translateY(0);
  transition:opacity var(--d-std) var(--e-effect), transform var(--d-spring) var(--e-spring);
}

/* ---------- скелет ---------- */
.pv-skel{
  background:var(--s1); border-radius:var(--r-md);
  position:relative; overflow:hidden;
}
.pv-skel::after{
  content:''; position:absolute; inset:0;
  background:linear-gradient(90deg, transparent, var(--hair), transparent);
  transform:translateX(-100%);
  animation:pvShimmer 1400ms var(--e-out) infinite;
}
@keyframes pvShimmer{ to{ transform:translateX(100%); } }
.pv-skel.line{ height:var(--sp4); border-radius:var(--r-full); }
.pv-skel.line + .pv-skel.line{ margin-top:var(--sp2); }

/* ---------- достижения (единственное место для --mark) ---------- */
.pv-mark{ color:var(--mark); }

/* ---------- тосты ---------- */
.pv-toast{
  position:fixed; left:50%; bottom:calc(var(--sp8) + var(--sab));
  z-index:100; transform:translateX(-50%) translateY(var(--sp3)); opacity:0; pointer-events:none;
  display:flex; align-items:center; gap:var(--sp3);
  background:var(--s5); color:var(--t1); border:1px solid var(--hair2);
  box-shadow:var(--sh-lg);
  border-radius:var(--r-full); padding:var(--sp3) var(--sp3) var(--sp3) var(--sp5);
  font:600 var(--fs-small)/1.3 var(--f-ui); max-width:min(82vw, var(--col));
  transition:opacity var(--d-exit-std) var(--e-effect), transform var(--d-exit-std) var(--e-in);
}
.pv-toast.show{
  opacity:1; transform:translateX(-50%) translateY(0); pointer-events:auto;
  transition:opacity var(--d-std) var(--e-effect), transform var(--d-std) var(--e-spring-soft);
}
.pv-toast > span{ min-width:0; }
.pv-toast-act{
  flex:none; min-height:var(--ctl-vis); padding:0 var(--sp4);
  border:0; border-radius:var(--r-full); cursor:pointer;
  background:var(--hero); color:var(--on-hero);
  font:700 var(--fs-over)/1 var(--f-ui); letter-spacing:var(--ls-over); text-transform:uppercase;
}
.pv-toast-act:active{ transform:scale(.94); }
.pv-toast:not(:has(.pv-toast-act)){ padding-right:var(--sp5); }

/* ---------- пустое состояние ---------- */
.pv-empty{ text-align:center; padding:var(--sp7) var(--sp4); }
.pv-empty .pv-ic{ width:32px; height:32px; margin:0 auto var(--sp4); color:var(--t3); }
.pv-empty p{ margin:0 0 var(--sp3); color:var(--t2); text-wrap:pretty; }

/* ---------- reduced motion ----------
   Не «отключить всё», а «убрать перемещение, оставить fade». */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
  .pv-enter, .pv-rise{ opacity:1; transform:none; }
  .pv-btn:active, .pv-iconbtn:active, .pv-seg button:active,
  .pv-chip:active, .pv-toast-act:active, .pv-sheet-close:active{ transform:none; }
  .pv-skel::after{ display:none; }
  .pv-skel{ opacity:.7; }
}


/* ============================================================
   ДЕСКТОП
   Раздел был сделан как телефон и на 1440px выглядел растянутой
   полосой: шапка во всю ширину, контент в колонке 660px, карточка
   колоды вообще без ограничения. Ниже — общие правила раскладки;
   поэкранные сетки лежат в screens.css и chat.css.
   ============================================================ */
@media (min-width: 900px){
  /* Шапка выравнивается по той же колонке, что и контент, иначе кнопки
     «назад» и «ещё» разъезжаются к краям экрана на полтора метра друг от друга. */
  .pv-top{
    padding-left:0; padding-right:0;
    border-bottom:1px solid var(--hair);
  }
  .pv-top > *{ position:relative; }
  .pv-top-inner,
  .pv-top{
    --top-pad: max(var(--sp4), calc((100vw - var(--col)) / 2));
  }
  .pv-top{ padding-left:var(--top-pad); padding-right:var(--top-pad); }

  /* Липкие подвалы и панели тоже держатся колонки */
  .pv-shell{ padding-left:var(--sp5); padding-right:var(--sp5); }

  /* Шторки на десктопе — не во всю ширину снизу, а карточкой по центру */
  .pv-sheet{
    left:50%; bottom:auto; top:50%;
    transform:translate(-50%, -46%) scale(.98);
    width:min(520px, calc(100vw - var(--sp8)));
    max-width:none; max-height:min(76dvh, 720px);
    border-radius:var(--r-md); border-bottom:1px solid var(--hair2);
    transition:transform var(--d-exit-sheet) var(--e-in),
               opacity var(--d-exit-std) var(--e-effect),
               visibility 0s linear var(--d-exit-sheet);
    opacity:0;
  }
  .pv-sheet.show{
    transform:translate(-50%, -50%) scale(1); opacity:1;
    transition:transform var(--d-sheet) var(--e-spring),
               opacity var(--d-std) var(--e-effect), visibility 0s;
  }
  /* ручку тянуть некуда — на десктопе закрывают крестиком или Esc */
  .pv-sheet-grip{ display:none; }

  .pv-toast{ bottom:var(--sp7); }
}

/* Очень широкий экран: колонка чтения не должна расти бесконечно,
   но и болтаться в углу тоже не должна. */
@media (min-width: 1400px){
  .pv-shell{ max-width:var(--col); }
}

/* ============================================================
   ЛИЦО НА ВЕСЬ ЭКРАН
   ------------------------------------------------------------
   Аватар рисуется в 512px, а живёт в кружке 96px — всё, что автор выбирал,
   в этот кружок не помещается.

   Почему не «картинка на чёрном фоне»: квадрат 512px на широком экране либо
   растягивается в кашу, либо тонет в чёрных полях, и в обоих случаях выглядит
   дёшево. Поэтому фон — та же картинка, увеличенная и размытая (приём Apple
   Music и Spotify): экран заливается цветом самого персонажа, а портрет
   читается крупно и по центру.
   ============================================================ */
.pv-zoomable{ cursor:zoom-in; }
.pv-zoomable:focus-visible{ outline:2px solid var(--hero); outline-offset:3px; }

.pv-zoom{
  position:fixed; inset:0; z-index:200;
  display:flex; align-items:center; justify-content:center;
  /* dvh, а не vh: на мобильных адресная строка съезжает, и 100vh скачет */
  height:100dvh;
  padding:max(var(--sp5), env(safe-area-inset-top)) var(--sp5)
          max(var(--sp5), env(safe-area-inset-bottom));
  /* Непрозрачная подложка обязательна: без неё страница просвечивает
     сквозь размытие и окно читается как полупрозрачная плёнка, а не как
     отдельный экран. */
  background:#090a0e;
  opacity:0; transition:opacity .24s ease;
  cursor:zoom-out; overflow:hidden;
  --pv-drag:1;
}
.pv-zoom.on{ opacity:1; }

/* размытая копия портрета */
.pv-zoom-amb{
  position:absolute; inset:-20%;
  background-position:center; background-size:cover; background-repeat:no-repeat;
  filter:blur(72px) saturate(150%);
  /* translate3d заставляет Safari считать блюр на видеокарте — без него
     размытие такого радиуса ощутимо тормозит */
  transform:translate3d(0,0,0) scale(1.25);
  opacity:calc(.7 * var(--pv-drag));
  transition:opacity .24s ease;
}
.pv-zoom-veil{
  position:absolute; inset:0;
  background:
    radial-gradient(ellipse at 50% 42%, rgba(8,9,12,0) 0%, rgba(8,9,12,.55) 70%, rgba(8,9,12,.86) 100%),
    linear-gradient(180deg, rgba(8,9,12,.5) 0%, rgba(8,9,12,.25) 30%, rgba(8,9,12,.7) 100%);
  opacity:calc(.5 + .5 * var(--pv-drag));
}

/* сам портрет: квадрат, крупно, но без растяжения */
.pv-zoom-fig{
  position:relative; margin:0; touch-action:none;
  width:min(92vw, 78dvh, 620px);
  aspect-ratio:1 / 1;
  border-radius:28px; overflow:hidden;
  background:var(--s2);
  /* мягкая тень и внутренняя подсветка вместо жёсткой обводки */
  box-shadow:0 32px 80px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.12);
  transform:scale(.94); transition:transform .26s cubic-bezier(.2,.9,.25,1);
  cursor:default; will-change:transform;
  /* щипок не должен утаскивать за собой страницу под окном */
  overscroll-behavior:contain;
}
.pv-zoom.on .pv-zoom-fig{ transform:none; }
.pv-zoom.drag .pv-zoom-fig{ transition:none; }
.pv-zoom-fig img{
  width:100%; height:100%; display:block; object-fit:cover;
  -webkit-user-select:none; user-select:none;
}

/* подпись поверх портрета: градиент в девять ступеней, иначе виден шов */
.pv-zoom-fig figcaption{
  position:absolute; left:0; right:0; bottom:0;
  padding:var(--sp8) var(--sp5) var(--sp5);
  display:flex; flex-direction:column; gap:var(--sp2);
  text-align:left; pointer-events:none;
  background:linear-gradient(to top,
    rgba(0,0,0,.86) 0%, rgba(0,0,0,.78) 12%, rgba(0,0,0,.66) 24%,
    rgba(0,0,0,.5) 36%, rgba(0,0,0,.34) 48%, rgba(0,0,0,.2) 60%,
    rgba(0,0,0,.1) 72%, rgba(0,0,0,.03) 86%, transparent 100%);
}
.pv-zoom-fig figcaption b{
  color:#fff; font:700 clamp(22px, 6vw, 34px)/1.15 var(--f-serif);
  text-shadow:0 2px 8px rgba(0,0,0,.45);
}
.pv-zoom-fig figcaption span{
  color:rgba(255,255,255,.82); font-size:var(--fs-small); line-height:var(--lh-body);
  text-shadow:0 1px 6px rgba(0,0,0,.5);
}

/* стеклянная кнопка закрытия, приглушённая — без белых обводок */
.pv-zoom-x{
  position:absolute; z-index:2;
  top:max(var(--sp4), env(safe-area-inset-top)); right:var(--sp4);
  width:44px; height:44px; border:0; border-radius:var(--r-full);
  background:rgba(20,20,24,.42); color:#fff;
  -webkit-backdrop-filter:blur(20px) saturate(160%);
  backdrop-filter:blur(20px) saturate(160%);
  box-shadow:0 8px 30px rgba(0,0,0,.35), inset 0 1px 0 rgba(255,255,255,.1);
  font:400 26px/1 var(--f-ui); cursor:pointer;
}
.pv-zoom-x:hover{ background:rgba(40,40,48,.6); }
.pv-zoom-x:focus-visible{ outline:2px solid #fff; outline-offset:2px; }

/* на широком экране портрет не должен упираться в потолок */
@media (min-width:900px){
  .pv-zoom-fig{ width:min(70vh, 560px); }
}

@media (prefers-reduced-motion: reduce){
  .pv-zoom, .pv-zoom-fig, .pv-zoom-amb{ transition:none !important; }
  .pv-zoom-fig{ transform:none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   ССЫЛОЧНЫЙ ПОДВАЛ (yzseo:footer) · 2026-08-21
   ───────────────────────────────────────────────────────────────────────────
   Раньше эти правила жили только в hub.css, и подвал был только на витринах.
   Теперь его печатает и страница персонажа, и каталог — то есть страницы,
   которые грузят ui.css, а hub.css не грузят. Правила переехали сюда, в общий
   файл раздела; в hub.css свой набор остаётся (у витрин другие переменные).
   ═══════════════════════════════════════════════════════════════════════════ */
.yz-seo-footer{border-top:1px solid var(--hair2);margin:var(--sp7) auto 0;
  padding:var(--sp5) var(--sp5) calc(var(--sp8) * 2);max-width:1120px}
.yz-seo-footer ul{list-style:none;display:flex;flex-wrap:wrap;gap:7px 16px;margin:0;padding:0}
.yz-seo-footer a{font-size:13.5px;color:var(--t2);text-decoration:none}
.yz-seo-footer a:hover{color:var(--hero, currentColor)}
.yz-seo-footer span{font-size:13.5px;color:var(--t3)}
.yz-seo-footer-note{margin-top:14px;font-size:12.5px;color:var(--t3);max-width:620px;line-height:1.5}

/* Ряд входов в категории — витрина каталога и посадочная. */
.yz-cat-row{display:flex;flex-wrap:wrap;gap:var(--sp2);margin:var(--sp4) 0}
.yz-cat-row a{display:inline-flex;align-items:center;gap:6px;padding:8px 14px;
  border:1px solid var(--hair2);border-radius:999px;font-size:14px;
  color:var(--t1);text-decoration:none;background:var(--s1)}
.yz-cat-row a:hover{border-color:currentColor}
.yz-cat-row a i{font-style:normal;color:var(--t3);font-size:12.5px}


/* ═══════════════════════════════════════════════════════════════════════════
   БЫСТРАЯ СБОРКА ИЗ ПОИСКА (qm) · 2026-08-30
   ───────────────────────────────────────────────────────────────────────────
   Содержимое шторки, которую открывает persona/assets/quick_make.js: человек
   искал персонажа, не нашёл и собирает своего. Сама шторка — общая .pv-sheet
   выше, здесь только её начинка, и своих цветов у неё нет: всё через токены.

   Правила живут в ui.css, а не в showcase3.css или browse.css, потому что
   шторку открывают ДВЕ страницы — главная и каталог, — а общий файл раздела
   грузят обе. Держать одни и те же правила в двух листах значит однажды
   поправить только один.
   ═══════════════════════════════════════════════════════════════════════════ */
/* Фокус на контейнер ставится из скрипта и клавиатурой не достижим
   (tabindex="-1") — кольцо тут только мигало бы при каждой смене экрана. */
.qm-sheet:focus{ outline:none; }
.qm-sheet .qm-h{
  margin:0 0 var(--sp2); font:700 var(--fs-title)/1.25 var(--f-serif);
  color:var(--t1); letter-spacing:-.01em;
}
.qm-sheet .qm-lead{ margin:0 0 var(--sp5); font-size:var(--fs-small); color:var(--t2); }
.qm-sheet .qm-hint{ margin:var(--sp3) 0 0; font-size:12px; line-height:1.5; color:var(--t3); text-align:center; }
.qm-sheet .qm-foot{ margin-top:var(--sp3); }

/* ожидание: скелет повторяет раскладку карточки, которая приедет, — иначе
   переход между экранами читается как подмена, а не как загрузка */
.qm-wait{ display:flex; align-items:center; gap:var(--sp4); }
.qm-wait-face{ width:var(--mono-lg); height:var(--mono-lg); flex:none; border-radius:var(--r-full); }
.qm-wait-tx{ flex:1; min-width:0; }
.qm-wait-bubble{ height:64px; margin-top:var(--sp4); border-radius:var(--r-md) var(--r-md) var(--r-md) var(--sp1); }

/* карточка черновика */
.qm-who{ display:flex; align-items:center; gap:var(--sp4); }
.qm-who-tx{ min-width:0; }
.qm-who-tx b{ display:block; font:700 var(--fs-title)/1.2 var(--f-serif); color:var(--t1); }
.qm-who-tx span{ display:block; margin-top:var(--sp1); font-size:var(--fs-small); color:var(--t2); }
.qm-first{
  margin-top:var(--sp4); padding:var(--sp3) var(--sp4);
  background:var(--s1); border:1px solid var(--hair);
  border-radius:var(--r-md) var(--r-md) var(--r-md) var(--sp1);
}
.qm-first p{
  margin:var(--sp1) 0 0; font:400 var(--fs-body)/var(--lh-body) var(--f-serif); color:var(--t1);
}
.qm-acts{ display:grid; gap:var(--sp2); margin-top:var(--sp5); }
/* .pv-btn — inline-flex; в сетке ссылка-кнопка иначе не тянется на всю ширину */
.qm-acts .pv-btn{ width:100%; text-decoration:none; }
