/* ============================================================
 * Кабинет арендатора v2 — основа: каркас, панель навигации,
 * типографические роли и базовые компоненты (этап S0).
 * Экранные стили — portal_<экран>.css; CRM-компоненты (badge, chip,
 * btn, table, doc-row, skeleton, timeline) перестилизованы только
 * скоупом .portal-body — в CRM они не меняются (бриф §6). ui.css
 * подключается позже этого файла, поэтому скоуп здесь обязателен.
 *
 * Правило (решения v2 §2): цвет, кегль, отступ, радиус, тень и
 * длительность — только var(--ios-*) из tokens.css. Литералы геометрии:
 * 0 (0px в calc/env), 1px — разделители и рамки, 2px 8px — бейдж,
 * 2px и 12px — кольцо и точка ленты, 50%, 90%, 100%, 90deg; пороги
 * медиа- и контейнер-запросов (900px, 440px; 1184px — сетка главной в две
 * колонки: --ios-container-wide 1120 + 2 × --ios-gutter десктопа 32, в
 * медиазапросе var() не работает).
 * Шорткат font: var(--ios-type-*) сбрасывает font-variant-numeric —
 * tabular-nums ставится после font.
 * ============================================================ */

/* --- Корень: только светлая тема, якоря и фокус не под панелью --- */

.portal-root {
  color-scheme: only light;
  scroll-padding-top: var(--ios-scroll-offset);
}

.portal-body {
  margin: 0;
  background: var(--ios-bg);
  color: var(--ios-text);
  font: var(--ios-type-body);
  -webkit-font-smoothing: antialiased;
}

.portal-body a {
  color: var(--ios-accent);
}

.portal-body a:hover {
  color: var(--ios-accent-hover);
}

.portal-body a:active {
  color: var(--ios-accent-active);
}

/* Фокус — outline цветом акцента (виден и в режиме принудительных цветов);
 * --focus-ring (box-shadow) CRM-компонентов в кабинете гасим */
.portal-body :focus-visible,
.portal-body .btn:focus-visible,
.portal-body .field__input:focus-visible {
  outline: var(--ios-focus-width) solid var(--ios-focus);
  outline-offset: var(--ios-focus-offset);
  box-shadow: none;
}

/* Строки во всю ширину группы прилегают к краям подложки, а та скругляет
 * углы через overflow: hidden и срезала бы кольцо снаружи. Им кольцо —
 * внутрь строки, со скруглением подложки: оно параллельно её углу и
 * видно целиком и у одной строки в группе, и у крайних. Меню
 * переключателя скруглено радиусом поля, группы — радиусом карточки */
.portal-body .portal-row--link:focus-visible,
.portal-body .portal-invoice__summary:focus-visible,
.portal-body .portal-switcher__item:focus-visible {
  border-radius: var(--ios-card-radius);
  outline-offset: calc(-1 * (var(--ios-focus-width) + var(--ios-focus-offset)));
}

.portal-body .portal-switcher__item:focus-visible {
  border-radius: var(--ios-radius-field);
}

/* --- Контейнеры: ширина содержимого по токенам, поля экрана снаружи
 *     (content-box: max-width — ширина колонки, gutter добавляется) --- */

.portal-shell,
.portal-footer {
  box-sizing: content-box;
  margin: 0 auto;
  padding-left: var(--ios-gutter);
  padding-right: var(--ios-gutter);
}

.portal-shell {
  padding-top: var(--ios-space-4);
  padding-bottom: var(--ios-space-8);
}

.portal-shell--narrow,
.portal-footer--narrow {
  max-width: var(--ios-container-narrow);
}

.portal-shell--invoice,
.portal-footer--invoice {
  max-width: var(--ios-container-invoice);
}

.portal-shell--wide,
.portal-footer--wide {
  max-width: var(--ios-container-wide);
}

/* --- Подвал: сноска мелким текстом (бриф §3 п. 8) --- */

.portal-footer {
  padding-bottom: calc(var(--ios-space-8) + env(safe-area-inset-bottom, 0px));
}

.portal-footer__text {
  margin: 0;
  padding-top: var(--ios-space-4);
  border-top: 1px solid var(--ios-separator);
  font: var(--ios-type-caption);
  color: var(--ios-text-secondary);
}

/* Ссылка на политику ПДн (Р-69, Y1) — отдельной строкой под сноской */
.portal-footer__legal {
  display: block;
  margin-top: var(--ios-space-2);
  color: inherit;
}

/* ============================================================
 * Панель навигации (бриф §4.0; решения v2 §2 «Панель»)
 * Липкая; полупрозрачная с размытием только внутри @supports, иначе
 * сплошной фон. Вторичного текста в панели нет (контраст 3,86).
 * Телефон — меню на <details>, десктоп (≥900px) — пункты в строку.
 * ============================================================ */

.portal-nav {
  position: sticky;
  top: 0;
  z-index: var(--ios-z-nav);
  padding-top: env(safe-area-inset-top, 0px);
  border-bottom: 1px solid var(--ios-separator);
  background: var(--ios-nav-bg-solid);
}

@supports (backdrop-filter: none) or (-webkit-backdrop-filter: none) {
  .portal-nav {
    background: var(--ios-nav-bg);
    -webkit-backdrop-filter: var(--ios-nav-blur);
    backdrop-filter: var(--ios-nav-blur);
  }
}

.portal-nav__bar {
  box-sizing: content-box;
  display: flex;
  align-items: center;
  gap: var(--ios-space-4);
  max-width: var(--ios-container-wide);
  height: var(--ios-nav-height);
  margin: 0 auto;
  padding: 0 var(--ios-gutter);
}

/* Название выбранного договора; длинное — в одну строку с многоточием:
 * полное название — на самой странице */
