/* ============================================================
 * Кабинет арендатора v2 — главная (бриф §4.3, §4.4, §4.5, §4.6).
 * Этап S1: шапка с h1, hero по шаблону блока, состояния главной,
 * строки счетов, сетка десктопа и колонка бухгалтера. Этап S2: листы
 * «Оплата» и «Когда сможете оплатить?», плашка обещания.
 * Только var(--ios-*); литералы — по списку в шапке portal.css.
 * ============================================================ */

/* --- Шапка: УК · арендатор, h1 (переключатель договоров), инициалы --- */

.portal-header {
  display: flex;
  align-items: flex-start;
  gap: var(--ios-space-3);
  padding: var(--ios-space-2) 0 0;
}

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

/* h1 главной — роль --ios-type-h1 (.portal-title), без отступов шаблона
 * страницы: шапка сама задаёт ритм. Длинное название переносится */
.portal-header__title {
  margin: var(--ios-space-1) 0 0;
  overflow-wrap: anywhere;
}

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

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

/* Инициалы — декор, не кнопка: нейтральный кружок без акцента (бриф §4.3),
 * скрыт от скринридера (aria-hidden). Текст — нейтральный статусный тон:
 * на подложке --ios-status-neutral-bg он даёт 6,06:1 (вторичный — 4,16) */
.portal-avatar {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: var(--ios-space-8);
  height: var(--ios-space-8);
  margin-top: var(--ios-space-1);
  border-radius: 50%;
  background: var(--ios-status-neutral-bg);
  color: var(--ios-status-neutral);
  font: var(--ios-type-badge);
}

/* Переключатель договоров — меню на <details>, без JS. h1 — вне summary
 * (заголовок внутри кнопки скринридер не объявляет); summary без текста
 * растянут поверх названия, так что нажатие по названию открывает меню, а
 * кольцо фокуса обводит его целиком. Зона нажатия — не ниже 44 (бриф §8):
 * строка h1 на телефоне 34, на десктопе 38 */
.portal-switcher {
  position: relative;
  display: flex;
  align-items: center;
  min-height: var(--ios-touch-min);
}

.portal-switcher__summary {
  position: absolute;
  inset: 0;
  display: block;
  min-height: var(--ios-touch-min);
  list-style: none;
  cursor: pointer;
}

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

.portal-switcher__summary::-webkit-details-marker {
  display: none;
}

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

.portal-switcher__caret {
  display: inline-block;
  color: var(--ios-icon-muted);
  transition: transform var(--ios-duration-fast) var(--ios-ease);
}

.portal-switcher:has(> .portal-switcher__details[open]) .portal-switcher__caret {
  transform: rotate(90deg);
}

/* Меню — под названием: details без позиционирования, отсчёт от
 * .portal-switcher */
.portal-switcher__menu {
  position: absolute;
  z-index: var(--ios-z-menu);
  top: 100%;
  left: 0;
  right: 0;
  margin-top: var(--ios-space-2);
  overflow: hidden;
  border-radius: var(--ios-radius-field);
  background: var(--ios-surface);
  box-shadow: var(--ios-shadow-popover);
}

.portal-body .portal-switcher__item {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--ios-space-1);
  min-height: var(--ios-row-height);
  padding: var(--ios-space-3) var(--ios-space-4);
  color: var(--ios-text);
  text-decoration: none;
}

.portal-body .portal-switcher__item:hover {
  background: var(--ios-bg);
  color: var(--ios-text);
  text-decoration: none;
}

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

.portal-switcher__name {
  overflow-wrap: anywhere;
}

.portal-switcher__hint {
  font: var(--ios-type-secondary);
  color: var(--ios-text-secondary);
  overflow-wrap: anywhere;
}

.portal-switcher__item--current .portal-switcher__name {
  font-weight: 600;
}

.portal-switcher__item--current .portal-switcher__hint {
  color: var(--ios-text);
}

/* --- Hero — главный ответ: без карточки, на фоне страницы (бриф §3 п. 1).
 *     Шаблон «надстрочник → сумма → подзаголовок → таблетка + ссылка».
 *     Кегль суммы — формула от ширины контейнера (решения v2 §2) --- */

/* Интервал после hero — --ios-gap-hero (48 / 80, роль из доски токенов).
 * Следующий блок сам отступает на --ios-gap-section (32 / 64: «Сумма
 * изменится», плашка обещания, секции); hero добирает разницу снизу —
 * отступы не схлопываются (padding), итог ровно --ios-gap-hero */
