/* css/variables.css */
/* Зарегистрированная длина: иначе смена --row-pad-v не интерполируется, padding в таблице «прыгает». */
@property --row-pad-v {
  syntax: "<length>";
  inherits: true;
  initial-value: 11px;
}
html {
  transition: --row-pad-v 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  /* Плотность / сортировка / закрытие черновика — один радиус; glass задаёт ниже */
  --filter-toolbar-icon-radius: 7px;
}
html[data-style='glass'],
html[data-style='simple'],
html[data-style='nova'] {
  --filter-toolbar-icon-radius: 12px;
}
@media (prefers-reduced-motion: reduce) {
  html {
    transition: none;
  }
}

[data-theme="light"] {
  --bg: #F3F3F3; --card-bg: #FFFFFF; --card-border: rgba(0,0,0,0.08);
  --card-shadow: 0 2px 8px rgba(0,0,0,0.06), 0 0 0 1px rgba(0,0,0,0.04);
  --text: #1A1A1A; --text-secondary: #605E5C; --text-tertiary: #A19F9D;
  --divider: rgba(0,0,0,0.08); --row-hover: rgba(0,0,0,0.04);
  --row-alt: rgba(0,0,0,0.02); --today-bg: rgba(0,120,212,0.06);
  --dropdown-bg: #FFFFFF; --dropdown-shadow: 0 8px 32px rgba(0,0,0,0.14), 0 0 0 1px rgba(0,0,0,0.06);
  /* Поверхность модалок = как у .card; при data-style=glass см. glass.css (--auth-modal-shadow). */
  --auth-modal-shadow: var(--card-shadow);
  --filter-border: rgba(0,0,0,0.15); --dashed-border: rgba(0,0,0,0.18);
  --header-icon: #605E5C; --header-icon-active: #1A1A1A;
  --table-header: #605E5C; --table-border: rgba(0,0,0,0.06);
  --accent: #0078D4; --accent-hover: #106EBE; --accent-light: rgba(0,120,212,0.10);
  --header-bg: rgba(243,243,243,0.85);
  --card-radius: 8px;
  --mica-bg: rgba(243,243,243,0.72);
  --sidebar-dash-bottom-gap: 14px;
  --account-avatar-gradient: linear-gradient(135deg, #0757b8 0%, #0b7fd4 42%, #35c8ff 100%);
  --account-avatar-gradient-hover: linear-gradient(135deg, #064a9e 0%, #096bb8 42%, #28b8f0 100%);
  --scrollbar-thumb: rgba(0, 0, 0, 0.18);
  --scrollbar-thumb-hover: rgba(0, 0, 0, 0.28);
  --scrollbar-track: var(--bg);
  /* Нативный <select>: триггер (список option рисует ОС/браузер) */
  --native-select-radius: 10px;
  --native-select-py: 9px;
  --native-select-pl: 14px;
  --native-select-pr: 38px;
  /* Индекс движения рынка: цвет состояния (calm/wave/storm) для SVG-визуализаций */
  --mi-calm: #2f7fd4;  --mi-calm-bg: rgba(47,127,212,.12);
  --mi-wave: #d99a2b;  --mi-wave-bg: rgba(217,154,43,.15);
  --mi-storm: #e0533d; --mi-storm-bg: rgba(224,83,61,.13);
  /* Предупреждение (уценка/некондиция, лимит квоты). Значение ПРИБИТО к нынешнему
     эффективному рендеру: до 28.07.2026 токен не был объявлен вовсе и table.css
     (.substandard-badge, .analogs-item-match.partial) всегда падал в литерал-фолбэк
     #c9a227. Объявляем ровно его — тогда единый источник появляется, а ни одна
     существующая поверхность не сдвигается. Тюнинг тона — отдельным решением владельца.
     Использовать для ЗАЛИВОК и рамок; для текста — --text-secondary (контраст). */
  --accent-warn: #c9a227;
  /* Цена и остаток «есть в наличии». #2f8f56 (прежний литерал в watchlist/ai-chat) даёт
     на белом всего 4.05:1 — ниже AA для 12–13px/700. Считать надо не по идеальному
     --card-bg, а по фактическому: в стиль-паке simple карточка ПОЛУПРОЗРАЧНАЯ (72%),
     и замер в живом браузере дал у #1E7A44 всего 4.48:1 — недобор. #17663A держит
     6.2:1 на той же полупрозрачной подложке. */
  --price-ok: #17663A;
}
/* Согласовать нативные элементы ОС (в т.ч. fallback-скролл) с тёмной/светлой темой */
html[data-theme="light"] { color-scheme: light; }
html[data-theme="dark"] { color-scheme: dark; }

[data-theme="dark"] {
  --bg: #202020; --card-bg: #2D2D2D; --card-border: rgba(255,255,255,0.09);
  --card-shadow: 0 2px 8px rgba(0,0,0,0.32); --text: #FFFFFF;
  --text-secondary: #9D9D9D; --text-tertiary: #6E6E6E;
  --divider: rgba(255,255,255,0.07); --row-hover: rgba(255,255,255,0.06);
  --row-alt: rgba(255,255,255,0.025); --today-bg: rgba(0,120,212,0.14);
  --dropdown-bg: #3D3D3D; --dropdown-shadow: 0 8px 32px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.07);
  --auth-modal-shadow: var(--card-shadow);
  --filter-border: rgba(255,255,255,0.12); --dashed-border: rgba(255,255,255,0.14);
  --header-icon: #9D9D9D; --header-icon-active: #fff;
  --table-header: #9D9D9D; --table-border: rgba(255,255,255,0.06);
  --accent: #0078D4; --accent-hover: #1A86D4; --accent-light: rgba(0,120,212,0.18);
  --header-bg: rgba(32,32,32,0.88);
  --card-radius: 8px;
  --mica-bg: rgba(32,32,32,0.80);
  --sidebar-dash-bottom-gap: 14px;
  --account-avatar-gradient: linear-gradient(135deg, #0757b8 0%, #0b7fd4 42%, #35c8ff 100%);
  --account-avatar-gradient-hover: linear-gradient(135deg, #064a9e 0%, #096bb8 42%, #28b8f0 100%);
  --scrollbar-thumb: rgba(255, 255, 255, 0.22);
  --scrollbar-thumb-hover: rgba(255, 255, 255, 0.36);
  --scrollbar-track: var(--bg);
  --native-select-radius: 10px;
  --native-select-py: 9px;
  --native-select-pl: 14px;
  --native-select-pr: 38px;
  /* Индекс движения: в тёмной теме состояние ярче (конкурсный борд 16.07) */
  --mi-calm: #55a4ec;  --mi-calm-bg: rgba(85,164,236,.16);
  --mi-wave: #e9b04a;  --mi-wave-bg: rgba(233,176,74,.16);
  --mi-storm: #f0705a; --mi-storm-bg: rgba(240,112,90,.16);
  /* См. коммент в светлой теме: значение прибито к нынешнему фолбэку table.css,
     который до объявления токена работал одинаково в обеих темах. */
  --accent-warn: #c9a227;
  /* На --card-bg #2D2D2D даёт 6.06:1 — совпадает с нынешним литералом watchlist. */
  --price-ok: #6BBD86;
}

body {
  background: var(--bg); color: var(--text);
  font-family: 'Segoe UI Variable', 'Segoe UI', 'Inter', system-ui, sans-serif;
}
/* Win11: no noise texture */

/* css/fonts.css */
/* Inter variable (self-hosted WOFF2) — без запросов к fonts.googleapis.com / gstatic */

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url('../assets/fonts/inter-cyrillic-wght-normal.woff2') format('woff2-variations');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url('../assets/fonts/inter-latin-wght-normal.woff2') format('woff2-variations');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Manrope — тот же self-hosted VF, что у бренда гостевого лэндинга (Delect.ru) */
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('../assets/fonts/manrope-vf-latin.woff2') format('woff2-variations');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('../assets/fonts/manrope-vf-cyrillic.woff2') format('woff2-variations');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* css/base.css */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Inline SVG без собственных размеров до приезда component CSS получает от браузера
   intrinsic 300x150. Application CSS в production намеренно грузится неблокирующе,
   поэтому такой SVG успевал на один кадр развернуться огромной иконкой. Нулевая
   специфичность оставляет это только безопасным prepaint-default: любое штатное
   правило компонента (.search-icon svg, .cab-tab-icon svg, графики и т.д.) сразу
   перекрывает 1em без !important, без дополнительного запроса и без CLS от 300x150. */
:where(svg[viewBox]:not([width]):not([height])) {
  width: 1em;
  height: 1em;
}

html {
  overflow-x: hidden;
  height: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Жёлоб под scrollbar-gutter рисуется на фоне html; без этого при dark — чёрная полоса, не var(--bg) */
  background: var(--bg);
  /* Меньше сдвиг контента при появлении/исчезновении полосы (модалки и т.п.) */
  scrollbar-gutter: stable;
}
body { overflow-x: hidden; }

/* js/scroll-lock.js — уменьшает «резиновый» скролл цепочки под оверлеем */
html.modal-scroll-lock {
  overscroll-behavior: none;
}
body {
  font-family: 'Segoe UI Variable', 'Segoe UI', 'Inter', system-ui, sans-serif;
  font-size: 13.5px; line-height: 1.45;
  transition: background-color 0.3s ease, color 0.3s ease;
  min-height: 100vh;
  display: flex; flex-direction: column;
  background: var(--bg); color: var(--text);
}
button { cursor: pointer; background: none; border: none; font: inherit; }
table  { border-collapse: collapse; width: 100%; }
input[type="file"] { display: none; }

/* Win11 Fluent Design tokens */

/* css/layout.css */
/* Рельса живёт в общей разметке каталога, но её тяжёлые стили грузятся условно.
   Поэтому безопасное состояние обязано быть в общем листе: без условного стиля
   рельсы элементы не должны становиться обычными кнопками с SVG во весь доступный
   размер. Каждый стиль с рельсой включает её своим более специфичным правилом. */
.nova-rail-quick,
.nova-rail-item {
  display: none;
}

/* mobile.css owns the visible state inside the widgets sheet. Keeping this
   header inert here prevents a flash on desktop and before that layer arrives. */
.mobile-widgets-sheet__header {
  display: none;
}

.page-wrapper {
  max-width: 1440px;
  width: 100%;
  margin: 0 auto;
  padding: 0 24px 0;
  overflow-x: clip;
  /* flex:1 на прямом потомке body: заполняем высоту окна минус подвал (подвал снаружи обёртки из-за overflow-x) */
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
}
/* Footer CSS is deferred on the production guest path. Keep the session-only
   directory row hidden from the first frame even before that stylesheet applies. */
html.b2b-has-session .site-footer__dirs,
html[data-b2b-guest-session='0'] .site-footer__dirs,
body.is-logged-in .site-footer__dirs {
  display: none;
}
/* auth.css is runtime-only on a cold guest. Keep its dropdown in the native
   closed state until that stylesheet is restored; `.user-menu.open` in
   auth.css has higher specificity and remains the only visible state. */
.user-menu {
  display: none;
}
/* Application-only projects.css/cards.css are inert on the cold guest path.
   Keep the dormant spec toolbar (and its otherwise native-size SVG) out of the
   first frame; projects.js flips aria-hidden only after runtime CSS is ready. */
#spec-draft-toolbar-title[aria-hidden='true'] {
  display: none;
}
/* Application modal CSS is inert on the cold guest path. Keep every dormant,
   top-level surface out of the first frame; the original runtime `.open`
   rules have higher specificity and apply only after their CSS is ready. */
.chart-modal-overlay,
.cabinet-overlay,
.cconfirm-overlay,
.spec-name-modal,
.kp-modal,
.dist-overlay {
  display: none;
}

/* These overlays animate opacity/visibility instead of display. Fixed position
   removes their raw DOM from document flow before auth.css is restored. */
.auth-overlay,
.report-overlay {
  position: fixed;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* Cabinet panels intentionally stay rendered off-canvas for their transition.
   Mirror only the closed geometry; cabinet.css owns dimensions and visuals. */
.cabinet-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  transform: translateX(102%);
}
/* Переключатель "компактный/широкий" применяется только на десктопе:
   мобильную геометрию оставляем без изменений, чтобы не ломать адаптив.
   none не интерполируется — для анимации используем 100% (как dynamics: max-height). */
@media (min-width: 921px) {
  .page-wrapper {
    transition: max-width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  }
  html[data-layout-width="wide"] .page-wrapper {
    max-width: 100%;
  }
}
@media (min-width: 921px) and (prefers-reduced-motion: reduce) {
  .page-wrapper {
    transition: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .layout-width-trigger svg {
    transition: none;
  }
}

/* HEADER */
.header {
  display: flex; align-items: center; justify-content: space-between;
  height: 48px;
}
.header-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: var(--b2b-logo-margin-left, 15px);
}
.header-logo[data-b2b-home-nav="1"] {
  cursor: pointer;
}
.header-logo[data-b2b-home-nav="1"]:focus-visible {
  outline: 2px solid var(--accent, #4a9eff);
  outline-offset: 2px;
  border-radius: 6px;
}

/* Guest landing boot: до guest-landing.css — не показывать пустой каталог гостю */
html.guest-landing-boot #catalog-filter-bar,
html.guest-landing-boot #catalog-table-card,
html[data-b2b-guest-landing="pending"] #catalog-filter-bar,
html[data-b2b-guest-landing="pending"] #catalog-table-card {
  display: none !important;
}
html.guest-landing-boot .right-col > .catalog-search-dock,
html.guest-landing-boot .right-col > #search-kind-hint,
html[data-b2b-guest-landing="pending"] .right-col > .catalog-search-dock,
html[data-b2b-guest-landing="pending"] .right-col > #search-kind-hint {
  display: none !important;
}
html.guest-landing-boot #header-anomaly-title,
html[data-b2b-guest-landing="pending"] #header-anomaly-title {
  display: none !important;
}
html.guest-landing-boot .left-col,
html.guest-landing-boot .sidebar-divider,
html[data-b2b-guest-landing="pending"] .left-col,
html[data-b2b-guest-landing="pending"] .sidebar-divider {
  display: none !important;
}
html.guest-landing-boot #guest-landing,
html[data-b2b-guest-landing="pending"] #guest-landing {
  display: block !important;
}
/* guest-landing.css is requested dynamically by the synchronous boot script.
   The parser can reach the footer before that request finishes, so the blocking
   shell must already reserve one viewport and keep the raw footer below fold.
   The identical late rule remains in guest-landing.css as a split=0 fallback. */
