/* Страницы оплаты Buba VPN: /pay/, /pay/done, /pay/test/ — и страница входа /join/.
   Общие токены, градиент страницы и цвет ссылок берутся из /assets/styles.css; здесь только то,
   чего там нет: цвета состояний, карточка-окно, пакеты, поля, кнопки в работе, устройства
   кабинета и QR-код. Значения — из design/tokens.json. Встроенных стилей в разметке нет (CSP). */

:root {
  --surface-solid: #FFFAF6;

  --state-off-text: #434E6A;
  --state-off-solid: #64708A;
  --state-off-soft: #E8ECF4;
  --state-connecting-text: #17589C;
  --state-connecting-solid: #2B76C9;
  --state-connecting-soft: #DDEEFC;
  --state-protected-text: #1B6633;
  --state-protected-solid: #2A8548;
  --state-protected-soft: #E3FBE3;
  --state-warning-text: #7D4B00;
  --state-warning-solid: #A86400;
  --state-warning-soft: #FFEFC7;
  --state-expired-text: #A0391B;
  --state-expired-solid: #C74D2A;
  --state-expired-soft: #FFE4D4;
  --state-error-text: #A81F3C;
  --state-error-solid: #CE2B4E;
  --state-error-soft: #FFDFE6;
}

/* Скрытое атрибутом hidden должно оставаться скрытым, даже если у класса есть display. */
[hidden] { display: none !important; }

