body {
  background-color: var(--bs-secondary);
}

/* Bootstrap-контейнер по умолчанию упирается в 1320px на xxl (>=1400px) — расширяем именно
   этот верхний порог до 1600px, остальные брейкпоинты (960/1140px и т.п.) не трогаем. */
@media (min-width: 1400px) {
  .container {
    max-width: 1600px;
  }
}

.header {
  z-index: 3;
  position: sticky;
  top: 0;
  left: 0;
}

/* Бренд-акцент сайта — та же бронза, что уже откалибрована для .specimen--coin (карточка
   разновидности монеты), вынесена на уровень всего сайта (шапка, hero, лента "недавно
   добавлено"), а не только карточки предмета. Одна пара переменных на обе темы, --bs-theme=dark
   переопределяет. */
:root {
  --brand-accent: #a5672b;
  --brand-accent-rgb: 165, 103, 43;
}

[data-bs-theme="dark"] {
  --brand-accent: #d99a54;
  --brand-accent-rgb: 217, 154, 84;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  text-decoration: none;
  color: var(--bs-emphasis-color);
}

/* Увеличено с 34px/1.1rem (issue Бориса 2026-08-19: "лого и текст рядом... побольше") — header
   имеет фиксированную высоту 100px (.main grid-template-rows), запас большой, новый размер
   в него свободно вписывается с исходным вертикальным центрированием. */
.brand__mark {
  width: 46px;
  height: 46px;
  flex: none;
  border-radius: 50%;
  background: var(--brand-accent);
  color: var(--bs-body-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Fraunces", Georgia, serif;
  font-weight: 600;
  font-size: 1.5rem;
}

.brand__word {
  font-family: "Fraunces", Georgia, serif;
  font-weight: 600;
  font-size: 1.85rem;
  letter-spacing: -0.01em;
}

.main {
  min-height: 100vh;
  display: grid;
  /* Первая строка auto, не фиксированный 100px (issue Бориса 2026-09-02, мобильная
     адаптивность) — на узких экранах .navbar-right (см. ниже) не помещается в один ряд рядом с
     логотипом и переносится на вторую строку; с жёсткой высотой 100px вторая строка просто
     обрезалась бы/наезжала на контент. auto — сама подстраивается под реальную высоту шапки на
     любом брейкпоинте, на десктопе визуально не меняет ничего (контент и так укладывался
     примерно в 100px). */
  grid-template-rows: auto 1fr 100px;
  /* minmax(0, 1fr), не голый 1fr (issue Бориса 2026-09-02, мобильная адаптивность) — без
     grid-template-columns у сетки была ровно одна неявная колонка auto-размера: её ширину CSS
     Grid считает по МИНИМАЛЬНОМУ содержимому самого широкого потомка (в т.ч. глубоко вложенного
     — на практике им оказывалась сетка "Недавно добавлено" из index.html), а не по ширине
     самого .main. На узких экранах это раздувало колонку (а с ней header/content/footer,
     растянутые под неё через justify-self:stretch) далеко за пределы viewport — сайт горизонтально
     скроллился уже на этом уровне, ЕЩЁ ДО того, как дело доходило до сайдбара. minmax(0, ...)
     обнуляет автоматический минимум трека — колонка честно занимает ширину .main, содержимому
     приходится переноситься/сжиматься внутри неё, как и должно быть. */
  grid-template-columns: minmax(0, 1fr);
}

.header>.container,
.content>.container {
  border-bottom: 1px solid var(--bs-border-color);
}

/* Лого и меню в одну строку на уровне высоты (issue Бориса 2026-08-14) — раньше .container не был
   flex-контейнером, .brand и nav.navbar стояли друг под другом блоками. Плюс группировка правых
   контролов (колокольчик/логин/язык/тема) в один кластер с равными отступами вместо вперемешку. */
.header>.container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  /* wrap (issue Бориса 2026-09-02) — на узких экранах .navbar-right (5 элементов: коллекция/
     колокольчик/юзер/язык/тема) физически не помещается в одну строку рядом с логотипом без
     переноса — раньше просто вылезал за границу экрана, растягивая всю шапку и вместе с ней
     всю страницу горизонтально. row-gap отдельно от общего gap — расстояние между строками
     после переноса не обязано совпадать с горизонтальным зазором лого/меню. */
  flex-wrap: wrap;
  row-gap: 0.5rem;
}

.navbar {
  flex: 1;
}

.navbar-right {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
  row-gap: 0.5rem;
  gap: 0.75rem;
  /* margin-left:auto, не только justify-content:space-between на родителе .navbar (issue
     Бориса 2026-08-18: "теперь всё вплотную к логотипу") — .navbar раньше держал два flex-
     ребёнка (<ul class="navbar-nav"> слева + .navbar-right справа), space-between разводил их
     по краям; после того как <ul> убрали (см. предыдущий коммит), .navbar-right остался
     единственным ребёнком — с одним элементом space-between прижимает его к началу, а не к
     концу. margin-left:auto работает независимо от того, сколько соседей осталось. */
  margin-left: auto;
}

.header,
.content,
.footer {
  display: flex;
  align-items: stretch;
}

/* Баннер cookie-consent (issue Бориса 2026-09-05, стиль — 2026-09-06: "некрасивый на весь
   экран") — раньше был полноширинной полосой встык с краями экрана, с плоскими углами и
   заливкой в цвет фона: ничем не отличалась от системного alert() и выбивалась из остального
   сайта, где даже нейтральные уведомления оформлены карточкой. Теперь — плавающая карточка,
   тот же язык, что у .specimen/.ledger-form (тонкая рамка, дефис-полоска акцентом сверху,
   прямые углы — сайт нарочно нигде не скругляет "важные" карточки, см. комментарии у
   .specimen__photo-frame про банкноты). max-width + margin-inline:auto с left/right:1rem —
   по центру на широких экранах, во всю ширину минус отступы на узких, без отдельного медиа-запроса.
   [hidden] управляется скриптом (cookie_consent.js), не отдельным классом — тот же приём,
   что рекомендован для артефактов, здесь просто общий хороший тон: показывать/прятать через
   el.hidden, а не переключением класса. */
.cookie-consent {
  position: fixed;
  left: 1rem;
  right: 1rem;
  bottom: 1rem;
  max-width: 560px;
  margin-inline: auto;
  z-index: 4;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  padding: 1rem 1.25rem 0.9rem;
  background-color: var(--bs-body-bg);
  border: 1px solid var(--bs-border-color);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.22);
}

.cookie-consent::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background-image: repeating-linear-gradient(
    90deg, var(--brand-accent) 0, var(--brand-accent) 2px, transparent 2px, transparent 5px
  );
  opacity: 0.55;
}

.cookie-consent__text {
  flex: 1 1 280px;
  font-size: 0.9rem;
}

.cookie-consent__actions {
  display: flex;
  flex: none;
  gap: 0.5rem;
}

/* Только на md и выше — ниже этой точки .left уходит в offcanvas-режим (position:fixed,
   выезжающая панель, issue Бориса 2026-09-02), у которого уже есть своя граница/тень от
   Bootstrap (--bs-offcanvas-border-width) — вторая рамка поверх была бы лишней. */
@media (min-width: 768px) {
  .left {
    border-right: 1px solid var(--bs-border-color);
  }
}

/* Раньше padding был на самом <aside> (единственное место в проекте, где он встречается) —
   после перехода на offcanvas-md реальный контент сайдбара на один уровень глубже, в
   .offcanvas-body (см. base.html), сам <aside> — просто позиционирующая обёртка. На md и
   выше Bootstrap сам обнуляет padding у .offcanvas-body (см. его же .offcanvas-md CSS) —
   восстанавливаем те же 10px, что были всегда; ниже md используем то же значение — не задел
   штатный отступ офканвас-панели. */
.left .offcanvas-body {
  padding: 10px;
  /* На md и выше Bootstrap сам включает .offcanvas-body { display:flex } (без flex-direction —
     задуман под горизонтальные меню-офканвасы), из-за чего btn-group/поиск/аккордеон вставали
     в РЯД, а не друг под другом, и растягивались на всю высоту (align-items:stretch по
     умолчанию) — тот самый "огромный синий блок" при первой проверке. column возвращает
     обычную вертикальную раскладку, тот же вид, что был до offcanvas. */
  flex-direction: column;
}

/* Чуть уже дефолтных 400px (--bs-offcanvas-width) — на маленьких телефонах (320-375px) панель
   на всю ширину экрана визуально сливается с обычной страницей, не читается как "выезжающая
   панель поверх контента". min() — не шире 320px, но не увеличивает подложку сверх 85% экрана
   на совсем узких устройствах. */
.left.offcanvas-md {
  --bs-offcanvas-width: min(320px, 85vw);
}

.sidebar-toggle-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
}

#sidemenu {
  max-height: 1000px;
  overflow: hidden;
}

#sidemenu .accordion-item ul {
  max-height: 500px;
  overflow-y: auto;
}

.flag-icon {
  width: 20px;
  height: 15px;
  vertical-align: middle;
  margin-right: 4px;
  /* contain, не cover — у большинства флагов пропорции близки к 3:2, но у нескольких
     исторических (СССР — 1200x600, официально 1:2) cover обрезает по бокам так сильно,
     что герб/эмблема, стоящая не по центру полотна, оказывается почти полностью
     срезана. contain всегда показывает флаг целиком (ценой небольших полей сверху/снизу
     у нестандартных пропорций), это надёжнее для набора флагов, включающего исторические
     государства с нетипичными соотношениями сторон. */
  object-fit: contain;
}

.flag-icon-lg {
  width: 160px;
  height: 120px;
  margin-right: 10px;
}

/* ЭКСПЕРИМЕНТ (issue Бориса 2026-09-07) с флагом-фоном за заголовком страны/группы — три раунда
   (почти прозрачный растянутый флаг → показывать целиком без обрезки → увеличить в 4 раза по
   площади → текст наверх, не вниз) закончились решением Бориса "так себе получается": вернулись
   к простой раскладке в ряд — флаг слева, название справа, без прозрачности и без наложения
   текста на флаг. Подробности прежних раундов — в истории git (эта же секция файла), здесь уже
   не нужны, раз сам приём "флаг как полупрозрачный фон" не прижился.

   Высота флага менялась по площади каждый раз (√n по каждой линейной размерности, не n):
   130px (раунд 1) → ×4 → 260px (раунд 3) → ÷16 → 65px (раунд 4) → ÷4 (раунд 5, тем же днём,
   "флаг ещё меньше раза в 4") → 32px. */
