*, *::before, *::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

/* Все ссылки и активные кнопки — рука (force, не полагаемся на UA-defaults).
   Disabled-кнопки — стрелка (см. .nb-hbtn:disabled и аналогичные правила). */
a, button { cursor: pointer; }
button:disabled, button[disabled] { cursor: default; }

:root {
  --blue:        #1A8FE3;
  --blue-dark:   #1278C5;
  --blue-light:  #E8F4FD;
  --text:        #1A1A1A;
  /* #8E8E93 на белом давал контраст ~3.5:1 — ниже WCAG AA для мелкого текста.
     #6B6B70 даёт ~5.2:1. Применяется ко всем .preview / .label / .sub-надписям. */
  --text-muted:  #6B6B70;
  --border:      #E5E5EA;
  --bg:          #F8F8F8;
  --white:       #FFFFFF;
  --green:       #34C759;
  --orange:      #FF9500;
  --red:         #FF3B30;

  /* Мягкие статусные пары (фон + текст) для бейджей */
  --green-soft:        #DCF6E0;
  --green-soft-text:   #1A7F37;
  --orange-soft:       #FEEED4;
  --orange-soft-text:  #9B5400;
  --red-soft:          #FEE5E2;
  --red-soft-text:     #C72A1F;

  /* Прозрачные «тинты» для hover-эффектов и подсветок —
     согласованы с фирменными --blue / --red, не hardcoded */
  --blue-tint-hover:   rgba(26, 143, 227, 0.06);   /* var(--blue) с alpha 6% */
  --highlight:         var(--blue-light);          /* подсветка search-hit, выбора */
  --danger-bg-soft:    var(--red-soft);            /* фон destructive hover-row */
  --highlight-yellow:  #fff3a0;                    /* маркер поиска (намеренно ярко, вне основной палитры) */

  /* Размеры аватаров — стандартизированная шкала.
     До этого было «кто во что горазд»: 28/30/34/72 — нечитаемо на ретина,
     визуальный разнобой. Сейчас: 32px список, 36px модалки/header, 72px профиль.
     --av-md=36 чуть больше нативного iOS (34) — для лучшей читаемости имени рядом. */
  --av-sm:            32px;
  --av-md:            36px;
  --av-lg:            72px;

  --font:        -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --radius-sm:   8px;
  --radius-md:   12px;
  --header-h:    52px;
  --sidebar1-w:  263px;
  --sidebar2-w:  350px;
}

