/* ПОРЯДОК ЭТИХ ДВУХ СТРОК ЗНАЧИМ И ПРОВЕРЯЕТСЯ СТОРОЖЕМ.
   Барьер от протекания стилей модуля работает тем, что стоит в каскаде РАНЬШЕ
   правил-владельцев формы: он бьёт чужие правила нулевой специфичности и уступает
   собственным правилам Ядра той же специфичности, объявленным после него. Поэтому
   первым идёт барьер, вторым — файл-владелец формы и порядка правого кластера (его
   же подключают напрямую страницы, у которых общего хедера нет), и только затем
   правила этого файла. @import обязан стоять до правил. */
@import url("header-barrier.css");
@import url("chrome-cluster.css");
/* ======================================================================
   Единый хедер подпрограмм Raschet.
   Подключается в каждой подпрограмме через <link rel="stylesheet"
   href="../shared/app-header.css">. Высота — токен --ge-header-h,
   отступы фиксированные. Левая часть: home-иконка + «Raschet» + название подпрограммы.

   Цвет — через ЦЕНТРАЛЬНЫЕ токены семейства (var(--ge-color-*, <светлый-fallback>)):
   светлая тема берёт значения из :root (suite-theme.css), тёмная — из
   :root[data-theme="dark"] (themes/dark/dark.css). Поэтому общий хром следует за
   единым бренд-зерном, а отдельный dark-оверрайд не нужен. Fallback в var() = текущий
   светлый hex (страховка, если токен не подгружен). Сплошные заливки с белым текстом
   (sync-кнопка) и категориальная палитра plan-бейджей — намеренно фикс. hex.
   ====================================================================== */
/* ── Декларативный каркас (Фаза 1, карта 1478) ─────────────────────────────
   <suite-header> — обёртка-якорь: сам тег не участвует в layout (contents),
   хедер внутри ведёт себя как прямой ребёнок body (sticky работает как раньше). */
suite-header { display: contents; }
/* Барьер от протекания CSS модуля живёт в header-barrier.css и подключён ПЕРВЫМ
   импортом этого файла. Здесь его нет намеренно: правило работает своим местом в
   каскаде, а объявление на прежнем месте — после файла-владельца формы — сносило
   раскладку самого Ядра. Разбор и требование к порядку — в том файле. */