.portal-nav__title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  font: var(--ios-type-nav-title);
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Разделы в строку и таблетка «Оплатить» — только на десктопе; на
 * телефоне (дизайн v3, T1) — нижняя панель, вверху остаются название
 * договора и «Выйти» */
.portal-nav__sections,
.portal-nav .portal-nav__pay {
  display: none;
}

.portal-nav__links {
  margin: 0;
  padding: 0;
  list-style: none;
}

.portal-nav__signout-form {
  flex: none;
  margin: 0;
}

/* Пункт: ссылка раздела или кнопка «Выйти» — одинаково, цветом «можно
 * нажать»; текущий раздел — основным цветом текста и начертанием 600:
 * не только цветом (контраст акцента и текста между собой 2,6:1) */
.portal-nav__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--ios-touch-min);
  padding: 0;
  border: 0;
  background: none;
  color: var(--ios-accent);
  font: var(--ios-type-button-nav);
  text-decoration: none;
  cursor: pointer;
}

.portal-body .portal-nav__link:hover {
  color: var(--ios-accent-hover);
  text-decoration: none;
}

.portal-body .portal-nav__link[aria-current="page"] {
  color: var(--ios-text);
  font-weight: 600;
}

/* «Уведомления» (Р-105, E3): колокольчик с числом непрочитанных — на обеих
 * ширинах, перед «Выйти»; зона нажатия 44. Число — таблеткой поверх значка:
 * непрочитанное видно не только цветом, имя ссылки говорит число словами */
.portal-nav__bell {
  position: relative;
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  min-width: var(--ios-touch-min);
  min-height: var(--ios-touch-min);
  color: var(--ios-accent);
  text-decoration: none;
}

.portal-body .portal-nav__bell:hover {
  color: var(--ios-accent-hover);
}

.portal-body .portal-nav__bell[aria-current="page"] {
  color: var(--ios-text);
}

.portal-nav__bell-icon {
  width: var(--ios-tab-icon);
  height: var(--ios-tab-icon);
}

.portal-nav__bell-count {
  position: absolute;
  top: var(--ios-space-1);
  right: 0;
  min-width: var(--ios-space-4);
  padding: 0 var(--ios-space-1);
  border-radius: var(--ios-radius-pill);
  background: var(--ios-accent);
  color: var(--ios-text-on-accent);
  font: var(--ios-type-badge);
  text-align: center;
}

/* «Выйти» на телефоне — справа в строке названия; зона нажатия 44 */
.portal-nav__signout {
  min-width: var(--ios-touch-min);
  justify-content: flex-end;
}

@media (min-width: 900px) {
  .portal-nav__sections {
    display: block;
  }

  .portal-nav__links {
    display: flex;
    align-items: center;
    gap: var(--ios-space-6);
  }

  .portal-nav__link {
    min-height: var(--ios-target-min);
  }

  .portal-nav__signout {
    min-width: 0;
  }

  /* «Выйти» — тем же шагом, что разделы (бар даёт --ios-space-4) */
  .portal-nav__signout-form {
    margin-left: calc(var(--ios-space-6) - var(--ios-space-4));
  }

  /* Таблетка «Оплатить» (бриф §4.0, этап S2): при долге выбранного
   * договора на договоре, счёте и заявках — последней в панели, справа.
   * Визуально 30, зона нажатия 44 — модификатор --nav */
  .portal-nav .portal-nav__pay {
    display: inline-flex;
    flex: none;
  }
}

/* ============================================================
 * Нижняя панель телефона (дизайн v3, T1; ролик «Motion tabs»)
 * Плавающая капсула по центру внизу, над safe-area; стекло — только
 * внутри @supports, иначе плотный белый фон. Выбранная вкладка — тёмная
 * таблетка с подписью, остальные — значки 44×44. Этап 1 — статика:
 * перетекание таблетки — в этапе 2, сейчас только смена фона при
 * наведении (длительность обнуляет reduced motion).
 * Содержимое не уходит под панель: подвал отступает на
 * --ios-tabbar-clearance, фокус — scroll-padding-bottom. От 900px панели
 * нет — верхняя панель v2.
 * ============================================================ */

.portal-root {
  scroll-padding-bottom: var(--ios-tabbar-clearance);
}

.portal-tabbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(var(--ios-tabbar-offset) + env(safe-area-inset-bottom, 0px));
  z-index: var(--ios-z-nav);
  display: flex;
  align-items: center;
  gap: var(--ios-space-1);
  width: max-content;
  max-width: var(--ios-tabbar-max);
  box-sizing: border-box;
  height: var(--ios-tabbar-height);
  margin: 0 auto;
  padding: var(--ios-tabbar-pad);
  border-radius: var(--ios-radius-pill);
  background: var(--ios-tabbar-bg-solid);
  box-shadow: var(--ios-tabbar-shadow);
}

@supports (backdrop-filter: none) or (-webkit-backdrop-filter: none) {
  .portal-tabbar {
    background: var(--ios-tabbar-bg);
    -webkit-backdrop-filter: var(--ios-tabbar-blur);
    backdrop-filter: var(--ios-tabbar-blur);
  }
}

.portal-tabbar__tabs {
  display: flex;
  align-items: center;
  gap: var(--ios-space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.portal-tabbar__item {
  display: flex;
}

/* Вкладка-значок: круг 44×44; выбранная — таблетка со значком и подписью */
.portal-body .portal-tabbar__tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ios-space-2);
  min-width: var(--ios-touch-min);
  height: var(--ios-touch-min);
  box-sizing: border-box;
  border-radius: var(--ios-radius-pill);
  color: var(--ios-text);
  font: var(--ios-type-button-nav);
  text-decoration: none;
  transition: background-color var(--ios-duration-fast) var(--ios-ease);
}

.portal-body .portal-tabbar__tab:hover,
.portal-body .portal-tabbar__tab:active {
  background: var(--ios-tab-hover-bg);
  color: var(--ios-text);
}