.catalog-hero {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1rem;
}

/* width:auto — как и раньше, сохраняет собственные пропорции флага без искажений (Латвия и её
   узкая белая полоса, см. историю раунда 2, тут та же логика, просто без object-fit — он был
   нужен только чтобы вписать флаг В ЗАДАННЫЙ БОКС фона, здесь бокса нет, есть просто <img> с
   фиксированной высотой). flex-shrink:0 — чтобы длинное название периода в h2 рядом не сжимало
   сам флаг, у него единственного в этом ряду размер должен оставаться постоянным. */
.catalog-hero__flag {
  height: 32px;
  width: auto;
  flex-shrink: 0;
}

/* min-width:0 — без него длинный заголовок (например, "Российская империя — Пётр I
   (1700 — 1725)") как flex-элемент по умолчанию не сжимается меньше своей однострочной ширины
   (min-width:auto у флекс-детей по умолчанию) и вылезает за пределы колонки вместо переноса
   строк. Раньше это правило висело на обёртке .catalog-hero__content вокруг h2 — та обёртка
   ушла (issue Бориса 2026-09-07, раунд 6: крошку "назад в группу" вынесли из .catalog-hero
   совсем, см. index.html), h2 сам стал прямым флекс-элементом, и min-width переехал сюда же. */
.catalog-hero h2 {
  min-width: 0;
}

/* Столбцы по странам-участницам на странице исторической группы (issue Бориса 2026-09-06,
   backlog-пункт 28 в PROJECT_CONTEXT.md) — auto-fit, а не фиксированное repeat(3, ...): число
   стран в группе не хардкодится, при 2 странах (Germany/German Democratic Republic) будет 2
   колонки, при будущей группе с 5-6 участниками лишние сами перенесутся на новую строку по
   ширине контейнера, а не потребуют правки вёрстки под конкретное число. minmax(220px, 1fr) —
   достаточно для самого длинного из текущих названий столбца ("Российская империя" + флаг),
   не растягивая колонку без надобности на широком экране. */
.catalog-group-columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.5rem 2rem;
}

.catalog-group-columns__country-heading {
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 0.5rem;
}

/* Страница /catalog/ (issue Бориса 2026-09-07, аудит hero, часть 3 — "точка входа в каталог у
   нас всегда главная, это не очень правильно... каталог должен начинаться со списка стран").
   Те же countries/continents/extinct_countries, что ест компактный сайдбар (sidemenu.html) —
   здесь развёрнутым списком в основном контенте, каждый континент своей секцией. */
.catalog-country-section {
  margin-bottom: 2rem;
}

.catalog-country-section__heading {
  font-family: "Fraunces", Georgia, serif;
  font-weight: 600;
  margin-bottom: 1rem;
}

/* auto-fill, не auto-fit (в отличие от .catalog-group-columns выше) — секции с 1-2 странами
   (Антарктида, Океания) не должны растягивать единственную карточку на всю ширину контейнера,
   пустых колонок-плейсхолдеров auto-fill это не создаёт, просто оставляет пустое место справа. */
.catalog-country-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 0.6rem;
}

.catalog-country-card {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--bs-border-color);
  border-radius: 0.5rem;
  text-decoration: none;
  color: var(--bs-emphasis-color);
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.catalog-country-card:hover {
  border-color: var(--brand-accent);
  background-color: var(--bs-tertiary-bg);
  color: var(--bs-emphasis-color);
}

.catalog-country-card__flag {
  width: 32px;
  height: 24px;
  /* contain, не cover (тот же вывод, что у .catalog-hero__flag — см. комментарий там) — карточка
     фиксированного размера, а пропорции флагов разные (большинство ~3:2, но не все), cover обрезал
     бы часть флага непредсказуемо в зависимости от конкретных пропорций. */
  object-fit: contain;
  flex-shrink: 0;
}

.catalog-country-card__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.catalog-country-card__count {
  flex-shrink: 0;
}

.zoomable {
  cursor: zoom-in;
}

/* <picture> вокруг маленьких превью-иконок (WebP <source>, аудит производительности,
   продолжение 2026-09-07) — сам <picture> ничего не должен значить для вёрстки, он там только
   ради resource-selection между <source type="image/webp"> и <img>. display:contents убирает
   его собственный бокс из рендер-дерева целиком, так что <img> внутри становится прямым потомком
   исходного flex/grid/table-контейнера ДЛЯ ЛЮБЫХ целей вёрстки (flex-item сайзинг, CSS-селекторы
   по descendant-комбинатору — им и раньше было всё равно, прямой потомок или нет) — то есть все
   существующие классы/стили на самом <img> (.recent-item-img, .banknote-thumb и т.д.) продолжают
   работать без единой правки, как будто <picture> не существует. */
.thumb-picture {
  display: contents;
}

/* Аверс+реверс рядом в карточке "недавно добавлено" (issue Бориса 2026-08-14) — раньше показывали
   только одно фото, что не по стандарту сайта (везде обе стороны). --bs-tertiary-bg, не --bs-light
   — второй фиксирован (#f8f9fa) в обеих темах, первый сам темнеет вместе с --bs-theme=dark. */
.recent-item-photos {
  display: flex;
  gap: 1px;
  /* overflow/radius (issue Бориса 2026-08-15: "фотография съедает часть рамки блока" в режиме
     Плитка) — .recent-item-photos первый ребёнок .card, а сам .card ничего не обрезает по
     умолчанию (только скругляет border-radius визуально), поэтому квадратные углы фото
     торчали поверх скруглённого верхнего угла карточки. Радиус здесь — свой, а не
     unclipped-наследование от .card, чтобы правило работало в любом контейнере, не только
     внутри .card. */
  overflow: hidden;
  border-radius: var(--bs-card-border-radius) var(--bs-card-border-radius) 0 0;
}

.recent-item-img,
.recent-item-img-placeholder {
  width: 50%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background-color: var(--bs-tertiary-bg);
}

/* Банкноты вытянутые — квадратный object-fit:cover обрезал их с обеих сторон до нечитаемого
   обрубка (issue Бориса 2026-08-22: "кусок одной и кусок другой, ни то ни сё"). Свой модификатор
   вместо квадратного кропа: аспект пошире (типичное соотношение сторон банкноты) и
   object-fit:contain — вся банкнота целиком, с полями по бокам вместо обрезки, тот же приём,
   что уже верно сделан на странице Типа/Разновидности (.specimen__photos--banknote). */
.recent-item-img--banknote,
.recent-item-img-placeholder--banknote {
  aspect-ratio: 2 / 1;
  object-fit: contain;
}

/* Фиксированная высота текста в 3 строки (issue Бориса 2026-08-14) — без этого длинные названия
   коллекционных монет растягивали карточку, и высота ряда скакала между страницами пагинации.
   line-height задан явно и height = 3 * line-height, чтобы короткие (1-строчные) названия тоже
   резервировали полную высоту — иначе line-clamp только подрезал бы длинные сверху, а короткие
   карточки оставались бы ниже соседних. */
.recent-item-text {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.3em;
  height: 3.9em;
}

/* btn-outline-*, не btn-primary/btn-danger — заливные варианты держат один и тот же насыщенный
   цвет в обеих темах (Bootstrap не делает --bs-btn-bg тёмной темой), на тёмном фоне это смотрится
   грубо. Outline берёт цвет текста/рамки из --bs-primary/--bs-danger и остаётся прозрачным —
   в обеих темах читается ровно. */
a.btn-square.btn-sm,
button.btn-square.btn-sm {
  width: 32px;
  height: 32px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  font-size: 1.1rem;
}

/* text-bg-light (Bootstrap) не адаптируется под тему — тот же fixed #f8f9fa, что и --bs-light
   выше, белым пятном на тёмном фоне. Для "пустого" бейджа (нет предметов) нужен прозрачный
   вариант на var(--bs-border-color)/var(--bs-secondary-color) — они уже меняются с темой. */
.badge-outline {
  background-color: transparent;
  border: 1px solid var(--bs-border-color);
  color: var(--bs-secondary-color);
  font-weight: 500;
}

/* Панель "Уведомления" в шапке — dropdown-menu без Dropdown-плагина (см. menu.html, тот требует
   Popper, которого нет). Позиционируем сами: .collapse у Bootstrap сам по себе в потоке, а не
   плавающий — display:block переопределяет их inline-стиль display:none только пока свёрнуто.
   Селектор `.notif-panel-wrapper .notif-panel`, не просто `.notif-panel` — у Bootstrap есть
   `.navbar-nav .dropdown-menu { position: static }` (адаптация дропдаунов под мобильный navbar),
   специфичнее одного класса и без этого перебивала бы position: absolute обратно. */
.notif-panel-wrapper {
  position: relative;
}

.notif-bell {
  display: inline-flex;
  align-items: center;
  position: relative;
  padding: 4px;
}

.notif-bell-badge {
  position: absolute;
  top: -2px;
  right: -2px;
  font-size: 0.6rem;
  padding: 0.2em 0.4em;
}

.notif-panel-wrapper .notif-panel {
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 1050;
  margin-top: 4px;
}

/* Выпадашка по имени пользователя (menu.html) — те же правила позиционирования, что у панели
   уведомлений выше (тот же collapse-без-Popper приём), под отдельными именами — семантически
   разные панели. */
.user-menu-wrapper {
  position: relative;
}

.user-menu-toggle {
  display: inline-flex;
  align-items: center;
}

.user-menu-wrapper .user-menu-panel {
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 1050;
  margin-top: 4px;
}

/* Акцент по материалу — общий для карточки разновидности (.specimen) и формы добавления в
   коллекцию (.ledger-form, ниже): бронза/медь у монет, типографская зелень у банкнот,
   откалибровано отдельно под тёмную и светлую тему. Раньше сюда же входила и сетка карточек
   разновидностей (.variant-grid/.variant-card) на странице типа — убрана целиком (issue Бориса
   2026-08-14: "В разновидностях можно выбрать плитку... уберём. Оставим только список"),
   detail.html теперь всегда таблица (variant-list-table в этом же файле). variant-card-in
   оставлен — переиспользуется анимацией .specimen__spec ниже. */
.specimen--coin,
.ledger-form--coin {
  --variant-accent: #a5672b;
}

[data-bs-theme="dark"] .specimen--coin,
[data-bs-theme="dark"] .ledger-form--coin {
  --variant-accent: #d99a54;
}

.specimen--banknote,
.ledger-form--banknote {
  --variant-accent: #2f6f6b;
}