.portal-hero {
  container-type: inline-size;
  padding: var(--ios-space-6) 0 calc(var(--ios-gap-hero) - var(--ios-gap-section));
}

/* Сумма всегда основным цветом, JetBrains Mono 600; --len — число знаков
 * с пробелами и ₽, класс ставит сервер (portal_amount_len_class) */
.portal-hero__amount {
  --len: 16;
  margin: var(--ios-space-1) 0 var(--ios-space-2);
  color: var(--ios-text);
  font-family: var(--ios-font-mono);
  font-size: clamp(var(--ios-amount-min), calc(100cqi / (var(--len) * var(--ios-amount-advance))), var(--ios-amount-max));
  font-weight: 600;
  line-height: var(--ios-amount-leading);
  letter-spacing: var(--ios-tracking-display);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.portal-hero__amount--len-6 { --len: 6; }
.portal-hero__amount--len-7 { --len: 7; }
.portal-hero__amount--len-8 { --len: 8; }
.portal-hero__amount--len-9 { --len: 9; }
.portal-hero__amount--len-10 { --len: 10; }
.portal-hero__amount--len-11 { --len: 11; }
.portal-hero__amount--len-12 { --len: 12; }
.portal-hero__amount--len-13 { --len: 13; }
.portal-hero__amount--len-14 { --len: 14; }
.portal-hero__amount--len-15 { --len: 15; }
.portal-hero__amount--len-16 { --len: 16; }

@container (min-width: 440px) {
  .portal-hero__amount {
    --ios-amount-max: var(--ios-amount-max-wide);
  }
}

/* «Оплатить до ДД.ММ.ГГГГ» — подзаголовок шаблона: обычное начертание */
.portal-hero__due {
  margin: 0;
  font: var(--ios-type-subtitle);
  font-variant-numeric: tabular-nums;
}

/* Плашка просрочки — единственный красный элемент hero; встаёт на место
 * «Оплатить до». Суммы пеней внутри фразы — Onest с табличными цифрами */
.portal-hero__overdue {
  display: inline-block;
  margin: 0;
  padding: var(--ios-space-1) var(--ios-space-3);
  border-radius: var(--ios-radius-plate);
  background: var(--ios-status-danger-bg);
  color: var(--ios-status-danger);
  font: var(--ios-type-secondary);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* «· пени 2 057,41 ₽» не рвётся: перенос — перед точкой */
.portal-hero__penalty {
  white-space: nowrap;
}

/* Таблетка «Оплатить …» и текстовая «Обещаю оплатить до…» — в строку,
 * на узком экране ссылка переносится под таблетку */
.portal-hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ios-space-2) var(--ios-space-6);
  margin-top: var(--ios-space-6);
}

/* «Всё оплачено» — по центру (бриф §3 «Выравнивание»): галочка,
 * заголовок в роли h1, прогноз. Без конфетти и анимаций */
.portal-hero--settled {
  padding-top: var(--ios-space-8);
  text-align: center;
}

.portal-hero__ok {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--ios-space-16);
  height: var(--ios-space-16);
  margin: 0 auto var(--ios-space-4);
  border-radius: 50%;
  background: var(--ios-status-success-bg);
  color: var(--ios-status-success);
}

.portal-hero__ok-icon {
  width: var(--ios-space-8);
  height: var(--ios-space-8);
}

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

/* Прогноз — подзаголовок шаблона блока (бриф §3 п. 2, §4.3: «подзаголовок
 * с прогнозом»), обычное начертание. Только в левой колонке 360 от 1184px —
 * основной текст (см. сетку десктопа ниже): подзаголовок 26/32 растянул
 * бы фразу там на пять строк */
.portal-hero__hint {
  margin: var(--ios-space-2) 0 0;
  color: var(--ios-text-secondary);
  font: var(--ios-type-subtitle);
  font-variant-numeric: tabular-nums;
}

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

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

/* --- Чек «Оплачено» (дизайн v3, T2; ролик «Run Receipt»): квитанция
 *     вместо галочки «всё оплачено». Бумага — белая, строки моно с
 *     табличными цифрами, пунктирные разделители, рваный нижний край
 *     маской (зубцы — половина --ios-receipt-tooth); без mask — ровный
 *     край. Тень — drop-shadow обёртки: повторяет форму зубцов, а
 *     box-shadow маска срезала бы. Текст слева: чек читается как документ,
 *     а не как заголовок по центру --- */

.portal-hero--receipt {
  padding-top: var(--ios-space-6);
}