html.guest-landing-boot #guest-landing {
  display: block !important;
  overflow-anchor: none;
  min-height: 100vh;
  min-height: 100dvh;
}
/* Здесь лежал второй резерв именно скелетона: min-height: min(50dvh, 420px) за
   :not([hidden]). Он не работал никогда, когда был нужен: [hidden] снимает
   syncGuestLandingBootDom по DOMContentLoaded, а тот в троттлинге наступает на
   23.6 с — на 7.7 с позже монтажа импла. А когда DOMContentLoaded успевал (тёплый
   быстрый путь), правило всё равно перекрывалось более специфичным
   html.guest-landing-boot #guest-landing #gl-boot-skeleton из guest-landing.css.
   Габарит самого скелетона живёт там; layout.css выше резервирует viewport
   на контейнере до приезда динамического CSS; см. test_guest_landing_pending_cls.py. */
.logo-icon-wrap {
  position: relative;
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
}
.logo-beta-badge {
  display: none;
  position: absolute;
  right: -2px;
  bottom: -1px;
  font-size: 11px;
  line-height: 1;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: #d32f2f;
  font-family: "Segoe Script", "Brush Script MT", "Apple Chancery", "Snell Roundhand", cursive;
  text-shadow: 0 0 1px rgba(255, 255, 255, 0.95), 0 1px 2px rgba(0, 0, 0, 0.18);
  pointer-events: none;
  transform: rotate(-7deg);
}
html[data-logo-beta="1"] .logo-beta-badge {
  display: block;
}
.logo-icon {
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  display: block;
  object-fit: contain;
}
.logo-text {
  position: relative;
  --b2b-header-wordmark-gradient: linear-gradient(
    96deg,
    #4a3614 0%,
    #6b4f1d 10%,
    #8a6a2f 18%,
    #a8823a 26%,
    #6b4f1d 34%,
    #c49a45 42%,
    #8a6a2f 50%,
    #a8823a 58%,
    #5a4018 66%,
    #b98f3e 74%,
    #8a6a2f 82%,
    #6b4f1d 90%,
    #4a3614 100%
  );
}
/* Delect.ru справа от лого: 1:1 с .gl-subnav__brand-text (лэндинг v3 Gold).
   Шрифт Manrope + кегль/трекинг/градиент как у бренда субнава. Высота .header = 48px. */