[data-bs-theme="dark"] .specimen--banknote,
[data-bs-theme="dark"] .ledger-form--banknote {
  --variant-accent: #6fc2bc;
}

@keyframes variant-card-in {
  from { opacity: 0; transform: translateY(5px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Страница одной разновидности (variant_detail.html) — "экземплярская карточка": тот же акцент
   по материалу, тот же Fraunces на годе, тот же JetBrains Mono на числах. Тут это разворачивается
   в полноценный лист-паспорт экземпляра:
   крупный год + номинал в шапке на мягком радиальном ореоле акцентного цвета, аверс/реверс как
   пара "холдеров" слева, паспортные данные — вертикальная ведомость лейбл/значение справа. */
.specimen {
  --variant-accent: var(--bs-emphasis-color);
  position: relative;
  border: 1px solid var(--bs-border-color);
  background: var(--bs-body-bg);
  margin: 1rem 0 1.5rem;
  overflow: hidden;
}

.specimen::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background-image: repeating-linear-gradient(
    90deg, var(--variant-accent) 0, var(--variant-accent) 2px, transparent 2px, transparent 5px
  );
  opacity: 0.55;
}

.specimen__header {
  position: relative;
  padding: 2rem 1.75rem 1.5rem;
  background-image: radial-gradient(ellipse 60% 100% at 0% 0%, color-mix(in srgb, var(--variant-accent) 16%, transparent), transparent 70%);
}

.specimen__eyebrow {
  display: block;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--variant-accent);
  margin-bottom: 0.5rem;
}

.specimen__title {
  margin: 0;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 0.75rem;
}

.specimen__year {
  font-family: "Fraunces", Georgia, serif;
  font-optical-sizing: auto;
  font-weight: 600;
  font-size: clamp(2.4rem, 5vw, 3.4rem);
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--bs-emphasis-color);
}

.specimen__denomination {
  font-family: "Fraunces", Georgia, serif;
  font-weight: 500;
  font-size: 1.15rem;
  color: var(--bs-secondary-color);
}

.specimen__subtitle {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.9rem;
  color: var(--bs-secondary-color);
}

.specimen__body {
  display: grid;
  /* 260-420px, было 220-320px (issue Бориса 2026-08-17: "делаем фото больше") */
  grid-template-columns: minmax(260px, 420px) 1fr;
  gap: 2rem;
  padding: 0 1.75rem 1.75rem;
}

@media (max-width: 700px) {
  .specimen__body {
    grid-template-columns: 1fr;
  }
}

.specimen__photos {
  display: flex;
  /* wrap (issue Бориса 2026-08-17: "делаем фото больше") — настоящая причина маленьких фото:
     .specimen__photo-credit ("Фото: ...") — прямой ребёнок этого же flex-ряда, наравне с двумя
     .specimen__photo, а не подпись под ними. Без wrap все три делили одну строку по ширине —
     атрибуция без ограничения по размеру отъедала ~150px, оставляя каждой монете ~35-40px
     вместо ожидаемых ~170px. flex-basis:100% у credit ниже заставляет её перейти на свою
     строку, фото остаются вдвоём на первой.

     max-width — issue Бориса 2026-08-17: "давай сделаем также в Типе" — .specimen__photos
     переиспользован на странице типа (detail.html) вне .specimen__body, у которого раньше
     этот предел задавала grid-колонка (minmax(260px,420px)). Без него на detail.html фото
     растянулись бы на всю ширину контентной колонки; на variant_detail.html ничего не меняет
     — там ширина и так ограничена grid-колонкой снизу этого значения. */
  flex-wrap: wrap;
  gap: 0.75rem;
  max-width: 420px;
  /* align-items:flex-start, не дефолтный stretch (issue Бориса 2026-09-03: "фото-яйцо" —
     .specimen__body ниже это CSS grid без своего align-items, то есть тоже дефолтный stretch;
     колонка характеристик у Разновидности намного выше, чем у Типа (~13 строк вроде диаметра/
     толщины/веса/формы/гурта против ~5 у Типа) — правая grid-ячейка стретчила левую (эту, с
     фото) под свою высоту, а .specimen__photos, сам flex-контейнер с тем же дефолтным stretch,
     тянул СВОЙ единственный child — .specimen__photo--empty — на всю эту высоту. aspect-ratio:1
     у плейсхолдера тут не спасает: explicit-высота от stretch отменяет то, что дал бы
     aspect-ratio. Реальные фото (.specimen__photo-frame) эту проблему не показывали — их
     aspect-ratio:1 всегда давал высоту ИЗ ширины раньше, чем что-то успевало её растянуть, но
     технически подвержены тому же риску. flex-start применяется к обоим случаям сразу, а не
     точечно к пустому плейсхолдеру — не только чинит, но и не может сломаться так же в будущем
     для настоящих фото. */
  align-items: flex-start;
}

.specimen__photo {
  flex: 1;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
}

.specimen__photo-credit {
  flex-basis: 100%;
}

/* .specimen__photo-frame — отдельный контейнер-маска (issue Бориса 2026-08-19: "в четвёртый
   раз... обрезка осталась", после того как накрутка padding на самом <img> (8% → 18%) не
   убедила визуально). border-radius на <img> (replaced-элемент) с одновременным aspect-ratio +
   object-fit — комбинация, где клип в разных браузерах/версиях может считаться не совсем так,
   как в обычном блочном контейнере; overflow:hidden на ПРОСТОМ div/span — самый предсказуемый,
   стандартный способ круглого кропа, без всяких нюансов рендеринга replaced-элементов. Рамка
   (border/background/border-radius) — на .specimen__photo-frame; сам <img> просто на 100%
   заполняет её (width/height 100%, object-fit:contain), padding по-прежнему даёт запас между
   почти безграничной монетой на фото (99.4-99.7% кадра, см. предыдущие коммиты) и краем маски. */
.specimen__photo-frame {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  overflow: hidden;
  background: var(--bs-tertiary-bg);
  border: 1px solid var(--bs-border-color);
  border-radius: 50%;
}

.specimen__photo-frame img {
  display: block;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  object-fit: contain;
  /* padding НЕ решение (issue Бориса 2026-08-19: "квадраты в круге" — с 18% стал виден
     квадратный белый фон исходного фото внутри круглой рамки, монету визуально "усохло").
     Вместо уменьшения монеты — мягкое растушёванное затухание к краю через mask-image:
     radial-gradient, closest-side — круг ровно по размеру рамки (та же окружность, что и
     border-radius:50% ниже). Непрозрачно до 92% радиуса (issue Бориса, тем же днём: "уменьшить
     расстояние между фото и рамкой" — было 78%/padding 2%, широкое серое кольцо между монетой
     и рамкой; растушёвка начинается позже, почти у самого края), дальше быстро уходит в
     прозрачность — на прозрачных пикселях просвечивает background рамки, а не обрывается
     резкая линия. Так компенсируются исходники, где монета обрезана почти впритык к кадру
     (99.4-99.7%, см. предыдущие коммиты) — без потери видимого размера монеты и почти
     без зазора до рамки. */
  padding: 0;
  mask-image: radial-gradient(circle closest-side, black 96%, transparent 100%);
  -webkit-mask-image: radial-gradient(circle closest-side, black 96%, transparent 100%);
  cursor: zoom-in;
}

/* Банкноты — не круглая "монета в капсуле", а прямоугольная рамка, аверс сверху/реверс снизу
   (issue Бориса 2026-08-17: "их не надо помещать в окружность... можно в рамку"). Банкнота не
   квадратная (обычно шире, чем выше) — рамка не форсирует aspect-ratio:1, высота идёт от
   собственных пропорций картинки (height:auto на img вместо 100%/object-fit, иначе высота
   рамки не из чего было бы посчитать — img внутри неё был бы единственным источником размера).
   Без обрезки в квадратный бокс. flex-direction:column вместо ряда бок о бок — тот же порядок
   DOM (аверс раньше реверса), просто друг под другом. */
.specimen__photos--banknote {
  flex-direction: column;
  align-items: center;
}

.specimen__photos--banknote .specimen__photo {
  flex: 0 0 auto;
  width: 100%;
}

.specimen__photos--banknote .specimen__photo-frame {
  aspect-ratio: auto;
  border-radius: 0;
}

.specimen__photos--banknote .specimen__photo-frame img {
  height: auto;
  padding: 0;
  mask-image: none;
  -webkit-mask-image: none;
}

.specimen__photos--banknote .specimen__photo--empty {
  aspect-ratio: 16 / 9;
  border-radius: 0;
}

/* .specimen__photo-credit растягивается через flex-basis:100% (см. правило ниже) — это работает
   только в родительском flex-ряду (главная ось = ширина). У банкнот родитель — flex-column
   (issue выше), там главная ось — высота, и flex-basis:100% пытался растянуть высоту вместо
   ширины: подпись про источник фото схлопывалась по ширине и наезжала на соседнюю колонку
   характеристик (issue Бориса 2026-08-17: "текст про источник съехал в характеристики"). width
   переопределяет именно то намерение ("на всю ширину"), уже независимо от направления оси. */
.specimen__photos--banknote .specimen__photo-credit {
  flex: 0 0 auto;
  width: 100%;
}

/* Фото водяного знака в detail.html (issue Бориса 2026-09-06, раздел "Водяной знак") — вне
   .specimen__photos, поэтому .specimen__photo-frame без max-width родителя растянулось бы на
   всю ширину контентной колонки; тут своя небольшая ширина. Рамка прямоугольная, не круглая
   (это кадр из банкноты, не монета) — то же переопределение, что у .specimen__photos--banknote
   выше, повторено точечно, раз сам блок вне того контейнера. */
.specimen__photo--watermark {
  max-width: 220px;
}

.specimen__photo--watermark .specimen__photo-frame {
  aspect-ratio: auto;
  border-radius: 0;
}

.specimen__photo--watermark .specimen__photo-frame img {
  height: auto;
  padding: 0;
  mask-image: none;
  -webkit-mask-image: none;
}

.specimen__photo figcaption {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--bs-secondary-color);
}