.portal-body .portal-tabbar__tab--current,
.portal-body .portal-tabbar__tab--current:hover,
.portal-body .portal-tabbar__tab--current:active {
  padding: 0 var(--ios-space-4) 0 var(--ios-space-3);
  background: var(--ios-tab-current-bg);
  color: var(--ios-tab-current-text);
  font-weight: 600;
}

.portal-tabbar__icon {
  flex: none;
  width: var(--ios-tab-icon);
  height: var(--ios-tab-icon);
}

.portal-tabbar__label {
  white-space: nowrap;
}

/* Разделитель вкладок и «Оплатить» — декор */
.portal-tabbar__sep {
  flex: none;
  align-self: center;
  width: 1px;
  height: var(--ios-tab-icon);
  margin: 0 var(--ios-space-1);
  background: var(--ios-separator);
}

/* «Оплатить» — акцентная таблетка во всю высоту вкладки (44), открывает
 * лист реквизитов; подпись короткая, сумма — в aria-label */
.portal-body .portal-tabbar__pay {
  flex: none;
  min-height: var(--ios-touch-min);
  height: var(--ios-touch-min);
  padding: 0 var(--ios-space-4);
  font: var(--ios-type-button-nav);
  font-weight: 600;
  white-space: nowrap;
}

/* Четыре вкладки (E2: Главная, Счета, Договоры, Заявки) с подписью у
 * выбранной и «Оплатить» на узком телефоне в капсулу не помещаются: при
 * долге выбранная вкладка — тёмный круг 44×44 со значком, подпись скрыта
 * только визуально (остаётся именем ссылки). Порог — ширина, на которой
 * капсула с самой длинной подписью («Договоры») и «Оплатить» влезает
 * целиком (замер — отчёт E2) */
@media (max-width: 429px) {
  .portal-body .portal-tabbar--pay .portal-tabbar__tab--current,
  .portal-body .portal-tabbar--pay .portal-tabbar__tab--current:hover,
  .portal-body .portal-tabbar--pay .portal-tabbar__tab--current:active {
    padding: 0;
  }

  .portal-tabbar--pay .portal-tabbar__tab--current .portal-tabbar__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* Подвал отступает от панели: последняя строка видна над капсулой */
.portal-footer {
  padding-bottom: calc(var(--ios-space-8) + var(--ios-tabbar-clearance));
}

@media (min-width: 900px) {
  .portal-root {
    scroll-padding-bottom: 0;
  }

  .portal-tabbar {
    display: none;
  }

  .portal-footer {
    padding-bottom: calc(var(--ios-space-8) + env(safe-area-inset-bottom, 0px));
  }
}

/* ============================================================
 * Типографические роли (записка, раздел 2 «Типографика»)
 * ============================================================ */

/* Надстрочник: «УК Морской · ПТК Ромашка-Сервис», «К оплате» */
.portal-overline {
  margin: 0;
  font: var(--ios-type-secondary);
  color: var(--ios-text-secondary);
}

/* h1 страницы: главная и заявки — --ios-type-h1; договор и счёт —
 * модификатор --page (44/50 на десктопе). Трекинг переключается токеном */
.portal-title {
  margin: var(--ios-space-4) 0 var(--ios-space-6);
  font: var(--ios-type-h1);
  letter-spacing: var(--ios-tracking-h1);
}

.portal-title--page {
  font: var(--ios-type-h1-page);
  letter-spacing: var(--ios-tracking-h1-page);
}

/* Подзаголовок — строка под заголовком страницы или блока */
.portal-subtitle {
  margin: 0;
  font: var(--ios-type-subtitle);
}

/* Заголовок блока — обычным регистром, без капса (бриф §3 п. 7) */
.portal-heading,
.portal-section__title {
  margin: 0 0 var(--ios-space-3);
  font: var(--ios-type-block);
}

.portal-text {
  margin: 0;
  font: var(--ios-type-body);
}

.portal-secondary {
  margin: 0;
  font: var(--ios-type-secondary);
  color: var(--ios-text-secondary);
}

/* Сноска: подвал, пояснения к расчётам */
.portal-caption {
  margin: 0;
  font: var(--ios-type-caption);
  color: var(--ios-text-secondary);
}

/* Цифры в тексте — Onest с табличными цифрами: даты, номера, ИНН,
 * проценты и суммы внутри фразы (решения v2 §2 «Где моно») */
.portal-num {
  font-variant-numeric: tabular-nums;
}

/* Сумма отдельным значением — JetBrains Mono в кегле своей строки:
 * обычные 400, итоги — модификатор --total (600) */
.portal-amount {
  font-family: var(--ios-font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

.portal-amount--total {
  font-weight: 600;
}

/* Даты в CRM-классе .num (таблица, документы) — Onest, не моно */
.portal-body .num {
  font-family: inherit;
  font-size: inherit;
  font-variant-numeric: tabular-nums;
}

/* ============================================================
 * Ссылки и кнопки-таблетки (бриф §3 «Компоненты-ориентиры»)
 * ============================================================ */

.portal-link {
  color: var(--ios-accent);
}

/* Текстовая ссылка-переход: «Как посчитано ›». Знак — оформление,
 * скринридер его не читает */
.portal-link--more::after {
  content: "›";
  content: "›" / "";
  margin-left: var(--ios-space-1);
}

/* «‹ Главная» на дочерней странице (счёт). Знак — оформление, как «›»:
 * в ::before, скринридер читает только «Главная» */
.portal-back {
  margin: 0;
}

.portal-back__link {
  display: inline-flex;
  align-items: center;
  gap: var(--ios-space-1);
  min-height: var(--ios-touch-min);
}

.portal-back__link::before {
  content: "‹";
  content: "‹" / "";
}

/* ============================================================
 * Шапка страницы договора и счёта — основной шаблон блока (бриф §3
 * п. 2, этап S3): надстрочник → h1 (--ios-type-h1-page: 28/34, на
 * десктопе 44/50) → подзаголовок обычного начертания → действие-ссылка.
 * На фоне, без карточки, по левому краю (данные, бриф §3). Длинный
 * номер и название переносятся, не обрезаются
 * ============================================================ */

.portal-page-head {
  margin: var(--ios-space-4) 0 var(--ios-gap-section);
}

/* Под «‹ Главная» шапка встаёт сразу: у ссылки своя зона нажатия 44 */
.portal-back + .portal-page-head {
  margin-top: 0;
}

.portal-page-head__title {
  margin: var(--ios-space-1) 0 0;
  overflow-wrap: anywhere;
}

.portal-page-head__sub {
  margin: var(--ios-space-2) 0 0;
  overflow-wrap: anywhere;
}

.portal-page-head__actions {
  margin: var(--ios-space-2) 0 0;
}

/* Ссылка на связанный документ внутри подзаголовка «не к оплате» (счёт):
 * визуально строка текста, зона нажатия 44 — псевдоэлементом по
 * вертикали (бриф §6, §8: 44×44 на телефоне, включая текстовые ссылки).
 * Ссылка — блоком в строке: номер с датой переносится целиком, зона
 * считается от её собственной коробки. Фокус — на тексте, не на зоне */
.portal-page-head__sub .portal-link {
  position: relative;
  display: inline-block;
  max-width: 100%;
}

.portal-page-head__sub .portal-link::after {
  content: "";
  position: absolute;
  inset: calc(50% - var(--ios-touch-min) / 2) 0;
}

/* Зона ссылки выходит под строку подзаголовка — «Скачать PDF» ниже
 * отодвигается, чтобы зоны не перекрывались */
.portal-page-head__sub:has(.portal-link) + .portal-page-head__actions {
  margin-top: var(--ios-space-4);
}

.portal-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ios-space-2);
  min-height: var(--ios-button-height);
  margin: 0;
  padding: 0 var(--ios-space-6);
  border: 0;
  border-radius: var(--ios-radius-pill);
  background: none;
  font: var(--ios-type-button);
  font-variant-numeric: tabular-nums;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--ios-duration-fast) var(--ios-ease),
    color var(--ios-duration-fast) var(--ios-ease);
}