.logo-text .logo-title {
  display: inline-block;
  padding: 0;
  margin: 0;
  font-family: 'Manrope', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
    Roboto, Arial, sans-serif !important;
  font-size: clamp(19px, 2.2vw, 24px) !important;
  font-weight: 800 !important;
  font-style: normal !important;
  letter-spacing: -0.045em;
  line-height: 1;
  white-space: nowrap;
  /* Светлая тема: перелив тёмный (без #f6ead0/#f3dfa6) — не сливается с кремовым фоном. */
  background-image: var(--b2b-header-wordmark-gradient);
  background-size: 640% 100%;
  background-position: 0% 50%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent !important;
  -webkit-text-fill-color: transparent;
  animation: b2b-header-wordmark-flow 36s cubic-bezier(0.38, 0, 0.62, 1) infinite;
  filter: drop-shadow(0 1px 0 rgba(74, 54, 20, 0.18))
    drop-shadow(0 2px 8px rgba(36, 29, 18, 0.14));
}
/* Подзаголовок («Разумный выбор» и т.п.) в шапке больше не показываем —
   только Delect.ru с переливом справа от лого. Узел оставлен в DOM как <p>: до 19.08.2026
   это был <h1>, то есть СКРЫТЫЙ display:none заголовок — веса он не давал, а на скрытый
   текст в заголовке поисковики смотрят плохо. Единственный h1 главной — заголовок героя
   лендинга. */