.specimen__photo--empty {
  aspect-ratio: 1;
  width: 100%;
  /* max-width (issue Бориса 2026-09-01: "огромный пустой круг") — width:100% растягивал
     плейсхолдер на всю ширину .specimen__photos (до 420px, см. правило выше), хотя в обычном
     состоянии там бок о бок сидят ДВА кружка (аверс+реверс) по ~200px каждый — один пустой
     кружок занимал место сразу двух. 200px — примерный размер одного из них ((420px - gap)/2). */
  max-width: 200px;
  display: flex;
  /* column (issue Бориса 2026-09-01: "Фото пока нет" и "Поделиться фото" вставали бок о бок) —
     display:flex на родителе оборачивает "Фото пока нет"+<br> в один анонимный flex-item, а
     соседнюю ссылку <a> — в другой; в дефолтном flex-direction:row они встают в ряд, и <br>
     внутри первого анонимного бокса ни на что не влияет (переносы строк не работают между
     отдельными flex-item). column укладывает оба flex-item друг под другом без изменений
     в шаблоне. */
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--bs-border-color);
  border-radius: 50%;
  color: var(--bs-secondary-color);
  font-size: 0.75rem;
  text-align: center;
  padding: 1rem;
}

.specimen__specs {
  margin: 0;
  display: flex;
  flex-direction: column;
}

/* Сайдбар "Другие монеты/банкноты периода" на странице Типа (issue Бориса 2026-08-24) — простой
   список ссылок, без своей рамки/фона (страница и так насыщена блоками). Без max-height/overflow
   (issue Бориса, тем же днём, второй заход — превью по наведению): .list-item-preview__photos
   всплывает absolute-позиционированием НАД строкой, а scroll-контейнер обрезал бы его для
   строк ближе к нижнему краю — список просто растёт по высоте свободно, страница и так длинная.

   Список ограничен окном вокруг текущего предмета в самой view (SIBLING_PREVIEW_SIZE, сейчас 24
   — issue Бориса 2026-09-03, аудит другого чата: "сайдбар в 3-4 раза длиннее блока характеристик,
   ничто не подчёркивает, что это второстепенный контент, читается как равноценный"; изначально
   стояло 8, но тем же днём чуть позже Борис — "раньше было удобно переключаться, сейчас нет, за
   пределами 8 штук приходится переходить в период" (8→30), затем "делаем список из 24 вместо 30
   и на этом заканчиваем правки" — финальное число; пробовали компенсировать за счёт max-height/
   overflow-y на самом списке вместо более жёсткого окна — откатили сразу же: обрезает то самое
   превью по наведению чуть выше по этому же комментарию, а не только "лишние" нижние строки, как
   казалось на бумаге — right:100% на превью выносит его ЗА левый край списка целиком, при
   overflow-y:auto браузер зажимает overflow-x тоже, так что просто некуда было расти вбок).
   Окно всё ещё решает разницу в длине колонок при 24 (не идеально при 70+ в периоде, как у Peter
   I, но заметно лучше 8), но заголовок ("Другие монеты периода") оставался тем же <h3>, что и
   "Характеристики" слева, то есть той же важности на вид. detail-siblings-heading — тише
   (мельче, приглушённый цвет, капс), тот же приём "eyebrow", что у .catalog-stats__label, а не
   .hero__eyebrow — тому нарочно нужен бренд-акцент (бронза только СИЛЬНЕЕ притянула бы взгляд,
   здесь наоборот). Рамку/фон по-прежнему не добавляем — решение 2026-08-24 не пересматривали. */
.detail-siblings-heading {
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--bs-secondary-color);
  margin-bottom: 0.75rem;
}

.detail-siblings-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.detail-siblings-more {
  display: inline-block;
  margin-top: 0.6rem;
  font-size: 0.85rem;
}

/* Текущий предмет внутри собственного списка соседей (issue Бориса 2026-09-06: "должна быть в
   списке, но как текст, который нельзя выбрать" — раньше текущий предмет тихо выпадал из своего
   же списка, не давая понять, где он вообще стоит среди остальных монет/банкнот периода). Не
   переиспользуем bg-success как у "владею" (.catalog-item-card--owned/--row--owned выше по
   файлу) — тот цвет уже занят другим значением ("есть в коллекции"), здесь просто "вы сейчас
   здесь", нейтральный акцент. Отрицательные margin гасят padding — текст остаётся на той же
   левой границе, что у кликабельных соседей-<a> без padding, иначе строка визуально "прыгала"
   бы вправо среди остальных пунктов списка. */
.detail-siblings-current {
  display: inline-block;
  font-weight: 600;
  background-color: var(--bs-secondary-bg-subtle);
  border-radius: 0.25rem;
  padding: 0.1rem 0.4rem;
  margin: -0.1rem -0.4rem;
  cursor: default;
}

/* Разделитель по году внутри .detail-siblings-list (issue Бориса 2026-09-06, только Памятные/
   Коллекционные — см. sibling_group_by_year в detail.html) — сама черта достаточно тише
   .detail-siblings-heading (тот "eyebrow" уровня всего блока, этот — уровня группы внутри
   списка), но тот же приём "дефис-разделитель", что уже применяется в .catalog-filter-toolbar/
   .specimen__extra: dashed border-top, а не собственный фон. :first-child — у самой первой
   группы в списке черта не нужна, сверху и так .detail-siblings-heading. */
.detail-siblings-year {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--bs-secondary-color);
  border-top: 1px dashed var(--bs-border-color);
  padding-top: 0.5rem;
}

.detail-siblings-year:first-child {
  border-top: none;
  padding-top: 0;
}

.specimen__spec {
  display: flex;
  align-items: baseline;
  /* flex-start, не space-between (issue Бориса 2026-08-17: "справа от фото таблица — слишком
     большое расстояние от названия строки и значения") — space-between растягивало dt/dd на
     всю ширину строки, у короткой пары вроде "Металл" / "Серебро" это выглядело как два
     несвязанных слова по разные стороны экрана. border-bottom у самой строки по-прежнему на
     всю ширину (это блочный div, justify-content влияет только на позиционирование dt/dd
     внутри него), разделитель между строками не пострадал. */
  justify-content: flex-start;
  gap: 1rem;
  padding: 0.5rem 0;
  border-bottom: 1px dashed var(--bs-border-color);
  animation: variant-card-in 0.3s ease backwards;
  animation-delay: calc(var(--i, 0) * 25ms);
}

@media (prefers-reduced-motion: reduce) {
  .specimen__spec {
    animation: none;
  }
}

.specimen__spec dt {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--bs-secondary-color);
  /* Фиксированная ширина, не nowrap+auto (issue Бориса 2026-08-19: "значения должны быть
     выровнены, как в столбце таблицы") — каждая .specimen__spec строка сама по себе отдельный
     flex-контейнер (см. выше), поэтому dt/dd меряются по своему собственному содержимому НЕЗАВИСИМО
     от соседних строк: "Металл" и "Диаметр" разной длины — их dd оказывались на разной
     горизонтали. Общая ширина колонки label ЗАДАНА, а не измерена по контенту — тогда dd у всех
     строк начинается в одной точке, не растягиваясь на всю ширину (см. flex-start выше). Без
     nowrap — не обрезаем длинные подписи (например, "Соотношение сторон", "Выведена из
     обращения"), при нехватке места переносятся на вторую строку, а не вылезают за колонку.
     170px — с запасом под них на этом font-size/letter-spacing. */
  flex: 0 0 170px;
}

.specimen__spec dd {
  margin: 0;
  color: var(--bs-body-color);
}

.specimen__spec dd.specimen__value--num {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
}

.specimen__extra {
  padding: 0 1.75rem 1.75rem;
}

.specimen__extra h3 {
  font-size: 1rem;
}

.specimen__extra-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 0.75rem;
}

.specimen__extra-grid img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border: 1px solid var(--bs-border-color);
  cursor: zoom-in;
}

.specimen__extra-grid figcaption {
  margin-top: 0.3rem;
  font-size: 0.72rem;
  color: var(--bs-secondary-color);
  text-align: center;
}

.specimen__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  padding: 1.25rem 1.75rem;
  border-top: 1px solid var(--bs-border-color);
  background: var(--bs-tertiary-bg);
}

/* Формы экземпляра коллекции (_collection_item_form.html — и "Добавить в коллекцию", и
   "Редактировать экземпляр") — открываются как одна общая модалка (#collectionItemModal в
   base.html, JS в script.js), а не отдельные страницы. Тот же язык, что у .specimen: акцент по
   материалу, Fraunces на номинале экземпляра, маленькие caps-подписи
   полей — приёмка/правка экземпляра в "гроссбух" коллекции, а не произвольная форма из
   вебдванольных времён. */
.modal-content {
  background: var(--bs-body-bg);
}

.ledger-modal-close {
  position: absolute;
  top: 0.9rem;
  right: 0.9rem;
  z-index: 2;
}

#collectionItemModal .modal-body {
  padding: 0;
}

.ledger-form__loading {
  padding: 3rem 1.5rem;
  text-align: center;
  color: var(--bs-secondary-color);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.ledger-form {
  --variant-accent: var(--bs-emphasis-color);
  position: relative;
}

.ledger-form::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background-image: repeating-linear-gradient(
    90deg, var(--variant-accent) 0, var(--variant-accent) 2px, transparent 2px, transparent 5px
  );
  opacity: 0.55;
}

.ledger-form__context {
  padding: 1.75rem 1.75rem 1.25rem;
  background-image: radial-gradient(ellipse 70% 100% at 0% 0%, color-mix(in srgb, var(--variant-accent) 16%, transparent), transparent 70%);
}

.ledger-form__eyebrow {
  display: block;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--variant-accent);
  margin-bottom: 0.35rem;
}

.ledger-form__item {
  font-family: "Fraunces", Georgia, serif;
  font-weight: 500;
  font-size: 1.3rem;
  color: var(--bs-emphasis-color);
  line-height: 1.2;
}

.ledger-form form {
  padding: 0 1.75rem 1.75rem;
}

/* Личные фото/PDF-вложение экземпляра, показанные над формой их загрузки
   (collection_item_detail.html, issue Бориса 2026-08-20: "делаем дизайн страницы") — тот же
   горизонтальный отступ, что у формы ниже, у .ledger-form__context нет своего нижнего padding,
   поэтому без этого блок прилипал бы к краям карточки. */
.ledger-form__media {
  padding: 0 1.75rem 1rem;
}

.ledger-form__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}

.ledger-form__group {
  margin-top: 1.1rem;
  padding-top: 1rem;
  border-top: 1px dashed var(--bs-border-color);
}

.ledger-form__group-label {
  display: block;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--bs-secondary-color);
  margin-bottom: 0.6rem;
}

.ledger-form__field {
  margin-bottom: 0.75rem;
}

.ledger-form__field:last-child {
  margin-bottom: 0;
}