.portal-body .portal-button:hover {
  text-decoration: none;
}

/* Основная: заливка акцентом, текст 400 (решения v2 §2) */
.portal-body .portal-button--primary {
  background: var(--ios-accent);
  color: var(--ios-text-on-accent);
}

.portal-body .portal-button--primary:hover {
  background: var(--ios-accent-hover);
  color: var(--ios-text-on-accent);
}

.portal-body .portal-button--primary:active {
  background: var(--ios-accent-active);
  color: var(--ios-text-on-accent);
}

/* Второстепенная: тинт на сером фоне; на белой поверхности (лист,
 * диалог, группа) — заливка фоном страницы */
.portal-body .portal-button--secondary {
  background: var(--ios-accent-tint);
  color: var(--ios-accent);
}

.portal-body .portal-sheet .portal-button--secondary,
.portal-body .portal-card .portal-button--secondary {
  background: var(--ios-bg);
}

.portal-body .portal-button--secondary:hover {
  color: var(--ios-accent-hover);
}

/* Текстовая: визуально лёгкая, зона нажатия ≥ 44 по высоте */
.portal-body .portal-button--text {
  min-height: var(--ios-touch-min);
  padding: 0;
  background: none;
  color: var(--ios-accent);
}

.portal-body .portal-button--text:hover {
  color: var(--ios-accent-hover);
}

/* Во всю ширину: кнопки форм и листов */
.portal-button--block {
  display: flex;
  width: 100%;
}

/* Таблетка панели («Оплатить» при долге, .portal-nav__pay): визуально
 * 30, зона нажатия добирается псевдоэлементом до 44 */
.portal-button--nav {
  position: relative;
  min-height: var(--ios-nav-pill-height);
  padding: 0 var(--ios-space-3);
  font: var(--ios-type-button-nav);
}

.portal-button--nav::after {
  content: "";
  position: absolute;
  inset: calc((var(--ios-nav-pill-height) - var(--ios-touch-min)) / 2) 0;
}

/* Недоступна: серая заливка, причина — рядом обычным вторичным текстом */
.portal-body .portal-button:disabled,
.portal-body .portal-button[aria-disabled="true"] {
  background: var(--ios-fill-disabled);
  color: var(--ios-text-disabled);
  cursor: not-allowed;
}

.portal-body .portal-button--text:disabled,
.portal-body .portal-button--text[aria-disabled="true"] {
  background: none;
}

/* CRM-кнопки внутри кабинета (массовые действия, акт сверки) — таблетки
 * в кегле кнопок 17 (бриф §3: 14 — только таблетка панели) */
.portal-body .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--ios-touch-min);
  padding: 0 var(--ios-space-5);
  border: 0;
  border-radius: var(--ios-radius-pill);
  background: var(--ios-accent-tint);
  color: var(--ios-accent);
  font: var(--ios-type-button);
}

.portal-body .btn:hover {
  background: var(--ios-accent-tint);
  color: var(--ios-accent-hover);
}

.portal-body .btn--primary {
  background: var(--ios-accent);
  color: var(--ios-text-on-accent);
}

.portal-body .btn--primary:hover {
  background: var(--ios-accent-hover);
  color: var(--ios-text-on-accent);
}

/* ============================================================
 * Сгруппированный список «подпись — значение» (бриф §3)
 * Группу выделяет подложка, без рамок и теней; над группой —
 * заголовок блока, под ней — сноска .portal-group-note
 * ============================================================ */

.portal-section {
  margin-top: var(--ios-gap-section);
}

.portal-card {
  margin: 0 0 var(--ios-space-4);
  overflow: hidden;
  background: var(--ios-surface);
  border-radius: var(--ios-card-radius);
}