.portal-receipt {
  width: 100%;
  max-width: var(--ios-receipt-width);
  margin: 0 auto var(--ios-space-4);
  filter: var(--ios-receipt-shadow);
  text-align: left;
}

.portal-receipt__paper {
  padding: var(--ios-space-5) var(--ios-space-5) var(--ios-space-6);
  background: var(--ios-surface);
  font: var(--ios-type-receipt);
  font-variant-numeric: tabular-nums;
}

@supports (mask: none) or (-webkit-mask: none) {
  .portal-receipt__paper {
    padding-bottom: calc(var(--ios-space-6) + var(--ios-receipt-tooth) / 2);
    -webkit-mask: var(--ios-receipt-edge);
    mask: var(--ios-receipt-edge);
  }
}

.portal-receipt__title {
  margin: 0;
  font: var(--ios-type-receipt-title);
}

.portal-receipt__meta {
  margin: var(--ios-space-1) 0 0;
  color: var(--ios-text-secondary);
}

.portal-receipt__meta .portal-num {
  white-space: nowrap;
}

/* Группа строк — между пунктирными линиями */
.portal-receipt__lines {
  margin: var(--ios-space-3) 0 0;
  padding: var(--ios-space-3) 0 0;
  border-top: 1px dashed var(--ios-receipt-rule);
}

/* «Подпись — значение»: значение справа, не переносится; длинная
 * подпись переносится сама */
.portal-receipt__line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--ios-space-3);
}

.portal-receipt__line dt,
.portal-receipt__line dd {
  margin: 0;
}

.portal-receipt__line dt {
  min-width: 0;
}

.portal-receipt__line dd {
  flex: none;
  white-space: nowrap;
}

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

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

/* --- «Сумма изменится» (Р-38): не пары «подпись — значение» — на фоне,
 *     с переходом в историю условий --- */

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

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

.portal-changes__title {
  margin: 0;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

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

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

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

/* --- Плашка записанного обещания: ожидание — оранжевый тон (текст 6,05:1,
 *     «Изменить» акцентом 5,78:1 на подложке). Текст слева, «Изменить»
 *     справа; зона нажатия «Изменить» — 44×44 при лёгком виде (этап S2,
 *     бриф §6: раньше ≈20), плашка в одну строку — ровно 44 --- */

.portal-promise-note {
  display: flex;
  align-items: center;
  gap: var(--ios-space-3);
  margin: var(--ios-gap-section) 0 0;
  padding: 0 var(--ios-space-2) 0 var(--ios-space-4);
  border-radius: var(--ios-radius-plate);
  background: var(--ios-status-warning-bg);
  color: var(--ios-status-warning);
  font: var(--ios-type-secondary);
}

.portal-promise-note__text {
  flex: 1;
  min-width: 0;
  margin: 0;
  padding: var(--ios-space-3) 0;
}

/* Дизайн v3, T3: «Напоминания на паузе до ДД.ММ.ГГГГ» — заголовок
 * плашки начертанием 600, обещание — строкой под ним обычным; тон тот же
 * (ожидание). Дата не отрывается от предлога: перенос — до «до» */
.portal-promise-note__title,
.portal-promise-note__sub {
  margin: 0;
  font-variant-numeric: tabular-nums;
}

.portal-promise-note__title {
  font-weight: 600;
}

.portal-promise-note__until {
  white-space: nowrap;
}

.portal-promise-note__title + .portal-promise-note__sub {
  margin-top: var(--ios-space-1);
}

.portal-promise-note__edit {
  flex: none;
  min-width: var(--ios-touch-min);
  min-height: var(--ios-touch-min);
  padding: 0 var(--ios-space-2);
  border: 0;
  border-radius: var(--ios-radius-plate);
  background: none;
  color: var(--ios-accent);
  font: inherit;
  cursor: pointer;
}

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

/* --- Товарооборот (Р-28): заголовок блока — сама просьба, форма на фоне;
 *     сданный отчёт — пары «подпись — значение» в группе --- */

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

.portal-turnover__edit-toggle {
  display: flex;
  align-items: center;
  gap: var(--ios-space-1);
  width: fit-content;
  min-height: var(--ios-touch-min);
  list-style: none;
  cursor: pointer;
}

.portal-turnover__edit-toggle::-webkit-details-marker {
  display: none;
}

.portal-turnover__edit-toggle::after {
  content: "›";
  content: "›" / "";
  display: inline-block;
  transition: transform var(--ios-duration-fast) var(--ios-ease);
}

.portal-turnover__edit[open] .portal-turnover__edit-toggle::after {
  transform: rotate(90deg);
}

.portal-turnover__form {
  display: grid;
  gap: var(--ios-space-3);
}

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

/* ДС индексации на подписи (Р-29): строка «было → стало» длинная —
 * мельче и с переносом в любом месте */
.portal-amendment-preview {
  font: var(--ios-type-caption);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

/* --- Счета на телефоне: строка с раскрытием состава (<details>, без JS).
 *     Шеврон «›» — справа, поворот на 90° при раскрытии (бриф §4.3) --- */

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

.portal-invoice__summary {
  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);
  list-style: none;
  cursor: pointer;
}

.portal-invoice__summary::-webkit-details-marker {
  display: none;
}

.portal-invoice__head {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--ios-space-1);
  min-width: 0;
}

