/* ===== ТОКЕНЫ ПОРТАЛА =====
   Цвета рассчитываются из оформления (UI.Components/Theme: умолчания — PortalThemeDefaults, роли палитры MudBlazor —
   PortalThemeCalculator; своё оформление задаёт суперадмин в админке). Токены ниже — только имена портала для
   переменных палитры, поэтому светлую и тёмную тему переключает провайдер, а цветов числами здесь нет. */
:root {
  /* Высота знака: в шапке, в шапке с меню по кнопке (ниже 960px она ниже) и в подвале. */
  --logo-height: 56px;
  --logo-height-compact: 48px;
  --logo-height-footer: 44px;
  /* Фирменное поле — тёмный градиент под героями разделов в тёмной теме (.catalog-hero), фоном входа и экрана загрузки.
     Форма его градиентов (--brand-field-*, --brand-login-*) — общая с админкой, в UI.Components/brand-field.css. Цвета
     остановок (--brand-base*, --brand-glow-*) и фирменные цвета (--brand-dark — тёмная заливка, --brand-accent — акцент,
     --brand-accent-text — надпись на нём, --brand-light и --brand-field-text* — текст на поле) выводит inline-стиль
     App.razor (PortalBrandFieldCss): от палитры текущей темы поле не зависит. Поле, выключенное в оформлении
     (data-brand-field="off" на <html>), выводится там же ролями тёмной палитры — фон, серый фон и поверхность вместо
     свечений, — так что вход и экран загрузки остаются тёмными в любой теме; героя без поля рисует правило
     .catalog-hero ниже. */

  --bg: var(--mud-palette-background);
  --bg-card: var(--mud-palette-surface);
  --bg-panel: var(--mud-palette-background-gray);
  --bg-input: var(--mud-palette-surface);
  --bg-dropdown: var(--mud-palette-surface);
  --bg-hover: color-mix(in srgb, var(--mud-palette-text-primary) 5%, var(--mud-palette-surface));
  --bg-active: var(--accent-light);
  --card-bg: var(--mud-palette-surface);
  --tab-bg: var(--mud-palette-background-gray);
  --footer-bg: var(--mud-palette-appbar-background);
  --overlay-bg: var(--mud-palette-overlay-dark);

  --text-primary: var(--mud-palette-text-primary);
  --text-secondary: var(--mud-palette-text-secondary);
  --text-muted: var(--mud-palette-gray-dark);
  --text-on-accent: var(--mud-palette-primary-text);

  --accent: var(--mud-palette-primary);
  --accent-hover: var(--mud-palette-primary-darken);
  --accent-light: rgba(var(--tint-rgb), 0.12);
  --accent-subtle: rgba(var(--tint-rgb), 0.06);

  /* Второй акцент — подсветки, счётчики и ссылки в тексте. По умолчанию это основной цвет;
     портал с двумя фирменными цветами направляет эти четыре токена на другой цвет палитры. */
  --tint-rgb: var(--mud-palette-tertiary-rgb);
  --highlight: var(--mud-palette-tertiary-lighten);
  --text-on-highlight: var(--mud-palette-black);
  --link: var(--mud-palette-tertiary);

  --success: var(--mud-palette-success);
  --success-bg: rgba(var(--mud-palette-success-rgb), 0.12);
  --warning: var(--mud-palette-warning);
  --warning-bg: rgba(var(--mud-palette-warning-rgb), 0.12);
  --danger: var(--mud-palette-error);
  --danger-bg: rgba(var(--mud-palette-error-rgb), 0.12);
  --info: var(--mud-palette-info);

  --border: var(--mud-palette-lines-default);
  --border-light: var(--mud-palette-divider);
  --border-input: var(--mud-palette-lines-inputs);
  --border-input-hover: var(--mud-palette-text-secondary);
  --border-color: var(--mud-palette-lines-default);

  --tag-green-bg: var(--success-bg);
  --tag-green-text: var(--mud-palette-success);
  --tag-blue-bg: rgba(var(--mud-palette-info-rgb), 0.12);
  --tag-blue-text: var(--mud-palette-info);
  --tag-orange-bg: var(--warning-bg);
  --tag-orange-text: var(--mud-palette-warning);
  --tag-red-bg: var(--danger-bg);
  --tag-red-text: var(--mud-palette-error);
  /* Декоративный тег без смысла статуса — второй фирменный цвет палитры (у «Альфа-Групп» это бронза).
     Имя историческое: раньше тег был фиолетовым, но такого цвета в палитре заказчика нет. */
  /* Подложка слабая, 8 %: при 14 % мелкий текст тега на ней не дотягивал до контраста 4,5:1 в обеих темах. */
  --tag-purple-bg: color-mix(in srgb, var(--mud-palette-secondary) 8%, transparent);
  --tag-purple-text: var(--mud-palette-secondary);

  --scrollbar-thumb: var(--mud-palette-gray-light);

  --font-display: 'Merriweather', Georgia, serif;
  --font-body: 'Commissioner', system-ui, sans-serif;
  /* Боковое поле оболочки: одно для шапки, содержимого и подвала. */
  --page-gutter: 24px;

  --portal-action-height: 46px;
  /* Заголовок внутренней страницы раздела (карточка, форма, список) — один размер на портал: на ступень ниже
     заголовка каталога в герое (36 px), на телефоне — как он (24 px). Модуль берёт переменную, своего размера не пишет. */
  --portal-page-title-size: 30px;
  --portal-person-avatar-size: 48px;
  --portal-person-avatar-bg: color-mix(in srgb, var(--highlight) 14%, var(--bg-card));
  --portal-person-avatar-color: color-mix(in srgb, var(--accent) 80%, var(--text-primary));
  --portal-person-avatar-border: color-mix(in srgb, var(--highlight) 20%, var(--border));
}