html, body {
  height: 100%;
  font-family: var(--font);
  color: var(--text);
  background: var(--bg);
  font-size: 14px;
  line-height: 1.5;
  /* MOBILE-FIRST: документ сам скроллится (overflow:auto), на десктопе
     переопределяем в hidden — там скрол идёт внутри .main.
     overflow-x: hidden — жёстко запрещает гориз.скрол страницы. Если элементу
     нужен hor.scroll (mail-tabs), пусть скроллится внутри себя. */
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* MOBILE-FIRST: .app растёт по контенту, document скроллится.
   На десктопе (@media min-width: 769px ниже) переключаемся на fixed-viewport
   модель со split-view: .app фиксируется на 100dvh, скрол идёт внутри .main.
   100dvh = «динамическая» высота вьюпорта (без URL-бара iOS). */
.app {
  display: flex;
  width: 100vw;
  min-height: 100vh;
  min-height: 100dvh;
  position: relative;
}

.sidebar {
  width: var(--sidebar1-w);
  min-width: var(--sidebar1-w);
  background: var(--white);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  box-shadow: 2px 0 4px rgba(0,0,0,0.08);
  z-index: 10;
}

.sidebar-logo {
  height: var(--header-h);
  padding: 0 16px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

.sidebar-logo-icon {
  width: 30px;
  height: 30px;
  background: var(--blue);
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.sidebar-logo-icon img {
  width: 18px;
  height: 18px;
  filter: brightness(0) invert(1);
}

.sidebar-logo-text {
  font-size: 16px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: -0.3px;
}

.sidebar-nav {
  flex: 1;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow-y: auto;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-size: 14px;
  font-weight: 400;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s, color 0.15s;
}

/* Иконки nav рендерятся как mask-container: фон = currentColor, форма = SVG.
   Так корпоративный --blue точно применяется к активным иконкам, а
   text-muted к неактивным. SVG-stroke="currentColor" внутри img не работает
   (изолированный документ), отсюда workaround через mask. */
.nav-item .nav-ico {
  width: 18px;
  height: 18px;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;  mask-repeat: no-repeat;
  -webkit-mask-position: center;   mask-position: center;
  -webkit-mask-size: contain;      mask-size: contain;
  /* color наследуется от .nav-item (var(--text-muted) для обычных,
     var(--blue) для .active, var(--text) для :hover). Так иконка
     ВСЕГДА в точности того же цвета что и соседний текст пункта меню. */
  color: inherit;
  transition: background-color 0.15s;
}
/* Подключаем mask для каждой иконки.
   Stroke-версии (контурные) с явным stroke="#000" — silhouette из тонких
   линий, мaask работает по alpha-каналу. При активности меняется ТОЛЬКО
   цвет (color), не картинка — единый паттерн на всех навбарах. */
#nav-dashboard .nav-ico { -webkit-mask-image: url('images/icon-home.svg');      mask-image: url('images/icon-home.svg'); }
#nav-calendar  .nav-ico { -webkit-mask-image: url('images/icon-calendar.svg');  mask-image: url('images/icon-calendar.svg'); }
#nav-mail      .nav-ico { -webkit-mask-image: url('images/icon-mail.svg');      mask-image: url('images/icon-mail.svg'); }
#nav-chat      .nav-ico { -webkit-mask-image: url('images/icon-chat.svg');      mask-image: url('images/icon-chat.svg'); }
#nav-notebook  .nav-ico { -webkit-mask-image: url('images/icon-notebook.svg');  mask-image: url('images/icon-notebook.svg'); }
#nav-directory .nav-ico { -webkit-mask-image: url('images/icon-directory.svg'); mask-image: url('images/icon-directory.svg'); }
#nav-finance   .nav-ico { -webkit-mask-image: url('images/icon-finance.svg');   mask-image: url('images/icon-finance.svg'); }
#nav-god       .nav-ico { -webkit-mask-image: url('images/icon-god.svg');       mask-image: url('images/icon-god.svg'); }

/* Раздел «Финансы» — только для пользователя с ролью admin (на сейчас
   единственный — Слав). По умолчанию пункт скрыт во всех местах; показываем
   когда profile.js подтвердил роль и добавил body.has-finance. Flash-free. */
#nav-finance,
.app-drawer-link[href="finance.html"] { display: none; }
body.has-finance #nav-finance               { display: flex; }
body.has-finance .app-drawer-link[href="finance.html"] { display: flex; }
/* На мобиле в bottom-nav «Финансы» убрана даже у admin — попасть туда
   только через выезжающий drawer слева (иконка Штабеля). */
@media (max-width: 768px) {
  body.has-finance #nav-finance { display: none !important; }
}

.nav-item:hover {
  background: var(--bg);
  color: var(--text);
}

.nav-item.active {
  background: var(--blue-light);
  color: var(--blue);
  font-weight: 500;
}

.nav-badge {
  margin-left: auto;
  background: var(--blue);
  color: var(--white);
  font-size: 11px;
  font-weight: 600;
  padding: 2px 6px;
  border-radius: 999px;
  min-width: 18px;
  text-align: center;
}

.sidebar-profile {
  height: var(--header-h);
  border-top: 1px solid var(--border);
  /* padding-left == padding .sidebar-nav (8px) — левый край аватара
     совпадает с левым краем подложки активного пункта меню.
     Горизонтальный padding у .profile-item обнулён (см. ниже), чтобы
     избежать двойного отступа. */
  padding: 0 8px;
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.profile-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  border-radius: var(--radius-sm);
  /* Не кликабельный — клик-логика ушла в шестерёнку (.sidebar-gear) */
  cursor: default;
  transition: background 0.15s;
}

/* .profile-item:hover убран — карточка не интерактивна */

.avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--blue-light);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 600;
  color: var(--blue);
  flex-shrink: 0;
}

.profile-name {
  font-size: 13px;
  color: var(--text);
  font-weight: 500;
  line-height: 1.2;
}

.profile-role {
  font-size: 11px;
  color: var(--text-muted);
}

/* Десктоп: шестерёнка-настройки справа в `.sidebar-profile`. На мобиле
   скрывается вместе с .sidebar-profile (см. media-query ниже). */
.sidebar-gear {
  flex-shrink: 0;
  width: 32px; height: 32px;
  border: none;
  /* Состояния — по аналогии с .nav-item: покой серый без подложки,
     наведение/фокус темнее + серая подложка, активная (на своей странице)
     синяя + синяя подложка. */
  background: transparent;
  color: var(--text-muted);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  margin-left: auto;
  transition: background 0.15s, color 0.15s;
}
.sidebar-gear:hover,
.sidebar-gear:focus-visible { background: var(--bg); color: var(--text); outline: none; }
.sidebar-gear.active { background: var(--blue-light); color: var(--blue); }
.sidebar-gear svg { width: 18px; height: 18px; }

/* Блок компании в подвале сайдбара (над блоком пользователя). Зеркало
   .sidebar-profile: логотип соразмерен аватару (30px), текст НЕ кликабелен —
   действие только у шестерёнки. Черты сверху нет. */
.sidebar-company {
  height: var(--header-h);
  padding: 0 8px;
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.company-item {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  cursor: default;
}
.company-text { min-width: 0; }
.company-logo {
  width: 30px;
  height: 30px;
  border-radius: 7px;
  background: var(--blue);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 600;
  overflow: hidden;
  flex-shrink: 0;
}
.company-logo img { width: 100%; height: 100%; object-fit: cover; }
.company-name {
  font-size: 13px;
  color: var(--text);
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.company-sub {
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ============================================================
   Десктоп: панель «Настройки» — второй sidebar, выезжает СЛЕВА направо
   при клике на шестерёнку в .sidebar-profile. Поверх основного sidebar
   (z-index выше), той же ширины. На мобиле скрывается (там свой drawer).
   ============================================================ */
.settings-sidebar {
  position: fixed;
  top: 0; left: 0; bottom: 0;
  width: var(--sidebar1-w);
  min-width: var(--sidebar1-w);
  background: var(--white);
  border-right: 1px solid var(--border);
  box-shadow: 2px 0 12px rgba(0,0,0,0.10);
  display: flex;
  flex-direction: column;
  z-index: 20;                /* .sidebar = 10 */
  transform: translateX(-100%);
  transition: transform 0.22s ease;
}
.settings-sidebar.open { transform: translateX(0); }
/* Применяется при восстановлении состояния «панель была открыта» —
   глушит slide-анимацию на один кадр, чтобы пластина появилась
   мгновенно (юзеру кажется, что она и не закрывалась). */
.settings-sidebar.settings-no-anim { transition: none !important; }

/* Шапка: ← Назад | Настройки | ✕  — выровнено на ту же высоту, что
   .sidebar-logo (var(--header-h)), чтобы заголовок «Настройки» сидел
   ровно на той же горизонтали, что и логотип «Штабель» в основном sidebar. */
.settings-sidebar-header {
  height: var(--header-h);
  flex-shrink: 0;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center;
  padding: 0 8px;
  gap: 8px;
}
.settings-sidebar-back,
.settings-sidebar-close {
  flex-shrink: 0;
  width: 32px; height: 32px;
  border: none; background: transparent;
  color: var(--text-muted);
  border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.settings-sidebar-back:hover,
.settings-sidebar-close:hover {
  background: var(--bg);
  color: var(--text);
}
.settings-sidebar-title {
  flex: 1;
  text-align: center;
  font-size: 16px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: -0.3px;
}

/* Тело — пункты в том же стиле, что .nav-item основного sidebar */
.settings-sidebar-nav {
  flex: 1;
  padding: 8px;
  display: flex; flex-direction: column;
  gap: 2px;
  overflow-y: auto;
}
.settings-sidebar-nav .settings-nav-item.danger {
  color: #c0392b;
}
.settings-sidebar-nav .settings-nav-item.danger:hover {
  background: #fdecea;
  color: #c0392b;
}
/* Иконки внутри пунктов «Настроек» — inline SVG (а не mask), потому что
   SVG сами по себе stroke=currentColor. Размер выравниваем с .nav-item: 18×18. */
.settings-nav-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px;
  color: inherit;
}
.settings-nav-ico svg {
  width: 18px; height: 18px;
}

/* Мобиль: панель не нужна (там свой drawer с экраном «Настройки») */
@media (max-width: 768px) {
  .settings-sidebar { display: none !important; }
}

/* MOBILE-FIRST: .main с padding под нижнюю навигацию.
   14px по периметру (включая верх) — даёт симметричную «рамку» вокруг контента
   и совпадает с вертикалью иконки Штабеля и кнопки «+» (обе на top: 14px).
   60px = высота bottom-nav, +env(safe-area-inset-bottom) для iOS home-indicator,
   +14px breathing — чтобы последняя карточка не упиралась в нижнюю навигацию.
   PWA-режим (Safari → На экран домой): добавляем env(safe-area-inset-top)
   к верхнему padding — без этого контент уезжает ПОД статус-бар iPhone. */
.main {
  flex: 1;
  position: relative;
  padding-top: calc(14px + env(safe-area-inset-top, 0px));
  padding-left: calc(14px + env(safe-area-inset-left, 0px));
  padding-right: calc(14px + env(safe-area-inset-right, 0px));
  padding-bottom: calc(75px + env(safe-area-inset-bottom, 0px) + 14px);
  background: var(--bg);
  min-width: 0;          /* предотвращает горизонтальный «расхлоп» flex-item'а */
}

/* Полноэкранные разделы (Блокнот/Чат): контент занимает всю высоту .main без
   padding — как .nb-layout жил прямо в .app в проде. Внутренний скролл берут на
   себя дочерние панели. Мобильный .main {overflow-y:auto} тоже гасим. */
.main--nb,
.main--chat,
.main--dir {
  display: flex;
  flex-direction: column;
  overflow: hidden !important;
  padding: 0 !important;
}

/* ============================================================
   MOBILE-FIRST блок для базовых property-flip'ов.
   Mobile-значения = дефолт, desktop добавляется через @media (min-width: 769px).
   До рефакторинга было наоборот: desktop был дефолтом, mobile перебивал через
   @media (max-width: 768px) с !important. Теперь !important не нужен.
   Этот блок постепенно растёт по мере того, как новые правила переезжают
   из старого @media (max-width: 768px) сюда (мобильное = база).
   ============================================================ */
.page-title {
  font-size: 20px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 4px;
  letter-spacing: -0.3px;
}
/* Подзаголовок на мобиле скрыт — место экономим, и так понятно по контексту */
.page-subtitle {
  display: none;
  font-size: 13px;
  color: var(--text-muted);
  margin-bottom: 24px;
}

.metrics {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 24px;
}

/* Инпуты ≥16px — iOS не зумит при фокусе на поле. На десктопе 16px тоже норм,
   так что просто делаем mobile-first дефолт без desktop-override. */
input[type="text"], input[type="email"], input[type="password"],
input[type="search"], input[type="tel"], textarea, select {
  font-size: 16px;
}

@media (min-width: 769px) {
  .page-title    { font-size: 22px; }
  .page-wrap > .page-title { margin: 0 0 4px; }
  .page-subtitle { display: block; }
  .metrics       { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  /* .main padding и tabs height на десктопе — смотри основной блок
     в @media (min-width:1024px) ниже (строка ~1890). */
}

.metric-card {
  background: var(--white);
  border-radius: var(--radius-md);
  padding: 16px 18px;
  border: 1px solid var(--border);
}

.metric-label { font-size: 12px; color: var(--text-muted); margin-bottom: 6px; }
.metric-value { font-size: 26px; font-weight: 600; color: var(--text); letter-spacing: -0.5px; }
.metric-value.green  { color: var(--green-soft-text); }
.metric-value.red    { color: var(--red-soft-text); }
.metric-value.orange { color: var(--orange-soft-text); }

.widgets {
  display: grid;
  /* MOBILE-FIRST: одна колонка; на десктопе — две (см. @media min-width: 769px) */
  grid-template-columns: 1fr;
  gap: 16px;
}

.widget {
  background: var(--white);
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  padding: 18px;
}

.widget-title { font-size: 15px; font-weight: 600; color: var(--text); margin-bottom: 14px; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 20px;
  border-radius: var(--radius-md);
  font-size: 14px;
  font-weight: 600;
  font-family: var(--font);
  border: none;
  cursor: pointer;
  transition: background 0.2s, transform 0.1s;
}

.btn-primary { background: var(--blue); color: var(--white); }
.btn-primary:hover  { background: var(--blue-dark); }
.btn-primary:active { transform: scale(0.98); }
.btn-ghost { background: none; color: var(--blue); border: 1px solid var(--border); }
.btn-ghost:hover { background: var(--bg); }

.employee-list { display: flex; flex-direction: column; gap: 8px; }
/* Карточка-плитка по образцу календарной «Сегодня на смене»:
   белый фон + лёгкая обводка + скругление + мягкая тень. Единый вид
   для всех карточек-списков по разделам. */
.employee-item {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--white);
  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
  cursor: pointer;
  transition: border-color .12s, box-shadow .12s;
}
.employee-item:hover { border-color: var(--blue); box-shadow: 0 2px 8px rgba(0,0,0,0.10); }
.employee-info { flex: 1; min-width: 0; }
.employee-name { font-size: 13px; font-weight: 500; color: var(--text); }
.employee-place { font-size: 11px; color: var(--text-muted); }

.status-badge { font-size: 11px; font-weight: 500; padding: 2px 7px; border-radius: 999px; border: 1px solid color-mix(in srgb, currentColor 50%, transparent); }
.status-badge.green  { background: var(--green-soft); color: var(--green-soft-text); }
.status-badge.orange { background: var(--orange-soft); color: var(--orange-soft-text); }
.status-badge.red    { background: var(--red-soft); color: var(--red-soft-text); }

.task-list { display: flex; flex-direction: column; gap: 8px; }
.task-item {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--white);
  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
  cursor: pointer;
  transition: border-color .12s, box-shadow .12s;
}
.task-item:hover { border-color: var(--blue); box-shadow: 0 2px 8px rgba(0,0,0,0.10); }

.task-check {
  width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--border); flex-shrink: 0;
}
.task-check.done {
  background: var(--green); border-color: var(--green);
  display: flex; align-items: center; justify-content: center;
}
.task-check.done::after {
  content: '';
  width: 8px; height: 5px;
  border-left: 2px solid #fff;
  border-bottom: 2px solid #fff;
  transform: rotate(-45deg) translateY(-1px);
}

.task-text { flex: 1; font-size: 13px; color: var(--text); }
.task-text.done { text-decoration: line-through; color: var(--text-muted); }
.task-due {
  font-size: 11px;
  font-weight: 500;
  padding: 2px 8px;
  border-radius: 999px;
}
.task-due.orange { background: var(--orange-soft); color: var(--orange-soft-text); }
.task-due.red    { background: var(--red-soft);    color: var(--red-soft-text); }

.tabs { display: flex; background: var(--bg); border-radius: var(--radius-sm); padding: 3px; gap: 2px; margin-bottom: 14px; }
.tab { flex: 1; text-align: center; padding: 7px; border-radius: 6px; font-size: 13px; font-weight: 500; color: var(--text-muted); cursor: pointer; transition: background 0.15s, color 0.15s; }
.tab.active { background: var(--white); color: var(--text); box-shadow: 0 1px 3px rgba(0,0,0,0.08); }

.flex-between { display: flex; align-items: center; justify-content: space-between; }

/* ============================================================
   Сообщения (используется в chat.html и notebook.html)
   ============================================================ */

.msg-in  { display: flex; justify-content: flex-start; gap: 8px; align-items: flex-end; }
.msg-out { display: flex; justify-content: flex-end; }

.msg-av {
  width: 26px; height: 26px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 600;
  flex-shrink: 0;
  background: var(--blue-light); color: var(--blue);
}

.msg-in-body {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: flex-start;
}

/* Пузырьки — max-width 80%, классический мессенджер-стиль:
   входящие — светло-серый с тёмным текстом (iMessage/Telegram). */
.bubble-in  { max-width: 80%; background: #E5E5EA; color: var(--text); border-radius: 0 12px 12px 12px; padding: 9px 12px; }
.bubble-out { max-width: 80%; background: var(--blue);  border-radius: 12px 0 12px 12px; padding: 9px 12px; }

/* Заголовок ВНУТРИ пузырька: маленький аватар-кружок + имя автора синим.
   Используется в групповых чатах и комментариях задач (Telegram-стиль). */
.msg-head-in {
  display: flex; align-items: center; gap: 6px;
  margin-bottom: 4px;
}
.msg-av-in {
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--blue-light); color: var(--blue);
  font-size: 9px; font-weight: 600;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.msg-name-in {
  font-size: 12px; font-weight: 600;
  color: var(--blue);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Личный чат — без msg-head-in (нет имени и аватара), пузырёк с полностью равными углами */
.msg-in.personal .bubble-in { border-radius: 12px 12px 12px 12px; }

.msg-name { font-size: 11px; color: var(--text-muted); margin-bottom: 3px; }
.msg-ti   { font-size: 13px; color: var(--text); }
.msg-to   { font-size: 13px; color: #fff; }

.msg-meta { margin-top: 4px; display: flex; align-items: center; justify-content: flex-end; gap: 4px; }
.time-i { font-size: 10px; color: var(--text-muted); }
.time-o { font-size: 10px; color: rgba(255,255,255,0.85); }

/* Поле ввода сообщения */
.msg-input-area {
  height: var(--header-h);
  padding: 0 16px;
  border-top: 1px solid var(--border);
  display: flex; align-items: center; gap: 8px;
  flex-shrink: 0;
  background: var(--white);
}
.msg-input-wrap {
  flex: 1; display: flex; align-items: center;
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 0 4px 0 12px;
  /* :focus-visible не срабатывает при клике мышью; используем :focus-within
     чтобы рамка появлялась и при тапе по полю, и при tab-focus */
  box-shadow: inset 0 0 0 1px transparent;
  transition: background 0.12s, box-shadow 0.12s;
}
.msg-input-wrap:focus-within {
  background: var(--white);
  box-shadow: inset 0 0 0 1px var(--blue);
}
.msg-input-wrap input,
.msg-input-wrap textarea {
  flex: 1; border: none; outline: none;
  font-size: 13px; color: var(--text);
  background: transparent;
  font-family: var(--font);
  caret-color: var(--blue);          /* как у поисков — заметная синяя каретка */
  padding-left: 3px;                 /* лёгкий отступ от иконки/левого края */
  resize: none;                       /* без ручного ресайза, авто-grow в JS */
  line-height: 1.4;
  max-height: 140px;                  /* потолок ~6 строк, дальше scroll */
  overflow-y: auto;
  padding-top: 7px; padding-bottom: 7px;
}
.msg-input-wrap input::placeholder,
.msg-input-wrap textarea::placeholder { color: var(--text-muted); }

.clip-btn {
  width: 30px; height: 30px;
  border: none; background: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-muted);
}
.clip-btn:hover { color: var(--blue); }

.send-btn {
  background: var(--blue); color: #fff;
  border: none; border-radius: var(--radius-sm);
  padding: 8px 14px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.2s;
}
.send-btn:hover { background: var(--blue-dark); }

/* ============================================================
   Галочки прочитанности (chat.html, notebook.html)
   ============================================================ */
.chat-checks, .nb-checks { color: var(--blue); }
.chat-checks.muted, .nb-checks.muted { color: var(--text-muted); }
.chat-checks svg, .nb-checks svg { stroke: currentColor; }

/* ============================================================
   Focus-visible: видимая обводка при tab-навигации
   ============================================================ */
:focus { outline: none; }

/* Синяя focus-обводка — только на устройствах с настоящим указателем (клавиатура/мышь).
   На тач-устройствах никогда не показываем (раздражает при тапе). */
@media (hover: hover) and (pointer: fine) {
  :focus-visible {
    outline: 2px solid var(--blue);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
  }
}

/* На круглых элементах (аватары, бейджи, кружки) делаем обводку круглой */
.avatar:focus-visible,
.mail-av:focus-visible,
.msg-av:focus-visible,
.nav-badge:focus-visible,
.chat-badge:focus-visible {
  border-radius: 50%;
}

/* ============================================================
   ОБЩАЯ ОБОЛОЧКА КОНТЕНТА — одинаковая на всех страницах.
   Контент центрируется в окне с равными отступами от бортов.
   ============================================================ */
.page-wrap {
  padding: 12px 14px;
  width: 100%;
  box-sizing: border-box;
}
/* На широких экранах добавляем воздуха по бокам — иначе контент
   приклеен к бортам, выглядит дешёво. Постепенный рост через clamp
   позволил бы то же самое одной строкой, но явные брейкпойнты проще
   читать и отлаживать. */
@media (min-width: 1280px) {
  .page-wrap { padding: 12px 24px; }
}
@media (min-width: 1600px) {
  .page-wrap { padding: 16px 32px; }
}
/* MOBILE-FIRST: 18px воздуха до табов/контента. Desktop переопределяет в 4px
   (компактнее когда сразу под заголовком идёт подзаголовок). */
.page-wrap > .page-title { margin: 0 0 18px; }
/* Подзаголовок (описание раздела) скрыт глобально — и на десктопе, и на мобиле.
   Был «Личные диалоги, группы…» / «Заметки и задачи» и т.д. */
.page-subtitle { display: none !important; }
.page-wrap > .page-subtitle { margin: 0 0 18px; }

/* Стандартная a11y-утилита: визуально скрывает, оставляет для screen-readers.
   Применяется только на ДЕСКТОПЕ — на мобиле titles нужны (sidebar
   скрыт, видна только bottom-nav без подписей). */
@media (min-width: 769px) {
  .visually-hidden {
    position: absolute !important;
    width: 1px !important; height: 1px !important;
    padding: 0 !important; margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
  }
}

/* ============================================================
   ОБЩИЕ ТАБЫ + ТУЛБАР (паттерн справочника) — используются на всех
   страницах со списочным контентом: справочник, блокнот, почта, etc.
   ============================================================ */
.dir-tabs {
  display: flex; gap: 4px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 16px;
}
.dir-tab {
  padding: 10px 16px; cursor: pointer; user-select: none;
  font-size: 13px; color: var(--text-muted);
  background: none; border: none; border-bottom: 2px solid transparent;
  font-family: var(--font);
  transition: color .12s, border-color .12s;
}
.dir-tab:hover  { color: var(--text); }
.dir-tab.active { color: var(--blue); border-bottom-color: var(--blue); font-weight: 500; }

.dir-toolbar {
  display: flex; gap: 10px; align-items: center; margin-bottom: 14px;
}
/* Кнопка «+ Добавить» всегда прижата вправо, что бы ни стояло между ней и поиском */
.dir-toolbar > .dir-add-btn { margin-left: auto; }
.dir-search {
  flex: 1; max-width: 320px;
  background: var(--white); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 7px 10px;
  display: flex; align-items: center; gap: 8px;
  transition: border-color .12s;
}
/* Активное (в фокусе) поле поиска — синяя рамка, как «обводка» у чат-поиска.
   Серую рамку в покое оставляем. */
.dir-search:focus-within { border-color: var(--blue); }
/* Шрифт-семья для всего блока .dir-search — чтобы и input, и <select> с этим
   классом использовали корпоративный шрифт (а не системный default Safari). */
.dir-search { font-family: var(--font); color: var(--text); }
.dir-search input {
  flex: 1; border: none; outline: none;
  font-family: var(--font); font-size: 13px; color: var(--text);
  background: transparent; caret-color: var(--blue);
  /* Левый отступ 3px — чтобы моргающая каретка была видна целиком, а не
     прижата к краю (как в чат-поиске .chat-search-inner). */
  padding: 0 0 0 3px; cursor: text;
}
/* <select class="dir-search"> — выпадающие фильтры. Семья + размер 15px:
   подгоняем под заголовок карточек (.row-title 15px/500). */
select.dir-search {
  font-family: var(--font); font-size: 15px; font-weight: 500; color: var(--text);
}
.dir-add-btn {
  padding: 7px 14px; background: var(--blue); color: white;
  border: none; border-radius: var(--radius-sm);
  font-family: var(--font); font-size: 13px; cursor: pointer;
}
.dir-add-btn:hover { background: var(--blue-dark); }

@media (max-width: 768px) {
  .dir-tabs { overflow-x: auto; white-space: nowrap; gap: 0; }
  .dir-tab  { flex-shrink: 0; padding: 10px 12px; }
  .dir-toolbar { flex-wrap: wrap; gap: 8px; padding: 0; }
  /* Пустой <span style="flex:1"> служит спейсером на десктопе.
     На мобиле он переносится на новую строку и съедает +8px высоты
     (gap у toolbar). Прячем его — кнопка «+» всё равно position:absolute. */
  .dir-toolbar > span { display: none !important; }
  .dir-toolbar > .dir-search,
  .dir-toolbar .dir-search {
    max-width: none !important; width: 100% !important;
    flex: 1 1 100% !important;
  }
  /* На мобиле input внутри .dir-search должен быть 16px (no-zoom iOS), а не 13.
     Селект тоже 16px (visually близко к 15px заголовка карточки). */
  .dir-search input { font-size: 16px; }
  select.dir-search { font-size: 16px; }
  .dir-add-btn { width: 100%; }
}

/* ============================================================
   .dir-table — единая «таблица-список» (слитные карточки на десктопе,
   раздельные карточки на мобиле). Используется в справочнике и блокноте.
   ============================================================ */
.dir-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--white);
  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
  table-layout: auto;
}
.dir-table th, .dir-table td {
  padding: 10px 14px; text-align: left;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
  border-right:  1px solid var(--border);  /* вертикальные разделители колонок */
  overflow: hidden;                         /* при сужении колонки текст обрезается, не вылазит на соседа */
}
/* Если у таблицы есть класс .dir-table--fit — все колонки кроме помеченной
   data-grow жмутся по содержимому слева. Используем класс (а не :has()),
   чтобы работало во всех браузерах одинаково. */
.dir-table--fit th:not([data-grow]),
.dir-table--fit td:not([data-grow]) {
  width: 1px; white-space: nowrap;
}
.dir-table th:last-child,
.dir-table td:last-child { border-right: none; }
.dir-table th {
  color: var(--text); font-weight: 600;
  background: #ECECF0;          /* серый на пару тонов темнее фона (--bg #F8F8F8) */
  font-size: 11px;
  text-transform: uppercase; letter-spacing: 0.5px;
  position: relative;
  user-select: none;
  white-space: nowrap;
  border-bottom: 1px solid var(--border);
  border-right-color: rgba(0,0,0,0.05);
}
/* Колонка-резинка: занимает всё оставшееся место. Помечается в HTML
   атрибутом data-grow — на th и td одновременно. white-space не трогаем —
   локальные классы (chat-row-preview и т.п.) сами решают, обрезать ли ellipsis'ом. */
.dir-table th[data-grow],
.dir-table td[data-grow] { width: auto; }


/* Бейдж непрочитанных сообщений (например, в первом столбце таблиц с чатами).
   Перенесён из chat.html для использования во всех разделах. */
.chat-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 9px; background: var(--blue); color: white;
  font-size: 10px; font-weight: 600;
}

/* Бейджи приоритета и статуса задач — общие для notebook.html и chat.html. */
.nb-badge, .nb-badge-status {
  font-size: 11px; font-weight: 500; padding: 1px 7px; border-radius: 999px;
  flex-shrink: 0; display: inline-block;
  border: 1px solid color-mix(in srgb, currentColor 50%, transparent);
}
.nb-badge.urgent     { background: var(--red-soft);    color: var(--red-soft-text); }
.nb-badge.important  { background: var(--orange-soft); color: var(--orange-soft-text); }
.nb-badge.current    { background: var(--green-soft);  color: var(--green-soft-text); }
.nb-badge.done       { background: var(--bg);          color: var(--text-muted); }
.nb-badge-status.new     { background: var(--orange-soft); color: var(--orange-soft-text); }
.nb-badge-status.inwork  { background: var(--blue-light);  color: var(--blue); }
.nb-badge-status.done    { background: var(--green-soft);  color: var(--green-soft-text); }
.nb-badge-status.closed  { background: var(--bg);          color: var(--text-muted); }

/* Архивная таблица — тело приглушено, шапка нужна СТРУКТУРНО (table-layout:fixed
   без видимой шапки ломает widths колонок). Делаем её узкой и тихой, чтобы
   визуально не повторяла основную, но колонки держала. */
.dir-table.archived,
.dir-table.archived td { color: var(--text-muted); }
.dir-table.archived tbody tr { background: var(--bg); }
@media (hover: hover) and (pointer: fine) {
  .dir-table.archived tbody tr:hover { background: var(--blue-tint-hover); }
}
/* Архивная таблица: шапка нужна структурно (table-layout без thead ломается),
   но визуально полностью прячем — все дочерние элементы (текст, SVG галочек,
   resizer'ы) убираем display:none, и сам th схлопывается до тонкой линии. */
.dir-table.archived thead th {
  padding: 0; height: 0; line-height: 0;
  font-size: 0; color: transparent;
  border-bottom: none;
  background: transparent;
}
.dir-table.archived thead th > * { display: none; }
.dir-table thead { border-bottom: 1px solid var(--border); }
.dir-table tbody tr {
  cursor: pointer; transition: background .12s, box-shadow .12s;
  -webkit-tap-highlight-color: transparent;   /* iOS системная серая подсветка тапа — выкл */
}
.dir-table tbody tr.active,
.dir-table tbody tr.selected { background: var(--blue-light); }        /* выделение — фирменный голубой */
/* Hover ТОЛЬКО на устройствах с настоящим указателем (десктоп). */
@media (hover: hover) and (pointer: fine) {
  .dir-table tbody tr:hover { background: var(--blue-tint-hover); }   /* лёгкий синий тинт */
}
.dir-table td.muted { color: var(--text-muted); }
.dir-table td.actions { text-align: right; white-space: nowrap; }

/* Resize-хэндл колонок — всегда виден тонкой полоской, толстеет и синеет при hover/drag */
.col-resizer {
  position: absolute; right: -1px; top: 25%;
  width: 2px; height: 50%;
  cursor: col-resize;
  background: var(--border);
  transition: background .12s, width .12s, top .12s, height .12s;
  z-index: 2;
}
.col-resizer:hover,
.col-resizer.active {
  background: var(--blue);
  width: 3px;
  top: 0; height: 100%;
}
.dir-table th:last-child .col-resizer { display: none; }
@media (max-width: 768px) { .col-resizer { display: none; } }

.dir-empty {
  padding: 40px 20px; text-align: center;
  color: var(--text-muted); font-size: 13px;
}

.badge {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 1px 7px;
  border-radius: 999px; font-size: 11px; font-weight: 500;
  /* Обводка 1px в полупрозрачном тоне текста бейджа — как у .nb-badge-status
     в задачах. Делает бейдж визуально «плотнее» и одинаковым со статусами
     в блокноте. color-mix даёт 50% непрозрачный currentColor — подсвечивается
     лёгкая рамка ровно в цвет текста. */
  border: 1px solid color-mix(in srgb, currentColor 50%, transparent);
}

@media (max-width: 768px) {
  /* Таблица превращается в стек блочных карточек. Важно: сама <table>
     тоже становится block — иначе table-layout:fixed + скрытый thead
     даёт колонки шириной 0px (и текст в td становится невидимым). */
  .dir-table {
    display: block !important;
    table-layout: auto !important;
    background: transparent; box-shadow: none;
    width: 100%;
  }
  /* Десктопный трюк «width:1px на колонках без data-grow для усадки по содержимому»
     ломает мобильный стек — колонки остаются шириной 1px. Сбрасываем. */
  .dir-table--fit th:not([data-grow]),
  .dir-table--fit td:not([data-grow]) { width: auto !important; white-space: normal !important; }
  .dir-table thead { display: none; }
  .dir-table tbody { display: block; }
  /* Карточка-строка по образцу .mail-card (см. mail.html):
     grid 2 колонки (контент | дата-метка справа сверху), точка-индикатор
     в правом нижнем углу. Единый вид для чатов/задач/лидов/заметок. */
  .dir-table tr {
    display: grid !important;
    grid-template-columns: 1fr auto;
    column-gap: 8px; row-gap: 3px;
    align-items: center;
    width: 100%;
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    /* padding-top: 11 (а не 12) — border-top 1px + padding 11 = 12 от внешнего
       края карточки до заголовка. Совпадает с .mail-card (которая считает
       расстояние от outer-края card-а до title тоже как 12). */
    padding: 11px 14px 12px;
    margin-bottom: 8px;
    box-shadow: 0 1px 4px rgba(0,0,0,0.06);
    transition: border-color .12s, box-shadow .12s;
    position: relative;
  }
  /* Hover-эффект карточки ТОЛЬКО на устройствах с настоящим указателем
     (десктоп). На iOS Safari touch ставит sticky-:hover и держит синюю
     обводку — именно поэтому раньше карточка «светилась» под пальцем. */
  @media (hover: hover) and (pointer: fine) {
    .dir-table tr:hover {
      border-color: var(--blue); background: var(--white);
      box-shadow: 0 2px 8px rgba(0,0,0,0.10);
    }
  }
  .dir-table td {
    display: block; border: none; padding: 0;
    font-size: 12px; line-height: 16px; height: 16px;
    color: var(--text-muted);
    text-align: left;
    /* По умолчанию td уезжают в строку 1 колонку 1 — конкретные классы
       ниже переопределяют для каждого типа таблицы. */
    grid-column: 1; grid-row: 1;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  /* «Подпись карточки» (имя/тема) — большой жирный текст в первом ряду.
     align-self: start — принудительно прижимает заголовок к ВЕРХУ grid-ячейки.
     Без этого align-items: center у .dir-table tr центрирует заголовок,
     и если соседний td в row 1 (бейдж) выше 18px из-за padding, заголовок
     уезжает вниз на 1-2px → визуально title оказывается дальше от верха
     карточки (13px вместо 12). */
  .dir-table .row-title,
  .chat-row-name {
    align-self: start;
    display: block;
    font-weight: 500; font-size: 14px !important; line-height: 16px; height: 16px;
    color: var(--text);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }

  /* ===== CHAT/GROUPS/OBJECTS/TASK-CHATS =====
     Карточка ровно в 3 строки: имя (1), превью (2 строки = 32px фикс.).
     Аватар на всю высоту контента (3 ряда × 16 = 48px) слева. */
  .dir-table[data-table="chats"] tr,
  .dir-table[data-table="groups"] tr,
  .dir-table[data-table="chat_objects"] tr,
  .dir-table[data-table="tasks_chats"] tr {
    grid-template-columns: 48px 1fr auto;
    grid-template-rows: 16px 16px 16px;
    column-gap: 12px;
  }
  /* Статус (✓✓ / непрочтённое) — абсолютно справа снизу */
  .dir-table[data-table="chats"] tr > td:nth-child(1),
  .dir-table[data-table="groups"] tr > td:nth-child(1),
  .dir-table[data-table="chat_objects"] tr > td:nth-child(1),
  .dir-table[data-table="tasks_chats"] tr > td:nth-child(1) {
    position: absolute; right: 14px; bottom: 12px;
    grid-column: unset; grid-row: unset;
    height: auto; width: auto;
    text-align: right !important;
  }
  /* Время — правый столбец верхнего ряда */
  .dir-table[data-table="chats"] tr > td:nth-child(2),
  .dir-table[data-table="groups"] tr > td:nth-child(2),
  .dir-table[data-table="chat_objects"] tr > td:nth-child(2),
  .dir-table[data-table="tasks_chats"] tr > td:nth-child(2) {
    grid-column: 3; grid-row: 1; text-align: right;
    font-size: 11px;
  }
  /* Имя+аватар-ячейка — занимает левую колонку (аватар) + средний верх (имя) */
  .dir-table[data-table="chats"] tr > td.chat-row-name-cell,
  .dir-table[data-table="groups"] tr > td.chat-row-name-cell,
  .dir-table[data-table="chat_objects"] tr > td.chat-row-name-cell,
  .dir-table[data-table="tasks_chats"] tr > td.chat-row-name-cell {
    grid-column: 1 / 3; grid-row: 1;
    display: contents;   /* распускаем вложенные span'ы в grid */
  }
  /* Аватар (внутри chat-row-name-cell) — на 3 строки сетки слева */
  .dir-table[data-table="chats"] tr .chat-row-av,
  .dir-table[data-table="groups"] tr .chat-row-av,
  .dir-table[data-table="chat_objects"] tr .chat-row-av,
  .dir-table[data-table="tasks_chats"] tr .chat-row-av {
    grid-column: 1; grid-row: 1 / 4;
    width: 48px; height: 48px;
    border-radius: 50%;
    background: var(--blue-light); color: var(--blue);
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 13px; font-weight: 600;
    align-self: center;
  }
  .dir-table[data-table="chats"] tr .chat-row-av.group,
  .dir-table[data-table="groups"] tr .chat-row-av.group,
  .dir-table[data-table="chat_objects"] tr .chat-row-av.group,
  .dir-table[data-table="tasks_chats"] tr .chat-row-av.group { border-radius: var(--radius-sm); }
  /* Имя — средняя колонка, ряд 1 */
  .dir-table[data-table="chats"] tr .chat-row-name,
  .dir-table[data-table="groups"] tr .chat-row-name,
  .dir-table[data-table="chat_objects"] tr .chat-row-name,
  .dir-table[data-table="tasks_chats"] tr .chat-row-name {
    grid-column: 2; grid-row: 1;
    align-self: start;
    font-weight: 500; font-size: 14px; line-height: 16px;
    color: var(--text);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  /* Превью — две строки фикс. (даже если контента на одну) */
  .dir-table[data-table="chats"] tr > td:nth-child(4),
  .dir-table[data-table="groups"] tr > td:nth-child(4),
  .dir-table[data-table="chat_objects"] tr > td:nth-child(4),
  .dir-table[data-table="tasks_chats"] tr > td:nth-child(4) {
    grid-column: 2 / -1; grid-row: 2 / 4;
    height: 35px;
    padding-right: 22px;
    white-space: normal;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    line-height: 16px;
  }

  /* ===== NOTEBOOK NOTES (3 td: дата | заголовок | превью)
     Карточка в 3 строки (как в Сообщениях), без аватара. */
  .dir-table[data-table="notes"] tr {
    grid-template-columns: 1fr auto;
    grid-template-rows: 16px 16px 16px;
  }
  .dir-table[data-table="notes"] tr > td:nth-child(1) {  /* дата */
    grid-column: 2; grid-row: 1; text-align: right;
    font-size: 11px;
  }
  .dir-table[data-table="notes"] tr > td:nth-child(2) {  /* заголовок */
    grid-column: 1; grid-row: 1;
  }
  .dir-table[data-table="notes"] tr > td:nth-child(3) {  /* превью — 2 строки */
    grid-column: 1 / -1; grid-row: 2 / 4;
    height: 35px;
    white-space: normal;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; line-height: 16px;
  }

  /* ===== NOTEBOOK TASKS (6 td: ✓✓ | статус | приоритет | срок | заголовок | превью)
     Раскладка как в Сообщениях: заголовок + дата сверху, превью посередине,
     БЕЙДЖИ статуса/приоритета — на ПОСЛЕДНЕЙ строке (чтобы глаз не прыгал
     с верха карточки на верх следующей через большой статус-бейдж). */
  .dir-table[data-table="tasks"] tr {
    grid-template-columns: auto auto 1fr;
    grid-template-rows: 16px 16px auto;
    /* row-gap: 3px — тесный шаг заголовок↔превью, как в карточках Сообщений/
       Почты (.mail-card-top margin-bottom: 3px). Перед бейджами добавляем
       отдельный отступ через padding-top на td-бейджах (см. ниже) — так
       заголовок→содержимое тесно, а содержимое→бейджи шире. */
    column-gap: 6px; row-gap: 3px;
  }
  /* Бейдж статуса — последняя строка, слева.
     white-space: nowrap !important перебивает .dir-table--fit td:not([data-grow])
     которое поставило normal — иначе «в работе» переносится на 2 строки. */
  .dir-table[data-table="tasks"] tr > td:nth-child(1) {
    grid-column: 1; grid-row: 3; height: auto;
    align-self: center;
    /* padding-top: 5px — отделяет бейджи от блока «заголовок+содержимое»
       сильнее, чем row-gap 3px между заголовком и превью. */
    padding: 5px 0 0 0;
    white-space: nowrap !important; overflow: visible !important;
  }
  /* Бейдж приоритета — последняя строка, рядом со статусом */
  .dir-table[data-table="tasks"] tr > td:nth-child(2) {
    grid-column: 2; grid-row: 3; height: auto;
    align-self: center;
    padding: 5px 0 0 0;
    white-space: nowrap !important; overflow: visible !important;
  }
  /* Срок — row 1 справа */
  .dir-table[data-table="tasks"] tr > td:nth-child(3) {
    grid-column: 1 / -1; grid-row: 1; text-align: right; font-size: 11px;
    align-self: center;
  }
  /* Заголовок — row 1 на всю ширину (срок наложится справа через grid-stack) */
  .dir-table[data-table="tasks"] tr > td:nth-child(4) {
    grid-column: 1 / -1; grid-row: 1;
    z-index: 1;
    padding-right: 90px;
  }
  /* Превью — row 2 на всю ширину */
  .dir-table[data-table="tasks"] tr > td:nth-child(5) {
    grid-column: 1 / -1; grid-row: 2;
    padding-right: 22px;
  }

  /* ===== DIRECTORY — трёхстрочные карточки =====
     Раскладка по образу .dir-table[data-table="tasks"] (блокнот):
       Row 1: заголовок (имя/название) — на ВСЮ ширину
       Row 2: 2 текстовых поля (слева + справа)
       Row 3: статус-бейдж в левом нижнем углу
     Так заголовок ни с чем не конкурирует в row 1 и сидит ровно на 12px от
     верхней границы карточки, как во всех остальных разделах. Бейдж переехал
     вниз — взгляд: имя → детали → статус (как в задачах). */
  .dir-table[data-table="leads"] tr,
  .dir-table[data-table="employees"] tr,
  .dir-table[data-table="objects"] tr,
  .dir-table[data-table="equipment"] tr,
  .dir-table[data-table="companies"] tr,
  .dir-table[data-table="customers"] tr,
  .dir-table[data-table="reps"] tr {
    /* rows 16 + row-gap 3 — точно как у задач (data-table="tasks").
       padding-bottom: 8 — компенсирует 4px overhead, который .row-title с
       grid-column: 1 / -1 и .dir-table td height: 18 добавляют к row 1/2
       (видимо grid в 2-col раскладке считает иначе чем в 3-col у задач).
       Эмпирически: с padding-bot 8 расстояние badge→низ-карточки = 13,
       как у задач. */
    grid-template-rows: 16px 16px auto;
    row-gap: 3px;
    padding: 11px 14px 8px;
  }
  /* Бейдж статуса (td1) — row 3 col 1 (нижний левый угол, как у задач). */
  .dir-table[data-table="leads"] tr > td:nth-child(1),
  .dir-table[data-table="employees"] tr > td:nth-child(1),
  .dir-table[data-table="objects"] tr > td:nth-child(1),
  .dir-table[data-table="equipment"] tr > td:nth-child(1),
  .dir-table[data-table="companies"] tr > td:nth-child(1) {
    grid-column: 1; grid-row: 3; text-align: left; height: auto;
    align-self: center; padding: 0;
    white-space: nowrap !important; overflow: visible !important;
  }
  /* Имя/название (td2) — row 1 на ВСЮ ширину (без бейджа справа теперь) */
  .dir-table[data-table="leads"] tr > td:nth-child(2),
  .dir-table[data-table="employees"] tr > td:nth-child(2),
  .dir-table[data-table="objects"] tr > td:nth-child(2),
  .dir-table[data-table="companies"] tr > td:nth-child(2) {
    grid-column: 1 / -1; grid-row: 1;
  }
  /* Row 2: td3 слева, td4 справа */
  .dir-table[data-table="leads"] tr > td:nth-child(3),
  .dir-table[data-table="employees"] tr > td:nth-child(3),
  .dir-table[data-table="objects"] tr > td:nth-child(3),
  .dir-table[data-table="companies"] tr > td:nth-child(3) {
    grid-column: 1; grid-row: 2;
  }
  .dir-table[data-table="leads"] tr > td:nth-child(4),
  .dir-table[data-table="employees"] tr > td:nth-child(4),
  .dir-table[data-table="objects"] tr > td:nth-child(4),
  .dir-table[data-table="companies"] tr > td:nth-child(4) {
    grid-column: 2; grid-row: 2; text-align: right;
  }

  /* ----- EQUIPMENT — особая раскладка (title в td3) ----- */
  /* td1=status, td2=type, td3=model(title), td4=serial, td5=object, td6=owner */
  .dir-table[data-table="equipment"] tr > td:nth-child(2) {
    grid-column: 1; grid-row: 2;                       /* type → row 2 col 1 */
  }
  .dir-table[data-table="equipment"] tr > td:nth-child(3) {
    grid-column: 1 / -1; grid-row: 1;                  /* model → row 1 full */
  }
  .dir-table[data-table="equipment"] tr > td:nth-child(4) {
    grid-column: 2; grid-row: 2; text-align: right;    /* serial → row 2 col 2 */
  }

  /* ----- CUSTOMERS — БЕЗ статуса в первой колонке ----- */
  /* td1=name(title), td2=inn, td3=phone, td4=email */
  .dir-table[data-table="customers"] tr > td:nth-child(1) {
    grid-column: 1 / -1; grid-row: 1;           /* name на всю ширину row 1 */
  }
  .dir-table[data-table="customers"] tr > td:nth-child(2) {
    grid-column: 1; grid-row: 2;                /* inn → row 2 col 1 */
  }
  .dir-table[data-table="customers"] tr > td:nth-child(3) {
    grid-column: 2; grid-row: 2; text-align: right;  /* phone → row 2 col 2 */
  }

  /* ----- REPS — БЕЗ статуса ----- */
  /* td1=name(title), td2=position, td3=customer, td4=phone, td5=email */
  .dir-table[data-table="reps"] tr > td:nth-child(1) {
    grid-column: 1 / -1; grid-row: 1;           /* name на всю ширину row 1 */
  }
  .dir-table[data-table="reps"] tr > td:nth-child(2) {
    grid-column: 1; grid-row: 2;                /* position → row 2 col 1 */
  }
  .dir-table[data-table="reps"] tr > td:nth-child(3) {
    grid-column: 2; grid-row: 2; text-align: right;  /* customer → row 2 col 2 */
  }

  /* Скрываем поля начиная с 5-го (для большинства) или 4-го (для customers) —
     на мобильной карточке не помещаются. */
  .dir-table[data-table="leads"] tr > td:nth-child(n+5),
  .dir-table[data-table="employees"] tr > td:nth-child(n+5),
  .dir-table[data-table="objects"] tr > td:nth-child(n+5),
  .dir-table[data-table="companies"] tr > td:nth-child(n+5),
  .dir-table[data-table="equipment"] tr > td:nth-child(n+5),
  .dir-table[data-table="reps"] tr > td:nth-child(n+4),
  .dir-table[data-table="customers"] tr > td:nth-child(n+4) { display: none; }

  /* Статус/✓✓-ячейка по центру на десктопе → на мобиле в начало строки */
  .dir-table td[style*="text-align:center"] { text-align: left; }
}

/* ============================================================
   ОБЩИЕ КАРТОЧКИ-СПИСКИ — слитная таблица на десктопе,
   раздельные карточки на мобиле. Используется во всех разделах:
   directory, mail, notebook (список заметок/задач), chat (список чатов/объектов).
   ============================================================ */
.card-list {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
}
/* Карточка-плитка единого стиля (по образцу календарной «Сегодня на смене»). */
.card-list {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  display: flex; flex-direction: column; gap: 8px;
}
.card-row {
  display: flex; gap: 12px; align-items: center;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--white);
  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
  margin: 0;
  cursor: pointer;
  transition: border-color .12s, box-shadow .12s;
  text-decoration: none;
  color: inherit;
}
.card-row { -webkit-tap-highlight-color: transparent; }   /* iOS системная подсветка тапа — выкл */
.card-row.active { border-color: var(--blue); background: var(--blue-light); }
.card-row.archived { color: var(--text-muted); background: var(--bg); }
/* Hover ТОЛЬКО на устройствах с настоящим указателем (десктоп). */
@media (hover: hover) and (pointer: fine) {
  .card-row:hover  { border-color: var(--blue); box-shadow: 0 2px 8px rgba(0,0,0,0.10); }
  .card-row.archived:hover { border-color: var(--border); background: var(--bg); }
}

@media (max-width: 768px) {
  .page-wrap { padding: 8px; }
}

/* ============================================================
   Shared mobile layout (≤768px) — гамбургер + sidebar-drawer.
   ВЫНЕСЕНО из notebook/chat: эти страницы имеют собственные
   media-блоки с дополнительными правилами (back-стрелки в шапке
   списка/редактора и т.п.). Здесь — общий каркас для остальных
   страниц (dashboard, calendar, mail, directory).
   ============================================================ */
.nav-toggle-btn {
  display: none;
  width: 40px; height: 40px;
  border: none; cursor: pointer;
  align-items: center; justify-content: center;
  background: none;
  color: var(--blue);   /* применяется к SVG через stroke=currentColor */
  position: absolute;
  top: calc(14px + env(safe-area-inset-top, 0px));
  left: calc(14px + env(safe-area-inset-left, 0px));
  z-index: 4;
  padding: 0;
}
.nav-toggle-btn .nav-toggle-icon {
  width: 26px; height: 26px;
  /* Цвет берётся из родителя через currentColor — точный фирменный синий */
}
.nav-toggle-btn:hover { opacity: 0.7; }

/* Inline-вариант кнопки — кладётся внутрь .page-wrap на страницах со
   скроллящимся заголовком. Кнопка в потоке = скроллится вместе с .page-wrap.
   Перебиваем position:absolute дефолта. Сейчас этот класс никто не вешает
   (см. relocateNavToggleIfScrolls в app-drawer.js), оставлено на будущее. */
.nav-toggle-btn.nav-toggle-inline {
  position: static;
  margin: -2px 0 6px -2px;
}

/* ============================================================
   Mobile: dashboard — заголовок «Добрый день» приклеен сверху под иконкой,
   подзаголовок (дата) скроллится с контентом. Иконка Штабеля остаётся
   на абсолютной позиции в .app (top:14 left:14, не трогается).
   ============================================================ */
@media (max-width: 768px) {
  .main--dash .page-wrap > .page-title {
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--white);
    /* Перетягиваем фон на весь .main (через отрицательный margin) — иначе
       скроллящийся контент будет просвечивать слева/справа от заголовка
       (поскольку .page-wrap padding 12 14). */
    margin: -12px -14px 0;
    padding: 14px 14px 6px;
    /* Сдвигаем текст вниз, чтобы он начинался ПОД иконкой Штабеля
       (иконка top:14 height:40 → нижний край на 54px от верха .main). */
    text-indent: 0;
    padding-top: 48px;
  }
  .main--dash .page-wrap > .page-subtitle {
    margin-top: 0;
  }
}

/* ============================================================
   Desktop: заголовок страницы (page-title) выровнен по той же горизонтали,
   что и текст «Штабель» в sidebar-logo. .sidebar-logo имеет height=52px и
   центрирует логотип; page-title тоже занимает 52px и центрируется flex'ом
   — оба сидят на одной горизонтальной линии.
   Применяется к dashboard и mail (главный экран с папками).
   ============================================================ */
@media (min-width: 769px) {
  .main--dash .page-wrap > .page-title,
  .main--mail .page-wrap > .page-title,
  .main--fin  .page-wrap > .page-title {
    height: var(--header-h);
    display: flex;
    align-items: center;
    margin: 0 0 12px;
    padding: 0;
    line-height: 1;
    /* page-wrap уже даёт padding 12 24 — отступы слева/справа совпадают
       с глобальным padding содержимого. */
  }
  /* Подзаголовок дашборда — на десктопе под заголовком, отступа сверху не
     нужно (margin-bottom заголовка уже даёт 12px). */
  .main--dash .page-wrap > .page-subtitle {
    margin-top: 0;
    margin-bottom: 16px;
  }
}

/* ============================================================
   Desktop: открытое окно (чат / заметка / карточка справочника) должно
   занимать всё пространство от sidebar справа до правого края экрана,
   и от верха до низа — без padding со стороны .main / .nb-layout / .page-wrap.
   У блокнота нет обёртки <main> — там .nb-layout играет ту же роль,
   поэтому правила дублируются на оба контейнера.
   ============================================================ */
@media (min-width: 769px) {
  .app.chat-open    .main--chat,
  .app.chat-open    .main--chat > .page-wrap,
  .app.nb-item-open .main,
  .app.nb-item-open .main > .page-wrap,
  .app.nb-item-open .nb-layout,
  .app.nb-item-open .nb-layout > .page-wrap,
  .app.card-open    .main,
  .app.card-open    .main > .page-wrap {
    padding: 0 !important;
  }
  /* В блокноте/справочнике .page-wrap содержит заголовок + tabs + search —
     при открытой карточке всё это надо скрыть, чтобы редактор занял
     всю высоту .nb-layout (как chat-main внутри .main--chat). */
  .app.nb-item-open .nb-layout > .page-wrap,
  .app.card-open    .main > .page-wrap {
    display: none !important;
  }
}

.nav-backdrop {
  display: none;
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.42);
  z-index: 99;
}