.ledger-form__field label {
  display: block;
  font-size: 0.78rem;
  color: var(--bs-secondary-color);
  margin-bottom: 0.25rem;
}

.ledger-form__switches {
  margin-top: 1.1rem;
  padding-top: 1rem;
  border-top: 1px dashed var(--bs-border-color);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.ledger-form__switches .form-check-input:checked {
  background-color: var(--variant-accent);
  border-color: var(--variant-accent);
}

.ledger-form__submit {
  margin-top: 1.25rem;
  display: flex;
  justify-content: flex-end;
}

.ledger-form__submit .btn {
  border-color: var(--variant-accent);
  color: var(--variant-accent);
}

.ledger-form__submit .btn:hover {
  background-color: var(--variant-accent);
  border-color: var(--variant-accent);
  color: var(--bs-body-bg);
}

@media (max-width: 480px) {
  .ledger-form__row {
    grid-template-columns: 1fr;
  }
}

/* Полностраничный фолбэк (add_to_collection.html, без JS/прямой заход по URL) — та же
   .ledger-form карточка, просто в потоке страницы вместо модалки. */
.ledger-form-page .ledger-form {
  border: 1px solid var(--bs-border-color);
  max-width: 640px;
  overflow: hidden;
}

/* Переключатель языка в шапке (menu.html) — обычный <select>, не сегментированные кнопки:
   задуман на много языков в перспективе, кнопки-toggle (как Монеты/Банкноты) масштабируются
   только на два варианта. form-select у Bootstrap по умолчанию растягивается на 100% ширины
   родителя — здесь родитель inline-form внутри flex-шапки, без auto-ширины select раздулся бы
   на всё доступное место. */
.lang-switcher {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.lang-switcher__icon {
  color: var(--bs-secondary-color);
  flex-shrink: 0;
}

.lang-switcher__select {
  width: auto;
}

.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Компактный hero главной страницы (issue Бориса 2026-08-13) — заголовок + одна короткая строка +
   кнопка, без длинного описательного абзаца (сайдбар со странами и так объясняет, что за сайт).
   Подстраивается под тему сайта (--bs-body-bg/--bs-emphasis-color), не собственный тёмный блок
   независимо от переключателя, как в первом черновике. */
.hero {
  padding: 2rem 0 1.75rem;
  border-bottom: 1px solid var(--bs-border-color);
  margin-bottom: 1.75rem;
}

.hero__eyebrow {
  display: block;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-accent);
  margin-bottom: 0.6rem;
}

/* Аудит hero (issue Бориса 2026-09-07): --brand-accent (#a5672b) на светлой теме даёт 4.35:1 на
   фоне карточки (#f8f9fa) — не проходит WCAG AA для мелкого текста (нужно 4.5:1, крупные цифры
   .catalog-stats__number того же цвета не задеты, там порог 3:1 для крупного текста). Тёмная
   тема тем же --brand-accent (#d99a54) уже проходит (5.52:1) — трогаем только light, не сам
   --brand-accent (это отдельный, более крупный вопрос "один акцент на весь сайт", не решаем его
   тут же попутно). Замер контраста делался и на локальном сервере, и напрямую на bonumic.com —
   числа совпали, поэтому 4.35 — не опечатка и не разница dev/prod. */
[data-bs-theme="light"] .hero__eyebrow {
  color: #945d27;
}

.hero__title {
  font-family: "Fraunces", Georgia, serif;
  font-weight: 600;
  font-size: clamp(1.75rem, 3.2vw, 2.5rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
  margin: 0 0 1rem;
  color: var(--bs-emphasis-color);
}

.hero__line {
  font-size: 0.95rem;
  color: var(--bs-secondary-color);
  margin: 0 0 1.5rem;
}

.hero__actions {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
}

/* CTA hero был btn-sm (31px высотой) — ниже минимальной тач-цели 44px (WCAG 2.5.5, iOS/Android
   HIG) и визуально мельче кнопки "Светлая тема" в шапке рядом (аудит hero, issue Бориса
   2026-09-07). btn-lg (см. классы в index.html) уже даёт ~48px по высоте штатными отступами
   Bootstrap; font-weight добавляем отдельно — сам .btn-lg вес шрифта не меняет. */
.hero__actions .btn {
  font-weight: 600;
}

/* Статистика каталога под hero на главной (issue Бориса 2026-08-24) — те же цифровые акценты,
   что уже использует .hero__eyebrow (--brand-accent), но крупнее и как отдельные плитки, не
   строка текста: это витрина масштаба каталога, должна считываться с одного взгляда. */
.catalog-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 1rem;
  margin-bottom: 1.75rem;
}

.catalog-stats__item {
  display: flex;
  flex-direction: column;
}

.catalog-stats__number {
  font-family: "Fraunces", Georgia, serif;
  font-weight: 600;
  font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  color: var(--brand-accent);
  line-height: 1.1;
}

.catalog-stats__label {
  font-size: 0.8rem;
  color: var(--bs-secondary-color);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Бронза — единственный акцентный цвет сайта, не два вперемешку с дефолтным синим Bootstrap
   (аудит другого чата, issue Бориса 2026-09-03: "либо бронза — единственный важный цвет, либо
   явное правило синий/золото — но не вперемешку, как сейчас"). До этой правки .btn-primary был
   бронзовым только точечно, где кто-то потрудился переопределить (.hero — CTA "Моя коллекция",
   .auth-card__submit — вход/регистрация/сброс пароля), а в остальных местах (тогглы каталога в
   sidemenu.html/index.html, "Сохранить"/"Отправить" в аккаунте, "+" добавить в коллекцию) молча
   оставался дефолтным Bootstrap-синим — не осознанное разделение ролей, а просто нехватка
   внимания к деталям. Глобальное правило заменяет обе точечные версии ниже (.hero .btn-primary,
   .auth-card__submit .btn — удалены, полностью покрыты этим). --bs-btn-* — те же переменные,
   что Bootstrap использует внутри .btn-primary/.btn-outline-primary, просто с других значений;
   --brand-accent-rgb (см. :root выше) нужен для --bs-btn-focus-shadow-rgb — Bootstrap использует
   его как rgba(), не как обычный цвет. */
.btn-primary {
  --bs-btn-bg: var(--brand-accent);
  --bs-btn-border-color: var(--brand-accent);
  --bs-btn-hover-bg: var(--brand-accent);
  --bs-btn-hover-border-color: var(--brand-accent);
  --bs-btn-active-bg: var(--brand-accent);
  --bs-btn-active-border-color: var(--brand-accent);
  --bs-btn-disabled-bg: var(--brand-accent);
  --bs-btn-disabled-border-color: var(--brand-accent);
  --bs-btn-color: var(--bs-body-bg);
  --bs-btn-hover-color: var(--bs-body-bg);
  --bs-btn-active-color: var(--bs-body-bg);
  --bs-btn-disabled-color: var(--bs-body-bg);
  --bs-btn-focus-shadow-rgb: var(--brand-accent-rgb);
}

.btn-outline-primary {
  --bs-btn-color: var(--brand-accent);
  --bs-btn-border-color: var(--brand-accent);
  --bs-btn-hover-color: var(--bs-body-bg);
  --bs-btn-hover-bg: var(--brand-accent);
  --bs-btn-hover-border-color: var(--brand-accent);
  --bs-btn-active-color: var(--bs-body-bg);
  --bs-btn-active-bg: var(--brand-accent);
  --bs-btn-active-border-color: var(--brand-accent);
  --bs-btn-disabled-color: var(--brand-accent);
  --bs-btn-disabled-border-color: var(--brand-accent);
  --bs-btn-focus-shadow-rgb: var(--brand-accent-rgb);
}

/* Лента "недавно добавлено" — полноценный блок, не узкая полоска (issue Бориса 2026-08-13).
   Листается стрелками влево/вправо по количеству (не по дате, см. views.py CatalogHome) — источник
   данных сейчас Collectible.time_create (наполнение каталога), позже переключится на активность
   коллекций пользователей, когда появится реальная база пользователей. */
.recent-block__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}

.recent-block__title {
  font-family: "Fraunces", Georgia, serif;
  font-weight: 600;
  font-size: 1.3rem;
  margin: 0;
}

.recent-block__nav {
  display: flex;
  gap: 0.4rem;
  flex: none;
}

.recent-block__nav-btn {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid var(--bs-border-color);
  background: var(--bs-body-bg);
  color: var(--bs-emphasis-color);
  text-decoration: none;
  line-height: 1;
}

.recent-block__nav-btn:hover {
  border-color: var(--brand-accent);
  color: var(--brand-accent);
}

.recent-block__nav-btn[aria-disabled="true"] {
  opacity: 0.35;
  pointer-events: none;
}

/* Карточки предметов в списке фильтрации/периода (index.html) — тот же аверс+реверс паттерн,
   что у "Недавно добавлено" (.recent-item-photos), issue Бориса 2026-08-14: раньше это был
   голый текстовый список без единой фотографии, единственное место на сайте, где карточка
   предмета не показывала обе стороны. Кнопка "+" — оверлеем поверх карточки, не hover-reveal —
   этот список могут листать и с тач-экрана, где :hover не сработает. */
.catalog-item-card {
  position: relative;
}

/* Подсветка типов, уже собранных в коллекции пользователя (issue Бориса 2026-08-19) — мягкая
   заливка через bootstrap-переменные --bs-success-bg-subtle/--bs-success-border-subtle, а не
   свой цвет: они уже адаптированы под тёмную/светлую тему сайта (см. свитчер темы в menu.html),
   заливка вручную пришлось бы дублировать в обеих. Кнопка "+" остаётся кликабельной и здесь —
   она добавляет ЕЩЁ один экземпляр (другой год/состояние/дубликат), это не тумблер "есть/нет",
   поэтому не блокируется и не прячется, только красится в success вместо primary (см. index.html). */
.catalog-item-card--owned {
  background-color: var(--bs-success-bg-subtle);
  border-color: var(--bs-success-border-subtle);
}

.catalog-list-table__row--owned,
.variant-list-table__row--owned {
  /* --bs-table-bg, не background-color напрямую — ячейки таблицы красит правило Bootstrap
     `.table > :not(caption) > * > *` через var(--bs-table-bg), и у него та же специфичность,
     что у обычного селектора по классу строки; переопределить саму переменную надёжнее, чем
     спорить за порядок каскада. .variant-list-table__row--owned — та же подсветка на странице
     Типа (detail.html, таблица "Разновидности", issue Бориса 2026-08-19: "для целостности"),
     хотя там владение и так видно по развёрнутой владельческой подстроке под вариантом —
     сама строка варианта раньше никак не выделялась среди остальных до раскрытия подстроки. */
  --bs-table-bg: var(--bs-success-bg-subtle);
}

/* "+" рядом с заголовком, не absolute поверх карточки (issue Бориса 2026-09-03, третий заход
   подряд на эту кнопку — сначала лежала в углу фото и перекрывала реверс монеты, потом
   переносили в подвал карточки и это добавляло пустой высоты, не понравилось). Теперь кнопка —
   обычный flex-ребёнок в одном ряду с заголовком (см. .catalog-item-card__title-row в шаблоне),
   её позиция следует из вёрстки, а не вычисляется вручную absolute-координатами — так надёжно
   для обоих форматов фото сразу (квадратные монеты 1:1 и вытянутые банкноты 2:1 дают РАЗНУЮ
   высоту блока фото, любой фиксированный top/bottom неизбежно промахнулся бы мимо одного из них).
   flex:none — не сжимается и не растягивается наравне с заголовком. */
.catalog-item-card__title-row {
  display: flex;
  align-items: flex-start;
  gap: 0.375rem;
}

.catalog-item-card__title-link {
  /* min-width:0 обязателен — без него flex-item по умолчанию не сжимается уже своего контента
     (min-width:auto), из-за чего .recent-item-text внутри теряет и line-clamp, и перенос строк,
     просто раздвигая ряд вместо того, чтобы занять отведённую ему часть ширины. */
  min-width: 0;
  flex: 1 1 auto;
}

.catalog-item-card__add {
  flex: none;
}

/* Превью аверс+реверс по наведению на строку списка (issue Бориса 2026-08-14) — список остался
   компактным текстом (не заменён карточками), но при наведении/фокусе на ссылку всплывает то же
   фото, что уже показано в режиме "Плитка". Чистый CSS (:hover/:focus-visible), без JS — и не
   работает по тапу на тач-экранах, что нормально: это опциональная подсказка поверх списка,
   плитка остаётся основным способом посмотреть фото на тач-устройствах. loading="lazy" на
   <img> в шаблоне — превью скрыты по умолчанию, но без lazy браузер всё равно скачал бы все
   фото списка сразу.

   :focus-visible, не :focus-within (issue Бориса 2026-08-17: "открытие на среднюю кнопку мыши —
   фото залипает") — открытие ссылки средним кликом (новая фоновая вкладка) в некоторых браузерах
   всё равно фокусирует саму ссылку в текущей вкладке, а blur может не наступить, пока фоновая
   вкладка открыта — превью зависало навсегда поверх списка. :focus-visible срабатывает только на
   действительно клавиатурную навигацию (эвристика браузера), не на клик мышью любой кнопкой,
   так что клавиатурная доступность сохраняется, а баг с залипанием — нет. .list-item-preview
   теперь всегда сама ссылка (не обёртка вокруг неё) везде, где используется этот класс, поэтому
   один общий селектор работает без :has(). */
.list-item-preview {
  position: relative;
  display: inline-block;
}

/* Превью выезжает ВЛЕВО от миниатюры, не вниз (issue Бориса 2026-08-25, второй заход
   2026-09-06: "превью больше раза в 3 и слева, не снизу" — миниатюра здесь первая колонка
   таблицы (index.html/collection.html/wantlist.html/public_collection.html), строки идут
   плотно одна за другой, и увеличенное вниз-превью перекрывало собой соседнюю строку целиком, а
   не только её край, как было терпимо при прежнем размере 180px).

   Позиция ниже (absolute/right:100%) — CSS-фолбэк на случай, если JS не выполнился. В рабочем
   состоянии её на каждый ховер/фокус перебивает script.js инлайн-стилями (position:fixed,
   left/width — под текущий прямоугольник .left, левого сайдбара, top — по строке с оглядкой на
   край экрана): issue Бориса 2026-09-06, третий заход — "пусть превью занимает серую колонку
   слева, так органичней всего". Миниатюра — первая колонка таблицы вплотную к сайдбару, и
   заранее заданной в CSS шириной/направлением совпасть с шириной сайдбара на всех брейкпоинтах
   (offcanvas на мобильном, разная ширина колонки на разных контейнерах) нельзя — либо считать
   в JS по месту, либо мириться с неточным совпадением.

   column, не row — при ширине "во весь сайдбар" (не фиксированных 312px, см. img/placeholder
   ниже) два фото РЯДОМ уменьшились бы вдвое каждое; одно под другим — оба на всю ширину
   колонки. */
.list-item-preview__photos {
  display: none;
  position: absolute;
  left: auto;
  right: 100%;
  top: 0;
  z-index: 10;
  width: 312px;
  margin-right: 4px;
  flex-direction: column;
  gap: 1px;
  background: var(--bs-border-color);
  border: 1px solid var(--bs-border-color);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

.list-item-preview:hover .list-item-preview__photos,
.list-item-preview:focus-visible .list-item-preview__photos {
  display: flex;
}

/* Сайдбар "Другие монеты/банкноты периода" — направление ВЛЕВО совпадает с общим правилом выше,
   но своя (row) раскладка фото и свой (меньший) размер: этот сайдбар — правая колонка широкого
   двухколоночного макета, слева от него всё ещё основной контент страницы (col-lg-8), места
   хватает даже на два штатных 180px фото РЯДОМ — там это уже проверено и работало до сегодняшней
   правки, менять незачем. */
.detail-siblings-list .list-item-preview__photos {
  width: auto;
  flex-direction: row;
}

.detail-siblings-list .list-item-preview__photos img,
.detail-siblings-list .list-item-preview__placeholder {
  width: 180px;
  height: 180px;
}

/* width:100% (не фиксированный px) — issue Бориса 2026-09-06, третий заход: контейнер
   .list-item-preview__photos теперь либо 312px (CSS-фолбэк), либо ширина сайдбара (JS,
   script.js) — картинка должна заполнять ту ширину, какая фактически досталась контейнеру, а
   не задавать свою поверх него. aspect-ratio: 1/1 — то же квадратное поведение, что раньше
   давала явная height:312px, но без завязки на конкретное число; у банкнот его перебивает
   .banknote-thumb ниже (2/1). */
.list-item-preview__photos img,
.list-item-preview__placeholder {
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background-color: var(--bs-tertiary-bg);
  display: block;
}

/* Раздельный ховер аверс/реверс на странице Периода/Страны (issue Бориса 2026-09-06, четвёртый
   заход — см. подробный комментарий в _catalog_list_row.html) — .catalog-thumb-pair это <a>,
   тот же триггер целиком, что раньше нёс класс .list-item-preview (там же и остаётся, для
   collection.html/wantlist.html/public_collection.html); здесь наведение обрабатывается на
   уровне отдельных .catalog-thumb-hover внутри него, а не на весь .list-item-preview целиком.
   position:relative на паре — точка отсчёта для CSS-фолбэка попапов, если JS не выполнился
   (см. .catalog-thumb-hover__preview ниже); сам .catalog-thumb-hover тоже relative — не для
   позиционирования попапа (он вынесен наружу, не его потомок), а чтобы клик/тап по своей
   половине миниатюры не терял область точно под курсором на всех браузерах. */
.catalog-thumb-pair,
.catalog-thumb-hover {
  position: relative;
  display: inline-block;
}

/* display:none по умолчанию — показывает/прячет script.js (не CSS :hover, см. комментарий в
   _catalog_list_row.html — попап и его триггер не соседи по DOM, а через :has() выбирать "свою"
   пару сложнее, чем через JS). position/width/top — тот же CSS-фолбэк и тот же JS-пересчёт под
   ширину сайдбара, что у .list-item-preview__photos выше, только heightMultiplier у
   positionPreviewAgainstSidebar (script.js) — 1 картинка, не 2 друг под другом. */
.catalog-thumb-hover__preview {
  display: none;
  position: absolute;
  right: 100%;
  top: 0;
  z-index: 10;
  width: 312px;
  margin-right: 4px;
  background: var(--bs-border-color);
  border: 1px solid var(--bs-border-color);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

.catalog-thumb-hover__preview img {
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background-color: var(--bs-tertiary-bg);
  display: block;
}

/* Тот же кроп-в-квадрат для банкнот в табличном виде (issue Бориса 2026-08-22, продолжение
   .recent-item-img--banknote выше) — .banknote-thumb на <img>/пустом <span> перебивает
   object-fit/height родительских правил (40px/120px/180px), ширина остаётся как задана ими,
   высота пересчитывается через aspect-ratio, поэтому один общий модификатор работает сразу для
   всех трёх размеров миниатюр (маленькая постоянная, увеличенная в .catalog-list-table,
   всплывающая по наведению), без отдельных правил под каждый размер. */
.collection-table__thumbs-small img.banknote-thumb,
.list-item-preview__photos img.banknote-thumb,
.catalog-thumb-hover__preview img.banknote-thumb,
.collection-table__thumb--empty.banknote-thumb,
.list-item-preview__placeholder.banknote-thumb {
  aspect-ratio: 2 / 1;
  height: auto;
  object-fit: contain;
}

/* Таблица "Моя коллекция" (collection.html), сгруппированная по стране (issue Бориса
   2026-08-14) — раньше был плоский список без структуры. table-group-divider (Bootstrap) уже
   рисует разделительную полосу между <tbody> разных стран; сама строка-заголовок страны
   дополнительно выделена фоном var(--bs-tertiary-bg), чтобы граница между странами читалась
   с первого взгляда, а не только по тонкой линии. */
.collection-table__country-row th {
  background-color: var(--bs-tertiary-bg);
  font-weight: 600;
  padding-top: 0.6rem;
  padding-bottom: 0.6rem;
}

/* Флаг страны в заголовке группы "Моей коллекции" — issue Бориса 2026-08-18: "увеличь картинки
   флагов, минимум раза в 4... флаги красиво смотрятся и украшают сайт". 80×60 — ровно ×4 от
   базового .flag-icon (20×15), не берём готовый .flag-icon-lg (160×120, для героя страницы под
   h1/h2) — в компактной строке таблицы с бейджем количества такой большой флаг перевесил бы
   остальной контент строки. */
.collection-table__country-row .flag-icon {
  width: 80px;
  height: 60px;
  margin-right: 10px;
}

/* Аверс+реверс вместо одной фотографии (issue Бориса 2026-08-14: "сделаем 2 фотографии
   аверс+реверс") — .collection-table__thumbs это тот же триггер, что .list-item-preview
   (см. правила list-item-preview__photos выше, переиспользуем 1-в-1: те же 180×180 при
   наведении/фокусе, без дублирования CSS), только сама "точка наведения" здесь не текстовая
   ссылка, а пара маленьких превью-миниатюр. */
.collection-table__thumb-cell {
  width: 90px;
}

.collection-table__thumbs-small {
  display: flex;
  gap: 1px;
}

.collection-table__thumbs-small img,
.collection-table__thumb--empty {
  display: block;
  width: 40px;
  height: 40px;
  object-fit: cover;
  background-color: var(--bs-tertiary-bg);
  border: 1px solid var(--bs-border-color);
}

/* Таблица разновидностей на странице типа (detail.html), список-режим — issue Бориса
   2026-08-14: "таблицу делаем более компактной, она не обязательно должна занимать всю
   горизонталь" (w-auto — см. также .table.w-auto в index.html для того же приёма) + "кнопка
   добавить - вне таблицы но в той же строке": последняя колонка (variant-list-table__actions)
   без границы/фона — та же строка технически, но визуально не выглядит табличным столбцом
   данных, а читается как отдельное действие сбоку. */
.variant-list-table th {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--bs-secondary-color);
}

.variant-list-table th,
.variant-list-table td {
  padding-right: 1.25rem;
}

.variant-list-table__actions {
  border: none !important;
  background: transparent;
  padding-right: 0;
}

/* Подстрока "уже в коллекции" под строкой разновидности (issue Бориса 2026-08-15: сначала
   была в последней ячейке действий — визуально попадала под колонку Mintage/Details, было
   непонятно, к чему она относится; затем — раньше был отдельный "Убрать" в ряд с "Добавить"
   на каждый экземпляр, при 2+ превращалось в частокол одинаковых кнопок без пояснения).
   Теперь отдельный <tr> с colspan на всю ширину таблицы сразу под строкой варианта — растянут
   на все колонки, а не зажат в одну ячейку. border-top: none — визуально приклеена к своей
   строке варианта сверху, а не читается как ещё одна самостоятельная строка таблицы. */
.variant-list-table__owned-row td {
  padding-top: 0;
  padding-bottom: 0.5rem;
  border-top: none;
  font-size: 0.82rem;
  color: var(--bs-secondary-color);
}

.variant-list-table__owned-row .btn-link {
  vertical-align: baseline;
}

/* Два <select> (месяц + год) поля "Дата приобретения" (common/forms.py, MonthYearWidget) —
   issue Бориса 2026-08-17. Bootstrap .form-select — display:block + width:100%, поэтому без
   этой обёртки два select'а вставали бы друг под другом на всю ширину, а не рядом. */
.month-year-widget {
  display: flex;
  gap: 0.5rem;
}

.month-year-widget select {
  width: auto;
  flex: 1;
}

/* Стрелки листания в модалке фото (#photoModal, detail.html/variant_detail.html) — issue
   Бориса 2026-08-17. Скрыты по умолчанию (d-none в разметке), JS (script.js) убирает d-none,
   только если .zoomable-фото на странице больше одного — листать между аверсом и реверсом
   (и доп. фото, если есть) есть смысл, между единственным фото — нет. */
.photo-modal-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--bs-border-color);
  background: var(--bs-body-bg);
  color: var(--bs-emphasis-color);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 5;
}

.photo-modal-nav:hover {
  border-color: var(--brand-accent);
  color: var(--brand-accent);
}

.photo-modal-nav--prev {
  left: 0.5rem;
}

.photo-modal-nav--next {
  right: 0.5rem;
}

/* Страница входа (accounts/login.html) — issue Бориса 2026-08-18: "делаем дизайн для страницы
   логина", раньше голый {{ form.as_p }} без единого класса. Тот же язык, что у .ledger-form/
   .specimen: узкая карточка, гурт-полоска сверху акцентным цветом бренда (не --variant-accent
   монеты/банкноты — тут никакого предмета нет, обычный --brand-accent), Fraunces на заголовке.
   С 2026-09-02 тем же паттерном оформлены register.html и вся ветка сброса/смены пароля и email
   (accounts/password_reset_*.html, password_change_*.html, email_change_form.html). */
.auth-card-wrap {
  display: flex;
  justify-content: center;
  padding: 2.5rem 1rem;
}

.auth-card {
  position: relative;
  width: 100%;
  max-width: 380px;
  background: var(--bs-body-bg);
  border: 1px solid var(--bs-border-color);
  padding: 2rem 1.75rem 1.75rem;
  overflow: hidden;
}

.auth-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background-image: repeating-linear-gradient(
    90deg, var(--brand-accent) 0, var(--brand-accent) 2px, transparent 2px, transparent 5px
  );
  opacity: 0.55;
}