/* Спрайт значков: лежит в разметке каждой страницы, сам не виден. */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Читается экранным диктором, глазом не виден. */
.sr-only {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Окно: на телефоне во всю ширину с полями 20, на большом экране — карточка до 420. */
.pay {
  flex: 1;
  width: 100%;
  max-width: 460px;
  margin: 0 auto;
  padding: 24px 20px max(32px, env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: 16px;
  font-size: 16px;
  line-height: 24px;
}

.pay-brand {
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-height: 48px;
  font-size: 22px;
  line-height: 28px;
  font-weight: 800;
  color: var(--text-primary);
  text-decoration: none;
}

.pay-brand img { width: 40px; height: 40px; border-radius: 10px; display: block; }

.pay-card {
  display: grid;
  gap: 16px;
  padding: 20px;
  background: var(--surface-glass);
  border: 1px solid var(--border-glass);
  outline: 1px solid var(--border-outline);
  border-radius: 24px;
  box-shadow: var(--shadow-card);
}

.pay-card > * { min-width: 0; }

.pay-title {
  margin: 0;
  font-size: 22px;
  line-height: 28px;
  font-weight: 800;
  letter-spacing: -0.1px;
}

.pay-lead { margin: 0; color: var(--text-secondary); }

/* Тона состояний: подложка, значок и текст берутся из переменных, их задаёт data-tone. */
[data-tone="off"] { --tone-soft: var(--state-off-soft); --tone-solid: var(--state-off-solid); --tone-text: var(--state-off-text); }
[data-tone="connecting"] { --tone-soft: var(--state-connecting-soft); --tone-solid: var(--state-connecting-solid); --tone-text: var(--state-connecting-text); }
[data-tone="protected"] { --tone-soft: var(--state-protected-soft); --tone-solid: var(--state-protected-solid); --tone-text: var(--state-protected-text); }
[data-tone="warning"] { --tone-soft: var(--state-warning-soft); --tone-solid: var(--state-warning-solid); --tone-text: var(--state-warning-text); }
[data-tone="expired"] { --tone-soft: var(--state-expired-soft); --tone-solid: var(--state-expired-solid); --tone-text: var(--state-expired-text); }
[data-tone="error"] { --tone-soft: var(--state-error-soft); --tone-solid: var(--state-error-solid); --tone-text: var(--state-error-text); }

.ico { display: block; flex: none; width: 24px; height: 24px; color: var(--tone-solid, var(--state-off-solid)); }

/* Баннер: сколько осталось, сообщения, отказы. Значок + слова, не один цвет. */
.note {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  padding: 12px 16px;
  border-radius: 16px;
  background: var(--tone-soft, var(--state-off-soft));
  color: var(--text-primary);
  font-size: 14px;
  line-height: 20px;
}

.note-text { margin: 0; min-width: 0; overflow-wrap: anywhere; }

.note-text + .note-text { margin-top: 4px; }

.note-strong { font-size: 16px; line-height: 24px; font-weight: 600; }

/* Заметная плашка тестового режима. */
.note-test {
  border: 2px solid var(--state-warning-solid);
  color: var(--state-warning-text);
  font-size: 16px;
  line-height: 22px;
  font-weight: 800;
}

.pay-loading {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  margin: 0;
  color: var(--text-secondary);
}

/* Крутилка. Один оборот за 1400 мс; при «меньше движения» стоит на месте. */
.spin {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2.5px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  animation: pay-spin 1400ms linear infinite;
}

.spin-dark { border-color: rgba(27, 35, 64, 0.14); border-top-color: var(--accent); }
.spin-lg { width: 48px; height: 48px; border-width: 4px; }

@keyframes pay-spin { to { transform: rotate(360deg); } }

/* Форма */
.pay-form { display: grid; gap: 16px; }

.pay-form > * { min-width: 0; }

/* fieldset нужен ради disabled на всю форму сразу; раскладка — во вложенном div (старые
   браузеры не умеют grid прямо на fieldset). */
.controls { min-width: 0; margin: 0; padding: 0; border: 0; }

.controls-grid { display: grid; gap: 16px; }

.controls-grid > * { min-width: 0; }

.controls:disabled { opacity: 0.6; }

.pay-label {
  margin: 0 0 8px;
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
  color: var(--text-secondary);
}

/* Пакеты — радиогруппа: настоящие radio, поверх которых нарисованы карточки. */
.plans { display: grid; gap: 8px; }

.plan {
  position: relative;
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) auto;
  column-gap: 12px;
  row-gap: 2px;
  align-items: center;
  min-height: 56px;
  padding: 12px 16px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.plan > * { position: relative; z-index: 1; }

.plan > .plan-input {
  position: absolute;
  z-index: 2;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.plan > .plan-face {
  position: absolute;
  z-index: 0;
  inset: 0;
  border-radius: 16px;
  background: var(--surface-solid);
  border: 2px solid var(--border-divider);
  transition: background-color 200ms, border-color 200ms;
}

.plan:hover > .plan-face { border-color: rgba(27, 35, 64, 0.22); }

.plan-input:checked ~ .plan-face { background: var(--accent-soft); border-color: var(--accent); }

.plan-input:focus-visible ~ .plan-face { outline: 3px solid var(--border-focus); outline-offset: 2px; }

.plan-input:focus-visible { border-radius: 16px; outline: 0; }

.plan-mark {
  grid-column: 1;
  grid-row: 1 / span 2;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 2px solid var(--state-off-solid);
  background: #fff;
  transition: background-color 200ms, border-color 200ms;
}

.plan-input:checked ~ .plan-mark { background: var(--accent); border-color: var(--accent); }

.plan-input:checked ~ .plan-mark::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 2px;
  width: 5px;
  height: 10px;
  border: solid #fff;
  border-width: 0 2.5px 2.5px 0;
  transform: rotate(45deg);
}

.plan-title { grid-column: 2; grid-row: 1; font-size: 17px; line-height: 22px; font-weight: 600; }

.plan-price {
  grid-column: 3;
  grid-row: 1;
  text-align: right;
  white-space: nowrap;
  font-size: 20px;
  line-height: 24px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.plan-extra {
  grid-column: 2 / span 2;
  grid-row: 2;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  font-size: 14px;
  line-height: 20px;
  color: var(--text-secondary);
}

/* Метка скидки. Не кнопка, поэтому ниже 44. */
.tag {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding: 0 8px;
  border-radius: 999px;
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--accent-text);
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px rgba(27, 102, 51, 0.28);
}

/* Поля */
.field { display: grid; gap: 8px; }

.field-label {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 8px;
  font-size: 14px;
  line-height: 20px;
  font-weight: 600;
  color: var(--text-secondary);
}

.field-label .opt { font-weight: 400; color: var(--text-tertiary); }

.pay-input {
  display: block;
  width: 100%;
  height: 52px;
  padding: 0 16px;
  font-family: inherit;
  font-size: 16px;
  line-height: 24px;
  color: var(--text-primary);
  background: #fff;
  border: 1.5px solid var(--state-off-solid);
  border-radius: 16px;
  -webkit-appearance: none;
  appearance: none;
  transition: background-color 200ms, border-color 200ms;
}

.pay-input::placeholder { color: var(--text-tertiary); opacity: 1; }

.pay-input:focus-visible { border-radius: 16px; border-color: var(--border-focus); }

.pay-input[aria-invalid="true"] { border-color: var(--state-error-solid); }

.amount-wrap { position: relative; }

.amount-wrap .pay-input { padding-right: 44px; font-weight: 600; font-variant-numeric: tabular-nums; }

.amount-wrap.is-active .pay-input { background: var(--accent-soft); border-color: var(--accent); }

.amount-unit {
  position: absolute;
  top: 0;
  right: 16px;
  bottom: 0;
  display: flex;
  align-items: center;
  font-weight: 600;
  color: var(--text-secondary);
  pointer-events: none;
}

.hint { margin: 0; min-height: 20px; font-size: 14px; line-height: 20px; color: var(--text-secondary); }

.hint[data-kind="ok"] { color: var(--accent-text); font-weight: 600; }

.hint[data-kind="error"] { color: var(--state-error-text); font-weight: 600; }

.check {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  min-height: 44px;
  padding: 8px 0;
  font-size: 14px;
  line-height: 20px;
  color: var(--text-secondary);
  cursor: pointer;
}

.check input { flex: none; width: 24px; height: 24px; margin: 0; accent-color: var(--accent); cursor: pointer; }

/* Кнопки: вид даёт .btn из styles.css (высота 56, pill, зелёная заливка у главной). */
.pay-btn { width: 100%; padding: 8px 16px; font-family: inherit; text-align: center; }

.btn:focus-visible { border-radius: 999px; }

.btn:active { transform: scale(0.98); }

.btn-primary:active { background: var(--accent-pressed); box-shadow: 0 1px 2px rgba(42, 133, 72, 0.24); }

/* Занята: та же заливка, крутилка слева, подпись остаётся. */
.btn-primary.is-busy {
  background: var(--accent-pressed);
  box-shadow: 0 1px 2px rgba(42, 133, 72, 0.24);
  cursor: progress;
}

.btn-secondary.is-busy { cursor: progress; }

.btn-danger.is-busy { background: var(--state-error-text); cursor: progress; }

/* Выключена (например, пока не прошла пауза после отказа): стекло и серая подпись. */
.btn[aria-disabled="true"]:not(.is-busy),
.btn:disabled:not(.is-busy) {
  color: var(--text-tertiary);
  background: var(--surface-glass-subtle);
  border: 1px solid rgba(255, 255, 255, 0.70);
  box-shadow: none;
  cursor: default;
}

.btn[aria-disabled="true"],
.btn:disabled { transform: none; }

.btn .ico { color: currentColor; }

/* Третий уровень: без заливки, подпись зелёная, зона нажатия от 48. */
.btn-text {
  min-height: 48px;
  color: var(--accent-text);
  background: none;
  box-shadow: none;
  font-weight: 600;
}

.btn-text:active { background: rgba(27, 35, 64, 0.06); }

/* Отключение устройства: красная заливка только у подтверждения. */
.btn-danger {
  color: var(--text-on-accent);
  background: var(--state-error-solid);
  box-shadow: 0 8px 20px rgba(206, 43, 78, 0.24);
}

.btn-danger:active { background: var(--state-error-text); }

/* Малая кнопка в строке списка: ниже 44 не бывает. */
.btn-sm { min-height: 44px; padding: 0 16px; font-size: 15px; line-height: 20px; }

.pay-fine { margin: 0; font-size: 13px; line-height: 18px; color: var(--text-tertiary); text-align: center; }

.pay-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 0 16px; }

.pay-links a { display: inline-flex; align-items: center; min-height: 44px; font-size: 14px; line-height: 20px; font-weight: 600; }

.pay-foot { margin: 0; font-size: 13px; line-height: 18px; text-align: center; color: var(--text-secondary); }

.pay-foot a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; }

