/* =============================================================
 * dev2-skin.css — оболочка dev2 (KISELEV GROUP) поверх panel.css
 * Подключается на ВСЕХ страницах последним (через shared-header) → выигрывает
 * каскад. Приводит панель 1-в-1 к прототипу: чистый фон без сетки, топбар с
 * пилюлями-виджетами, крупный поиск, просторная таблица, округлые кнопки,
 * левый сайдбар. Работает в светлой и тёмной теме через токены.
 *
 * ВАЖНО: .navbar сменил высоту 44px → 60px. Все места в panel.css, где top/
 * min-height жёстко считали от старых 44px (settings-panel, explorer-overlay,
 * .welcome, .pc-fullscreen .chat-pane-left), переопределены здесь на 60px.
 * ============================================================= */

:root { --kg-navbar-h: 60px; --kg-side-w: 224px; --kg-side-cw: 62px; --kg-ctrl-h: 32px; }

/* ── Фон: убираем сетку/паттерн ───────────────────────────── */
body.app-bg { background: hsl(var(--background)); }

/* ============================================================
 * ЛЕВЫЙ САЙДБАР (fixed слева, контент сдвинут padding-left у body)
 * ============================================================ */
/* Жёлоб сайдбара БЕЗ transition — иначе при первом показе контент 0.22с едет
   вправо («широко → вжимается»). Анимируем только ручное сворачивание (.side-anim,
   класс вешается через rAF после вставки). Pre-paint (html.kg-preauth) резервирует
   жёлоб ещё до вставки aside и до /api/me — по флагу прошлой авторизации. */
html.kg-preauth body { padding-left: var(--kg-side-w); }
html.kg-preauth-collapsed body { padding-left: var(--kg-side-cw); }
body.has-kg-sidebar { padding-left: var(--kg-side-w); }
body.has-kg-sidebar.kg-side-collapsed { padding-left: var(--kg-side-cw); }
body.has-kg-sidebar.side-anim { transition: padding-left .22s ease; }

.kg-sidebar {
  position: fixed; left: 0; top: 0; bottom: 0; width: var(--kg-side-w); z-index: 45;
  background: hsl(220 18% 7%); color: rgba(255,255,255,.85);
  display: flex; flex-direction: column; padding: 14px 12px; gap: 2px; overflow: hidden;
  border-right: 1px solid hsl(var(--border)); transition: width .22s ease;
  font-family: var(--font-sans);
}
.dark .kg-sidebar { background: hsl(38 22% 5%); }
/* Графит: холодный near-black вместо тёплого (селектор специфичнее .dark выше) */
.dark.theme-graphite .kg-sidebar { background: hsl(222 34% 7%); }
body.kg-side-collapsed .kg-sidebar { width: var(--kg-side-cw); }

.kgs-brand { display: flex; align-items: center; gap: 10px; padding: 4px 6px 16px; text-decoration: none; white-space: nowrap; }
.kgs-mark { width: 32px; height: 32px; flex-shrink: 0; background: hsl(var(--primary)); color: hsl(var(--primary-foreground));
  display: grid; place-items: center; font-family: var(--font-mono); font-weight: 800; font-size: 12px; border-radius: 9px; }