/* Тёмная тема — по умолчанию, светлая — по выбору человека. */
:root, [data-theme="dark"] {
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.2);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.25);
  --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.35);
  --shadow-modal: 0 20px 60px rgba(0, 0, 0, 0.5);
}

/* Светлые тени — в тоне «чёрного» палитры, а не чистым чёрным. */
[data-theme="light"] {
  --shadow-sm: 0 1px 3px color-mix(in srgb, var(--mud-palette-black) 5%, transparent);
  --shadow-md: 0 4px 16px color-mix(in srgb, var(--mud-palette-black) 7%, transparent);
  --shadow-lg: 0 8px 32px color-mix(in srgb, var(--mud-palette-black) 10%, transparent);
  --shadow-modal: 0 20px 60px color-mix(in srgb, var(--mud-palette-black) 15%, transparent);
}

/* Reset MudButton defaults before the existing portal classes set each action's design. */
.portal-action {
  display: inline-block;
  min-width: 0;
  padding: 0;
  font: inherit;
  line-height: normal;
  letter-spacing: normal;
  text-transform: none;
  justify-content: normal;
}
.portal-action:hover, .portal-action:active, .portal-action:focus-visible { background-color: transparent; }
.portal-action:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.portal-action > .mud-button-label { display: contents; }

/* Primary page actions use the same box and icon geometry across modules. */
.portal-primary-action.mud-button-root.mud-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  height: var(--portal-action-height);
  min-height: var(--portal-action-height);
  padding: 0 18px;
  border: 1px solid var(--accent);
  border-radius: var(--portal-radius-md);
  background: var(--accent);
  color: var(--text-on-accent);
  box-shadow: none;
  font-size: 14px;
  font-weight: 600;
  line-height: normal;
  letter-spacing: normal;
  text-transform: none;
}
.portal-primary-action.mud-button-root.mud-button:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}
.portal-primary-action.mud-button-root.mud-button > .mud-button-label {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.portal-primary-action.mud-button-root.mud-button .mud-button-icon-start { margin: 0; }
.portal-primary-action.mud-button-root.mud-button .mud-icon-root { font-size: 18px; }

/* Ряд действий страницы (героя или под вкладками) — одно правило портала: второстепенные — текстовые кнопки со
   значком в строку, главная (.portal-primary-action, последняя в разметке) на телефоне — своей строкой во всю ширину.
   Модуль ставит класс на обёртку ряда и не пишет своих правил ширины и положения кнопок. */
.portal-page-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* Кнопки разделов портала (модулей) — одной высоты с главной кнопкой. Модуль ставит portal-section на контейнер своей
   оболочки и своей копии правила не пишет; скругление и регистр кнопок задаёт тема MudBlazor (PortalTheme), шрифт — её
   умолчание. :where — чтобы правила модуля для своих мест (плотные ряды, компоновщик) перебивали это сами. */
:where(.portal-section) .mud-button { min-height: var(--portal-action-height); }
@media (max-width: 599.98px) {
  /* Сам ряд на телефоне — во всю строку: в герое он стоит рядом с заголовком в ряду с переносом, и без этого
     «во всю ширину» главной кнопки значило бы ширину узкого ряда. */
  .portal-page-actions { width: 100%; }
  /* Главная кнопка — во всю ширину и первой: второстепенные (текстовые) идут под ней, а не над. */
  .portal-page-actions > .portal-primary-action.mud-button-root.mud-button { flex: 1 1 100%; order: -1; }
  :root { --portal-page-title-size: 24px; }
}

/* ====== АДАПТИВНОСТЬ ======
   Переломы — только у MudBlazor: 600 (sm), 960 (md), 1280 (lg). Поведение по ширине задают адаптивные классы
   (d-sm-*, pa-md-*, min-width); своё @media — только там, где класса нет (размер шрифта, ширина колонки), и на тех же
   переломах: max-width 599.98px / 959.98px / 1279.98px, чтобы ровно на границе не срабатывали оба правила.
   Новых правил на 768, 480 и 1200 не пишут (хук check-frontend.sh не пропускает @media на 768px). Старые остались
   в модулях и в стилях оболочки (home, org-structure, login, employee-search, news) и переводятся по одному вместе
   с пересъёмкой эталонов; подвал (portal.css: 1199.98 и 767.98) не трогают по решению владельца.
   Исключение — узкие экраны: 380px у одного блока календаря и у кнопки «Поздравить» именинников, 359.98px у картинки
   «не найдено» и у подвала.
======================================================================= */


/* Плавный переход при смене темы */
body,
.card,
.dropdown,
input, select, textarea,
button {
  transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}

/* Смена темы волной (js/theme.js): новая тема проявляется поверх снимка старой по маске, которую скрипт
   перерисовывает каждый кадр; частицы — отдельный слой над обоими снимками. */
.theme-wave {
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
  view-transition-name: theme-wave;
}

/* Плавное перекрашивание выше иначе шло бы внутри снимка новой темы. */
html[data-theme-animating] *,
html[data-theme-animating] *::before,
html[data-theme-animating] *::after {
  transition: none !important;
}

html[data-theme-animating]::view-transition { pointer-events: none; }

/* Переход живёт, пока идёт эта анимация; волну рисует и заканчивает скрипт. */
html[data-theme-animating]::view-transition-group(root) {
  animation: theme-wave-hold 2s linear both;
  z-index: 1;
}

html[data-theme-animating]::view-transition-old(root),
html[data-theme-animating]::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}

