/* ==========================================================================
   OrtaBilim — Mnu 2.0
   Стили карточек документов и бокового меню.
   Кладётся как UiCustomPackages/ui-packages/ortabilim-mnu/style.css
   Префикс ob- не пересекается с существующей темой.
   ========================================================================== */

:root {
  --ob-primary: #006196;
  --ob-primary-hover: #00507E;
  --ob-link: #1B6E9C;
  --ob-link-hover: #2D8DC1;
  --ob-primary-soft: #E5F1F8;
  --ob-primary-soft-bg: #F4FAFD;
  --ob-primary-soft-line: #CFE2EE;
  --ob-primary-soft-line-hover: #9FC9E0;

  --ob-text: #2A2C31;
  /* Приглушённая ступень одна — #64717E: на белом это 5,0:1, то есть любой текст
     мельче 18,7px остаётся читаемым. Прежние #5F707F и #98A6AD давали три оттенка
     серого, из которых светлый не дотягивал и до 3:1. Имена оставлены: на них
     завязаны стили карточек, а значение теперь одно. */
  --ob-text-sub: #64717E;
  --ob-text-muted: #64717E;
  --ob-text-label: #64717E;
  --ob-text-faint: #64717E;
  --ob-text-ghost: #64717E;
  --ob-text-title-muted: #64717E;

  --ob-bg: #EEF4F8;
  --ob-surface: #FFFFFF;
  --ob-surface-alt: #F7FAFC;
  --ob-surface-hover: #FAFCFD;
  --ob-nav-hover: #F6F9FB;

  --ob-line: #E4E9F0;
  --ob-line-soft: #EAEFF4;
  --ob-line-faint: #F0F4F8;
  --ob-line-hairline: #F2F6F9;

  --ob-success: #52C41A;
  --ob-warn: #FAAD14;
  --ob-danger: #FF4D4F;

  --ob-r-xl: 12px;
  --ob-r-lg: 10px;
  --ob-r-md: 8px;
  --ob-r-sm: 7px;
  --ob-r-xs: 6px;
  --ob-r-2xs: 5px;
  --ob-r-pill: 20px;

  --ob-shadow-card: 0 0 35px 0 rgba(154, 161, 171, .15);
  --ob-shadow-header: 0 1px 3px rgba(42, 44, 49, .05);
  --ob-shadow-menu: 0 14px 38px rgba(16, 24, 40, .18);


  /* Дополнение палитры для тем (08-themes.md): тона статусов, текст на акценте
     и вторичная кнопка. Остальные темы переопределяют эти же имена на
     html[data-ob-theme] — ни один ob-класс о темах не знает. */
  --ob-on-accent: #FFFFFF;
  --ob-on-ghost: #FFFFFF;
  --ob-ghost: #2D8DC1;
  --ob-ghost-hover: #2680B2;
  --ob-info-tx: #1E6E9C;
  --ob-icon-faint: #C3CEDA;
  --ob-ok-bg: #EAF7E4;  --ob-ok-tx: #2F7A0D;  --ob-ok-tx-hover: #256208;  --ob-ok-soft: #BFE3AC; --ob-ok-ln: #CDEBD6;
  --ob-wn-bg: #FFF6E0;  --ob-wn-tx: #9A6B00;  --ob-wn-bg2: #FFE9B8; --ob-wn-tx2: #7A4E00; --ob-wn-ln: #F5DFA8;
  --ob-dn-bg: #FFECEC;  --ob-dn-tx: #D4383A;  --ob-dn-ln: #F5C6C7;
  --ob-nu-bg: #F1F5F9;

  --ob-font: 'Inter', system-ui, -apple-system, sans-serif;
}

/* --------------------------------------------------------------------------
   Тона статусов
   -------------------------------------------------------------------------- */
.ob-tone-success { background: var(--ob-ok-bg); color: var(--ob-ok-tx); }
.ob-tone-info    { background: var(--ob-primary-soft); color: var(--ob-info-tx); }
.ob-tone-warn    { background: var(--ob-wn-bg); color: var(--ob-wn-tx); }
.ob-tone-danger  { background: var(--ob-dn-bg); color: var(--ob-dn-tx); }
.ob-tone-neutral { background: var(--ob-nu-bg); color: var(--ob-text-muted); }

/* Служебное скрытие для скрипта: пустой результат прячет таблицу, подвал прячет
   собственную подпись количества у ядра, поиск по меню — непопавшие пункты.
   !important — потому что скрываем элементы темы с их собственным display. */
.ob-hidden { display: none !important; }

/* «Требует действия» — отдельный тон, темнее предупреждения: этот бейдж
   единственный, который читают в спешке, и он обязан пройти 4,5:1 на своём фоне
   (var(--ob-wn-tx2) на var(--ob-wn-bg2) — 5,4:1). */
.ob-tone-action  { background: var(--ob-wn-bg2); color: var(--ob-wn-tx2); }

/* ==========================================================================
   1. Шапка карточки
   ========================================================================== */
.ob-header {
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--ob-surface);
  border-bottom: 1px solid var(--ob-line);
  box-shadow: var(--ob-shadow-header);
  font-family: var(--ob-font);
}

/* Одна навигация вместо двух: стрелка возврата + крошки. Отдельная кнопка «Назад»
   дублировала предпоследнюю крошку слово в слово. */
/* Верхняя часть шапки — две колонки: слева крошки и кнопки друг под другом,
   справа заголовок со статусом, выровненный по нижней кромке — на одну линию
   с кнопками действий. */
.ob-header__nav {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 32px;
  flex-wrap: wrap;
  padding: 16px 36px;
}
.ob-header__nav-left {
  display: flex;
  flex-direction: column;
  gap: 13px;
  min-width: 0;
}
.ob-crumbs-row {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  min-width: 0;
}
.ob-header__titles {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  flex-wrap: wrap;
  min-width: 0;
}

/* Только стрелка: адрес возврата и так написан последней крошкой. */
.ob-back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: var(--ob-r-xs);
  color: var(--ob-link);
  text-decoration: none;
}
.ob-back:hover { background: var(--ob-primary-soft); }
.ob-back > i { font-size: 19px; }

.ob-crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  margin: 0;
  padding: 0;
  list-style: none;
  font: 400 12.5px/1.3 var(--ob-font);
}
/* Цепочка заканчивается реестром, а НЕ названием текущей страницы:
   оно уже написано в <h1> строкой ниже. */
.ob-crumbs li { display: flex; align-items: center; gap: 7px; }
.ob-crumbs a { color: var(--ob-text-sub); text-decoration: none; }
.ob-crumbs a:hover { color: var(--ob-link); }
.ob-crumbs li::after { content: '›'; color: var(--ob-icon-faint); }
.ob-crumbs li:last-child::after { content: none; }
.ob-crumbs li:last-child::after { content: none; }

/* Полоса табов: табы слева, справочная строка справа — правая половина этой полосы
   всё равно пустовала, а мете не нужна собственная строка. */
.ob-header__bottom {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 28px;
  padding: 0 36px;
}

.ob-header__titles { min-width: 0; }

.ob-header__row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.ob-title {
  margin: 0;
  font: 600 20px/1.25 var(--ob-font);
  color: var(--ob-text);
  letter-spacing: -.015em;
  text-align: right;
}

/* Тип документа — просто первый элемент строки меты, не плашка у заголовка. */
.ob-chip-type { font: 500 12px/1.4 var(--ob-font); color: var(--ob-text-muted); }

.ob-status {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: var(--ob-r-pill);
  padding: 4px 11px 4px 8px;
  font: 600 12px/1.3 var(--ob-font);
}
.ob-status::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.ob-header__meta {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 9px;
  flex-wrap: wrap;
  padding-bottom: 13px;
}

/* Без рамки: ID живёт в одной строке с остальной метой и не спорит с заголовком. */
.ob-idcopy {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  font: 400 12px/1.4 var(--ob-font);
  color: var(--ob-text-muted);
  transition: color .15s ease;
}
.ob-idcopy:hover { color: var(--ob-text); }
.ob-idcopy__value {
  font-weight: 500;
  color: var(--ob-text-sub);
  font-variant-numeric: tabular-nums;
}
.ob-idcopy > i { font-size: 14px; color: var(--ob-text-ghost); }

.ob-copied {
  font: 600 11px/1.4 var(--ob-font);
  color: var(--ob-success);
  animation: ob-fade .2s ease;
}
@keyframes ob-fade {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}
[data-ob-copy] .ob-copied { display: none; }
[data-ob-copy].is-copied .ob-copied { display: inline; }

.ob-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font: 400 12px/1.4 var(--ob-font);
  color: var(--ob-text-muted);
}
.ob-meta-item::before {
  content: '';
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--ob-icon-faint);
}

/* --------------------------------------------------------------------------
   Кнопки действий
   -------------------------------------------------------------------------- */
/* Отдельной строкой под заголовком, слева направо: в правом углу действия не замечают. */
.ob-actions {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
}

.ob-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: var(--ob-r-xs);
  padding: 7px 12px;
  cursor: pointer;
  font: 400 12px/1.2 var(--ob-font);
  white-space: nowrap;
  text-decoration: none;
  border: 0;
  transition: background .15s ease, border-color .15s ease;
}
.ob-btn > i { font-size: 14px; }

.ob-btn--primary { background: var(--ob-primary); color: var(--ob-on-accent); }
.ob-btn--primary:hover { background: var(--ob-primary-hover); color: var(--ob-on-accent); }

/* Вторичное действие — заливка светло-синим, как в текущем OrtaBilim:
   действия по документу должны читаться как кнопки, а не как серый фон. */
/* Заливка — родной цвет вторичной кнопки OrtaBilim, а не --ob-link. */
.ob-btn--ghost {
  border: 0;
  background: var(--ob-ghost);
  color: var(--ob-on-ghost);
}
.ob-btn--ghost:hover { background: var(--ob-ghost-hover); color: var(--ob-on-ghost); }

.ob-btn--soft {
  border: 1px solid var(--ob-primary);
  background: var(--ob-surface);
  color: var(--ob-primary);
}
.ob-btn--soft:hover { background: var(--ob-primary-soft-bg); color: var(--ob-primary); }

.ob-btn--success { background: var(--ob-success); color: var(--ob-on-accent); }

/* ==========================================================================
   2. Табы
   ========================================================================== */
.ob-tabs {
  display: flex;
  gap: 4px;
  min-width: 0;
  overflow-x: auto;
}

.ob-tab {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 0;
  background: none;
  cursor: pointer;
  padding: 11px 14px 13px;
  font: 600 12.5px/1.2 var(--ob-font);
  white-space: nowrap;
  color: var(--ob-text-muted);
  text-decoration: none;
  transition: color .15s ease, box-shadow .15s ease;
}
.ob-tab:hover { color: var(--ob-text-sub); }
.ob-tab--active {
  color: var(--ob-primary);
  box-shadow: inset 0 -2px 0 var(--ob-primary);
}

.ob-tab__count {
  border-radius: var(--ob-r-pill);
  padding: 1px 6px;
  font: 600 10.5px/1.6 var(--ob-font);
  background: var(--ob-nu-bg);
  color: var(--ob-text-muted);
}
.ob-tab--active .ob-tab__count { background: var(--ob-primary-soft); color: var(--ob-info-tx); }

/* ==========================================================================
   3. Тело карточки
   ========================================================================== */
.ob-body {
  padding: 32px 36px 72px;
  display: flex;
  gap: 32px;
  align-items: flex-start;
  background: var(--ob-bg);
  font-family: var(--ob-font);
}

.ob-body__main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 26px;
}

/* Правая колонка — «История операций». Внутреннее оформление НЕ трогаем,
   добавлена только липкость. */
.ob-body__aside {
  width: 330px;
  flex: none;
  position: sticky;
  top: 28px;
}

/* ==========================================================================
   4. Алерт
   ========================================================================== */
.ob-alert {
  display: flex;
  gap: 13px;
  border-radius: var(--ob-r-lg);
  padding: 18px 20px;
  border: 1px solid transparent;
}
.ob-alert > i {
  flex: none;
  align-self: flex-start;
  font-size: 17px;
  margin-top: 1px;
}
.ob-alert__title { font: 700 12.5px/1.4 var(--ob-font); margin-bottom: 2px; }
.ob-alert__text  { font: 400 12.5px/1.55 var(--ob-font); opacity: .9; }

.ob-alert--success { background: var(--ob-ok-bg); color: var(--ob-ok-tx); border-color: var(--ob-ok-ln); }
.ob-alert--info    { background: var(--ob-primary-soft); color: var(--ob-info-tx); border-color: var(--ob-primary-soft-line); }
.ob-alert--warn    { background: var(--ob-wn-bg); color: var(--ob-wn-tx); border-color: var(--ob-wn-ln); }
.ob-alert--danger  { background: var(--ob-dn-bg); color: var(--ob-dn-tx); border-color: var(--ob-dn-ln); }

/* ==========================================================================
   5. Степпер
   ========================================================================== */
.ob-steps {
  background: var(--ob-surface);
  border: 0;
  border-radius: var(--ob-r-xl);
  padding: 24px 28px 20px;
}

.ob-steps__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
}
.ob-steps__title { font: 600 14px/1.3 var(--ob-font); color: var(--ob-text); }
.ob-steps__progress { font: 400 12px/1.2 var(--ob-font); color: var(--ob-text-faint); }

.ob-steps__track { display: flex; align-items: stretch; }

.ob-step {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.ob-step__rail {
  display: flex;
  align-items: center;
  width: 100%;
  height: 20px;
}
.ob-step__line { flex: 1; height: 2px; background: var(--ob-line-soft); }
.ob-step:first-child .ob-step__line--before,
.ob-step:last-child  .ob-step__line--after { background: transparent; }

.ob-step__dot {
  width: 20px;
  height: 20px;
  flex: none;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ob-surface);
  border: 2px solid var(--ob-line);
}
.ob-step__dot > i { font-size: 13px; color: var(--ob-on-accent); }

/* завершён */
.ob-step--done .ob-step__dot { background: var(--ob-success); border-color: var(--ob-success); }
.ob-step--done .ob-step__line { background: var(--ob-ok-soft); }
.ob-step--done .ob-step__label { color: var(--ob-text-sub); }

/* текущий */
.ob-step--current .ob-step__dot {
  background: var(--ob-primary);
  border-color: var(--ob-primary);
  box-shadow: 0 0 0 4px rgba(0, 97, 150, .14);
}
.ob-step--current .ob-step__dot::after {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ob-surface);
}
.ob-step--current .ob-step__line--before { background: var(--ob-ok-soft); }
.ob-step--current .ob-step__label { color: var(--ob-primary); }

/* будущий */
.ob-step--todo .ob-step__label { color: var(--ob-text-ghost); }