.auth-card__eyebrow {
  display: block;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-accent);
  margin-bottom: 0.5rem;
}

.auth-card__title {
  font-family: "Fraunces", Georgia, serif;
  font-weight: 600;
  font-size: 1.75rem;
  margin: 0 0 1.5rem;
  color: var(--bs-emphasis-color);
}

.auth-card__field {
  margin-bottom: 1rem;
}

.auth-card__field label {
  display: block;
  font-size: 0.82rem;
  color: var(--bs-secondary-color);
  margin-bottom: 0.3rem;
}

.auth-card__submit {
  margin-top: 1.25rem;
}

/* Кнопка (btn-outline-primary) теперь бронзовая через глобальное правило .btn-outline-primary
   выше — своего переопределения тут больше не нужно, было ровно то же самое, только без
   active/focus-состояний. */

.auth-card__links {
  margin-top: 1.25rem;
  padding-top: 1rem;
  border-top: 1px dashed var(--bs-border-color);
  text-align: center;
  font-size: 0.85rem;
}

.auth-card__links-sep {
  margin: 0 0.5rem;
  color: var(--bs-secondary-color);
}

/* Счётчик в правом верхнем углу вкладки Регулярные/Памятные/Коллекционные (index.html) — issue
   Бориса 2026-08-19, тот же приём позиционирования, что у .notif-bell-badge (position:absolute,
   top/right в минус). z-index нужен, т.к. кнопки внутри .btn-group у Bootstrap перекрывают друг
   друга по краю (отрицательный margin-left для схлопывания рамок) — без z-index бейдж соседней
   кнопки мог бы перекрыть его. */