.portal-group-note {
  margin: calc(var(--ios-space-2) - var(--ios-space-4)) 0 var(--ios-space-4);
  padding: 0 var(--ios-space-4);
  font: var(--ios-type-caption);
  color: var(--ios-text-secondary);
}

.portal-row {
  display: flex;
  align-items: center;
  gap: var(--ios-space-3);
  min-height: var(--ios-row-height);
  padding: var(--ios-space-3) var(--ios-space-4);
}

.portal-row + .portal-row {
  border-top: 1px solid var(--ios-separator);
}

.portal-row__label {
  color: var(--ios-text-secondary);
}

.portal-row__value {
  margin-left: auto;
  text-align: right;
}

.portal-row__text {
  flex: 1;
  min-width: 0;
}

.portal-row__title {
  font-weight: 600;
}

.portal-row__sub {
  font: var(--ios-type-secondary);
  color: var(--ios-text-secondary);
}

/* Пояснение под значением строки («по договору; срок оплаты — в счёте») */
.portal-row__hint {
  display: block;
  font: var(--ios-type-caption);
  color: var(--ios-text-secondary);
}

.portal-row--multi {
  align-items: flex-start;
}

/* Строка-переход: вся строка кликабельна, справа «›» */
.portal-body .portal-row--link,
.portal-body .portal-row--link:hover {
  color: inherit;
  text-decoration: none;
}

.portal-row--link .portal-row__value {
  color: var(--ios-text-secondary);
}

.portal-row--link::after {
  content: "›";
  content: "›" / "";
  flex: none;
  color: var(--ios-icon-muted);
}

/* ============================================================
 * Бейджи и чипы: тон статусов (решения v2 §2 «Тон статусов»)
 * Варианты в разметке не меняются — тон задают скоупленные правила.
 * Синий — только у того, что можно нажать; статус всегда текстом.
 *   красный     — просрочка и ошибки (danger);
 *   оранжевый   — частичная оплата, близкий срок, ожидание подписи
 *                 или проверки (warning; «Не подписан» в документах);
 *   зелёный     — оплачено, выполнено, принято, подписано (success;
 *                 чип «подписано» у ДС в ленте);
 *   нейтральный — всё остальное: бывшие синие «Выставлен», «Отправлен»,
 *                 «Новая», «вступят в силу» (info) и muted.
 * ============================================================ */

.portal-body .badge,
.portal-body .chip {
  display: inline-block;
  padding: 2px 8px;
  border: 0;
  border-radius: var(--ios-radius-badge);
  font: var(--ios-type-badge);
  white-space: nowrap;
}

.portal-body .badge--success,
.portal-body .chip--success {
  color: var(--ios-status-success);
  background: var(--ios-status-success-bg);
}

.portal-body .badge--warning,
.portal-body .chip--warning {
  color: var(--ios-status-warning);
  background: var(--ios-status-warning-bg);
}

.portal-body .badge--danger,
.portal-body .chip--danger {
  color: var(--ios-status-danger);
  background: var(--ios-status-danger-bg);
}

.portal-body .badge--info,
.portal-body .badge--muted,
.portal-body .chip--info,
.portal-body .chip--muted {
  color: var(--ios-status-neutral);
  background: var(--ios-status-neutral-bg);
}

/* Группа документов: «Не подписан» (badge--info) — ожидание подписи */
.portal-body .portal-docs .badge--info {
  color: var(--ios-status-warning);
  background: var(--ios-status-warning-bg);
}

/* Статусы, которых нет в утверждённом списке, — по правилу тона (решения
 * v2 §2, бриф §3): отклонённое ДС (badge--danger в документах) — не
 * просрочка и не ошибка, заявка «В работе» (badge--warning) — ход за
 * управляющим, как у «Новая»: обе нейтральные. Варианты в CRM прежние */
.portal-body .portal-docs .badge--danger,
.portal-body .portal-request .badge--warning {
  color: var(--ios-status-neutral);
  background: var(--ios-status-neutral-bg);
}

/* Лента условий: чип «подписано» (chip--info) у подписанного ДС — зелёный */
.portal-body .portal-terms-entry[data-state="signed"] .chip--info {
  color: var(--ios-status-success);
  background: var(--ios-status-success-bg);
}

/* Точки ленты истории 12×12: текущие — зелёная, на подписи — оранжевая,
 * прошлые — серая; будущие условия — полое кольцо; подписанное ДС —
 * зелёная (вариант точки в разметке у него тот же, что у будущих) */
.portal-body .timeline-item__dot {
  flex: 0 0 12px;
  width: 12px;
  height: 12px;
  margin-top: var(--ios-space-1);
  background: var(--ios-icon-muted);
}

.portal-body .timeline-item__dot--success {
  background: var(--ios-status-success);
}

.portal-body .timeline-item__dot--warning {
  background: var(--ios-status-warning);
}

.portal-body .timeline-item__dot--danger {
  background: var(--ios-status-danger);
}

.portal-body .timeline-item__dot--info {
  background: none;
  box-shadow: inset 0 0 0 2px var(--ios-icon-muted);
}

.portal-body .timeline-item:has(.portal-terms-entry[data-state="signed"]) .timeline-item__dot {
  background: var(--ios-status-success);
  box-shadow: none;
}

.portal-body .timeline-item {
  gap: var(--ios-space-3);
}

.portal-body .timeline-item__line {
  background: var(--ios-separator);
}

.portal-body .timeline-item__body {
  padding-bottom: var(--ios-space-4);
}

/* ============================================================
 * Поля ввода: подпись видна всегда (над полем), ошибка — текстом под
 * полем; 17px — iOS не увеличивает страницу при фокусе. Рамка
 * --ios-control-border — поля можно ставить на оба фона.
 * Существующие классы полей экранов получают тот же вид.
 * ============================================================ */