html[data-theme-animating]::view-transition-old(root) { z-index: 1; }

html[data-theme-animating]::view-transition-new(root) {
  z-index: 2;
  mask-image: var(--theme-wave-mask);
  mask-size: 100% 100%;
  mask-repeat: no-repeat;
}

html[data-theme-animating]::view-transition-group(theme-wave) {
  animation: none;
  z-index: 2;
}

html[data-theme-animating]::view-transition-old(theme-wave) {
  animation: none;
  opacity: 0;
}

html[data-theme-animating]::view-transition-new(theme-wave) {
  animation: none;
  mix-blend-mode: normal;
}

@keyframes theme-wave-hold {
  from { opacity: 1; }
  to { opacity: 1; }
}

/* ──────────── Text utilities ──────────── */
.text-muted { color: var(--text-muted) !important; }

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text-primary);
  min-height: 100vh;
  /* Clip horizontal overflow without creating a scroll container for sticky children. */
  overflow-x: clip;
  line-height: 1.6;
}
html {
  overflow-x: clip;
  scroll-behavior: smooth;
}

body::before, body::after { display: none; }

@media (max-width: 599.98px) {
  :root { --page-gutter: 16px; }
}

/* ===== USER AVATAR DROPDOWN ===== */
.user-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-hover, var(--accent)));
  color: var(--text-on-accent);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.5px;
  user-select: none;
  transition: box-shadow 0.2s;
}
.user-avatar-lg {
  width: 40px;
  height: 40px;
  font-size: 16px;
}
@keyframes dropdownFadeIn {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}
.user-dropdown-header {
  text-decoration: none;
  transition: background 0.15s;
}
.user-dropdown-header:hover {
  background: var(--bg-hover);
}
.user-dropdown-header-text {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}
.user-dropdown-name {
  color: var(--text-primary);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.user-dropdown-email {
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.user-dropdown-chevron {
  flex-shrink: 0;
  color: var(--text-muted);
}

/* ═══ Notification Bell ═══ */
/* notif-bell-wrap uses inline style for position:relative */
.notif-bell, .notif-bell.mud-button-root {
  width: 40px; height: 40px;
  border-radius: 50%; border: none;
  background: var(--mud-palette-action-default-hover);
  color: var(--text-secondary);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.2s, color 0.2s;
  position: relative;
}
.notif-bell:hover, .notif-bell.mud-button-root:hover { background: rgba(var(--mud-palette-text-primary-rgb), 0.12); color: var(--text-primary); }
.notif-badge {
  position: absolute; top: 2px; right: 2px;
  min-width: 18px; height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--danger);
  color: var(--mud-palette-error-text);
  font-size: 11px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  line-height: 1;
  pointer-events: none;
}
.notif-overlay {
  position: fixed; inset: 0; z-index: 199;
}
.notif-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 380px;
  max-height: 480px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--portal-radius-lg);
  box-shadow: 0 8px 32px rgba(0,0,0,0.12);
  z-index: 200;
  display: flex; flex-direction: column;
  animation: dropdownFadeIn 0.18s ease-out;
}
.notif-panel-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.notif-panel-title {
  font-size: 15px; font-weight: 600; color: var(--text-primary);
}
.notif-mark-all.mud-button-root {
  background: none; border: none;
  color: var(--accent); font-size: 13px; font-weight: 500;
  cursor: pointer; padding: 0;
  transition: opacity 0.2s;
}
.notif-mark-all.mud-button-root:hover { opacity: 0.8; }
.notif-panel-body {
  overflow-y: auto; flex: 1;
  max-height: 420px;
}
.notif-empty {
  padding: 40px 16px;
  text-align: center;
  color: var(--text-muted);
  font-size: 14px;
}
.notif-item {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 16px;
  cursor: pointer;
  transition: background 0.15s;
  border-bottom: 1px solid var(--border);
}
.notif-item:last-child { border-bottom: none; }
.notif-item:hover { background: var(--bg-hover); }
.notif-item--unread { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.notif-item--unread:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.notif-item-icon {
  width: 32px; height: 32px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-muted);
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.notif-item-icon svg { width: 100%; height: 100%; }
.notif-item-content {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 2px;
}
.notif-item-type {
  font-size: 13px; font-weight: 600; color: var(--text-primary);
}
.notif-item-message {
  font-size: 13px; color: var(--text-secondary);
}
.notif-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--highlight);
  flex-shrink: 0;
  margin-top: 6px;
}
.notif-loading {
  display: flex; justify-content: center; padding: 12px;
}
.notif-sentinel { height: 1px; }
/* На телефоне панель — во всю ширину под шапкой. !important у position — против .mud-paper{position:relative !important}
   MudBlazor (панель — это MudPaper). */