/* Серверы: ряд небольших квадратных плиток под логотипом, выше кабинета. В плитке флаг и номер
   сервера, загрузка и состояние: точка и слово — смысл несёт слово, цвет его только подкрепляет.
   Плитки одного размера и переносятся по строкам: на 320 px их две в ряду, на 390 — три. */
.srv { display: grid; gap: 8px; padding: 0; }

.srv-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0 12px; }

.srv-label { margin: 0; font-size: 14px; line-height: 20px; font-weight: 600; color: var(--text-secondary); }

.srv-legend { margin: 0; font-size: 12px; line-height: 16px; color: var(--text-tertiary); }

.srv-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, 101px);   /* на 360 px — три в ряд, на 320 — две */
  justify-content: start;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.srv-list > li { aspect-ratio: 1; }

.srv-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  padding: 6px 0;
  text-align: center;
  background: var(--tone-soft-glass, var(--surface-glass));
  border: 1px solid var(--border-glass);
  outline: 1px solid var(--border-outline);
  border-radius: 20px;
  box-shadow: var(--shadow-card);
}

/* Не «работает» — подложка цвета состояния: плитку видно среди остальных. Работающие — стекло. */
.srv-tile[data-state="checking"], .srv-tile[data-state="down"], .srv-tile[data-state="maintenance"] {
  --tone-soft-glass: var(--tone-soft);
}