.portal-field {
  display: grid;
  gap: var(--ios-space-2);
}

.portal-field__label {
  font: var(--ios-type-secondary);
  color: var(--ios-text-secondary);
}

.portal-field__input,
.portal-date-input,
.portal-request-form__input,
.portal-turnover__input {
  width: 100%;
  min-height: var(--ios-field-height);
  padding: 0 var(--ios-space-4);
  border: 1px solid var(--ios-control-border);
  border-radius: var(--ios-radius-field);
  background: var(--ios-surface);
  color: var(--ios-text);
  font: var(--ios-type-body);
  font-variant-numeric: tabular-nums;
}

textarea.portal-field__input,
textarea.portal-request-form__input {
  padding-top: var(--ios-space-3);
  padding-bottom: var(--ios-space-3);
}

/* Число (оборот): выравнивание вправо, как суммы */
.portal-field__input--number,
.portal-turnover__input {
  text-align: right;
}

.portal-field__input:disabled {
  border-color: var(--ios-fill-disabled);
  background: var(--ios-fill-disabled);
  color: var(--ios-text-disabled);
}

/* Пример в недоступном поле (режим просмотра) читался бы как значение —
 * у недоступного поля его не видно (этап S4) */
.portal-field__input:disabled::placeholder {
  opacity: 0;
}

.portal-field__input[aria-invalid="true"],
.portal-field--invalid .portal-field__input {
  border-color: var(--ios-status-danger);
}

/* Обёртка Rails вокруг поля модели с ошибкой (field_error_proc) в
 * раскладке не участвует: поле остаётся прямым элементом .portal-field,
 * ошибку показывает .portal-field__error ниже (этап S4) */
.portal-body .field_with_errors {
  display: contents;
}

/* Ошибка — текстом под полем (бриф §3 «Поле ввода»; «ошибки у полей во
 * всех формах», этап S4). Длинное значение в тексте ошибки переносится */
.portal-field__error {
  margin: 0;
  font: var(--ios-type-secondary);
  color: var(--ios-status-danger);
  overflow-wrap: anywhere;
}

.portal-field__hint {
  margin: 0;
  font: var(--ios-type-caption);
  color: var(--ios-text-secondary);
}

/* Группа полей формы (этап S4): в режиме просмотра одна группа
 * отключает все поля и кнопку отправки сразу (атрибут disabled у
 * fieldset). Рамки и отступов браузера у неё нет — раскладку держит
 * форма */
.portal-fieldset {
  display: grid;
  gap: inherit;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

/* Причина, по которой форма отключена (режим просмотра): обычный
 * вторичный текст рядом с формой — --ios-text-disabled только у самого
 * недоступного элемента (решения v2 §2 «Недоступный элемент») */
.portal-readonly-note {
  margin: 0;
  font: var(--ios-type-secondary);
  color: var(--ios-text-secondary);
}

/* «Идёт отправка» (бриф §4.1 «идёт вход», §4.9; этап S4): Turbo на время
 * запроса делает кнопку недоступной, ставит форме aria-busy и меняет
 * подпись (data-turbo-submits-with). Занятая основная кнопка остаётся
 * акцентной («нажата»), а не серой, как недоступная по причине.
 * «Записать обещание» стоит вне своей формы (атрибут form, в форме
 * method="dialog" листа): aria-busy получает форма своей даты, поэтому
 * второй селектор (доводка S4). В режиме просмотра форма не занята —
 * недоступная кнопка остаётся серой */
.portal-body [aria-busy="true"] .portal-button--primary:disabled,
.portal-body .portal-promise-sheet:has(#portal-promise-form[aria-busy="true"]) .portal-sheet__actions .portal-button--primary:disabled {
  background: var(--ios-accent-active);
  color: var(--ios-text-on-accent);
  cursor: progress;
}

.portal-body input[type="checkbox"] {
  width: var(--ios-check-size);
  height: var(--ios-check-size);
  accent-color: var(--ios-accent);
}

/* ============================================================
 * Flash над содержимым: успех (role=status) и ошибка (role=alert)
 * ============================================================ */

.portal-flash {
  margin: 0 0 var(--ios-space-4);
  padding: var(--ios-space-3) var(--ios-space-4);
  border-radius: var(--ios-radius-plate);
  font: var(--ios-type-secondary);
}

.portal-flash--notice {
  color: var(--ios-status-success);
  background: var(--ios-status-success-bg);
}

.portal-flash--alert {
  color: var(--ios-status-danger);
  background: var(--ios-status-danger-bg);
}

/* Баннер режима просмотра коробки (бриф §4.0, этап S4): нейтральная
 * плашка над flash — не ошибка и не просрочка (решения v2 §2 «Тон
 * статусов»); текст своими словами, без служебных команд */
.portal-license {
  margin: 0 0 var(--ios-space-4);
  padding: var(--ios-space-3) var(--ios-space-4);
  border-radius: var(--ios-radius-plate);
  background: var(--ios-status-neutral-bg);
  color: var(--ios-text);
  font: var(--ios-type-secondary);
}

/* Плашка демо-стенда (Demo::ProfileSwitch): кабинет открыт из «Смотреть
 * как» CRM. Не часть кабинета — пунктир и тег «Демо», как в CRM */
.portal-demo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ios-space-2) var(--ios-space-3);
  margin: 0 0 var(--ios-space-4);
  padding: var(--ios-space-3) var(--ios-space-4);
  border: 1px dashed var(--warning-border);
  border-radius: var(--ios-radius-plate);
  background: var(--ios-status-warning-bg);
  color: var(--ios-text);
  font: var(--ios-type-secondary);
}

.portal-demo__tag {
  padding: 0 var(--ios-space-1);
  border: 1px solid var(--warning-border);
  border-radius: var(--ios-radius-badge);
  background: var(--ios-surface);
  color: var(--ios-status-warning);
  font-weight: 600;
}