/* Стрелка «закрыть drawer» внутри шапки sidebar. На десктопе скрыта. */
.sidebar-close-btn {
  display: none;
  width: 32px; height: 32px;
  border: none; background: none; cursor: pointer;
  border-radius: var(--radius-sm);
  align-items: center; justify-content: center;
  color: var(--text-muted); margin-left: auto;
}
.sidebar-close-btn:hover { color: var(--blue); background: var(--bg); }

@media (max-width: 768px) {
  /* Запрещаем выделение текста, системные контекст-меню iOS на долгом нажатии,
     и focus-обводку при тапе по кликабельным элементам.
     Исключения — поля ввода, там всё нужно. */
  * {
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
    outline: none !important;
    -webkit-tap-highlight-color: transparent !important;
  }
  *:focus, *:focus-visible, *:active, *:hover { outline: none !important; }
  input:focus, textarea:focus { outline: none !important; }
  input, textarea, [contenteditable="true"] {
    -webkit-user-select: text !important;
    user-select: text !important;
  }

  /* Tap-фидбек: короткая подсветка карточки при настоящем тапе
     (не при провождении пальцем). Добавляет/снимает класс js/tap-feedback.js. */
  .tap-flash {
    border-color: var(--blue) !important;
    box-shadow: 0 2px 8px rgba(0,0,0,0.10) !important;
    background: var(--blue-light) !important;
    transition: border-color .08s, background .08s, box-shadow .08s;
  }
  .dir-table tr.tap-flash { background: var(--blue-light) !important; }

  /* ============================================================
     FIXED-APP МОДЕЛЬ (как на десктопе): документ НЕ скроллится, скролл идёт
     внутри .main / .nb-layout. Это убирает rubber-band bounce всего документа,
     из-за которого навбар (position:fixed bottom) «прыгал/улетал» при pull.
     Навбар теперь стоит вне скролла и стабилен. */
  html, body {
    height: 100%;
    overflow: hidden !important;          /* документ не скроллится */
    overscroll-behavior: none;
  }
  .app {
    height: 100dvh;
    min-height: 100dvh;
    overflow: hidden;
  }
  .main,
  .nb-layout {
    flex: 1;
    overflow-y: auto;                     /* внутренний скролл контента */
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }

  /* Нижняя safe-area (home-indicator) — гарантированно белый фон, чтобы из-под
     навбара не проглядывала серая полоса body (--bg). Слой под навбаром (z 49). */
  body::after {
    content: '';
    position: fixed;
    left: 0; right: 0; bottom: 0;
    height: env(safe-area-inset-bottom, 0px);
    background: var(--white);
    z-index: 49;
    pointer-events: none;
  }

  /* ============================================================
     Mobile bottom tab bar — все пункты меню вынесены в подвал
     иконками, белый фон + бордюр сверху. Никаких drawer/гамбургера. */
  .sidebar {
    position: fixed !important;
    top: auto !important;
    bottom: 0; left: 0; right: 0;
    width: 100% !important;
    min-width: 0 !important;
    height: 60px !important;
    transform: none !important;
    flex-direction: row !important;
    background: var(--white) !important;
    border-right: none !important;
    border-top: 1px solid var(--border) !important;
    box-shadow: 0 -1px 4px rgba(0,0,0,0.06) !important;
    z-index: 50;
    /* Высота = 60px (иконки) + 15px белого фона снизу. Эти 15px отодвигают
       иконки от скругления экрана iPhone и виртуальной полоски home-indicator,
       чтобы навбар их не «съедал». + safe-area на случай PWA-режима. */
    height: calc(75px + env(safe-area-inset-bottom, 0px)) !important;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    /* nav-меню (60px) прижато к верху; нижние 15px — чистый белый фон. */
    align-items: flex-start !important;
  }
  .sidebar-logo, .sidebar-profile { display: none !important; }
  .sidebar-nav {
    display: flex !important;
    flex-direction: row !important;
    width: 100%;
    /* Высота строго 60px — иконки центрируются ТОЛЬКО в этой зоне, выше
       home-indicator. Нижние env(safe-area-inset-bottom) остаются чистым
       белым фоном навбара (см. height/padding-bottom .sidebar). */
    height: 60px;
    flex: 0 0 auto;
    padding: 0 !important; margin: 0 !important;
    gap: 0 !important;
    overflow: visible !important;
  }
  .nav-item {
    flex: 1;
    flex-direction: column !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 0 !important;
    padding: 8px 4px !important;
    /* Подписи под иконками не показываем — font-size:0 скрывает текстовые ноды.
       Бейдж непрочитанных получает свой размер ниже. */
    font-size: 0 !important;
    line-height: 0 !important;
    color: transparent !important;
    min-width: 0;
    text-align: center;
    border-radius: 0 !important;
    background: none !important;
  }
  /* Иконку <img> прячем — рисуем её через ::before c CSS mask. ::after — синяя
     pill-подложка под иконкой для активного состояния (полная инверсия:
     иконка становится белой на фирменно-синем фоне). */
  .nav-item .nav-ico { display: none !important; }
  /* Круглая подложка под иконкой активной кнопки. 42×42 круг центрирован
     ровно по центру 26×26 иконки (icon-center = 29.5px от верха nav-item).
     Размер 42 (а не 36) — некоторые иконки визуально шире 26px-bounding box
     (mail, directory, notebook) и не помещались в 36-круг с комфортным halo.
     42 = 36 + ~17%, halo вокруг иконки 8px со всех сторон.
     top = 29.5 − 21 = 8.5 (округляем до 9). */
  .nav-item::after {
    content: '';
    position: absolute;
    top: 9px; left: 50%;
    transform: translateX(-50%);
    width: 42px; height: 42px;
    background: var(--blue);
    border-radius: 50%;
    opacity: 0;
    transition: opacity 0.15s;
    z-index: 0;
    pointer-events: none;
  }
  /* Активное состояние БЕЗ синего круга-фона (он багал) — просто синяя иконка. */
  .nav-item.active::after { opacity: 0; }
  /* Иконка через CSS mask. Активная — синяя (без фона), иначе — приглушённо-серая. */
  .nav-item::before {
    content: '';
    width: 26px; height: 26px; display: block;
    background-color: var(--text-muted);
    -webkit-mask: var(--nav-icon) center / contain no-repeat;
    mask: var(--nav-icon) center / contain no-repeat;
    transition: background-color 0.15s;
    position: relative;
    z-index: 1;
  }
  .nav-item.active::before { background-color: var(--blue); }
  .nav-item:hover::before { background-color: var(--blue); }
  .nav-item.active { background: none !important; color: var(--blue) !important; }
  .nav-item:hover { background: none !important; color: var(--blue); }

  /* Привязка SVG-маски к каждой кнопке по её id.
     Иконки stroke-версии (контурные) — те же что на десктопе.
     При .active НЕ меняется картинка (не заливается), только цвет —
     через color: var(--blue) на .nav-item.active выше. */
  #nav-dashboard { --nav-icon: url('images/icon-home.svg'); }
  #nav-calendar  { --nav-icon: url('images/icon-calendar.svg'); }
  #nav-mail      { --nav-icon: url('images/icon-mail.svg'); }
  #nav-chat      { --nav-icon: url('images/icon-chat.svg'); }
  #nav-notebook  { --nav-icon: url('images/icon-notebook.svg'); }
  #nav-directory { --nav-icon: url('images/icon-directory.svg'); }
  #nav-finance   { --nav-icon: url('images/icon-finance.svg'); }
  #nav-god       { --nav-icon: url('images/icon-god.svg'); }
  /* Бейдж непрочитанных уведомлений — красный круг с цифрой счётчика,
     прикреплён к правому-верхнему углу иконки. Цифру (textContent) ставит JS
     через setNavBadge(navId, count). Скрытие при count=0 — через JS style.display=none. */
  .nav-item .nav-badge {
    position: absolute;
    top: 8px; right: calc(50% - 24px);
    min-width: 20px; height: 20px;
    padding: 0 5px;
    border-radius: 999px;          /* 1 цифра — круг (20×20), 2+ — pill */
    background: var(--red) !important;
    color: #fff !important;
    box-sizing: border-box;
    font-size: 12px; line-height: 20px;
    font-weight: 700;
    text-align: center;
    overflow: visible;
    display: inline-block;          /* НЕ !important — иначе JS не сможет скрыть через style.display='none' */
    z-index: 2;
  }
  /* Серый вариант для «выключенных» уведомлений раздела. */
  .nav-item .nav-badge.muted { background: var(--text-muted) !important; }
  .nav-item { position: relative; }

  /* Кнопка-гамбургер (иконка Штабеля) — справа сверху, поверх контента.
       Backdrop и close-кнопка drawer-а не нужны — sidebar теперь в подвале. */
  .nav-backdrop, .sidebar-close-btn { display: none !important; }
  .nav-toggle-btn { display: flex !important; }
  .app.nav-open .sidebar { transform: none !important; }

  /* html/body/.app/.main теперь mobile-first дефолт — здесь дублирование не нужно.
     Desktop-overrides в @media (min-width: 769px). */

  /* ============================================================
     МОБИЛЬНЫЙ режим полного экрана при открытой карточке.
     .app фиксируется по высоте viewport + doc-scroll выключается, иначе шапка
     диалога и поле ввода уезжают вместе со страницей. На десктопе этого не
     нужно: там split-view, обе колонки уже видны одновременно.
     Поддерживаемые классы-флаги:
       .app.chat-open    — открыт диалог в Сообщениях
       .app.nb-item-open — открыта заметка/задача в Блокноте
       .app.card-open    — универсальный флаг для будущих разделов */
  .app.chat-open,
  .app.nb-item-open,
  .app.card-open {
    height: 100dvh !important;
    min-height: 100dvh !important;
    overflow: hidden !important;
  }
  html:has(.app.chat-open),
  html:has(.app.nb-item-open),
  html:has(.app.card-open),
  body:has(.app.chat-open),
  body:has(.app.nb-item-open),
  body:has(.app.card-open) { overflow: hidden !important; }
  /* Полностью прячем «обвязку» раздела, когда открыта карточка:
       — .page-title / .page-subtitle — заголовок раздела
       — .dir-tabs / .chat-tabs / .mail-tabs — меню/табы раздела
       — .nav-toggle-btn — иконка Штабеля в левом верхнем углу
                           (относится к шапке раздела, без неё висит лишним)
       — .sidebar — нижняя навигация (подвал)
                    карточка раскрывается на весь экран без отвлечений. */
  .app.chat-open .nav-toggle-btn,
  .app.nb-item-open .nav-toggle-btn,
  .app.card-open .nav-toggle-btn,
  .app.chat-open .sidebar,
  .app.nb-item-open .sidebar,
  .app.card-open .sidebar,
  .app.chat-open .page-title,    .app.chat-open .page-subtitle,
  .app.nb-item-open .page-title, .app.nb-item-open .page-subtitle,
  .app.card-open .page-title,    .app.card-open .page-subtitle,
  .app.chat-open .dir-tabs,      .app.chat-open .chat-tabs,    .app.chat-open .mail-tabs,
  .app.nb-item-open .dir-tabs,   .app.nb-item-open .chat-tabs, .app.nb-item-open .mail-tabs,
  .app.card-open .dir-tabs,      .app.card-open .chat-tabs,    .app.card-open .mail-tabs {
    display: none !important;
  }
  .app.chat-open .main,
  .app.nb-item-open .main,
  .app.card-open .main { overflow: hidden !important; }
  /* Сайдбар (нижняя нав) скрыт — резерв 60px+ под него на padding-bottom не нужен,
     карточка должна занять всю высоту до низа viewport. */
  .app.chat-open .main,
  .app.nb-item-open .main,
  .app.card-open .main { padding-bottom: 0 !important; padding-top: 0 !important; }
  /* page-wrap внутри тоже сбрасываем — у chat-main свои отступы для шапки/инпута. */
  .app.chat-open .main > .page-wrap,
  .app.chat-open .main--chat > .page-wrap { padding: 0 !important; }

  /* .main padding теперь mobile-first дефолт (см. наверху файла).
     width:100% — следствие width:100vw у .app + flex, не нужно дублировать. */
  .main > .page-wrap,
  .main--chat > .page-wrap {
    padding-top: 0; padding-left: 0; padding-right: 0;
  }
  /* notebook не имеет .main — компенсируем top-отступ здесь, 14px чтобы совпало
     с глобальной горизонтальной линией Штабель-иконка / заголовок / + */
  .nb-layout > .page-wrap {
    padding-top: 14px; padding-left: 0; padding-right: 0;
  }
  /* Заголовок раздела: центрирован по горизонтали (без вычитания кнопки-Штабеля)
     и по вертикали выровнен с центром иконки Штабеля (high 40px на top:14 → center 34).
     Все три верхних элемента (Штабель-иконка, заголовок, «+»-кнопка) теперь
     сидят на y=14 одной горизонтальной линией. */
  .page-title {
    padding-left: 0; padding-right: 0;
    text-align: center;
    min-height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    /* margin-bottom: 18px — даёт больше воздуха до контента (раньше было 14
       и казалось тесно особенно на дашборде где сразу карточки). */
    margin: 0 0 18px;
  }
  /* .page-subtitle уже скрыт mobile-first дефолтом — здесь не нужно дублировать */

  /* Кнопка «+ Создать / + Новый чат / + Написать».
     Размер 32×32 (а не 40×40) — компенсирует то, что у Штабель-иконки слева
     ВИДНА только 26×26 SVG (фон-прозрачный), а у «+» весь квадрат залит синим.
     При равных outer-размерах синий квадрат визуально тяжелее тонких линий
     SVG. 32×32 — визуальный баланс.

     ВЫРАВНИВАНИЕ ПО ЦЕНТРУ: оба элемента шапки центруются по y=34
     (горизонтальная линия через заголовок раздела, ровно посередине его
     min-height:40 от top:14). Поэтому:
       - Штабель-иконка 40×40 на top:14 → center = 14+20 = 34
       - «+» кнопка 32×32 на top:18 → center = 18+16 = 34
     При равном top:14 кнопка «+» сидела бы на 4px выше центра — выглядело
     несимметрично. */
  .dir-add-btn,
  .mail-write-btn {
    position: absolute !important;
    top: calc(18px + env(safe-area-inset-top, 0px));
    right: calc(14px + env(safe-area-inset-right, 0px));
    z-index: 4;
    width: 32px !important; height: 32px !important;
    padding: 0 !important;
    border: none !important;
    border-radius: var(--radius-sm) !important;
    background: var(--blue) !important;
    box-shadow: 0 2px 6px rgba(0,0,0,0.12);
    font-size: 0 !important; color: transparent !important;
    overflow: hidden;
    display: inline-flex; align-items: center; justify-content: center;
  }
  .dir-add-btn::before,
  .mail-write-btn::before {
    content: '+';
    color: #fff;
    font-size: 18px;
    font-weight: 400;
    line-height: 1;
    display: block;
  }
  .dir-add-btn:hover,
  .mail-write-btn:hover { background: var(--blue-dark) !important; }

  /* .metrics/.widgets/.page-title — все теперь mobile-first дефолт. */

  /* ============================================================
     MOBILE TYPOGRAPHY +1 STEP
     На мобиле все ключевые шрифты увеличены на ~1px относительно десктопа —
     мелкий текст хуже читается с расстояния руки. Шкала шагов:
       11→12, 12→13, 13→14, 14→15. 16+ остаются (16 нужно для iOS no-zoom inputs).
     Высоты строк/блоков подняты пропорционально, чтобы не обрезался текст. */
  .page-title { font-size: 22px; }                              /* was 20 */
  .dir-table td { font-size: 13px; line-height: 18px; height: 18px; }   /* was 12/16/16 */
  .dir-table .row-title,
  .chat-row-name { font-size: 15px !important; line-height: 18px; height: 18px; }  /* was 14/16/16 */
  /* Бейджи и подписи-капшены */
  .nb-badge,
  .nb-badge-status,
  .badge { font-size: 12px; }                                   /* was 11 */
  .nb-archive-label,
  .chat-archive-label,
  .mail-section-label { font-size: 12px; }                      /* was 11 */
  /* Карточки почты */
  .mail-card-from { font-size: 15px; line-height: 18px; height: 18px; }   /* was 14 */
  .mail-card-subj { font-size: 14px; line-height: 18px; height: 18px; }   /* was 13 */
  .mail-card-preview { font-size: 13px; line-height: 18px; }    /* was 12 */
  .mail-card-date { font-size: 12px; line-height: 18px; }       /* was 11 */
  .mail-tab,
  .dir-tab,
  .chat-tab { font-size: 14px; }                                /* was 13 */
  /* Виджеты dashboard */
  .widget-title,
  .metric-label { font-size: 12px; }                            /* was 11 */
  .employee-name,
  .task-text { font-size: 14px; }                               /* was 13 */
  .employee-place { font-size: 12px; }                          /* was 11 */

  /* Табы разделов больше не нужны — навигация по подразделам идёт через
     левый drawer (Штабель-иконка). Скрываем .dir-tabs (notebook/directory),
     .chat-tabs (если используется), .mail-tabs. JS-логика табов остаётся,
     hash сохраняется и работает — просто визуальный элемент скрыт. */
  .dir-tabs,
  .chat-tabs,
  .mail-tabs { display: none !important; }

  /* Подзаголовок текущей вкладки — заменяет визуально скрытые табы.
     Показывает «Чаты» под «Сообщения», «Лиды» под «Справочник» и т.д.
     Синий — совпадает с активным состоянием бывшей таб-кнопки. */
  .sub-section-title {
    text-align: center;
    font-size: 16px;
    font-weight: 500;
    color: var(--blue);
    margin: -8px 0 14px;   /* −8 чтобы прижаться к page-title (у того margin-bottom 18) */
    line-height: 18px;
    min-height: 18px;
  }
}