.srv-top { display: flex; align-items: center; justify-content: center; gap: 6px; min-height: 28px; }

.srv-flag { font-size: 22px; line-height: 28px; }

.srv-num { font-size: 20px; line-height: 28px; font-weight: 800; font-variant-numeric: tabular-nums; }

.srv-load { min-height: 20px; font-size: 15px; line-height: 20px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--text-primary); }

.srv-load.is-none { color: var(--text-tertiary); font-weight: 400; }

.srv-state {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  max-width: 100%;
  font-size: 12px;
  line-height: 16px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--tone-text, var(--state-off-text));
}

.srv-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--tone-solid, var(--state-off-solid));
}

/* Кабинет: заголовок, устройства, добавление. */
.cabinet > * { min-width: 0; }

.cab-title { margin: 0; font-size: 22px; line-height: 28px; font-weight: 800; letter-spacing: -0.1px; }

.cabinet .facts { margin: 0; }

/* Устройства кабинета: список, отключение, добавление, код входа. */
.devices-box { display: grid; gap: 12px; }

.devices-box > * { min-width: 0; }

.devices { display: grid; margin: 0; padding: 0; list-style: none; }

.device {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px 12px;
  padding: 12px 0;
  border-top: 1px solid var(--border-divider);
}

.device:first-child { border-top: 0; padding-top: 4px; }

.device-info { min-width: 0; }

/* Модель и пометка «это устройство»: пометка встаёт рядом, а если модель длинная — под ней. */
.device-name {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px 8px;
  margin: 0;
  font-weight: 600;
}

.device-model { min-width: 0; max-width: 100%; overflow-wrap: anywhere; }

.tag-this {
  color: var(--state-off-text);
  background: var(--state-off-soft);
  box-shadow: inset 0 0 0 1px rgba(67, 78, 106, 0.22);
}