.portal-demo__link {
  margin-left: auto;
  font-weight: 600;
}

/* ============================================================
 * Шаблон блока на фоне (бриф §3 п. 2): надстрочник → заголовок →
 * подзаголовок → действие. Вход, «Ссылка устарела», «Не найдено»,
 * ошибка загрузки — по центру, без карточки и без красного (этап S4)
 * ============================================================ */

.portal-notice {
  padding: var(--ios-space-20) 0 var(--ios-space-12);
  text-align: center;
}

.portal-notice__overline {
  margin-bottom: var(--ios-space-2);
}

.portal-notice__title {
  margin: 0 0 var(--ios-space-3);
  font: var(--ios-type-h1);
  letter-spacing: var(--ios-tracking-h1);
}

/* Подзаголовок шаблона блока — роль subtitle обычного начертания (бриф §3
 * п. 2); вторичный цвет — спокойный вид, не как у ошибки (бриф §4.2) */
.portal-notice__text {
  margin: 0;
  color: var(--ios-text-secondary);
  font: var(--ios-type-subtitle);
}

.portal-notice__action {
  margin: var(--ios-space-6) 0 0;
}

/* Пустое состояние в потоке страницы (главная без договоров) */
.portal-notice--inline {
  padding: var(--ios-space-8) var(--ios-space-4);
}

/* Пустое состояние CRM внутри кабинета */
.portal-body .empty-state__title {
  font: var(--ios-type-body);
  font-weight: 600;
}

.portal-body .empty-state__description {
  margin: var(--ios-space-1) 0 0;
  font: var(--ios-type-secondary);
  color: var(--ios-text-secondary);
}

/* ============================================================
 * Нижний лист на нативном <dialog> (решения v2 §2 «Поверхности»):
 * без тени и ручки, не выше 90% окна (у fixed-элемента процент — от
 * окна). Лист — колонка из двух блоков: .portal-sheet__body прокручивается,
 * .portal-sheet__actions (кнопки) стоит под ним вне прокрутки и несёт
 * нижний отступ с safe-area (бриф §3 «Нижний лист», решения v2 §5
 * «Кнопка листа»). Кнопки не накрывают содержимое: элемент в фокусе
 * докручивается внутри тела и не уходит под них (бриф §8, WCAG 2.4.11).
 * На десктопе — диалог по центру с тенью --ios-shadow-dialog.
 * Появление — прогрессивное улучшение (@starting-style); при reduced
 * motion длительности 0 — лист появляется сразу.
 * ============================================================ */

.portal-sheet {
  position: fixed;
  inset: auto 0 0;
  width: 100%;
  max-width: var(--ios-container-narrow);
  max-height: 90%;
  margin: 0 auto;
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: var(--ios-radius-sheet) var(--ios-radius-sheet) 0 0;
  background: var(--ios-surface);
  color: var(--ios-text);
  font: var(--ios-type-body);
}

/* Только открытый: закрытый <dialog> прячет display: none браузера */
.portal-sheet[open] {
  display: flex;
  flex-direction: column;
}

/* Лист, открытый сервером без JS (?sheet=…, этап S2), — немодальный
 * <dialog open>: он не в верхнем слое, поэтому встаёт над липкой панелью
 * и шапкой таблицы слоем меню. С JS контроллер делает его модальным */
.portal-sheet[open]:not(:modal) {
  z-index: var(--ios-z-menu);
}

/* Кнопка, открывающая лист, — внутри GET-формы (без JS форма открывает
 * главную с листом); в раскладке форма не участвует */
.portal-sheet-trigger {
  display: contents;
}

.portal-sheet::backdrop {
  background: var(--ios-backdrop);
}

/* Прокручиваемое тело: поля экрана — внутри области прокрутки, чтобы
 * кольцо фокуса у края не обрезалось; снизу — запас на кольцо.
 * position: relative — абсолютные потомки (скрытые поля копирования
 * реквизитов) прокручиваются с телом, а не с листом: иначе они выходят за
 * край тела, и фокус на них прокручивает сам лист вместе с кнопками */