.logo-text .logo-subtitle,
.header-logo .logo-subtitle {
  display: none !important;
}

/* Режим «только надпись»: прячем иконку, кегль как у бренда лэндинга */
html[data-b2b-header-wordmark="1"] .logo-icon-wrap {
  display: none !important;
}
html[data-b2b-header-wordmark="1"] .header-logo {
  gap: 0;
  margin-left: 0;
}
.logo-wordmark-geometric {
  display: none;
  width: 176px;
  aspect-ratio: 2220 / 188;
  flex: 0 0 auto;
  background-image: var(--b2b-header-wordmark-gradient);
  background-size: 640% 100%;
  background-position: 0% 50%;
  -webkit-mask: url('/assets/delect-wordmark-geometric.svg?v=20260825-geometric-wordmark3') center / contain no-repeat;
  mask: url('/assets/delect-wordmark-geometric.svg?v=20260825-geometric-wordmark3') center / contain no-repeat;
  animation: b2b-header-wordmark-flow 36s cubic-bezier(0.38, 0, 0.62, 1) infinite;
  filter: drop-shadow(0 1px 0 rgba(74, 54, 20, 0.18))
    drop-shadow(0 2px 8px rgba(36, 29, 18, 0.14));
}
html[data-b2b-header-wordmark="1"][data-b2b-header-wordmark-variant="geometric"] .logo-title {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  clip-path: inset(50%) !important;
  white-space: nowrap !important;
  border: 0 !important;
}
html[data-b2b-header-wordmark="1"][data-b2b-header-wordmark-variant="geometric"] .logo-wordmark-geometric {
  display: block;
}
[data-theme='dark'] .logo-text {
  --b2b-header-wordmark-gradient: linear-gradient(
    96deg,
    #8a6a2f 0%,
    #b98f3e 10%,
    #d4af5f 18%,
    #ecd393 24%,
    #b98f3e 32%,
    #f3dfa6 40%,
    #d4af5f 48%,
    #ecd393 56%,
    #b98f3e 64%,
    #f6ead0 72%,
    #c9a44f 80%,
    #ecd393 88%,
    #8a6a2f 100%
  );
}
@media (max-width: 600px) {
  .logo-wordmark-geometric {
    width: 142px;
  }
}
@media (max-width: 420px) {
  .logo-wordmark-geometric {
    width: 124px;
  }
}
@media (max-width: 1023px) {
  /* Как .gl-subnav__brand-text на лэндинге ≤1023 */
  .logo-text .logo-title {
    font-size: clamp(17px, 2vw, 21px) !important;
  }
}
@keyframes b2b-header-wordmark-flow {
  0%,
  100% {
    background-position: 0% 50%;
  }
  15% {
    background-position: 18% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  85% {
    background-position: 82% 50%;
  }
}
@media (prefers-reduced-motion: reduce) {
  .logo-text .logo-title,
  .logo-wordmark-geometric {
    animation: none;
    background-position: 42% 50%;
  }
}
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .logo-text .logo-title {
    color: #a8823a !important;
    -webkit-text-fill-color: #a8823a;
    background: none;
    filter: none;
  }
}