.tab-count-badge {
  position: absolute;
  top: -6px;
  right: -6px;
  z-index: 2;
  font-size: 0.6rem;
  padding: 0.2em 0.4em;
}

/* Миниатюры в списке "Страна"/"Период" (index.html, .catalog-list-table) крупнее, чем базовые
   40px у .collection-table__thumbs-small (issue Бориса 2026-08-19: "фото надо сделать больше.
   Таким же, как в режиме Плитка") — не трогаем сам .collection-table__thumbs-small, он общий
   с "Моей коллекцией" (collection.html), там просьба не касалась размера. 120px — фото в
   Плитке (.recent-item-img) само responsive (50% ширины карточки row-cols-*), точного
   "одинакового" размера в фиксированной ячейке таблицы не бывает; 120px — то, что Плитка
   реально показывает на типичном десктопном экране (~1400px), взято как ориентир.
   thumb-cell шире под них (250px = 2×120 + 1px gap + запас на отступы ячейки). */
.catalog-list-table .collection-table__thumb-cell {
  width: 250px;
}

.catalog-list-table .collection-table__thumbs-small img,
.catalog-list-table .collection-table__thumb--empty {
  width: 120px;
  height: 120px;
}

/* Тот же banknote-thumb модификатор (см. выше), но здесь нужно явно перебить именно это
   126px-переопределение — та же специфичность (2 класса + тег), а это правило идёт в файле
   позже, поэтому без явного повтора здесь высота обратно схлопнулась бы в квадрат 120×120. */
.catalog-list-table .collection-table__thumbs-small img.banknote-thumb,
.catalog-list-table .collection-table__thumb--empty.banknote-thumb {
  height: auto;
  aspect-ratio: 2 / 1;
}

/* На узких экранах 120px-миниатюры выше не оставляют места для названия/кнопки "+" — таблица
   (table-sm w-auto, БЕЗ .table-responsive-обёртки, см. index.html) раздувается шире экрана
   целиком (issue Бориса 2026-09-04: "почини таблицу списка на мобильном"). thumb-cell один даёт
   250px — на телефоне 375px это уже 2/3 ширины. Возвращаем на этой ширине тот же базовый размер,
   что и у .collection-table__thumbs-small везде, где 120px не запрашивали явно (сама "Моя
   коллекция" всегда была 40px, крупный размер — только для этого списка каталога, см. комментарий
   выше). 576px — брейкпоинт Bootstrap sm, тот же, что уже использует .sibling-nav-btn ниже. */
@media (max-width: 576px) {
  .catalog-list-table .collection-table__thumb-cell {
    width: 90px;
  }

  .catalog-list-table .collection-table__thumbs-small img,
  .catalog-list-table .collection-table__thumb--empty {
    width: 40px;
    height: 40px;
  }
}

/* Заголовки исторических периодов внутри списка предметов страны/группы (issue Бориса
   2026-08-22: "визуальное разделение списка на Периоды") — тонкая верхняя граница вместо
   полноценной карточки/фона: список и так длинный, отдельные подложки под каждый заголовок
   визуально утяжелили бы страницу больше, чем разделительная линия. Первый заголовок
   (:first-child) — без отступа/линии сверху, вплотную к переключателю Список/Плитка. */
.catalog-period-heading {
  margin: 2rem 0 0.75rem;
  padding-top: 1rem;
  border-top: 1px solid var(--bs-border-color);
  font-size: 1.1rem;
}

.catalog-period-heading:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

.catalog-period-heading a {
  color: inherit;
  text-decoration: none;
}

.catalog-period-heading a:hover {
  text-decoration: underline;
}

.catalog-period-heading-row td {
  padding-top: 1.5rem;
  font-size: 1.1rem;
  border-bottom: 1px solid var(--bs-border-color);
}

.catalog-period-heading-row:first-child td {
  padding-top: 0.5rem;
}

.catalog-period-heading-row a {
  color: inherit;
  text-decoration: none;
}

.catalog-period-heading-row a:hover {
  text-decoration: underline;
}

/* Разбивка по валюте ("1 динар = 1000 филсов") под заголовком периода (issue Бориса
   2026-08-22) — своей строкой, а не через запятую после диапазона лет, чтобы не удлинять и
   так не короткую шапку периода ещё сильнее вбок. */