.portal-sheet__body {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  padding: var(--ios-space-6) var(--ios-gutter) var(--ios-space-1);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.portal-sheet__title {
  margin: 0 0 var(--ios-space-1);
  font: var(--ios-type-block);
}

.portal-sheet__sub {
  margin: 0 0 var(--ios-space-4);
  font: var(--ios-type-secondary);
  color: var(--ios-text-secondary);
}

.portal-sheet__text {
  margin: 0 0 var(--ios-space-1);
}

/* Плашка в листе (нет расчётного счёта, A2): текст и тон задаёт экран */
.portal-sheet__banner {
  margin: 0 0 var(--ios-space-5);
  padding: var(--ios-space-3) var(--ios-space-4);
  border-radius: var(--ios-radius-plate);
  font: var(--ios-type-secondary);
}

/* Кнопки — вне прокрутки, всегда внизу листа. Зазор до тела — 16 вместе
 * с запасом на кольцо у тела; нижний отступ — с safe-area */
.portal-sheet__actions {
  flex: none;
  display: grid;
  gap: var(--ios-space-2);
  padding: var(--ios-space-3) var(--ios-gutter) calc(var(--ios-space-5) + env(safe-area-inset-bottom, 0px));
}

@supports (transition-behavior: allow-discrete) {
  .portal-sheet {
    transform: translateY(100%);
    transition: transform var(--ios-duration) var(--ios-ease),
      overlay var(--ios-duration) allow-discrete,
      display var(--ios-duration) allow-discrete;
  }

  .portal-sheet[open] {
    transform: none;
  }

  @starting-style {
    .portal-sheet[open] {
      transform: translateY(100%);
    }
  }
}

/* Десктоп — диалог по центру («предложение, обязательное», бриф §4.5):
 * все углы скруглены, тень всплывающего диалога, шире телефонного листа —
 * реквизиты и назначение платежа переносятся реже */
@media (min-width: 900px) {
  .portal-sheet {
    inset: 0;
    max-width: var(--ios-dialog-width);
    height: fit-content;
    margin: auto;
    border-radius: var(--ios-radius-sheet);
    box-shadow: var(--ios-shadow-dialog);
  }

  .portal-sheet__body {
    padding: var(--ios-space-8) var(--ios-space-8) var(--ios-space-1);
  }

  .portal-sheet__actions {
    padding: var(--ios-space-3) var(--ios-space-8) var(--ios-space-8);
  }

  @supports (transition-behavior: allow-discrete) {
    .portal-sheet {
      opacity: 0;
      transform: none;
      transition: opacity var(--ios-duration) var(--ios-ease),
        overlay var(--ios-duration) allow-discrete,
        display var(--ios-duration) allow-discrete;
    }

    .portal-sheet[open] {
      opacity: 1;
    }

    @starting-style {
      .portal-sheet[open] {
        opacity: 0;
      }
    }
  }
}

/* ============================================================
 * Скелетон главной (бриф §4.0): блоки в форме hero и группы строк.
 * Класс .skeleton из CRM сохранён (его ждут тесты) — вид сброшен
 * ============================================================ */

.portal-body .skeleton.portal-skeleton {
  display: grid;
  gap: var(--ios-space-3);
  margin: 0;
  padding: var(--ios-space-4) 0 0;
  border: 0;
  background: none;
}

.portal-skeleton__block {
  height: var(--ios-space-4);
  border-radius: var(--ios-radius-badge);
  background: var(--ios-skeleton-fill);
  animation: portal-shimmer var(--ios-duration-shimmer) var(--ios-ease) infinite;
}

.portal-skeleton__block--overline,
.portal-skeleton__block--line {
  width: 50%;
}

.portal-skeleton__block--amount {
  width: 90%;
  height: var(--ios-amount-max);
  border-radius: var(--ios-radius-plate);
}

.portal-skeleton__block--button {
  width: 50%;
  height: var(--ios-button-height);
  margin-top: var(--ios-space-3);
  border-radius: var(--ios-radius-pill);
}

.portal-skeleton__group {
  margin-top: var(--ios-gap-section);
  background: var(--ios-surface);
  border-radius: var(--ios-card-radius);
}

.portal-skeleton__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ios-space-4);
  min-height: var(--ios-row-height);
  padding: 0 var(--ios-space-4);
}

.portal-skeleton__row + .portal-skeleton__row {
  border-top: 1px solid var(--ios-separator);
}

.portal-skeleton__block--label {
  flex: 1;
}

.portal-skeleton__block--value {
  flex: none;
  width: var(--ios-space-24);
}

@keyframes portal-shimmer {
  0%,
  100% { opacity: 1; }
  50% { opacity: .5; }
}

/* Движение отключаемо: длительности уже 0 (tokens.css), скелетон статичен */
@media (prefers-reduced-motion: reduce) {
  .portal-skeleton__block {
    animation: none;
  }
}

/* ============================================================
 * «Войти по почте» (Р-101, E1): форма адреса в шаблоне блока на фоне —
 * поле и кнопка по ширине узкого контейнера, подписи слева
 * ============================================================ */

.portal-login__form {
  display: grid;
  gap: var(--ios-space-4);
  margin: var(--ios-space-6) 0 0;
  text-align: left;
}

.portal-login__note {
  margin-top: var(--ios-space-3);
}

/* ============================================================
 * Вход по паролю и «Профиль» (Р-130, Р-105, E4)
 * ============================================================ */

/* Ссылка внутри фразы подвала («задайте пароль в профиле») — в строку */
.portal-footer__link {
  color: inherit;
}

/* «Профиль» в шапке — кружок с инициалами рядом с колокольчиком на обеих
 * ширинах; зона нажатия 44, как у колокольчика. Текущая страница — кольцо
 * акцентом: не только цветом фона */
.portal-nav__profile {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  min-width: var(--ios-touch-min);
  min-height: var(--ios-touch-min);
  text-decoration: none;
}

.portal-nav__avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--ios-space-8);
  height: var(--ios-space-8);
  border-radius: 50%;
  background: var(--ios-status-neutral-bg);
  color: var(--ios-accent);
  font: var(--ios-type-badge);
}

.portal-body .portal-nav__profile:hover .portal-nav__avatar {
  color: var(--ios-accent-hover);
}

.portal-body .portal-nav__profile[aria-current="page"] .portal-nav__avatar {
  box-shadow: 0 0 0 var(--ios-focus-width) var(--ios-text);
  color: var(--ios-text);
}

/* Выбор арендатора после входа паролем: кнопки во всю ширину столбиком */
.portal-login__choices {
  display: grid;
  gap: var(--ios-space-3);
  margin: var(--ios-space-6) 0 0;
  padding: 0;
  list-style: none;
}

.portal-login__choice {
  margin: 0;
}

/* Формы профиля — поля столбиком, кнопка под ними слева */
.portal-profile__form {
  display: grid;
  gap: var(--ios-space-4);
  margin: var(--ios-space-4) 0 0;
}

.portal-profile__form .portal-button {
  justify-self: start;
}

.portal-profile__lead {
  margin: 0 0 var(--ios-space-2);
}

/* Адрес почты длинный и без пробелов — переносится где угодно */
.portal-profile__email {
  overflow-wrap: anywhere;
}

.portal-profile__people {
  margin-top: 0;
  padding: 0;
  list-style: none;
}

.portal-profile__signout {
  margin: var(--ios-space-3) 0 0;
}

/* Имя и «это вы · адрес» — строками друг под другом */
.portal-profile__people .portal-row__title,
.portal-profile__people .portal-row__sub {
  display: block;
}

.portal-profile__people .portal-row__sub {
  overflow-wrap: anywhere;
}