/* На десктопе подзаголовок не нужен — там видны сами табы Чаты/Группы/Объекты/Задачи. */
@media (min-width: 769px) {
  .sub-section-title { display: none !important; }
}

@media (max-width: 768px) {

  /* ============================================================
     APP-DRAWER — глобальный левый сайдбар-меню (вызов: тап по иконке
     Штабеля). Стек из 2 экранов: nav (level 0) / settings (level 1).
     Перекрывает контент И нижнюю навигацию (z-index 999).
     HTML инжектируется через js/app-drawer.js. */
  .app-drawer {
    position: fixed; inset: 0;
    z-index: 999;
    visibility: hidden;
    pointer-events: none;
  }
  body.app-drawer-open .app-drawer {
    visibility: visible;
    pointer-events: auto;
  }
  .app-drawer-backdrop {
    position: absolute; inset: 0;
    background: rgba(0, 0, 0, 0.42);
    opacity: 0;
    transition: opacity 0.22s ease;
  }
  body.app-drawer-open .app-drawer-backdrop { opacity: 1; }

  /* Контейнер стека — слайдит ИЗ-ЗА левого края при открытии.
     На мобиле занимает 100% ширины — drawer полноэкранный. */
  .app-drawer-stack {
    position: absolute;
    top: 0; left: 0; bottom: 0;
    width: 100%;
    background: var(--white);
    transform: translateX(-100%);
    transition: transform 0.22s ease;
    display: flex;
    overflow: hidden;
  }
  body.app-drawer-open .app-drawer-stack { transform: translateX(0); }

  /* Экраны стека: лежат side-by-side, переключаются через transform всех.
     ВАЖНО: в DOM первым идёт settings, вторым nav (см. buildDrawer()).
     Дефолт (level=0) — оба сдвинуты на -100%: nav (был на 100%, справа)
     встаёт в видимую область; settings (был на 0) уходит за левый край.
     Уровень 1 — оба возвращаются на 0: nav уезжает вправо, settings
     выезжает в центр СЛЕВА. */
  .app-drawer-screen {
    flex: 0 0 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    transform: translateX(-100%);
    transition: transform 0.22s ease;
  }
  .app-drawer-stack[data-level="1"] .app-drawer-screen {
    transform: translateX(0);
  }

  /* Шапка — попиксельно совпадает с шапкой разделов:
       - Штабель-иконка слева на top:14px (40×40, как .nav-toggle-btn у разделов)
       - Заголовок «Штабель» по центру 22px (как .page-title)
       - Крестик ✕ справа на top:14px (40×40, как .chat-hbtn инфо)
       - Заголовок имеет min-height 40, margin-bottom 18 — итого 14+40+18 = 72px высоты
     Без border-bottom — лишняя линия не совпадала с общим дизайном разделов. */
  .app-drawer-header {
    position: relative;
    /* Top-padding с учётом safe-area для notch iPhone в PWA-режиме */
    padding: calc(14px + env(safe-area-inset-top, 0px)) 60px 18px;
    flex-shrink: 0;
  }
  .app-drawer-title {
    font-size: 22px;
    font-weight: 600;
    color: var(--text);
    letter-spacing: -0.3px;
    margin: 0;
    min-height: 40px;
    display: flex; align-items: center; justify-content: center;
    text-align: center;
  }
  .app-drawer-logo {
    position: absolute;
    top: 14px; left: 14px;
    width: 40px; height: 40px;
    display: flex; align-items: center; justify-content: center;
    color: var(--blue);   /* совпадает с .nav-toggle-btn разделов */
  }
  .app-drawer-close,
  .app-drawer-back {
    position: absolute;
    top: 14px;
    width: 40px; height: 40px;
    border: none; background: none;
    display: flex; align-items: center; justify-content: center;
    color: var(--text-muted);
    cursor: pointer;
    border-radius: var(--radius-sm);
    transition: color 0.12s;
  }
  .app-drawer-close { right: 14px; }
  .app-drawer-back  { left: 14px; }
  .app-drawer-close:hover,
  .app-drawer-back:hover { color: var(--blue); }

  /* Тело — скроллится при необходимости */
  .app-drawer-body {
    flex: 1;
    overflow-y: auto;
    padding: 6px 0;
  }
  .app-drawer-list {
    list-style: none;
    padding: 0;
    margin: 0;
  }
  /* Пункты — без border-bottom (раньше резало глаз) и без фоновой подсветки.
     Активный — синим текстом, без фона. */
  .app-drawer-link {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 20px;
    font-size: 16px;
    color: var(--text);
    text-decoration: none;
    transition: color 0.12s;
  }
  .app-drawer-link:hover { color: var(--blue); }
  .app-drawer-link.active {
    color: var(--blue);
    font-weight: 500;
  }
  .app-drawer-link.danger { color: var(--red); }
  .app-drawer-link.danger:hover { color: var(--red); }
  .app-drawer-icon {
    flex-shrink: 0;
    width: 20px; height: 20px;
    color: var(--text-muted);
    transition: color 0.12s;
  }
  .app-drawer-link:hover .app-drawer-icon,
  .app-drawer-link.active .app-drawer-icon { color: var(--blue); }
  .app-drawer-link.danger .app-drawer-icon { color: var(--red); }
  .app-drawer-empty {
    padding: 32px 20px;
    text-align: center;
    color: var(--text-muted);
    font-size: 14px;
  }
  .app-drawer-mail-link {
    display: inline-block;
    margin-top: 10px;
    color: var(--blue);
    text-decoration: none;
    font-weight: 500;
  }
  /* Счётчик непрочитанных у папки почты в drawer */
  .app-drawer-mail-count {
    margin-left: auto;
    background: var(--blue-light);
    color: var(--blue);
    font-size: 11px;
    font-weight: 600;
    padding: 1px 8px;
    border-radius: 10px;
  }
  .app-drawer-link { position: relative; }
  /* Бейдж непрочитанных в меню drawer — синий, справа, 1 цифра круг / 2+ pill */
  .app-drawer-badge {
    margin-left: auto;
    min-width: 20px; height: 20px;
    padding: 0 6px;
    box-sizing: border-box;
    border-radius: 999px;
    background: var(--blue);
    color: #fff;
    font-size: 12px; font-weight: 600;
    line-height: 20px; text-align: center;
    flex-shrink: 0;
  }

  /* Подвал — на той же визуальной высоте, что bottom-nav. */
  .app-drawer-footer {
    flex-shrink: 0;
    /* Выровнено по высоте с bottom-nav: 60px контента + 15px белого снизу
       (+ safe-area). Контент центрируется в верхних 60px — как иконки навбара. */
    height: calc(75px + env(safe-area-inset-bottom, 0px));
    padding: 0 14px 15px;
    border-top: 1px solid var(--border);
    display: flex; align-items: center; gap: 12px;
    background: var(--white);
  }
  /* Аватар пользователя в подвале drawer'а — кружок 38×38 с инициалами,
     синий blue на blue-light фоне (как `.avatar` десктопного sidebar, но крупнее). */
  .app-drawer-avatar {
    flex-shrink: 0;
    width: 38px; height: 38px;
    border-radius: 50%;
    background: var(--blue-light);
    color: var(--blue);
    display: flex; align-items: center; justify-content: center;
    font-weight: 700;
    font-size: 13px;
    line-height: 1;
    user-select: none;
  }
  .app-drawer-user {
    flex: 1;
    min-width: 0;
  }
  .app-drawer-user-name {
    font-size: 14px; font-weight: 500;
    color: var(--text);
    line-height: 18px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .app-drawer-user-role {
    font-size: 12px;
    color: var(--text-muted);
    line-height: 16px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  /* Шестерёнка: круглая, вертикально = ник+роль (18+16=34px).
     Иконка ~20px внутри, цвет — синий на blue-light фоне. */
  .app-drawer-gear {
    flex-shrink: 0;
    width: 34px; height: 34px;
    border: none;
    background: var(--blue-light);
    color: var(--blue);
    border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer;
    transition: background 0.12s, color 0.12s;
  }
  .app-drawer-gear:hover {
    background: var(--blue);
    color: #fff;
  }
}

/* ============================================================
   DESKTOP OVERRIDES — раньше эти значения были дефолтными, а мобиль их
   перебивала через !important. Теперь дефолт = мобиль, а здесь добавляем
   только то, что отличается на десктопе.
   ============================================================ */
@media (min-width: 769px) {
  /* Document не скроллится — скрол идёт внутри .main (split-view). */
  html, body {
    overflow-y: hidden;
    overscroll-behavior: auto;
  }
  /* .app — fixed viewport со split-view: sidebar + main рядом. */
  .app {
    width: auto;
    height: 100vh;
    height: 100dvh;
    min-height: 0;
    overflow: hidden;
  }
  /* Основная область раздела — собственный скрол. padding-top: 0 чтобы
     вкладки разделов лежали прямо у верха, и их нижнее подчёркивание
     совпадало с подчёркиванием шапки сайдбара (обе на y=52).
     .nb-layout — отдельный контейнер блокнота вместо .main, ему те же
     правила; иначе блокнот съезжал к левому краю sidebar (исторически
     padding жил в .nb-layout > .page-wrap = 28/46, что давало
     несовпадающие подчёркивания). */
  .main, .nb-layout {
    overflow-y: auto;
    padding: 0 32px 14px;
  }
  /* page-wrap на десктопе уже выровнен через .main/.nb-layout padding. */
  .main > .page-wrap,
  .main--chat > .page-wrap,
  .nb-layout > .page-wrap { padding: 0; }
  /* nb-split: без своего padding на десктопе (иначе двойной отступ
     с .nb-layout). На мобиле сохраняется его собственный padding из
     notebook.html (0 0 80px — для bottom-nav). */
  .nb-split { padding: 0; }
  /* Заголовок раздела — слева, не растягивается на всю ширину. */
  .page-title {
    text-align: left;
    min-height: 0;
    display: block;
    margin: 0 0 4px;
  }
  /* .widgets на десктопе — две колонки. */
  .widgets { grid-template-columns: 1fr 1fr; }

  /* Вкладки разделов высотой ровно 52px = высоте шапки сайдбара,
     чтобы их border-bottom лёг на одну горизонталь с подчёркиванием
     блока «Штабель» сверху сайдбара. */
  .dir-tabs, .nb-tabs, .cal-months, .mail-tabs {
    height: 52px;
    align-items: stretch;
    margin-bottom: 16px;
    box-sizing: border-box;
  }
  .dir-tab, .nb-tab, .cal-month-tab, .mail-tab {
    padding: 0 16px;
    display: inline-flex; align-items: center;
  }

  /* Sticky table headers — только на десктопе. На мобиле другой layout
     (карточки), sticky не нужен и может конфликтовать с overflow. */
  .dir-table thead th {
    position: sticky;
    top: 0;
    z-index: 5;
  }
  /* Единая высота строк во всех табличных разделах — только десктоп.
     На мобиле карточки имеют свой layout по контенту. */
  .dir-table tbody tr {
    height: 52px;
  }
}

/* ============================================================
   Pull-to-refresh индикатор (PWA-режим, mobile).
   JS — js/pull-refresh.js. Виден только при потягивании страницы
   вниз от верхней границы; крутится во время location.reload(). */
.ptr-indicator {
  position: fixed;
  /* Фиксированная позиция в шапке по центру. Не двигается с пальцем —
     при потягивании меняется только opacity и вращение спиннера. */
  top: calc(16px + env(safe-area-inset-top, 0px));
  left: 50%;
  width: 36px; height: 36px;
  background: var(--white);
  border-radius: 50%;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10000;
  opacity: 0;
  transform: translateX(-50%);
  pointer-events: none;
  will-change: opacity, transform;
}
/* SVG-кольцо: серый трек + зелёный заполняемый сектор */
.ptr-spinner { display: block; transform-origin: center; }
.ptr-track { stroke: var(--border); }
.ptr-fill  { stroke: var(--green); }
/* Во время обновления — серый трек убираем, зелёное кольцо плавно
   заполняется от 0 до 100% за время до reload (≈700мс). */
.ptr-indicator.refreshing .ptr-track { opacity: 0; }
/* Кольцо заполняется в цикле, пока браузер не покажет новую страницу.
   На быстром интернете кольцо не успеет дойти до 100% — это нормально. */
.ptr-indicator.refreshing .ptr-fill {
  animation: ptr-fill 1.5s linear infinite;
}
@keyframes ptr-fill {
  from { stroke-dashoffset: 62.83; }
  to   { stroke-dashoffset: 0; }
}
/* Pull-to-refresh — только мобильный паттерн (тач-устройства).
   На десктопе он бесполезен, а z-index:10000 поднимает его над всем
   стеком (может мелькнуть глитчем при анимациях или фокусах). */
@media (min-width: 769px) {
  .ptr-indicator { display: none !important; }
}