.catalog-period-heading__currency,
.catalog-period-heading-row .catalog-period-heading__currency {
  display: block;
  margin-top: 0.15rem;
}

/* Номинал в "Расширенных фильтрах" — чекбоксы по представленным значениям вместо диапазона
   от/до (issue Бориса 2026-08-31). Django-виджет CheckboxSelectMultiple по умолчанию рендерит
   один вариант на строку — тесно для десятка коротких номиналов, раскладываем в строку.
   max-height+overflow — у стран с большим разбросом номиналов список может стать очень
   длинным (issue Бориса 2026-08-31, тем же днём) — окно со скроллом вместо растягивания
   всей страницы. */
.filter-checkbox-group {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 0.25rem 1rem;
  max-height: 12rem;
  overflow-y: auto;
  border: 1px solid var(--bs-border-color);
  border-radius: 0.25rem;
  padding: 0.5rem;
  margin-top: 0.25rem;
}

.filter-checkbox-group > div {
  white-space: nowrap;
}

/* Кнопка "Расширенные фильтры" — <summary> сам по себе не поддерживает Bootstrap-классы
   до конца: браузер добавляет собственный треугольник-маркер (::marker/::-webkit-details-marker),
   которого нет ни у одной другой кнопки на странице (issue Бориса 2026-08-31, "выбивается из
   общего дизайна"). display:inline-block + list-style:none — убирает и маркер, и стандартный
   list-item-подобный intrinsic size <summary>, чтобы .btn выглядела как обычная кнопка. */
.filter-details > summary {
  list-style: none;
  display: inline-block;
}

.filter-details > summary::-webkit-details-marker {
  display: none;
}

.filter-details > summary::marker {
  content: '';
}

/* Тулбар фильтров (Регулярные/Памятные/Коллекционные + Расширенные фильтры) — раньше это были
   два отдельных .btn-group, поставленных друг под другом с одинаковым mb-2 (issue Бориса
   2026-09-04: "сверху вниз слитно кнопки не связанные между собой, но слитые в единый блок
   визуально" — при таком раскладе single-row .btn-group ничем не отличался по вертикальному
   отступу от двух РАЗНЫХ виджетов под ним, поэтому все три читались как один составной
   компонент). Теперь оба виджета в одной строке (gap между ними задаёт "это разные элементы",
   а не расстояние внутри .btn-group — там кнопки по-прежнему слиты общей рамкой) и отделены от
   переключателя вида списка снизу отдельной чертой — тем же приёмом border-top dashed, что уже
   используется в .specimen__extra на карточке предмета, а не изобретённым здесь новым узором. */
.catalog-filter-toolbar {
  display: flex;
  flex-wrap: wrap;
  /* flex-start, не center (issue Бориса 2026-09-04, второй заход) — пока <details> "Расширенные
     фильтры" свёрнута, она такой же высоты, как .btn-group рядом, разницы не видно. Открытая
     деталь становится намного выше (раскрывается форма с чекбоксами), и center вертикально
     центрирует низкий .btn-group относительно этой большой высоты строки — вкладки Регулярные/
     Памятные/Коллекционные визуально уезжают в середину/низ, будто вообще другой блок. flex-start
     прибивает оба элемента к верху строки независимо от того, что внутри второго. */
  align-items: flex-start;
  gap: 0.5rem 0.75rem;
  margin-bottom: 1rem;
  padding-bottom: 1rem;
  border-bottom: 1px dashed var(--bs-border-color);
}

/* display:contents — форма отправки "Расширенных фильтров" не должна иметь собственного бокса
   в раскладке (иначе она как блочный элемент разрывала бы общую строку тулбара), но обязана
   остаться настоящей <form> для сабмита — скрытые поля (historical_period/type/issue_category)
   должны попасть в тот же submit, что и filter_form. Видимые дети (ссылка "Сбросить всё" и
   <details>) становятся прямыми участниками flex-строки .catalog-filter-toolbar. */
.catalog-filter-toolbar form {
  display: contents;
}

/* Тулбар результатов (счётчик "Найдено" + Список/Плитка) — та же логика "это один узел, не два
   случайно оказавшихся рядом": количество слева, переключатель вида справа на одной строке,
   как в большинстве каталогов (сортировка/вид — у количества найденного, а не у фильтров сверху).
   margin-top задаёт зазор от .catalog-filter-toolbar (у него уже есть свой padding-bottom и
   черта снизу) отдельно от него самого. */
.catalog-results-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: 0.5rem;
  margin-bottom: 0.75rem;
}

/* Правая половина тулбара результатов — "Показывать по" и Список/Плитка сгруппированы вместе
   (issue Бориса 2026-09-05): оба про то, как отображён уже найденный список, в отличие от
   счётчика "Найдено" слева от них. Внутренний gap меньше, чем зазор filter-toolbar сверху
   (0.75rem) — эти два виджета более тесно связаны по смыслу друг с другом, чем категории
   выпуска с "Расширенными фильтрами" там. */
.catalog-results-toolbar__view-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
}

.catalog-per-page {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  font-size: 0.8125rem;
  color: var(--bs-secondary-color);
}

.catalog-per-page select {
  width: auto;
}

/* Кнопки "предыдущий/следующий предмет периода" (detail.html) — у памятных/коллекционных монет
   название может быть очень длинным, без ограничения кнопка растягивалась на всю ширину.
   inline-block обязателен: overflow/text-overflow не работают на элементах со сдвигом
   baseline по умолчанию у <a>, а .btn уже задаёт inline-block, но max-width тут переопределяет. */
.sibling-nav-btn {
  display: inline-block;
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
}

@media (max-width: 576px) {
  .sibling-nav-btn {
    max-width: 140px;
  }
}

/* Кнопки "Убрать"/"Убрать из коллекции" — красный оставлен только как сигнал ПОД курсором
   (issue Бориса 2026-09-03: "красный должен остаться редким сигналом, а не тиражированным
   элементом интерфейса" — раньше btn-outline-danger/text-danger красили эти кнопки красным на
   каждой строке списка постоянно, хотя сам клик всё равно уходит в подтверждающий
   confirm()/window.confirm ниже по цепочке, а не удаляет сразу). В обычном состоянии — нейтральный
   btn-outline-secondary, краснеет только при наведении/фокусе, непосредственно перед кликом.

   Не переопределяем сами переменные .btn-outline-secondary глобально — точечный модификатор
   поверх стандартного класса, чтобы не задеть остальные вторичные кнопки на сайте. */
.btn-remove-quiet {
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--bs-danger);
  --bs-btn-hover-border-color: var(--bs-danger);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--bs-danger);
  --bs-btn-active-border-color: var(--bs-danger);
  --bs-btn-focus-shadow-rgb: var(--bs-danger-rgb);
}

/* Тот же принцип для текстовых ссылок-кнопок (variant-list-table__owned-row в detail.html) —
   вместо постоянного text-danger, приглушённый цвет по умолчанию, краснеет только при наведении. */
.link-remove-quiet {
  color: var(--bs-secondary-color);
}

.link-remove-quiet:hover,
.link-remove-quiet:focus-visible {
  color: var(--bs-danger) !important;
}

/* Индикатор "непрочитано" прямо в строке списка уведомлений (accounts/notifications.html) —
   issue Бориса 2026-09-04, этап 3 п.1: "не только цифра в шапке". Точка — тот же bg-danger,
   что уже используют счётчики непрочитанного (.notif-bell-badge и бейджи в inbox.html), плюс
   полужирный текст самой строки — оба сигнала сразу, как и просили ("точка/акцентный фон
   строки/полужирный текст"), без выбора одного варианта. Полноценный акцентный фон строки не
   стал делать — list-group-item-action и так меняет фон по hover, добавление ещё одного
   постоянного фона поверх спорило бы с этим и с уже подсвеченными строками catalog-item-card
   ("уже в коллекции" — bg-success-subtle), у той подсветки другой смысл, лучше не путать языки. */
.notif-list-item--unread {
  font-weight: 600;
}

.notif-unread-dot {
  display: inline-block;
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  margin-top: 0.4em;
  border-radius: 50%;
  background-color: var(--bs-danger);
}

/* Превью личного фото сразу под input[type=file] (collection_item_detail.html, script.js
   .js-file-preview-field) — issue Бориса 2026-09-04, этап 3 п.3. Небольшая миниатюра, тот же
   язык рамки/фона, что у остальных фото-превью сайта (.collection-table__thumbs-small img),
   не увеличенный specimen__photo-frame — здесь это просто подтверждение "файл выбран
   правильный", а не витрина, крупнее не нужно. */
.ledger-form__file-preview {
  display: block;
  margin-top: 0.5rem;
  width: 90px;
  height: 90px;
  object-fit: cover;
  background-color: var(--bs-tertiary-bg);
  border: 1px solid var(--bs-border-color);
}

/* Нумерованная пагинация каталога (issue Бориса 2026-09-04, index.html/_pagination.html) —
   своя вёрстка, не Bootstrap .pagination (тот — синие "таблетки" в рамках, здесь используем
   тот же язык компактных числовых меток, что уже есть на сайте: JetBrains Mono, как у
   .ledger-form__group-label/.catalog-stats__label, текущая страница — brand-accent сплошной
   заливкой, тот же приём, что у .catalog-pagination__page--current). flex-wrap — на мобильном
   с длинным списком страниц перенос на вторую строку лучше горизонтального скролла. */
.catalog-pagination {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.15rem;
  margin: 1rem 0;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 0.8rem;
}

.catalog-pagination__page,
.catalog-pagination__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.75rem;
  height: 1.75rem;
  padding: 0 0.35rem;
  border-radius: 0.25rem;
  color: var(--bs-emphasis-color);
  text-decoration: none;
}

a.catalog-pagination__page:hover,
a.catalog-pagination__arrow:hover {
  background-color: var(--bs-tertiary-bg);
  color: var(--brand-accent);
}

.catalog-pagination__page--current {
  background-color: var(--brand-accent);
  color: var(--bs-body-bg);
  font-weight: 600;
}

.catalog-pagination__arrow--disabled {
  color: var(--bs-secondary-color);
  opacity: 0.35;
}

.catalog-pagination__ellipsis {
  color: var(--bs-secondary-color);
  padding: 0 0.1rem;
  /* Не даём "…" самому переноситься от соседних номеров при flex-wrap — читалось бы как
     повисший символ в начале строки. */
  white-space: nowrap;
}