.kgs-brandtext { display: flex; flex-direction: column; line-height: 1; }
.kgs-brandtext b { color: #fff; font-size: 14px; font-weight: 700; letter-spacing: -.01em; }
.kgs-brandtext i { color: rgba(255,255,255,.4); font-size: 9.5px; font-style: normal; letter-spacing: .06em; text-transform: uppercase; margin-top: 3px; }

.kgs-nav { display: flex; flex-direction: column; gap: 2px; }
.kgs-grp { font-family: var(--font-mono); font-size: 9.5px; color: rgba(255,255,255,.4);
  padding: 16px 8px 6px; letter-spacing: .07em; text-transform: uppercase; white-space: nowrap; }
.kgs-link { display: flex; align-items: center; gap: 11px; padding: 9px 9px; border-radius: 9px;
  font-size: 13px; color: rgba(255,255,255,.82); text-decoration: none; white-space: nowrap;
  transition: background .12s; position: relative; }
.kgs-link:hover { background: rgba(255,255,255,.06); }
.kgs-link.kgs-active { background: rgba(255,255,255,.10); color: #fff; font-weight: 600; }
.kgs-link.kgs-active::before { content: ""; position: absolute; left: -12px; top: 8px; bottom: 8px; width: 3px; border-radius: 0 3px 3px 0; background: hsl(var(--primary)); }
.kgs-link svg { flex-shrink: 0; opacity: .72; }
.kgs-link.kgs-active svg { opacity: 1; }
.kgs-spacer { flex: 1; }
.kgs-foot { border-top: 1px solid rgba(255,255,255,.09); padding-top: 10px; margin-top: 8px; }
.kgs-user { display: flex; align-items: center; gap: 10px; padding: 6px; white-space: nowrap; }
.kgs-av { width: 30px; height: 30px; flex-shrink: 0; border-radius: 50%;
  background: linear-gradient(135deg, hsl(var(--primary)), hsl(15 90% 41%));
  display: grid; place-items: center; color: #fff; font-weight: 700; font-size: 11px; font-family: var(--font-mono); }
.kgs-uname { color: #fff; font-size: 12.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.kgs-logout { margin-left: auto; flex-shrink: 0; color: rgba(255,255,255,.5); display: grid; place-items: center; cursor: pointer; }
.kgs-logout:hover { color: #fff; }

body.kg-side-collapsed .kgs-brandtext,
body.kg-side-collapsed .kgs-link span,
body.kg-side-collapsed .kgs-grp,
body.kg-side-collapsed .kgs-uname,
body.kg-side-collapsed .kgs-logout { display: none; }
body.kg-side-collapsed .kgs-link { justify-content: center; }
body.kg-side-collapsed .kgs-user { justify-content: center; }
body.kg-side-collapsed .kgs-brand { justify-content: center; padding-left: 0; padding-right: 0; }
body.kg-side-collapsed .kgs-link.kgs-active::before { display: none; }

/* ============================================================
 * ТОПБАР (navbar) — чистый, с пилюлями. Высота 60px (было 44px).
 * ============================================================ */
.navbar {
  height: var(--kg-navbar-h); padding: 0 18px 0 14px; gap: 10px;
  background: hsl(var(--card)); border-bottom: 1px solid hsl(var(--border));
  /* Шапка никогда не раздвигает страницу: чипов в ней много, и на окне уже
     ~1150px последняя кнопка вылезала за правый край — внизу появлялась
     горизонтальная прокрутка всей страницы. Не влезло — прокручивается сама
     шапка (полоса скрыта). Всплывающие меню шапки висят на body с
     position:fixed, их этот overflow не обрезает. */
  overflow-x: auto; scrollbar-width: none;
}
.navbar::-webkit-scrollbar { display: none; }
.kgs-burger { display: none; }
body.has-kg-sidebar .kgs-burger { display: inline-flex; }
body.has-kg-sidebar .navbar-kg,
body.has-kg-sidebar .navbar-center { display: none; }

/* Места, где panel.css жёстко считал от старой высоты navbar (44px) —
   пересчитаны на новую (60px), иначе появляется нахлёст/щель. */
.settings-panel { top: var(--kg-navbar-h); }
.explorer-overlay { top: var(--kg-navbar-h); }
.welcome { min-height: calc(100vh - var(--kg-navbar-h)); }
body.pc-fullscreen .chat-pane-left { top: var(--kg-navbar-h); }

/* ── CPU/MEM (server-stats): ДВЕ строки (CPU, MEM), каждая — ярлык + свой
   sparkline. Структура .server-stats > .stat-row×2 > (label, svg, pct)
   ОБЯЗАНА остаться flex-direction:column на внешнем контейнере — иначе
   строки едут в один ряд и график растягивается на всю ширину пилюли. */
.server-stats {
  height: var(--kg-ctrl-h); border-radius: 9px; box-sizing: border-box;
  background: hsl(var(--background)); border: 1px solid hsl(var(--border));
  display: flex; flex-direction: column; align-items: stretch; justify-content: center;
  padding: 3px 10px; gap: 2px; width: auto;
}
.stat-row { display: flex; align-items: center; gap: 6px; height: 12px; }
.stat-label {
  font-family: var(--font-mono); font-size: 8px; font-weight: 600;
  letter-spacing: .04em; color: hsl(var(--muted-foreground)); width: 22px; flex-shrink: 0;
}
.stat-chart { width: 42px; height: 10px; flex-shrink: 0; }
.stat-chart polyline, .stat-chart path {
  stroke: hsl(var(--smui-green, 142 60% 42%)); fill: none;
  stroke-linejoin: round; stroke-linecap: round;
}
/* Проценты рядом с графиком. Высота строки 12px — размер шрифта берём такой,
   чтобы цифра не распирала строку и не выталкивала содержимое за рамку. */
.stat-pct {
  font-size: 9.5px; font-weight: 700; line-height: 12px;
  font-variant-numeric: tabular-nums; min-width: 3ch; text-align: right;
}

/* ── DISK: отдельный чип той же высоты, что остальные элементы топбара.
   Внутрь server-stats не помещается — там жёсткая высота --kg-ctrl-h на две
   строки. Держим место на контроле: на 90% портал встаёт молча. */
.disk-chip {
  height: var(--kg-ctrl-h); width: auto; min-width: 56px; border-radius: 9px; box-sizing: border-box;
  background: hsl(var(--background)); border: 1px solid hsl(var(--border));
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 0 10px; flex-shrink: 0; cursor: pointer;
  color: hsl(var(--muted-foreground)); transition: border-color .15s, color .15s;
}
.disk-chip:hover { border-color: hsl(var(--smui-border-hover, var(--border))); }
.disk-label {
  font-family: var(--font-mono); font-size: 8px; font-weight: 600;
  letter-spacing: .04em; opacity: .8;
}
/* Цифра зелёная, пока места хватает, — как проценты CPU/MEM. Белым она читалась
   как «просто текст», хотя это такой же показатель здоровья сервера. */
.disk-pct {
  font-family: var(--font-mono); font-size: 12px; font-weight: 700;
  font-variant-numeric: tabular-nums; min-width: 4ch; text-align: right;
  color: hsl(142 60% 50%);
}
.disk-chip { border-color: hsl(142 50% 35% / 0.5); color: hsl(142 60% 50%); }
.disk-chip.disk-orange { border-color: hsl(38 80% 40% / .6); color: hsl(38 92% 50%); }
.disk-chip.disk-orange .disk-pct { color: hsl(38 92% 55%); }
.disk-chip.disk-red    { border-color: hsl(0 60% 45% / .7); color: hsl(0 65% 55%); }
.disk-chip.disk-red    .disk-pct { color: hsl(0 70% 60%); }

/* «Данных о лимите нет» — отдельный нейтральный вид. Зелёная пилюля с «0%»
   означала бы «лимит цел», хотя на деле пробник просто не ответил. */
.claude-limit.cl-lvl-none { border-color: hsl(var(--border)); opacity: .75; }
.claude-limit.cl-lvl-none .cl-bar-fill { background: hsl(var(--muted-foreground) / .4); }
.claude-limit.cl-lvl-none .cl-text { color: hsl(var(--muted-foreground)); }

/* Плашка падений сервисов. Появляется только когда есть что показать, поэтому
   красная всегда: приглушённого состояния у неё не бывает. */
.svc-chip { border-color: hsl(0 60% 45% / .8); color: hsl(0 68% 60%); background: hsl(0 60% 30% / .12); }
.svc-chip .disk-pct { color: hsl(0 72% 65%); }
.svc-chip:hover { border-color: hsl(0 70% 55%); }

/* ── Claude limit: узкая пилюля, бар сверху + % и время снизу (структура
   .claude-limit > .cl-bar, .cl-text — тоже флекс-колонка, не трогаем). */
/* .claude-pill — все лимит-чипы. Правая рабочая область сохраняет прежнюю
   ширину 92px, слева добавлена отдельная колонка 24px под логотип. */
.claude-limit.claude-pill {
  height: var(--kg-ctrl-h); width: 116px; flex-shrink: 0; border-radius: 9px; box-sizing: border-box;
  background: hsl(var(--background)); border: 1px solid hsl(var(--border));
  display: flex; flex-direction: column; align-items: stretch; justify-content: center;
  position: relative; padding: 4px 10px 4px 34px; gap: 3px;
}
.cl-bar { height: 5px; border-radius: 999px; overflow: hidden; }
.cl-bar-fill { border-radius: 999px; }
/* min-width:0 у колонок обязателен: без него флекс не даёт им сжиматься ниже
   содержимого, и длинная подпись («100% 20ч 12м») вылезает за скруглённую рамку
   пилюли, а не ужимается внутри неё. */
.cl-text { justify-content: space-between; gap: 4px; min-width: 0; overflow: hidden; }
.cl-pct-text { font-size: 10.5px; font-weight: 700; flex: 0 0 auto; }
.claude-pill .cl-time-long { display: none; }
.claude-pill .cl-time-short {
  display: inline; font-size: 10px; white-space: nowrap;
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
}

/* Логотип занимает отдельную левую колонку. За счёт +24px общей ширины и
   padding-left:34px рабочая ширина бара/текста остаётся ровно прежней. */
.ai-pill-logo {
  position: absolute; left: 7px; top: 4px;
  width: 20px; height: calc(100% - 8px);
  display: block; pointer-events: none;
}
.ai-pill-logo-claude { width: 19px; left: 7px; }
.ai-pill-logo-codex { width: 18px; left: 8px; color: hsl(var(--foreground)); opacity: .9; }
.ai-pill-logo-kimi { width: 19px; left: 7px; color: hsl(225 85% 68%); }

/* Порог 1400, а не 1100: шесть пилюль по 116px переполняли верхнюю полосу уже
   на 1150–1300, и правые чипы обрезались краем окна. */
@media (max-width: 1400px) {
  .claude-limit.claude-pill {
    width: 70px; padding: 2px 4px 2px 28px;
  }
  .ai-pill-logo { left: 5px; top: 5px; width: 16px; height: calc(100% - 10px); }
  .ai-pill-logo-codex { left: 6px; width: 15px; }
  .ai-pill-logo-kimi { left: 5px; width: 16px; }
}

/* ── CC sessions: иконка терминала + счётчик ────────────────── */
.cc-sessions, .cc-sessions.cc-sessions-narrow {
  height: var(--kg-ctrl-h); width: auto; min-width: 56px; border-radius: 9px; box-sizing: border-box;
  background: hsl(var(--background)); border: 1px solid hsl(var(--border));
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 0 12px;
}
/* min-width + tabular-nums: пилюля не «дышит» при 0→NN (моноширинные цифры) */
.cc-count { font-size: 12px; min-width: 2ch; text-align: center; font-variant-numeric: tabular-nums; }

/* Иконки топбара — округлые квадраты */
.btn-icon {
  width: var(--kg-ctrl-h); height: var(--kg-ctrl-h); border-radius: 9px;
  border: 1px solid hsl(var(--border)); background: hsl(var(--card));
  color: hsl(var(--muted-foreground));
  display: inline-flex; align-items: center; justify-content: center;
}
.btn-icon:hover { background: hsl(var(--background)); border-color: hsl(var(--muted-foreground)); color: hsl(var(--foreground)); }
.btn-icon.nav-active { border-color: hsl(var(--primary)); color: hsl(var(--primary)); background: hsl(var(--primary) / 0.08); }

/* admin / выйти — высота как у остальных элементов топбара (было: без
   box-sizing:border-box, padding добавлялся поверх фиксированных 30px из
   panel.css → плашка получалась заметно выше соседних иконок). */
.auth-group {
  height: var(--kg-ctrl-h); box-sizing: border-box;
  border-radius: 9px; padding: 3px 10px; border: 1px solid transparent;
  display: inline-flex; flex-direction: column; align-items: flex-end; justify-content: center;
  line-height: 1.15; gap: 2px;
}
.auth-group:hover { border-color: hsl(var(--border)); background: hsl(var(--background)); }

/* ============================================================
 * ПЛАВАЮЩАЯ КНОПКА CLAUDE — карточка со скруглением вместо тёмного
 * квадрата (было: чёрный квадрат в стиле .navbar-kg).
 * ============================================================ */
.btn-chat-fab {
  width: auto; min-width: 72px; height: 64px; border-radius: 16px;
  background: hsl(var(--card)); border: 1px solid hsl(var(--border));
  color: hsl(var(--foreground));
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  padding: 0 14px;
  box-shadow: 0 10px 18px -10px hsl(var(--primary) / 0.4);
  transition: transform .15s, border-color .15s;
}
.btn-chat-fab:hover { transform: translateY(-2px); border-color: hsl(var(--primary) / 0.5); }
.btn-chat-fab .fab-ic { color: hsl(var(--primary)); display: flex; }
.btn-chat-fab .fab-ic svg { width: 18px; height: 18px; }
.btn-chat-fab .fab-label {
  font-family: var(--font-mono); font-size: 9.5px; font-weight: 700;
  letter-spacing: .08em; color: hsl(var(--muted-foreground));
}

/* ============================================================
 * ТУЛБАР ПРОЕКТОВ (заголовок + поиск + кнопки)
 * ============================================================ */
.section-head { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 18px; }
.section-head-left { display: flex; align-items: baseline; gap: 10px; }
.section-label { font-family: var(--font-mono); font-size: 13px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
.section-path { font-family: var(--font-mono); font-size: 11px; color: hsl(var(--muted-foreground)); }

/* Строка тулбара — та же высота, что и в топбаре (var(--kg-ctrl-h)),
   единообразно с виджетами/иконками выше. */
.project-search {
  flex: 1; min-width: 220px; max-width: 620px; height: var(--kg-ctrl-h); box-sizing: border-box;
  border-radius: 9px; background: hsl(var(--background));
  border: 1px solid hsl(var(--border)); padding: 0 12px; gap: 8px;
  display: flex; align-items: center;
}
.project-search:focus-within { border-color: hsl(var(--primary)); }
.project-search svg { color: hsl(var(--muted-foreground)); flex-shrink: 0; width: 13px; height: 13px; }
.project-search input { flex: 1; border: none; background: none; outline: none; font-family: var(--font-sans); font-size: 12.5px; color: hsl(var(--foreground)); }

.dashboard-actions { display: flex; align-items: center; gap: 8px; }

/* Кнопки — округлые (радиус глобально; размер тулбара — только там) */
.btn { border-radius: 9px; font-family: var(--font-sans); font-weight: 600; transition: transform .12s, filter .15s, background .15s, border-color .15s; }
.btn:active { transform: translateY(1px); }
.dashboard-actions .btn { height: var(--kg-ctrl-h); box-sizing: border-box; padding: 0 14px; font-size: 12.5px; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.btn-primary { background: hsl(var(--primary)); color: hsl(var(--primary-foreground)); border: 1px solid transparent; }
.btn-primary:hover { filter: brightness(1.05); opacity: 1; }
/* Текст приглушённый (muted-foreground), как у "/data/projects/" рядом —
   было --foreground (полный чёрный/белый), слишком контрастно на обеих темах. */
#btn-empty { background: hsl(var(--card)); color: hsl(var(--muted-foreground)); border: 1px solid hsl(var(--border)); }
#btn-empty:hover { background: hsl(var(--background)); color: hsl(var(--foreground)); }
.btn-owner-filter { border-radius: 9px; height: var(--kg-ctrl-h); box-sizing: border-box; }
.btn-ghost { background: hsl(var(--card)); color: hsl(var(--muted-foreground)); border: 1px solid hsl(var(--border)); }
.btn-ghost:hover { background: hsl(var(--background)); color: hsl(var(--foreground)); }

/* ── Выпадающий список фильтра (статус, автор) ────────────────
   Пришёл на смену модалке: отбор — мелкое частое действие, затемнять ради него
   экран и прятать список незачем. Живёт в body с фиксированными координатами,
   иначе его обрезал бы контейнер таблицы с прокруткой. */
.filter-pop {
  position: fixed; z-index: 1200;
  min-width: 232px; max-height: min(70vh, 520px); overflow-y: auto;
  padding: 6px; border: 1px solid hsl(var(--border)); border-radius: 12px;
  background: hsl(var(--card)); box-shadow: 0 18px 44px hsl(0 0% 0% / .5);
  display: flex; flex-direction: column; gap: 2px;
}
.filter-pop .fp-item {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 9px; border: 1px solid transparent; border-radius: 9px;
  background: transparent; cursor: pointer; text-align: left; width: 100%;
  font-family: var(--font-mono); font-size: 12px; color: hsl(var(--foreground));
  transition: background .12s, border-color .12s;
}
.filter-pop .fp-item:hover { background: hsl(var(--secondary) / .55); }
.filter-pop .fp-item.is-on { border-color: hsl(var(--primary) / .5); background: hsl(var(--primary) / .08); }
/* Своя «галка»: нативный чекбокс в тёмной теме выглядит инородно и не красится. */
.filter-pop .fp-box {
  flex: none; width: 15px; height: 15px; border-radius: 5px;
  border: 1.5px solid hsl(var(--border)); position: relative;
}
.filter-pop .fp-item.is-on .fp-box { border-color: hsl(var(--primary)); background: hsl(var(--primary) / .9); }
.filter-pop .fp-item.is-on .fp-box::after {
  content: ''; position: absolute; left: 4px; top: 1px; width: 4px; height: 8px;
  border: solid hsl(var(--primary-foreground, 0 0% 100%)); border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.filter-pop .fp-name { flex: 1 1 auto; min-width: 0; }
.filter-pop .fp-count { flex: none; font-size: 11px; color: hsl(var(--muted-foreground)); }
.filter-pop .fp-all { font-weight: 600; }

/* ============================================================
 * ТАБЛИЦА ПРОЕКТОВ — карточка, просторные строки, округлые кнопки
 * ============================================================ */
/* overflow-x: auto, а не hidden: на ноутбучных ширинах ряд кнопок шире карточки
   и при hidden крайние («глаз», «удалить») просто срезались краем — нажать их
   было нельзя. На широком экране переполнения нет, вид не меняется. */
.proj-table-wrap { border: 1px solid hsl(var(--border)); border-radius: 16px; overflow-x: auto; overflow-y: hidden; background: hsl(var(--card)); }
.projects-grid { overflow-x: auto; }
.proj-table { width: 100%; }
/* Фон — на СТРОКЕ заголовка, а не на ячейках: колонки фиксированной ширины,
   а строки-полосы папок растягивают таблицу по карточке, поэтому заливка
   ячеек обрывалась на середине и правая треть шапки оставалась другого цвета. */
.proj-table thead tr { background: hsl(var(--background)); }
.proj-table th {
  padding: 11px 16px; font-family: var(--font-mono); font-size: 10.5px;
  letter-spacing: .06em; text-transform: uppercase; color: hsl(var(--muted-foreground));
  background: transparent; border-bottom: 1px solid hsl(var(--border));
}
.proj-table td { padding: 9px 16px; border-bottom: 1px solid hsl(var(--border) / 0.5); }
.proj-table tbody tr:last-child td { border-bottom: none; }
/* background-COLOR: сокращение сбросило бы background-image, а на нём держится
   полоса папки у строк проектов внутри неё (panel.css, блок «Проект внутри папки»). */
.proj-table tbody tr:hover { background-color: hsl(var(--secondary) / 0.45); }
/* Размеры на вкладке «Проекты» подняты на ступень: прежние 9.5–13px читались
   как техническая консоль, в них приходилось всматриваться. Растут все элементы
   строки разом, иначе ряд разъезжается по базовой линии. */
.tbl-name { font-family: var(--font-mono); font-size: 13.5px; font-weight: 600; }
.tbl-author, .tbl-date { font-family: var(--font-mono); font-size: 12px; color: hsl(var(--muted-foreground)); }

.type-badge, .tbl-status-badge { border-radius: 7px; padding: 4px 9px; font-family: var(--font-mono); font-size: 10px; letter-spacing: .05em; }
.tbl-actions-row { gap: 5px; }
.tbl-btn {
  height: 31px; min-width: 31px; border-radius: 9px; padding: 0 10px;
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  border: 1px solid hsl(var(--border)); color: hsl(var(--muted-foreground));
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  /* Не сжимать: колонка «Действия» фиксированной ширины, и flex-shrink по
     умолчанию молча ужимал кнопки — подписи ПУБ/КОП резались по краям. */
  flex: none;
}
.tbl-btn svg { width: 14px; height: 14px; }
.tbl-btn:hover { border-color: hsl(var(--muted-foreground)); color: hsl(var(--foreground)); background: hsl(var(--background)); }
.tbl-btn.tbl-claude { color: hsl(var(--primary)); border-color: hsl(var(--primary) / 0.4); }
.tbl-btn.tbl-claude:hover { background: hsl(var(--primary)); color: hsl(var(--primary-foreground)); border-color: hsl(var(--primary)); }
.tbl-applink { border-radius: 8px; }

/* ============================================================
 * МОДАЛКИ / НАСТРОЙКИ / ФОРМЫ — единое скругление
 * ============================================================ */
.settings-panel { border-radius: 16px 0 0 16px; }
.modal { border-radius: 16px; }
.modal-close { border-radius: 8px; }
.form-input { border-radius: 9px; height: 38px; }
.template-card { border-radius: 9px; }

/* ============================================================
 * ФОРМА ПРАВКИ — своя типографика и ритм
 * ------------------------------------------------------------
 * Классы с префиксом .fb- намеренно: общая .form-group рассчитана на плотные
 * технические формы (моно-шрифт, капс, 11px), и в форме, которую заполняет
 * человек словами, это читалось как консоль, а не как обращение. Трогать общие
 * классы нельзя — на них сидят ещё десяток модалок.
 * ============================================================ */
.fb-modal { max-width: 520px; }
/* Шапка: иконка + название и автор в две строки. Общий .modal-title — моно-капс
   («НОВАЯ ПРАВКА»), и для формы, которую человек заполняет словами, он выглядел
   как заголовок системного диалога. */
.fb-header { align-items: center; gap: 11px; padding: 15px 18px; }
.fb-icon {
  width: 32px; height: 32px; flex-shrink: 0; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  background: hsl(var(--primary) / .14); color: hsl(var(--primary));
}
.fb-head-text { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.fb-title { font-size: 15px; font-weight: 600; color: hsl(var(--foreground)); letter-spacing: 0; }

.fb-body { padding: 16px 20px 4px; display: flex; flex-direction: column; gap: 14px; }

/* Футер: «Все правки» — тихая ссылка слева, действия — справа. */
.fb-footer { display: flex; align-items: center; gap: 10px; padding: 14px 18px 16px; }
.fb-all {
  margin-right: auto; font-size: 12px; text-decoration: none;
  color: hsl(var(--muted-foreground)); transition: color .15s;
}
.fb-all:hover { color: hsl(var(--primary)); }
.fb-btn {
  display: inline-flex; align-items: center; gap: 7px;
  font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
  padding: 9px 16px; border-radius: 10px; border: 1px solid transparent;
  transition: background .15s, border-color .15s, opacity .15s;
}
.fb-btn-ghost {
  background: transparent; border-color: hsl(var(--border));
  color: hsl(var(--muted-foreground));
}
.fb-btn-ghost:hover { background: hsl(var(--accent)); color: hsl(var(--foreground)); }
.fb-btn-primary {
  background: hsl(var(--primary)); color: hsl(var(--primary-foreground)); font-weight: 600;
}
.fb-btn-primary:hover:not(:disabled) { background: hsl(var(--primary) / .88); }
.fb-btn-primary:disabled { opacity: .45; cursor: not-allowed; }
.fb-field { display: flex; flex-direction: column; gap: 6px; }
.fb-label { font-size: 12.5px; font-weight: 600; color: hsl(var(--foreground)); }
.fb-sub { font-size: 11.5px; font-weight: 400; color: hsl(var(--muted-foreground)); margin-left: 4px; }

/* Поля — обычным шрифтом, а не моно: это текст на русском, а не команда. */
.fb-input {
  width: 100%; box-sizing: border-box;
  font: inherit; font-size: 13.5px; line-height: 1.45;
  color: hsl(var(--foreground));
  background: hsl(var(--secondary));
  border: 1px solid hsl(var(--input)); border-radius: 10px;
  padding: 10px 12px; outline: none;
  transition: border-color .15s, box-shadow .15s;
}
.fb-input::placeholder { color: hsl(var(--muted-foreground)); opacity: .65; }
.fb-input:focus {
  border-color: hsl(var(--primary));
  box-shadow: 0 0 0 3px hsl(var(--primary) / .16);
}
textarea.fb-input { resize: vertical; min-height: 92px; }

/* Зона файлов — строкой, а не пустым прямоугольником в пол-экрана. */
.fb-drop {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 12px; cursor: pointer;
  border: 1px dashed hsl(var(--border)); border-radius: 10px;
  background: hsl(var(--muted) / .25);
  color: hsl(var(--muted-foreground)); font-size: 12.5px;
  transition: border-color .15s, background .15s, color .15s;
}
.fb-drop:hover, .fb-drop.is-over {
  border-color: hsl(var(--primary)); color: hsl(var(--foreground));
  background: hsl(var(--primary) / .07);
}
.fb-drop svg { flex-shrink: 0; opacity: .8; }
.fb-drop-limit { margin-left: auto; font-size: 11px; opacity: .75; white-space: nowrap; }

/* Приложенные файлы — чипами: имя и крестик рядом, а не строкой во всю ширину. */
.fb-files { display: flex; flex-wrap: wrap; gap: 6px; }
.fb-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  padding: 5px 8px 5px 10px; border-radius: 8px;
  background: hsl(var(--muted) / .5); border: 1px solid hsl(var(--border));
  font-size: 12px; color: hsl(var(--foreground));
}
.fb-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fb-chip-size { color: hsl(var(--muted-foreground)); font-size: 11px; flex-shrink: 0; }
.fb-chip button {
  border: 0; background: none; cursor: pointer; padding: 0 2px;
  color: hsl(var(--muted-foreground)); font-size: 13px; line-height: 1;
}
.fb-chip button:hover { color: hsl(var(--destructive)); }

/* Автор — в шапке модалки, а не отдельной сиротливой строкой над первым полем. */
.fb-author { font-size: 11.5px; color: hsl(var(--muted-foreground)); }

/* ============================================================
 * ПУСТЫЕ СОСТОЯНИЯ СПИСКА ПРОЕКТОВ
 * ------------------------------------------------------------
 * Пустая сетка молчит одинаково и когда проектов правда нет, и когда запрос
 * упал, и когда всё отсеяли фильтры. Плашка обязана говорить, что именно из
 * трёх, — иначе человек решает, что портал потерял его проекты.
 * ============================================================ */
.projects-note {
  grid-column: 1 / -1;
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  padding: 20px 22px; border-radius: 12px;
  background: hsl(var(--muted) / .35);
  border: 1px dashed hsl(var(--border));
  color: hsl(var(--muted-foreground)); font-size: 12.5px; line-height: 1.5;
}
.projects-note b { color: hsl(var(--foreground)); font-size: 13.5px; font-weight: 600; }
.projects-note-error {
  border-style: solid; border-color: hsl(0 60% 45% / .55);
  background: hsl(0 60% 30% / .12);
}
.projects-note-error b { color: hsl(0 70% 72%); }
.projects-note-btn {
  margin-top: 6px; font: inherit; font-size: 12px; cursor: pointer;
  padding: 7px 14px; border-radius: 8px;
  border: 1px solid hsl(var(--border)); background: hsl(var(--card));
  color: hsl(var(--foreground));
}
.projects-note-btn:hover { background: hsl(var(--accent)); border-color: hsl(var(--primary)); }

/* ============================================================
 * ЧАТ (общий + чат проекта) — скругление контролов, сохраняя структуру
 * ============================================================ */
.chat-textarea { border-radius: 10px; }
.chat-send { border-radius: 10px; }
.chat-bubble-user, .chat-bubble-assistant { border-radius: 12px; }
.pc-tool-btn { border-radius: 8px; }
.pc-dd-btn { border-radius: 8px; }
.pc-dd-menu { border-radius: 10px; }
.pc-mode-seg { border-radius: 9px; overflow: hidden; }

/* ============================================================
 * ПОПАПЫ ВИДЖЕТОВ (лимиты Claude / нагрузка сервера 24ч / сессии CC,
 * widget-popups.js + идентичная разметка в index.html) и фильтры по
 * автору/статусу — эти компоненты унаследовали новые цвета из
 * tokens.css автоматически (hsl(var(--x))), но проход по скруглению
 * их не касался: карточки/строки/пилюли оставались с radius:0.
 * ============================================================ */
.cl-card { border-radius: 14px; }
.cl-card .cl-session-bar, .cl-card .cl-session-bar-fill { border-radius: 999px; }
.cl-stat { border-radius: 10px; }
.cl-card-badge { border-radius: 6px; }

.cc-row { border-radius: 12px; }
.cc-filter { border-radius: 999px; }
.cc-row-kill, .cc-kill-extras { border-radius: 8px; }
.cc-tag { border-radius: 4px; }

.owner-filter-item { border-radius: 9px; }
.ofi-count { border-radius: 999px; }
/* Пустой счётчик (статусы, "Все") раньше рендерился как серая полоска —
   скрываем, вместо того чтобы показывать пустой бейдж. */
.ofi-count:empty { display: none; }

/* ============================================================
 * ФАЙЛОВЫЙ ЭКСПЛОРЕР — скругление верхних контролов
 * ============================================================ */
.expl-vsc-btn, .btn-close-box { border-radius: 8px; }
.tree-row { border-radius: 6px; }

/* explorer-overlay в panel.css анкерится к краю viewport (position:fixed,
   left:0 / left:calc(--left-chat-w + 4px)) — не знает про новый фиксированный
   левый сайдбар (224/62px), из-за чего наезжал на сайдбар и часть открытого
   чата. Досчитываем left с учётом --kg-side-w/--kg-side-cw. */
body.has-kg-sidebar .explorer-overlay { left: var(--kg-side-w); }
body.has-kg-sidebar.kg-side-collapsed .explorer-overlay { left: var(--kg-side-cw); }
body.has-kg-sidebar.has-left-chat .explorer-overlay { left: calc(var(--kg-side-w) + var(--left-chat-w, 380px) + 4px); }
body.has-kg-sidebar.has-left-chat.left-collapsed .explorer-overlay { left: calc(var(--kg-side-w) + 40px); }
body.has-kg-sidebar.kg-side-collapsed.has-left-chat .explorer-overlay { left: calc(var(--kg-side-cw) + var(--left-chat-w, 380px) + 4px); }
body.has-kg-sidebar.kg-side-collapsed.has-left-chat.left-collapsed .explorer-overlay { left: calc(var(--kg-side-cw) + 40px); }

/* ============================================================
 * СТАТИСТИКА (statistika.html — стили заданы инлайново в самом файле,
 * все компоненты изначально с radius:0). Округляем все карточки/бейджи.
 * ============================================================ */
.stat-notice { border-radius: 12px; overflow: hidden; }
.kpi { border-radius: 12px; }
.stat-card { border-radius: 12px; }
.team-table-wrap { border-radius: 14px; overflow: hidden; }
.chart-empty { border-radius: 10px; }
.seg { border-radius: 10px; overflow: hidden; }
.stat-custom input[type=date] { border-radius: 8px; }
.kpi-delta, .tm-mini-delta { border-radius: 6px; }
.inactive-item { border-radius: 8px; }
.user-panel { border-radius: 16px 0 0 16px; }
.up-avatar { border-radius: 10px; }
.up-project { border-radius: 9px; }
.up-project a { border-radius: 6px; }
.up-signal { border-radius: 9px; }
.tm-avatar { border-radius: 7px; }
.pr-status { border-radius: 5px; }
.up-close { border-radius: 8px; }
.heatmap .cell { border-radius: 3px; }

/* ============================================================
 * FAQ / АРХИТЕКТУРА (faq.html — инлайн-стили в самом файле)
 * ============================================================ */
.ref-tabs { top: var(--kg-navbar-h); }
.ref-card { border-radius: 10px; }
.ref-sname { border-radius: 6px; }
.ref-code-block { border-radius: 10px; }
.ref-code { border-radius: 5px; }
/* Один радиус для всех крупных блоков портала: карточки Статистики (.stat-card)
   скруглены на 12px, а блоки Инфо шли углами (0) и на 10px — разнобой был
   заметен при переходе между страницами. */
.ref-box, .ref-cat-header, .ref-pre, .ref-toc-item { border-radius: 12px; }
.ref-pre { border-radius: 10px; }

/* ── Единая анимация появления контента (все страницы) ─────────── */
/* Один keyframe для дашборд-секций, Статистики и Инфо — чтобы «вылет» был
   одинаковым везде, а не свой на каждой странице. Идут opacity/transform
   (композитор, без reflow), translateY не двигает соседей. */
@keyframes kgPageIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
/* fill-mode: backwards, НЕ both. При `both` после анимации на элементе остаётся
   transform: translateY(0) из to-кадра, а любой transform ≠ none делает элемент
   containing block для position:fixed потомков. Тогда модалки (.modal-overlay,
   position:fixed inset:0), вставленные в <body class="page-enter">, начинают
   позиционироваться относительно body, а не окна: на длинных страницах (Инфо,
   Статистика) оверлей растягивается на всю высоту документа, а карточка
   центрируется далеко за экраном — виден только блюр. `backwards` даёт анти-FOUC
   (opacity:0 до старта), но после анимации transform сбрасывается в none. */
/* ЕДИНСТВЕННОЕ место, где назначается анимация появления. Раньше её ставили
   вразнобой: класс page-enter вручную в разметке (Статистика — на <main>, Инфо —
   на <body>), своё правило в panel.css для секций дашборда (с fill-mode both), а
   История, Правки и вкладки Статистики не анимировались вовсе — переключение
   выглядело по-разному на каждой странице. Теперь один keyframe, одна
   длительность и один список того, что появляется:
     · корневой контейнер страницы — при загрузке;
     · секция дашборда и вкладка Статистики — при каждом переключении
       (снятие display:none перезапускает анимацию).
   .page-enter оставлен как ручной хук для будущих страниц. */
.page-enter,
.stat-shell, .hist-wrap, .fb-page, .ref-wrap, #view-dashboard,
#view-dashboard .section-block:not(.hidden),
.stat-page.active { animation: kgPageIn .18s ease backwards; }

/* ── Микроанимации для отзывчивости (дёшево, без CLS) ──────────── */
/* Пункт сайдбара: плавная смена фона/цвета при hover и активации */
.kgs-link { transition: background .15s ease, color .15s ease; }
.kgs-link svg { transition: opacity .15s ease; }
/* Строки таблицы проектов: мягкий hover */
.proj-table tbody tr { transition: background .12s ease; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Лог приложения в модалке публикации: свёрнут по умолчанию, раскрыт при падении */
.pub-log-box {
  border: 1px solid hsl(var(--border));
  border-radius: 8px;
  margin-bottom: 12px;
  overflow: hidden;
}
.pub-log-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 10px;
  background: hsl(var(--muted) / .35);
  flex-wrap: wrap;
}
.pub-log-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 0;
  padding: 2px 0;
  cursor: pointer;
  font: inherit;
  font-size: 12px;
  color: hsl(var(--foreground));
}
.pub-log-caret { font-size: 10px; color: hsl(var(--muted-foreground)); transition: transform .15s ease; }
.pub-log-box.is-open .pub-log-caret { transform: rotate(90deg); }
.pub-log-actions { display: flex; align-items: center; gap: 8px; }
.pub-log-meta { font-size: 11px; color: hsl(var(--muted-foreground)); }
.pub-log-btn { padding: 2px 10px; font-size: 11px; }
.pub-log-text {
  margin: 0;
  padding: 10px 12px;
  max-height: 260px;
  overflow: auto;
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  border-top: 1px solid hsl(var(--border));
  color: hsl(var(--muted-foreground));
}
.pub-log-text.is-empty { color: hsl(var(--muted-foreground) / .7); font-style: italic; }

/* Состояния публикации: «спит» и «упало» больше не выглядят одинаково */
/* Селекторы с #pub-status намеренно: у элемента есть id, и правило вида
   .pub-state-crashed проигрывало бы ему по специфичности — «упало» осталось
   бы серым, хотя класс на элементе стоит правильный. */
#pub-status { color: hsl(var(--muted-foreground)); }
#pub-status.pub-state-running { color: hsl(var(--smui-green)); }
#pub-status.pub-state-asleep  { color: hsl(var(--muted-foreground)); }
#pub-status.pub-state-crashed { color: hsl(var(--destructive)); font-weight: 600; }
#pub-status.pub-state-stuck   { color: hsl(var(--smui-yellow)); font-weight: 600; }

/* Модельный микс и дорогие сессии на вкладке «Команда» */
.mix-bar {
  display: flex;
  height: 22px;
  border-radius: 6px;
  overflow: hidden;
  margin-bottom: 14px;
  background: hsl(var(--muted) / .4);
}
.mix-seg {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  overflow: hidden;
}
/* Белым по цветной заливке: одинаково читается и в тёмной, и в светлой теме —
   цвет самой полосы от темы не зависит. */
.mix-seg-pct {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  color: #fff;
  white-space: nowrap;
  text-shadow: 0 1px 2px rgb(0 0 0 / .35);
}
/* Цвет — по инструменту (семейство оттенка), ступень внутри — по порядку модели.
   Именно цвет, а не filter: brightness() глушил и подпись внутри сегмента вместе
   с заливкой, из-за чего проценты становились нечитаемыми. Оттенки подобраны так,
   чтобы белый текст читался на каждом. */
.mix-t-cc.mix-lv0 { background: hsl(18 88% 56%); }
.mix-t-cc.mix-lv1 { background: hsl(32 90% 50%); }
.mix-t-cc.mix-lv2 { background: hsl(8 72% 52%); }
.mix-t-cc.mix-lv3 { background: hsl(42 85% 45%); }
.mix-t-cc.mix-lv4 { background: hsl(355 60% 50%); }

.mix-t-cx.mix-lv0 { background: hsl(152 58% 42%); }
.mix-t-cx.mix-lv1 { background: hsl(172 55% 38%); }
.mix-t-cx.mix-lv2 { background: hsl(132 45% 40%); }
.mix-t-cx.mix-lv3 { background: hsl(186 50% 36%); }
.mix-t-cx.mix-lv4 { background: hsl(110 40% 38%); }

.mix-t-km.mix-lv0 { background: hsl(213 62% 56%); }
.mix-t-km.mix-lv1 { background: hsl(230 55% 60%); }
.mix-t-km.mix-lv2 { background: hsl(196 55% 46%); }
.mix-t-km.mix-lv3 { background: hsl(250 45% 58%); }
.mix-t-km.mix-lv4 { background: hsl(182 45% 40%); }

.mix-seg + .mix-seg { border-left: 1px solid hsl(var(--card)); }
/* Хвост мелких долей — нейтральный серый: он не принадлежит одному инструменту. */
.mix-tail { background: hsl(220 8% 45%); }
.mix-dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 2px;
  margin-right: 7px;
}
.mix-table { width: 100%; border-collapse: collapse; font-family: var(--font-mono); font-size: 11px; }
.mix-table th {
  text-align: left;
  font-size: 9px; font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: hsl(var(--muted-foreground));
  padding: 10px 12px;
  white-space: nowrap;
}
/* Числа — ПО ЦЕНТРУ, как в таблице сотрудников выше (там td.num/th.num centered). */
.mix-table th.num, .mix-table td.num { text-align: center; font-variant-numeric: tabular-nums; }
.mix-table td { padding: 10px 12px; border-top: 1px solid hsl(var(--border) / .6); vertical-align: middle; }
.mix-table td.mix-tool { color: hsl(var(--muted-foreground)); font-size: 11px; }
.mix-empty { font-size: 12px; color: hsl(var(--muted-foreground)); padding: 4px 2px; }
/* Строка агента раскрывается в его модели — как строка сотрудника в проекты. */
.mix-row { cursor: pointer; }
.mix-row:hover { background: hsl(var(--accent) / .4); }
.mix-agent-cell { display: inline-flex; align-items: center; }
.mix-caret {
  font-size: 9px; color: hsl(var(--muted-foreground));
  display: inline-block; width: 10px; margin-right: 6px;
  transition: transform .15s;
}
/* Модели внутри агента: приглушённый фон и отступ, чтобы читались как вложенные. */
.mix-model-row td { background: hsl(var(--muted) / .12); border-top: 1px solid hsl(var(--border) / .3); font-size: 11px; }
.mix-model-name { display: inline-flex; align-items: center; padding-left: 18px; color: hsl(var(--muted-foreground)); }
/* Справочные ячейки (токены, доля модели) — обычным цветом, НЕ серым: серость
   читалась как «неважные/выключены». Пометка «справочно» осталась в тултипе th. */
.mix-table td.mix-ref { color: hsl(var(--foreground)); }
/* но во вложенных строках моделей общий приглушённый тон сохраняем. */
.mix-model-row td.mix-ref { color: hsl(var(--muted-foreground)); }
/* Полоса «доля запросов» в строке агента: наглядно, кто сколько работал.
   Длина = доля агента по числу запросов (сравнимо между инструментами). */
.mix-table td.mix-share { padding: 8px 12px; min-width: 160px; }
.mix-share-in {
  display: flex; align-items: center; gap: 9px;
}
.mix-bar {
  flex: 1; height: 9px; min-width: 40px;
  background: hsl(var(--muted) / .4);
  border-radius: 5px; overflow: hidden;
}
.mix-bar-fill { display: block; height: 100%; border-radius: 5px; transition: width .2s; }
.mix-bar-pct {
  flex-shrink: 0; width: 34px; text-align: right;
  font-weight: 700; color: hsl(var(--foreground));
  font-variant-numeric: tabular-nums;
}
/* Бейдж «выжато лимита» у имени агента: отдельная ось от объёма работы
   (мало запросов, но лимит на 100% — как у Kimi). НЕ капается: сброс лимита
   посреди недели даёт суммарно 150–200%. Цвет = насколько близко к потолку. */
.mix-lim {
  margin-left: 8px; padding: 1px 6px; border-radius: 6px;
  font-size: 9px; font-weight: 700; letter-spacing: .03em;
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.mix-lim-ok   { color: hsl(var(--muted-foreground)); background: hsl(var(--muted) / .5); }
.mix-lim-warn { color: hsl(38 92% 62%);  background: hsl(38 92% 52% / .12); }
.mix-lim-hot  { color: hsl(0 78% 66%);    background: hsl(0 78% 56% / .14); }
/* Сбой загрузки — НЕ то же самое, что «данных нет»: одинаковым серым текстом их
   не различить, а вывод человек делает противоположный. Красим как предупреждение
   и даём рамку, чтобы блок читался как состояние, а не как подпись. */
.mix-failed {
  color: hsl(38 92% 62%); background: hsl(38 92% 52% / .08);
  border: 1px solid hsl(38 92% 52% / .25); border-radius: 10px; padding: 10px 12px;
}
.mix-retry {
  margin-left: 8px; font: inherit; font-size: 11px; cursor: pointer;
  color: hsl(var(--foreground)); background: hsl(var(--muted) / .6);
  border: 1px solid hsl(var(--border)); border-radius: 7px; padding: 3px 9px;
  transition: background .15s ease, border-color .15s ease;
}
.mix-retry:hover:not(:disabled) { background: hsl(var(--accent)); border-color: hsl(var(--foreground) / .3); }
.mix-retry:disabled { opacity: .6; cursor: default; }

.sess-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  border-top: 1px solid hsl(var(--border) / .6);
  font-size: 11px;
}
.sess-row:first-child { border-top: 0; }
.sess-bar {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  background: hsl(var(--primary) / .10);
  border-radius: 4px;
  pointer-events: none;
}
.sess-main { position: relative; flex: 1; min-width: 0; }
.sess-who { color: hsl(var(--foreground)); }
.sess-proj { font-family: var(--font-mono); font-size: 11px; color: hsl(var(--muted-foreground)); }
.sess-when { font-size: 11px; color: hsl(var(--muted-foreground)); margin-top: 2px; }
.sess-nums { position: relative; text-align: right; }
.sess-tok { font-variant-numeric: tabular-nums; }
.sess-sub { font-size: 11px; color: hsl(var(--muted-foreground)); margin-top: 2px; }

/* Сводка «чем работал» над списком проектов сотрудника */
.tm-summary td {
  padding: 6px 16px 6px 52px !important;
  font-size: 11.5px;
  color: hsl(var(--muted-foreground));
  background: hsl(var(--muted) / .25);
}

/* Метка инструмента у дорогой сессии: полное название (Claude Code / Codex /
   Kimi Code). Аббревиатуры CC/CX/KM читались только тем, кто и так знает, чем
   работает команда, — а список смотрят и те, кто нет. Ширина фиксированная,
   чтобы имена сессий шли одной колонкой. */
.sess-tool {
  position: relative;
  flex: 0 0 auto;
  width: 86px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .04em;
  padding: 2px 0;
  border-radius: 4px;
  border: 1px solid currentColor;
}
.sess-tool-cc { color: hsl(var(--primary)); }
.sess-tool-cx { color: hsl(var(--smui-green)); }
.sess-tool-km { color: hsl(var(--smui-frost-3)); }


/* Табличные цифры во всём моношрифте: без tnum подменённые цифры Onest имеют
   пропорциональную ширину, и колонки чисел в таблицах гуляют. */
code, pre, .mono, [class*="mono"],
.stat-title, .kpi-value, .team-table, .mix-table, .sess-row, .cl-pct-text {
  font-variant-numeric: tabular-nums;
}


/* Единый вид `code` в контенте страниц. Было: в Инфо — оранжевый моноблок с
   подложкой, в Истории — 13px белым, на Статистике — 11px серым. Один и тот же
   по смыслу элемент выглядел тремя разными способами. Чат на дашборде не
   трогаем: там своя разметка сообщений. */
.hist-wrap code, .stat-shell code, .fb-page code {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: hsl(var(--primary));
  background: hsl(var(--muted) / .5);
  border-radius: 4px;
  padding: 1px 5px;
}


/* Ссылки внутри текста страниц. Без стиля браузер рисует их своим синим
   (#0000EE) — он не из палитры портала и в тёмной теме читается плохо.
   Селектор с :not([class]) намеренно: ссылки-кнопки и иконки имеют классы и
   свой цвет, их трогать нельзя. */
.hist-wrap a:not([class]), .stat-shell a:not([class]),
.ref-wrap a:not([class]), .fb-page a:not([class]) {
  color: hsl(var(--primary));
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Логотип в сайдбаре — ссылка без явного цвета: сам текст внутри перекрашен
   дочерними правилами, но любой новый узел внутри унаследовал бы браузерный
   синий. Фиксируем наследование. */
.kgs-brand { color: inherit; }

/* Длинные имена проектов (это имена каталогов — пробелов в них нет) выдавливали
   колонку с числами за край карточки и давали странице горизонтальную прокрутку. */
.sess-who, .sess-proj, .mix-table td, .tm-detail td { overflow-wrap: anywhere; }


/* Кнопка общей панели метрик и сама панель — только мобильные
   (открываются в @media 640 ниже). Сюда же кнопка меню действий и лупа. */
#btn-metrics, .kg-metrics-drawer, #btn-navmenu, #btn-search-toggle { display: none; }

/* ═══════════════════════════════════════════════════════════════
 * МОБИЛЬНАЯ ОБОЛОЧКА (≤640px)
 * 1. Сайдбар — выезжающий drawer поверх контента: постоянная колонка
 *    224px на телефоне сжимала контент до ~130px. Открывается бургером
 *    (JS-ветка kg-drawer-open в shared-header.js), закрывается кликом
 *    по затемнению или по пункту меню. Десктоп не меняется.
 * 2. Навбар: пилюли лимитов/нагрузки/сессий на 360px не влезают —
 *    прячем. Чип «СБОЙ» (падения сервисов) оставлен: он редкий и
 *    важный, без него авария на мобиле была бы невидимой.
 * ═════════════════════════════════════════════════════════════ */
@media (max-width: 640px) {
  #btn-metrics { display: inline-flex; }
  .kg-metrics-drawer { display: flex; }

  /* Контент — на всю ширину, жёлоба под сайдбар нет (ни живого, ни pre-paint) */
  body.has-kg-sidebar,
  body.has-kg-sidebar.kg-side-collapsed,
  html.kg-preauth body,
  html.kg-preauth-collapsed body { padding-left: 0; }

  .kg-sidebar {
    width: min(280px, 84vw);
    transform: translateX(-105%);
    transition: transform .22s ease;
    z-index: 60; /* выше навбара (45) и затемнения (55) */
    box-shadow: 8px 0 32px hsl(0 0% 0% / .45);
  }
  /* На мобиле «свёрнутости» нет — drawer всегда полной ширины */
  body.kg-side-collapsed .kg-sidebar { width: min(280px, 84vw); }
  body.kg-drawer-open .kg-sidebar { transform: none; }

  /* …и надписи в нём — всегда, даже когда kg-side-collapsed приехал из
     десктопного localStorage (там collapsed прячет тексты, dev2-skin:71-79).
     В drawer места достаточно — показываем пункты полностью. */
  body.kg-side-collapsed .kgs-brandtext { display: block; }
  body.kg-side-collapsed .kgs-link span,
  body.kg-side-collapsed .kgs-uname,
  body.kg-side-collapsed .kgs-logout { display: inline; }
  body.kg-side-collapsed .kgs-grp { display: block; }
  body.kg-side-collapsed .kgs-link,
  body.kg-side-collapsed .kgs-user,
  body.kg-side-collapsed .kgs-brand { justify-content: flex-start; }
  body.kg-side-collapsed .kgs-brand { padding-left: 12px; padding-right: 12px; }
  body.kg-side-collapsed .kgs-link.kgs-active::before { display: block; }

  /* Затемнение под drawer (меню и панель метрик). Клик по нему ловит
     document-listener в shared-header.js и закрывает drawer. */
  body.kg-drawer-open::after,
  body.kg-metrics-open::after {
    content: '';
    position: fixed; inset: 0;
    background: hsl(0 0% 0% / .5);
    z-index: 55;
  }

  /* Проводник файлов — поверх всего экрана, без отступа под сайдбар */
  body.has-kg-sidebar .explorer-overlay,
  body.has-kg-sidebar.kg-side-collapsed .explorer-overlay { left: 0; }

  /* Навбар: пилюли метрик скрыты, пока не открыта общая панель (кнопка
     #btn-metrics → body.kg-metrics-open, JS в shared-header.js). Чип «СБОЙ»
     не скрывается: он редкий и важный, авария должна быть видна сразу. */
  body:not(.kg-metrics-open) #server-stats,
  body:not(.kg-metrics-open) #disk-chip,
  body:not(.kg-metrics-open) #cc-sessions,
  body:not(.kg-metrics-open) .claude-limit.claude-pill { display: none; }

  /* Открытая панель метрик — выезжающая слева drawer-панель (как меню),
     JS в shared-header.js переносит туда живые пилюли из navbar. */
  .kg-metrics-drawer {
    position: fixed; left: 0; top: 0; bottom: 0;
    /* По ширине самого широкого чипа — не на весь экран */
    width: max-content; max-width: 84vw;
    background: hsl(var(--card));
    border-right: 1px solid hsl(var(--border));
    box-shadow: 8px 0 32px hsl(0 0% 0% / .45);
    z-index: 60; /* выше навбара (45) и затемнения (55) */
    transform: translateX(-105%);
    transition: transform .22s ease;
    display: flex; flex-direction: column;
    align-items: flex-start; /* чипы — натуральной ширины, не растянуты */
    gap: 10px; padding: 12px;
    overflow-y: auto;
  }
  body.kg-metrics-open .kg-metrics-drawer { transform: none; }
  .kg-metrics-head {
    display: flex; align-items: center; justify-content: space-between;
    align-self: stretch; /* заголовок — на всю ширину панели */
    font-size: 13px; font-weight: 600; color: hsl(var(--foreground));
    padding-bottom: 8px; border-bottom: 1px solid hsl(var(--border));
  }
  .kg-metrics-close {
    background: none; border: 0; color: hsl(var(--muted-foreground));
    font-size: 14px; cursor: pointer; padding: 4px 6px;
  }

  /* Плавающая кнопка Claude — компактнее, чтобы не закрывала контент */
  .btn-chat-fab { min-width: 56px; height: 52px; border-radius: 13px; }

  /* ── Пилюли в панели метрик (запрос dima.z, итерация 3): панель 166px
     (расширение до 190 отменено — сокращённые подписи «5 ч» / «нед» влезают
     и так), пилюли — на всю её ширину. У лимитов подпись ПЕРИОДА счётчика
     («5 ч» / «нед», у Codex — «нед», 5-часового окна у него нет) — абсолютом
     ПОД иконкой нейронки, поэтому отдельной строки внизу чипа нет и он стал
     ниже. Бары лимитов с заметным треком, у CPU/MEM/DISK — прогресс-полоски
     (ширина от --pct, её ставит shared-header.js; sparkline-графики в узкой
     панели скрыты). Правила позже одноимённых в этой же медиа-секции —
     десктоп не затронут. */
  .kg-metrics-drawer { width: min(166px, 84vw); align-items: stretch; gap: 8px; }

  /* Лимит-пилюли — той же высоты, что чип диска (46px, запрос dima.z) */
  .kg-metrics-drawer .claude-limit.claude-pill {
    width: 100%; height: auto; min-height: 46px;
    padding: 6px 12px 6px 44px; gap: 4px;
  }
  /* Подписей периода под иконками НЕТ (запрос dima.z): по времени остатка
     («2ч 17м» vs «3д 6ч») и так понятно, 5-часовое это окно или недельное. */
  /* Бар: трек заметный (в panel.css он hsl(--muted) — сливается с фоном
     карточки). display:block !important — ОБЯЗАТЕЛЕН: panel.css @media ≤1100px
     прячет .claude-limit .cl-bar { display:none !important }, поэтому в drawer
     полоска была невидима совсем. */
  .kg-metrics-drawer .cl-bar { display: block !important; height: 8px; background: hsl(var(--muted-foreground) / .22); border: 0; }
  /* Процент и время — В ОДНУ строку (запрос dima.z). panel.css @media ≤1100
     ставит .cl-text колонкой с !important — перебиваем своим !important. */
  .kg-metrics-drawer .claude-limit .cl-text { flex-direction: row !important; justify-content: space-between; align-items: baseline; gap: 6px; }
  .kg-metrics-drawer .cl-pct-text { display: inline; width: auto; text-align: left; font-size: 15px; }
  /* Время тоже короткой формой. Замер 02.08.2026: «100% 20ч 12м» просит 94 px
     при 83 px рабочей ширины пилюли (панель 166 px), и минуты обрезались краем.
     Точное значение — в подсказке пилюли и в окне лимита. */
  .kg-metrics-drawer .cl-time-long { display: none; }
  .kg-metrics-drawer .cl-time-short { display: inline; width: auto; text-align: right; font-size: 12px; }
  /* Иконка — почти на всю высоту чипа (место под подпись периода больше
     не нужно: подписи убраны) */
  .kg-metrics-drawer .ai-pill-logo { left: 10px; top: 8px; width: 24px; height: calc(100% - 16px); }
  .kg-metrics-drawer .ai-pill-logo-claude { width: 22px; }
  .kg-metrics-drawer .ai-pill-logo-codex { left: 11px; width: 20px; }
  .kg-metrics-drawer .ai-pill-logo-kimi { width: 22px; }

  /* CPU/MEM: sparkline скрыт, вместо него прогресс-полоска под строкой
     (--pct и stat-lvl-* ставит sparkline() в shared-header.js).
     display:flex !important — ОБЯЗАТЕЛЕН: panel.css @media ≤700px прячет
     .server-stats { display:none !important } («его видно в панели настроек»),
     и без этого чип в drawer невидим (в DOM есть, клик работает). */
  .kg-metrics-drawer .server-stats { display: flex !important; flex-direction: column; width: 100%; height: auto; padding: 9px 12px; gap: 10px; }
  .kg-metrics-drawer .stat-row { height: auto; position: relative; padding-bottom: 7px; gap: 6px; justify-content: space-between; }
  .kg-metrics-drawer .stat-row::before,
  .kg-metrics-drawer .stat-row::after {
    content: ''; position: absolute; left: 0; bottom: 0; height: 5px; border-radius: 999px;
  }
  .kg-metrics-drawer .stat-row::before { right: 0; background: hsl(var(--muted-foreground) / .18); }
  .kg-metrics-drawer .stat-row::after { width: calc(var(--pct, 0) * 1%); background: hsl(142 60% 42%); }
  .kg-metrics-drawer .stat-row.stat-lvl-orange::after { background: hsl(38 92% 50%); }
  .kg-metrics-drawer .stat-row.stat-lvl-red::after { background: hsl(0 65% 50%); }
  /* Ярлыки CPU/MEM — panel.css @media ≤1100px их прячет (без !important) */
  .kg-metrics-drawer .stat-label { display: inline; font-size: 10px; width: 28px; }
  .kg-metrics-drawer .stat-chart { display: none; }
  /* Все проценты панели (CPU/MEM, диск, NETA) — единый моно-шрифт и поле
     4ch с выравниванием вправо: правые края цифр стоят на одной вертикали */
  .kg-metrics-drawer .stat-pct,
  .kg-metrics-drawer .disk-pct {
    font-family: var(--font-mono, 'IBM Plex Mono', monospace);
    font-size: 13px; min-width: 4ch; text-align: right;
  }

  /* DISK — две строки, как чип CPU/MEM (запрос dima.z): локальный диск +
     NetAngels (тарифная квота, d.netangels.quotaPct). Строка: метка слева,
     цифра справа, полоска под строкой (--pct: у DISK-строки наследуется от
     чипа, у NA — свой от updateStats; цвета: DISK — от disk-orange/red на
     чипе, NA — от stat-lvl-* на строке). Сессии — высотой как бывший
     однострочный диск (46px), с меткой sess вместо непонятной «18». */
  .kg-metrics-drawer .disk-chip,
  .kg-metrics-drawer .cc-sessions {
    width: 100%; height: auto; min-height: 46px; padding: 8px 12px;
    justify-content: space-between; position: relative;
  }
  /* Сессии — на 35% ниже (46px → 30px, запрос dima.z) */
  .kg-metrics-drawer .cc-sessions { min-height: 30px; padding-top: 4px; padding-bottom: 4px; }
  /* Диск — той же геометрии, что чип CPU/MEM: те же gap и паддинги,
     оснований быть выше у него нет */
  .kg-metrics-drawer .disk-chip:not(.svc-chip) {
    flex-direction: column; align-items: stretch; justify-content: center;
    gap: 10px; padding-top: 9px; padding-bottom: 9px;
  }
  .kg-metrics-drawer .disk-row { display: flex; justify-content: space-between; position: relative; padding-bottom: 7px; }
  .kg-metrics-drawer .disk-row::before,
  .kg-metrics-drawer .disk-row::after {
    content: ''; position: absolute; left: 0; bottom: 0; height: 5px; border-radius: 999px;
  }
  .kg-metrics-drawer .disk-row::before { right: 0; background: hsl(var(--muted-foreground) / .18); }
  .kg-metrics-drawer .disk-row::after { width: calc(var(--pct, 0) * 1%); background: hsl(142 60% 50%); }
  .kg-metrics-drawer .disk-row.stat-lvl-orange::after { background: hsl(38 92% 50%); }
  .kg-metrics-drawer .disk-row.stat-lvl-red::after { background: hsl(0 65% 55%); }
  .kg-metrics-drawer .disk-chip.disk-orange:not(.svc-chip) .disk-row:not(.disk-na)::after { background: hsl(38 92% 50%); }
  .kg-metrics-drawer .disk-chip.disk-red:not(.svc-chip) .disk-row:not(.disk-na)::after { background: hsl(0 65% 55%); }
  /* Метка DISK — panel.css @media ≤1100 прячет её («чип до одной цифры»),
     а в drawer она нужна: без неё 82% читается как непонятное число. */
  .kg-metrics-drawer .disk-label { display: inline; font-size: 10px; }
  /* Цифра сессий — того же кегля, что проценты (13px); само правило
     процентов (disk-pct вместе со stat-pct) — выше, у stat-chart. */
  .kg-metrics-drawer .cc-count { font-size: 13px; }
  /* Отступ первому чипу от заголовка панели (запрос dima.z) */
  .kg-metrics-drawer .kg-metrics-head { margin-bottom: 4px; }
  /* Метка SESS капсом (как DISK/CPU/MEM), строка выровнена по центру —
     цифра на одной линии с меткой, не «вверху справа» */
  .kg-metrics-drawer .cc-sessions { align-items: center; }
  .kg-metrics-drawer .cc-sessions::before {
    content: 'SESS'; font-size: 10px; letter-spacing: .04em;
    color: hsl(var(--muted-foreground));
  }

  /* ── Единое меню действий (запрос dima.z, 1-С): иконки справа прячем,
     их действия — пунктами dropdown под новой шестерёнкой #btn-navmenu
     у правого края (стили меню — в конце файла, глобально). Попап
     уведомлений позиционируется от #agent-bell-wrap — он остаётся в DOM,
     поэтому программный клик по скрытой кнопке открывает его как раньше. */
  #btn-agent-bell, #btn-theme, #btn-settings, #btn-logout { display: none !important; }
  #btn-navmenu { display: inline-flex; }

  /* Чип нагрузки — якорь для пин-кнопки (у disk/cc/pills relative уже есть) */
  .kg-metrics-drawer .server-stats { position: relative; }

  /* Кнопки навбара — всегда квадратные (--kg-ctrl-h × --kg-ctrl-h): когда в
     шапке закреплённые чипы, flex сжимал бургер/метрики в «узкие» (а при
     открытой панели, когда чипы уезжают, они расправлялись обратно). */
  .navbar .btn-icon { flex-shrink: 0; }

  /* ── Шапка не шире экрана (запрос dima.z): поля и gap динамические
     (clamp от ширины экрана); страховка — если всё равно не влезло, шапка
     скроллится ВНУТРИ себя (overflow-x:auto, полоса скрыта), страница не
     раздувается. Меню шестерёнки (.kg-navmenu) висит на body с
     position:fixed — его overflow шапки не обрезает. */
  .navbar {
    gap: clamp(4px, 1.5vw, 10px);
    padding-left: clamp(6px, 2vw, 14px); padding-right: clamp(6px, 2vw, 18px);
    overflow-x: auto; scrollbar-width: none;
  }
  .navbar::-webkit-scrollbar { display: none; }
  /* Свободное место шапки — чипам, а не пустоте (запрос dima.z): спейсеры
     схлопнуты, под шестерёнку резервируется только её собственная ширина
     (margin-left:auto прижимает её вправо, когда чипов нет), запиненные
     чипы делят всё оставшееся место поровну и тянутся. */
  .navbar .navbar-spacer { flex: 0 1 0; min-width: 0; }
  #kg-navbar #btn-navmenu { margin-left: auto; }
  #kg-navbar .kg-pinned { flex: 1 1 0; }
  #kg-navbar .kg-pinned.claude-pill { width: auto; min-width: 56px; padding-left: 30px; }
  #kg-navbar .kg-pinned.claude-pill .ai-pill-logo { width: 16px; left: 6px; }

  /* Закреплённые в шапке чипы (пин): возвращаем метки/иконки — без них
     «3», «2%/10%», «82%» не читаются (запрос dima.z). Цифры — по правому
     краю, чипы чуть шире компакт-режима @media ≤1100, чтобы метка+цифра
     влезали. Метки прячут panel.css (.disk-label, .stat-label, svg узких
     чипов) — наши селекторы с #kg-navbar специфичнее. */
  /* Чип сессий — ТОЧНАЯ копия шаблона рабочих чипов (disk/server-stats):
     реальный span.cc-label слева + цифра справа через flex space-between.
     Псевдоэлемент ::before и grid убраны — они давали схлопы и наложения.
     Зазоры от краёв одинаковые (10px), метка/цифра кеглями как у соседей.
     display НЕ задаём: flex уже в базе panel.css, а жёсткий display:flex
     здесь ломал пин — чип не скрывался при снятии закрепа. */
  #kg-navbar #cc-sessions { justify-content: space-between !important; align-items: center; flex-shrink: 0; width: auto !important; min-width: 64px; padding: 0 10px !important; gap: 8px; }
  /* Метка SESS — реальный элемент (в разметке, на десктопе скрыта) */
  #kg-navbar #cc-sessions .cc-label { display: inline !important; font-size: 10px; letter-spacing: 0; color: hsl(var(--muted-foreground)); }
  #kg-navbar #cc-sessions .cc-count { font-size: 12px; min-width: 0; text-align: right; font-variant-numeric: normal; }
  /* Диск в шапке — две строки (локальный + NA), как в панели и как CPU/MEM */
  #kg-navbar .kg-pinned.disk-chip { flex-direction: column; align-items: stretch; justify-content: center; gap: 2px; min-width: 62px; padding: 2px 8px; }
  #kg-navbar .kg-pinned.disk-chip .disk-row { display: flex; justify-content: space-between; align-items: center; gap: 4px; height: 12px; }
  #kg-navbar .kg-pinned.disk-chip .disk-label { display: inline; font-size: 8px; }
  #kg-navbar .kg-pinned.disk-chip .disk-pct { font-size: 9.5px; min-width: 4ch; text-align: right; }
  /* Проценты CPU/MEM и диска — одно поле 4ch с выравниванием вправо и
     одинаковый отступ от края чипа (8px): правые края цифр на одной
     вертикали во всех чипах шапки */
  #kg-navbar .kg-pinned.server-stats { width: auto; min-width: 62px; padding: 2px 8px; }
  #kg-navbar .kg-pinned.server-stats .stat-label { display: inline; width: auto; }
  #kg-navbar .kg-pinned.server-stats .stat-row { justify-content: space-between; gap: 4px; }
  #kg-navbar .kg-pinned.server-stats .stat-pct { min-width: 4ch; text-align: right; }

  /* ── Фильтры проектов (запрос dima.z): ФИКС-ШИРИНА — обе кнопки ВСЕГДА
     равны и не пляшут при выборе значения (flex: 1 1 0, базис ноль, не от
     контента); вся четвёрка (лупа, статус, автор, + Создать) занимает всю
     ширину строки. Подписи «СТАТУС»/«АВТОР» — ПО ЦЕНТРУ; когда выбрано
     значение (app.js вешает .active), текст уходит к ЛЕВОМУ краю, шеврон
     остаётся справа. Длинные значения режутся под «…» — ширина кнопки от
     этого не меняется. Паддинги 8px (база 14px) — чтобы четвёрка влезала
     в 360px; шрифт — базовый 12.5px (запрос dima.z). */
  .section-head .dashboard-actions .btn { padding-left: 8px; padding-right: 8px; gap: 4px; }
  #btn-search-toggle { min-width: 32px; flex-shrink: 0; }
  #btn-status-filter, #btn-owner-filter {
    flex: 1 1 0; width: auto; min-width: 0; justify-content: center;
  }
  #btn-status-filter.active, #btn-owner-filter.active { justify-content: space-between; }
  #btn-create { min-width: 0; flex-shrink: 0; }
  #btn-status-filter .of-text, #btn-owner-filter .of-text {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
  }

  /* Строка фильтров точно в экране: поля страницы, gap группы и кнопка
     «+ Создать» подстраиваются под ширину (запрос dima.z). Главное —
     section-head больше не шире экрана: в базе он max-width:654px и
     центрирован, поэтому вылезал за оба края (слева пустота, справа
     обрезка «+ Создать») и давал горизонтальный скролл окна. */
  .section-head { max-width: 100%; }
  .dashboard { padding-left: clamp(8px, 2.5vw, 12px); padding-right: clamp(8px, 2.5vw, 12px); }
  /* Группа кнопок — во ВСЮ ширину строки (запрос dima.z): иначе она
     shrink-to-fit и жмётся к краю, а фильтрам-flex некуда расти. С полной
     шириной лупа слева, «+ Создать» справа, фильтры делят середину. */
  .section-head .dashboard-actions { width: 100%; margin-left: 0; gap: clamp(6px, 2vw, 10px); }
  .dashboard-actions #btn-create, .dashboard-actions #btn-empty { padding-left: clamp(8px, 2.5vw, 12px); padding-right: clamp(8px, 2.5vw, 12px); }

  /* Заголовок «Проекты» (+ путь) на мобиле скрыт совсем (запрос dima.z):
     с ним строка фильтров не влезала и переносилась; без него — хватает. */
  .section-head-left { display: none; }

  /* ── Кнопка-лупа в строке фильтров (запрос dima.z): поисковая строка
     скрыта, разворачивается НИЖЕ по body.kg-search-open (тоггл в app.js).
     Зазоры — общий gap группы, как у остальных кнопок. */
  #btn-search-toggle { display: inline-flex; align-items: center; justify-content: center; }
  #btn-search-toggle.active { border-color: hsl(var(--primary)); color: hsl(var(--primary)); }
  .project-search { display: none; }
  body.kg-search-open .project-search { display: flex; }
}

/* ── Меню действий и пин чипов — глобальные стили (запрос dima.z) ── */
/* Кнопка меню #btn-navmenu скрыта вместе с #btn-metrics выше (:885),
   видна только на ≤640px (правило в медиа-секции). */
/* Метка SESS в чипе сессий — только в мобильной шапке (правило медиа-секции
   выше); на десктопе чип компактный: иконка терминала + число. */
.cc-label { display: none; }
/* Кнопка-лупа скрыта вместе с #btn-metrics выше (:885) — как #btn-navmenu;
   на ≤640px её показывает правило медиа-секции. Глобальный display:none
   здесь НЕ ставить: он перебил бы медиа-правило (та же ловушка, что была
   с #btn-navmenu). */
.kg-navmenu {
  position: fixed; top: calc(var(--kg-navbar-h, 48px) + 6px); right: 8px; z-index: 70;
  display: none; flex-direction: column; min-width: 150px;
  background: hsl(var(--card)); border: 1px solid hsl(var(--border));
  border-radius: 10px; box-shadow: 0 8px 32px hsl(0 0% 0% / .45); padding: 6px;
}
.kg-navmenu.open { display: flex; }
.kg-navmenu-item {
  background: none; border: 0; color: hsl(var(--foreground));
  text-align: left; font-size: 13px; font-family: inherit;
  padding: 9px 10px; border-radius: 7px; cursor: pointer;
  display: flex; align-items: center; gap: 9px;
}
.kg-navmenu-item svg { flex-shrink: 0; opacity: .75; }
.kg-navmenu-item:hover { background: hsl(var(--muted)); }
.kg-navmenu-item:hover svg { opacity: 1; }

/* Пин-кнопка чипа: только в панели метрик (в navbar чип её не таскает) */
.kg-chip-pin {
  display: none; position: absolute; top: 3px; right: 4px; z-index: 2;
  background: none; border: 0; padding: 2px;
  font-size: 10px; line-height: 1; cursor: pointer; opacity: .45;
}
.kg-metrics-drawer .kg-chip-pin { display: block; }
.kg-chip-pin.kg-pin-on { opacity: 1; }
/* Закреплённый чип (до 3, localStorage kg.metrics.pins) остаётся в заголовке
   при закрытой панели метрик: перебивает мобильные скрытия чипов, включая
   panel.css ≤700px .server-stats{display:none !important} — наш !important
   при большей специфичности (0,3,0 против 0,1,0) выигрывает. */
body:not(.kg-metrics-open) .kg-pinned { display: flex !important; }

/* Строки чипа диска: вне мобильной панели — display:contents (десктопный
   однострочный чип не меняется), вторая строка (NetAngels) видна только в
   панели — там .disk-row/.disk-na становятся flex (правила медиа-секции
   специфичнее). Без данных JS прячет строку инлайн-стилем. */
.disk-row { display: contents; }
.disk-na { display: none; }


/* ── Шапка раздела: ширина ровно по таблице (base: max-width: --proj-table-w)
   Растягивать её на всю полосу контента нельзя: при space-between заголовок,
   поиск и кнопки расползаются по краям широкого экрана. Ряд держим плотным и
   выровненным с таблицей под ним; перенос в два ряда на узких окнах лечим
   сжатием кнопок и поиска ниже, а не расширением блока. */

/* Совсем узкий экран: в строку не влезает и так — поиск уходит вниз целиком,
   наверху остаются заголовок и кнопки. */
@media (max-width: 900px) {
  .section-head .project-search { order: 20; flex: 1 1 100%; max-width: none; }
  .section-head .dashboard-actions { margin-left: auto; }
}

/* Средние экраны (ноутбук с открытым сайдбаром): ужимаем строку управления,
   чтобы шесть кнопок и поиск остались в одном ряду. Замер на 1120px: доступно
   ~872px, а до сжатия ряд требовал ~955px. Экономим на полях кнопок (14→9px)
   и минимальной ширине поиска (220→150px) — этого хватает. */
@media (max-width: 1250px) {
  /* Замер на 1120px: доступно 832px, ряду нужно 175 (заголовок) + 478 (кнопки)
     + отступы. Поиску остаётся ~120px — этого хватает на иконку и несколько
     символов, а полное поле человек видит, как только окно шире. */
  .section-head { gap: 8px; }
  .section-head .dashboard-actions { gap: 6px; }
  .section-head .dashboard-actions .btn { padding: 0 9px; gap: 4px; }
  .section-head .project-search { min-width: 110px; }
}