@media (max-width: 599.98px) {
  .notif-panel {
    position: fixed !important;
    top: var(--header-h);
    left: 12px;
    right: 12px;
    width: auto;
    max-height: calc(100vh - var(--header-h) - 24px);
  }
}

.auth-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 20px 0 16px;
  color: var(--text-secondary);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 1px;
}
.auth-divider::before,
.auth-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border-light);
}

/* Scrollbar */
/* Вертикальная полоса узкая, горизонтальная (таблицы, редактор на телефоне) — 8 px, как и была. */
::-webkit-scrollbar { width: 5px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

/* Blazor-specific */
#blazor-error-ui {
    background: var(--brand-dark);
    color: var(--brand-light);
    padding: 12px 24px;
    position: fixed;
    bottom: 0;
    width: 100%;
    z-index: 1000;
    display: none;
}

#blazor-error-ui .reload, #blazor-error-ui .dismiss {
    color: var(--brand-accent);
    margin-left: 12px;
}

/* Крошки портала — в стилях общего компонента, portal-breadcrumbs.css. */

/* Текст статьи (.article-content) — только в общем файле ui.shared/wwwroot/css/article-content.css. */

/* ===== SCROLL TO TOP ===== */
.scroll-to-top {
    position: fixed;
    bottom: 32px;
    right: 32px;
    z-index: 999;
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-hover);
    border: 1px solid var(--border);
    /* Не больше трети стороны: в «Мягких» кнопка иначе стала бы кругом. */
    border-radius: min(var(--portal-radius-lg), 14px);
    color: var(--accent);
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    transform: translateY(12px);
    transition: opacity 0.25s ease, transform 0.25s ease, background 0.15s, box-shadow 0.15s;
    box-shadow: 0 4px 16px rgba(0,0,0,0.15);
}
[data-theme="light"] .scroll-to-top {
    background: var(--bg-card);
    border-color: var(--border);
    color: var(--accent);
    box-shadow: 0 4px 16px rgba(0,0,0,0.08);
}
[data-theme="light"] .scroll-to-top:hover {
    background: var(--accent-subtle);
    color: var(--accent);
    box-shadow: 0 6px 20px rgba(0,0,0,0.12);
}