.header-controls {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  flex: 1 1 auto;
  justify-content: flex-end;
}
.header-welcome-slot {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding: 0 10px 0 0;
  pointer-events: none;
}
.header-welcome-msg {
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 12px;
  color: var(--text-secondary);
  opacity: 0;
  transform: translateX(4px);
  transition: opacity 0.45s ease, transform 0.45s ease;
}
.header-welcome-msg.is-visible {
  opacity: 1;
  transform: translateX(0);
}
@media (max-width: 920px) {
  .header-welcome-slot {
    display: none;
  }
}
.layout-width-trigger svg {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 16px;
  height: 16px;
  transform: translate(-50%, -50%);
  display: block;
  margin: 0;
  pointer-events: none;
  transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.layout-icon--collapse { opacity: 0; }
.layout-icon--expand { opacity: 1; }
html[data-layout-width="wide"] .layout-icon--expand { opacity: 0; }
html[data-layout-width="wide"] .layout-icon--collapse { opacity: 1; }
/* На телефонах и планшетах кнопку ширины не показываем */
@media (max-width: 920px) {
  .layout-width-trigger {
    display: none !important;
  }
}
/* Theme pill: circle trigger + drop-down slider */
.theme-wrap {
  position: relative;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Кнопка-триггер темы: база под Square; Circle / Glass переопределяют в themes.css и glass.css */
.theme-trigger {
  position: relative;
  width: 30px;
  height: 30px;
  display: block;
  line-height: 0;
  border: 0;
  background: none;
  cursor: pointer;
  border-radius: 4px;
  color: var(--header-icon);
  padding: 0;
  transition: background 0.18s, color 0.18s, border-radius 0.2s ease;
  -webkit-tap-highlight-color: transparent;
  appearance: none;
  -webkit-appearance: none;
}
.theme-trigger::-moz-focus-inner {
  border: 0;
  padding: 0;
}
.theme-trigger:hover { background: rgba(128,128,128,0.12); color: var(--header-icon-active); }
/* Триггер темы: геометрический центр; слайдер — .theme-panel (--header-icon-optical) */
.theme-trigger svg {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 16px;
  height: 16px;
  transform: translate(-50%, -50%);
  display: block;
  margin: 0;
  pointer-events: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
/* Раскрывающаяся панель: внешняя рамка; внутри только смена цвета иконки при hover (без подложки) */
.theme-panel {
  position: absolute;
  top: 50%;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  background: var(--dropdown-bg);
  border: 1px solid var(--card-border);
  border-radius: 4px;
  box-shadow: var(--dropdown-shadow);
  /* Только ячейки слайдера — лёгкая подгонка визуального центра штриха */
  --header-icon-optical: 0.5px;
  --theme-panel-pad: 2px;
  --theme-panel-slot: 30px;
  --theme-panel-inner-gap: 2px;
  padding: 0;
  z-index: 300;
  width: 30px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-50%);
  box-sizing: border-box;
  transition:
    width 0.3s cubic-bezier(0.22, 1, 0.36, 1),
    opacity 0.22s ease,
    box-shadow 0.22s ease;
}
.theme-panel.open {
  overflow: visible;
  padding: var(--theme-panel-pad);
  justify-content: center;
  /* border-box: +2px под левую и правую обводку (1px), иначе ряд кнопок сжимается */
  width: calc(
    2 * var(--theme-panel-pad) + 3 * var(--theme-panel-slot) + 2 * var(--theme-panel-inner-gap) + 2px
  );
  opacity: 1;
  pointer-events: auto;
}
/* Фиксированный порядок: светлая | тёмная | авто — ряд по центру капсулы */
.theme-panel__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--theme-panel-inner-gap);
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  flex-shrink: 0;
}
.theme-panel__btn {
  box-sizing: border-box;
  width: var(--theme-panel-slot);
  height: var(--theme-panel-slot);
  flex-shrink: 0;
  margin: 0;
  padding: 0;
  border: 0;
  display: block;
  line-height: 0;
  cursor: pointer;
  border-radius: 4px;
  background: none;
  color: var(--header-icon);
  position: relative;
  transition: color 0.18s ease, border-radius 0.2s ease;
  -webkit-tap-highlight-color: transparent;
  appearance: none;
  -webkit-appearance: none;
}
.theme-panel__btn::-moz-focus-inner {
  border: 0;
  padding: 0;
}
.theme-panel__btn svg {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 16px;
  height: 16px;
  transform: translate(
    calc(-50% + var(--header-icon-optical)),
    calc(-50% + var(--header-icon-optical))
  );
  display: block;
  margin: 0;
  pointer-events: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  overflow: visible;
}
.theme-panel__btn:hover:not(.active) {
  background: none;
  color: var(--header-icon-active);
}
.theme-panel__btn.active {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 0 0 1px var(--card-border);
  z-index: 1;
}
.theme-panel__btn.active:hover {
  background: var(--accent-hover, var(--accent));
  color: #fff;
  box-shadow: 0 0 0 1px var(--card-border);
}