.device-traffic {
  margin: 0;
  font-size: 13px;
  line-height: 18px;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* Номер для поддержки: мелко под расходом трафика. Не секрет: по нему нельзя ни войти, ни оплатить.
   Кнопка «Скопировать номер» мала на вид, но зона нажатия у неё 44 px: поля её рамки заходят на
   соседние строки (отрицательные отступы), высота строки от этого не растёт. */
.device-no {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 12px;
  margin: 0;
  font-size: 12px;
  line-height: 16px;
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.link-btn.link-sm { margin: -14px -8px; font-size: 13px; line-height: 18px; letter-spacing: 0; }

.device .btn-sm { color: var(--state-error-text); }

.device-confirm { grid-column: 1 / -1; }

/* Кнопка добавления с мелкой ценой следующего устройства под ней. */
.add-box { display: grid; gap: 4px; }

.add-price { margin: 0; text-align: center; font-size: 13px; line-height: 18px; color: var(--text-secondary); }

/* Блок под списком: подтверждение, «что будет», код входа. Фон — подложка тона. */
.panel {
  display: grid;
  gap: 12px;
  padding: 16px;
  border-radius: 16px;
  background: var(--tone-soft, var(--state-off-soft));
  color: var(--text-primary);
}

.panel > * { min-width: 0; }

.panel-title { margin: 0; font-size: 17px; line-height: 22px; font-weight: 800; }

.panel-text { margin: 0; overflow-wrap: anywhere; }

.panel-text strong { font-weight: 800; }

.panel-hint { margin: 0; font-size: 14px; line-height: 20px; color: var(--text-secondary); }

.panel-error { margin: 0; font-size: 14px; line-height: 20px; font-weight: 600; color: var(--state-error-text); }

.panel-actions { display: grid; gap: 8px; }

.note-body { min-width: 0; }

/* Код входа в кабинет: QR-код, сам код, обратный отсчёт. Основа — .codebox. */
.invite { justify-items: center; text-align: center; }

.invite > * { max-width: 100%; }

.invite .pay-btn { width: 100%; }

.invite .panel-actions { width: 100%; }

.invite .codebox-label { color: var(--text-primary); font-size: 17px; line-height: 22px; font-weight: 800; }

/* Белая плитка под QR-код: белое поле вокруг кода нужно камере, а не красоте. */
.qr-box { width: 100%; max-width: 232px; }

.qr {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 12px;
  box-shadow: 0 0 0 1px var(--border-divider);
  shape-rendering: crispEdges;
}

.qr-back { fill: #fff; }

.qr-dark { fill: #1B2340; }

.invite-timer {
  margin: 0;
  font-size: 14px;
  line-height: 20px;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.invite-timer[data-kind="warn"] { color: var(--state-warning-text); font-weight: 600; }

.invite-timer[data-kind="dead"] { color: var(--state-expired-text); font-weight: 600; }

/* Срок кода вышел: код и QR бледнеют, чтобы их не показали по ошибке. */
.invite[data-dead="true"] .qr-box,
.invite[data-dead="true"] .code { opacity: 0.3; }

.invite[data-wait="true"] .qr-box,
.invite[data-wait="true"] .code { opacity: 0.5; }

/* Страница входа /join/ */
.join { display: grid; gap: 16px; }

.join > * { min-width: 0; }

/* Нет доступа к оплате, ссылка устарела, не загрузилось. */
.stop { display: grid; gap: 12px; }

.stop-hint { margin: 0; font-size: 14px; line-height: 20px; color: var(--text-secondary); }

.actions { display: grid; gap: 12px; width: 100%; }

/* Страница результата */
.result { display: grid; justify-items: center; gap: 12px; text-align: center; }

.result > * { min-width: 0; max-width: 100%; }

.result-icon { display: block; width: 56px; height: 56px; color: var(--tone-solid, var(--state-off-solid)); }

.result-title { margin: 0; font-size: 22px; line-height: 28px; font-weight: 800; letter-spacing: -0.1px; }

.result-text { margin: 0; color: var(--text-secondary); }

.result-back { margin: 0; font-weight: 600; }

.facts { display: grid; width: 100%; margin: 4px 0 0; padding: 0; text-align: left; }

.facts div { display: flex; justify-content: space-between; gap: 16px; padding: 12px 0; border-top: 1px solid var(--border-divider); }

.facts div:first-child { border-top: 0; }

.facts dt { color: var(--text-secondary); }

.facts dd { margin: 0; font-weight: 600; text-align: right; overflow-wrap: anywhere; }

.codebox {
  display: grid;
  gap: 12px;
  width: 100%;
  padding: 16px;
  border-radius: 16px;
  background: var(--surface-solid);
  border: 1.5px solid var(--border-divider);
}

.codebox-label { margin: 0; font-size: 14px; line-height: 20px; font-weight: 600; color: var(--text-secondary); }

/* Размер кода идёт за шириной окна, чтобы 19 знаков умещались в одну строку и на узком
   телефоне; если всё же не умещаются, код рвётся посередине (см. done.js). */
.code {
  margin: 0;
  font-size: clamp(17px, 5.3vw, 24px);
  line-height: 32px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  user-select: all;
  -webkit-user-select: all;
}

.code-part { white-space: nowrap; }

.codebox-note { margin: 0; font-size: 14px; line-height: 20px; color: var(--text-secondary); }

/* Тестовая страница заглушки: пометка должна быть видна сразу. */
.test-hero {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 16px;
  border-radius: 16px;
  border: 2px solid var(--state-warning-solid);
  background: var(--state-warning-soft);
  color: var(--state-warning-text);
  font-size: 22px;
  line-height: 28px;
  font-weight: 800;
  text-align: center;
}

.test-hero .ico { width: 32px; height: 32px; }

/* Заметка из нескольких строк: значок стоит у первой. */
.note-top { align-items: flex-start; }

/* Страница сама прокручивает к панелям и кнопкам кабинета; нижняя полоса не должна их закрыть. */
html { scroll-padding-bottom: 104px; }

/* Куда программа переносит фокус сама (окно, панели), рамка не нужна: это не кнопка. */
[tabindex="-1"]:focus, [tabindex="-1"]:focus-visible { outline: 0; }

/* Нижняя полоса кабинета: кнопка «Пополнить доступ» всегда под рукой. Пока кабинет длиннее экрана,
   полоса прилипает к нижнему краю окна, а на коротком кабинете стоит внизу страницы. Плотное
   стекло: под ней прокручивается содержимое. */
.dock {
  position: sticky;
  bottom: 0;
  z-index: 20;
  padding: 12px 20px max(12px, env(safe-area-inset-bottom));
  background: var(--surface-glass-strong);
  -webkit-backdrop-filter: blur(24px);
  backdrop-filter: blur(24px);
  border-top: 1px solid var(--border-outline);
  box-shadow: 0 -8px 32px rgba(31, 42, 74, 0.10);
}

.dock-in { width: 100%; max-width: 420px; margin: 0 auto; }

/* Окно пополнения. По личной ссылке — лист снизу (на широком экране — окно по центру); без ссылки та
   же форма стоит на странице обычной карточкой. Режим задаёт data-mode у .sheet-root. */
html.has-sheet { overflow: hidden; }

.sheet-x {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--border-divider);
  color: var(--text-secondary);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.sheet-x .ico { width: 24px; height: 24px; color: currentColor; }

.sheet-x:active { background: rgba(27, 35, 64, 0.18); }

.sheet-x:focus-visible { border-radius: 50%; }

.sheet-grip { display: none; }

.sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }

.sheet-body { display: grid; gap: 16px; }

.sheet-body > * { min-width: 0; }

.sheet-foot { display: grid; gap: 12px; }

.sheet-foot > * { min-width: 0; }

/* — лист: затемнение, поверх него окно — */
.sheet-root[data-mode="sheet"] {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.sheet-root[data-mode="sheet"] .sheet-scrim {
  position: absolute;
  inset: 0;
  background: rgba(27, 35, 64, 0.40);
  animation: sheet-fade 200ms ease-out;
}

.sheet-root[data-mode="sheet"] .sheet {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0;
  width: 100%;
  max-width: 520px;
  max-height: 92vh;
  max-height: 92dvh;
  padding: 0;
  background: var(--surface-glass-strong);
  -webkit-backdrop-filter: blur(24px);
  backdrop-filter: blur(24px);
  border: 0;
  outline: 0;
  border-radius: 32px 32px 0 0;
  box-shadow: 0 -8px 32px rgba(31, 42, 74, 0.16);
  animation: sheet-rise 360ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.sheet-root[data-mode="sheet"] .sheet-grip {
  display: block;
  flex: none;
  width: 36px;
  height: 4px;
  margin: 8px auto 0;
  border-radius: 2px;
  background: var(--state-off-solid);
  opacity: 0.55;
}

.sheet-root[data-mode="sheet"] .sheet-head { flex: none; padding: 4px 12px 4px 20px; }

.sheet-root[data-mode="sheet"] .pay-form { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; gap: 0; }

.sheet-root[data-mode="sheet"] .sheet-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 4px 20px 12px;
}

.sheet-root[data-mode="sheet"] .sheet-foot {
  flex: none;
  padding: 12px 20px max(16px, env(safe-area-inset-bottom));
  border-top: 1px solid var(--border-divider);
}

/* — страница: форма без окна. Полоса с кнопкой оплаты прилипает к нижнему краю экрана, пока форма
   на виду (пакеты, своя сумма и почта вместе длиннее экрана телефона), а дойдя до своего места,
   встаёт на него. Отказы показываются в ней же, над кнопкой: иначе после нажатия они оказались бы
   ниже края экрана. Полоса идёт во всю ширину карточки и закрывает прокручиваемое цветом карточки. — */
.sheet-root[data-mode="page"] .sheet-x,
.sheet-root[data-mode="page"] .sheet-scrim { display: none; }

.sheet-root[data-mode="page"] .sheet-foot {
  position: sticky;
  bottom: 0;
  z-index: 2;
  margin: 0 -20px;
  padding: 16px 20px max(12px, env(safe-area-inset-bottom));
  background: linear-gradient(to bottom, rgba(255, 250, 246, 0) 0, rgba(255, 250, 246, 0.96) 16px);
}

@keyframes sheet-fade { from { opacity: 0; } to { opacity: 1; } }

@keyframes sheet-rise { from { transform: translateY(40px); opacity: 0; } to { transform: none; opacity: 1; } }

/* Своя сумма: сначала только небольшая текстовая кнопка, поле раскрывается по нажатию. */
.custom-row { display: grid; gap: 8px; margin: -6px 0; }

.link-btn {
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 44px;
  margin: 0 -8px;
  padding: 0 8px;
  border: 0;
  border-radius: 12px;
  background: none;
  font-family: inherit;
  font-size: 15px;
  line-height: 20px;
  font-weight: 600;
  color: var(--accent-text);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.link-btn .chev { flex: none; width: 18px; height: 18px; }

.link-btn:active { background: rgba(27, 35, 64, 0.06); }

.link-btn:focus-visible { border-radius: 12px; }

/* Почта для чека: небольшое поле и мелкая подсказка. */
.field-compact { gap: 6px; }

.field-compact .pay-input { height: 48px; }

.field-compact .hint { min-height: 0; font-size: 13px; line-height: 18px; }

@media (min-width: 600px) {
  .sheet-root[data-mode="sheet"] { align-items: center; }

  .sheet-root[data-mode="sheet"] .sheet {
    max-width: 460px;
    max-height: 88vh;
    max-height: 88dvh;
    border-radius: 24px;
  }

  .sheet-root[data-mode="sheet"] .sheet-grip { display: none; }

  .sheet-root[data-mode="sheet"] .sheet-head { padding-top: 16px; }
}

@media (min-width: 768px) {
  .pay { padding-top: 48px; }
}

/* На самых узких экранах кнопка в строке устройства уходит под сведения о нём: иначе длинная
   модель и расход трафика теснятся в узком столбце слева. */
@media (max-width: 374px) {
  .device { grid-template-columns: minmax(0, 1fr); }

  .device .btn-sm { justify-self: start; }
}

@media (prefers-reduced-motion: reduce) {
  .spin { animation: none; }
  .plan > .plan-face, .plan-mark, .pay-input { transition: none; }
  .btn:active { transform: none; }
  .sheet-root[data-mode="sheet"] .sheet-scrim,
  .sheet-root[data-mode="sheet"] .sheet { animation: none; }
}