.scroll-to-top.visible {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
}

.scroll-to-top:hover {
    background: var(--accent);
    color: var(--text-on-accent);
    box-shadow: 0 6px 20px rgba(0,0,0,0.5);
    transform: translateY(-2px);
}

@media (max-width: 599.98px) {
    .scroll-to-top {
        bottom: 20px;
        right: 16px;
        width: 40px;
        height: 40px;
        border-radius: min(var(--portal-radius-md), 13px);
    }
}

/* На странице с панелью сохранения (SaveChangesBar) кнопки нет: обе стоят в правом нижнем углу окна, кнопка
   закрывала главную кнопку панели, и нажатие прокручивало страницу вместо сохранения. Поднять кнопку над панелью
   мало: в конце страницы панель уходит со своего места у края окна и снова попадает под кнопку. */
body:has(.portal-save-bar) .scroll-to-top { display: none; }

/* ===== Каркас каталога: герой раздела и контейнер под ним ===== */
/* Герой один на весь портал: главная, новости, сообщества, опросы, афиша, сотрудники, оргструктура, благодарности.
   Отступ сверху равен отступу каркаса карточки (.container.*-wrap): крошки каталога и карточки стоят на одной высоте.
   В тёмной теме герой стоит на фирменном поле, в светлой (и в тёмной, когда поле выключено в оформлении) — на спокойном
   фоне страницы с лёгким свечением акцента. */
.catalog-hero {
    padding: 28px 0 32px;
    position: relative;
    overflow: hidden;
}
/* Светлая тема и тёмная без фирменного поля: фон и свечение из палитры темы, содержимое красится обычными токенами. */
:is([data-theme="light"], [data-brand-field="off"]) .catalog-hero {
    background: linear-gradient(135deg, var(--mud-palette-background-gray) 0%, var(--mud-palette-background) 100%);
}
:is([data-theme="light"], [data-brand-field="off"]) .catalog-hero::before {
    content: '';
    position: absolute; top: -40%; right: -15%;
    width: 600px; height: 600px;
    background: radial-gradient(circle, rgba(var(--tint-rgb), 0.10) 0%, transparent 70%);
    pointer-events: none;
}
/* Тёмная тема (она по умолчанию): фирменное поле. Токены, которыми красится содержимое героя — крошки, заголовок,
   подписи, кнопки, карточка внутри, — герой задаёт сам, фирменными цветами. Акцент остаётся акцентом страницы: в тёмной
   теме это и есть --brand-accent. Надпись на нём — --brand-accent-text: тёмная заливка поля, если она читается на
   акценте, иначе рассчитанный по контрасту текст на основном цвете (PortalBrandFieldCss). */