.portal-invoice__title {
  font: var(--ios-type-secondary);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

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

.portal-invoice__note {
  font: var(--ios-type-secondary);
  font-variant-numeric: tabular-nums;
}

/* Подстроки состояния: просрочка — красный, частичная оплата и близкий
 * срок — оранжевый, «не к оплате» — нейтральный (бриф §4.3) */
.portal-note--danger { color: var(--ios-status-danger); }
.portal-note--warning { color: var(--ios-status-warning); }
.portal-note--muted { color: var(--ios-text-secondary); }

.portal-invoice__side {
  display: flex;
  flex: none;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--ios-space-1);
}

/* Сумма отдельным значением — моно в кегле строки (обычная, 400) */
.portal-invoice__amount {
  font: var(--ios-type-secondary);
  font-family: var(--ios-font-mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Аннулированный счёт — сумма документа не к оплате: вторичным цветом */
.portal-invoice--void .portal-invoice__amount {
  color: var(--ios-text-secondary);
}

.portal-invoice__chevron {
  flex: none;
  color: var(--ios-icon-muted);
  transition: transform var(--ios-duration-fast) var(--ios-ease);
}

.portal-invoice[open] .portal-invoice__chevron {
  transform: rotate(90deg);
}

.portal-invoice__detail {
  padding: 0 var(--ios-space-4) var(--ios-space-2);
}

/* «Открыть счёт ›» и «Скачать PDF» — явные действия, зона нажатия 44 */
.portal-invoice__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--ios-space-6);
  margin: var(--ios-space-1) 0 0;
}

.portal-invoice__open,
.portal-invoice__pdf {
  display: inline-flex;
  align-items: center;
  min-height: var(--ios-touch-min);
}

/* Много счетов — группы по годам (<details>), раскрыт текущий год */
.portal-invoice-year + .portal-invoice-year {
  margin-top: var(--ios-space-2);
}

.portal-invoice-year__summary {
  display: flex;
  align-items: center;
  gap: var(--ios-space-2);
  min-height: var(--ios-touch-min);
  list-style: none;
  cursor: pointer;
}

.portal-invoice-year__summary::-webkit-details-marker {
  display: none;
}