.ob-step__label {
  margin-top: 11px;
  padding: 0 8px;
  min-height: 34px; /* выравнивает даты в одну линию при двухстрочных подписях */
  font: 500 12px/1.4 var(--ob-font);
  text-wrap: pretty;
}
.ob-step__date {
  font: 400 11px/1.4 var(--ob-font);
  color: var(--ob-text-ghost);
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   6. KPI
   ========================================================================== */
/* Один блок с волосяными разделителями вместо четырёх карточек в рамках. */
.ob-kpis {
  display: grid;
  grid-template-columns: repeat(var(--ob-kpi-cols, 4), minmax(0, 1fr));
  gap: 1px;
  background: var(--ob-nav-hover);
  border-radius: var(--ob-r-xl);
  overflow: hidden;
}

.ob-kpi {
  background: var(--ob-surface);
  padding: 22px 26px 24px;
}

.ob-kpi__label {
  font: 400 12px/1.4 var(--ob-font);
  color: var(--ob-text-muted);
  margin-bottom: 10px;
}
.ob-kpi__row { display: flex; align-items: baseline; gap: 5px; }
.ob-kpi__value {
  font: 600 22px/1.1 var(--ob-font);
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  color: var(--ob-text);
}
.ob-kpi--success .ob-kpi__value { color: var(--ob-ok-tx); }
.ob-kpi--danger  .ob-kpi__value { color: var(--ob-dn-tx); }
.ob-kpi__unit { font: 500 11.5px/1.2 var(--ob-font); color: var(--ob-text-ghost); }
.ob-kpi__hint { margin-top: 8px; font: 400 11px/1.5 var(--ob-font); color: var(--ob-text-muted); }

/* ==========================================================================
   7. Секция
   ========================================================================== */
/* Без рамки: белая плоскость на светлом фоне читается как блок сама по себе. */
.ob-section {
  background: var(--ob-surface);
  border: 0;
  border-radius: var(--ob-r-xl);
  overflow: hidden;
}

.ob-section__head {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  border: 0;
  background: none;
  cursor: pointer;
  padding: 20px 26px;
  text-align: left;
  transition: background .15s ease;
}
.ob-section__head:hover { background: var(--ob-surface-hover); }

.ob-section__caret {
  flex: none;
  font-size: 17px;
  color: var(--ob-text-faint);
  transform: rotate(-90deg);
  transition: transform .18s ease;
}
.ob-section.is-open .ob-section__caret { transform: rotate(0deg); }

.ob-section__title { font: 600 14.5px/1.3 var(--ob-font); color: var(--ob-text); }

.ob-section__badge {
  flex: none;
  border-radius: var(--ob-r-xs);
  padding: 2px 8px;
  font: 500 11.5px/1.5 var(--ob-font);
  background: var(--ob-nu-bg);
  color: var(--ob-text-muted);
}

.ob-section__spacer { flex: 1; }

.ob-section__action {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font: 600 11.5px/1.3 var(--ob-font);
  color: var(--ob-link);
  text-decoration: none;
}
.ob-section__action > i { font-size: 14px; }

.ob-section__body { display: none; padding: 0 26px 26px; }
.ob-section.is-open .ob-section__body { display: block; }

/* --------------------------------------------------------------------------
   7.1 Поля
   -------------------------------------------------------------------------- */
.ob-fields {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 24px 44px;
  border-top: 1px solid var(--ob-line-faint);
  padding-top: 24px;
}

.ob-field { min-width: 0; }
.ob-field--wide { grid-column: span 2; }

.ob-field__label {
  font: 400 12px/1.4 var(--ob-font);
  color: var(--ob-text-muted);
  margin-bottom: 5px;
}

.ob-field__row {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.ob-field__value {
  font: 500 14px/1.55 var(--ob-font);
  color: var(--ob-text);
  min-width: 0;
  text-wrap: pretty;
  font-variant-numeric: tabular-nums;
}

a.ob-field__value {
  color: var(--ob-link);
  display: inline;
  overflow-wrap: anywhere;
  text-decoration: none;
}
a.ob-field__value:hover { color: var(--ob-primary); text-decoration: underline; }
a.ob-field__value > i { font-size: 12px; margin-left: 5px; vertical-align: -1px; }

.ob-field__hint { margin-top: 3px; font: 400 11px/1.45 var(--ob-font); color: var(--ob-text-label); }

.ob-copy {
  width: 22px;
  height: 22px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--ob-line);
  background: var(--ob-surface);
  border-radius: var(--ob-r-2xs);
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.ob-copy:hover { border-color: var(--ob-primary-soft-line-hover); background: var(--ob-primary-soft-bg); }
.ob-copy > i { font-size: 12px; color: var(--ob-text-muted); }

/* --------------------------------------------------------------------------
   7.2 Таблица
   -------------------------------------------------------------------------- */
.ob-table { border-top: 1px solid var(--ob-line-faint); }

.ob-table__head,
.ob-table__row {
  display: grid;
  grid-template-columns: var(--ob-table-cols);
}

.ob-table__head { border-bottom: 1px solid var(--ob-line-soft); }
.ob-table__th {
  padding: 14px 16px 12px;
  font: 400 12px/1.3 var(--ob-font);
  color: var(--ob-text-muted);
}

.ob-table__row { border-bottom: 1px solid var(--ob-line-faint); }
.ob-table__row:last-child { border-bottom: 0; }
.ob-table__row:hover { background: var(--ob-surface-hover); }

.ob-table__td {
  padding: 14px 16px;
  min-width: 0;
  font: 400 12.5px/1.45 var(--ob-font);
  color: var(--ob-text-sub);
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ob-table__td:first-child { font-weight: 500; color: var(--ob-text); }

.ob-table__pill {
  display: inline-flex;
  align-items: center;
  border-radius: var(--ob-r-2xs);
  padding: 2px 8px;
  font: 600 11px/1.5 var(--ob-font);
}

.ob-table__more { padding: 14px; text-align: center; }
.ob-table__more a { font: 600 12px/1.3 var(--ob-font); color: var(--ob-link); text-decoration: none; }

/* --------------------------------------------------------------------------
   7.3 Файлы
   -------------------------------------------------------------------------- */
/* Список строк, а не сетка плиток: строки оставляют место под действия
   и не дробят блок рамками. */
.ob-files { border-top: 1px solid var(--ob-line-faint); }

.ob-file {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 4px;
  border-bottom: 1px solid var(--ob-line-faint);
  transition: background .15s ease;
}
.ob-file:hover { background: var(--ob-surface-hover); }

/* силуэт листа с расширением внизу */
.ob-file__ext {
  width: 32px;
  height: 40px;
  flex: none;
  border: 1px solid var(--ob-line);
  border-radius: 4px;
  background: var(--ob-surface);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 5px;
  font: 600 8.5px/1 var(--ob-font);
  letter-spacing: .03em;
  color: var(--ob-text-muted);
}
.ob-file__ext--pdf { color: #C2565A; }
.ob-file__ext--xls { color: #4E8A5B; }

.ob-file__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ob-file__name {
  font: 500 13.5px/1.4 var(--ob-font);
  color: var(--ob-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-decoration: none;
}
.ob-file__name:hover { color: var(--ob-link); }
.ob-file__meta { font: 400 12px/1.35 var(--ob-font); color: var(--ob-text-faint); }

/* срок действия — читается без открытия файла */
.ob-file__tag {
  flex: none;
  border-radius: var(--ob-r-pill);
  padding: 3px 10px;
  font: 500 11.5px/1.4 var(--ob-font);
}

.ob-file__actions { flex: none; display: flex; align-items: center; gap: 6px; }
.ob-file__act {
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background: none;
  border-radius: var(--ob-r-sm);
  cursor: pointer;
  transition: background .15s ease;
}
.ob-file__act:hover { background: var(--ob-nav-hover); }
.ob-file__act > i { font-size: 16px; color: var(--ob-text-muted); }

.ob-files__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 4px 0;
}
.ob-files__add {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  font: 500 13px/1.3 var(--ob-font);
  color: var(--ob-link);
}
.ob-files__add > i { font-size: 15px; }

/* ==========================================================================
   8. Боковое меню
   ========================================================================== */
.ob-nav { font-family: var(--ob-font); }

.ob-nav__search-wrap { padding: 0 16px 10px; }
.ob-nav__search {
  display: flex;
  align-items: center;
  gap: 9px;
  border: 1px solid var(--ob-line);
  background: var(--ob-surface-alt);
  border-radius: 9px;
  padding: 10px 12px;
}
.ob-nav__search:focus-within { border-color: var(--ob-primary-soft-line-hover); }
.ob-nav__search > i { flex: none; font-size: 15px; color: var(--ob-text-ghost); }
.ob-nav__search input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  outline: none;
  font: 400 13px/1.3 var(--ob-font);
  color: var(--ob-text);
}
.ob-nav__search button {
  flex: none;
  border: 0;
  background: none;
  cursor: pointer;
  padding: 0;
  display: flex;
}

.ob-nav__group { padding-top: 10px; }

.ob-nav__group-title {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 18px 22px 8px;
}
.ob-nav__group-title span:first-child {
  font: 600 11px/1.2 var(--ob-font);
  letter-spacing: .05em;
  color: var(--ob-text-ghost);
}
.ob-nav__group-title::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--ob-nav-hover);
}

.ob-nav__item,
.ob-nav__child {
  width: 100%;
  display: flex;
  align-items: center;
  border: 0;
  background: none;
  cursor: pointer;
  text-align: left;
  text-decoration: none;
  transition: background .12s ease;
}
.ob-nav__item:hover,
.ob-nav__child:hover { background: var(--ob-nav-hover); }

.ob-nav__item { gap: 12px; padding: 10px 22px; }
.ob-nav__child { gap: 9px; padding: 8px 22px 8px 52px; }

.ob-nav__icon {
  flex: none;
  width: 18px;
  font-size: 17px;
  color: var(--ob-text-faint);
}

.ob-nav__label {
  flex: 1;
  min-width: 0;
  font: 400 13.5px/1.35 var(--ob-font);
  color: var(--ob-text-sub);
  text-wrap: pretty;
}
.ob-nav__child .ob-nav__label { font-size: 13px; }

.ob-nav__item--active,
.ob-nav__child--active {
  background: var(--ob-primary-soft);
  box-shadow: inset 3px 0 0 var(--ob-primary);
}
.ob-nav__item--active .ob-nav__label,
.ob-nav__child--active .ob-nav__label { font-weight: 600; color: var(--ob-primary); }
.ob-nav__item--active .ob-nav__icon { color: var(--ob-primary); }

/* родитель активного ребёнка */
.ob-nav__item--parent-active .ob-nav__label { font-weight: 600; color: var(--ob-link); }
.ob-nav__item--parent-active .ob-nav__icon { color: var(--ob-primary); }

.ob-nav__badge {
  flex: none;
  border-radius: 4px;
  padding: 1px 5px;
  font: 600 10px/1.5 var(--ob-font);
}
.ob-nav__badge--action { background: var(--ob-wn-bg2); color: var(--ob-wn-tx2); }
.ob-nav__badge--count  { background: var(--ob-primary-soft); color: var(--ob-info-tx); }

.ob-nav__caret {
  flex: none;
  font-size: 16px;
  color: var(--ob-icon-faint);
  transform: rotate(-90deg);
  transition: transform .16s ease;
}
.ob-nav__branch.is-open > .ob-nav__item .ob-nav__caret { transform: rotate(0deg); }

.ob-nav__children { display: none; padding: 4px 0 8px; }
.ob-nav__branch.is-open > .ob-nav__children { display: block; }

.ob-nav__empty {
  padding: 22px 20px;
  text-align: center;
  font: 400 12.5px/1.5 var(--ob-font);
  color: var(--ob-text-ghost);
}

.ob-nav__group.is-hidden,
.ob-nav__item.is-hidden,
.ob-nav__child.is-hidden { display: none; }

/* ==========================================================================
   9. Адаптив
   ========================================================================== */

/* Правая колонка уходит вниз */
@media (max-width: 1280px) {
  .ob-body { flex-direction: column; }
  .ob-body__aside {
    width: 100%;
    position: static;
  }
}

/* Сайдбар за бургером, KPI по 2 */
@media (max-width: 1024px) {
  .ob-kpis { --ob-kpi-cols: 2; }

  .ob-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 80;
    transform: translateX(-100%);
    transition: transform .22s ease;
  }
  .ob-sidebar.is-open { transform: none; }

  .ob-sidebar-overlay {
    position: fixed;
    inset: 0;
    z-index: 79;
    background: rgba(32, 36, 43, .45);
    opacity: 0;
    pointer-events: none;
    transition: opacity .22s ease;
  }
  .ob-sidebar.is-open + .ob-sidebar-overlay { opacity: 1; pointer-events: auto; }
}

/* Телефоны */
@media (max-width: 768px) {
  .ob-header { position: static; }
  .ob-header__nav { padding: 14px 18px 0; }
  .ob-header__main {
    flex-direction: column;
    align-items: stretch;
    gap: 16px;
    padding: 14px 18px 18px;
  }
  .ob-crumbs { display: none; }
  .ob-title { font-size: 18px; }

  .ob-actions { flex-direction: column; align-items: stretch; }
  .ob-btn {
    justify-content: center;
    min-height: 44px; /* тап-таргет */
  }

  .ob-tabs {
    padding: 0 18px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .ob-tabs::-webkit-scrollbar { display: none; }

  .ob-body { padding: 22px 18px 48px; }
  .ob-fields { grid-template-columns: 1fr; }
  .ob-field--wide { grid-column: auto; }
  .ob-file__meta { white-space: normal; }

  .ob-nav__item { padding: 13px 22px; }
  .ob-nav__child { padding: 11px 22px 11px 52px; }
}

/* Узкие телефоны: вертикальный степпер, таблицы карточками */
@media (max-width: 560px) {
  .ob-kpis { --ob-kpi-cols: 1; }

  .ob-steps__track { flex-direction: column; align-items: stretch; }
  .ob-step {
    flex-direction: row;
    align-items: flex-start;
    text-align: left;
    gap: 11px;
    padding-bottom: 12px;
    position: relative;
  }
  .ob-step__rail {
    width: 20px;
    height: auto;
    flex: none;
    flex-direction: column;
    align-self: stretch;
  }
  .ob-step__line { width: 2px; height: auto; flex: 1; }
  .ob-step__label { margin-top: 0; min-height: 0; }
  .ob-step__text { padding-top: 1px; }

  .ob-table { border: 0; border-radius: 0; }
  .ob-table__head { display: none; }
  .ob-table__row {
    display: block;
    border: 1px solid var(--ob-line-soft);
    border-radius: var(--ob-r-md);
    margin-bottom: 8px;
    padding: 4px 0;
  }
  .ob-table__row:hover { background: none; }
  .ob-table__td {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 6px 12px;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }
  .ob-table__td::before {
    content: attr(data-label);
    flex: none;
    font: 500 11px/1.6 var(--ob-font);
    color: var(--ob-text-muted);
  }
}

/* ==========================================================================
   10. Печать
   ========================================================================== */
@media print {
  .ob-sidebar,
  .ob-actions,
  .ob-tabs,
  .ob-back,
  .ob-copy,
  .ob-idcopy > i { display: none !important; }

  .ob-header { position: static; box-shadow: none; }
  .ob-body { display: block; padding: 0; background: var(--ob-surface); }
  .ob-section { break-inside: avoid; border-color: var(--ob-line); }
  .ob-section__body { display: block !important; }

  /* Ширины столбцов реестра посчитаны под ширину экрана и проставлены в пикселях
     (12.7.1). У листа бумаги ширина своя, поэтому на печати таблица раскладывается
     заново. !important — единственный способ перебить ширину в атрибуте style. */
  .ob-lbody__main table.ob-ltable { table-layout: auto !important; }
  .ob-lbody__main table.ob-ltable th { width: auto !important; }
}

/* ==========================================================================
   11. Интеграция с текущей темой hyper
   Дописано при переносе прототипа в проект: прототип рисовал страницу целиком,
   в приложении карточка живёт внутри .content-page > .container-fluid.
   ========================================================================== */

/* Пакет не должен зависеть от глобального ресета: без border-box padding кнопок
   и полей прибавляется к flex-basis и ломает раскладку строки действий. */
[class^="ob-"],
[class*=" ob-"] { box-sizing: border-box; }

/* Шапка карточки — в потоке, не липкая.
   В теме .wrapper и .content-page объявлены overflow:hidden, поэтому sticky
   привязывается к нескроллируемому боксу: прилипания к вьюпорту не происходит,
   а offset top только сдвигает шапку вниз — она наезжает на алерт под собой
   (замер: static top=78, sticky top:70px даёт top=148 при нулевом скролле).
   Статус и действия и так видны без прокрутки — шапка стоит первой на странице. */
.ob-header {
  position: static;
  top: auto;
}

/* Страница с новой шапкой сама показывает заголовок и крошки —
   старый .page-title-box темы на таких страницах лишний. */
.container-fluid:has(.ob-header) > .row > .col-12 > .page-title-box { display: none; }

/* Реестр в новом виде печатает название первой строкой карточки с полосой
   процесса, а тема выводит то же название в <h4 class="page-title"> — получалось
   два одинаковых заголовка подряд. Прячем ТОЛЬКО заголовок: в том же блоке лежат
   хлебные крошки и локальные задачи (кнопки AsLocalTask), их убирать нельзя. */
.container-fluid:has(.ob-chain) > .row > .col-12 > .page-title-box > h4.page-title { display: none; }

/* Карточка «История операций» в правой колонке: внешний вид не меняем,
   снимаем только нижний отступ, чтобы sticky-колонка не «прыгала». */
.ob-body__aside > .card:last-child { margin-bottom: 0; }

/* Произвольное содержимое секции (превью документа, подписание, таблицы Yoda).
   Отделяется от шапки так же, как .ob-fields. */
.ob-section__content {
  border-top: 1px solid var(--ob-line-faint);
  padding-top: 24px;
}
.ob-section__content > .card,
.ob-section__content > .card-body { box-shadow: none; margin-bottom: 0; }

/* overflow:hidden из раздела 7 обрезал всё, что рисуется поверх секции:
   выпадающие списки фильтров Yoda-поиска (например «Тип обучения» в секции
   контингента) уходили под нижнюю границу. Скругление углов держим на самой
   шапке — ради него overflow и ставился. */
.ob-section { overflow: visible; }
.ob-section__head { border-radius: var(--ob-r-xl) var(--ob-r-xl) 0 0; }
.ob-section:not(.is-open) .ob-section__head { border-radius: var(--ob-r-xl); }

/* Yoda-поиск внутри секции: таблица не должна распирать карточку. */
.ob-section__content .table-responsive { overflow-x: auto; }

/* Шапка таблиц ядра. Бутстрап держит .thead-light th прошитыми #f1f3fa и #6c757d
   — это 4,2:1, ниже порога AA и мимо принятой единственной приглушённой ступени
   (см. --ob-text-sub в начале файла). Роли те же: подложка на ступень от карточки
   и приглушённый текст, поэтому берём переменные палитры — заодно шапка перестаёт
   быть светлой полосой поперёк тёмной карточки (палитры переопределяют те же имена).
   В бутстрапе правило записано как `.table .thead-light th`, поэтому `.thead-light th`
   его не перебивает даже последним пакетом — нужна та же пара классов, а `html`
   впереди снимает зависимость от порядка подключения. Селектор по потомку, как в
   бутстрапе: тот же класс висит и на <tfoot> с итогами. */
html .table .thead-light th {
  background-color: var(--ob-surface-alt);
  color: var(--ob-text-sub);
  border-color: var(--ob-line-soft);
}

/* Страховка для нативных списков множественного выбора внутри секций: тема
   объявляет .form-control{height:calc(30px + 2px)} без исключения для [multiple]
   (в бутстрапе оно есть), из-за чего список сжимался в одну строку со скроллом.
   Поля, которые подхватил bootstrap-multiselect (класс .multiselect), не трогаем:
   у них исходный select скрыт, а видимой остаётся кнопка выпадающего списка. */
.ob-section__body select[multiple]:not(.multiselect),
.ob-section__body select[size]:not(.multiselect) {
  width: 100%;
  height: auto;
  min-height: 132px;
  padding: 6px 8px;
  line-height: 1.5;
}

/* min-width в процентах бесполезен — он считается от той самой колонки, которую
   нужно раздвинуть. Абсолютное значение включаем только там, где для него есть
   место: на телефоне оно вызвало бы горизонтальную прокрутку. */
@media (min-width: 769px) {
  .ob-section__body select[multiple]:not(.multiselect),
  .ob-section__body select[size]:not(.multiselect) { min-width: 340px; }

  /* Колонка bootstrap-сетки фиксирует max-width в процентах, и список вылезал
     за её границу на соседнюю колонку. Даём колонке со списком ширину по
     содержимому — строка фильтров перенесётся сама. */
  .ob-section__body [class*="col-"]:has(select[multiple]:not(.multiselect)),
  .ob-section__body [class*="col-"]:has(select[size]:not(.multiselect)) {
    flex: 0 0 auto;
    width: auto;
    max-width: 100%;
  }
}

/* Выпадающий список bootstrap-multiselect — тот, что заменяет собой поля
   отбора со справочником. Пункты в нём печатаются как .dropdown-item, а у
   бутстрапа это white-space:nowrap; ширину списку ядро не задаёт вовсе
   (widthSynchronizationMode:'never' — значение по умолчанию, инициализация
   пакета bootstrap-multiselect его не меняет). В итоге справочник с длинным
   названием — «Образовательная деятельность в сфере начального, основного
   среднего…» в отборе по виду деятельности — растягивал список на всю строку
   названия (замер: 1713px при поле в 320px): список уезжал за край страницы,
   popper сдвигал его к левому краю окна, и появлялась горизонтальная прокрутка.

   Ширину берём у самого поля, как у нативного <select>: проценты считаются от
   .btn-group, которому ядро ставит width:100% колонки. Правило на css, а не
   синхронизация шириной на JS: та отрабатывает только в момент открытия и
   расходится с полем после смены размера окна.

   overflow-wrap нужен именно anywhere: break-word не уменьшает минимальную
   ширину содержимого, и одно длинное слово всё равно распирало бы список.

   overflow-y:auto вместо scroll из css пакета: короткому списку пустая полоса
   прокрутки не нужна. */
.multiselect-container.dropdown-menu {
  min-width: 100%;
  max-width: 100%;
  overflow-y: auto;
}
.multiselect-container .multiselect-all,
.multiselect-container .multiselect-group,
.multiselect-container .multiselect-option {
  white-space: normal;
  overflow-wrap: anywhere;
}

/* Подвал списка вложений. Кнопки «Добавить документ» из макета нет — загрузка
   файлов в OrtaBilim идёт операциями документа, а не из карточки, — поэтому
   в подвале остаётся только «Скачать всё архивом». */
.ob-files__all {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 0;
  background: var(--ob-nu-bg);
  border-radius: var(--ob-r-sm);
  padding: 8px 13px;
  cursor: pointer;
  font: 500 12.5px/1.2 var(--ob-font);
  color: var(--ob-text-sub);
  text-decoration: none;
  transition: background .15s ease;
}
.ob-files__all:hover { background: var(--ob-nav-hover); color: var(--ob-text-sub); }
.ob-files__all > i { font-size: 15px; }

/* --------------------------------------------------------------------------
   11.1 Число колонок KPI
   Задаётся классом, а не инлайновым стилем: инлайн перебивал медиазапросы
   раздела 9, и на планшете KPI оставались в четыре колонки.
   Правила стоят в конце файла, поэтому выигрывают у раздела 9 по порядку.
   -------------------------------------------------------------------------- */
.ob-kpis--1 { --ob-kpi-cols: 1; }
.ob-kpis--2 { --ob-kpi-cols: 2; }
.ob-kpis--3 { --ob-kpi-cols: 3; }
.ob-kpis--4 { --ob-kpi-cols: 4; }

@media (max-width: 1024px) {
  .ob-kpis--3,
  .ob-kpis--4 { --ob-kpi-cols: 2; }
}

@media (max-width: 560px) {
  .ob-kpis--2,
  .ob-kpis--3,
  .ob-kpis--4 { --ob-kpi-cols: 1; }
}

/* --------------------------------------------------------------------------
   11.2 Адаптив шапки
   Раздел 9 адресует .ob-header__main — блока с таким классом в новой разметке
   шапки нет (она собрана из .ob-header__nav и .ob-header__bottom),
   поэтому мобильные правила для шапки описаны здесь.
   -------------------------------------------------------------------------- */

/* Планшет: заголовок перестаёт делить строку с крошками и уходит под них. */
@media (max-width: 1024px) {
  .ob-header__nav {
    align-items: flex-start;
    gap: 16px;
    padding: 16px 22px;
  }
  .ob-header__titles { justify-content: flex-start; }
  .ob-title { text-align: left; }
  .ob-header__bottom { padding: 0 22px; }
}

/* Телефон: шапка в одну колонку, действия — первичное на всю строку,
   вторичные по два в ряд, тап-таргет 44px. Мета уходит под табы. */
@media (max-width: 768px) {
  .ob-header__nav {
    flex-direction: column;
    align-items: stretch;
    gap: 14px;
    padding: 14px 18px;
  }
  /* display:contents растворяет левую колонку, чтобы порядок сверху вниз был
     «крошки → заголовок → действия»: иначе заголовок оказывается под кнопками. */
  .ob-header__nav-left { display: contents; }
  .ob-crumbs-row { order: 1; }
  .ob-header__titles { order: 2; }
  .ob-actions { order: 3; }
  .ob-header__bottom {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0 18px;
  }
  .ob-header__meta {
    justify-content: flex-start;
    padding: 10px 0 13px;
  }
  .ob-header__titles { justify-content: flex-start; }
  .ob-title { text-align: left; font-size: 18px; }

  .ob-actions {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 8px;
  }
  .ob-actions > .ob-btn {
    flex: 1 1 calc(50% - 4px);
    min-width: 0;
    justify-content: center;
    white-space: normal;
    text-align: center;
    min-height: 44px;
  }
  .ob-actions > .ob-btn--primary { flex-basis: 100%; }

  /* Длинный ID не должен растягивать шапку по горизонтали. */
  .ob-idcopy { max-width: 100%; }
  .ob-idcopy__value { overflow: hidden; text-overflow: ellipsis; }
}

/* Вертикальный степпер на узких экранах: подпись должна занимать всю ширину
   справа от точки, иначе она жмётся к своему min-content и рвётся по словам. */
@media (max-width: 560px) {
  .ob-step__text {
    flex: 1;
    min-width: 0;
  }
  .ob-step__label { padding: 0; }
}

/* --------------------------------------------------------------------------
   11.3 Поиск по боковому меню (Слой 1)
   Разметку рисует MenuSidebarBlock.cshtml, поэтому селекторы завязаны
   на классы темы hyper, а не на .ob-nav из раздела 8.
   -------------------------------------------------------------------------- */
.ob-navsearch { padding: 8px 16px 10px; }
.ob-navsearch__box {
  display: flex;
  align-items: center;
  gap: 9px;
  border: 1px solid var(--ob-line);
  background: var(--ob-surface-alt);
  border-radius: 9px;
  padding: 10px 12px;
}
.ob-navsearch__box:focus-within { border-color: var(--ob-primary-soft-line-hover); }
.ob-navsearch__box > i { flex: none; font-size: 15px; color: var(--ob-text-ghost); }
.ob-navsearch__box input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  outline: none;
  font: 400 13px/1.3 var(--ob-font);
  color: var(--ob-text);
}
.ob-navsearch__clear {
  flex: none;
  display: none;
  border: 0;
  background: none;
  cursor: pointer;
  padding: 0;
  color: var(--ob-text-ghost);
}
.ob-navsearch.is-filled .ob-navsearch__clear { display: flex; }
.ob-navsearch__empty {
  display: none;
  padding: 22px 20px;
  text-align: center;
  font: 400 12.5px/1.5 var(--ob-font);
  color: var(--ob-text-ghost);
}
.ob-navsearch__empty.is-visible { display: block; }
.side-nav-item.ob-hidden,
.side-nav-title.ob-hidden { display: none !important; }

/* ==========================================================================
   12. Реестры (Mnu*List) — пилот
   Полоса процесса, шапка с числом записей и ячейки таблицы. Сама таблица и блок
   фильтров рендерятся ядром Yoda-поиска — стилизуем только содержимое ячеек.
   ========================================================================== */

/* --------------------------------------------------------------------------
   12.1 Полоса процесса: где я в жизненном цикле и переход на соседний шаг
   -------------------------------------------------------------------------- */
/* Карточка: первой строкой — заголовок реестра со счётчиком, ниже полоса шагов.
   Отдельной шапки над полосой не нужно, это про одно и то же. */
.ob-chain {
  background: var(--ob-surface);
  border-radius: var(--ob-r-xl);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-family: var(--ob-font);
  margin-bottom: 14px;
}

.ob-chain__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.ob-chain__title { font: 600 16px/1.3 var(--ob-font); color: var(--ob-text); }
.ob-chain__note {
  font: 400 12.5px/1.4 var(--ob-font);
  color: var(--ob-text-muted);
  font-variant-numeric: tabular-nums;
}

.ob-chain__steps {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1px;
  margin-left: -10px; /* компенсация левого padding кнопки первого шага */
}

.ob-chain__step {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border-radius: var(--ob-r-md);
  font: 400 12.5px/1.3 var(--ob-font);
  color: var(--ob-link);
  text-decoration: none;
  white-space: nowrap;
}
.ob-chain__step > i { font-size: 14px; color: var(--ob-link); }
a.ob-chain__step:hover { background: var(--ob-nav-hover); color: var(--ob-link); }

.ob-chain__step--current {
  background: var(--ob-primary-soft);
  color: var(--ob-primary);
  font-weight: 600;
  cursor: default;
}
.ob-chain__step--current > i { color: var(--ob-primary); }

/* Третье состояние — «нет доступа». Шаг остаётся в полосе: он объясняет, что
   будет с документом дальше, даже если этого реестра в кабинете нет. Недоступность
   читается по иконке и курсору, подпись остаётся полноконтрастной — бледный текст
   означал бы «неважно», а шаг важен. */
.ob-chain__step--locked {
  cursor: not-allowed;
  color: var(--ob-text);
}
.ob-chain__step--locked > i { color: var(--ob-icon-faint); }

.ob-chain__count {
  border-radius: var(--ob-r-pill);
  padding: 1px 6px;
  font: 500 10.5px/1.6 var(--ob-font);
  background: var(--ob-nu-bg);
  color: var(--ob-text-muted);
  font-variant-numeric: tabular-nums;
}
.ob-chain__step--current .ob-chain__count { background: var(--ob-surface); color: var(--ob-info-tx); }

/* Четвёртое состояние — шаг с развилкой: у одного шага процесса два реестра
   (заявления A1 и A2/A3). Подпись шага остаётся текстом — непонятно, какой из
   двух реестров она открыла бы, — а выбор стоит рядом короткими подписями.
   Открытая помечена, вторая кликается: из реестра A1 видно, что есть A2/A3. */
.ob-chain__step--choice {
  color: var(--ob-text);
  cursor: default;
  gap: 4px;
}
.ob-chain__step--choice > i { color: var(--ob-icon-faint); }
.ob-chain__step--choice.ob-chain__step--current > i { color: var(--ob-primary); }

.ob-chain__pick {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: 2px;
  padding: 2px 7px;
  border-radius: var(--ob-r-2xs);
  font: 500 11.5px/1.4 var(--ob-font);
  color: var(--ob-link);
  text-decoration: none;
  white-space: nowrap;
}
a.ob-chain__pick { background: var(--ob-surface-alt); }
a.ob-chain__pick:hover {
  background: var(--ob-primary-soft-bg);
  color: var(--ob-primary);
}
.ob-chain__pick--current {
  background: var(--ob-surface);
  color: var(--ob-primary);
  cursor: default;
}

.ob-chain__sep {
  font-size: 15px;
  color: var(--ob-icon-faint);
  flex: none;
}

/* --------------------------------------------------------------------------
   12.2 Ячейки таблицы реестра (внутри штатной таблицы Yoda-поиска)
   -------------------------------------------------------------------------- */
/* Опознавательная / парная ячейка: главная строка + подпись.

   Размеры считаются от --ob-lfs таблицы (12.7): один и тот же кегль у ячейки
   MnuListCells и у штатной колонки ядра рядом. Подстраховка 13px — на случай,
   если ячейка напечатана вне таблицы реестра, где переменной нет. */
.ob-lcell { min-width: 0; font-family: var(--ob-font); }
.ob-lcell__main {
  display: block;
  font: 500 var(--ob-lfs, 13px)/1.5 var(--ob-font);
  color: var(--ob-text);
  text-decoration: none;
  text-wrap: pretty;
  font-variant-numeric: tabular-nums;
}
a.ob-lcell__main { color: var(--ob-link); }
a.ob-lcell__main:hover { color: var(--ob-primary); text-decoration: underline; }
.ob-lcell__sub {
  display: block;
  font: 400 calc(var(--ob-lfs, 13px) - 1.5px)/1.4 var(--ob-font);
  color: var(--ob-text-muted);
  text-wrap: pretty;
  font-variant-numeric: tabular-nums;
}

/* Идентификатор второй строкой — ссылка на карточку сущности. Остаётся
   второстепенным по размеру, но цветом и подчёркиванием при наведении читается
   как ссылка: серый текст-ссылка без признаков кликабельности не находится. */
a.ob-lcell__sub--link {
  color: var(--ob-link);
  text-decoration: none;
}
a.ob-lcell__sub--link:hover {
  color: var(--ob-primary);
  text-decoration: underline;
}

/* Идентификаторы — одной строкой. Перенос по символам делал min-content ячейки
   равным одному знаку, и авто-раскладка таблицы сжимала колонку до предела,
   разбивая 18-значный номер на четыре строки.

   Короткое значение (дата, код) — там же: перенос «14.02.2026» на две строки
   читается хуже, чем та же дата в столбце по содержимому. Скрипт делит столбцы
   на растяжимые и по содержимому по этому же признаку (5.3.1). */
.ob-lcell--id .ob-lcell__main,
.ob-lcell--id .ob-lcell__sub,
.ob-lcell--short .ob-lcell__main {
  white-space: nowrap;
  overflow-wrap: normal;
}

/* Наименования — переносятся по словам, колонка не растёт без предела. Предел
   один и тот же у столбца и у ячейки (--ob-lcol-text на таблице): будь ячейка
   уже столбца, разница осталась бы пустым местом внутри столбца. */
.ob-lcell--text { max-width: var(--ob-lcol-text, 260px); }
.ob-lcell--text .ob-lcell__main,
.ob-lcell--text .ob-lcell__sub {
  white-space: normal;
  overflow-wrap: break-word;
}

/* Опознавательное наименование (первый столбец реестра) — потолок выше обычного:
   с него читается вся строка, оно же ведёт в карточку, и сжимать его в первую
   очередь неправильно. Правило стоит после .ob-lcell--text намеренно: вес
   селекторов одинаковый, и спор о потолке решает порядок в файле. */
.ob-lcell--name { max-width: var(--ob-lcol-name, 340px); }

/* Второстепенный текст (признаки, пояснения) — потолок ниже: столбец, пустой в
   большинстве строк, просил ширину наравне с наименованием. */
.ob-lcell--narrow { max-width: var(--ob-lcol-narrow, 170px); }

/* Число: вправо, tabular-nums; знак валюты живёт в заголовке столбца. */
.ob-lnum {
  text-align: right;
  font: 500 var(--ob-lfs, 13px)/1.5 var(--ob-font);
  color: var(--ob-text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Статус — пилюля с точкой, тон по общей таблице статусов. */
.ob-lpill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: var(--ob-r-xs);
  padding: 3px 9px;
  font: 500 calc(var(--ob-lfs, 13px) - 1px)/1.4 var(--ob-font);
  white-space: nowrap;
}
.ob-lpill::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

/* Шапка реестра из MnuHeader: вместо статус-пилюли — счётчик записей. */
.ob-status.ob-tone-neutral { font-variant-numeric: tabular-nums; }

/* Алерт над реестром прижат к полосе процесса. */
.ob-list-alert { margin-bottom: 14px; }

/* --------------------------------------------------------------------------
   12.3 Карточка «Поиск и отбор»: два уровня и сворачивание целиком
   -------------------------------------------------------------------------- */
/* Шапка карточки во всю ширину: она живёт внутри bootstrap-строки ядра, поэтому
   ширину берёт распоркой flex-basis, а не классом col-12 — на блочном родителе
   правило тоже верно. */
.ob-lsearch__head {
  flex: 0 0 100%;
  width: 100%;
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0 0 12px;
  padding: 0 0 10px;
  border-bottom: 1px solid var(--ob-line-faint);
  cursor: pointer;
  user-select: none;
  font-family: var(--ob-font);
  min-width: 0;
}
.ob-lsearch__chev {
  font-size: 17px;
  line-height: 1;
  color: var(--ob-text-muted);
  transition: transform .15s ease;
  align-self: center;
}
.ob-lsearch__head.is-collapsed .ob-lsearch__chev { transform: rotate(-90deg); }
.ob-lsearch__title {
  font: 600 14px/1.4 var(--ob-font);
  color: var(--ob-text);
  flex: none;
}
/* Сводка отбора: одна строка с обрезкой. min-width:0 обязателен — без него
   flex-элемент не сжимается ниже своего текста и эллипсис не появляется. */
.ob-lsearch__summary {
  flex: 1 1 auto;
  min-width: 0;
  font: 400 12.5px/1.5 var(--ob-font);
  color: var(--ob-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
  transition: opacity .12s ease;
}
.ob-lsearch__head.is-collapsed .ob-lsearch__summary { opacity: 1; }

/* Свёрнутая карточка прячет ровно поля. Кнопки подвала («Найти», «Сбросить»,
   «Выгрузить в Excel») лежат в том же родителе и остаются доступны: свернуть
   отбор и выгрузить текущую выборку — обычная пара действий. */
.ob-lsearch__box--off { display: none !important; }

/* «Ещё фильтры (N)» — второй уровень отбора. Число в подписи считает скрипт
   по фактическому количеству скрытых полей. */
.ob-lmore {
  flex: 0 0 100%;
  width: max-content;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin: 0 0 12px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  font: 500 13px/1.4 var(--ob-font);
  color: var(--ob-link);
}
.ob-lmore:hover { color: var(--ob-primary); text-decoration: underline; }
.ob-lmore > i { font-size: 15px; transition: transform .15s ease; }
.ob-lmore.is-on > i { transform: rotate(180deg); }

.ob-filter-hidden { display: none !important; }

/* Подпись поля отбора убрана: название живёт внутри самого контрола
   (placeholder у input, первый пункт у select, подпись кнопки у multiselect). */
.ob-filter-label-hidden { display: none !important; }

/* Подвал карточки: копия кнопки «Поиск» ядра (§4.3.1 script.js) и рядом с ней
   действия реестра — «Добавить производственную базу», «Создать акт» (§5
   приносит их сюда из строки ядра). Полная ширина распоркой, как у шапки и
   тумблера — своей колонки в bootstrap-строке ядра у неё нет. Линия сверху
   повторяет линию шапки: кнопки завершают карточку, а не продолжают строку
   отбора.

   Перенос разрешён: на узком экране пара кнопок не должна выдавливать строку
   за край карточки. */
.ob-lsearch__actions {
  flex: 0 0 100%;
  width: 100%;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding-top: 12px;
  border-top: 1px solid var(--ob-line-faint);
}

/* Зазор в строке держит gap, поэтому собственный отступ ядра между кнопками
   снимаем: иначе между «Поиском» и действием он складывается с gap
   в полуторный. */
.ob-lsearch__actions .btn + .btn { margin-left: 0; }

/* --------------------------------------------------------------------------
   12.4 Отбор отрезком «от … до …» для денежных полей
   Единственное поле отбора, которое печатает свою подпись само: placeholder'ы
   заняты словами «от» и «до», а внешний label прячется общим правилом выше.
   -------------------------------------------------------------------------- */
.ob-frange { font-family: var(--ob-font); }
.ob-frange__cap {
  display: block;
  margin-bottom: 4px;
  font: 500 12px/1.35 var(--ob-font);
  color: var(--ob-text-sub);
}
.ob-frange__row {
  display: flex;
  align-items: center;
  gap: 6px;
}
/* Обе половины отрезка одной ширины: разная ширина читается как разная
   значимость границ. min-width:0 обязателен — иначе form-control не сжимается. */
.ob-frange__in {
  flex: 1 1 0;
  min-width: 0;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.ob-frange__dash {
  flex: none;
  color: var(--ob-text-muted);
  font: 400 13px/1 var(--ob-font);
}

/* --------------------------------------------------------------------------
   12.5 Кнопки подвала блока поиска
   Кнопки ядра — inline-block и выравниваются по базовой линии текста, поэтому
   кнопка с иконкой («Поиск») стояла выше кнопок без иконки. vertical-align
   лечит базовую линию, align-self — тот же случай, если обёртка окажется flex.
   Область действия — только новый вид реестра (.ob-lbody__main).
   -------------------------------------------------------------------------- */
.ob-lbody__main .btn {
  vertical-align: middle;
  align-self: center;
  /* Не 0: тулбар переносится на вторую строку на узком экране, и без нижнего
     отступа строки кнопок слипаются. Отступ одинаков у всех — на выравнивание
     по вертикали он не влияет, его держит vertical-align. */
  margin-bottom: 6px;
  border-radius: var(--ob-r-xs);
  font: 500 13px/1.4 var(--ob-font);
  padding: 7px 14px;
}
.ob-lbody__main .btn + .btn { margin-left: 8px; }

/* Кнопка, у которой уже есть свой правый отступ (mr-1 и подобные утилиты
   bootstrap), не должна получать сверху ещё и наш: иначе зазор становится
   в полтора раза шире, чем у соседних пар. */
.ob-lbody__main .btn[class*="mr-"] + .btn { margin-left: 0; }

/* Первичное действие подвала — «Найти», ровно одно. Вторичное — «Сбросить». */
.ob-lbody__main .btn-primary {
  background: var(--ob-primary);
  border-color: var(--ob-primary);
  color: var(--ob-on-accent);
}
.ob-lbody__main .btn-primary:hover,
.ob-lbody__main .btn-primary:focus {
  background: var(--ob-primary-hover);
  border-color: var(--ob-primary-hover);
}
.ob-lbody__main .btn-secondary,
.ob-lbody__main .btn-light {
  background: var(--ob-link-hover);
  border-color: var(--ob-link-hover);
  color: var(--ob-on-accent);
}
.ob-lbody__main .btn-secondary:hover,
.ob-lbody__main .btn-light:hover {
  background: var(--ob-link);
  border-color: var(--ob-link);
  color: var(--ob-on-accent);
}

/* Роль-действия («Добавить производственную базу», «Создать акт») — зелёные.
   В подвале отбора они стоят рядом с «Поиском», и это действия разной природы:
   «Поиск» работает с уже заведёнными записями, роль-действие заводит новую.
   Цвет их и разводит — синее к отбору, зелёное к заведению.

   Реестры объявляют такую кнопку одним классом (MnuListPage.ActionButtonCss =
   btn-outline-primary); btn-success и btn-info остаются в правиле для реестров,
   ещё не переведённых на общую константу, — иначе одно и то же действие
   выглядело бы в них иначе.

   Заливка — --ob-ok-tx, а не --ob-success: второй задуман как акцент для точек
   и пилюль статуса, и белый текст на нём держится на пределе читаемости.
   Наведение — парный --ob-ok-tx-hover, как у --ob-primary и --ob-ghost: шаг того
   же зелёного в сторону, где контраст с текстом кнопки только растёт (в тёмной
   теме это светлее, в остальных темнее — текст на акценте там разный). Своих
   цветов правило не заводит: обе переменные объявлены во всех темах. */
.ob-lbody__main .btn-success,
.ob-lbody__main .btn-outline-primary,
.ob-lbody__main .btn-info {
  background: var(--ob-ok-tx);
  border-color: var(--ob-ok-tx);
  color: var(--ob-on-accent);
}
.ob-lbody__main .btn-success:hover,
.ob-lbody__main .btn-outline-primary:hover,
.ob-lbody__main .btn-info:hover {
  background: var(--ob-ok-tx-hover);
  border-color: var(--ob-ok-tx-hover);
  color: var(--ob-on-accent);
}

/* «Выгрузить в Excel» отжата вправо распоркой — на своём историческом месте
   в конце строки. Ищем по признаку «ссылка-кнопка на выгрузку»: у ядра это
   отдельная кнопка, класс которой от локали не зависит. */
.ob-lsearch__foot {
  flex: 0 0 100%;
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0;
}
.ob-lsearch__foot .btn[href*="xcel"],
.ob-lsearch__foot .btn[href*="xport"],
.ob-lsearch__foot .btn[onclick*="xcel"] { margin-left: auto; }

/* Пилюля статуса переносилась по словам: с nowrap её min-content забирал ширину
   у остальных столбцов. Теперь ширину столбцов считает 12.7.1 — короткий столбец
   берёт ровно своё, а излишек уходит в заполнитель, — и перенос стал вредным:
   «В обработке» ломалось на две строки даже когда полтаблицы пустует. */

/* --------------------------------------------------------------------------
   12.6 Панель НАД таблицей: чипы отбора слева, справа — «Показано N из M»,
   пагинация и выбор столбцов. Всё управление списком стоит до таблицы:
   страницы переключают, просмотрев её сверху, а не уходя в конец.
   -------------------------------------------------------------------------- */
.ob-lpanel {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin: 4px 0 10px;
  font-family: var(--ob-font);
}

.ob-lpanel__tools {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-left: auto;
}

.ob-lpanel__shown {
  font: 400 12.5px/1.5 var(--ob-font);
  color: var(--ob-text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Блок пагинации ядра переезжает в эту панель как есть: собственная сетка
   bootstrap внутри него больше не нужна — распорки задаёт панель. */
.ob-lpanel__tools > .row { margin: 0; width: auto; }

/* --------------------------------------------------------------------------
   12.6.2 Панель ПОД таблицей: та же пагинация ещё раз.

   Панель над таблицей остаётся главной — страницу чаще всего переключают,
   окинув список взглядом сверху. Но у того, кто список действительно
   прочитал, следующий шаг ровно один: следующая страница, — а пагинация в
   этот момент за экраном, и до неё надо прокрутить весь реестр обратно.
   Поэтому под последней строкой стоит вторая пагинация: не альтернатива
   верхней, а её продолжение в том месте, где чтение закончилось.

   Здесь только переключение страниц и подпись количества: кнопки реестра,
   выгрузка и выбор столбцов остаются наверху в единственном экземпляре —
   два «Выгрузить в Excel» на странице читались бы как две разные выгрузки.
   -------------------------------------------------------------------------- */
.ob-lpanel--bottom {
  margin: 12px 0 4px;
  /* Прижата вправо, как и верхняя: пагинация под левым краем таблицы и
     пагинация над её правым — это два разных элемента на вид. */
  justify-content: flex-end;
}

/* --------------------------------------------------------------------------
   12.6.1 Пагинация ядра — один вид во всех местах.

   Bootstrap сцепляет страницы в группу: рамки наезжают друг на друга на -1px,
   скруглены только края. Наша прежняя правка снимала рамку и радиус, но только
   внутри панели над таблицей — там, где пагинация осталась на своём месте
   (рядом с подписью «Всего записей» у ядра), она выглядела сцепленной группой.
   Один и тот же элемент выглядел двумя разными.

   Собираем страницы как отдельные плитки того же вида, что кнопки рядом:
   белая поверхность, рамка var(--ob-line), радиус var(--ob-r-xs). Селекторы
   с .pagination — чтобы перебить и тему hyper, и порядок подключения файлов.
   -------------------------------------------------------------------------- */
.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin: 0;
  padding-left: 0;
  list-style: none;
}
.pagination .page-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  min-height: 30px;
  margin: 0;
  padding: 0 8px;
  background: var(--ob-surface);
  border: 1px solid var(--ob-line);
  border-radius: var(--ob-r-xs);
  box-shadow: none;
  color: var(--ob-link);
  font: 500 12.5px/1.4 var(--ob-font);
}
/* Скругление краёв группы у bootstrap висит на :first-child/:last-child —
   перебиваем его же весом, иначе крайние страницы остаются с радиусом 10px. */
.pagination .page-item:first-child .page-link,
.pagination .page-item:last-child .page-link { border-radius: var(--ob-r-xs); }
.pagination .page-link:hover,
.pagination .page-link:focus {
  background: var(--ob-primary-soft-bg);
  border-color: var(--ob-primary-soft-line-hover);
  color: var(--ob-primary);
}
/* Текущая страница — приглушённая заливка и рамка акцентом: заливка держится
   на одном оттенке от фона, и в тёмных палитрах «вы здесь» читалось бы слабо,
   а рамка акцентом видна в любой из пяти. */
.pagination .page-item.active .page-link {
  background: var(--ob-primary-soft);
  border-color: var(--ob-primary);
  color: var(--ob-primary);
}
/* Недоступные ««» и «»» на первой и последней странице: остаются на месте,
   чтобы строка не прыгала, но не притворяются кнопками. */
.pagination .page-item.disabled .page-link {
  background: var(--ob-surface);
  border-color: var(--ob-line-soft);
  color: var(--ob-text-muted);
  opacity: .5;
}

/* Кнопки ядра, живущие рядом с пагинацией («Выгрузить в Excel», настройка
   колонок), — значки без подписи. Залитый синим квадрат читается как
   первичное действие, которым выгрузка не является: приводим их к тому же
   белому виду с рамкой, что у кнопки выбора столбцов рядом. */
.ob-lpanel__tools .btn,
.ob-lpanel__tools .btn-primary,
.ob-lpanel__tools .btn-secondary,
.ob-lpanel__tools .btn-info,
.ob-lpanel__tools .btn-success {
  /* Одна высота с плиткой страницы: кнопки и пагинация стоят в одной строке,
     и разница в один-два пикселя читается как сбитое выравнивание. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  min-height: 30px;
  background: var(--ob-surface);
  border: 1px solid var(--ob-line);
  border-radius: var(--ob-r-xs);
  box-shadow: none;
  padding: 0 9px;
  margin: 0;
  color: var(--ob-link);
  font: 500 12.5px/1.4 var(--ob-font);
}
.ob-lpanel__tools .btn:hover,
.ob-lpanel__tools .btn:focus {
  background: var(--ob-primary-soft-bg);
  border-color: var(--ob-primary-soft-line-hover);
  color: var(--ob-primary);
}
.ob-lpanel__tools .btn > i { font-size: 15px; }

/* Кнопка «Таблица» ядра — значок uil-table. Ядро печатает её в переключателе
   вида выборки (там же «Список» и «Конвертация в Excel»), а скрипт приносит
   кнопки ядра в панель над таблицей (§5). Переключаться некуда: реестр и так
   таблица, а панель, чипы отбора и выбор столбцов (§5.3) есть только у нашего
   вида — «Таблица» уводит из него в служебный вид ядра. Значок в разметке
   проекта больше нигде не встречается, поэтому убираем его везде, где бы ядро
   его ни напечатало.

   Прячем кнопку целиком, а не только значок: пустая рамка читалась бы как
   сломанное действие. Второе правило — обёртка кнопки, если кнопка в ней одна:
   иначе в строке с gap остаётся её зазор. Третье — сам значок, на случай
   разметки без кнопки вокруг.

   !important обязателен: display кнопкам панели задаёт правило выше
   (.ob-lpanel__tools .btn), и по весу оно сильнее. */
:is(a, button):has(.uil-table),
:is(.btn-group, .input-group-append, .input-group-prepend):has(> :only-child .uil-table),
.uil-table {
  display: none !important;
}

.ob-lchips {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  min-width: 0;
}
.ob-lchips__none {
  font: 400 12.5px/1.5 var(--ob-font);
  color: var(--ob-text-muted);
}
.ob-lchip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 4px 4px 9px;
  border-radius: var(--ob-r-pill);
  background: var(--ob-primary-soft);
  font: 400 12.5px/1.4 var(--ob-font);
  color: var(--ob-info-tx);
  max-width: 340px;
}
.ob-lchip__cap { color: var(--ob-info-tx); opacity: .8; }
.ob-lchip__cap::after { content: ':'; }
.ob-lchip__val {
  font-weight: 500;
  color: var(--ob-info-tx);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ob-lchip__x {
  flex: none;
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ob-info-tx);
  cursor: pointer;
}
.ob-lchip__x:hover { background: var(--ob-surface); color: var(--ob-primary); }
.ob-lchip__x > i { font-size: 13px; }

.ob-lchips__reset {
  border: 0;
  padding: 4px 2px;
  background: none;
  cursor: pointer;
  font: 500 12.5px/1.4 var(--ob-font);
  color: var(--ob-link);
}
.ob-lchips__reset:hover { color: var(--ob-primary); text-decoration: underline; }

/* Выбор столбцов. Подпись «Столбцы N из M» считает скрипт по фактическим
   столбцам таблицы. */
/* Кнопка с выпадающим списком в панели реестра. Их две — выбор столбцов и выбор
   кегля (§12.5.1) — и вид у них общий: рядом в одной строке две разные плитки
   читались бы как два разных по важности действия, а они равные. */
.ob-lcols,
.ob-lfont { position: relative; flex: none; }
.ob-lcols__btn,
.ob-lfont__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* Одна высота с плиткой страницы и кнопками ядра (12.6.1): в строке стоят
     пагинация, «Выгрузить в Excel», «Столбцы» и кегль, и четыре разные высоты
     читаются как сбитое выравнивание, а не как четыре равных действия. */
  min-height: 30px;
  padding: 0 10px;
  border: 1px solid var(--ob-line);
  border-radius: var(--ob-r-xs);
  background: var(--ob-surface);
  cursor: pointer;
  font: 500 12.5px/1.4 var(--ob-font);
  color: var(--ob-text-sub);
  white-space: nowrap;
}
.ob-lcols__btn:hover,
.ob-lfont__btn:hover { border-color: var(--ob-primary-soft-line-hover); color: var(--ob-primary); }
.ob-lcols__btn > i,
.ob-lfont__btn > i { font-size: 14px; }

.ob-lcols__menu,
.ob-lfont__menu {
  display: none;
  position: absolute;
  right: 0;
  top: calc(100% + 5px);
  z-index: 30;
  min-width: 240px;
  max-height: 330px;
  overflow-y: auto;
  padding: 6px;
  background: var(--ob-surface);
  border: 1px solid var(--ob-line);
  border-radius: var(--ob-r-md);
  box-shadow: var(--ob-shadow-menu);
}
.ob-lcols.is-open .ob-lcols__menu,
.ob-lfont.is-open .ob-lfont__menu { display: block; }

.ob-lcols__item,
.ob-lfont__item {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 6px 8px;
  border-radius: var(--ob-r-2xs);
  cursor: pointer;
  font: 400 13px/1.4 var(--ob-font);
  color: var(--ob-text);
}
.ob-lcols__item:hover,
.ob-lfont__item:hover { background: var(--ob-nav-hover); }
.ob-lcols__cap { flex: 1 1 auto; min-width: 0; }
.ob-lcols__always {
  flex: none;
  font: 400 11px/1.4 var(--ob-font);
  color: var(--ob-text-muted);
}
.ob-lcols__item > input[disabled] + .ob-lcols__cap { color: var(--ob-text-muted); }

.ob-lcol-off { display: none !important; }

/* --------------------------------------------------------------------------
   12.5.1 Выбор кегля реестра.

   Плотность (12.7.1) кегль уже меняет, но по своей надобности — чтобы столбцы
   поместились в ширину, — и мельчит его ровно тогда, когда столбцов много.
   Человеку же нужно обратное и по своей причине: реестр, за которым сидят
   весь день, читается крупнее, а масштаб браузера растянул бы заодно меню,
   шапку и полосу процесса — то есть отобрал бы ту самую ширину, которой
   реестру и так не хватает.

   Выбор общий на все реестры и живёт в localStorage: кому мелко здесь, мелко
   и в соседнем списке.
   -------------------------------------------------------------------------- */
.ob-lfont__menu { min-width: 190px; }

/* Шаг — кнопка, а не label с радио, как в выборе столбцов: там переключают
   набор из десятка галочек, здесь выбирают одно из четырёх и меню закрывается.
   Вид общий (правило выше), поэтому здесь только сброс собственных свойств
   кнопки — без него у неё серая заливка и рамка от браузера. */
.ob-lfont__item {
  width: 100%;
  border: 0;
  background: none;
  text-align: left;
  -webkit-appearance: none;
  appearance: none;
}

/* Подпись шага — своим кеглем: выбор видно до нажатия, и «Крупный» не
   приходится проверять на самой таблице. */
.ob-lfont__item[data-ob-size="s"]  { font-size: 12px; }
.ob-lfont__item[data-ob-size="m"]  { font-size: 13px; }
.ob-lfont__item[data-ob-size="l"]  { font-size: 14.5px; }
.ob-lfont__item[data-ob-size="xl"] { font-size: 16px; }

.ob-lfont__cap { flex: 1 1 auto; min-width: 0; }

/* Выбранный шаг — галочкой и заливкой: точка выбора в списке из четырёх
   подписей одинакового смысла иначе не находится. */
.ob-lfont__item > i {
  flex: none;
  font-size: 15px;
  color: var(--ob-primary);
  visibility: hidden;
}
.ob-lfont__item.is-active {
  background: var(--ob-primary-soft-bg);
  color: var(--ob-primary);
}
.ob-lfont__item.is-active > i { visibility: visible; }

/* --------------------------------------------------------------------------
   12.7 Таблица реестра
   Разметку печатает ядро, поэтому это доводка готовой таблицы: прокрутка
   снаружи, min-width внутри, шапка липнет, строка целиком ведёт в карточку.
   -------------------------------------------------------------------------- */
.ob-ltable__scroll {
  overflow-x: auto;
  overflow-y: visible;
  -webkit-overflow-scrolling: touch;
  background: var(--ob-surface);
  border-radius: var(--ob-r-lg);
}

.ob-lbody__main table.ob-ltable {
  min-width: 100%;
  width: 100%;
  margin-bottom: 0;
  border-collapse: separate;
  border-spacing: 0;
  font-family: var(--ob-font);

  /* Кегль реестра — одним числом на таблицу.

     Раньше каждый размер стоял в своём правиле цифрой, и в одной строке
     соседствовали два кегля: ячейка MnuListCells печаталась 13px/500, а штатная
     колонка ядра (t.Column(x => x.flId)) не получала ни одного нашего правила и
     оставалась 0.9rem/400 темы — 14.4px. Разница в полтора пикселя и в
     насыщенности читается как сбитая вёрстка, а не как выделение.

     Теперь размер один и считается из двух слагаемых:
       --ob-lfs-base — выбор пользователя (§12.5.1, кнопка кегля);
       --ob-lfs-step — поправка плотности (12.7.1, расчёт ширин).
     Оба переопределяются на самой таблице, поэтому --ob-lfs объявлен здесь же:
     подстановка var() в custom property происходит на том элементе, где
     свойство объявлено, и вынеси мы его в :root — выбор кегля перестал бы
     на него влиять.

     Значение здесь равно шагу по умолчанию (xl, см. FONT_DEFAULT в script.js),
     а не «обычному» 13px: атрибут data-ob-lfont скрипт ставит уже после первой
     отрисовки, и таблица успевала мигнуть мелким кеглем перед тем, как принять
     свой настоящий. */
  --ob-lfs-base: 16px;
  --ob-lfs-step: 0px;
  --ob-lfs: calc(var(--ob-lfs-base) + var(--ob-lfs-step));

  /* Предел столбца наименования. Одним значением на таблицу: им же ограничена
     сама ячейка (.ob-lcell--text), иначе внутри широкого столбца остаётся
     пустое место — тот же разъезд, только внутри ячейки.

     Считается от кегля, а не задаётся числом: предел в пикселях означает предел
     в знаках, а знак крупным кеглем шире. Фиксированные 300px на «Очень крупном»
     держали в строке не 40 знаков, а 33 — и наименование, занимавшее пять строк,
     разъезжалось на девять, хотя справа пустовал заполнитель. Множитель подобран
     так, чтобы на «Обычном» (13px) выйти на прежние 300px. */
  --ob-lcol-text: calc(var(--ob-lfs) * 23);
  /* Опознавательное наименование и второстепенный текст считаются от него, а не
     задаются числом: адаптив (15.) меняет один --ob-lcol-text, и оба предела
     съезжают вместе с ним.

     У опознавательного столбца потолок вдвое выше обычного текста, а не на 15%:
     это единственный столбец, с которого читают всю строку, и наименование
     организации в двести знаков ниже этого предела не укладывается ни на одном
     кегле. Столбец берёт эту ширину только когда она есть — иначе расчёт
     (5.3.1) сжимает его первым. */
  --ob-lcol-name: calc(var(--ob-lcol-text) * 2);
  --ob-lcol-narrow: calc(var(--ob-lcol-text) * 0.55);
}

/* Выбор кегля (§12.5.1). Атрибут ставит скрипт на саму таблицу — там же, где
   объявлен --ob-lfs, иначе подстановка прошла бы мимо выбора.

   Четыре шага, а не ползунок: реестр читают, а не настраивают, и выбор из
   четырёх подписей делается одним нажатием. Крупные шаги существуют ради тех,
   кто сидит за реестром весь день — 13px на большом мониторе им мелко, а
   масштаб браузера растягивает заодно и меню, и шапку. */
.ob-lbody__main table.ob-ltable[data-ob-lfont="s"]  { --ob-lfs-base: 12px; }
.ob-lbody__main table.ob-ltable[data-ob-lfont="m"]  { --ob-lfs-base: 13px; }
.ob-lbody__main table.ob-ltable[data-ob-lfont="l"]  { --ob-lfs-base: 14.5px; }
.ob-lbody__main table.ob-ltable[data-ob-lfont="xl"] { --ob-lfs-base: 16px; }

/* Шапка: подписи обычным регистром — капслок читается медленнее и ломает
   казахские подписи. Липнет к верху, чтобы при прокрутке было видно, что где. */
.ob-lbody__main table.ob-ltable th {
  position: sticky;
  top: 0;
  z-index: 2;
  vertical-align: bottom;
  white-space: normal;
  text-transform: none;
  letter-spacing: 0;
  background: var(--ob-surface);
  border-bottom: 1px solid var(--ob-line);
  padding: 10px 12px;
  font: 500 calc(var(--ob-lfs, 13px) - 1px)/1.4 var(--ob-font);
  color: var(--ob-text-muted);
}

/* Ячейки данных — по верхней кромке: в строке соседствуют одно- и трёхстрочные
   значения, и «прибитые» к верху они читаются как одна запись.

   Кегль задан у самой ячейки, а не только у .ob-lcell внутри неё: ячейку
   печатает либо MnuListCells (тогда внутри свой span со своим правилом), либо
   ядро — штатной колонкой поля, ссылкой, Label. У второй разметки наших классов
   нет, и без правила здесь она печаталась кеглем темы: одна и та же таблица
   выводила часть столбцов на 13px, часть на 14.4px. */
.ob-lbody__main table.ob-ltable td {
  vertical-align: top;
  padding: 10px 12px;
  border-bottom: 1px solid var(--ob-line-hairline);
  background: transparent;
  font: 400 var(--ob-lfs, 13px)/1.5 var(--ob-font);
  color: var(--ob-text);
}

/* Ссылка штатной колонки ядра: цвет ссылки, но не подчёркивание в покое —
   в столбце, где кликается каждая строка, сплошное подчёркивание читается
   как разметка, а не как действие. Тот же вид, что у .ob-lcell__main.
   Кнопка-ссылка (LinkUrl с btn) исключена: у неё свой вид от bootstrap. */
.ob-lbody__main table.ob-ltable td a:not(.btn) {
  color: var(--ob-link);
  text-decoration: none;
}
.ob-lbody__main table.ob-ltable td a:not(.btn):hover {
  color: var(--ob-primary);
  text-decoration: underline;
}

.ob-lbody__main table.ob-ltable tbody tr:hover td { background: var(--ob-surface-hover); }
.ob-lbody__main table.ob-ltable tbody tr.ob-lrow { cursor: pointer; }

/* Запись, которая ждёт действия роли: полоса слева вместо ещё одного бейджа
   в строке — она читается периферийным зрением и не занимает колонку. */
.ob-lbody__main table.ob-ltable tbody tr.ob-lrow--action td:first-child {
  box-shadow: inset 3px 0 0 var(--ob-warn);
}

/* Последняя колонка — шеврон: 34px хватает ровно на значок. */
.ob-lbody__main table.ob-ltable th.ob-lchev,
.ob-lbody__main table.ob-ltable td.ob-lchev {
  width: 34px;
  padding-left: 0;
  padding-right: 10px;
  text-align: right;
}
.ob-lbody__main table.ob-ltable td.ob-lchev > i {
  font-size: 16px;
  color: var(--ob-icon-faint);
}
.ob-lbody__main table.ob-ltable tbody tr:hover td.ob-lchev > i { color: var(--ob-link); }

/* --------------------------------------------------------------------------
   12.7.1 Ширина столбцов: запись читается одним взглядом слева направо.
   Тип столбца проставил скрипт (см. 5.3.1 в script.js).
   -------------------------------------------------------------------------- */
/* Ширина считается и проставляется в пикселях, поэтому она обязана считаться от
   края до края ячейки — вместе с её отступами. */
.ob-lbody__main table.ob-ltable th,
.ob-lbody__main table.ob-ltable td { box-sizing: border-box; }

/* Короткое значение — ровно по содержимому: width:1px в авто-раскладке таблицы
   и есть «по содержимому». Перенос запрещён у ячейки, а не у шапки: подпись
   «Сумма по договору, ₸» в одну строку задала бы столбцу лишние 60px. */
.ob-lbody__main table.ob-ltable td.ob-lc--hug {
  width: 1px;
  white-space: nowrap;
}
.ob-lbody__main table.ob-ltable th.ob-lc--hug { width: 1px; }

/* Наименование — растяжимый столбец: он и сжимается первым, когда места мало. */
.ob-lbody__main table.ob-ltable th.ob-lc--flex,
.ob-lbody__main table.ob-ltable td.ob-lc--flex { width: var(--ob-lcol-text); }

/* Опознавательный столбец просит по своему потолку, а не по общему для текста.

   Без этого правила ширина столбца наименования падала с ростом экрана: на
   1440px расчёт (5.3.1) раздавал ширины сам и отдавал наименованию 647px, а на
   1920px реестр помещался без расчёта — и в авто-раскладке столбец просил
   общие --ob-lcol-text, то есть 368px, а лишние 600px уходили в заполнитель.
   Наименование на широком экране разъезжалось на большее число строк, чем на
   узком. Потолок --ob-lcol-name объявлен ровно для этого столбца (12.7), здесь
   он становится и его запросом ширины. */
.ob-lbody__main table.ob-ltable td.ob-lc--flex:has(.ob-lcell--name) { width: var(--ob-lcol-name); }

/* Столбец, освобождённый расчётом (unlockWideHugs в 5.3.1): значение просило
   больше своей доли ширины и выдавливало остальные столбцы за край. Запрет
   переноса снимается — дальше значение делится по пробелам.

   overflow-wrap здесь намеренно не трогаем: он остаётся normal, и неразрывное
   значение (тот самый 18-значный номер) по символам не рвётся. Освобождение
   помогает прозе — наименованию из десятка слов, — а идентификатору не мешает.

   Потолок ячейки снимается тоже: ширину освобождённого столбца задаёт теперь
   расчёт, и потолок --id/--short внутри него оставил бы пустое место. */
.ob-lbody__main table.ob-ltable td.ob-lc--unlocked,
.ob-lbody__main table.ob-ltable td.ob-lc--unlocked .ob-lcell__main,
.ob-lbody__main table.ob-ltable td.ob-lc--unlocked .ob-lcell__sub {
  white-space: normal;
  max-width: none;
}

/* Заполнитель: забирает излишек ширины вместо промежутков между значениями. */
.ob-lbody__main table.ob-ltable th.ob-lfill,
.ob-lbody__main table.ob-ltable td.ob-lfill {
  width: auto;
  padding: 0;
}

/* Замер (на один расчёт, между двумя кадрами не видно). !important здесь по делу:
   замер обязан перебить и ширины столбцов выше, и уже проставленные пиксельные —
   иначе он мерил бы собственный прошлый ответ. */
.ob-lbody__main table.ob-ltable--measure {
  min-width: 0;
  /* !important и здесь: расчёт снимает --fixed перед замером, но правило ниже
     стоит в файле позже, и без него порядок источника решал бы за нас. */
  table-layout: auto !important;
}
.ob-lbody__main table.ob-ltable--measure th,
.ob-lbody__main table.ob-ltable--measure td {
  width: auto !important;
  min-width: 0 !important;
}
.ob-lbody__main table.ob-ltable--measure td.ob-lfill,
.ob-lbody__main table.ob-ltable--measure th.ob-lfill { display: none; }

/* Значения: по содержимому и без шапки — ширину задаёт значение, а не подпись. */
.ob-lbody__main table.ob-ltable--measure-body { width: max-content; }
.ob-lbody__main table.ob-ltable--measure-body > thead { display: none; }

/* Подписи: самое узкое слово подписи — это пол столбца. */
.ob-lbody__main table.ob-ltable--measure-head { width: min-content; }
.ob-lbody__main table.ob-ltable--measure-head > tbody { display: none; }

/* Ширины посчитаны и проставлены: содержимое переносится внутри своего столбца,
   а не расталкивает соседей. Предел ячейки наименования снят — предел теперь
   сам столбец, и внутри него текст занимает всю ширину. */
.ob-lbody__main table.ob-ltable--fixed { table-layout: fixed; }
.ob-ltable--fixed .ob-lcell--text { max-width: none; }

/* Перенос по слогам, а по символам — только если иначе слово не поместится:
   в самом узком столбце «Общеобразовательная» приходится рвать, и «Общеобразо-
   вательная» с переносом читается, а «Общеобразо/вательная» — нет.
   Правило на всей ячейке, а не на .ob-lcell--text: в растяжимый столбец попадает
   и штатная колонка поля с длинным значением, и ей перенос нужен так же. */
.ob-ltable--fixed td.ob-lc--flex {
  hyphens: auto;
  overflow-wrap: anywhere;
}

/* Шаг 1 — плотность: отступы и кегль. Читается по-прежнему, но реестр из
   десятка столбцов вмещается там, где не вмещался.

   Кегль правится одной поправкой к --ob-lfs, а не пятью числами по элементам:
   иначе плотность стирала бы выбранный пользователем кегль (§12.5.1) — реестр,
   которому не хватило ширины, возвращался бы к 12px независимо от выбора. */
.ob-lbody__main table.ob-ltable--tight { --ob-lfs-step: -0.75px; }
.ob-lbody__main table.ob-ltable--tight th,
.ob-lbody__main table.ob-ltable--tight td { padding: 8px 7px; }
.ob-ltable--tight .ob-lpill { padding: 2px 7px; }

/* Шаг 2 — плотнее: реестр, где одних сумм четыре столбца, на ноутбуке помещается
   только так. Мельче этого шага нет: 11px — предел, на котором цифра в таблице
   ещё читается, а дальше плотность перестаёт что-либо решать. */
.ob-lbody__main table.ob-ltable--dense { --ob-lfs-step: -1.25px; }
.ob-lbody__main table.ob-ltable--dense th,
.ob-lbody__main table.ob-ltable--dense td { padding: 7px 5px; }
.ob-ltable--dense .ob-lpill { padding: 2px 6px; }

/* Шага «переносить всё подряд» здесь нет намеренно: номер акта, сумма и статус
   в две строки читаются хуже, чем та же таблица с прокруткой. Реестр, которому
   не хватает ширины и на самом плотном шаге, сокращается снятием столбцов. */

/* Стрелка «Сначала новые» на первом столбце. Порядок задан на сервере, здесь
   только подпись — кнопки «Обновить» в реестре нет, перерисовка на «Найти». */
.ob-lsort {
  display: inline-flex;
  margin-left: 4px;
  vertical-align: -1px;
  color: var(--ob-text-muted);
}
.ob-lsort > i { font-size: 13px; }

/* Флаг «да/нет» значком: столбец галочек читается быстрее столбца слов. */
.ob-lflag { text-align: center; font-size: 16px; line-height: 1.4; }
.ob-lflag--yes { color: var(--ob-ok-tx); }
.ob-lflag--no { color: var(--ob-dn-tx); }
.ob-lflag--none { color: var(--ob-text-muted); font-size: 13px; }

/* --------------------------------------------------------------------------
   12.8 Пустой результат
   «Ничего не найдено» без пояснения читается как поломка, поэтому рядом —
   число записей реестра и выход из отбора.
   -------------------------------------------------------------------------- */
.ob-lempty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 46px 20px 50px;
  background: var(--ob-surface);
  border-radius: var(--ob-r-lg);
  text-align: center;
  font-family: var(--ob-font);
}
.ob-lempty__icon { font-size: 30px; color: var(--ob-icon-faint); }
.ob-lempty__title { font: 600 15px/1.4 var(--ob-font); color: var(--ob-text); }
.ob-lempty__hint {
  font: 400 13px/1.55 var(--ob-font);
  color: var(--ob-text-muted);
  max-width: 460px;
}
.ob-lempty > .ob-btn { margin-top: 6px; }

/* ==========================================================================
   13. Боковая панель: свёрнутая полоса с раскрытием по наведению
   (06-sidebar-rail.md). Панель темы остаётся position:fixed — полоса
   переопределяет только ширину, слои содержимого и отступ контента.

   Отступ контента — родными механизмами темы (margin-left у .content-page,
   left у .navbar-custom/.footer), а не распоркой из ТЗ: тема позиционирует
   рабочую область от фиксированной панели, статического потока здесь нет.
   Закрепление и раскрытие по-прежнему различаются одним классом (body).
   ========================================================================== */

body.ob-railed .left-side-menu.ob-rail {
  width: 78px;
  background: var(--ob-surface);
  border-right: 1px solid var(--ob-line);
  box-shadow: none;
  z-index: 1030; /* выше топбара темы (1001): раскрытая панель ложится поверх */
  transition: width .4s cubic-bezier(.25, .9, .3, 1), box-shadow .3s ease;
}
body.ob-railed .left-side-menu.ob-rail.is-open,
body.ob-railed .left-side-menu.ob-rail.ob-rail--pinned {
  width: 284px;
}
/* Тень — только пока панель оверлей; закреплённая встаёт в поток страницы. */
body.ob-railed .left-side-menu.ob-rail.is-open:not(.ob-rail--pinned) {
  box-shadow: 18px 0 40px -18px rgba(16, 24, 40, .22);
}

/* --- Строка логотипа -------------------------------------------------------
   Высота равна шапке приложения (70px в этой теме): разделительная линия идёт
   непрерывно через всю страницу и не обрывается на 78-м пикселе. */
body.ob-railed .ob-rail .logo {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: 70px;
  line-height: 70px;
  background: var(--ob-surface);
  border-bottom: 1px solid var(--ob-line);
  z-index: 2;
  overflow: hidden;
}
/* Оба логотипа в разметке одновременно — кроссфейд знака и полной версии. */
body.ob-railed .ob-rail .logo span.logo-lg,
body.ob-railed .ob-rail .logo span.logo-sm {
  position: absolute;
  top: 0; bottom: 0;
  display: flex;
  align-items: center;
}
body.ob-railed .ob-rail .logo span.logo-sm {
  left: 0; right: 0;
  justify-content: center;
  opacity: 1;
  transform: none;
  transition: opacity .18s ease, transform .34s cubic-bezier(.25, .9, .3, 1);
}
body.ob-railed .ob-rail .logo span.logo-lg {
  left: 20px;
  opacity: 0;
  transform: translateX(-10px);
  transition: opacity .26s ease .12s, transform .38s cubic-bezier(.25, .9, .3, 1) .1s;
}
body.ob-railed .ob-rail.is-open .logo span.logo-sm,
body.ob-railed .ob-rail.ob-rail--pinned .logo span.logo-sm {
  opacity: 0;
  transform: scale(.82);
}
body.ob-railed .ob-rail.is-open .logo span.logo-lg,
body.ob-railed .ob-rail.ob-rail--pinned .logo span.logo-lg {
  opacity: 1;
  transform: none;
}

/* Кнопка закрепления — в строке логотипа, видна только в раскрытой панели. */
.ob-rail__pin {
  position: absolute;
  top: 21px; right: 14px;
  width: 28px; height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--ob-text-muted);
  cursor: pointer;
  z-index: 3;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .2s ease, visibility .2s ease, background .16s ease;
}
.ob-rail__pin:hover { background: var(--ob-nav-hover); }
.ob-rail__pin > i { font-size: 17px; transition: transform .3s ease; }
body.ob-railed .ob-rail.is-open .ob-rail__pin,
body.ob-railed .ob-rail.ob-rail--pinned .ob-rail__pin {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}
/* Закреплено — стрелки смотрят обратно. */
.ob-rail--pinned .ob-rail__pin > i { transform: rotate(180deg); }

/* --- Два слоя содержимого --------------------------------------------------
   Полоса значков и полное меню наложены друг на друга; у скрытого слоя
   обязательны все три свойства — visibility убирает потомков из обхода Tab. */
.ob-rail__icons {
  position: absolute;
  top: 70px; bottom: 0;
  left: 0; right: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 10px 0;
  overflow-y: auto;
  opacity: 1;
  visibility: visible;
  transition: opacity .15s ease, visibility .15s ease;
}
body.ob-railed .ob-rail.is-open .ob-rail__icons,
body.ob-railed .ob-rail.ob-rail--pinned .ob-rail__icons {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
body.ob-railed .ob-rail .ob-rail__full {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .26s ease .1s, visibility .26s ease .1s;
}
body.ob-railed .ob-rail.is-open .ob-rail__full,
body.ob-railed .ob-rail.ob-rail--pinned .ob-rail__full {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

/* Значок раздела. */
.ob-rail__ico {
  flex: none;
  width: 46px; height: 42px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 13px;
  background: none;
  color: var(--ob-text-muted);
  cursor: pointer;
  position: relative;
  text-decoration: none;
  transition: background .16s ease;
}
.ob-rail__ico:hover { background: var(--ob-nav-hover); color: var(--ob-text-muted); }
.ob-rail__ico > i { font-size: 19px; }
.ob-rail__ico.is-active { background: var(--ob-primary-soft); color: var(--ob-primary); }
.ob-rail__ico.is-active:hover { color: var(--ob-primary); }


/* --- Каскад подписей -------------------------------------------------------
   Подписи выезжают слева по очереди; --i проставляет script.js (потолок 22).
   При сворачивании задержек нет — базовый transition без delay. */
body.ob-railed .ob-rail .ob-rail__full .side-nav-title,
body.ob-railed .ob-rail .ob-rail__full .side-nav-item > a > span,
body.ob-railed .ob-rail .ob-rail__full .ob-navsearch,
body.ob-railed .ob-rail .ob-rail__full .help-box {
  opacity: 0;
  transform: translateX(-10px);
  transition: opacity .28s ease, transform .34s cubic-bezier(.2, .9, .25, 1);
}
body.ob-railed .ob-rail.is-open .ob-rail__full .side-nav-title,
body.ob-railed .ob-rail.is-open .ob-rail__full .side-nav-item > a > span,
body.ob-railed .ob-rail.is-open .ob-rail__full .ob-navsearch,
body.ob-railed .ob-rail.is-open .ob-rail__full .help-box,
body.ob-railed .ob-rail.ob-rail--pinned .ob-rail__full .side-nav-title,
body.ob-railed .ob-rail.ob-rail--pinned .ob-rail__full .side-nav-item > a > span,
body.ob-railed .ob-rail.ob-rail--pinned .ob-rail__full .ob-navsearch,
body.ob-railed .ob-rail.ob-rail--pinned .ob-rail__full .help-box {
  opacity: 1;
  transform: none;
  transition-delay: calc(90ms + var(--i, 0) * 16ms);
}

/* --- Отступ рабочей области ------------------------------------------------
   Наведение НЕ сдвигает контент (панель — оверлей); закрепление сдвигает. */
body.ob-railed .content-page {
  margin-left: 78px;
  transition: margin-left .4s cubic-bezier(.25, .9, .3, 1);
}
body.ob-railed .navbar-custom {
  left: 78px;
  transition: left .4s cubic-bezier(.25, .9, .3, 1);
}
body.ob-railed .footer { left: 78px; transition: left .4s cubic-bezier(.25, .9, .3, 1); }
body.ob-railed.ob-rail-pinned .content-page { margin-left: 284px; }
body.ob-railed.ob-rail-pinned .navbar-custom { left: 284px; }
body.ob-railed.ob-rail-pinned .footer { left: 284px; }

/* Затемнение: появляется только при закреплении на узких экранах (ниже). */
.ob-rail-scrim {
  position: fixed;
  inset: 0;
  z-index: 1029;
  background: rgba(32, 36, 43, .42);
  opacity: 0;
  pointer-events: none;
  transition: opacity .3s ease;
}

/* --- Узкие экраны ----------------------------------------------------------
   1120: отдать 284px из ~900 — сломать таблицу. Закрепление остаётся
   оверлеем с затемнением; контент не сдвигается. */
@media (max-width: 1120px) {
  body.ob-railed.ob-rail-pinned .content-page { margin-left: 78px; }
  body.ob-railed.ob-rail-pinned .navbar-custom { left: 78px; }
  body.ob-railed.ob-rail-pinned .footer { left: 78px; }
  body.ob-railed.ob-rail-pinned .ob-rail-scrim {
    opacity: 1;
    pointer-events: auto;
  }
}

/* 768–1024: панель за бургером, полосы значков нет. */
@media (min-width: 768px) and (max-width: 1024.98px) {
  body.ob-railed .left-side-menu.ob-rail {
    width: 284px;
    transform: translateX(-100%);
    transition: transform .4s cubic-bezier(.25, .9, .3, 1);
  }
  body.ob-railed.sidebar-enable .left-side-menu.ob-rail,
  body.ob-railed.ob-rail-open .left-side-menu.ob-rail {
    transform: none;
    box-shadow: 18px 0 40px -18px rgba(16, 24, 40, .22);
  }
  body.ob-railed .content-page,
  body.ob-railed.ob-rail-pinned .content-page { margin-left: 0; }
  body.ob-railed .navbar-custom,
  body.ob-railed.ob-rail-pinned .navbar-custom { left: 0; }
  body.ob-railed .footer,
  body.ob-railed.ob-rail-pinned .footer { left: 0; }
  body.ob-railed .button-menu-mobile.disable-btn { display: inline-block; }
  /* За бургером всегда полное меню. */
  body.ob-railed .ob-rail .ob-rail__icons { display: none; }
  body.ob-railed .ob-rail .ob-rail__full,
  body.ob-railed .ob-rail .ob-rail__full .side-nav-title,
  body.ob-railed .ob-rail .ob-rail__full .side-nav-item > a > span,
  body.ob-railed .ob-rail .ob-rail__full .ob-navsearch,
  body.ob-railed .ob-rail .ob-rail__full .help-box {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: none;
  }
  body.ob-railed .ob-rail .ob-rail__pin { display: none; }
}

/* До 768 работает штатный мобильный режим темы (display:none + sidebar-enable);
   полоса не вмешивается — только возвращает слоям видимость. */
@media (max-width: 767.98px) {
  body.ob-railed .left-side-menu.ob-rail { width: 284px; }
  body.ob-railed .content-page { margin-left: 0; }
  body.ob-railed .ob-rail .ob-rail__icons { display: none; }
  body.ob-railed .ob-rail .ob-rail__full,
  body.ob-railed .ob-rail .ob-rail__full .side-nav-title,
  body.ob-railed .ob-rail .ob-rail__full .side-nav-item > a > span,
  body.ob-railed .ob-rail .ob-rail__full .ob-navsearch,
  body.ob-railed .ob-rail .ob-rail__full .help-box {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: none;
  }
  body.ob-railed .ob-rail .ob-rail__pin { display: none; }
}

/* Тач-устройства: наведения нет, раскрытие только закреплением (тап по значку
   раздела). Без этого первый тап раскрывал бы панель, а второй — переходил
   по ссылке, и пользователь терял один тап. */
@media (hover: none) {
  body.ob-railed .left-side-menu.ob-rail:hover { width: 78px; }
  body.ob-railed .left-side-menu.ob-rail.is-open,
  body.ob-railed .left-side-menu.ob-rail.ob-rail--pinned { width: 284px; }
}

/* ==========================================================================
   14. Боковое меню: вид по шаблону (02-components.md §7)
   Разметку рендерит ядро (MenuSidebarBlock + metismenu), поэтому переопределяем
   классы темы, а не заводим свои. Область действия — только раскрытая панель
   (.ob-rail__full), чтобы правила не протекли в мобильное меню и топбар.

   Специфичность держим на уровне «body.ob-railed .ob-rail__full …»: тема бьёт
   по body[data-leftbar-theme] и одним классом её не перекрыть.
   ========================================================================== */

/* Список: свои отступы, без наследия темы. */
body.ob-railed .ob-rail__full .side-nav {
  padding: 4px 0 8px;
  margin: 0;
  list-style: none;
  font-family: var(--ob-font);
}

/* --- Заголовок раздела: подпись + волосяная линия до края --- */
body.ob-railed .ob-rail__full .side-nav .side-nav-title {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 18px 22px 8px;
  font: 600 11px/1.2 var(--ob-font);
  letter-spacing: .05em;
  color: var(--ob-text-muted);
  text-transform: none; /* капслока в шаблоне нет — тема его включает */
  background: none;
}
body.ob-railed .ob-rail__full .side-nav .side-nav-title::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--ob-nav-hover);
}
/* Первый заголовок не отбивается от поиска лишним воздухом. */
body.ob-railed .ob-rail__full .side-nav > .side-nav-title:first-child { padding-top: 6px; }

/* --- Пункт первого уровня --- */
body.ob-railed .ob-rail__full .side-nav .side-nav-item > a {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 22px;
  font: 400 13.5px/1.35 var(--ob-font);
  color: var(--ob-text-sub);
  text-decoration: none;
  position: relative;
  transition: background .14s ease, color .14s ease;
}
/* Иконка — фиксированный бокс 18px и НУЛЕВЫЕ собственные отступы: интервал между
   иконкой и подписью задаёт gap строки. Тема ставит иконкам свой margin-right,
   и без сброса он складывался с gap — подпись уезжала на 10px. */
body.ob-railed .ob-rail__full .side-nav .side-nav-item > a > i {
  flex: none;
  width: 18px;
  min-width: 18px;
  margin: 0;
  font-size: 17px;
  line-height: inherit;
  text-align: center;
  color: var(--ob-text-ghost);
  transition: color .14s ease;
}
/* Подпись занимает остаток строки: бейдж и шеврон прижимаются вправо. */
body.ob-railed .ob-rail__full .side-nav .side-nav-item > a > span:not(.badge):not(.menu-arrow) {
  flex: 1;
  min-width: 0;
}
body.ob-railed .ob-rail__full .side-nav .side-nav-item > a:hover {
  background: var(--ob-nav-hover);
  color: var(--ob-text-sub);
}
body.ob-railed .ob-rail__full .side-nav .side-nav-item > a:hover > i { color: var(--ob-text-sub); }

/* Активный пункт: фон + полоса слева врезкой, чтобы не менять геометрию строки. */
body.ob-railed .ob-rail__full .side-nav .side-nav-item.mm-active > a,
body.ob-railed .ob-rail__full .side-nav .side-nav-item > a.active {
  background: var(--ob-primary-soft);
  box-shadow: inset 3px 0 0 var(--ob-primary);
  font-weight: 600;
  color: var(--ob-primary);
}
body.ob-railed .ob-rail__full .side-nav .side-nav-item.mm-active > a > i,
body.ob-railed .ob-rail__full .side-nav .side-nav-item > a.active > i { color: var(--ob-primary); }

/* Родитель активной ветки: выделен насыщенностью, но не фоном — фон занят
   самим активным пунктом внутри, две плашки подряд читались бы как две страницы. */
body.ob-railed .ob-rail__full .side-nav .side-nav-item.mm-active:has(.mm-show .mm-active) > a,
body.ob-railed .ob-rail__full .side-nav .side-nav-item.mm-active:has(ul .mm-active) > a {
  background: none;
  box-shadow: none;
  color: var(--ob-link);
}
body.ob-railed .ob-rail__full .side-nav .side-nav-item.mm-active:has(ul .mm-active) > a > i { color: var(--ob-primary); }

/* --- Вложенные уровни --- */
body.ob-railed .ob-rail__full .side-nav .side-nav-second-level,
body.ob-railed .ob-rail__full .side-nav .side-nav-third-level,
body.ob-railed .ob-rail__full .side-nav .side-nav-forth-level {
  padding: 0;
  margin: 0;
  list-style: none;
}
body.ob-railed .ob-rail__full .side-nav .side-nav-second-level > .side-nav-item > a,
body.ob-railed .ob-rail__full .side-nav .side-nav-third-level > .side-nav-item > a,
body.ob-railed .ob-rail__full .side-nav .side-nav-forth-level > .side-nav-item > a {
  padding: 8px 22px 8px 52px;
  font: 400 13px/1.35 var(--ob-font);
  color: var(--ob-text-muted);
}
body.ob-railed .ob-rail__full .side-nav .side-nav-third-level > .side-nav-item > a { padding-left: 66px; }
body.ob-railed .ob-rail__full .side-nav .side-nav-forth-level > .side-nav-item > a { padding-left: 80px; }

/* Заголовок внутри группы («Реестры» → «Финансирование») — тоньше внешнего. */
body.ob-railed .ob-rail__full .side-nav .side-nav-second-level > .side-nav-title {
  padding: 12px 22px 6px 52px;
  font-size: 10.5px;
}

/* Состояния вложенного пункта — ПОСЛЕ правил уровня: правила уровня задают
   размер и цвет для всех вложенных ссылок и иначе перебивают активный вид
   (одинаковая специфичность, кто ниже — тот и прав). */
body.ob-railed .ob-rail__full .side-nav .side-nav-second-level > .side-nav-item > a:hover,
body.ob-railed .ob-rail__full .side-nav .side-nav-third-level > .side-nav-item > a:hover,
body.ob-railed .ob-rail__full .side-nav .side-nav-forth-level > .side-nav-item > a:hover {
  background: var(--ob-nav-hover);
  color: var(--ob-text-sub);
}
body.ob-railed .ob-rail__full .side-nav .side-nav-second-level > .side-nav-item.mm-active > a,
body.ob-railed .ob-rail__full .side-nav .side-nav-third-level > .side-nav-item.mm-active > a,
body.ob-railed .ob-rail__full .side-nav .side-nav-forth-level > .side-nav-item.mm-active > a {
  background: var(--ob-primary-soft);
  box-shadow: inset 3px 0 0 var(--ob-primary);
  font-weight: 600;
  color: var(--ob-primary);
}

/* --- Шеврон раскрытия --- */
body.ob-railed .ob-rail__full .side-nav .menu-arrow {
  flex: none;
  margin-left: auto;
  width: 16px;
  height: 16px;
  position: static;
  color: var(--ob-icon-faint);
  transition: transform .16s ease;
}
body.ob-railed .ob-rail__full .side-nav .menu-arrow::before {
  content: '\e829'; /* uil-angle-down из hyper-theme/icons/unicons */
  font-family: 'unicons';
  font-size: 16px;
  line-height: 16px;
  display: block;
  transform: rotate(-90deg);
  transition: transform .16s ease;
}
/* Раскрытая ветка — шеврон вниз. aria-expanded ставит metismenu. */
body.ob-railed .ob-rail__full .side-nav .side-nav-item > a[aria-expanded="true"] .menu-arrow::before,
body.ob-railed .ob-rail__full .side-nav .side-nav-item.mm-active > a .menu-arrow::before {
  transform: none;
}

/* --- Бейджи: «требует действия» жёлтым, справочные числа синим --- */
/* float:none — тема кладёт бейдж во float-right, а в flex-строке это ломает порядок.
   margin-right:0 — её же отступ уводил бейдж от правого края на лишние 10px. */
body.ob-railed .ob-rail__full .side-nav .badge {
  flex: none;
  margin: 0 0 0 auto;
  float: none !important;
  position: static;
  border-radius: 4px;
  padding: 1px 5px;
  font: 600 10px/1.5 var(--ob-font);
  font-variant-numeric: tabular-nums;
}
body.ob-railed .ob-rail__full .side-nav .badge-warning {
  background: var(--ob-warn);
  color: var(--ob-on-accent);
}
body.ob-railed .ob-rail__full .side-nav .badge-info,
body.ob-railed .ob-rail__full .side-nav .badge-primary,
body.ob-railed .ob-rail__full .side-nav .badge-secondary {
  background: var(--ob-primary-soft);
  color: var(--ob-info-tx);
}
/* Бейдж перед шевроном: у пункта с детьми справа сначала число, потом стрелка. */
body.ob-railed .ob-rail__full .side-nav .side-nav-item > a > .badge + .menu-arrow { margin-left: 8px; }

/* QR-блок: отбит линией, как отдельный подвал панели. */
body.ob-railed .ob-rail__full .help-box {
  margin: 14px 16px 8px;
  padding-top: 14px;
  border-top: 1px solid var(--ob-line-faint);
  font: 400 12px/1.45 var(--ob-font);
  color: var(--ob-text-muted);
}

/* ==========================================================================
   15. Адаптив реестра
   Брейкпоинты те же, что у карточек: 1280 / 1024 / 768 / 560. На 560px таблица
   перестаёт быть таблицей и становится списком карточек — подписи ячеек
   скрипт проставил в data-label из шапки.
   ========================================================================== */
/* Пределы столбцов на узких экранах — тем же множителем кегля, что и в 12.7:
   числом они перестали бы съезжать вместе с выбранным кеглем. Множители 17 и 14
   дают на «Обычном» прежние 220px и 180px. */
@media (max-width: 1280px) {
  .ob-chain { padding: 12px 14px; }
  .ob-lbody__main table.ob-ltable { --ob-lcol-text: calc(var(--ob-lfs) * 17); }
}

@media (max-width: 1024px) {
  .ob-chain__steps { gap: 0; }
  .ob-chain__step { padding: 5px 8px; font-size: 12px; }
  .ob-lbody__main table.ob-ltable { --ob-lcol-text: calc(var(--ob-lfs) * 14); }
}

@media (max-width: 768px) {
  .ob-lpanel { flex-direction: column; align-items: stretch; }
  .ob-lcols,
  .ob-lfont { align-self: flex-start; }
  .ob-lpanel__tools { margin-left: 0; }
  /* Полоса процесса на узком экране прокручивается по горизонтали: перенос
     шагов на вторую строку рвёт последовательность, а она здесь и есть смысл. */
  .ob-chain__steps {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

@media (max-width: 560px) {
  .ob-lbody__main table.ob-ltable,
  .ob-lbody__main table.ob-ltable tbody,
  .ob-lbody__main table.ob-ltable tr,
  .ob-lbody__main table.ob-ltable td { display: block; width: auto; }

  .ob-lbody__main table.ob-ltable thead { display: none; }

  .ob-lbody__main table.ob-ltable tbody tr {
    margin-bottom: 10px;
    padding: 4px 0;
    background: var(--ob-surface);
    border: 1px solid var(--ob-line-faint);
    border-radius: var(--ob-r-md);
  }

  /* Ячейка карточки: слева подпись из шапки, справа значение. */
  .ob-lbody__main table.ob-ltable tbody td {
    display: flex;
    align-items: baseline;
    gap: 10px;
    border-bottom: 0;
    padding: 6px 12px;
  }
  .ob-lbody__main table.ob-ltable tbody td::before {
    content: attr(data-label);
    flex: 0 0 42%;
    font: 400 calc(var(--ob-lfs, 13px) - 1.5px)/1.4 var(--ob-font);
    color: var(--ob-text-muted);
  }
  .ob-lbody__main table.ob-ltable tbody td > * { flex: 1 1 auto; min-width: 0; }
  .ob-lnum { text-align: left; }

  /* Полоса «требует действия» — по всей карточке, а не у одной ячейки. */
  .ob-lbody__main table.ob-ltable tbody tr.ob-lrow--action {
    box-shadow: inset 3px 0 0 var(--ob-warn);
  }
  .ob-lbody__main table.ob-ltable tbody tr.ob-lrow--action td:first-child { box-shadow: none; }

  /* Шеврон в карточке не нужен: вся карточка и так кликается. */
  .ob-lbody__main table.ob-ltable td.ob-lchev { display: none; }

  /* Столбцов в карточном виде нет — значит, нет и их ширин: каждая ячейка это
     строка «подпись — значение» во всю карточку. Заполнитель ширины тем более
     ни к чему: пустая строка в конце каждой карточки. */
  .ob-lbody__main table.ob-ltable td.ob-lc--hug,
  .ob-lbody__main table.ob-ltable td.ob-lc--flex {
    width: auto;
    min-width: 0;
    white-space: normal;
  }
  .ob-lbody__main table.ob-ltable th.ob-lfill,
  .ob-lbody__main table.ob-ltable td.ob-lfill { display: none; }

  .ob-lcell--text { max-width: none; }
  .ob-lchip { max-width: 100%; }
}

/* ==========================================================================
   16. Темы интерфейса (08-themes.md)

   Пять палитр: светлая (значения :root выше), тёмная, тёплая, высокий
   контраст, монохромная. Все ob-классы написаны через var(--…), поэтому
   тема — это переопределение переменных на html[data-ob-theme="…"], ни один
   компонент о темах не знает.

   Атрибут ставится inline-скриптом в <head> до первой отрисовки
   (LayoutVertical.cshtml), выбор хранится в localStorage.
   ========================================================================== */

/* --------------------------------------------------------------------------
   16.1 Тёмная: работа в темноте. Акценты СВЕТЛЕЕ фона, поэтому текст на
   цветных кнопках и бейджах тёмный (--ob-on-accent), а роль теней берут
   границы — светящаяся тень на тёмном фоне выглядит грязью.
   -------------------------------------------------------------------------- */
html[data-ob-theme="dark"] {
  --ob-primary: #7FC2E8;
  --ob-primary-hover: #A3D5F2;
  --ob-link: #8CCAEC;
  --ob-link-hover: #A8D8F3;
  --ob-primary-soft: #1B2C38;
  --ob-primary-soft-bg: #16232E;
  --ob-primary-soft-line: #2E4A5E;
  --ob-primary-soft-line-hover: #3D5F76;

  --ob-text: #E6EAF0;
  --ob-text-sub: #A3B0BE;
  --ob-text-muted: #A3B0BE;
  --ob-text-label: #A3B0BE;
  --ob-text-faint: #A3B0BE;
  --ob-text-ghost: #A3B0BE;
  --ob-text-title-muted: #A3B0BE;

  --ob-bg: #12161B;
  --ob-surface: #1A1F26;
  --ob-surface-alt: #20262E;
  --ob-surface-hover: #232A33;
  --ob-nav-hover: #273039;

  --ob-line: #2C3540;
  --ob-line-soft: #262E38;
  --ob-line-faint: #212832;
  --ob-line-hairline: #212832;

  --ob-success: #7DD65A;
  --ob-warn: #F0C05A;
  --ob-danger: #F08183;

  --ob-on-accent: #0C1116;
  --ob-on-ghost: #E6EAF0;
  --ob-ghost: #2E4A5E;
  --ob-ghost-hover: #3D5F76;
  --ob-info-tx: #8CCAEC;
  --ob-icon-faint: #4E5A66;
  --ob-ok-bg: #172A16;  --ob-ok-tx: #96E07A;  --ob-ok-tx-hover: #A9E890;  --ob-ok-soft: #26401F; --ob-ok-ln: #26401F;
  --ob-wn-bg: #2E2410;  --ob-wn-tx: #EFC875;  --ob-wn-bg2: #3A2C10; --ob-wn-tx2: #F2CE84; --ob-wn-ln: #3A2C10;
  --ob-dn-bg: #301A1B;  --ob-dn-tx: #F0999B;  --ob-dn-ln: #4A2426;
  --ob-nu-bg: #232A33;

  --ob-shadow-card: 0 0 0 1px rgba(255, 255, 255, .06);
  --ob-shadow-header: 0 1px 0 rgba(255, 255, 255, .06);
  --ob-shadow-menu: 0 0 0 1px rgba(255, 255, 255, .08), 0 14px 38px rgba(0, 0, 0, .5);
}

/* --------------------------------------------------------------------------
   16.2 Тёплая: меньше синего света. Акцент — тёплый коричневый: синяя
   первичная кнопка свела бы смысл темы на нет на самом заметном элементе.
   -------------------------------------------------------------------------- */
html[data-ob-theme="warm"] {
  --ob-primary: #8A5518;
  --ob-primary-hover: #6E4211;
  --ob-link: #8A5518;
  --ob-link-hover: #A86A25;
  --ob-primary-soft: #F1E3CB;
  --ob-primary-soft-bg: #F7EEDE;
  --ob-primary-soft-line: #DCC7A4;
  --ob-primary-soft-line-hover: #C9AF85;

  --ob-text: #332B20;
  --ob-text-sub: #6B5D48;
  --ob-text-muted: #6B5D48;
  --ob-text-label: #6B5D48;
  --ob-text-faint: #6B5D48;
  --ob-text-ghost: #6B5D48;
  --ob-text-title-muted: #6B5D48;

  --ob-bg: #F2EAD8;
  --ob-surface: #FCF8EE;
  --ob-surface-alt: #F6EFE0;
  --ob-surface-hover: #F9F3E6;
  --ob-nav-hover: #F3EBDA;

  --ob-line: #E0D3B8;
  --ob-line-soft: #E8DCC5;
  --ob-line-faint: #EFE6D3;
  --ob-line-hairline: #EFE6D3;

  --ob-success: #4E7A1F;
  --ob-warn: #9A6B00;
  --ob-danger: #A83C2A;

  --ob-on-accent: #FDF8ED;
  --ob-on-ghost: #FDF8ED;
  --ob-ghost: #A86A25;
  --ob-ghost-hover: #8A5518;
  --ob-info-tx: #8A5518;
  --ob-icon-faint: #BFB09A;
  --ob-ok-bg: #E8EFD5;  --ob-ok-tx: #3F6416;  --ob-ok-tx-hover: #345211;  --ob-ok-soft: #CFDCB0; --ob-ok-ln: #CFDCB0;
  --ob-wn-bg: #F5E6C4;  --ob-wn-tx: #7A5300;  --ob-wn-bg2: #F0DDB2; --ob-wn-tx2: #6B4700; --ob-wn-ln: #EBD5A0;
  --ob-dn-bg: #F5DED6;  --ob-dn-tx: #8E3020;  --ob-dn-ln: #E0BCAF;
  --ob-nu-bg: #F0E7D6;
}

/* --------------------------------------------------------------------------
   16.3 Высокий контраст: солнце, дешёвый монитор, слабое зрение. Границы
   намеренно тёмные — рамка видна, а не угадывается; пары текст/фон ≥7:1.
   -------------------------------------------------------------------------- */
html[data-ob-theme="contrast"] {
  --ob-primary: #00456B;
  --ob-primary-hover: #003452;
  --ob-link: #00456B;
  --ob-link-hover: #00354F;
  --ob-primary-soft: #D8E9F4;
  --ob-primary-soft-bg: #E8F2F9;
  --ob-primary-soft-line: #00456B;
  --ob-primary-soft-line-hover: #00456B;

  --ob-text: #000000;
  --ob-text-sub: #2B333D;
  --ob-text-muted: #2B333D;
  --ob-text-label: #2B333D;
  --ob-text-faint: #2B333D;
  --ob-text-ghost: #2B333D;
  --ob-text-title-muted: #2B333D;

  --ob-bg: #FFFFFF;
  --ob-surface: #FFFFFF;
  --ob-surface-alt: #F2F4F6;
  --ob-surface-hover: #F7F8FA;
  --ob-nav-hover: #EDEFF2;

  --ob-line: #5A6472;
  --ob-line-soft: #7C8794;
  --ob-line-faint: #98A2AE;
  --ob-line-hairline: #98A2AE;

  --ob-success: #1B6E00;
  --ob-warn: #7A4E00;
  --ob-danger: #A5060A;

  --ob-on-accent: #FFFFFF;
  --ob-on-ghost: #FFFFFF;
  --ob-ghost: #00456B;
  --ob-ghost-hover: #003452;
  --ob-info-tx: #00456B;
  --ob-icon-faint: #5A6472;
  --ob-ok-bg: #DCF0D2;  --ob-ok-tx: #14520A;  --ob-ok-tx-hover: #0E3D06;  --ob-ok-soft: #1B6E00; --ob-ok-ln: #1B6E00;
  --ob-wn-bg: #F7E6BE;  --ob-wn-tx: #5C3B00;  --ob-wn-bg2: #F2DCA8; --ob-wn-tx2: #4A2F00; --ob-wn-ln: #7A4E00;
  --ob-dn-bg: #F8D7D8;  --ob-dn-tx: #7A0407;  --ob-dn-ln: #A5060A;
  --ob-nu-bg: #E4E7EB;
}

/* --------------------------------------------------------------------------
   16.4 Монохромная: цвет не отвлекает от цифр; цветовая слепота; проверка
   перед печатью. Допустима потому, что каждая статус-пилюля несёт подпись,
   а флаги — разные глифы: статус читается без цвета.
   -------------------------------------------------------------------------- */
html[data-ob-theme="mono"] {
  --ob-primary: #2E3236;
  --ob-primary-hover: #16181A;
  --ob-link: #33383D;
  --ob-link-hover: #4A5055;
  --ob-primary-soft: #E4E5E7;
  --ob-primary-soft-bg: #F1F2F3;
  --ob-primary-soft-line: #C4C7CA;
  --ob-primary-soft-line-hover: #A8ACB1;

  --ob-text: #16181A;
  --ob-text-sub: #55595E;
  --ob-text-muted: #55595E;
  --ob-text-label: #55595E;
  --ob-text-faint: #55595E;
  --ob-text-ghost: #55595E;
  --ob-text-title-muted: #55595E;

  --ob-bg: #F0F1F2;
  --ob-surface: #FFFFFF;
  --ob-surface-alt: #F5F6F7;
  --ob-surface-hover: #FAFAFB;
  --ob-nav-hover: #F0F1F2;

  --ob-line: #CBCDD1;
  --ob-line-soft: #DCDEE1;
  --ob-line-faint: #E9EAEC;
  --ob-line-hairline: #E9EAEC;

  --ob-success: #3F4448;
  --ob-warn: #5E656B;
  --ob-danger: #16181A;

  --ob-on-accent: #FFFFFF;
  --ob-on-ghost: #FFFFFF;
  --ob-ghost: #4A5055;
  --ob-ghost-hover: #33383D;
  --ob-info-tx: #33383D;
  --ob-icon-faint: #A8ACB1;
  --ob-ok-bg: #E7E8EA;  --ob-ok-tx: #2A2E31;  --ob-ok-tx-hover: #1B1E20;  --ob-ok-soft: #CFD1D4; --ob-ok-ln: #CFD1D4;
  --ob-wn-bg: #EDEEF0;  --ob-wn-tx: #3A3E42;  --ob-wn-bg2: #E2E4E6; --ob-wn-tx2: #2A2E31; --ob-wn-ln: #CFD1D4;
  --ob-dn-bg: #E4E5E7;  --ob-dn-tx: #16181A;  --ob-dn-ln: #B5B9BD;
  --ob-nu-bg: #EBECEE;
}

/* 16.5 Тема по умолчанию — светлая: палитра :root (§16.1) действует, пока на
   html нет data-ob-theme, и отдельного html[data-ob-theme="light"] нет —
   светлая это и есть отсутствие атрибута. Настройка ОС не учитывается:
   prefers-color-scheme не читает ни css, ни inline-скрипт в <head>
   (LayoutVertical.cshtml), тёмную ставит только явный выбор пользователя. */

/* --------------------------------------------------------------------------
   16.6 Печать — всегда в светлой палитре, какая бы тема ни была выбрана.
   -------------------------------------------------------------------------- */
@media print {
  html, html[data-ob-theme] {
    --ob-primary: #006196;
    --ob-primary-hover: #00507E;
    --ob-link: #1B6E9C;
    --ob-link-hover: #2D8DC1;
    --ob-primary-soft: #E5F1F8;
    --ob-primary-soft-bg: #F4FAFD;
    --ob-primary-soft-line: #CFE2EE;
    --ob-primary-soft-line-hover: #9FC9E0;

    --ob-text: #2A2C31;
    --ob-text-sub: #64717E;
    --ob-text-muted: #64717E;
    --ob-text-label: #64717E;
    --ob-text-faint: #64717E;
    --ob-text-ghost: #64717E;
    --ob-text-title-muted: #64717E;

    --ob-bg: #FFFFFF;
    --ob-surface: #FFFFFF;
    --ob-surface-alt: #F7FAFC;
    --ob-surface-hover: #FAFCFD;
    --ob-nav-hover: #F6F9FB;

    --ob-line: #E4E9F0;
    --ob-line-soft: #EAEFF4;
    --ob-line-faint: #F0F4F8;
    --ob-line-hairline: #F2F6F9;

    --ob-success: #52C41A;
    --ob-warn: #FAAD14;
    --ob-danger: #FF4D4F;

    --ob-on-accent: #FFFFFF;
    --ob-on-ghost: #FFFFFF;
    --ob-ghost: #2D8DC1;
    --ob-ghost-hover: #2680B2;
    --ob-info-tx: #1E6E9C;
    --ob-icon-faint: #C3CEDA;
    --ob-ok-bg: #EAF7E4;  --ob-ok-tx: #2F7A0D;  --ob-ok-tx-hover: #256208;  --ob-ok-soft: #BFE3AC; --ob-ok-ln: #CDEBD6;
    --ob-wn-bg: #FFF6E0;  --ob-wn-tx: #9A6B00;  --ob-wn-bg2: #FFE9B8; --ob-wn-tx2: #7A4E00; --ob-wn-ln: #F5DFA8;
    --ob-dn-bg: #FFECEC;  --ob-dn-tx: #D4383A;  --ob-dn-ln: #F5C6C7;
    --ob-nu-bg: #F1F5F9;
  }
}

/* --------------------------------------------------------------------------
   16.7 Переключатель темы в белой шапке: активная тема помечена галочкой,
   а иконка самой кнопки показывает выбранную тему — солнце у светлой, луна
   у тёмной и так далее. Кисть была одна на все пять палитр: какая тема стоит
   сейчас, приходилось выяснять, открыв меню.

   Глиф ставится в css по html[data-ob-theme], а не скриптом: атрибут стоит
   ещё до первой отрисовки (inline-скрипт в <head>), поэтому правильная иконка
   видна сразу — при выборе темы скриптом менять её отдельно не нужно.
   Коды взяты из unicons.css: sun, moon, coffee, adjust-half, circle-layer.
   -------------------------------------------------------------------------- */
.ob-theme-toggle-icon { font-size: 17px; }

/* Тема по умолчанию — светлая: атрибута может не быть вовсе. */
.ob-theme-toggle-icon::before { content: '\eb9d'; }
html[data-ob-theme="light"] .ob-theme-toggle-icon::before { content: '\eb9d'; }
html[data-ob-theme="dark"] .ob-theme-toggle-icon::before { content: '\eacc'; }
html[data-ob-theme="warm"] .ob-theme-toggle-icon::before { content: '\e909'; }
html[data-ob-theme="contrast"] .ob-theme-toggle-icon::before { content: '\e80f'; }
html[data-ob-theme="mono"] .ob-theme-toggle-icon::before { content: '\e8cb'; }

[data-ob-theme-pick] { position: relative; padding-right: 34px; }
[data-ob-theme-pick].is-active::after {
  content: '\2713';
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  font-weight: 700;
  color: var(--ob-primary);
}

/* --------------------------------------------------------------------------
   16.8 Тема и оболочка hyper. Палитры выше красят только ob-классы; контейнеры
   темы (фон страницы, белая шапка, панель меню, карточки, выпадающие меню)
   покрашены темой жёстко. В нестандартной палитре их приводим к переменным —
   иначе тёмная тема выглядела бы тёмным островом контента в белой раме.
   Область действия — только когда выбрана НЕ светлая палитра: светлая тема
   оставляет оболочку ровно такой, какой её рисует hyper.
   -------------------------------------------------------------------------- */
html[data-ob-theme="dark"] body,
html[data-ob-theme="warm"] body,
html[data-ob-theme="contrast"] body,
html[data-ob-theme="mono"] body,
html[data-ob-theme="dark"] .content-page,
html[data-ob-theme="warm"] .content-page,
html[data-ob-theme="contrast"] .content-page,
html[data-ob-theme="mono"] .content-page {
  background: var(--ob-bg);
  color: var(--ob-text);
}

html[data-ob-theme="dark"] .navbar-custom,
html[data-ob-theme="warm"] .navbar-custom,
html[data-ob-theme="contrast"] .navbar-custom,
html[data-ob-theme="mono"] .navbar-custom,
html[data-ob-theme="dark"] .left-side-menu,
html[data-ob-theme="warm"] .left-side-menu,
html[data-ob-theme="contrast"] .left-side-menu,
html[data-ob-theme="mono"] .left-side-menu {
  background: var(--ob-surface);
  box-shadow: none;
  border-color: var(--ob-line);
}

html[data-ob-theme="dark"] .card,
html[data-ob-theme="warm"] .card,
html[data-ob-theme="contrast"] .card,
html[data-ob-theme="mono"] .card,
html[data-ob-theme="dark"] .dropdown-menu,
html[data-ob-theme="warm"] .dropdown-menu,
html[data-ob-theme="contrast"] .dropdown-menu,
html[data-ob-theme="mono"] .dropdown-menu,
html[data-ob-theme="dark"] .modal-content,
html[data-ob-theme="warm"] .modal-content,
html[data-ob-theme="contrast"] .modal-content,
html[data-ob-theme="mono"] .modal-content {
  background: var(--ob-surface);
  color: var(--ob-text);
  box-shadow: var(--ob-shadow-card);
}

html[data-ob-theme="dark"] .dropdown-item,
html[data-ob-theme="warm"] .dropdown-item,
html[data-ob-theme="contrast"] .dropdown-item,
html[data-ob-theme="mono"] .dropdown-item { color: var(--ob-text); }

html[data-ob-theme="dark"] .dropdown-item:hover,
html[data-ob-theme="warm"] .dropdown-item:hover,
html[data-ob-theme="contrast"] .dropdown-item:hover,
html[data-ob-theme="mono"] .dropdown-item:hover {
  background: var(--ob-nav-hover);
  color: var(--ob-text);
}

/* Контролы форм: поля отбора реестров и полей карточек. */
html[data-ob-theme="dark"] .form-control,
html[data-ob-theme="warm"] .form-control,
html[data-ob-theme="contrast"] .form-control,
html[data-ob-theme="mono"] .form-control,
html[data-ob-theme="dark"] .custom-select,
html[data-ob-theme="warm"] .custom-select,
html[data-ob-theme="contrast"] .custom-select,
html[data-ob-theme="mono"] .custom-select {
  background-color: var(--ob-surface);
  border-color: var(--ob-line);
  color: var(--ob-text);
}
html[data-ob-theme="dark"] .form-control::placeholder,
html[data-ob-theme="warm"] .form-control::placeholder,
html[data-ob-theme="contrast"] .form-control::placeholder,
html[data-ob-theme="mono"] .form-control::placeholder { color: var(--ob-text-muted); }

/* Таблицы ядра вне нового вида реестра. */
html[data-ob-theme="dark"] .table,
html[data-ob-theme="warm"] .table,
html[data-ob-theme="contrast"] .table,
html[data-ob-theme="mono"] .table { color: var(--ob-text); }

html[data-ob-theme="dark"] .table th, html[data-ob-theme="dark"] .table td,
html[data-ob-theme="warm"] .table th, html[data-ob-theme="warm"] .table td,
html[data-ob-theme="contrast"] .table th, html[data-ob-theme="contrast"] .table td,
html[data-ob-theme="mono"] .table th, html[data-ob-theme="mono"] .table td {
  border-color: var(--ob-line-soft);
}

/* Шапка таблицы под палитру — правило общее для всех тем, включая светлую,
   и живёт в §11 рядом с прочими правками таблиц ядра. */

/* Текст темы: заголовки страниц, крошки, подписи. */
html[data-ob-theme="dark"] .page-title, html[data-ob-theme="dark"] .breadcrumb-item, html[data-ob-theme="dark"] label,
html[data-ob-theme="warm"] .page-title, html[data-ob-theme="warm"] .breadcrumb-item, html[data-ob-theme="warm"] label,
html[data-ob-theme="contrast"] .page-title, html[data-ob-theme="contrast"] .breadcrumb-item, html[data-ob-theme="contrast"] label,
html[data-ob-theme="mono"] .page-title, html[data-ob-theme="mono"] .breadcrumb-item, html[data-ob-theme="mono"] label {
  color: var(--ob-text);
}

/* Пункты бокового меню темы. */
html[data-ob-theme="dark"] .side-nav .side-nav-link,
html[data-ob-theme="warm"] .side-nav .side-nav-link,
html[data-ob-theme="contrast"] .side-nav .side-nav-link,
html[data-ob-theme="mono"] .side-nav .side-nav-link { color: var(--ob-text-sub); }

/* --------------------------------------------------------------------------
   16.9 Остатки светлой оболочки, до которых 16.8 не достаёт: hyper красит их
   жёсткими #ffffff и #E5F1F8 в обход своих же переменных, поэтому в тёмной
   палитре над меню висела белая плашка логотипа, полоса локальных задач
   оставалась белой, а QR-блок — голубым. Каждый цвет заменён на ту же роль
   из палитры, а не на «просто тёмный»: белая подложка — var(--ob-surface),
   голубая заливка — var(--ob-primary-soft).
   -------------------------------------------------------------------------- */

/* Строка логотипа. structure.css красит её `#ffffff !important` через
   body[data-leftbar-theme], поэтому перебить можно только тем же флагом. */
html[data-ob-theme="dark"] .left-side-menu .logo,
html[data-ob-theme="warm"] .left-side-menu .logo,
html[data-ob-theme="contrast"] .left-side-menu .logo,
html[data-ob-theme="mono"] .left-side-menu .logo {
  background: var(--ob-surface) !important;
}

/* Сам знак на этой плашке. Он есть в двух вариантах: тёмные чернила (#313A46)
   под светлую подложку и светлые — под тёмную. Тема выбирает вариант по
   data-leftbar-theme и о палитре не знает, поэтому на потемневшей плашке
   оставался тёмный знак. Подменяем файл у dark-классов, а не переключаем пару
   .logo-light/.logo-dark: пара есть только в боковой панели, а те же классы
   висят ещё в подвале и в мобильной шапке — одно правило закрывает все три.

   Только dark: warm, contrast и mono — светлые палитры, тёмные чернила там верны.
   Знак «-sm» не подменяем: light и dark различаются лишь id градиентов. */
html[data-ob-theme="dark"] .logo-template-dark {
  background-image: url(../../../Theme/ui-packages/project-theme/logo/template-light.svg);
}
html[data-ob-theme="dark"] .logo-template-dark-text::before { color: var(--ob-text); }

/* Исключение — мобильная верхняя полоса: .mobile-topbar залит #f2f3f8 и тёмным
   не становится, там тёмный знак по-прежнему единственный читаемый. */
html[data-ob-theme="dark"] .mobile-topbar .logo-template-dark {
  background-image: url(../../../Theme/ui-packages/project-theme/logo/template-dark.svg);
}

/* Подсветка под знаком — rgb(255 255 255 / 10%) у images.css. На белой плашке
   её не видно, на тёмной она превращается в светлую полосу вокруг логотипа. */
html[data-ob-theme="dark"] .menu-logo-container { background-color: transparent; }

/* Полоса локальных задач (MenuLocalTasks): в разметке у неё utility-класс
   bg-white, а он тоже с !important. Класс .bg-white целиком не перекрашиваем:
   им же залита подложка QR-кода eGov Mobile в окне подписи (user-certificate-*)
   — коду нужно белое поле, иначе его не считает камера. */
html[data-ob-theme="dark"] .nav-local-tasks.bg-white,
html[data-ob-theme="warm"] .nav-local-tasks.bg-white,
html[data-ob-theme="contrast"] .nav-local-tasks.bg-white,
html[data-ob-theme="mono"] .nav-local-tasks.bg-white {
  background-color: var(--ob-surface) !important;
}

/* Utility-класс .bg-light (#E5F1F8 с !important) — светлая подложка: плитки
   файлов, блоки <pre>, карточки подписи, чипы кода и — чаще всего —
   readonly-поля: ядро рисует их не полем, а `<div class='form-control
   bg-light'>`, поэтому правило для .form-control (§16.8) до них не достаёт, и
   поле оставалось светло-голубым со светлым текстом внутри. Роль переносится
   один в один: var(--ob-primary-soft) в светлой палитре и есть #E5F1F8.
   !important обязателен: у оригинала он есть. */
html[data-ob-theme="dark"] .bg-light,
html[data-ob-theme="warm"] .bg-light,
html[data-ob-theme="contrast"] .bg-light,
html[data-ob-theme="mono"] .bg-light {
  background-color: var(--ob-primary-soft) !important;
}

/* Шапка карточки — ею же ядро рисует заголовок аккордеона (Accordion →
   .card-header.accordion-header-N), а bootstrap заливает её #ffffff. Тело
   карточки темнеет по §16.8, шапка — нет, и надпись, наследующая --ob-text,
   оказывалась белым по белому. Ссылка в шапке аккордеона — не ссылка, а сам
   заголовок (data-toggle="collapse" сворачивает карточку), поэтому её красим
   текстом, а не --ob-link. .header-title и .text-dark — та же надпись у шапок,
   собранных разметкой модулей; у .text-dark свой !important. */
html[data-ob-theme="dark"] .card-header,
html[data-ob-theme="warm"] .card-header,
html[data-ob-theme="contrast"] .card-header,
html[data-ob-theme="mono"] .card-header {
  background-color: var(--ob-surface-alt);
  border-bottom-color: var(--ob-line);
  color: var(--ob-text);
}

html[data-ob-theme="dark"] .card-header a[data-toggle="collapse"],
html[data-ob-theme="dark"] .card-header .header-title,
html[data-ob-theme="dark"] .card-header .text-dark,
html[data-ob-theme="warm"] .card-header a[data-toggle="collapse"],
html[data-ob-theme="warm"] .card-header .header-title,
html[data-ob-theme="warm"] .card-header .text-dark,
html[data-ob-theme="contrast"] .card-header a[data-toggle="collapse"],
html[data-ob-theme="contrast"] .card-header .header-title,
html[data-ob-theme="contrast"] .card-header .text-dark,
html[data-ob-theme="mono"] .card-header a[data-toggle="collapse"],
html[data-ob-theme="mono"] .card-header .header-title,
html[data-ob-theme="mono"] .card-header .text-dark {
  color: var(--ob-text) !important;
}

/* Неактивная вкладка у hyper — #6c757d: на тёмной подложке это 3,4:1, ниже
   порога для 13px. */
html[data-ob-theme="dark"] .nav-local-tasks > li > a,
html[data-ob-theme="warm"] .nav-local-tasks > li > a,
html[data-ob-theme="contrast"] .nav-local-tasks > li > a,
html[data-ob-theme="mono"] .nav-local-tasks > li > a { color: var(--ob-text-sub); }

html[data-ob-theme="dark"] .nav-local-tasks > li > a.active,
html[data-ob-theme="warm"] .nav-local-tasks > li > a.active,
html[data-ob-theme="contrast"] .nav-local-tasks > li > a.active,
html[data-ob-theme="mono"] .nav-local-tasks > li > a.active {
  background-color: var(--ob-primary);
  color: var(--ob-on-accent);
}

/* Пагинация здесь не переопределяется. Её вид (§12.6.1) целиком собран
   на переменных палитры, поэтому каждая тема получает его сама. Прежние
   правила на html[data-ob-theme] заливали текущую страницу акцентом, а в
   панели реестра возвращали приглушённый чип — из-за этого один и тот же
   блок выглядел в двух местах по-разному. Разница была не в темах, а в
   правилах: их и убрали.
   -------------------------------------------------------------------------- */

/* QR-блок в подвале панели: hyper заливает его #E5F1F8 — это ровно
   --ob-primary-soft светлой палитры, так что роль переносится один в один. */
html[data-ob-theme="dark"] .left-side-menu .help-box,
html[data-ob-theme="warm"] .left-side-menu .help-box,
html[data-ob-theme="contrast"] .left-side-menu .help-box,
html[data-ob-theme="mono"] .left-side-menu .help-box {
  background-color: var(--ob-primary-soft);
  color: var(--ob-text-muted);
}

html[data-ob-theme="dark"] .left-side-menu .help-box a,
html[data-ob-theme="warm"] .left-side-menu .help-box a,
html[data-ob-theme="contrast"] .left-side-menu .help-box a,
html[data-ob-theme="mono"] .left-side-menu .help-box a { color: var(--ob-link); }