:root:not([data-theme="light"]):not([data-brand-field="off"]) .catalog-hero {
    background: var(--brand-field-shade), var(--brand-field-glow);
    color: var(--brand-field-text);
    --text-primary: var(--brand-field-text);
    --text-secondary: var(--brand-field-text-secondary);
    --text-muted: var(--brand-field-text-muted);
    --accent-hover: color-mix(in srgb, var(--brand-accent) 80%, var(--brand-dark));
    --text-on-accent: var(--brand-accent-text);
    --bg-card: var(--brand-dark);
    --border-light: color-mix(in srgb, var(--brand-accent) 12%, var(--brand-dark));
    /* Этим MudBlazor красит своё: кнопку без заливки — цветом текста палитры, под курсором и в фокусе — подсветкой. */
    --mud-palette-text-primary: var(--brand-field-text);
    --mud-palette-action-default-hover: color-mix(in srgb, var(--brand-field-text) 8%, transparent);
    --mud-palette-skeleton: color-mix(in srgb, var(--brand-accent) 10%, transparent);
}
/* Фокус с клавиатуры в герое: MudBlazor гасит обводку ссылок, а правила модулей до героя не достают —
   он лежит над их контейнерами. */
.catalog-hero :is(a, button):focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.catalog-hero-title {
    font-family: var(--font-display);
    color: var(--text-primary);
    font-size: clamp(24px, 3vw, 36px);
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.02em;
    margin-bottom: 8px;
    position: relative;
}
.catalog-hero-sub {
    color: var(--text-secondary);
    font-size: 15px;
    position: relative;
}
/* Текстовая шапка справочника или страницы управления на том же поле (PortalDictionaryHeading в герое, шапки новостей):
   надзаголовок красится токеном поля, как подзаголовок, — его собственный цвет вычислен вне героя. */
.catalog-hero .portal-dictionary-eyebrow { color: var(--text-secondary); }
.catalog-wrap {
    padding-top: 24px;
    padding-bottom: 60px;
}
/* Страница без героя (карточка объекта, форма, управление): отступ от шапки портала до крошек и до подвала. Один на
   портал — крошки стоят на той же высоте, что в героях разделов; на телефоне уменьшается вместе с героем (ниже). */
.container.page-wrap {
    padding-top: 28px;
    padding-bottom: 64px;
}

.catalog-empty {
    text-align: center;
    padding: 64px 24px;
    color: var(--text-muted);
    font-size: 15px;
}

/* skeleton cards */
.skel {
    background: var(--border-light);
    border-radius: var(--portal-radius-sm);
    position: relative;
    overflow: hidden;
}
.skel::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent 0%, var(--bg-hover, rgba(255,255,255,0.06)) 50%, transparent 100%);
    animation: skel-shimmer 1.4s ease-in-out infinite;
}
@keyframes skel-shimmer {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(100%); }
}
.skel-card { pointer-events: none; }
.skel-line {
    width: 100%;
    height: 14px;
    margin-top: 8px;
}
.skel-line--short {
    width: 60%;
}
.skel-author {
    width: 100px;
    height: 14px;
}

@media (max-width: 599.98px) {
    .catalog-hero { padding: 20px 0 32px; }
    .container.page-wrap { padding-top: 20px; padding-bottom: 40px; }
    :root:not([data-theme="light"]):not([data-brand-field="off"]) .catalog-hero {
        background: var(--brand-field-shade), var(--brand-field-glow-phone);
    }
    .catalog-hero-title { font-size: 24px; }
    /* Вторые кнопки героя («Категории», «Товары») — высотой с остальные кнопки портала, а не 36,5 px MudBlazor. */
    .catalog-hero .mud-button-root:not(.mud-icon-button) { min-height: var(--portal-action-height); }
}