/* MAIN — заполняет высоту между шапкой и низом page-wrapper, чтобы пунктир разделителя тянулся до подвала */
.page-main {
  flex: 1 1 auto;
  /* min-content: при длинной левой колонке блок растёт вместе с контентом (иначе min-height:0 + 1fr режут пунктир по высоте вьюпорта) */
  min-height: min-content;
  display: flex;
  flex-direction: column;
  /* Как зазор у нижнего конца пунктирного разделителя (.sidebar-divider::before) — до подвала */
  padding-bottom: var(--sidebar-dash-bottom-gap, 14px);
  box-sizing: border-box;
}
/* Direct catalog/session paints may precede results. Keep the footer below the
   viewport so inserting the first result set cannot shift the whole page. */
html[data-b2b-application-intent="1"] .page-main {
  min-height: calc(100vh - 52px);
  min-height: calc(100dvh - 52px);
}

/* MAIN GRID */
@property --b2b-sidebar-w {
  syntax: '<length>';
  inherits: true;
  initial-value: 320px;
}
.main-grid {
  --b2b-sidebar-w: 320px;
  display: grid;
  /* Желоб общий с шириной .header-logo (молния «Часто ищут» над лупой) */
  grid-template-columns: var(--b2b-sidebar-w) var(--b2b-main-gutter, 20px) minmax(0, 1fr);
  gap: 0;
  align-items: start;
}
/* На десктопе строка грида не короче контента левой колонки и тянется на всю .page-main при коротком контенте */
@media (min-width: 921px) {
  .main-grid {
    align-items: stretch;
    grid-template-rows: minmax(min-content, 1fr);
    /* flex: 1 даёт flex-basis: 0 — при длинном каталоге блок не обязан расти по контенту так же предсказуемо; 1 1 auto + min-height оставляют скролл окну и дают sticky работать от viewport. */
    flex: 1 1 auto;
    min-height: min-content;
  }
}
.left-col { display: flex; flex-direction: column; gap: 16px; }

/* CARD */