.portal-invoice-year__title {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.portal-invoice-year__sep,
.portal-invoice-year__count {
  font: var(--ios-type-secondary);
  color: var(--ios-text-secondary);
}

.portal-invoice-year__summary::after {
  content: "›";
  content: "›" / "";
  margin-left: auto;
  color: var(--ios-icon-muted);
  transition: transform var(--ios-duration-fast) var(--ios-ease);
}

.portal-invoice-year[open] > .portal-invoice-year__summary::after {
  transform: rotate(90deg);
}

/* Пусто — честное состояние на фоне, по центру (бриф §3 «Выравнивание») */
.portal-invoices-mobile__empty {
  padding: var(--ios-space-4) 0;
  text-align: center;
}

/* --- Депозит (Р-9): справочная сумма, не оплата; пояснение — сноской --- */

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

/* --- Лист «Оплата» (Р-26; бриф §4.5, этап S2): реквизиты группами
 *     «Получатель», «Банк», «Платёж», у каждой строки «Скопировать».
 *     Лист — белая поверхность: группы разделяет воздух и заголовок над
 *     группой (роль надстрочника, как у групп документов), строки — линии.
 *     Подложку группам не даём: на белом она была бы фоном страницы, и
 *     «Скопировать» (заливка фоном страницы) на ней пропала бы --- */

.portal-requisite-group + .portal-requisite-group {
  margin-top: var(--ios-space-6);
}

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

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

/* Кнопка — по верху строки: у многострочного назначения она не уезжает
 * в середину абзаца */
.portal-requisite {
  display: flex;
  align-items: flex-start;
  gap: var(--ios-space-3);
  padding: var(--ios-space-2) 0;
  border-top: 1px solid var(--ios-separator);
}

.portal-requisite:first-child {
  border-top: 0;
}

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

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

/* Длинные значения (название юрлица, назначение до 210 знаков, р/с из 20
 * цифр) переносятся целиком, не обрезаются */
.portal-requisite__value {
  overflow-wrap: anywhere;
}

/* Коды (ИНН, КПП, БИК, счета из 20 цифр) — одно «слово»: на 375 рядом с
 * «Скопировать» счёт не помещается, и перенос в конце давал «…022 / 5».
 * Переносим посередине: любые места переноса + выравнивание строк */
.portal-requisite__value--code {
  word-break: break-all;
  text-wrap: balance;
}

/* Реквизит «Сумма» — отдельная сумма: моно (решения v2 §2 «Где моно») */
.portal-requisite[data-requisite="amount"] .portal-requisite__value {
  font-family: var(--ios-font-mono);
}

/* Источник копирования — значение «для буфера» (без NBSP и U+2212).
 * Обычно вне экрана; при ошибке копирования — видимое поле ниже */
.portal-requisite__source {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.portal-requisite__side {
  display: flex;
  flex-shrink: 0;
}

/* «Скопировать» — второстепенная таблетка на белом листе: заливка фоном
 * страницы (решения v2 §2 «Поверхности»), зона нажатия 44 (бриф §4.5) */
.portal-requisite__copy {
  min-width: var(--ios-touch-min);
  min-height: var(--ios-touch-min);
  padding: 0 var(--ios-space-3);
  border: 0;
  border-radius: var(--ios-radius-pill);
  background: var(--ios-bg);
  color: var(--ios-accent);
  font: var(--ios-type-button-nav);
  cursor: pointer;
  transition: background-color var(--ios-duration-fast) var(--ios-ease),
    color var(--ios-duration-fast) var(--ios-ease);
}

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

/* Без JS копировать нечем — кнопки нет (мёртвых кнопок не бывает);
 * значение видно и выделяется на экране */
@media (scripting: none) {
  .portal-requisite__copy {
    display: none;
  }
}

/* «Скопировано» — принято: зелёный тон (5,76:1 на своей подложке);
 * появление — --ios-duration-fast, при reduced motion сразу */
.portal-requisite[data-clipboard-state="copied"] .portal-requisite__copy {
  background: var(--ios-status-success-bg);
  color: var(--ios-status-success);
}

/* Ошибка копирования (бриф §4.5, «предложение, обязательное»): сообщение
 * красным под значением, ниже — видимое выделенное поле со значением
 * «для буфера»: скопировать вручную. Поле 17px — iOS не увеличивает
 * страницу при фокусе */
.portal-requisite__error {
  margin: var(--ios-space-1) 0 0;
  font: var(--ios-type-secondary);
  color: var(--ios-status-danger);
}

.portal-requisite[data-clipboard-state="error"] .portal-requisite__source {
  position: static;
  box-sizing: border-box;
  display: block;
  width: 100%;
  height: auto;
  min-height: var(--ios-field-height);
  margin: var(--ios-space-2) 0 0;
  padding: var(--ios-space-3) var(--ios-space-4);
  border: 1px solid var(--ios-control-border);
  border-radius: var(--ios-radius-field);
  opacity: 1;
  background: var(--ios-surface);
  color: var(--ios-text);
  font: var(--ios-type-body);
  font-variant-numeric: tabular-nums;
  pointer-events: auto;
  resize: none;
  field-sizing: content;
}

/* Нет расчётного счёта (A2): ожидание данных от управляющего — оранжевый
 * тон плашки (6,05:1) */
.portal-requisites__missing {
  background: var(--ios-status-warning-bg);
  color: var(--ios-status-warning);
}

/* --- Лист «Когда сможете оплатить?» (бриф §4.6, этап S2): текущее
 *     обещание, пресеты и своя дата с ошибкой под полем --- */

.portal-promise-current {
  margin: 0 0 var(--ios-space-4);
  font-variant-numeric: tabular-nums;
}

.portal-presets {
  display: flex;
  gap: var(--ios-space-2);
  margin-bottom: var(--ios-space-5);
}

/* Форма пресета растягивает кнопку: пресеты одной высоты, даже если
 * подпись «Через неделю» перенеслась на две строки */
.portal-preset-form {
  display: flex;
  flex: 1;
  min-width: 0;
}

/* Пресет на белом листе — заливка фоном страницы (решения v2 §2).
 * Растянутый по высоте соседа пресет держит подпись и дату по центру */
.portal-preset {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--ios-space-1);
  width: 100%;
  min-height: var(--ios-button-height);
  padding: var(--ios-space-2);
  border: 0;
  border-radius: var(--ios-radius-field);
  background: var(--ios-bg);
  color: var(--ios-text);
  font: var(--ios-type-secondary);
  cursor: pointer;
  transition: background-color var(--ios-duration-fast) var(--ios-ease);
}

.portal-preset:active {
  background: var(--ios-accent-tint);
}

/* Дата текущего обещания совпала с пресетом — индикатор выбранного:
 * кольцо внутрь цветом рамки полей (3,73:1 к заливке пресета, не ниже 3:1 —
 * бриф §3) и подпись 600; не акцентом — синее кольцо читалось бы как фокус
 * (он тоже синий, снаружи). Для скринридера — скрытый текст «— текущее
 * обещание» в разметке */
.portal-preset--current {
  box-shadow: inset 0 0 0 2px var(--ios-control-border);
}

.portal-preset--current .portal-preset__label {
  font-weight: 600;
}

.portal-preset__date {
  font: var(--ios-type-caption);
  color: var(--ios-text-secondary);
  font-variant-numeric: tabular-nums;
}

/* Режим просмотра (этап S4): пресет недоступен — заливка и текст
 * недоступного элемента, дата тем же цветом; причина — строкой выше */
.portal-preset:disabled,
.portal-preset:disabled .portal-preset__date {
  color: var(--ios-text-disabled);
}

.portal-preset:disabled {
  background: var(--ios-fill-disabled);
  cursor: not-allowed;
}

.portal-promise-sheet .portal-readonly-note {
  margin-bottom: var(--ios-space-4);
}

.portal-promise-form {
  display: grid;
  gap: var(--ios-space-3);
}

/* ============================================================
 * Десктоп главной и колонка бухгалтера (бриф §4.4; F.3, Р-19): та же
 * страница и данные, одна разметка. До 900px обёртки колонок прозрачны
 * (display: contents), колонка бухгалтера скрыта. 900–1183px — одна
 * колонка: сводка (не шире --ios-measure), под ней колонка бухгалтера во
 * всю ширину (836–1119). От 1184px контейнер набирает 1120, и главная
 * становится «сводка --ios-home-side слева | таблица и документы справа»
 * (728). Список счетов телефона на десктопе скрыт — его заменяет таблица.
 * Сетка 900–1183 — «предложение, по желанию» брифа §4.4: в 444–696 px
 * правой колонки таблица без прокрутки не помещается.
 * ============================================================ */

.portal-columns,
.portal-columns__side {
  display: contents;
}

.portal-columns__main {
  display: none;
}

@media (min-width: 900px) {
  .portal-columns__side {
    display: block;
    max-width: var(--ios-measure);
  }

  .portal-columns__main {
    display: block;
  }

  .portal-invoices-mobile {
    display: none;
  }
}

@media (min-width: 1184px) {
  .portal-columns {
    display: grid;
    grid-template-columns: var(--ios-home-side) minmax(0, 1fr);
    gap: 0 var(--ios-space-8);
    align-items: start;
  }

  .portal-columns__side,
  .portal-columns__main {
    min-width: 0;
  }

  .portal-columns__side {
    max-width: none;
  }

  /* Первая секция колонки — вровень с hero */
  .portal-columns__main > .portal-section:first-child {
    margin-top: var(--ios-space-6);
  }

  /* Прогноз «всё оплачено» в колонке 360 — основным текстом */
  .portal-hero__hint {
    font: var(--ios-type-body);
    font-variant-numeric: tabular-nums;
  }
}

/* --- Таблица «Счета по договору» (бриф §3 «Плотность», §4.4) ---
 * Строки 48, только горизонтальные разделители, шапка 12/600 без капса и
 * липкая под панелью, суммы моно справа, ₽ — в шапке. Таблица помещается
 * в колонку без прокрутки: объединённые колонки (см. строку таблицы) и
 * переносы внутри ячеек. Прокрутку-обёртку CRM (.table-scroll) кабинет
 * гасит: прокручиваемая обёртка отвязала бы шапку от окна, и она
 * перестала бы липнуть. Подложка скругляет углы через overflow: clip — он
 * не создаёт области прокрутки (hidden создал бы и тоже снял бы липкость) */
.portal-body .portal-columns__main .table-scroll {
  padding: 0;
  overflow: visible;
}

.portal-body .portal-columns__main .table-panel {
  overflow: hidden;
  overflow: clip;
  border: 0;
  border-radius: var(--ios-card-radius);
  background: var(--ios-surface);
}

.portal-body .portal-columns__main .table {
  font: var(--ios-type-table);
  font-variant-numeric: tabular-nums;
}

/* Шапка липнет под панелью навигации (--ios-scroll-offset = панель +
 * safe-area), фон — поверхность таблицы: строки уходят под неё */
.portal-body .portal-columns__main .table thead th {
  top: var(--ios-scroll-offset);
  z-index: var(--ios-z-sticky);
  height: var(--ios-table-head);
  padding: 0 var(--ios-space-2);
  border-bottom: 1px solid var(--ios-separator);
  background: var(--ios-surface);
  color: var(--ios-text-secondary);
  font: var(--ios-type-table-head);
  letter-spacing: 0;
  text-transform: none;
  vertical-align: middle;
}

/* Ячейки выровнены по первой строке (baseline): № и состав в две-три
 * строки, дата и сумма — вровень с номером */
.portal-body .portal-columns__main .table tbody td {
  height: var(--ios-table-row);
  padding: var(--ios-space-3) var(--ios-space-2);
  border-bottom: 1px solid var(--ios-separator);
  vertical-align: baseline;
}

.portal-body .portal-columns__main .table tbody tr:last-child td {
  border-bottom: 0;
}

/* Крайние столбцы — отступ от скругления подложки */
.portal-body .portal-columns__main .table tr > :last-child {
  padding-right: var(--ios-space-4);
}

/* Наведение и фокус внутри строки — подложка строки (бриф §4.4:
 * состояния строк заданы явно); кольцо фокуса — у самого элемента */
.portal-body .portal-columns__main .table tbody tr:hover,
.portal-body .portal-columns__main .table tbody tr:focus-within {
  background: var(--ios-bg);
}

/* Просроченная строка — красный тон (вместо янтарного --warning-row-bg);
 * при наведении и фокусе — плотнее той же гаммы */
.portal-body .portal-columns__main .table tbody tr.row--attention {
  background: var(--ios-status-danger-row);
}

.portal-body .portal-columns__main .table tbody tr.row--attention:hover,
.portal-body .portal-columns__main .table tbody tr.row--attention:focus-within {
  background: var(--ios-status-danger-bg);
}

/* Элемент строки в фокусе не прячется под липкой шапкой: к отступу
 * панели (scroll-padding-top у html) добавляется высота шапки */
.portal-body .portal-columns__main .table tbody :is(a, input) {
  scroll-margin-top: var(--ios-table-head);
}

/* Ссылки строки («№ …» и «PDF») — цель нажатия на десктопе не меньше
 * 24×24, включая текстовые ссылки (бриф §6, §8; решения v2 §2). Строчный
 * «PDF» — 27×17 по кеглю 14. Цель добирает псевдоэлемент (решения v2 §2:
 * «padding или псевдоэлементом»): он выходит за текст на недостающее до
 * 24 поровну с каждой стороны. Вёрстка строки не меняется — высота и
 * базовые линии прежние, соседние цели не перекрываются (отступ ячейки 12) */
.portal-body .portal-columns__main .table tbody td a {
  position: relative;
}

.portal-body .portal-columns__main .table tbody td a::after {
  content: "";
  position: absolute;
  top: min(0px, calc((100% - var(--ios-target-min)) / 2));
  right: min(0px, calc((100% - var(--ios-target-min)) / 2));
  bottom: min(0px, calc((100% - var(--ios-target-min)) / 2));
  left: min(0px, calc((100% - var(--ios-target-min)) / 2));
}

.portal-body .portal-columns__main .table .cell--warning {
  color: var(--ios-status-danger);
}

.portal-body .portal-columns__main .table .cell--muted {
  color: var(--ios-text-secondary);
}

/* Даты — в одну строку */
.portal-body .portal-columns__main .table td .num {
  white-space: nowrap;
}

/* № и состав: номер — ссылка на страницу счёта, состав и «не к оплате» —
 * второй строкой сноской, с переносом (не многоточием: подсказки по
 * наведению на телефоне нет, бриф §3) */
.portal-body .portal-columns__main .table .cell--main {
  font-weight: 400;
}

/* Номер — аварийный перенос: с префиксами арендодателя и объекта (до 10
 * знаков каждый) он бывает до ~27 знаков и не должен распирать таблицу за
 * колонку (у ссылки класс .num — перебиваем его nowrap «дат в одну
 * строку»). anywhere снимает номер из минимума колонки — его держит
 * неразрывный диапазон дат состава (он шире обычного номера), и обычный
 * номер по-прежнему стоит в одну строку (замеры в S1.md) */
.portal-body .portal-columns__main .table td .portal-invoices-table__number {
  white-space: normal;
  overflow-wrap: anywhere;
}

.portal-invoices-table__brief,
.portal-invoices-table__void,
.portal-invoices-table__overdue,
.portal-invoices-table__remaining {
  display: block;
  font: var(--ios-type-caption);
  font-variant-numeric: tabular-nums;
}

.portal-invoices-table__brief,
.portal-invoices-table__void,
.portal-invoices-table__remaining {
  color: var(--ios-text-secondary);
}

/* Строка состава — своим блоком: перенос между строками и по словам
 * внутри строки, не в середине склейки «дата, следующая строка» */
.portal-invoices-table__brief-line {
  display: block;
}

/* Данные не рвутся: диапазон «15.07.2026 — 31.07.2026» неразрывен (NBSP
 * вокруг тире) и держит минимальную ширину колонки. break-word, а не
 * anywhere: anywhere обнуляет минимум ячейки, и авто-раскладка таблицы
 * сжимала колонку уже диапазона даже там, где места хватало (дата
 * рвалась «31.07.202 / 6»). Минимум таблицы на худшем наборе — 717 из
 * 728 (замеры в S1.md) */
.portal-invoices-table__brief,
.portal-invoices-table__void {
  overflow-wrap: break-word;
}

/* «просрочен на N дней» переносится по словам: «12 дней» — неразрывно */
.portal-invoices-table__overdue {
  white-space: normal;
}

/* Суммы в ячейках — моно в кегле строки, обычные 400 (решения v2 §2 «Где
 * моно»: 600 — только итоги; та же сумма в строке телефона — 400); шапка
 * «Сумма, ₽» — Onest, как у остальных столбцов (CRM красит моно и
 * th.cell--num) */
.portal-body .portal-columns__main .table td.cell--num {
  font-family: var(--ios-font-mono);
  font-size: inherit;
  font-weight: 400;
}

.portal-body .portal-columns__main .table th.cell--num {
  font: var(--ios-type-table-head);
}

/* Остаток при частичной оплате — под суммой: подпись Onest, сумма моно;
 * в узкой колонке подпись уходит строкой выше числа */
.portal-invoices-table__remaining {
  white-space: normal;
}

.portal-invoices-table__remaining-sum {
  font-family: var(--ios-font-mono);
  white-space: nowrap;
}

/* Документ «не к оплате» — сумма вторичным цветом */
.portal-body .portal-columns__main .table .portal-invoices-table__row--void td.cell--num {
  color: var(--ios-text-secondary);
}

.portal-body .portal-columns__main .table .portal-check-col {
  width: var(--ios-touch-min);
  padding-left: var(--ios-space-3);
  padding-right: 0;
  text-align: left;
}

.portal-bulk {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ios-space-2) var(--ios-space-3);
  padding: var(--ios-space-4) 0 0;
}

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

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