.rs-header {
  position: sticky;
  top: 0;
  z-index: 9990;
  flex: none;
  /* Высота шапки — ВХОДНОЙ токен центральной темы, а не литерал. Литерал здесь означал
     второго писателя: светлая тема объявляла ту же высоту через токен (48px), тёмная не
     объявляла ничего — и шапка отличалась размером от темы к теме. Запасное значение равно
     объявленному в suite-theme.css: страница без файла токенов получает ту же высоту. */
  height: var(--ge-header-h, 48px);
  /* Размер считаем ПО ГРАНИЦЕ: токен должен равняться высоте, которую шапка
     реально занимает. При размере по содержимому нижняя граница добавлялась
     сверх токена, шапка занимала на пиксель больше — и любая поверхность,
     отступившая ровно на токен (навигационный рельс, выезжающая панель), села
     бы на эту границу и подрезала линию шапки: слева линии нет, справа есть
     (замечание владельца 28.07). Один факт — одно число. */
  box-sizing: border-box;
  background: var(--ge-color-surface, #fff);
  border-bottom: 1px solid var(--ge-color-border, #edebe9);
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Слева шапка отступает НЕ произвольным полем, а ровно так, чтобы кнопка запуска продуктов
     встала в ту же колонку, что значки свёрнутого рельса под ней (замечание владельца 28.07:
     «вафля не выровнена по иконкам меню сайдбара»). Колонку задаёт рельс шириной своей
     свёрнутой полосы (--gus-mini-w), ширину зоны органа — владелец ряда (--rs-zone-h): половина
     разницы и есть поле, при котором ЦЕНТРЫ совпадают. Литерал здесь был третьим числом,
     не связанным ни с полосой, ни с органом, — потому и расходился. Запасные значения равны
     объявленным у владельцев. */
  padding: 0 24px 0 calc((var(--gus-mini-w, 56px) - var(--rs-zone-h, 48px)) / 2);
  /* Шрифт шапки — тоже через токен семейства: тема меняет НАБОРНУЮ ГАРНИТУРУ в одном месте,
     не переобъявляя правил хрома. Запасное значение — прежний стек. */
  font-family: var(--ge-font-family, -apple-system, "Segoe UI", Roboto, sans-serif);
  color: var(--ge-color-text, #201f1e);
  -webkit-font-smoothing: antialiased;
}
/* Нижний padding-bottom управляет suite-footer.js (52px для fixed-футера).
   Здесь только базовый reset, без отступа — иначе race condition: app-header.css
   подключается синхронно в <head>, suite-footer.js инжектится позже и перезаписывает
   значение → визуальное «слетание». */
body { margin: 0; box-sizing: border-box; }
/* Полоса под шапкой — ЕДИНСТВЕННОЕ место для строк состояния (активный проект, локальный
   расчёт, истечение подписки). Живёт на уровне body сразу за хедером, поэтому сдвиг контента,
   который рельс применяет к контейнеру продукта (data-push), её не задевает — читаем занятую
   рельсом ширину из его токена --gus-push (пишет рельс, см. applyPush). Нет рельса — 0px и
   полная ширина. Полосы кладём В контейнер, а не рядом с хедером поштучно: у места ровно один
   владелец, и порядок строк не зависит от того, кто смонтировался раньше. */
.rs-underbar {
  margin-left: var(--gus-push, 0px);
}
/* Левая зона шапки занимает ровно полосу рельса, поэтому строка поиска начинается там же,
   где начинается СОДЕРЖИМОЕ страницы. Прежде три органа шапки стояли островами (бренд у
   левого края, поиск в середине окна, кластер у правого), и на широком экране шапка читалась
   разорванной — она не соглашалась ни с рельсом, ни с содержимым (замечание Владельца 30.07).
   Полосу знает рельс и публикует токеном --gus-push; вычитаем собственное поле шапки, чтобы
   сумма дала ровно край содержимого. Нет рельса (или он оверлеем) — 0px, и зона остаётся по
   содержимому: правило само себя выключает там, где полосы нет. */
.rs-header-left {
  display: flex;
  align-items: center;
  gap: 12px;
  /* ЗОНА БЕЗ ОБЪЯВЛЕННОЙ ПОЛОСЫ РАВНА СВОЕМУ СОДЕРЖИМОМУ, А НЕ НУЛЮ (правка 30.07, карта 2513855).
     Прежняя редакция считала основу зоны из --gus-push всегда, а полосу публикует рельс из
     сценария. До его исполнения токена нет, запасное значение 0px давало основу 0 — и зона
     получала не «собственное содержимое», как утверждала прежняя запись, а АВТОМАТИЧЕСКИЙ
     МИНИМУМ flex-элемента, то есть min-content. Для текста min-content — это самое широкое
     СЛОВО, а не строка: имя платформы разрывалось по дефису, шапка вставала в две строки и
     схлопывалась в одну, когда рельс наконец публиковал полосу. Отсюда наблюдение Пользователя
     «при перезагрузке две строки, потом проходит — но не всегда»: в режимах без полосы
     (canvas, оверлей) рельс её не объявляет, и две строки остаются навсегда.
     Запасное значение токена и было вторым писателем факта: оно давало раскладку ДО того, как
     владелец успел сказать своё слово. Поэтому основа из полосы применяется НИЖЕ и только при
     признаке рельса — единственного, кто полосу знает. */
  flex: 0 1 auto;
}
/* Полосу применяем, когда её владелец объявился: признак ставит сам рельс (applyPush), одним
   шагом с присвоением. Нет рельса, оверлейный режим, сценарий ещё не исполнен — зона остаётся
   по содержимому, и промежуточной раскладки не существует вовсе. */
:root[data-gus-rail="live"] .rs-header-left {
  flex-basis: max(0px, calc(var(--gus-push, 0px) - (var(--gus-mini-w, 56px) - var(--rs-zone-h, 48px)) / 2));
}
/* Раскладку, форму и порядок правого кластера (.rs-header-right, .rs-slot, .rs-icon-btn)
   задаёт chrome-cluster.css — файл-владелец, подключённый импортом выше. Здесь их нет
   намеренно: второе объявление тех же правил и разводило продукты по разным видам. */
/* «Глупая шапка» G-Search: центральная строка глобального поиска (MS365-style).
   Ядро не ищет само — по Enter редирект на портал. flex:0 1 — ужимается при нехватке. */
.rs-header-search {
  flex: 0 1 460px;
  display: flex;
  align-items: center;
  gap: 8px;
  height: var(--rs-ctl-h, 34px);
  margin: 0 16px;
  padding: 0 10px;
  border: 1px solid var(--ge-color-border, #edebe9);
  border-radius: var(--rs-fld-r, 8px);
  background: var(--rs-bg-soft, #f4f6fa);
  transition: border-color .15s, background .15s, box-shadow .15s;
  min-width: 0;
}
.rs-header-search:focus-within {
  background: var(--ge-color-surface, #fff);
  border-color: var(--ge-color-brand, #4f46e5);
  box-shadow: 0 0 0 3px var(--ge-color-brand-soft, rgba(80, 120, 200, .14));
}
.rs-gsearch-ic { display: inline-flex; align-items: center; color: var(--ge-color-text-mute, #605e5c); flex: none; }
.rs-gsearch-ic svg { width: 17px; height: 17px; }
.rs-gsearch-input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font: inherit;
  font-size: 14px;
  color: var(--ge-color-text, #201f1e);
  padding: 0;
}
.rs-gsearch-input::placeholder { color: var(--ge-color-text-faint, #726f6d); }
/* нативный «крестик» очистки скрываем — единый вид во всех браузерах */
.rs-gsearch-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.rs-gsearch-kbd {
  flex: none;
  font: 600 11px/1 -apple-system, "Segoe UI", Roboto, sans-serif;
  color: var(--ge-color-text-mute, #605e5c);
  background: var(--ge-color-surface, #fff);
  border: 1px solid var(--ge-color-border, #edebe9);
  border-radius: 5px;
  padding: 3px 6px;
  letter-spacing: .3px;
}
.rs-header-search:focus-within .rs-gsearch-kbd { display: none; }
/* На узких экранах строка мешает — прячем (поиск доступен на портале/по Ctrl+K нет смысла без строки). */
@media (max-width: 900px) {
  .rs-header-search { display: none; }
}
/* Канон Suite: вафля-переключатель продуктов крайней слева. Пуста (switcher не
   загрузился / не сконфигурирован) — не занимает место (без фантомного gap). */
.rs-suite-switch { display: inline-flex; align-items: center; }
.rs-suite-switch:empty { display: none; }

/* Дом — орган только со значком, значит круг той же высоты, что весь ряд
   (правило формы и токен высоты — chrome-cluster.css, импорт в начале файла). */
.rs-home-btn {
  width: var(--rs-ctl-h, 34px);
  height: var(--rs-ctl-h, 34px);
  border: 1px solid var(--ge-color-border, #edebe9);
  border-radius: 50%;
  background: var(--rs-bg-soft, #fff);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ge-color-text-mute, #605e5c);
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.rs-home-btn:hover {
  background: var(--rs-bg-hover, #f5f7fa);
  border-color: var(--ge-color-brand, #4f46e5);
  color: var(--ge-color-brand, #4f46e5);
}
.rs-home-btn svg { width: 20px; height: 20px; }

/* #9: селектор рабочего пространства (#wsxSpace) — на месте удалённой локальной вафли
   (4 квадрата). Наполняется suite-spaces.js теми же пространствами, что Хаб/рабочее место;
   при единственном доступном пространстве компонент сам прячет его (обычный режим модуля). */
.rs-space-select {
  height: var(--rs-ctl-h, 34px);
  max-width: 240px;
  padding: 0 30px 0 12px;
  border: 1px solid var(--ge-color-border, #edebe9);
  border-radius: var(--rs-fld-r, 8px);
  background-color: var(--rs-bg-soft, #fff);
  color: var(--ge-color-text, #201f1e);
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  background-size: 15px;
  transition: background-color 0.15s, border-color 0.15s;
}
.rs-space-select:hover { background-color: var(--rs-bg-hover, #f5f7fa); border-color: var(--ge-color-brand, #4f46e5); }
.rs-space-select:focus-visible { outline: 2px solid var(--ge-color-brand, #4f46e5); outline-offset: 2px; }

.rs-brand {
  font-size: 18px;
  font-weight: 700;
  color: var(--ge-color-text, #201f1e);
  letter-spacing: 0.3px;
  /* ИМЯ ПЛАТФОРМЫ — ОДНА СТРОКА (правка 30.07, карта 2513855). Правило коробки выше убирает
     промежуточную раскладку, но не отвечает за узкое окно: зона шапки ужимаема по замыслу, и
     при нехватке места её нижний предел — min-content, то есть самое широкое СЛОВО. Имя с
     дефисом («G-Suite», «G-TechHub») на этом пределе разрывается, и шапка растёт вверх-вниз —
     тот же дефект, что при холодной загрузке, только вызванный шириной окна.
     Ужимание здесь НЕ прячет переполнение: строка усекается многоточием, полный текст остаётся
     доступен подсказкой узла (title ставит app-header.js), а зона имени — ужимаемый элемент,
     поэтому ей нужен нулевой пол, иначе усечение не наступает вовсе. Высота шапки при этом
     остаётся токеном и здесь не объявляется: фиксированной высотой этот дефект не лечится. */
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rs-version {
  font-size: 11px;
  color: var(--ge-color-text-faint, #726f6d);
  font-weight: 400;
  margin-left: 6px;
}

/* ===== Кнопки справа =====
   Форма кнопки-глифа (.rs-icon-btn) объявлена ТОЛЬКО в chrome-cluster.css. Здесь стояло
   второе её объявление — прямоугольник 36px со скруглением 8px, — и оно, будучи ниже по
   файлу, выигрывало у круга: на каждой странице, подключавшей этот файл, кластер выходил
   скруглёнными квадратами (репорт Пользователя 2026-07-28). */

.rs-auth-widget { display: inline-flex; align-items: center; }

.rs-user-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px 4px 4px;
  border: 1px solid var(--ge-color-border, #edebe9);
  border-radius: 20px;
  background: var(--rs-bg-soft, #f5f7fa);
  cursor: pointer;
  transition: background 0.15s;
}
.rs-user-chip:hover { background: var(--rs-bg-hover, #e8eef5); }
.rs-user-photo {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--ge-color-border, #edebe9);
}
.rs-user-name {
  font-size: 13px;
  color: var(--ge-color-text, #201f1e);
  font-weight: 500;
  max-width: 160px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ===== v0.59.342: back-кнопка и project-badge ===== */
.rs-back-btn {
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding: 0 12px;
  border: 1px solid var(--ge-color-border, #edebe9);
  border-radius: 8px;
  background: var(--rs-bg-soft, #fff);
  color: var(--ge-color-text-mute, #605e5c);
  cursor: pointer;
  font-size: 12px;
  font-family: inherit;
  font-weight: 500;
  white-space: nowrap;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  margin-left: 4px;
}
.rs-back-btn:hover {
  background: var(--rs-bg-hover, #f1f5f9);
  border-color: var(--ge-color-brand, #4f46e5);
  color: var(--ge-color-brand, #4f46e5);
}
/* project-badge: брендовый soft-чип (следует за зерном в обеих темах). */
.rs-proj-badge {
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding: 0 12px;
  border: 1px solid color-mix(in srgb, var(--ge-color-brand, #4f46e5) 30%, transparent);
  border-radius: 16px;
  background: var(--ge-color-brand-soft, #eef2ff);
  color: var(--ge-color-brand, #4f46e5);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  max-width: 280px;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background 0.15s, border-color 0.15s;
}
.rs-proj-badge:hover {
  background: color-mix(in srgb, var(--ge-color-brand, #4f46e5) 16%, var(--ge-color-surface, #fff));
  border-color: color-mix(in srgb, var(--ge-color-brand, #4f46e5) 45%, transparent);
}
/* v0.60.103: standalone-режим (модуль запущен напрямую без ?project=).
   Предупреждающий (warn) soft-чип, чтобы визуально отличить от привычного
   брендового «через ссылку из /projects/». При клике — меню переключения/создания. */
.rs-proj-badge.rs-proj-badge-standalone {
  background: #fef3c7;
  border-color: color-mix(in srgb, var(--ge-color-warn, #b45309) 30%, transparent);
  color: var(--ge-color-warn, #b45309);
  cursor: pointer;
}
.rs-proj-badge.rs-proj-badge-standalone:hover {
  background: color-mix(in srgb, var(--ge-color-warn, #b45309) 22%, var(--ge-color-surface, #fff));
  border-color: color-mix(in srgb, var(--ge-color-warn, #b45309) 45%, transparent);
}
/* Нет активного проекта вообще (после очистки LS / первой загрузки) — error soft-чип. */
.rs-proj-badge.rs-proj-badge-empty {
  background: var(--ge-color-err-bg, #fde7e9);
  border-color: color-mix(in srgb, var(--ge-color-err, #b91c1c) 30%, transparent);
  color: var(--ge-color-err, #b91c1c);
  cursor: pointer;
}
.rs-proj-badge.rs-proj-badge-empty:hover {
  background: color-mix(in srgb, var(--ge-color-err, #b91c1c) 22%, var(--ge-color-surface, #fff));
  border-color: color-mix(in srgb, var(--ge-color-err, #b91c1c) 45%, transparent);
}
/* button-стиль для бейджей. Раньше были <span>, теперь <button>. */
button.rs-proj-badge {
  font-family: inherit;
  cursor: pointer;
}

/* v0.60.137: plan-badge — текущий план подписки в шапке.
   Click → global-settings → секция «Подписка».
   Категориальная палитра по плану (free/starter/pro/enterprise/trial/internal) —
   намеренно фикс. hex: 6 различимых тиров не сводятся к 4 семантическим токенам без
   потери различия. Это мягкие чипы (светлый фон + тёмный текст), читаемы и на тёмном холсте. */
.rs-plan-badge {
  font-family: inherit;
  cursor: pointer;
  padding: 4px 10px;
  border-radius: 12px;
  font-size: 11.5px;
  font-weight: 600;
  border: 1px solid;
  margin-right: 6px;
  transition: all 0.15s;
  white-space: nowrap;
}
.rs-plan-badge.rs-plan-free {
  background: var(--ge-color-surface-2, #faf9f8);
  color: var(--ge-color-text-mute, #605e5c);
  border-color: var(--ge-color-border-strong, #d2d0ce);
}
.rs-plan-badge.rs-plan-free:hover { background: #e5e7eb; }
/* Истёкшая подписка: план читается, но состояние видно сразу — иначе «Enterprise»
   в шапке выглядит как действующий доступ, хотя срок вышел. */
.rs-plan-badge.rs-plan-expired {
  background: #fef3c7;
  color: var(--ge-color-warn, #b45309);
  border-color: var(--ge-color-warn, #b45309);
}
.rs-plan-badge.rs-plan-starter {
  background: var(--ge-color-info-bg, #ddf4ff);
  color: var(--ge-color-info, #0969da);
  border-color: var(--ge-color-info, #0969da);
}
.rs-plan-badge.rs-plan-starter:hover { background: #bfdbfe; }
.rs-plan-badge.rs-plan-pro {
  background: #fef3c7;
  color: var(--ge-color-warn, #b45309);
  border-color: var(--ge-color-warn, #b45309);
}
.rs-plan-badge.rs-plan-pro:hover { background: #fde68a; }
.rs-plan-badge.rs-plan-enterprise {
  background: var(--ge-color-ok-bg, #dafbe1);
  color: var(--ge-color-ok, #15803d);
  border-color: var(--ge-color-ok, #15803d);
}
.rs-plan-badge.rs-plan-enterprise:hover { background: #a7f3d0; }
.rs-plan-badge.rs-plan-trial {
  background: #fef3c7;
  color: var(--ge-color-warn, #b45309);
  border-color: var(--ge-color-warn, #b45309);
  animation: rs-plan-trial-pulse 2.5s infinite;
}
.rs-plan-badge.rs-plan-trial:hover { background: #fed7aa; }
@keyframes rs-plan-trial-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(253, 186, 116, 0); }
  50% { box-shadow: 0 0 0 4px rgba(253, 186, 116, 0.3); }
}
.rs-plan-badge.rs-plan-internal {
  background: #ede9fe;
  color: #6d28d9;
  border-color: #c4b5fd;
}

/* v0.60.872: org-name chip — имя организации справа в шапке
   (паттерн MS 365). Для админов компании/системы кликабелен →
   управление организацией; для обычных членов — пассивный лейбл.
   Брендовый soft-чип (как project-badge) — следует за зерном. */
.rs-org-badge {
  font-family: inherit;
  padding: 4px 10px;
  border-radius: 12px;
  font-size: 11.5px;
  font-weight: 600;
  border: 1px solid color-mix(in srgb, var(--ge-color-brand, #4f46e5) 30%, transparent);
  background: var(--ge-color-brand-soft, #eef2ff);
  color: var(--ge-color-brand, #4f46e5);
  margin-right: 6px;
  transition: background .15s, border-color .15s;
  white-space: nowrap;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rs-org-badge:hover { background: color-mix(in srgb, var(--ge-color-brand, #4f46e5) 16%, var(--ge-color-surface, #fff)); border-color: color-mix(in srgb, var(--ge-color-brand, #4f46e5) 45%, transparent); }
.rs-org-badge[data-passive="1"] { cursor: default; }
.rs-org-badge[data-passive="1"]:hover { background: var(--ge-color-brand-soft, #eef2ff); border-color: color-mix(in srgb, var(--ge-color-brand, #4f46e5) 30%, transparent); }
.rs-plan-badge.rs-plan-internal:hover { background: #ddd6fe; }

/* v0.59.780: storage-mode badge & modal */
.rs-storage-mode-btn {
  border: 1px solid var(--ge-color-border, #edebe9);
  background: var(--rs-bg-soft, #f9fafb);
  color: var(--ge-color-text-mute, #605e5c);
  border-radius: 4px;
  padding: 5px 10px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s;
  white-space: nowrap;
}
.rs-storage-mode-btn:hover { background: var(--rs-bg-hover, #f3f4f6); border-color: var(--ge-color-border-strong, #d2d0ce); }
.rs-storage-mode-btn.rs-storage-cloud {
  background: var(--ge-color-info-bg, #ddf4ff);
  color: var(--ge-color-info, #0969da);
  border-color: color-mix(in srgb, var(--ge-color-info, #0969da) 35%, transparent);
}
.rs-storage-mode-btn.rs-storage-cloud:hover { background: color-mix(in srgb, var(--ge-color-info, #0969da) 20%, var(--ge-color-surface, #fff)); }
.rs-storage-mode-btn.rs-storage-local {
  background: #fef3c7;
  color: var(--ge-color-warn, #b45309);
  border-color: color-mix(in srgb, var(--ge-color-warn, #b45309) 35%, transparent);
}
.rs-storage-mode-btn.rs-storage-local:hover { background: color-mix(in srgb, var(--ge-color-warn, #b45309) 20%, var(--ge-color-surface, #fff)); }

.rs-storage-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
.rs-storage-modal {
  background: var(--ge-color-surface, #fff);
  border-radius: 8px;
  width: min(560px, 92vw);
  max-height: 88vh;
  overflow-y: auto;
  box-shadow: var(--ge-shadow-pop, 0 12px 40px rgba(0, 0, 0, 0.2));
}
.rs-storage-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--ge-color-border, #edebe9);
}
.rs-storage-modal-head h3 { margin: 0; font-size: 16px; color: var(--ge-color-text, #201f1e); }
.rs-storage-modal-close {
  background: none;
  border: none;
  font-size: 22px;
  color: var(--ge-color-text-mute, #605e5c);
  cursor: pointer;
  padding: 0 4px;
}
.rs-storage-modal-close:hover { color: var(--ge-color-text, #201f1e); }
.rs-storage-modal-body { padding: 16px 18px; display: flex; flex-direction: column; gap: 16px; }
.rs-storage-status {
  background: var(--rs-bg-soft, #f9fafb);
  border: 1px solid var(--ge-color-border, #edebe9);
  border-radius: 5px;
  padding: 10px 12px;
  font-size: 13px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.rs-storage-status .rs-mode-cloud { color: var(--ge-color-info, #0969da); font-weight: 600; }
.rs-storage-status .rs-mode-local { color: var(--ge-color-warn, #b45309); font-weight: 600; }
.rs-storage-modes {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.rs-storage-mode-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border: 1.5px solid var(--ge-color-border, #edebe9);
  border-radius: 5px;
  cursor: pointer;
  transition: all 0.15s;
}
.rs-storage-mode-row:hover { border-color: var(--ge-color-brand, #93c5fd); background: var(--ge-color-hover, #f3f2f1); }
.rs-storage-mode-row.selected {
  border-color: var(--ge-color-brand, #4f46e5);
  background: var(--ge-color-brand-soft, #eef2ff);
}
.rs-storage-mode-row.disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}
.rs-storage-mode-row input { margin-top: 3px; }
.rs-storage-mode-name { font-weight: 600; font-size: 13.5px; color: var(--ge-color-text, #201f1e); margin-bottom: 2px; }
.rs-storage-mode-desc { font-size: 11.5px; color: var(--ge-color-text-mute, #605e5c); line-height: 1.4; }
.rs-storage-sync {
  border-top: 1px solid var(--ge-color-border, #edebe9);
  padding-top: 14px;
}
.rs-storage-sync h4 { margin: 0 0 6px; font-size: 13px; color: var(--ge-color-text-mute, #605e5c); text-transform: uppercase; letter-spacing: 0.4px; }
.rs-storage-sync p { margin: 0 0 10px; font-size: 11.5px; }
.rs-storage-sync-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
/* Сплошная заливка с белым текстом — фикс. бренд-hex (в тёмной теме осветлённый
   токен под белым текстом провалил бы контраст; см. dark.css правило primary-кнопок). */
.rs-storage-sync-actions button {
  padding: 7px 14px;
  border: 1px solid #4f46e5;
  background: #4f46e5;
  color: var(--ge-color-on-fill, #ffffff);
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
  font-weight: 500;
}
.rs-storage-sync-actions button:hover:not(:disabled) { background: #4338ca; }
.rs-storage-sync-actions button:disabled {
  background: #9ca3af;
  border-color: var(--ge-color-border-strong, #d2d0ce);
  cursor: not-allowed;
}
.rs-storage-sync-result {
  margin-top: 8px;
  font-size: 11.5px;
}

/* ── Полосы прокрутки: ОДИН вид на всё семейство ───────────────────────────────
   Вид полосы прокрутки — факт семейства, и до сих пор у него не было владельца:
   каждый, кому системная полоса мешала, объявлял свою (консоль администратора 6px,
   дизайн-система проектов 8px, портал разработки и управление 10px, две расчётные
   поверхности 10px со своим цветом), а на всех прочих поверхностях не объявлял никто —
   там оставался системный вид. Владелец объявлен здесь: этот файл подключает каждая
   страница семейства с домена Ядра, поэтому одна выкладка меняет вид во всех продуктах,
   не трогая их код.

   Цвет — ТОЛЬКО из палитры темы: ползунок в покое — усиленная граница, под указателем —
   приглушённый текст. Обе пары объявлены и светлой, и тёмной, поэтому вид следует теме
   без второго объявления. Запасное значение в var() равно объявленному в файле токенов
   (канон этого файла): страница, до которой тема не доехала, получает то же самое.

   Firefox: scrollbar-width/scrollbar-color объявлены на КОРНЕ, а не на «*». Оба свойства
   наследуемые — корень раздаёт их всему дереву и оставляет поддереву право объявить своё;
   «*» это право отнимает, и любая поверхность со своим видом полосы перестала бы им
   управлять. Прокрутку по горизонтали и стабильную колею (scrollbar-gutter) правило не
   касается: это раскладка, у неё свой владелец. */
:root {
  scrollbar-width: thin;
  scrollbar-color: var(--ge-color-border-strong, #d2d0ce) transparent;
}
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
::-webkit-scrollbar-track,
::-webkit-scrollbar-corner {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: var(--ge-color-border-strong, #d2d0ce);
  border-radius: var(--ge-radius-pill, 999px);
}
::-webkit-scrollbar-thumb:hover {
  background: var(--ge-color-text-faint, #726f6d);
}

/* ── Тема: общий хром следует центральным токенам (--ge-color-* / --rs-*) ───────
   База выше объявлена через var(--ge-color-*, <светлый-fallback>): светлая берёт
   значения из :root (suite-theme.css), тёмная — из :root[data-theme="dark"]
   (themes/dark/dark.css). Отдельный dark-оверрайд-блок удалён — он дублировал карту
   токенов. Смена бренд-зерна перекрашивает хедер/вафлю в обеих темах согласованно. */

/* ======================================================================
   ШАПКА РАЗДЕЛА — заголовок на одном месте, под ним ПАНЕЛЬ КОМАНД.
   Владелец вида на всё семейство (образец — центр администрирования).

   Узел один и тот же в каждом продукте: заголовок раздела плюс кнопки
   добавления и управления записями. Реализаций было ШЕСТНАДЦАТЬ — по числу
   продуктов, каждая со своим именем класса и своим «заголовок слева, кнопки
   справа». Отсюда и разный вид: заголовок прыгал по вертикали от наличия
   кнопки, кнопки стояли обведёнными коробками у правого края (замечание
   владельца 28.07: «убери эти ужасные кнопки по всей платформе»).

   Здесь объявлен ОДИН вид: заголовок занимает свою строку, все органы
   раздела переносятся под него и образуют панель команд от левого края,
   без рамок и заливок, с плашкой при наведении.

   Реестр имён — это имена ОДНОГО узла в разных продуктах, а не разные узлы.
   Головы ВЫЕЗЖАЮЩИХ панелей, МОДАЛЬНЫХ пикеров, сайдбаров, КАРТОЧЕК и секций меню
   в реестр НЕ входят: там заголовок и
   кнопка закрытия по краям — правильная раскладка, и трогать её нельзя.

   РОЛЬ ВМЕСТО ИМЕНИ (28.07, доведено 30.07). Реестр чужих имён не масштабируется и,
   что важнее, НЕ ЗНАЧИТ НИЧЕГО: имя обёртки в чужом продукте не говорит, что за узел
   под ним. Реестр и собирался поиском подстроки «-head» по семейству — то есть ровно
   тем способом, который здесь же объявлен ошибкой. Разбор 30.07: из тринадцати чужих
   имён шапкой раздела оказались ЧЕТЫРЕ; семь были другим узлом (голова модального
   окна и карточки, полоса фильтров, строка состояния, заголовок маркетингового блока
   в предпросмотре редактора сайтов), а два не встречались НИ НА ОДНОЙ странице,
   грузящей этот файл, — они жили в отдельных витринах со своей сборкой.

   Поэтому здесь называются ТОЛЬКО собственные имена платформы, а поверхность продукта
   объявляет свою РОЛЬ атрибутом и вид получает отсюда:
     data-ge-cmdbar="head" — ШАПКА РАЗДЕЛА: заголовок занимает строку, органы под ним;
     data-ge-cmdbar="bar"  — ПОЛОСА ИНСТРУМЕНТА: своя подложка и своя раскладка
                             остаются продукту, общей становится только ФОРМА органа.
   Роль объявляет тот, кто знает узел, — сам продукт; общий хром чужого пространства
   имён не знает и знать не может. Голова МОДАЛЬНОГО окна роль не объявляет никогда:
   её органы — действия диалога («Отмена», «Применить»), и рамка там осмысленна.
   Сторож проверяет и это, и само правило: имя, объявленное продуктом и не объявленное
   Ядром, в общем хроме краснит набор (`chromeNamespaceFindings`).
   ====================================================================== */
.panel-head, [data-ge-cmdbar="head"] {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-start;
  gap: 8px 10px;
}
/* Слот `.panel-title` из перечня снят (30.07): его не рисовал никто. Единственное вхождение
   этого имени в семействе — заголовок ДРУГОГО узла (`.panel-header` технической консоли),
   под правило не попадавший вовсе. Заголовок шапки — это h1/h2/h3. */
.panel-head > h1, .panel-head > h2, .panel-head > h3,
[data-ge-cmdbar="head"] > h1, [data-ge-cmdbar="head"] > h2, [data-ge-cmdbar="head"] > h3 {
  flex: 1 0 100%;
  margin: 0;
}
/* Панель команд: орган раздела — ТЕКСТ С ПЛАШКОЙ ПРИ НАВЕДЕНИИ, а не коробка.
   Ни рамки, ни заливки, ни скругления, ни тени, ни градиента — в том числе у
   главного действия: в панели команд «главное» выражено порядком, а не цветом
   (заливка остаётся за кнопкой подтверждения в форме и выезжающей панели).

   ВЕС ПРАВИЛА. Первая редакция стояла на `:where(...)` (вес 0,0,0) и физически
   не могла победить продуктовое `.bo-btn` (0,1,0) и `.bo-btn.pri` (0,2,0) —
   вид оставался прежним, хотя правило было выложено. Здесь вес 0,3,0: контекст
   шапки бьёт объявление класса, но НЕ выходит за шапку — кнопки форм, панелей
   и строк таблицы свою форму сохраняют. Продуктовые объявления, заданные
   ВНУТРИ шапки, сняты в продуктах и запрещены сторожем (второй писатель).

   ОРГАН НАЗЫВАЕТСЯ УЗЛОМ, А НЕ ЧУЖИМ КЛАССОМ (30.07). В перечне органов стояло `.bo-btn` —
   имя кнопки одного продукта. Кнопка и так `<button>`, то есть перечень покрывал её дважды,
   а платформа при этом знала чужой класс. Имя снято; единственная ссылка, носившая только
   этот класс, получила платформенный `btn` у себя в продукте. */
:root :is(.panel-head, [data-ge-cmdbar])
  :is(button, .btn, .btn-primary, a.btn) {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: var(--rs-cmd-h, 36px);
  min-height: 0;
  /* Подпись органа — ОДНА строка. Панель команд переносит по органам, а не внутри органа:
     кнопка, ужатая соседями, иначе ломает подпись пополам и растёт вверх-вниз (замечание
     владельца 28.07: «зачем опять пишешь в 2 этажа»). Орган не ужимается и не растягивается. */
  flex: 0 0 auto;
  white-space: nowrap;
  padding: 0 10px;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  filter: none;
  text-shadow: none;
  color: var(--ge-color-text, #201f1e);
  font: inherit;
  font-size: 14px;
  font-weight: 400;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
}
:root :is(.panel-head, [data-ge-cmdbar])
  :is(button, .btn, .btn-primary, a.btn):hover {
  background: var(--ge-color-hover, #f3f2f1);
  color: var(--ge-color-text, #201f1e);
  box-shadow: none;
  filter: none;
}
:root :is(.panel-head, [data-ge-cmdbar])
  :is(button, .btn, .btn-primary, a.btn):active {
  background: var(--ge-color-pressed, #edebe9);
  box-shadow: none;
  filter: none;
  transform: none;
}