.portal-recon__form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--ios-space-3) var(--ios-space-4);
}

.portal-recon__field {
  flex: none;
}

.portal-recon__field .portal-date-input {
  width: auto;
}

/* Ошибка периода (этап S4) — строкой под полями и кнопкой: поля «С» и
 * «По» остаются на одной линии, текст относится к паре дат */
.portal-recon__error {
  flex-basis: 100%;
}

.portal-recon__hint {
  max-width: var(--ios-measure);
  margin: var(--ios-space-3) 0 0;
}

/* --- Группы документов: договор и ДС, акты и УПД ---
 * Сгруппированный список (бриф §3): короткий заголовок над подложкой
 * группы (роль надстрочника, вровень с текстом строк), пояснение —
 * сноской под группой; название слева, дата и статус справа */

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

/* Первая группа — сразу под заголовком блока */
.portal-docs__group:first-of-type {
  margin-top: 0;
}

.portal-body .portal-docs .doc-row {
  align-items: center;
  gap: var(--ios-space-3);
  min-height: var(--ios-table-row);
  padding: var(--ios-space-2) var(--ios-space-4);
  border-bottom: 1px solid var(--ios-separator);
  font: var(--ios-type-table);
}

.portal-docs__name {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}

.portal-body .portal-docs .doc-row:last-child {
  border-bottom: 0;
}
