/* ============================================================================
   LEDGER — дизайн-система превью (/next)
   Тезис: бухгалтерская книга. Деньги — главный объект: все суммы, номера
   и даты — моноширинные, выровнены в колонку. Один акцент — изумруд.
   Токены: primitive → semantic (задел под тёмную тему через [data-theme]).
   ========================================================================== */

:root {
  /* --- primitive ---------------------------------------------------------- */
  --l-green-700: #0A5C48;
  --l-green-600: #0E7A5F;
  --l-green-100: #E4F2EC;
  --l-amber-700: #8A5E00;
  --l-amber-100: #F9F1DD;
  --l-red-600:   #B3261E;
  --l-red-100:   #F9E5E3;
  --l-brass:     #C9A96A;

  --l-gray-950: #17191D;
  --l-gray-900: #1B1D1F;
  --l-gray-700: #3E4348;
  --l-gray-500: #6E7378;
  --l-gray-400: #8A9096;
  --l-gray-300: #C9CCC9;
  --l-gray-200: #E8E6E1;
  --l-gray-150: #F0EEE9;
  --l-gray-100: #F6F6F4;

  /* --- semantic (light) --------------------------------------------------- */
  --l-bg:            var(--l-gray-100);
  --l-surface:       #FFFFFF;
  --l-surface-hover: #FAFAF8;
  --l-border:        var(--l-gray-200);
  --l-hairline:      var(--l-gray-150);
  --l-text:          var(--l-gray-900);
  --l-text-2:        var(--l-gray-500);
  --l-text-3:        var(--l-gray-400);
  --l-accent:        var(--l-green-600);
  --l-accent-ink:    var(--l-green-700);
  --l-accent-soft:   var(--l-green-100);
  --l-warn:          var(--l-amber-700);
  --l-warn-soft:     var(--l-amber-100);
  --l-danger:        var(--l-red-600);
  --l-danger-ink:    #96201A; /* нажатое/наведённое состояние сплошной опасной кнопки */
  --l-danger-soft:   var(--l-red-100);
  /* Текст и глифы поверх сплошной заливки акцентом/опасностью. У тёмных тем
     акцент светлый, поэтому белый текст даёт контраст ниже 4.5:1 — там эти
     токены переопределяются на тёмные чернила самой темы (см. блок тем). */
  --l-on-accent:     #fff;
  --l-on-danger:     #fff;
  --l-info:          #2563EB; /* синий приоритета/акцентов; в тёмных темах светлее */
  --l-priority-high: #E88A00; /* яркий сигнал; не смешивается с приглушённым warn */
  --l-scroll-thumb:  color-mix(in srgb, var(--l-text-3) 58%, transparent);
  --l-scroll-hover:  color-mix(in srgb, var(--l-text-2) 76%, transparent);
  --l-scroll-track:  color-mix(in srgb, var(--l-border) 52%, transparent);

  /* Сайдбар: у светлых тем — светлый (как top2b/Claude), у тёмных — тёмный */
  --l-sidebar-bg:        #FFFFFF;
  --l-sidebar-border:    var(--l-gray-200);
  --l-sidebar-text:      #5B6167;
  --l-sidebar-strong:    var(--l-gray-900);
  --l-sidebar-title:     #A9AEB3;
  --l-sidebar-hover:     var(--l-gray-150);
  --l-sidebar-active-bg: var(--l-accent-soft);
  --l-sidebar-active-tx: var(--l-accent-ink);

  /* --- shape & depth ------------------------------------------------------ */
  --l-r-sm: 7px;
  --l-r-md: 10px;
  --l-r-lg: 14px;
  --l-r-full: 999px;
  --l-shadow-card: 0 1px 2px rgba(23, 25, 29, 0.04);
  --l-shadow-pop: 0 4px 24px rgba(23, 25, 29, 0.14), 0 1px 3px rgba(23, 25, 29, 0.08);

  /* --- type --------------------------------------------------------------- */
  --l-font: 'Golos Text', -apple-system, 'Segoe UI', sans-serif;
  --l-mono: 'IBM Plex Mono', 'SF Mono', monospace;

  /* --- z ------------------------------------------------------------------ */
  --l-z-pop: 400;
}

/* ============================================================================
   База
   ========================================================================== */
* { box-sizing: border-box; }
/* Android Chrome/Samsung Internet и iOS Safari рисуют поверх нажатого
   элемента собственную синюю подложку. Ledger показывает состояния сам,
   поэтому убираем только touch-highlight; клавиатурный :focus-visible ниже
   остаётся полноценным и контрастным. */
html { -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; }
body.ledger {
  margin: 0;
  font-family: var(--l-font);
  font-size: 14px;
  line-height: 1.45;
  color: var(--l-text);
  background: var(--l-bg);
  -webkit-font-smoothing: antialiased;
}
/* `hidden` — жёсткий UI-контракт. Компонентный display:flex/grid не должен
   случайно возвращать скрытые поиском, фильтром или состоянием элементы. */
.ledger [hidden] { display: none !important; }

/* Переходы между страницами. Приложение серверное: каждый клик по меню — это
   полная перезагрузка документа, и браузер показывал белую вспышку. Кросс-
   документные view transitions сглаживают её силами самого браузера (Chrome,
   Edge, Android); Safari и Firefox правило просто игнорируют, поведение
   прежнее. Держим 140ms — быстрее, чем дефолтные 250ms, чтобы навигация не
   казалась вязкой. Глобальный killer анимаций ниже сюда не достаёт:
   @view-transition отключается только собственным navigation: none. */
@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) { animation-duration: 140ms; }
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}

/* Единые полосы прокрутки Ledger. Firefox использует scrollbar-*,
   Chromium/Safari — webkit-псевдоэлементы. Полоса остаётся спокойной в покое
   и становится контрастнее только при наведении.
   Только для устройств с курсором: любая кастомизация webkit-скроллбара
   отключает на тач-устройствах нативное overlay-поведение, и полосы висят
   на экране постоянно вместо «появилась при прокрутке — растворилась». */
@media (hover: hover) and (pointer: fine) {
html,
.ledger,
.ledger * {
  scrollbar-width: thin;
  scrollbar-color: var(--l-scroll-thumb) transparent;
}
html::-webkit-scrollbar,
.ledger::-webkit-scrollbar,
.ledger *::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
html::-webkit-scrollbar-track,
.ledger::-webkit-scrollbar-track,
.ledger *::-webkit-scrollbar-track {
  background: transparent;
}
html::-webkit-scrollbar-thumb,
.ledger::-webkit-scrollbar-thumb,
.ledger *::-webkit-scrollbar-thumb {
  min-width: 36px;
  min-height: 36px;
  border: 2px solid transparent;
  border-radius: var(--l-r-full);
  background: var(--l-scroll-thumb);
  background-clip: padding-box;
}
html::-webkit-scrollbar-thumb:hover,
.ledger::-webkit-scrollbar-thumb:hover,
.ledger *::-webkit-scrollbar-thumb:hover {
  background: var(--l-scroll-hover);
  background-clip: padding-box;
}
html::-webkit-scrollbar-corner,
.ledger::-webkit-scrollbar-corner,
.ledger *::-webkit-scrollbar-corner {
  background: transparent;
}
html::-webkit-scrollbar-button,
.ledger::-webkit-scrollbar-button,
.ledger *::-webkit-scrollbar-button {
  display: none;
  width: 0;
  height: 0;
}
}

.ledger a { color: var(--l-accent); text-decoration: none; }
.ledger a:hover { color: var(--l-accent-ink); }
.ledger :focus-visible {
  outline: 2px solid var(--l-accent);
  outline-offset: 2px;
  border-radius: 4px;
}
/* Единый контракт курсора для интерактивных элементов. Явное правило важно
   для WebKit/Chromium на macOS: при переходе между текстом, SVG и фоном одного
   контрола курсор не должен на кадр возвращаться к системной стрелке. */
.ledger :where(
  a[href],
  button:not(:disabled),
  summary,
  [role="button"],
  label[for],
  select,
  input[type="checkbox"],
  input[type="radio"]
) { cursor: pointer; }

/* Базовый чекбокс Ledger. Правило намеренно глобальное внутри приложения:
   новые формы и динамически добавленные контролы не должны откатываться к
   синему системному оформлению браузера. Специализированные варианты ниже
   меняют только размер/форму, сохраняя те же состояния. */
.ledger input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  display: inline-grid;
  place-content: center;
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  margin: 0;
  border: 1.5px solid var(--l-gray-400);
  border-radius: 4px;
  background: var(--l-surface);
  color: var(--l-on-accent);
  vertical-align: middle;
  cursor: pointer;
  transition: border-color 100ms ease, background 100ms ease, box-shadow 100ms ease, opacity 100ms ease;
}
.ledger input[type="checkbox"]::before {
  content: "";
  width: 4px;
  height: 8px;
  border: solid currentColor;
  border-width: 0 2px 2px 0;
  transform: translateY(-1px) rotate(45deg) scale(0);
  transition: transform 90ms ease;
}
.ledger input[type="checkbox"]:hover:not(:disabled) {
  border-color: var(--l-accent);
}
.ledger input[type="checkbox"]:checked,
.ledger input[type="checkbox"]:indeterminate {
  border-color: var(--l-accent);
  background: var(--l-accent);
}
.ledger input[type="checkbox"]:checked::before {
  transform: translateY(-1px) rotate(45deg) scale(1);
}
.ledger input[type="checkbox"]:indeterminate::before {
  width: 8px;
  height: 2px;
  border: 0;
  border-radius: 1px;
  background: currentColor;
  transform: none;
}
.ledger input[type="checkbox"]:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--l-accent) 18%, transparent);
}
.ledger input[type="checkbox"]:disabled {
  opacity: .45;
  cursor: not-allowed;
}

/* Деньги, номера, даты — моноширинная колонка выписки */
.l-mono {
  font-family: var(--l-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

/* ============================================================================
   Каркас: сайдбар + рабочая область
   ========================================================================== */
.l-app { display: grid; grid-template-columns: 232px 1fr; min-height: 100vh; }

.l-sidebar {
  background: var(--l-sidebar-bg);
  border-right: 1px solid var(--l-sidebar-border);
  color: var(--l-sidebar-text);
  padding: 18px 14px 14px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  position: sticky;
  top: 0;
  height: 100vh;
}
/* Шапка меню: метка и название кабинета вместо логотипа сервиса. Название —
   ссылка на раздел по умолчанию, шеврон справа — переключатель кабинетов, и
   он есть в разметке только когда кабинетов больше одного. */
.t2-tenant-head {
  min-height: 46px;
  display: flex;
  align-items: center;
  gap: 4px;
}
.ledger .t2-tenant-home {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border-radius: var(--l-r-md);
  color: var(--l-sidebar-strong);
  text-decoration: none;
}
.ledger .t2-tenant-home:hover { background: var(--l-sidebar-hover); }
.ledger .t2-tenant-switch {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: var(--l-r-md);
  background: transparent;
  color: var(--l-sidebar-text);
  cursor: pointer;
}
.ledger .t2-tenant-switch:hover { background: var(--l-sidebar-hover); color: var(--l-sidebar-strong); }
.l-brand-svg {
  display: block;
  overflow: visible;
}
.l-brand-ink {
  fill: var(--l-brand-ink, var(--l-text));
}
.l-brand-accent {
  fill: var(--l-brand-accent, var(--l-accent));
}
.l-brand-accent-stroke {
  fill: none;
  stroke: var(--l-brand-accent, var(--l-accent));
}
/* Короткий вьюпорт (лендскейп телефона, невысокое окно на десктопе) не вмещает
   все 13 пунктов: без прокрутки навигация вылезала за сайдбар и наезжала на
   рабочую область. min-height:0 нужен, чтобы flex-элемент внутри колонки
   фиксированной высоты вообще мог сжаться и включить свой скролл.
   Полосу прячем: сайдбар узкий (на 721–960px это рельс в 64px), а
   навигационные ленты в Ledger листаются без видимой полосы. */
.l-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
}
.l-nav::-webkit-scrollbar { display: none; width: 0; height: 0; }
/* Полосы прокрутки нет, поэтому о скрытых пунктах говорит растворяющаяся
   нижняя кромка. Класс ставит ledger.js только когда прокрутка реально есть и
   список не долистан до конца — иначе кромка гасила бы последний пункт. */
.l-nav.is-scrollable:not(.is-scroll-end) {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 26px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 26px), transparent);
}
/* Рельса стала длиннее на группу «Кабинет» и блок профиля: заголовки групп и
   пункты подтянуты так, чтобы всё меню умещалось на ноутбучном экране без
   прокрутки. Первому заголовку верхнее поле не нужно — над ним логотип. */
.l-nav-title {
  padding: 13px 10px 5px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--l-sidebar-title);
}
.l-nav > .l-nav-title:first-child { padding-top: 2px; }
/* .ledger-префикс — чтобы перебить глобальное `.ledger a { color: accent }` */
.ledger .l-nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 10px;
  border-radius: var(--l-r-sm);
  color: var(--l-sidebar-text);
  font-size: 13.5px;
  font-weight: 500;
  text-decoration: none;
  transition: background 120ms ease, color 120ms ease;
}
.ledger .l-nav-item:hover { background: var(--l-sidebar-hover); color: var(--l-sidebar-strong); }
.ledger .l-nav-item.is-active {
  background: var(--l-sidebar-active-bg);
  color: var(--l-sidebar-active-tx);
}
.l-nav-item svg { flex: 0 0 auto; opacity: 0.75; }
/* Подвал: профиль отдельной строкой, «Свернуть» и выход — одной под ним.
   Пока они шли блоками друг под другом, подвал забирал у меню 168px. */
.l-sidebar-foot {
  padding: 0 10px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  row-gap: 2px;
  font-size: 12px;
  color: var(--l-sidebar-title);
}
.l-sidebar-foot .t2-drawer-foot { order: -1; }
.ledger .l-sidebar-foot a { color: var(--l-sidebar-text); }
.ledger .l-sidebar-foot a:hover { color: var(--l-sidebar-strong); }

.l-main { padding: 26px 34px 60px; max-width: 1180px; width: 100%; min-width: 0; /* грид-колонка не растягивается шире вьюпорта (доска задач скроллится внутри) */ }

/* ============================================================================
   Топбар
   ========================================================================== */
.l-topbar {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 20px;
}
.l-title {
  margin: 0;
  font-size: 21px;
  font-weight: 700;
  letter-spacing: -0.02em;
}
.l-topbar .l-spacer { flex: 1; }

/* Кнопки (селекторы с .ledger — чтобы перебить .ledger a) */
.ledger .l-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 14px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface);
  color: var(--l-text);
  font: inherit;
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer !important;
  transition: background 120ms ease, border-color 120ms ease;
  text-decoration: none;
  user-select: none;
  -webkit-user-select: none;
}
.ledger .l-btn:hover,
.ledger .l-btn:active,
.ledger .l-btn:focus-visible { cursor: pointer !important; }
/* Внутренний текст/иконка не становятся отдельной hit-зоной: это устраняет
   мерцание pointer ↔ default при движении внутри одной кнопки. */
.ledger .l-btn > * {
  pointer-events: none;
  cursor: inherit !important;
}
.ledger .l-btn:disabled,
.ledger .l-btn[aria-disabled="true"] {
  cursor: not-allowed !important;
}
.ledger .l-btn:hover { background: var(--l-surface-hover); border-color: var(--l-gray-300); color: var(--l-text); }
/* Иконка внутри кнопки центрируется сама, без зависимости от метрик шрифта. */
.ledger .l-btn .l-btn-glyph { display: block; flex: none; }
.ledger .l-btn--primary {
  background: var(--l-accent);
  border-color: var(--l-accent);
  color: var(--l-on-accent);
}
.ledger .l-btn--primary:hover { background: var(--l-accent-ink); border-color: var(--l-accent-ink); color: var(--l-on-accent); }
.ledger .l-btn--ghost { border-color: transparent; background: transparent; }
.ledger .l-btn--ghost:hover { background: var(--l-gray-150); border-color: transparent; }

/* ============================================================================
   Виджеты оборота: одна карта, три колонки с волосяными разделителями
   ========================================================================== */
.l-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  background: var(--l-surface);
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  box-shadow: var(--l-shadow-card);
  margin-bottom: 18px;
}
.l-tile { padding: 16px 22px; }
.l-tile + .l-tile { border-left: 1px solid var(--l-hairline); }
.l-tile-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--l-text-3);
  margin-bottom: 6px;
}
.l-tile-value { font-size: 21px; font-weight: 500; }
.l-tile-value .cur { font-size: 14px; color: var(--l-text-3); margin-left: 2px; }
.l-tile--warn .l-tile-value { color: var(--l-warn); }
/* Приход и расход читаются знаком цвета — подпись остаётся нейтральной. */
.l-tile--income .l-tile-value { color: var(--l-accent-ink); }
.l-tile--expense .l-tile-value { color: var(--l-danger); }
/* Сумма, которую текущий фильтр отображения не показывает: цифра остаётся
   (она часть итога), но перестаёт спорить за внимание с активной стороной. */
.l-tile.is-muted .l-tile-value { color: var(--l-text-3); }
.l-tile-sub { margin-top: 2px; font-size: 12px; color: var(--l-text-3); }
.ledger a.l-tile--danger { display: block; color: inherit; }
.ledger a.l-tile--danger:hover { background: var(--l-danger-soft); }
.l-tile--danger .l-tile-value { color: var(--l-danger); }
.l-tile--danger .l-tile-label { color: var(--l-danger); opacity: .75; }

/* ============================================================================
   Фильтры
   ========================================================================== */
.l-filters {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 16px;
}
/* Сворачиваемая шапка фильтров существует только на телефоне. Кнопку прячем и
   отдельно от контейнера: так она гарантированно вне таб-порядка на широком
   экране, где панель фильтров и так раскрыта. */
.l-filter-mobile-head { display: none; }
.l-filter-toggle { display: none; }
.l-filter-mobile-section { display: contents; }
.l-filter-panel { display: contents; }
.l-mobile-order-controls { display: none; }

/* сегмент-контрол (период, вкладки) */
.l-seg {
  display: inline-flex;
  padding: 3px;
  background: var(--l-gray-150);
  border-radius: var(--l-r-md);
  gap: 2px;
}
.l-seg a, .l-seg button {
  appearance: none;
  border: 0;
  background: transparent;
  padding: 5px 12px;
  border-radius: var(--l-r-sm);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--l-text-2);
  cursor: pointer;
  text-decoration: none;
  transition: background 120ms ease, color 120ms ease;
}
.l-seg a:hover, .l-seg button:hover { color: var(--l-text); }
.l-seg .is-active {
  background: var(--l-surface);
  color: var(--l-text);
  box-shadow: 0 1px 2px rgba(23, 25, 29, 0.08);
}

/* нативный select, одетый по-людски */
.l-select {
  appearance: none;
  -webkit-appearance: none;
  padding: 7px 30px 7px 12px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238A9096' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat right 11px center;
  font: inherit;
  font-size: 13px;
  color: var(--l-text-2);
  cursor: pointer;
  max-width: 190px;
  transition: border-color 120ms ease;
}
.l-select:hover { border-color: var(--l-gray-300); }
.l-select.is-set { color: var(--l-text); border-color: var(--l-gray-300); font-weight: 500; }

/* toggle «Требуют внимания» */
.l-attn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-full);
  background: var(--l-surface);
  font-size: 13px;
  font-weight: 500;
  color: var(--l-text-2);
  cursor: pointer;
  user-select: none;
  transition: all 120ms ease;
}
.l-attn::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--l-gray-300);
  transition: background 120ms ease;
}
.l-attn input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
}
.l-attn:has(input:checked) {
  background: var(--l-warn-soft);
  border-color: #E8D5A8;
  color: var(--l-warn);
}
.l-attn:has(input:checked)::before { background: var(--l-warn); }
.l-attn:has(input:focus-visible) { outline: 2px solid var(--l-accent); outline-offset: 2px; }

.ledger a.l-filter-reset {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface);
  color: var(--l-text-3);
  text-decoration: none;
  transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
}
.ledger a.l-filter-reset:hover,
.ledger a.l-filter-reset:focus-visible {
  outline: none;
  border-color: color-mix(in srgb, var(--l-danger) 35%, var(--l-border));
  background: var(--l-danger-soft);
  color: var(--l-danger);
}
.l-filter-reset svg {
  display: block;
  pointer-events: none;
}
/* Пара «группировка + чекбокс-фильтр» вне мобильной панели ведёт себя как
   обычные дети формы (display: contents); собственную сетку контейнер
   получает только внутри .l-filter-panel (мобильный блок ниже). */
/* Кнопка-«селект» фильтра «Этапы»: мультивыбор через поповер t2-menu, но в
   ряду фильтров она выглядит как соседние селекты. Выравнивание и обрезка —
   то, что браузер даёт <select> сам, а <button> надо попросить. */
.l-filter-status {
  overflow: hidden;
  text-align: left;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ряд с вкладками вида */
.l-viewbar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}
.ledger .l-task-overdue-filter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--l-text-2);
  font-size: 12px;
  font-weight: 500;
  text-decoration: none;
}
.ledger .l-task-overdue-filter:hover,
.ledger .l-task-overdue-filter.is-active {
  color: var(--l-danger);
  background: var(--l-danger-soft);
}
.l-task-overdue-mark {
  width: 9px;
  height: 9px;
  flex: 0 0 auto;
  border: 1.5px solid var(--l-danger);
  border-radius: 50%;
}
.l-task-overdue-filter.is-active .l-task-overdue-mark { background: var(--l-danger); }

/* ============================================================================
   Карта контрагента
   ========================================================================== */
.l-cp-list { display: flex; flex-direction: column; gap: 14px; }

.l-cp {
  background: var(--l-surface);
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  box-shadow: var(--l-shadow-card);
  overflow: hidden;
}
.l-cp-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 20px 12px;
}
.l-cp-name {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  min-width: 0;
}
.l-cp-count { font-size: 12.5px; color: var(--l-text-3); font-weight: 400; white-space: nowrap; }
.l-cp-head .l-spacer { flex: 1; }
.l-attn-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 500;
  color: var(--l-warn);
  white-space: nowrap;
}
.l-attn-chip::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--l-warn);
}

/* группа договора */
.l-ct { border-top: 1px solid var(--l-hairline); }
.l-ct-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 20px 4px;
}
.l-ct-label {
  appearance: none;
  border: 0;
  background: transparent;
  padding: 2px 0;
  font-family: var(--l-font);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--l-text-3);
  cursor: pointer;
}
.l-ct-label:hover { color: var(--l-accent); }
.l-ct-label--warn { color: var(--l-warn); }
.l-ct-label--warn:hover { color: var(--l-amber-700); }

/* строка документа */
.l-doc {
  display: grid;
  grid-template-columns: 180px 96px 1fr 170px 168px 128px;
  align-items: center;
  gap: 12px;
  padding: 9px 20px;
  cursor: pointer;
  transition: background 120ms ease;
}
.l-doc:hover { background: var(--l-surface-hover); }
.l-doc + .l-doc { border-top: 1px solid var(--l-hairline); }
.l-ct .l-doc:first-of-type { border-top: 0; }

.l-doc--act.is-child { position: relative; }
.l-doc--act.is-child .l-doc-id { padding-left: 18px; }
.l-doc--act.is-child .l-doc-id::before {
  content: '';
  position: absolute;
  left: 24px;
  top: 50%;
  width: 8px;
  height: 8px;
  border-left: 1.5px solid var(--l-gray-300);
  border-bottom: 1.5px solid var(--l-gray-300);
  border-bottom-left-radius: 3px;
  transform: translateY(-70%);
}

.l-doc-id { display: flex; align-items: center; gap: 9px; min-width: 0; position: relative; }
.l-tag {
  flex: 0 0 auto;
  padding: 2px 7px;
  border-radius: 5px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.l-tag--inv { background: var(--l-accent-soft); color: var(--l-accent-ink); }
.l-tag--act { background: var(--l-gray-150); color: var(--l-gray-500); }
.l-doc-num { font-size: 13px; font-weight: 600; }
.l-doc-num a { color: var(--l-text); }
.l-doc-num a:hover { color: var(--l-accent); }

.l-doc-date { font-size: 12.5px; color: var(--l-text-3); }

/* сумма + полоса прогресса оплаты — подпись системы */
.l-amt { text-align: right; justify-self: end; min-width: 132px; }
.l-amt-value { font-size: 13.5px; font-weight: 500; white-space: nowrap; }
.l-amt-sub {
  margin-top: 1px;
  font-size: 11px;
  color: var(--l-text-3);
  white-space: nowrap;
}
.l-paybar {
  margin-top: 4px;
  height: 2px;
  border-radius: 1px;
  background: var(--l-gray-150);
  overflow: hidden;
}
.l-paybar i {
  display: block;
  height: 100%;
  border-radius: 1px;
  background: var(--l-accent);
}
.l-paybar--partial i { background: var(--l-warn); }
.l-tax-limits-cell { min-width: 270px; }
.l-tax-limit-row {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 3px 10px;
  color: var(--l-text-3);
  font-size: 10.5px;
}
.l-tax-limit-row + .l-tax-limit-row { margin-top: 7px; }
.l-tax-limit-row > span:nth-child(2) { text-align: right; white-space: nowrap; }
.l-tax-limit-row .l-paybar { grid-column: 1 / -1; width: 100%; margin-top: 0; }
.is-cancelled .l-amt-value { text-decoration: line-through; color: var(--l-text-3); }
.l-doc.is-cancelled { opacity: 0.62; }

/* статус-чип (кликабельный) */
.l-status {
  appearance: none;
  border: 1px solid transparent;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 11px;
  border-radius: var(--l-r-full);
  background: transparent;
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--l-text-2);
  cursor: pointer;
  white-space: nowrap;
  justify-self: start;
  transition: background 120ms ease, border-color 120ms ease;
}
.l-status:hover { background: var(--l-gray-150); border-color: var(--l-border); }
.l-status::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: 0 0 auto;
  background: var(--l-gray-300);
}
.l-status--paid::before, .l-status--signed::before { background: var(--l-accent); }
.l-status--paid, .l-status--signed { color: var(--l-accent-ink); }
.l-status--partial::before { background: var(--l-warn); }
.l-status--partial { color: var(--l-warn); }
.l-status--wait::before { background: transparent; box-shadow: inset 0 0 0 1.5px var(--l-gray-400); }
.l-status--attn::before { background: transparent; box-shadow: inset 0 0 0 1.5px var(--l-warn); }
.l-status--attn { color: var(--l-warn); }
.l-status--muted::before { background: var(--l-gray-300); }
.l-status--muted { color: var(--l-text-3); }
.l-status--overdue::before { background: var(--l-danger); }
.l-status--overdue { color: var(--l-danger); }
.l-status--draft { border: 1px dashed var(--l-gray-300); }
.l-status--draft::before { display: none; }

/* статус договора — тише, чем у документов */
.l-ct-status {
  appearance: none;
  border: 0;
  background: transparent;
  padding: 2px 6px;
  border-radius: var(--l-r-sm);
  font: inherit;
  font-size: 11.5px;
  font-weight: 500;
  color: var(--l-text-3);
  cursor: pointer;
}
.l-ct-status:hover { background: var(--l-gray-150); color: var(--l-text-2); }
.l-ct-status.is-set { color: var(--l-text-2); }
.l-ct-status.is-done { color: var(--l-accent-ink); }

/* действие справа */
.l-act-cell { justify-self: end; text-align: right; }
.l-cta {
  appearance: none;
  border: 0;
  background: transparent;
  padding: 4px 0;
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--l-accent);
  cursor: pointer;
  white-space: nowrap;
}
.l-cta:hover { color: var(--l-accent-ink); text-decoration: underline; text-underline-offset: 3px; }
.l-wait { font-size: 12px; color: var(--l-text-3); white-space: nowrap; }

/* показать все */
.l-more {
  display: block;
  width: 100%;
  appearance: none;
  border: 0;
  border-top: 1px solid var(--l-hairline);
  background: transparent;
  padding: 9px 20px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--l-text-3);
  cursor: pointer;
  text-align: center;
  transition: color 120ms ease, background 120ms ease;
}
.l-more:hover { color: var(--l-accent); background: var(--l-surface-hover); }
.l-hidden-docs { display: none; }
.l-hidden-docs.is-open { display: block; animation: l-reveal 180ms ease; }
@keyframes l-reveal {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}

/* ============================================================================
   Вкладка «Список» — таблица-выписка
   ========================================================================== */
/* Заголовки колонок не переносятся (white-space: nowrap), поэтому широкая
   таблица вылезает за карточку на любом узком окне, а не только на телефоне:
   в диапазоне рельса (721–960px) и в лендскейпе так терялись «Сумма», «Итого»
   и кнопки строк. Горизонтальная прокрутка — базовая, вертикаль по-прежнему
   обрезается, иначе скругления карточки закрашивались бы таблицей. */
.l-table-card {
  background: var(--l-surface);
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  box-shadow: var(--l-shadow-card);
  max-width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-inline: contain;
}
/* Внутри модалки карточка нужна только ради горизонтальной прокрутки: тень и
   заливка второго уровня на поверхности диалога выглядят лишним слоем. */
.l-modal .l-table-card {
  background: transparent;
  box-shadow: none;
}
.l-table { width: 100%; border-collapse: collapse; }
.l-table th {
  padding: 11px 14px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--l-text-3);
  text-align: left;
  border-bottom: 1px solid var(--l-border);
  white-space: nowrap;
}
.l-table th a { color: inherit; }
.l-table th a:hover { color: var(--l-text); }
.l-table th.is-sorted a { color: var(--l-accent-ink); }
.l-table td {
  padding: 10px 14px;
  border-top: 1px solid var(--l-hairline);
  font-size: 13px;
  vertical-align: middle;
}
.l-table tr:first-child td { border-top: 0; }
.l-table tbody tr { cursor: pointer; transition: background 120ms ease; }
.l-table tbody tr:hover { background: var(--l-surface-hover); }
.l-table tbody tr[data-op-row]:focus-visible {
  outline: 2px solid var(--l-accent);
  outline-offset: -3px;
}
.l-table .num { text-align: right; }
.l-table th.num { text-align: right; }
.l-table-primary { font-weight: 400; color: var(--l-text); }
.ledger a.l-table-primary { color: var(--l-text); text-decoration: none; }
.ledger a.l-table-primary:hover { color: var(--l-accent-ink); }
.l-cell-cp { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.l-cell-ct { font-size: 12px; color: var(--l-text-3); }
/* Номер документа — цельная метка: «№ 50» и значок отправки рядом с ним не
   разрываются на две строки. Авто-раскладка таблицы на узком десктопе (окно
   ~1000px с развёрнутым сайдбаром) ужимала колонку до min-content и переносила
   номер под «№». Когда сжимать уже некуда, таблица уходит в горизонтальную
   прокрутку .l-table-card — это штатное поведение, а не потеря данных. */
.l-cell-num { white-space: nowrap; }

/* Живой поиск по справочникам */
.l-directory-tools {
  display: flex;
  align-items: center;
  gap: 11px;
  min-height: 40px;
  margin-bottom: 14px;
}
.l-live-search {
  position: relative;
  width: min(100%, 440px);
  flex: 0 1 440px;
}
.l-live-search-input {
  width: 100%;
  height: 40px;
  padding: 8px 40px 8px 39px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface);
  color: var(--l-text);
  font: inherit;
  font-size: 13.5px;
  line-height: 1;
  appearance: none;
  -webkit-appearance: none;
  box-shadow: var(--l-shadow-card);
  transition: border-color 120ms ease, box-shadow 120ms ease, background 120ms ease;
}
.l-live-search-input::-webkit-search-cancel-button { display: none; }
.l-live-search-input::placeholder { color: var(--l-text-3); }
.l-live-search-input:hover { border-color: var(--l-gray-300); }
.l-live-search-input:focus {
  outline: none;
  border-color: var(--l-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--l-accent) 14%, transparent);
}
.l-live-search-icon,
.l-live-search-clear {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
}
.l-live-search-icon {
  left: 13px;
  color: var(--l-text-3);
  pointer-events: none;
  transition: color 120ms ease;
}
.l-live-search:focus-within .l-live-search-icon { color: var(--l-accent); }
.l-live-search-clear {
  right: 7px;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--l-text-3);
  cursor: pointer;
}
.l-live-search-clear:hover { background: var(--l-gray-150); color: var(--l-text); }
.l-live-search-clear svg { pointer-events: none; }
.l-live-search-count {
  color: var(--l-text-3);
  font-size: 12.5px;
  white-space: nowrap;
}
.l-live-table [data-live-search-row][hidden] { display: none; }
.l-live-search-empty {
  min-height: 250px;
  padding: 42px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--l-text-3);
  background: var(--l-surface);
  border: 1px dashed var(--l-border);
  border-radius: var(--l-r-lg);
}
.l-live-search-empty[hidden] { display: none; }
.l-live-search-empty-icon {
  width: 44px;
  height: 44px;
  margin-bottom: 13px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--l-gray-150);
  color: var(--l-text-2);
  font-size: 25px;
  line-height: 1;
}
.l-live-search-empty strong { color: var(--l-text); font-size: 15px; font-weight: 600; }
.l-live-search-empty > span:not(.l-live-search-empty-icon) { margin-top: 4px; font-size: 13px; }
.l-live-search-empty .l-btn { margin-top: 16px; }
.l-task-search-empty { min-height: 360px; }
@media (max-width: 620px) {
  .l-directory-tools { align-items: stretch; flex-direction: column; gap: 7px; }
  .l-live-search { width: 100%; flex-basis: auto; }
  .l-live-search-count { padding-left: 2px; }
}

/* ============================================================================
   Пустые состояния
   ========================================================================== */
.l-empty {
  padding: 64px 20px;
  text-align: center;
  color: var(--l-text-3);
  background: var(--l-surface);
  border: 1px dashed var(--l-border);
  border-radius: var(--l-r-lg);
}
.l-empty strong { display: block; color: var(--l-text-2); font-size: 15px; margin-bottom: 4px; }

/* Пустая коллекция задач: не «обрыв» списка, а ясная стартовая точка. */
.l-task-empty {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: 430px;
  padding: 58px 36px 34px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  background:
    radial-gradient(circle at 50% 8%, var(--l-accent-soft), transparent 38%),
    var(--l-surface);
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  box-shadow: var(--l-shadow-card);
}
.l-task-empty::before,
.l-task-empty::after {
  content: '';
  position: absolute;
  z-index: -1;
  width: 180px;
  height: 180px;
  border: 1px solid var(--l-border);
  border-radius: 50%;
  opacity: .38;
  pointer-events: none;
}
.l-task-empty::before { top: -112px; left: -72px; }
.l-task-empty::after { right: -92px; bottom: -126px; width: 220px; height: 220px; }
.l-task-empty-orbit {
  position: relative;
  width: 68px;
  height: 68px;
  margin-bottom: 20px;
  display: grid;
  place-items: center;
  color: var(--l-accent-ink);
  background: var(--l-accent-soft);
  border: 1px solid color-mix(in srgb, var(--l-accent) 28%, var(--l-border));
  border-radius: 50%;
  box-shadow:
    0 0 0 9px color-mix(in srgb, var(--l-accent-soft) 52%, transparent),
    0 12px 30px color-mix(in srgb, var(--l-accent) 12%, transparent);
}
.l-task-empty-orbit svg { width: 32px; height: 32px; }
.l-task-empty-spark {
  position: absolute;
  width: 6px;
  height: 6px;
  background: var(--l-accent);
  border-radius: 50%;
  box-shadow: 0 0 0 4px var(--l-surface);
}
.l-task-empty-spark--one { top: 1px; right: -6px; }
.l-task-empty-spark--two { bottom: 5px; left: -8px; width: 4px; height: 4px; opacity: .65; }
.l-task-empty-kicker {
  margin-bottom: 7px;
  color: var(--l-accent-ink);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.l-task-empty h2 {
  margin: 0;
  color: var(--l-text);
  font-size: 23px;
  line-height: 1.2;
  letter-spacing: -.025em;
}
.l-task-empty > p {
  max-width: 510px;
  margin: 10px 0 0;
  color: var(--l-text-2);
  font-size: 13.5px;
  line-height: 1.55;
}
.l-task-empty-actions {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 22px;
}
.l-task-empty-guide {
  width: min(100%, 760px);
  margin-top: 42px;
  padding-top: 22px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  border-top: 1px solid var(--l-hairline);
  text-align: left;
}
.l-task-empty-step {
  min-width: 0;
  padding: 12px;
  display: flex;
  align-items: center;
  gap: 10px;
  background: color-mix(in srgb, var(--l-gray-100) 68%, transparent);
  border: 1px solid color-mix(in srgb, var(--l-border) 72%, transparent);
  border-radius: var(--l-r-md);
}
.l-task-empty-step-icon {
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  color: var(--l-accent-ink);
  background: var(--l-accent-soft);
  border-radius: 50%;
  font-size: 11px;
  font-weight: 700;
}
.l-task-empty-step strong,
.l-task-empty-step small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.l-task-empty-step strong { color: var(--l-text); font-size: 12.5px; font-weight: 600; }
.l-task-empty-step small { margin-top: 2px; color: var(--l-text-3); font-size: 11.5px; }
.l-task-empty--filtered,
.l-task-empty--archive,
.l-task-empty--compact { min-height: 350px; padding-bottom: 54px; }
.l-task-empty--filtered .l-task-empty-orbit,
.l-task-empty--archive .l-task-empty-orbit { color: var(--l-text-2); background: var(--l-gray-150); border-color: var(--l-border); box-shadow: 0 0 0 9px color-mix(in srgb, var(--l-gray-150) 55%, transparent); }
.l-task-empty--filtered .l-task-empty-kicker,
.l-task-empty--archive .l-task-empty-kicker { color: var(--l-text-3); }

/* ============================================================================
   Поповер
   ========================================================================== */
.l-pop {
  position: fixed;
  /* Поля в task drawer используют тот же общий popover. Он должен быть выше
     drawer (+10) и backdrop (+9), но ниже модалок (+100) и toast (+80). */
  z-index: calc(var(--l-z-pop) + 30);
  min-width: 210px;
  background: var(--l-surface);
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  box-shadow: var(--l-shadow-pop);
  padding: 5px;
  /* Ограничение по высоте — базовое, а не «мобильное»: невысокое окно бывает и
     на 740–960px (лендскейп телефона, половина экрана на ноутбуке), и там из
     поповера срока уезжали нижние пункты. Вложенные слои (календарь, часы,
     выпадающие списки) позиционируются fixed и этой прокруткой не режутся. */
  max-height: min(78dvh, 620px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.l-pop[hidden] { display: none; }
.l-pop button.l-pop-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  appearance: none;
  border: 0;
  background: transparent;
  padding: 7px 10px;
  border-radius: var(--l-r-sm);
  font: inherit;
  font-size: 13px;
  color: var(--l-text);
  cursor: pointer;
  text-align: left;
}
.l-pop button.l-pop-item:hover { background: var(--l-gray-150); }
.l-pop button.l-pop-item.is-active { background: var(--l-accent-soft); color: var(--l-accent-ink); font-weight: 500; }
.l-pop button.l-pop-item.is-danger { color: var(--l-danger); }
.l-pop-sep { height: 1px; background: var(--l-hairline); margin: 5px 4px; }
.l-pop-hint {
  padding: 6px 10px 3px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--l-text-3);
}
/* Второй шаг меню «+» в заметках: сетка размеров таблицы вместо списка.
   Клетка размером с палец, подсветка идёт до наведённой или нажатой. */
.l-tablepick {
  padding: 3px 5px 5px;
  display: grid;
  grid-template-columns: repeat(6, 34px);
  gap: 3px;
}
.l-tablepick-cell {
  height: 34px;
  padding: 0;
  appearance: none;
  border: 1px solid var(--l-border);
  border-radius: 5px;
  background: var(--l-bg);
  cursor: pointer;
}
.l-tablepick-cell.is-on {
  border-color: var(--l-accent);
  background: var(--l-accent-soft);
}
.l-tablepick-cell:focus-visible { outline: 2px solid var(--l-accent); outline-offset: 1px; }
.l-pop-form { display: flex; gap: 6px; padding: 4px 6px 6px; align-items: center; }
.l-pop-form input[type="number"] {
  width: 110px;
  padding: 6px 8px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-sm);
  font-family: var(--l-mono);
  font-size: 12.5px;
}
.l-pop-form select {
  padding: 6px 6px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-sm);
  font: inherit;
  font-size: 12.5px;
}
.l-pop-form .l-btn { padding: 6px 10px; font-size: 12.5px; }

/* ============================================================================
   Адаптив и доступность
   ========================================================================== */
@media (max-width: 960px) {
  .l-app { grid-template-columns: 64px 1fr; }
  .l-sidebar { padding: 18px 8px; }
  /* В рельсе от шапки остаётся одна метка кабинета: название и шеврон в 64px
     не помещаются, а метка и есть узнаваемый знак кабинета. */
  .t2-tenant-head { justify-content: center; }
  .ledger .t2-tenant-home { flex: 0 0 auto; justify-content: center; padding: 7px; }
  .t2-tenant-head .t2-tenant-name,
  .ledger .t2-tenant-switch { display: none; }
  /* Счётчик — тоже <span>, но прятать его вместе с подписью нельзя: просрочка
     и непрочитанное остаются единственным сигналом в рельсе. */
  .l-nav-title, .l-nav-item span:not(.l-nav-badge), .l-sidebar-foot { display: none; }
  .l-nav-item { justify-content: center; position: relative; }
  .l-main { padding: 20px 16px 48px; }
  .l-doc { grid-template-columns: 130px 1fr 150px; }
  .l-doc-date, .l-act-cell { display: none; }
  .l-tiles { grid-template-columns: 1fr; }
  .l-tile + .l-tile { border-left: 0; border-top: 1px solid var(--l-hairline); }
}

@media (prefers-reduced-motion: reduce) {
  .ledger *, .ledger *::before, .ledger *::after {
    animation: none !important;
    transition: none !important;
  }
}

/* ============================================================================
   Панели, страницы карточек и форм
   ========================================================================== */
.l-panel {
  background: var(--l-surface);
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  box-shadow: var(--l-shadow-card);
  padding: 20px 22px;
  margin-bottom: 14px;
}
.l-panel-title {
  margin: 0 0 14px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--l-text-3);
}

/* шапка страницы карточки/формы: назад + заголовок + действия */
.l-pagehead {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
}
.l-back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface);
  color: var(--l-text-2);
  flex: 0 0 auto;
}
.l-back:hover { background: var(--l-surface-hover); color: var(--l-text); }
/* Заголовок с крошкой — колонка: крошка мелкой строкой над названием, а
   стрелка «назад» остаётся слева и по центру блока. */
.l-pagehead-copy { min-width: 0; display: flex; flex-direction: column; }
.l-pagehead-crumb { display: flex; align-items: center; gap: 4px; margin-bottom: 1px; }
.l-pagehead .l-title { font-size: 19px; }
.l-pagehead-sub { font-size: 12.5px; color: var(--l-text-3); margin-top: 1px; }
.l-create-fab,
.l-doc-mobile-actions,
.l-doc-mobile-downloads { display: none; }
.l-op-period-select,
.l-dd:has(> .l-op-period-select),
.l-doc-period-select,
.l-dd:has(> .l-doc-period-select) { display: none; }
.l-doc-party-inn {
  margin-left: 6px;
  color: var(--l-text-3);
  font-size: 12px;
}
.l-doc-sign-summary { grid-column: 1 / -1; }
/* Кнопки отправки и подсказка о ненастроенном канале. */
.l-send-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}
.l-send-hint { font-size: 12.5px; color: var(--l-text-3); }
.l-doc-edo-hint {
  margin-top: 9px;
  color: var(--l-text-3);
  font-size: 12.5px;
}
.l-doc-edo-hint span {
  border-bottom: 1px dashed var(--l-border);
  opacity: .7;
}
.l-doc-send-time {
  color: var(--l-text-3);
  font-size: 12px;
}
.l-doc-send-to { font-size: 12.5px; }
.l-doc-sign-form {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
.l-doc-sign-form .l-select,
.l-doc-sign-form input[type="date"] { width: auto; }
.l-doc-sign-form input:disabled {
  opacity: .55;
  cursor: default;
}
.l-doc-sign-save-state {
  min-width: 78px;
  color: var(--l-text-3);
  font-size: 12.5px;
}
.l-doc-sign-save-state.is-error { color: var(--l-danger); }

/* --- Оплата счёта: сводка, список записей, форма ---------------------------- */
/* Сводка одной строкой: бейдж статуса + либо прогресс «оплачено X / Y», либо
   дата получения. Полосу прогресса убрали — она повторяла эту же цифру. */
.l-pay-summary {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}
.l-pay-progress { font-size: 13px; }
.l-pay-progress .is-paid { color: var(--l-warn); font-weight: 600; }
.l-pay-progress .is-rest { color: var(--l-text-3); }
.l-pay-note { color: var(--l-text-3); font-size: 12.5px; }
/* Ошибка формы оплаты живёт рядом с формой, а не в шапке страницы: причина
   отказа («переплата») относится к конкретному вводу. */
.l-pay-error { margin: 0 0 12px; }

.l-paylist { margin-bottom: 12px; }
/* Ряд записи: дата | сумма | инструменты. Форма правки занимает всю ширину
   ряда, поэтому ряд — грид, а не флекс. */
.l-paylist-row {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto;
  align-items: center;
  gap: 4px 14px;
  padding: 7px 0;
  border-bottom: 1px solid var(--l-hairline);
  font-size: 13.5px;
}
.l-paylist-row:first-child { border-top: 1px solid var(--l-hairline); }
.l-paylist-date { color: var(--l-text-2); white-space: nowrap; }
.l-paylist-amount { font-weight: 500; white-space: nowrap; }
.l-paylist-tools {
  display: flex;
  align-items: center;
  gap: 2px;
  justify-self: end;
}
/* Пока строку правят, её значения прячутся: два одинаковых числа рядом
   (текст и поле) читались как две разные оплаты. */
.l-paylist-row.is-editing > .l-paylist-date,
.l-paylist-row.is-editing > .l-paylist-amount,
.l-paylist-row.is-editing > .l-paylist-tools { display: none; }

.l-payform {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
/* enhanceDateInput оборачивает поле в .l-date с width:100% — без этого
   ограничения дата растянулась бы на весь ряд и вытолкнула сумму. */
.l-payform .l-date { width: auto; flex: 0 0 auto; }
.l-payform .l-date-btn { min-width: 148px; }
.l-payform input[type="date"],
.l-payform input[type="number"],
.l-payform .l-select { width: auto; }
.l-payform input[type="number"] { width: 140px; }
.l-payform-tools {
  display: flex;
  align-items: center;
  gap: 2px;
}
/* Подтверждение записи — не «ещё один значок», а кнопка сохранения: призрачная
   галочка цвета --l-text-3 не читалась как действие. Отмена рядом остаётся
   тихой, чтобы пара не спорила. */
.l-payform-tools .l-iconbtn[type="submit"] {
  color: var(--l-accent-ink);
  background: var(--l-accent-soft);
}
.l-payform-tools .l-iconbtn[type="submit"]:hover {
  color: var(--l-on-accent);
  background: var(--l-accent);
}

/* Разделитель перед действиями со всем счётом: список записей — про деньги,
   «Оплачен полностью» — про статус документа. */
.l-pay-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--l-hairline);
}
.l-pay-actions form { display: flex; align-items: center; gap: 8px; }
.l-pay-actions .l-date { width: auto; flex: 0 0 auto; }
.l-pay-actions input[type="date"],
.l-pay-actions select { width: auto; }

/* --- Служебные действия документа ------------------------------------------ */
/* Отдельная панель внизу страницы: смена статуса и отмена — не про оплату,
   в блоке «Оплата» они перебивали единственное там важное действие. */
.l-doc-service-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}
.l-doc-service-gap { flex: 1; }

/* хаб настроек: заголовок группы карточек.
   Рисунок .l-panel-title, но вне панели: группа — это подпись к сетке, а
   заворачивать сетку в панель значило бы вложить карточки в карточку. */
.l-setgroup-title {
  margin: 0 0 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--l-text-3);
}
/* Между группами воздуха больше, чем между заголовком и его сеткой, — иначе
   подпись липнет к чужим карточкам сверху. */
.l-setgrid + .l-setgroup-title { margin-top: 22px; }

/* хаб настроек: карточки модулей */
.l-setgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
  /* Тот же ритм, что у .l-panel: без него панель после сетки (например
     «Пароль» в профиле) прилипала к карточкам вплотную. */
  margin-bottom: 14px;
}
.l-setcard {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 16px 18px;
  background: var(--l-surface);
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  box-shadow: var(--l-shadow-card);
  color: inherit;
}
/* .ledger a красит ссылки акцентом — карточка остаётся текстовой поверхностью */
.ledger a.l-setcard { color: inherit; }
.ledger a.l-setcard:hover {
  border-color: var(--l-accent);
  background: var(--l-surface-hover);
  color: inherit;
}
.l-setcard-icon { color: var(--l-text-3); }
.l-setcard-title { font-size: 14px; font-weight: 600; }
.l-setcard-desc { font-size: 12.5px; color: var(--l-text-3); }
.l-setcard-hint { margin-top: 2px; }

/* Строки-ссылки внутри панели настроек («Настроить кассы», «Настроить
   категории»): заметный пункт с подписью и шевроном, а не пара слов у
   заголовка, которую читали как табы. */
.l-setrows { display: grid; gap: 8px; margin: 4px 0 14px; }
.l-setrow {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-gray-100);
}
.ledger a.l-setrow { color: inherit; }
.ledger a.l-setrow:hover { border-color: var(--l-accent); background: var(--l-surface-hover); color: inherit; }
.l-setrow-copy { min-width: 0; flex: 1; display: grid; gap: 2px; }
.l-setrow-copy strong { font-size: 13.5px; font-weight: 600; }
.l-setrow-copy small { color: var(--l-text-3); font-size: 12px; }
.l-setrow > svg { flex: 0 0 auto; color: var(--l-text-3); }

/* шапка выдвижной панели настроек (см. #settings-drawer в мобильном блоке) */
.l-setdrawer-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}
/* Распорка шапки: без неё «✕» вставало вплотную к заголовку, а не к краю. */
.l-setdrawer-head .l-spacer { flex: 1; }
.l-setdrawer-title { margin: 0; font-size: 17px; font-weight: 600; }

/* ключ-значение на карточках */
.l-kv { display: grid; grid-template-columns: 168px 1fr; gap: 9px 18px; font-size: 13.5px; }
.l-kv .k { color: var(--l-text-3); }
.l-kv .v { min-width: 0; }
.l-doc-badges {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 7px;
}
.l-doc-badges .l-badge { margin: 0; }
.l-doc-badge-note { color: var(--l-text-3); font-size: 12.5px; }

/* заголовок секции внутри страницы (карточки, разделы) */
.l-h2 { font-size: 15px; font-weight: 600; margin: 24px 0 10px; color: var(--l-text); }
.l-h2 .l-count { color: var(--l-text-3); font-weight: 500; font-size: 13px; margin-left: 4px; }

/* ============================================================================
   Финансы: реестр операций, платёжный календарь, отчёт ДДС
   ========================================================================== */
/* Оперативный дашборд «Деньги»: кассы, план, дебиторка и обороты. */
.l-money-overview {
  display: grid;
  grid-template-columns: minmax(0, 1.16fr) repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin-bottom: 26px;
  align-items: stretch;
}
.l-money-card {
  min-width: 0;
  height: 100%;
  padding: 18px;
}
.l-money-card-head,
.l-money-section-head {
  min-width: 0;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
}
.l-money-card-head { margin-bottom: 15px; }
.l-money-card-head > div,
.l-money-section-head > div { min-width: 0; }
.l-money-card .l-h2,
.l-money-section-head .l-h2 {
  margin: 0;
  font-size: 16px;
}
.l-money-card-note,
.l-money-section-head p {
  display: block;
  margin: 3px 0 0;
  color: var(--l-text-3);
  font-size: 11.5px;
  line-height: 1.35;
}
.l-money-head-value {
  flex: 0 0 auto;
  color: var(--l-text);
  font-size: 17px;
  font-weight: 600;
  white-space: nowrap;
}
.l-money-head-value.is-negative,
.l-money-account-group-head .is-negative,
.l-money-account-row .is-negative,
.l-turnover-row .is-negative { color: var(--l-danger); }
.ledger a.l-money-card-link {
  flex: 0 0 auto;
  padding-top: 2px;
  color: var(--l-text-3);
  font-size: 11.5px;
  font-weight: 550;
  white-space: nowrap;
}
.ledger a.l-money-card-link:hover { color: var(--l-accent-ink); }
.l-money-setup {
  min-height: 156px;
  padding: 18px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  gap: 6px;
  border: 1px dashed var(--l-border);
  border-radius: var(--l-r-md);
  color: var(--l-text-3);
  font-size: 12.5px;
  line-height: 1.45;
}
.l-money-setup strong { color: var(--l-text); font-size: 14px; }
.l-money-setup-actions {
  margin-top: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}
.l-money-account-groups {
  display: grid;
  gap: 15px;
}
.l-money-account-group {
  min-width: 0;
  display: grid;
  gap: 3px;
}
.l-money-account-group + .l-money-account-group {
  padding-top: 14px;
  border-top: 1px solid var(--l-hairline);
}
.l-money-account-group-head,
.l-money-account-row {
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
}
.l-money-account-group-head {
  padding: 0 8px 5px;
  color: var(--l-text-2);
  font-size: 12px;
}
.l-money-account-group-head > strong {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-money-account-group-head > span,
.l-money-account-row > .l-mono { white-space: nowrap; }
.ledger a.l-money-account-row {
  min-height: 45px;
  padding: 7px 8px;
  border-radius: var(--l-r-sm);
  color: var(--l-text);
}
.ledger a.l-money-account-row:hover {
  background: var(--l-surface-hover);
  color: var(--l-text);
}
.l-money-account-name {
  min-width: 0;
  display: grid;
  gap: 1px;
}
.l-money-account-name strong,
.l-money-account-name small {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-money-account-name strong { font-size: 13px; font-weight: 550; }
.l-money-account-name small { color: var(--l-text-3); font-size: 10.5px; }
.ledger a.l-money-summary-line {
  min-height: 40px;
  margin-bottom: 7px;
  padding: 8px 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border-radius: var(--l-r-sm);
  background: var(--l-danger-soft);
  color: var(--l-danger);
  font-size: 12px;
}
.l-money-list {
  display: grid;
  gap: 3px;
}
.ledger a.l-money-list-row {
  min-width: 0;
  min-height: 49px;
  padding: 7px 8px;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 9px;
  border-radius: var(--l-r-sm);
  color: var(--l-text);
}
.ledger a.l-money-list-row:hover {
  background: var(--l-surface-hover);
  color: var(--l-text);
}
.ledger a.l-money-list-row--debt {
  grid-template-columns: minmax(0, 1fr) auto;
}
.ledger a.l-money-list-row.is-overdue {
  background: color-mix(in srgb, var(--l-danger-soft) 58%, transparent);
}
.l-money-list-date {
  color: var(--l-text-3);
  font-size: 10.5px;
}
.l-money-list-main {
  min-width: 0;
  display: grid;
  gap: 2px;
}
.l-money-list-main strong,
.l-money-list-main small {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-money-list-main strong { font-size: 12.5px; font-weight: 550; }
.l-money-list-main small { color: var(--l-text-3); font-size: 10.5px; }
.l-money-list-sum {
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
}
.l-money-list-sum.is-income { color: var(--l-accent-ink); }
.l-money-list-sum.is-expense { color: var(--l-danger); }
.l-money-list-sum.is-transfer { color: var(--l-info); }
.l-money-empty {
  min-height: 112px;
  padding: 20px 12px;
  display: grid;
  place-items: center;
  color: var(--l-text-3);
  font-size: 12.5px;
  line-height: 1.45;
  text-align: center;
}
.l-money-receivable-summary {
  margin-bottom: 7px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid var(--l-hairline);
  border-radius: var(--l-r-md);
  overflow: hidden;
}
.l-money-receivable-summary > div,
.ledger .l-money-receivable-summary > a {
  min-width: 0;
  padding: 9px 10px;
  display: grid;
  gap: 3px;
  color: var(--l-text);
}
.l-money-receivable-summary > * + * { border-left: 1px solid var(--l-hairline); }
.l-money-receivable-summary span {
  overflow: hidden;
  color: var(--l-text-3);
  font-size: 10.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-money-receivable-summary strong {
  overflow: hidden;
  font-size: 13px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ledger .l-money-receivable-summary > a:hover {
  background: var(--l-surface-hover);
  color: var(--l-text);
}
.ledger .l-money-receivable-summary > a.is-danger,
.ledger .l-money-receivable-summary > a.is-danger span { color: var(--l-danger); }
.l-money-debt-side {
  display: grid;
  gap: 2px;
  justify-items: end;
  text-align: right;
}
.l-money-debt-side strong { font-size: 11.5px; white-space: nowrap; }
.l-money-debt-side small { color: var(--l-text-3); font-size: 9.5px; white-space: nowrap; }

.l-money-turnover { min-width: 0; }
.l-money-section-head {
  margin-bottom: 13px;
  align-items: end;
}
.l-turnover-periods { display: none; }
.l-turnover-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}
.l-turnover-card {
  min-width: 0;
  padding: 17px 18px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  background: var(--l-surface);
  box-shadow: var(--l-shadow-card);
}
.l-turnover-card.is-total {
  grid-column: 1 / -1;
  border-color: color-mix(in srgb, var(--l-accent) 35%, var(--l-border));
  background: color-mix(in srgb, var(--l-accent-soft) 35%, var(--l-surface));
}
.l-turnover-card h3 {
  min-width: 0;
  margin: 0 0 11px;
  overflow: hidden;
  color: var(--l-text);
  font-size: 14px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-turnover-table { min-width: 0; }
.l-turnover-row {
  min-width: 0;
  min-height: 35px;
  display: grid;
  grid-template-columns: minmax(110px, 1fr) repeat(3, minmax(100px, .8fr));
  align-items: center;
  gap: 12px;
  border-top: 1px solid var(--l-hairline);
  color: var(--l-text-2);
  font-size: 12px;
}
.l-turnover-row > *:not(:first-child) {
  min-width: 0;
  text-align: right;
  white-space: nowrap;
}
.l-turnover-row--head {
  min-height: 25px;
  border-top: 0;
  color: var(--l-text-3);
  font-size: 9.5px;
  font-weight: 650;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.l-turnover-row--total {
  min-height: 42px;
  color: var(--l-text);
}
.l-turnover-row--total > * { font-weight: 600; }

/* плановая операция — приглушённая строка */
.l-row-plan td { opacity: .72; }
.l-op-party-mobile,
.l-op-mobile-flags,
.l-planner-card-date { display: none; }
.l-op-amount.l-op-tone--income { color: var(--l-accent-ink); }
.l-op-amount.l-op-tone--expense { color: var(--l-danger); }
.l-op-amount.l-op-tone--transfer { color: var(--l-info); }
.l-op-status {
  min-height: 32px;
  padding: 5px 25px 5px 10px;
  position: relative;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-full);
  background: var(--l-gray-100);
  color: var(--l-text-2);
  font: inherit;
  font-size: 12px;
  white-space: nowrap;
  cursor: pointer;
}
.l-op-status::after {
  content: '';
  position: absolute;
  right: 10px;
  top: 50%;
  width: 6px;
  height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-65%) rotate(45deg);
}
.l-op-status:hover,
.l-op-status[aria-expanded="true"] {
  border-color: color-mix(in srgb, var(--l-accent) 38%, var(--l-border));
  background: var(--l-accent-soft);
  color: var(--l-accent-ink);
}
.l-inline-choice {
  display: inline-flex;
  align-items: center;
  min-height: 27px;
  padding: 4px 10px;
  border: 1px dashed var(--l-border);
  border-radius: var(--l-r-full);
  background: var(--l-gray-100);
  color: var(--l-text-3);
  font: inherit;
  font-size: 12px;
  white-space: nowrap;
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
}
.l-inline-choice:hover,
.l-inline-choice:focus-visible {
  outline: none;
  border-color: color-mix(in srgb, var(--l-accent) 45%, var(--l-border));
  background: var(--l-accent-soft);
  color: var(--l-accent-ink);
}
/* кассовый разрыв в прогнозе */
.l-row-gap td { background: var(--l-danger-soft); }
/* Лента дня в календаре платежей: колонка «Дата» уходила в каждую строку,
   хотя платежи читают по дням. Заголовок группы, а не строка таблицы. */
.l-table tr.l-planner-day td {
  padding: 18px 12px 6px;
  border-top: 0;
  border-bottom: 1px solid var(--l-hairline);
  font-size: 11.5px;
  font-weight: 650;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--l-text-2);
}
.l-table tbody tr.l-planner-day:first-child td { padding-top: 8px; }
/* Одна линия под лентой, а не две: у ячеек таблицы своя верхняя кромка. */
.l-table tr.l-planner-day + tr td { border-top: 0; }
.l-table tbody tr.l-planner-day,
.l-table tbody tr.l-planner-day:hover { cursor: default; background: transparent; }
.l-table tr.l-planner-day .l-badge { padding: 1px 8px; font-size: 10.5px; letter-spacing: .04em; }
.l-table tr.l-planner-day .l-badge::before { width: 5px; height: 5px; }

/* отчёт ДДС */
.l-dds td, .l-dds th { white-space: nowrap; }
.l-dds-total td { background: var(--l-gray-100); font-weight: 500; }
.l-dds-saldo td { border-top: 2px solid var(--l-border); font-weight: 500; }
.l-dds-bar {
  width: 110px;
  height: 6px;
  border-radius: 3px;
  background: var(--l-gray-150);
  overflow: hidden;
}
.l-dds-bar i { display: block; height: 100%; border-radius: 3px; }

/* модал операции */
.l-modal-overlay[hidden] { display: none; }
.l-modal.l-op-modal {
  display: flex;
  flex-direction: column;
  width: min(740px, calc(100vw - 32px));
  max-width: 740px;
  max-height: calc(100vh - 32px);
  padding: 0;
  overflow: hidden;
}
.l-modal.l-op-modal [hidden] { display: none !important; }
.l-op-modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  padding: 22px 26px 18px;
  border-bottom: 1px solid var(--l-hairline);
}
.l-op-modal-head .l-op-modal-kicker,
.l-op-section-title {
  color: var(--l-text-3);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.l-modal.l-op-modal .l-op-modal-head h3 {
  margin: 4px 0 3px;
  color: var(--l-text);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -.02em;
}
.l-modal.l-op-modal .l-op-modal-head p {
  margin: 0;
  color: var(--l-text-3);
  font-size: 12.5px;
}
.l-op-modal-close {
  flex: 0 0 auto;
  margin: -4px -6px 0 0;
  font-size: 15px;
}
.l-op-modal form {
  flex: 1 1 auto;
  min-height: 0;
  padding: 16px 26px 18px;
  overflow-y: auto;
}
.l-op-section + .l-op-section {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--l-hairline);
}
.l-op-section-title { margin-bottom: 8px; }
.l-op-modal .l-op-kind {
  display: flex;
  width: 100%;
  margin-bottom: 12px;
}
.l-op-modal .l-op-kind button {
  flex: 1;
  padding-top: 8px;
  padding-bottom: 8px;
  font-size: 13.5px;
}
.l-op-modal .l-grid2 {
  gap: 12px 18px;
}
.l-op-modal .l-grid2 + .l-grid2 { margin-top: 12px; }
.ledger .l-op-modal .l-label {
  margin: 0 0 6px;
  font-family: var(--l-font);
  font-size: 10.5px;
}
.l-op-modal .l-input,
.l-op-modal .l-dd-btn {
  min-height: 42px;
  font-family: var(--l-font);
  font-size: 13.5px;
  font-weight: 400;
  letter-spacing: normal;
  line-height: 1.3;
}
.l-op-modal .l-input.l-mono {
  font-family: var(--l-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}
.l-op-modal .l-dd-btn.is-set { font-weight: 400; }
.l-op-label-action {
  display: flex !important;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.l-op-label-action .l-cta {
  font-size: 11px;
  letter-spacing: 0;
  text-transform: none;
}
.l-op-options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-top: 14px;
}
.l-op-modal .l-op-option {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-width: 0;
  margin: 0;
  padding: 9px 12px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface);
  transition: border-color 120ms ease, background 120ms ease;
}
.l-op-modal .l-op-option:hover,
.l-op-modal .l-op-option:has(input:checked) {
  border-color: color-mix(in srgb, var(--l-accent) 35%, var(--l-border));
  background: color-mix(in srgb, var(--l-accent) 5%, var(--l-surface));
}
.l-op-option input { flex: 0 0 auto; margin-top: 2px; }
.l-op-option > span { min-width: 0; }
.l-op-option strong,
.l-op-option small { display: block; }
.l-modal.l-op-modal .l-op-option[hidden],
.l-op-option [hidden] { display: none !important; }
.l-op-option strong {
  color: var(--l-text);
  font-size: 13px;
  font-weight: 600;
}
.l-op-option small {
  margin-top: 2px;
  color: var(--l-text-3);
  font-size: 11.5px;
  line-height: 1.35;
}
.l-modal.l-op-modal .l-op-actions {
  position: relative;
  z-index: 2;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 15px 26px;
  border-top: 1px solid var(--l-hairline);
  background: var(--l-surface);
}

@media (max-width: 680px) {
  .l-modal.l-op-modal { width: min(100%, calc(100vw - 20px)); max-height: calc(100vh - 20px); }
  .l-op-modal-head { padding: 18px 18px 15px; }
  .l-op-modal form { padding: 17px 18px 20px; }
  .l-op-modal .l-grid2,
  .l-op-options { grid-template-columns: 1fr; }
  .l-modal.l-op-modal .l-op-actions {
    margin: 0;
    padding: 13px 18px;
    flex-wrap: wrap;
  }
}

/* ============================================================================
   Задачи: список, доска, карточка, drawer
   ========================================================================== */
.l-nav-badge {
  margin-left: auto;
  background: var(--l-danger);
  color: var(--l-on-danger);
  font-size: 10.5px;
  font-weight: 600;
  padding: 1px 7px;
  border-radius: var(--l-r-full);
  flex: 0 0 auto;
}
/* Красный бейдж означает «требует действия» (просрочка).
   Занятые места команды — не тревога, а факт: тот же пилюлькой, но спокойным
   цветом, иначе «1/5» читалось бы как авария. */
.l-nav-badge--calm {
  background: var(--l-sidebar-hover);
  color: var(--l-sidebar-text);
  font-family: var(--l-mono);
  letter-spacing: -.02em;
}
/* Непрочитанные уведомления — новость, а не тревога: бейдж колокольчика
   акцентный, в цвет темы, красным в навигации говорит только просрочка. */
#l-bell-btn .l-nav-badge {
  background: var(--l-accent);
  color: var(--l-on-accent);
}
html.l-collapsed .l-nav-badge { display: none; }
/* В свёрнутом сайдбаре цифре негде поместиться, но факт непрочитанного терять
   нельзя: бейдж колокольчика превращается в точку у верхнего угла иконки. */
html.l-collapsed #l-bell-btn { position: relative; }
html.l-collapsed #l-bell-btn .l-nav-badge {
  display: block;
  position: absolute;
  top: 6px;
  right: 12px;
  width: 8px;
  height: 8px;
  min-width: 0;
  margin: 0;
  padding: 0;
  border-radius: 50%;
  font-size: 0;
  line-height: 0;
}

/* Точка непрочитанного на мобильном колокольчике. Акцентная, не красная:
   непрочитанное уведомление — новость, а не тревога; красным в шапке говорит
   только просрочка. */
.l-bell-dot {
  position: absolute;
  top: 9px;
  right: 9px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--l-accent);
  box-shadow: 0 0 0 2px var(--l-bg);
}

/* --- Лента центра уведомлений (внутри .l-pop) ----------------------------- */
.l-pop[data-for="notifications"] { width: min(360px, calc(100vw - 20px)); }
.l-notif-list {
  display: flex;
  max-height: min(52vh, 420px);
  flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.l-notif-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 28px;
  align-items: start;
  gap: 2px;
  border-radius: var(--l-r-sm);
}
.l-notif-row:hover { background: var(--l-gray-150); }
.l-notif-main {
  display: flex;
  min-width: 0;
  padding: 8px 4px 8px 10px;
  flex-direction: column;
  gap: 3px;
  border: 0;
  border-radius: var(--l-r-sm);
  background: transparent;
  font: inherit;
  color: var(--l-text);
  text-align: left;
  cursor: pointer;
}
.l-notif-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.l-notif-head strong {
  min-width: 0;
  flex: 1;
  overflow: hidden;
  font-size: 13px;
  font-weight: 550;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-notif-time {
  flex: 0 0 auto;
  color: var(--l-text-3);
  font-size: 10.5px;
}
.l-notif-body {
  display: -webkit-box;
  overflow: hidden;
  color: var(--l-text-2);
  font-size: 12px;
  line-height: 1.4;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
.l-notif-row.is-unread .l-notif-head strong { font-weight: 650; }
.l-notif-toggle {
  position: relative;
  width: 24px;
  height: 24px;
  margin: 9px 4px 0 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}
.l-notif-toggle::before {
  content: "";
  display: block;
  width: 8px;
  height: 8px;
  margin: auto;
  border: 1.5px solid var(--l-gray-300);
  border-radius: 50%;
}
.l-notif-row.is-unread .l-notif-toggle::before {
  border-color: var(--l-accent);
  background: var(--l-accent);
}
.l-notif-toggle:hover::before { border-color: var(--l-accent); }
.l-notif-empty {
  padding: 14px 10px 16px;
  color: var(--l-text-3);
  font-size: 12.5px;
  text-align: center;
}
/* Подвал ленты: «Прочитать все» и «Очистить» — настоящие кнопки в один ряд,
   а не пункты меню, иначе на телефоне они читались как ещё два уведомления.
   Правило заперто в поповере уведомлений: .l-btn общий для всего приложения. */
.l-pop[data-for="notifications"] .l-notif-actions {
  display: flex;
  gap: 8px;
  padding: 4px;
}
.l-pop[data-for="notifications"] .l-notif-actions .l-btn {
  flex: 1;
  justify-content: center;
}
/* Канон опасного текстового действия: цвет, а не заливка (см. /design). */
.l-pop[data-for="notifications"] .l-notif-actions .l-btn.is-danger { color: var(--l-danger); }

.l-status-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--dot-c, var(--l-gray-400));
  display: inline-block; flex: 0 0 auto;
}

/* группы списка */
.l-tgroups { display: flex; flex-direction: column; gap: 18px; }
.l-tgroup-head {
  display: flex; align-items: center; gap: 8px;
  font-size: 13.5px; font-weight: 600; margin-bottom: 6px;
}
.l-tgroup-count { color: var(--l-text-3); font-weight: 500; font-size: 12px; }
.l-tgroup-body { display: flex; flex-direction: column; gap: 2px; min-height: 34px; }
.l-tgroup.is-empty {
  padding: 8px 10px;
  display: grid;
  grid-template-columns: minmax(180px, 240px) minmax(160px, 1fr);
  align-items: center;
  gap: 16px;
  border: 1px dashed var(--l-border);
  border-radius: var(--l-r-md);
  background: color-mix(in srgb, var(--l-gray-100) 44%, transparent);
}
.l-tgroup.is-empty .l-tgroup-head { margin: 0; }
.l-tgroup.is-empty .l-tgroup-body { min-height: 0; }
.l-tgroup.is-empty .l-inline-add-btn { padding: 6px 10px; text-align: right; }

/* строка задачи */
.l-trow {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 12px;
  background: var(--l-surface);
  background-clip: padding-box;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  overflow: hidden;
  cursor: grab;
}
.l-trow:hover { background: var(--l-surface-hover); }
.l-trow-title { font-size: 13.5px; cursor: pointer; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.l-trow-title:hover { color: var(--l-accent-ink); }
.l-trow.is-done .l-trow-title, .l-tcard.is-done .l-tcard-title { text-decoration: line-through; color: var(--l-text-3); }
.l-trow-meta { margin-left: auto; display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
/* Чекбокс массового выбора есть в каждой строке, но виден только в режиме
   выбора на телефоне (мобильный блок ниже): на широком экране для этого есть
   табличный вид со своей колонкой отметок. Селектор с .ledger обязателен —
   базовое правило .ledger input[type="checkbox"] специфичнее пары классов. */
.ledger .l-trow .l-rowcheck { display: none; }

/* чекбокс «готово» */
.l-done-check {
  width: 17px; height: 17px; flex: 0 0 auto;
  border: 1.6px solid var(--l-gray-400);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  position: relative;
  padding: 0;
}
.l-done-check:hover { border-color: var(--l-accent); }
.l-done-check:focus-visible {
  border-radius: 50%;
  outline-offset: 3px;
}
.l-done-check.is-on { background: var(--l-accent); border-color: var(--l-accent); }
.l-done-check.is-on::after {
  content: ''; position: absolute; left: 4.5px; top: 1.5px;
  width: 4px; height: 8px;
  border: solid var(--l-on-accent); border-width: 0 1.8px 1.8px 0;
  transform: rotate(45deg);
}

/* мета-элементы строки/карточки */
.l-tmeta { font-size: 11.5px; color: var(--l-text-3); background: none; border: 0; padding: 0; font-family: var(--l-font); }
button.l-tmeta, .l-tproject { cursor: pointer; }
.l-tproject:hover { color: var(--l-accent-ink); }
.l-tproject.is-empty { opacity: 0; }
.l-trow:hover .l-tproject.is-empty, .l-tcard:hover .l-tproject.is-empty { opacity: .7; }
.l-tdue {
  font-size: 11.5px; color: var(--l-text-2);
  background: none; border: 0; padding: 2px 4px; border-radius: var(--l-r-sm); cursor: pointer;
}
.l-tdue:hover { background: var(--l-gray-150); }
.l-tdue.is-overdue { color: var(--l-danger); font-weight: 600; }
.l-tdue.is-today { color: var(--l-warn); font-weight: 600; }
/* пустой срок: блеклый календарик, виден всегда (ярче на hover) */
.l-tdue.is-empty { opacity: .45; display: inline-flex; align-items: center; gap: 4px; font-family: var(--l-font); }
.l-trow:hover .l-tdue.is-empty, .l-tcard:hover .l-tdue.is-empty, .l-ttable tr:hover .l-tdue.is-empty { opacity: .9; }
.l-tdue.is-empty svg { flex: 0 0 auto; }
.l-prio { background: none; border: 0; padding: 2px; cursor: pointer; display: inline-flex; align-items: center; gap: 5px; border-radius: var(--l-r-sm); }
.l-prio:hover { background: var(--l-gray-150); }
.l-prio--urgent { color: var(--l-danger); }
.l-prio--high { color: var(--l-priority-high); }
.l-prio--normal { color: var(--l-gray-400); }
.l-prio--low { color: var(--l-info); }
/* «Обычный» — не сигнал: флажок скрыт до hover (в таблице и карточке задачи виден всегда) */
/* обычный приоритет показываем приглушённо-серым (пустое место — негармонично) */
.l-trow .l-prio--normal:not(.l-prio--labeled), .l-tcard .l-prio--normal:not(.l-prio--labeled) { opacity: .45; }
.l-trow:hover .l-prio--normal, .l-tcard:hover .l-prio--normal { opacity: 1; }
.l-prio--labeled { font-size: 12.5px; color: var(--l-text-2); font-family: var(--l-font); }
.l-prio--labeled svg { color: inherit; }
.l-prio--labeled.l-prio--urgent, .l-prio--labeled.l-prio--urgent svg { color: var(--l-danger); }
.l-prio--labeled.l-prio--high,
.l-prio--labeled.l-prio--high svg { color: var(--l-priority-high); }
.l-prio--labeled.l-prio--high { font-weight: 500; }
.l-prio--labeled.l-prio--low svg { color: var(--l-info); }
.l-avatar {
  width: 22px; height: 22px; flex: 0 0 auto;
  border-radius: 50%;
  background: var(--av-c, var(--l-gray-300));
  color: #fff;
  font-size: 9.5px; font-weight: 600;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; cursor: pointer; letter-spacing: .02em;
}
button.l-avatar:hover { box-shadow: 0 0 0 2px var(--l-accent-soft); }
.l-ttag {
  font-size: 10.5px; font-weight: 600;
  /* текст — тон тега, притянутый к цвету текста темы: сохраняет оттенок, но читаем
     (иначе светлые теги вроде #F59E0B/#22C55E давали контраст ~2:1) */
  color: color-mix(in srgb, var(--tag-c, var(--l-text-2)) 55%, var(--l-text));
  background: color-mix(in srgb, var(--tag-c, var(--l-gray-400)) 14%, transparent);
  padding: 1px 8px; border-radius: var(--l-r-full);
  white-space: nowrap;
}
.l-ttags-cell { background: none; border: 0; padding: 0; cursor: pointer; display: inline-flex; gap: 4px; flex-wrap: wrap; font: inherit; color: var(--l-text-2); font-size: 12.5px; }
.l-ttags-cell.is-empty { color: var(--l-text-3); }

/* доска */
.l-board {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  overflow-x: auto;
  padding-bottom: 12px;
  scrollbar-color: var(--l-scroll-hover) var(--l-scroll-track);
}
.l-board::-webkit-scrollbar { height: 12px; }
.l-board::-webkit-scrollbar-track {
  margin-inline: 4px;
  border-radius: var(--l-r-full);
  background: var(--l-scroll-track);
}
.l-board::-webkit-scrollbar-thumb {
  border-width: 3px;
  background: var(--l-scroll-hover);
  background-clip: padding-box;
}
.l-board-col { flex: 1 1 260px; min-width: 240px; max-width: 340px; }
.l-board-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; margin-bottom: 8px; padding: 0 2px; }
.l-board-body {
  display: flex; flex-direction: column; gap: 8px;
  min-height: 60px;
  background: var(--l-gray-100);
  border-radius: var(--l-r-lg);
  padding: 8px;
}
.l-board-col.is-empty .l-board-body {
  min-height: 118px;
  background: color-mix(in srgb, var(--l-gray-100) 58%, transparent);
  border: 1px dashed var(--l-border);
}
.l-board-col.is-empty .l-inline-add { min-height: 100%; flex: 1; display: flex; }
.l-board-col.is-empty .l-inline-add-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.l-tcard {
  background: var(--l-surface);
  background-clip: padding-box;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  overflow: hidden;
  padding: 10px 12px;
  cursor: grab;
  box-shadow: 0 1px 2px rgba(16, 20, 24, .04);
}
.l-tcard:hover { border-color: var(--l-gray-300); }
.l-tcard-top { display: flex; align-items: flex-start; gap: 8px; }
.l-tcard-title { font-size: 13px; line-height: 1.35; cursor: pointer; min-width: 0; }
.l-tcard-title:hover { color: var(--l-accent-ink); }
.l-tcard-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 7px; }
.l-tcard-foot { display: flex; align-items: center; gap: 7px; margin-top: 8px; }
.l-tcard-project { max-width: 90px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.l-tcard-projrow {
  margin-top: 7px;
  font-size: 11.5px;
  color: var(--l-text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-tmeta { white-space: nowrap; }
.is-dragging { opacity: .35; }
.l-task-drag-placeholder {
  min-height: 48px;
  border: 1px dashed color-mix(in srgb, var(--l-accent) 52%, var(--l-border));
  border-radius: var(--l-r-md);
  background: color-mix(in srgb, var(--l-accent) 7%, transparent);
}
.l-task-touch-ghost {
  position: fixed !important;
  z-index: calc(var(--l-z-modal) + 4) !important;
  margin: 0 !important;
  opacity: .96 !important;
  pointer-events: none !important;
  overflow: hidden !important;
  border-radius: var(--l-r-md) !important;
  box-shadow: 0 18px 44px rgba(8, 12, 16, .28), 0 0 0 1px color-mix(in srgb, var(--l-accent) 28%, var(--l-border));
  transform: scale(1.035) rotate(.45deg);
  transform-origin: center;
  transition: transform 120ms ease;
}
body.is-task-touch-dragging,
body.is-task-touch-dragging * {
  cursor: grabbing !important;
  -webkit-user-select: none !important;
  user-select: none !important;
}
/* Пока карточку несут пальцем, привязка прокрутки выключена: snap синхронно
   возвращал программный scrollLeft автопрокрутки доски к ближайшей колонке,
   и до соседнего этапа было не дотащить. После отпускания snap возвращается. */
body.is-task-touch-dragging .l-board { scroll-snap-type: none; }
[data-dnd-zone].is-touch-dropover {
  outline: 2px solid var(--l-accent);
  outline-offset: -2px;
  background: color-mix(in srgb, var(--l-accent) 8%, var(--l-gray-100));
}
.l-task-drag-ghost {
  position: fixed !important;
  left: -10000px !important;
  top: -10000px !important;
  margin: 0 !important;
  opacity: 1 !important;
  pointer-events: none !important;
  overflow: hidden !important;
  border-radius: var(--l-r-md) !important;
  clip-path: inset(0 round var(--l-r-md));
  -webkit-clip-path: inset(0 round var(--l-r-md));
  -webkit-mask-image: -webkit-radial-gradient(white, black);
  contain: paint;
}

/* inline-добавление */
.l-inline-add-btn {
  background: none; border: 0; cursor: pointer;
  color: var(--l-text-3); font-size: 12.5px; font-family: var(--l-font);
  padding: 6px 12px; text-align: left; width: 100%; border-radius: var(--l-r-md);
}
.l-inline-add-btn:hover { color: var(--l-accent-ink); background: var(--l-gray-100); }
.l-inline-add-input {
  width: 100%;
  border: 1.5px solid var(--l-accent);
  border-radius: var(--l-r-md);
  padding: 8px 12px;
  font: inherit;
  font-size: 13px;
  background: var(--l-surface);
  color: var(--l-text);
  outline: none;
}
.l-inline-add-input:focus, .l-inline-add-input:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--l-accent-soft);
}

/* таблица задач */
.l-ttable .l-trow-title { white-space: normal; }
.l-ttable th.is-sorted a { color: var(--l-text); }
.l-tstatus { --dot-c: var(--l-gray-400); }
.l-tstatus::before { background: var(--dot-c) !important; box-shadow: none !important; }
.l-ttable tr.is-done td { opacity: .65; }

/* поповер: пункт с цветной точкой */
.l-pop-item--dot { position: relative; padding-left: 28px !important; }
.l-pop-item--dot::before {
  content: ''; position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--dot-c, var(--l-gray-400));
}
.l-pop-item--muted { color: var(--l-text-3); }

/* drawer-карточка */
.l-drawer {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: min(580px, 92vw);
  background: var(--l-surface);
  border-left: 1px solid var(--l-border);
  box-shadow: -18px 0 40px rgba(16, 20, 24, .12);
  z-index: calc(var(--l-z-pop) + 10);
  transform: translateX(102%);
  transition: transform .18s ease;
  overflow-y: auto;
  padding: 20px 24px;
}
.l-drawer.is-open { transform: translateX(0); }
.l-drawer:focus { outline: none; }
/* Пока открыта выдвижная панель (карточка задачи или раздел настроек), страница
   под ней не прокручивается: палец у полосы подложки уводил список за панелью,
   и после закрытия экран оказывался в другом месте.
   Одного overflow: hidden мало — у нас html и body высотой 100%, и скрытие
   переполнения обнуляет прокрутку: фон прыгал к началу списка. Поэтому body
   фиксируется со сдвигом на текущую позицию (её проставляет L.lockPageScroll
   в ledger.js), а после закрытия страница возвращается ровно на место.
   stable-жёлоб держит ширину: без него исчезнувшая полоса прокрутки дёргала
   содержимое вбок на десктопе. */
html.l-scroll-locked { scrollbar-gutter: stable; }
html.l-scroll-locked body {
  position: fixed;
  left: 0;
  right: 0;
  width: 100%;
  overflow: hidden;
}
.l-drawer-backdrop {
  position: fixed; inset: 0;
  background: rgba(16, 20, 24, .28);
  z-index: calc(var(--l-z-pop) + 9);
}
.l-drawer-backdrop[hidden] { display: none; }

/* карточка задачи (drawer и страница) */
.l-tcardfull-head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.l-tcardfull-head .l-done-check { width: 20px; height: 20px; }
.l-tcardfull-head .l-done-check.is-on::after { left: 5.5px; top: 2.5px; width: 5px; height: 9px; }
.l-tcardfull-title { font-size: 17px; font-weight: 600; margin: 0; cursor: text; min-width: 0; flex: 1; }
.l-tcardfull-title:hover { background: var(--l-gray-100); border-radius: var(--l-r-sm); }
.l-tcardfull-meta { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 18px; }
.l-tmetarow { display: flex; align-items: center; gap: 10px; min-height: 28px; }
.l-tmetarow .k { display: inline-flex; align-items: center; gap: 6px; color: var(--l-text-3); font-size: 12px; width: 84px; flex: 0 0 auto; }
/* Значок подписи — резерв для узкого экрана: на широком место под слово есть,
   и дублировать смысл картинкой незачем. */
.l-tmetarow .k > svg { display: none; flex: 0 0 auto; }
/* значения начинаются с одного x: компенсируем левые паддинги пилюль */
.l-tmetarow .l-status { margin-left: -12px; }
.l-tmetarow .l-prio { margin-left: -2px; }
.l-tmetarow .l-tdue { margin-left: -4px; }
/* Пустые значения меты выглядят одинаково: «Назначить», «Указать», «Добавить»
   и пустой срок — приглушённая подсказка, а не акцентная ссылка. Раньше часть
   из них была изумрудной и читалась как заполненное поле. */
.l-tmetarow .l-cta.is-empty,
.l-tmetarow .l-ttags-cell.is-empty {
  color: var(--l-text-3);
  font-weight: 400;
}
.l-tmetarow .l-cta.is-empty:hover,
.l-tmetarow .l-ttags-cell.is-empty:hover { color: var(--l-accent-ink); }
.l-tmetarow .l-tdue.is-empty { opacity: 1; color: var(--l-text-3); font-weight: 400; }
.l-tmetarow .l-tdue.is-empty:hover { color: var(--l-accent-ink); }
.l-tcardfull-desc { width: 100%; min-height: 92px; margin-top: 4px; resize: vertical; }
.l-checklist { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; }
.l-checkitem { display: flex; align-items: center; gap: 9px; padding: 4px 6px; border-radius: var(--l-r-sm); font-size: 13.5px; }
.l-checkitem:hover { background: var(--l-gray-100); }
.l-checkitem.is-done span { text-decoration: line-through; color: var(--l-text-3); }
.l-check-toggle {
  appearance: none;
  -webkit-appearance: none;
  display: inline-grid;
  place-content: center;
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin: 0;
  border: 1.5px solid var(--l-gray-400);
  border-radius: 5px;
  background: var(--l-surface);
  color: var(--l-on-accent);
  cursor: pointer;
  transition: border-color 100ms ease, background 100ms ease, box-shadow 100ms ease, transform 100ms ease;
}
.l-check-toggle::before {
  content: '';
  width: 4px;
  height: 8px;
  border: solid currentColor;
  border-width: 0 2px 2px 0;
  transform: translateY(-1px) rotate(45deg) scale(0);
  transition: transform 90ms ease;
}
.l-check-toggle:hover { border-color: var(--l-accent); }
.l-check-toggle:active { transform: scale(.94); }
.l-check-toggle:checked {
  border-color: var(--l-accent);
  background: var(--l-accent);
}
.l-check-toggle:checked::before { transform: translateY(-1px) rotate(45deg) scale(1); }
.l-check-toggle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--l-accent) 18%, transparent);
}
.l-checkitem-del { opacity: 0; margin-left: auto; }
.l-checkitem:hover .l-checkitem-del { opacity: .7; }
.l-checklist-add { margin-top: 6px; }
.l-checklist-add.is-saving { opacity: .65; }
.l-comment { display: flex; gap: 10px; margin-top: 12px; }
.l-comment-body { min-width: 0; flex: 1; }
.l-comment-head { display: flex; align-items: center; gap: 8px; min-height: 28px; font-size: 12.5px; }
/* Правка и удаление живут при курсоре: постоянные значки шумели бы в ленте.
   Сенсорный экран hover не знает — там их показывает мобильный блок. */
/* Между «Изменить» и «Удалить» заметный зазор: значки стояли вплотную, и
   палец легко попадал в удаление вместо правки. */
.l-comment-tools { display: inline-flex; gap: 8px; margin-left: auto; opacity: 0; transition: opacity 120ms ease; }
.l-comment:hover .l-comment-tools,
.l-comment:focus-within .l-comment-tools { opacity: 1; }
.l-comment-tools .l-comment-tool { width: 28px; height: 28px; }
.l-comment-text { font-size: 13.5px; white-space: pre-wrap; margin-top: 2px; }
.l-comment-edit { display: flex; gap: 8px; align-items: flex-end; margin-top: 4px; }
.l-comment-edit textarea { flex: 1; min-height: 60px; resize: vertical; }
.l-comment-edit-tools { display: inline-flex; flex-direction: column; gap: 4px; }
.l-comment-form { display: flex; gap: 8px; align-items: flex-end; margin-top: 12px; }
.l-comment-form textarea { flex: 1; min-height: 40px; resize: vertical; }
/* Круглая кнопка отправки «как в мессенджере»: одна на форму, поэтому
   акцентная заливка не спорит с главным действием экрана. */
.l-send {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--l-accent);
  color: var(--l-on-accent);
  cursor: pointer;
  transition: opacity 120ms ease, transform 90ms ease, background 120ms ease;
}
.l-send:hover:not(:disabled) { background: var(--l-accent-ink); }
.l-send:active:not(:disabled) { transform: scale(.94); }
.l-send:disabled { opacity: .38; cursor: default; }
.l-send--sm { width: 32px; height: 32px; }
.l-send--ghost {
  background: transparent;
  color: var(--l-text-3);
}
.l-send--ghost:hover:not(:disabled) { background: var(--l-gray-100); color: var(--l-text); }
.l-tcardfull-foot { display: flex; align-items: center; gap: 10px; margin-top: 22px; padding-top: 14px; border-top: 1px solid var(--l-border); }
.l-tcardpage { max-width: 720px; }
/* Отдельная страница задачи: ссылка «открыть отдельной страницей» вела бы сама
   на себя, а «✕» уводило в сохранённый вид задач (часто — в календарь, откуда
   пользователь не приходил). Возврат здесь один и предсказуемый — стрелка «‹»
   в шапке страницы, она знает адрес, с которого карточку открыли. */
.l-tcardpage [data-card-permalink],
.l-tcardpage [data-drawer-close] { display: none; }

/* скромная ссылка на корзину внизу реестра документов */
.ledger a.l-trash-link {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--l-text-3);
}
.ledger a.l-trash-link:hover { color: var(--l-text-2); }

/* свотчи цвета в модалках настроек */
.l-swatches { display: flex; gap: 8px; flex-wrap: wrap; }
.l-swatch { width: 26px; height: 26px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; padding: 0; }
.l-swatch.is-active { border-color: var(--l-text); }

/* Облик поиска задач описан вместе с поиском заметок — см. .l-notes-search.
   Здесь остаётся только то, что относится к самому разделу. */
.l-tasks-search[aria-busy="true"] { opacity: .68; }
.l-task-view-nav > * {
  min-width: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.l-task-view-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.l-task-view-label {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* статичные бейджи для карточек */
.l-badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
  padding: 3px 11px;
  border-radius: var(--l-r-full);
  font-size: 12.5px;
  font-weight: 500;
  background: var(--l-gray-150);
  color: var(--l-text-2);
}
.l-badge::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: var(--l-gray-300); }
.l-badge--paid::before, .l-badge--signed::before { background: var(--l-accent); }
.l-badge--paid, .l-badge--signed { background: var(--l-accent-soft); color: var(--l-accent-ink); }
.l-badge--partial::before { background: var(--l-warn); }
.l-badge--partial { background: var(--l-warn-soft); color: var(--l-warn); }
.l-badge--attn::before { background: transparent; box-shadow: inset 0 0 0 1.5px var(--l-warn); }
.l-badge--attn { background: var(--l-warn-soft); color: var(--l-warn); }
/* «Просрочен» стоял в блоке .l-status выше по файлу — то есть до самой .l-badge,
   и базовое серое перекрывало красное. Модификатор живёт рядом со своими. */
.l-badge--overdue::before { background: var(--l-danger); }
.l-badge--overdue { background: var(--l-danger-soft); color: var(--l-danger); }
.l-badge--muted { opacity: .8; }
.l-badge--plain::before { display: none; }

/* ============================================================================
   Формы
   ========================================================================== */
.ledger .l-label {
  display: block;
  margin: 14px 0 5px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--l-text-3);
}
.ledger .l-input,
.ledger textarea.l-input {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface);
  font: inherit;
  font-size: 13.5px;
  color: var(--l-text);
  transition: border-color 120ms ease;
}
.ledger .l-input:hover { border-color: var(--l-gray-300); }
.ledger .l-input:focus { outline: none; border-color: var(--l-accent); box-shadow: 0 0 0 3px var(--l-accent-soft); }
.ledger .l-input.l-mono { font-family: var(--l-mono); }
.l-input-suffix { position: relative; }
.l-input-suffix .l-input { padding-right: 38px; }
.l-input-suffix > span {
  position: absolute;
  top: 50%;
  right: 13px;
  transform: translateY(-50%);
  color: var(--l-text-3);
  font: 500 12.5px/1 var(--l-mono);
  pointer-events: none;
}
.l-field-help {
  margin-top: 5px;
  color: var(--l-text-3);
  font-size: 11.5px;
  line-height: 1.35;
}
.ledger textarea.l-input { min-height: 64px; resize: vertical; }
.ledger select.l-input {
  appearance: none;
  -webkit-appearance: none;
  background: var(--l-surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238A9096' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat right 12px center;
  padding-right: 32px;
  cursor: pointer;
}

/* Единый календарь выбора даты */
.l-date {
  position: relative;
  display: inline-block;
  width: 100%;
  min-width: 0;
}
.ledger input.l-date-native {
  position: absolute !important;
  inset: auto auto 0 0;
  width: 1px !important;
  height: 1px !important;
  margin: 0 !important;
  padding: 0 !important;
  border: 0 !important;
  opacity: 0;
  pointer-events: none;
}
.ledger .l-date-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-width: 150px;
  min-height: 39px;
  text-align: left;
  cursor: pointer;
}
.ledger .l-date-btn.is-empty { color: var(--l-text-3); }
.ledger .l-date-btn:hover { border-color: var(--l-gray-300); }
.ledger .l-date-btn:focus-visible,
.ledger .l-date-btn.is-open {
  outline: none;
  border-color: var(--l-accent);
  box-shadow: 0 0 0 3px var(--l-accent-soft);
}
.l-date-btn .l-date-value {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-date-btn svg { flex: 0 0 auto; color: var(--l-text-3); pointer-events: none; }
.l-date-pop {
  position: fixed;
  z-index: calc(var(--l-z-pop) + 140);
  width: min(304px, calc(100vw - 16px));
  /* Календарь с сеткой дней и подвалом «Сегодня/Очистить» выше 400px: в
     лендскейпе он не помещался целиком, а placePanel() не умел прижимать его к
     низу окна. Клампа по высоте достаточно, чтобы подвал остался доступен. */
  max-height: calc(100dvh - 16px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 10px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  background: var(--l-surface);
  box-shadow: var(--l-shadow-pop);
  color: var(--l-text);
  font-family: var(--l-font);
}
.l-date-pop[hidden] { display: none; }
.l-date-head {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) 34px;
  align-items: center;
  gap: 5px;
  margin-bottom: 8px;
}
.l-date-title {
  min-width: 0;
  text-align: center;
  font-size: 13.5px;
  font-weight: 650;
  letter-spacing: -.01em;
}
.l-date-nav {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: var(--l-r-md);
  background: transparent;
  color: var(--l-text-2);
}
.l-date-nav:hover,
.l-date-nav:focus-visible {
  outline: none;
  background: var(--l-gray-150);
  color: var(--l-text);
}
.l-date-weekdays,
.l-date-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 2px;
}
.l-date-weekdays { margin-bottom: 3px; }
.l-date-weekdays span {
  padding: 4px 0;
  color: var(--l-text-3);
  text-align: center;
  font-size: 10px;
  font-weight: 650;
  text-transform: uppercase;
}
.l-date-day {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  min-width: 0;
  padding: 0;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--l-text);
  font: 500 12.5px/1 var(--l-mono);
  font-variant-numeric: tabular-nums;
}
.l-date-day:hover:not(:disabled),
.l-date-day:focus-visible:not(:disabled) {
  outline: none;
  background: var(--l-gray-150);
  color: var(--l-text);
}
.l-date-day.is-outside { color: var(--l-text-3); opacity: .52; }
.l-date-day.is-today:not(.is-selected) {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--l-accent) 55%, transparent);
  color: var(--l-accent-ink);
}
.l-date-day.is-selected,
.l-date-day.is-selected:hover,
.l-date-day.is-selected:focus-visible {
  background: var(--l-accent);
  color: var(--l-on-accent);
  box-shadow: 0 4px 12px color-mix(in srgb, var(--l-accent) 28%, transparent);
}
.l-date-day:disabled { opacity: .24; cursor: not-allowed; }
.l-date-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 9px;
  padding-top: 9px;
  border-top: 1px solid var(--l-hairline);
}
.l-date-action {
  padding: 6px 8px;
  border: 0;
  border-radius: var(--l-r-sm);
  background: transparent;
  color: var(--l-accent-ink);
  font: 600 11.5px/1.2 var(--l-font);
}
.l-date-action.is-muted { color: var(--l-text-3); }
.l-date-action:hover:not(:disabled),
.l-date-action:focus-visible:not(:disabled) {
  outline: none;
  background: var(--l-accent-soft);
}
.l-date-action:disabled { opacity: .35; cursor: default; }
/* Вертикальный ритм задаёт row-gap самой сетки, а не отступ метки: когда сетка
   схлопывается в одну колонку на телефоне, метки с margin-top:0 прилипали к
   полю строкой выше (row-gap был 0). */
.l-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 18px; }
.l-grid3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px 18px; }
/* grid-ячейки по умолчанию min-width:auto — длинный select/дропдаун распирал бы сетку */
.l-grid2 > div, .l-grid3 > div { min-width: 0; }
/* Метка первым элементом ячейки не добавляет свой верхний отступ поверх
   row-gap — инлайновые style="margin-top:0" в шаблонах больше не нужны. */
.l-grid2 > div > .l-label:first-child,
.l-grid3 > div > .l-label:first-child { margin-top: 0; }
/* Row-gap здесь обязателен: на мобильном сетка складывается в одну колонку,
   и «gap: 0 14px» оставлял поля лимитов слипшимися вплотную. */
.l-tax-limit-grid { gap: 14px; }
@media (max-width: 760px) {
  .l-tax-limit-grid { grid-template-columns: 1fr; }
}
.l-org-contact-grid { grid-template-columns: minmax(160px,.85fr) minmax(220px,1.15fr) minmax(180px,1fr); }
/* Статусы файлов организации («Лого — загружено», «Печать — не загружена»):
   плашки с воздухом и переносом, а не слипшиеся строки в мобильной карточке. */
td.l-org-files { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.l-org-files .l-badge.is-missing { color: var(--l-text-3); }
@media (max-width: 720px) {
  .l-org-contact-grid { grid-template-columns: 1fr 1fr; }
  .l-org-contact-grid .l-org-contact-website { grid-column: 1 / -1; }
  /* «Печать — не загружена» шире половины карточки, а бейдж не переносится по
     словам — плашки вылезали за правый край. Отдаём статусам всю ширину. */
  .l-mobile-cards tbody td.l-org-files { grid-column: 1 / -1; }
  .l-org-files .l-badge { max-width: 100%; white-space: normal; }
}
@media (max-width: 520px) {
  .l-org-contact-grid { grid-template-columns: 1fr; }
  .l-org-contact-grid .l-org-contact-website { grid-column: auto; }
}

/* ============================================================================
   Управляющий контур top2b
   Отдельная оболочка admin.top2b.ru использует те же токены и примитивы
   Ledger, но не подключает клиентскую навигацию и service worker.
   ========================================================================== */
.l-admin-body { min-width: 320px; min-height: 100%; overflow-x: hidden; }
.l-admin-shell {
  display: grid;
  grid-template-columns: 236px minmax(0, 1fr);
  min-height: 100dvh;
}
.l-admin-nav {
  position: sticky;
  top: 0;
  display: flex;
  flex-direction: column;
  gap: 20px;
  height: 100dvh;
  padding: 22px 16px;
  overflow-y: auto;
  color: var(--l-sidebar-text);
  background: var(--l-sidebar-bg);
  border-right: 1px solid var(--l-sidebar-border);
}
.l-admin-brand { display: grid; gap: 2px; padding: 0 8px; color: var(--l-text); }
.l-admin-brand img { width: 105px; height: auto; }
.l-admin-brand span { color: var(--l-text-3); font-size: 11px; letter-spacing: .08em; text-transform: uppercase; }
.l-admin-nav nav { display: grid; gap: 3px; }
.l-admin-nav-item {
  min-height: 40px;
  padding: 10px 12px;
  border-radius: var(--l-r-md);
  color: var(--l-sidebar-text) !important;
}
.l-admin-nav-item:hover { background: var(--l-sidebar-hover); }
.l-admin-nav-item.is-active { color: var(--l-sidebar-active-tx) !important; background: var(--l-sidebar-active-bg); font-weight: 600; }
.l-admin-person { display: grid; gap: 4px; margin-top: auto; padding: 12px 8px 0; border-top: 1px solid var(--l-sidebar-border); }
.l-admin-person span { color: var(--l-text-3); font-size: 12px; }
.l-admin-person form { margin-top: 6px; }
.l-admin-main {
  width: 100%;
  min-width: 0;
  max-width: 1560px;
  margin: 0 auto;
  padding: 28px clamp(22px, 3.5vw, 52px) 56px;
}
.l-admin-global-search { width: min(100%, 420px); margin: 0 0 18px auto; }
.l-admin-mobile-head { display: none; }
.l-admin-readonly,
.l-staff-access-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
  padding: 12px 16px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  background: var(--l-warn-soft);
  color: var(--l-warn);
}
.l-admin-readonly { min-height: 44px; font-size: 13px; }
.l-admin-readonly-mode .l-admin-main form[method="post"] { pointer-events: none; opacity: .62; }
.l-staff-access-banner { position: sticky; top: 10px; z-index: var(--l-z-pop); box-shadow: var(--l-shadow-pop); }
.l-staff-access-banner > div { display: grid; gap: 2px; }
.l-staff-access-banner span { font-size: 12px; }
.l-admin-auth { display: grid; place-items: center; min-height: 100dvh; padding: 20px; }
.l-admin-auth-card { width: min(100%, 430px); }
.l-admin-login-panel {
  display: grid;
  gap: 0;
  width: min(100%, 400px);
  padding: clamp(22px, 5vw, 32px);
}
.l-admin-login-logo {
  display: block;
  width: 108px;
  max-width: 42%;
  height: auto;
  margin: 0 0 22px;
}
.l-admin-login-panel > .l-title {
  margin: 0 0 20px;
  font-size: clamp(22px, 5vw, 26px);
  line-height: 1.16;
}
.l-admin-login-panel > .l-notice,
.l-admin-login-panel > .l-banner { margin: 0 0 18px; }
.l-admin-login-form { display: grid; gap: 8px; }
.l-admin-login-form .l-label { margin: 8px 0 0; }
.l-admin-login-form .l-label:first-of-type { margin-top: 0; }
.l-admin-login-form .l-input { width: 100%; min-width: 0; }
.l-admin-login-form .l-btn {
  justify-self: start;
  min-height: 44px;
  margin-top: 10px;
}
.l-admin-totp-qr {
  display: grid;
  place-items: center;
  width: min(100%, 276px);
  margin: 4px auto 18px;
  padding: 10px;
  overflow: hidden;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  background: var(--l-surface);
}
.l-admin-totp-qr img { display: block; width: 100%; height: auto; image-rendering: pixelated; }
.l-admin-totp-manual { margin: 0 0 18px; }
.l-admin-totp-manual summary { color: var(--l-text-2); font-size: 13px; cursor: pointer; }
.l-admin-totp-manual[open] summary { margin-bottom: 10px; }
.l-admin-secret {
  padding: 10px 12px;
  overflow-wrap: anywhere;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface-hover);
  font-size: 13px;
  letter-spacing: .04em;
}
.l-admin-recovery {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin: 4px 0 2px;
  padding: 0;
  list-style: none;
  counter-reset: recovery-code;
}
.l-admin-recovery li {
  display: flex;
  align-items: center;
  min-width: 0;
  padding: 10px 12px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface-hover);
  counter-increment: recovery-code;
}
.l-admin-recovery li::before {
  content: counter(recovery-code);
  flex: 0 0 20px;
  color: var(--l-text-3);
  font-size: 11px;
}
.l-admin-recovery code {
  min-width: 0;
  color: var(--l-text);
  font-size: 13px;
  letter-spacing: .035em;
  white-space: nowrap;
}
.l-admin-recovery-actions { flex-wrap: wrap; }
.l-admin-copy-state {
  min-height: 18px;
  margin: 8px 0 0;
  color: var(--l-text-2);
  font-size: 12px;
}
.l-admin-auth-brand { display: grid; justify-items: center; gap: 8px; margin-bottom: 22px; }
.l-admin-auth-brand img { width: 120px; }
.l-admin-auth-brand span { color: var(--l-text-3); }
.l-admin-main > .l-pagehead {
  justify-content: space-between;
  align-items: flex-end;
  gap: 24px;
}
.l-admin-main > .l-pagehead > div { min-width: 0; }
.l-admin-main .l-page-sub {
  max-width: 760px;
  margin: 5px 0 0;
  color: var(--l-text-2);
  font-size: 13.5px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.l-admin-kpis { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-bottom: 18px; }
.l-admin-kpis--small { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); margin: 0; }
.l-admin-kpi,
.l-admin-kpis--small > article { display: grid; gap: 6px; min-width: 0; padding: 18px; }
.l-admin-kpi > span,
.l-admin-kpis--small span { color: var(--l-text-2); font-size: 12px; }
.l-admin-kpi strong { overflow: hidden; font-size: clamp(21px, 2.5vw, 32px); text-overflow: ellipsis; }
.l-admin-kpi small { color: var(--l-text-3); }
.l-admin-grid2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-bottom: 16px; }
.l-admin-period .l-select { width: 160px; }
.l-admin-filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
  gap: 10px;
  align-items: end;
}
.l-admin-filters > * { min-width: 0; }
.l-admin-filterbar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
}
.l-admin-filterbar .l-btn { min-width: 104px; justify-content: center; }
.l-admin-user-filter { margin-bottom: 14px; }
.l-admin-user-filter > .l-panel { margin-bottom: 10px; }
.l-admin-filter-panel { padding: 0; overflow: hidden; }
.l-admin-filter-panel > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 48px;
  padding: 12px 16px;
  cursor: pointer;
  list-style: none;
}
.l-admin-filter-panel > summary::-webkit-details-marker { display: none; }
.l-admin-filter-panel > summary::after { content: '⌄'; color: var(--l-text-3); font-size: 18px; line-height: 1; }
.l-admin-filter-panel[open] > summary::after { transform: rotate(180deg); }
.l-admin-filter-panel > summary span { font-weight: 600; }
.l-admin-filter-panel > summary small { margin-left: auto; color: var(--l-text-3); }
.l-admin-filter-panel > .l-admin-filters { padding: 0 16px 16px; border-top: 1px solid var(--l-hairline); }
.l-admin-filter-panel > .l-admin-filters > * { margin-top: 12px; }
.l-admin-date-filter { display: grid; gap: 4px; color: var(--l-text-3); font-size: 11px; }
.l-admin-line,
.l-admin-rowlink {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 14px;
  min-height: 48px;
  padding: 10px 0;
  border-bottom: 1px solid var(--l-hairline);
  color: var(--l-text) !important;
}
.l-admin-rowlink > span:first-child { display: grid; min-width: 0; gap: 2px; }
.l-admin-line > span:first-of-type { display: grid; min-width: 0; gap: 3px; }
.l-admin-rowlink small,
.l-admin-line small { color: var(--l-text-3); }
.l-admin-break { overflow-wrap: anywhere; }
.l-admin-cardgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 290px), 1fr));
  gap: 14px;
}
.l-admin-tenant-card {
  display: grid;
  gap: 9px;
  min-width: 0;
  margin: 0;
  color: var(--l-text) !important;
  text-decoration: none;
  transition: border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}
.l-admin-tenant-card:hover {
  border-color: color-mix(in srgb, var(--l-accent) 34%, var(--l-border));
  box-shadow: var(--l-shadow-pop);
  transform: translateY(-1px);
}
.l-admin-tenant-card > .l-panel-title { margin: 0; }
.l-admin-tenant-card > strong { min-width: 0; font-size: 17px; line-height: 1.3; overflow-wrap: anywhere; }
.l-admin-tenant-card > small { display: block; color: var(--l-text-2); line-height: 1.45; overflow-wrap: anywhere; }
.l-admin-tenant-card > div { display: flex; flex-wrap: wrap; align-items: center; gap: 7px 10px; min-width: 0; }
.l-admin-tenant-card > .l-admin-card-head { justify-content: space-between; }
.l-admin-card-eyebrow { color: var(--l-text-3); font-size: 10.5px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.l-admin-card-meta { display: grid !important; gap: 3px !important; }
.l-admin-card-meta > span { color: var(--l-text-2); font-size: 12.5px; }
.l-admin-card-metrics {
  display: grid !important;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px !important;
  padding-top: 3px;
}
.l-admin-card-metrics > span {
  display: grid;
  gap: 2px;
  min-width: 0;
  padding: 8px;
  border-radius: var(--l-r-md);
  background: var(--l-surface-hover);
  color: var(--l-text-3);
  font-size: 10px;
}
.l-admin-card-metrics strong { color: var(--l-text); font-size: 14px; }
.l-admin-card-metrics .l-mono { overflow-wrap: anywhere; }
.l-admin-cell-note {
  display: block;
  max-width: 280px;
  margin-top: 4px;
  color: var(--l-text-3);
  font-family: var(--l-font);
  font-size: 11.5px;
  font-weight: 400;
  line-height: 1.4;
  white-space: normal;
  overflow-wrap: anywhere;
}
.l-admin-user-link { display: inline-block; max-width: 260px; overflow-wrap: anywhere; }
.l-admin-profile-progress {
  display: block;
  width: min(100%, 128px);
  height: 5px;
  margin-top: 6px;
  overflow: hidden;
  border: 0;
  border-radius: var(--l-r-full);
  background: var(--l-gray-150);
}
.l-admin-profile-progress::-webkit-progress-bar { background: var(--l-gray-150); }
.l-admin-profile-progress::-webkit-progress-value { background: var(--l-accent); }
.l-admin-profile-progress::-moz-progress-bar { background: var(--l-accent); }
.l-admin-table-wrap { max-width: 100%; padding: 0; overflow-x: auto; }
.l-admin-table-wrap > .l-panel-title { margin: 0; padding: 18px 20px 4px; }
.l-admin-table-wrap > .l-account-copy { padding: 0 20px 18px; }
.l-admin-table-wrap .l-table { min-width: 760px; }
.l-admin-table-wrap .l-table th,
.l-admin-table-wrap .l-table td { padding: 13px 14px; vertical-align: top; }
.l-admin-table-wrap .l-table tbody tr { cursor: default; }
.l-admin-table-wrap .l-table td.l-mono { white-space: nowrap; }
.l-admin-table { width: 100%; border-collapse: collapse; }
.l-admin-table th,
.l-admin-table td { padding: 11px 12px; border-bottom: 1px solid var(--l-hairline); text-align: left; vertical-align: top; }
.l-admin-table th { color: var(--l-text-3); font-size: 11px; letter-spacing: .04em; text-transform: uppercase; }
.l-admin-pages { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 14px; }
.l-admin-pages .l-btn { min-width: 40px; justify-content: center; }
.l-admin-pages .l-btn.is-active { border-color: var(--l-accent); background: var(--l-accent-soft); color: var(--l-accent-ink); }
.l-admin-thread { display: grid; gap: 12px; max-width: 860px; }
.l-admin-message { max-width: min(84%, 680px); padding: 12px 14px; border: 1px solid var(--l-border); border-radius: var(--l-r-lg); background: var(--l-surface-hover); }
.l-admin-message.is-admin { justify-self: end; background: var(--l-accent-soft); border-color: transparent; }
.l-admin-message header { display: flex; justify-content: space-between; gap: 12px; color: var(--l-text-2); font-size: 12px; }
.l-admin-message p { margin: 7px 0 0; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
.l-admin-editor { width: 100%; min-height: 360px; resize: vertical; font-family: var(--l-mono); line-height: 1.55; }
.l-admin-stat-list { display: grid; }
.l-admin-stat-list > .l-admin-line:last-child { border-bottom: 0; }
.l-admin-empty { padding: 28px 0; color: var(--l-text-3); text-align: center; }
.l-admin-staff-row { grid-template-columns: minmax(0, 1fr) auto; }
.l-admin-staff-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  min-width: 0;
}
.l-admin-staff-controls .l-select { width: auto; min-width: 128px; }
.l-support-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.l-support-thread { display: grid; gap: 12px; max-width: 820px; }
.l-support-message { max-width: min(82%, 640px); padding: 12px 14px; border: 1px solid var(--l-border); border-radius: var(--l-r-lg); background: var(--l-surface); }
.l-support-message.is-client { justify-self: end; background: var(--l-accent-soft); border-color: var(--l-accent-soft); }
.l-support-message header { display: flex; justify-content: space-between; gap: 12px; color: var(--l-text-2); font-size: 12px; }
.l-support-message p { margin: 6px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.l-support-attachments { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.l-support-attachments > strong { flex-basis: 100%; }
.l-public-cms { min-height: 100%; background: var(--l-surface); }
.l-public-head { display: flex; align-items: center; justify-content: space-between; gap: 24px; min-height: 72px; padding: 12px clamp(18px, 5vw, 72px); border-bottom: 1px solid var(--l-border); }
.l-public-head img { display: block; width: 112px; }
.l-public-head nav { display: flex; align-items: center; gap: 22px; }
.l-public-article { width: min(100% - 32px, 900px); margin: 0 auto; padding: clamp(36px, 7vw, 84px) 0 80px; }
.l-public-article article { width: min(100%, 760px); }
.l-public-article h1 { margin: 0 0 18px; font-size: clamp(32px, 6vw, 58px); line-height: 1.08; letter-spacing: -.035em; }
.l-public-kind { margin: 0 0 12px; color: var(--l-accent); font-weight: 600; }
.l-public-lead { margin: 0 0 32px; color: var(--l-text-2); font-size: clamp(17px, 2.5vw, 21px); line-height: 1.5; }
.l-public-prose { font-size: 17px; line-height: 1.7; overflow-wrap: anywhere; }
.l-public-prose img { max-width: 100%; height: auto; }
.l-public-prose table { display: block; max-width: 100%; overflow-x: auto; border-collapse: collapse; }
.l-public-list { display: grid; gap: 12px; }
.l-public-list .l-panel { display: grid; gap: 5px; color: var(--l-text); }
.l-public-list .l-panel span { color: var(--l-text-2); }

@media (max-width: 900px) {
  .l-admin-shell { grid-template-columns: 1fr; }
  .l-admin-nav { position: static; width: auto; height: auto; padding: 12px; border: 0; border-bottom: 1px solid var(--l-sidebar-border); }
  .l-admin-brand,
  .l-admin-person { display: none; }
  .l-admin-nav nav { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; }
  .l-admin-nav nav::-webkit-scrollbar { display: none; }
  .l-admin-nav-item { flex: 0 0 auto; }
  .l-admin-main { padding: 18px 14px 40px; }
  .l-admin-mobile-head { display: flex; justify-content: space-between; gap: 12px; margin-bottom: 14px; color: var(--l-text-2); }
  .l-admin-mobile-head > a { flex: 0 0 auto; white-space: nowrap; }
  .l-admin-mobile-head > span { min-width: 0; text-align: right; overflow-wrap: anywhere; }
  .l-admin-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 620px) {
  .l-admin-auth { align-items: start; padding: max(20px, env(safe-area-inset-top)) 14px 24px; }
  .l-admin-login-panel { margin-top: 8vh; padding: 22px 18px; }
  .l-admin-login-logo { width: 96px; margin-bottom: 20px; }
  .l-admin-login-form .l-btn { width: 100%; justify-content: center; }
  .l-admin-totp-qr { width: min(100%, 252px); padding: 8px; }
  .l-admin-grid2 { grid-template-columns: 1fr; }
  .l-admin-main > .l-pagehead { align-items: flex-start; gap: 12px; }
  .l-admin-main > .l-pagehead > form { width: auto; flex: 0 0 auto; }
  .l-admin-main .l-page-sub { font-size: 12.5px; }
  .l-admin-global-search { width: 100%; margin-bottom: 12px; }
  .l-admin-readonly { padding: 10px 12px; line-height: 1.4; }
  .l-admin-filterbar { grid-template-columns: minmax(0, 1fr) 92px; }
  .l-admin-filterbar .l-btn { min-width: 0; }
  .l-admin-filter-panel > summary { align-items: flex-start; }
  .l-admin-filter-panel > summary small { display: block; margin: 2px 0 0; }
  .l-admin-filter-panel > summary::after { margin-left: auto; }
  .l-admin-cardgrid { grid-template-columns: 1fr; }
  .l-admin-tenant-card { padding: 16px 14px; }
  .l-admin-table-wrap { margin-right: 0; margin-left: 0; }
  .l-admin-table-wrap .l-table { min-width: 700px; }
  .l-admin-table-wrap .l-admin-responsive-table {
    display: block;
    width: 100%;
    min-width: 0;
  }
  .l-admin-responsive-table thead { display: none; }
  .l-admin-responsive-table tbody { display: grid; width: 100%; gap: 10px; padding: 10px; }
  .l-admin-responsive-table tr {
    display: grid;
    width: 100%;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px 14px;
    padding: 14px;
    border: 1px solid var(--l-border);
    border-radius: var(--l-r-lg);
    background: var(--l-surface);
  }
  .l-admin-responsive-table td,
  .l-admin-responsive-table tr:first-child td {
    display: block;
    min-width: 0;
    padding: 0;
    border: 0;
    white-space: normal !important;
    overflow-wrap: anywhere;
  }
  .l-admin-responsive-table td::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 4px;
    color: var(--l-text-3);
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
  }
  .l-admin-responsive-table td:first-child { grid-column: 1 / -1; }
  .l-admin-responsive-table .l-admin-cell-note { max-width: none; }
  .l-admin-table-wrap .l-admin-users-table {
    display: block;
    width: 100%;
    min-width: 0;
  }
  .l-admin-users-table thead { display: none; }
  .l-admin-users-table tbody { display: grid; width: 100%; gap: 10px; padding: 10px; }
  .l-admin-users-table tr {
    display: grid;
    width: 100%;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px 14px;
    padding: 14px;
    border: 1px solid var(--l-border);
    border-radius: var(--l-r-lg);
    background: var(--l-surface);
  }
  .l-admin-users-table td,
  .l-admin-users-table tr:first-child td {
    display: block;
    min-width: 0;
    padding: 0;
    border: 0;
    white-space: normal !important;
  }
  .l-admin-users-table td::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 4px;
    color: var(--l-text-3);
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
  }
  .l-admin-users-table td:first-child { grid-column: 1 / -1; }
  .l-admin-users-table .l-admin-cell-note { max-width: none; }
  .l-admin-message { max-width: 94%; }
  .l-support-grid { grid-template-columns: 1fr; }
  .l-support-message { max-width: 92%; }
  .l-admin-kpis { grid-template-columns: 1fr 1fr; gap: 8px; }
  .l-admin-kpi { padding: 14px; }
  .l-admin-kpi strong { font-size: 21px; }
  .l-admin-line,
  .l-admin-rowlink { grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
  .l-admin-line small { grid-column: 1 / -1; }
  .l-admin-staff-row { grid-template-columns: minmax(0, 1fr); }
  .l-admin-staff-row small { grid-column: auto; overflow-wrap: anywhere; }
  .l-admin-staff-controls { justify-content: flex-start; }
  .l-admin-staff-controls .l-select { width: 100%; }
  .l-admin-readonly,
  .l-staff-access-banner { align-items: flex-start; }
  .l-staff-access-banner { top: 6px; }
  .l-public-head { align-items: flex-start; padding: 12px 16px; }
  .l-public-head nav { gap: 10px; flex-wrap: wrap; justify-content: flex-end; font-size: 12px; }
  .l-public-head nav a:not(.l-btn) { display: none; }
}

@media (max-width: 360px) {
  .l-admin-recovery { grid-template-columns: 1fr; }
}
.l-check { display: inline-flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--l-text-2); cursor: pointer; margin-top: 12px; }
.l-check input { width: 15px; height: 15px; }
/* 14px, а не 4: ряд действий — отдельный смысловой блок, и на мобильном
   растянутая кнопка в 4px от подсказки читалась как её продолжение. */
.l-form-actions { display: flex; gap: 10px; margin-top: 14px; }
/* Разделитель внутри панели — тонкая линия с воздухом. Замена инлайновым
   div style="margin-top…border-top…", расползшимся по разделам настроек. */
.l-fieldsep { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--l-border); }
/* Флекс-шапка панели: заголовок слева, статус или действия справа. Заголовок
   внутри шапки не несёт свой нижний отступ — его даёт сама шапка. */
.l-panel-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.l-panel-head .l-panel-title { margin: 0; }
/* Вводный абзац и примечание панели — вместо инлайновых <p style="…">. */
.l-panel-copy { margin: 0 0 12px; color: var(--l-text-2); font-size: 13px; line-height: 1.5; }
.l-panel-note { margin: 10px 0 0; color: var(--l-text-3); font-size: 12.5px; line-height: 1.45; }
/* Строка «поле + слово» («за N минут до срока», «в HH:MM»). */
.l-inline-field { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.l-inline-field .l-label { margin: 0; }
.l-inline-field > span { font-size: 13px; color: var(--l-text-2); }
/* Живой текст-результат рядом с кнопками («Письмо отправлено», ошибки). */
.l-actions-note { align-self: center; font-size: 12.5px; color: var(--l-text-3); }
/* Подчинённые настройки push при выключенном мастер-тумблере: приглушены и
   не редактируются, но НЕ disabled — значения сохраняются при отправке. */
[data-push-dep].is-off { opacity: .45; pointer-events: none; }
/* Превью письма в настройках почты. */
.l-mail-preview { margin-top: 12px; padding: 12px 14px; background: var(--l-surface-hover); border: 1px dashed var(--l-gray-300); border-radius: var(--l-r-md); }
.l-mail-preview-subject { font-weight: 600; font-size: 13px; }
.l-mail-preview-body { margin-top: 4px; font-size: 12.5px; color: var(--l-text-2); white-space: pre-wrap; }
/* Смежные отступы: подсказка и чекбокс не липнут к следующему блоку.
   Сетки нужны отдельно: их первая метка лишена верхнего отступа (правило
   выше), и без этого грид вставал вплотную к предыдущему чекбоксу. */
.l-field-help + .l-check { margin-top: 14px; }
.t2-rows + .l-field-help { margin-top: 10px; }
.l-check + .l-grid2,
.l-check + .l-grid3 { margin-top: 14px; }
.l-kv + .l-notice { margin-top: 14px; }
.l-notice {
  padding: 10px 14px;
  border: 1px solid #E8D5A8;
  background: var(--l-warn-soft);
  color: var(--l-warn);
  border-radius: var(--l-r-md);
  font-size: 13px;
  margin-bottom: 14px;
}
.l-account-email {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 6px;
  color: var(--l-text-3);
  font-size: 12.5px;
}
.l-account-email strong {
  color: var(--l-text);
  font-size: 13.5px;
  font-weight: 500;
}
.l-account-copy {
  margin: 0 0 16px;
  color: var(--l-text-2);
  font-size: 13px;
}
.l-account-form { max-width: 980px; }
/* Профиль: инициалы вместо аватара — фотографий в сервисе нет. */
.l-account-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 18px;
}
.l-account-avatar {
  display: grid;
  width: 52px;
  height: 52px;
  flex: none;
  place-items: center;
  border-radius: 50%;
  color: var(--l-accent-ink);
  background: var(--l-accent-soft);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: .02em;
}
/* Фотография занимает кружок целиком: и крупный кружок профиля, и аватар
   шапки/рельсы, и кружок участника команды. border-radius: inherit — чтобы
   картинка обрезалась ровно по форме контейнера, какой бы она ни была. */
.l-account-avatar img,
.t2-avatar img,
.l-avatar img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
/* Эмодзи вместо фотографии: кегль кружков подобран под инициалы, эмодзи при нём
   выглядит потерянным. Гарнитуру тоже возвращаем системную. */
.l-account-avatar.is-emoji,
.t2-avatar.is-emoji { font-family: inherit; line-height: 1; letter-spacing: normal; }
.l-account-avatar.is-emoji { font-size: 30px; }
.t2-avatar.is-emoji { font-size: 19px; }
.l-account-avatar-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 4px;
}
/* .l-inline-form задаёт display: inline и тем самым перебивает атрибут hidden:
   без этой строки скрытая кнопка «Удалить фото» осталась бы видимой. */
.l-account-avatar-actions [hidden] { display: none; }
.l-account-head-text {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
  color: var(--l-text-3);
  font-size: 12.5px;
}
.l-account-head-text strong {
  color: var(--l-text);
  font-size: 15px;
  font-weight: 600;
}
.l-account-notice {
  max-width: 980px;
  margin-bottom: 14px;
}
.l-account-notice--success {
  border-color: var(--l-accent-soft);
  background: var(--l-accent-soft);
  color: var(--l-accent-ink);
}
.l-account-notice--error {
  border-color: var(--l-danger-soft);
  background: var(--l-danger-soft);
  color: var(--l-danger);
}
@media (max-width: 820px) {
  .l-account-form .l-grid3 { grid-template-columns: 1fr; }
}

/* Кадрирование фотографии профиля (public/avatar-crop.js). Кадрирует и сжимает
   браузер, поэтому весь слой — это квадрат холста, круглая маска поверх него и
   ползунок масштаба. */
.l-modal.l-avatar-modal { max-width: 340px; }
.l-avatar-crop {
  position: relative;
  /* Кадр всегда квадратный, но на узком экране сжимается вместе с модалкой:
     фиксированные 288px вылезали бы за края на 320px-телефонах. Координаты
     жеста считаются от getBoundingClientRect, поэтому размер CSS свободен. */
  width: min(288px, 100%);
  aspect-ratio: 1 / 1;
  margin: 0 auto;
  overflow: hidden;
  border-radius: var(--l-r-lg);
  background: var(--l-bg);
  /* Жест перетаскивания принадлежит кадру, а не странице: без этого браузер
     телефона забирал бы движение себе и прокручивал модалку. */
  touch-action: none;
  cursor: grab;
}
.l-avatar-crop.is-dragging { cursor: grabbing; }
.l-avatar-crop canvas { display: block; width: 100%; height: 100%; }
/* Маска показывает будущий круг аватара: углы гасим полупрозрачным фоном темы,
   а не чёрным — иначе в тёмных темах получалась бы дыра. */
.l-avatar-crop-ring {
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(
    circle at 50% 50%,
    transparent 0,
    transparent calc(50% - 1px),
    color-mix(in srgb, var(--l-bg) 78%, transparent) calc(50% - 1px)
  );
  box-shadow: inset 0 0 0 1px var(--l-border);
}
.l-avatar-crop-ring::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--l-text) 25%, transparent);
}
.l-avatar-zoom {
  display: block;
  width: 100%;
  margin-top: 14px;
  accent-color: var(--l-accent);
}
.l-avatar-modal .l-field-help { text-align: center; }
.l-avatar-modal .l-notice { margin: 12px 0 0; }

/* Логотип кабинета садится в скруглённый квадрат, а не в круг: в шапке меню он
   так и выглядит, и круглая маска обещала бы не тот кадр. Радиус тот же 9px,
   что у .t2-tenant-mark, отмасштабированный под 288px кадра. */
.l-avatar-crop.is-rounded .l-avatar-crop-ring {
  background: none;
  box-shadow: inset 0 0 0 1px var(--l-border);
}
.l-avatar-crop.is-rounded .l-avatar-crop-ring::after {
  border-radius: var(--l-r-lg);
}

/* Английское имя для ссылок: адрес собран прямо в строке ввода, чтобы человек
   видел итог целиком, а не догадывался по подписи. */
.l-linkname-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px;
}
.l-linkname-prefix,
.l-linkname-suffix {
  color: var(--l-text-3);
  font-size: 13px;
  white-space: nowrap;
}
.l-linkname-row .l-input { flex: 1 1 160px; min-width: 0; }
.l-linkname-tips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.l-linkname-tips:empty { display: none; }
/* Подсказка — вариант имени, а не действие: выглядит как то, что подставится
   в поле, поэтому моноширинная и в тон адресу. Без своих правил браузер рисовал
   системную серую кнопку, чужую всему остальному экрану. */
.ledger .l-linkname-tip {
  min-height: 32px;
  padding: 0 12px;
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--l-border);
  border-radius: 999px;
  background: var(--l-surface);
  color: var(--l-text-2);
  font-family: var(--l-mono);
  font-size: 12.5px;
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
}
.ledger .l-linkname-tip:hover {
  border-color: var(--l-accent);
  background: var(--l-accent-soft);
  color: var(--l-accent-ink);
}
.ledger .l-linkname-tip:focus-visible {
  outline: none;
  border-color: var(--l-accent);
  box-shadow: 0 0 0 3px var(--l-accent-soft);
}
/* Занятое имя: адрес уже разошёлся по приглашениям, менять нечего — показываем
   итог строкой, а не полем, которое ничего не примет. */
.l-linkname-fixed {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px;
  padding: 9px 12px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface-hover);
  font-family: var(--l-mono);
  font-size: 13.5px;
  color: var(--l-text);
}
.l-linkname-fixed .l-linkname-prefix,
.l-linkname-fixed .l-linkname-suffix { font-size: 13.5px; }
[data-linkname-status].is-free { color: var(--l-ok, var(--l-accent-ink)); }
[data-linkname-status].is-busy { color: var(--l-danger-ink, var(--l-text-2)); }

/* Метка кабинета: превью и сетка значков. */
.l-badge-preview {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 2px 0 6px;
}
/* Превью крупнее метки в меню: здесь человек выбирает знак и должен его
   разглядеть. Оба класса в селекторе намеренно — правило .t2-tenant-mark идёт
   ниже по файлу и при равном весе схлопывало превью обратно до 32px. */
.t2-tenant-mark.l-badge-preview-mark {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  font-size: 22px;
}
.t2-tenant-mark.l-badge-preview-mark.is-emoji { font-size: 26px; }
.l-badge-preview-copy { display: grid; min-width: 0; }
.l-badge-preview-copy strong { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.l-badge-preview-copy small { color: var(--l-text-3); font-size: 12.5px; }

/* Клетка сетки — самостоятельная кнопка submit: выбор сохраняется одним
   нажатием, без «применить». Сетка авто-заполняемая, чтобы одинаково легла и
   на 320px, и на широком экране. */
.l-emoji-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
  gap: 4px;
  margin-top: 2px;
}
.ledger .l-emoji-cell {
  min-height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--l-r-md);
  background: transparent;
  font-size: 21px;
  line-height: 1;
  cursor: pointer;
}
.ledger .l-emoji-cell:hover { background: var(--l-surface-hover); }
.ledger .l-emoji-cell.is-on {
  border-color: var(--l-accent);
  background: var(--l-accent-soft);
}
.l-emoji-pick .l-cta { margin-top: 10px; }
/* Значок профиля прячем под <details>: на странице и так плотно, а меняют его
   единожды. Маркер убираем — подпись сама выглядит кнопкой. */
.l-account-emoji { margin-top: 12px; }
.l-account-emoji > summary { display: inline-block; cursor: pointer; list-style: none; }
.l-account-emoji > summary::-webkit-details-marker { display: none; }

/* Команда и доступ по модулям. Временный слой: экран собран на панелях,
   бейджах и аватарах, здесь только раскладка строки участника и чип модуля.
   Правка доступа — нативный <details>, поэтому строка сотрудника это <summary>:
   раскрытие работает без скрипта и с клавиатуры. */
.l-team-item { border-top: 1px solid var(--l-border); }
.l-team-item:first-of-type { border-top: 0; }
.l-team-row {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 0;
  list-style: none;
}
.l-team-row > .l-avatar { margin-top: 1px; }
.l-team-row > .l-team-pencil { margin-top: 4px; }
.l-team-row::-webkit-details-marker { display: none; }
details.l-team-item > .l-team-row { cursor: pointer; }
details.l-team-item > .l-team-row:hover .l-team-pencil { color: var(--l-accent); }
.l-team-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.l-team-name {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 14px; font-weight: 600; color: var(--l-text);
}
.l-team-email { font-size: 12.5px; color: var(--l-text-3); }
.l-team-mods { display: flex; flex-wrap: wrap; gap: 6px; }
.l-team-chip {
  font-size: 11px; line-height: 1; padding: 5px 8px;
  border-radius: 999px;
  border: 1px solid var(--l-border);
  color: var(--l-text-3);
}
.l-team-chip.is-on {
  background: var(--l-accent-soft);
  border-color: transparent;
  color: var(--l-accent-ink);
  font-weight: 600;
}
.l-team-pencil { flex: 0 0 auto; color: var(--l-text-3); display: inline-flex; }
details.l-team-item[open] > .l-team-row .l-team-pencil { color: var(--l-accent); }
.l-team-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 14px; }
.l-team-form { padding: 2px 0 16px; }
.l-team-copy { margin: 0; font-size: 13px; color: var(--l-text-2); }
.l-team-checks { display: flex; flex-wrap: wrap; gap: 2px 22px; }
.l-team-check {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 7px 0;
  font-size: 13.5px; color: var(--l-text-2); cursor: pointer;
}
.l-team-check input { flex: 0 0 auto; width: 15px; height: 15px; }
.l-team-checks--wide {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: 2px 24px; margin: 4px 0 16px;
}
.l-team-check--card { align-items: flex-start; }
.l-team-check--card input { margin-top: 2px; }
.l-team-check--card > span { display: flex; flex-direction: column; gap: 3px; }
.l-team-check--card strong { font-size: 13.5px; font-weight: 600; color: var(--l-text); }
.l-team-check--card em { font-style: normal; font-size: 12px; color: var(--l-text-3); }
@media (max-width: 720px) {
  .l-team-row { flex-wrap: wrap; }
  .l-team-actions { width: 100%; justify-content: flex-start; }
  .l-team-checks--wide { grid-template-columns: 1fr; }
}

/* ============================================================================
   Слой кабинета 2.0 (t2-) — подписка
   Первые t2-классы в проде: карточка пробного периода, полоса срока, тарифы и
   строки партнёрских правил. Метрики и раскладка взяты из дизайн-проекта без
   изменений; цвета — только семантические токены Ledger, поэтому блок живёт во
   всех темах.
   ========================================================================== */
.t2-trial { padding:16px; border:1px solid var(--l-border); border-radius:var(--l-r-lg); background:var(--l-surface); box-shadow:var(--l-shadow-card); }
.t2-trial-top { display:flex; align-items:baseline; gap:8px; }
.t2-trial-days { font-family:var(--l-mono); font-size:34px; font-weight:500; letter-spacing:-.05em; line-height:1; }
.t2-trial-unit { color:var(--l-text-2); font-size:13px; font-weight:550; }
.t2-trial-note { margin-top:6px; color:var(--l-text-3); font-size:12.5px; }
.t2-bar { height:6px; margin-top:13px; overflow:hidden; border-radius:var(--l-r-full); background:var(--l-gray-150); }
.t2-bar i { display:block; height:100%; border-radius:var(--l-r-full); background:var(--l-accent); }
.t2-bar.is-warn i { background:var(--l-warn); }
.ledger .t2-plan { width:100%; padding:14px 16px; display:grid; gap:9px; border:1px solid var(--l-border); border-radius:var(--l-r-lg); background:var(--l-surface); color:var(--l-text); font:inherit; text-align:left; }
.ledger .t2-plan.is-picked { border-color:var(--l-accent); box-shadow:0 0 0 3px color-mix(in srgb, var(--l-accent) 12%, transparent); }
.t2-plan-head { display:flex; align-items:center; gap:9px; }
.t2-plan-name { font-size:14.5px; font-weight:650; letter-spacing:-.01em; }
.t2-plan-save { padding:2px 8px; border-radius:var(--l-r-full); background:var(--l-accent-soft); color:var(--l-accent-ink); font-family:var(--l-mono); font-size:11px; font-weight:600; }
.t2-radio { width:20px; height:20px; margin-left:auto; flex:0 0 auto; display:grid; place-items:center; border:1.5px solid var(--l-gray-400); border-radius:50%; }
.t2-plan.is-picked .t2-radio { border-color:var(--l-accent); background:var(--l-accent); }
.t2-radio::after { content:''; width:7px; height:7px; border-radius:50%; background:var(--l-on-accent); opacity:0; }
.t2-plan.is-picked .t2-radio::after { opacity:1; }
.t2-plan-price { display:flex; align-items:baseline; gap:6px; font-family:var(--l-mono); font-size:24px; font-weight:500; letter-spacing:-.045em; }
.t2-plan-price small { color:var(--l-text-3); font-size:12.5px; font-weight:400; letter-spacing:0; }
.t2-plan-note { color:var(--l-text-3); font-size:12.5px; line-height:1.45; }
/* Последние дни: у свежего кабинета полоса .is-warn почти пустая, и единственным
   жёлтым сигналом остаётся само число. Ноль дней — это уже «срок кончился». */
.t2-trial-days.is-warn { color:var(--l-warn); }
.t2-trial-days.is-over { color:var(--l-danger); }
.t2-bar.is-over i { background:var(--l-danger); }
/* Строка списка «что входит» / «что доступно сейчас». */
.t2-feature { min-height:40px; padding:9px 14px; display:flex; align-items:flex-start; gap:10px; border-top:1px solid var(--l-hairline); font-size:13.5px; }
.t2-feature:first-of-type { border-top:0; }
.t2-feature svg { flex:0 0 auto; margin-top:3px; color:var(--l-accent); }
/* Строки несут собственные отступы (метрики из дизайн-проекта), поэтому внутри
   l-panel их горизонтальный padding компенсируется: иначе текст уезжал бы от
   заголовка панели. */
.t2-rows { margin:0 -14px; }
/* Тариф — это <label> с нативным radio внутри: выбор работает и без скрипта,
   с клавиатуры и со скринридером. Класс is-picked ставит скрипт, :has() —
   браузер; вместе они дают одинаковую картинку в обоих режимах. */
.ledger .t2-plan:has(input:checked) { border-color:var(--l-accent); box-shadow:0 0 0 3px color-mix(in srgb, var(--l-accent) 12%, transparent); }
.t2-plan:has(input:checked) .t2-radio { border-color:var(--l-accent); background:var(--l-accent); }
.t2-plan:has(input:checked) .t2-radio::after { opacity:1; }
.t2-plan:has(input:focus-visible) { outline:2px solid var(--l-accent); outline-offset:2px; }
.t2-plan input { position:absolute; width:1px; height:1px; margin:-1px; padding:0; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }
.t2-plans { display:grid; gap:10px; }

/* Партнёрка */
/* Оффер — крупная первая строка лендинга: продаёт словами, а не заливкой. */
.t2-ref-offer { margin:0 0 6px; font-size:17px; font-weight:650; letter-spacing:-.015em; line-height:1.3; }
/* Статистика в шапке партнёрки: обычный регистр (вне .l-panel-title, который
   капсит) и приглушённый цвет — это справка, а не кнопка. */
.t2-ref-stats { color: var(--l-text-3); font-size: 12.5px; font-weight: 500; }
.t2-ref { display:flex; align-items:center; gap:8px; }
/* Шаги «как это работает»: номер в акцентном кружке + строка. Список
   настоящий (ol) — скринридер читает порядок сам, кружки для него скрыты. */
.t2-ref-steps { margin:0; padding:0; list-style:none; display:grid; gap:12px; }
.t2-ref-steps li { display:flex; align-items:flex-start; gap:10px; font-size:13.5px; line-height:1.45; }
.t2-ref-steps li > span:last-child { padding-top:2.5px; }
.t2-ref-step-num {
  flex:0 0 auto;
  width:24px; height:24px;
  display:inline-flex; align-items:center; justify-content:center;
  border-radius:var(--l-r-full);
  background:var(--l-accent-soft); color:var(--l-accent-ink);
  font-family:var(--l-mono); font-size:12px; font-weight:600;
}
.t2-ref-link { min-width:0; flex:1 1 auto; padding:11px 12px; overflow:hidden; border:1px dashed color-mix(in srgb, var(--l-accent) 34%, var(--l-border)); border-radius:var(--l-r-md); background:color-mix(in srgb, var(--l-accent-soft) 45%, transparent); color:var(--l-accent-ink); font-family:var(--l-mono); font-size:12.5px; text-overflow:ellipsis; white-space:nowrap; }
.t2-bonus-row { min-height:58px; padding:11px 14px; display:flex; align-items:center; gap:12px; border-top:1px solid var(--l-hairline); }
.t2-bonus-row:first-of-type { border-top:0; }
.t2-bonus-days { flex:0 0 auto; min-width:52px; padding:4px 8px; border-radius:var(--l-r-full); background:var(--l-accent-soft); color:var(--l-accent-ink); font-family:var(--l-mono); font-size:13px; font-weight:600; letter-spacing:-.03em; text-align:center; }
.t2-bonus-copy { min-width:0; display:grid; gap:2px; }
.t2-bonus-copy strong { font-size:13.5px; font-weight:550; letter-spacing:-.01em; }
.t2-bonus-copy small { color:var(--l-text-3); font-size:11.5px; line-height:1.4; }
/* «Скоро» — правило есть, но ещё не работает: приглушаем, а не прячем. Число
   в плашке при этом остаётся текстом: на --l-gray-150 третичный цвет давал
   2.78:1, поэтому берём вторичный — тот же, что у .l-badge. */
.t2-bonus-row.is-soon .t2-bonus-days { background:var(--l-gray-150); color:var(--l-text-2); }
.t2-bonus-row.is-soon .t2-bonus-copy strong { color:var(--l-text-2); }
@media (max-width: 520px) {
  .t2-ref { flex-wrap:wrap; }
  .t2-ref-link { flex:1 0 100%; }
  .t2-ref .l-btn { flex:1 1 auto; }
}

/* ============================================================================
   Слой кабинета 2.0 (t2-) — мобильная навигация
   Два режима на телефоне: «панель снизу» (по умолчанию) и «меню сбоку»
   (прежняя шторка с бургером). Разметка обоих режимов лежит в шелле всегда,
   видимость переключают классы l-nav-tabs / l-nav-drawer на <html> — их ставит
   инлайн-скрипт в <head> до первой отрисовки, поэтому панель не мигает.
   Метрики и раскладка перенесены из дизайн-системы Ledger Mobile DS дословно;
   цвета — только семантические токены, поэтому блок живёт во всех темах.
   Все правила показа собраны в мобильном блоке @media (max-width: 720px)
   ниже по файлу; здесь — сами компоненты.
   ========================================================================== */

/* ── Шапка кабинета: иконки + крупный заголовок раздела ─────────────────── */
.t2-appbar {
  position: sticky;
  top: 0;
  z-index: calc(var(--l-z-pop) - 40);
  padding: calc(env(safe-area-inset-top) + 10px) 14px 14px;
  border-bottom: 1px solid color-mix(in srgb, var(--l-border) 82%, transparent);
  background: color-mix(in srgb, var(--l-bg) 88%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(1.2);
  backdrop-filter: blur(18px) saturate(1.2);
}
.t2-appbar-top { min-height: 52px; display: flex; align-items: center; gap: 8px; }
/* Метка кабинета: в рамку садится картинка, эмодзи или буквы названия.
   `overflow: hidden` здесь обязателен — загруженный логотип приходит квадратом
   256px и без обрезки разъезжался на всю ширину меню. Правило для img держим
   на базовом классе, а не на конкретном месте показа: иначе следующая точка
   вывода метки унаследует ту же поломку. */
.t2-tenant-mark {
  width: 32px;
  height: 32px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: 9px;
  background: var(--l-accent-soft);
  color: var(--l-accent-ink);
  font-family: var(--l-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: -.04em;
}
.t2-tenant-mark img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Эмодзи — не моноширинные инициалы: кегль 12px и отрицательный трекинг
   рассчитаны на две буквы, а картиночный знак от них становится вдвое мельче
   рамки. Отдаём эмодзи системную гарнитуру и свой размер. */
.t2-tenant-mark.is-emoji {
  font-family: inherit;
  font-size: 19px;
  line-height: 1;
  letter-spacing: normal;
}
.t2-tenant-copy { min-width: 0; display: grid; }
.t2-tenant-name {
  overflow: hidden;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.015em;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.t2-tenant-role {
  color: var(--l-text-3);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
}
.t2-tenant-chev { flex: 0 0 auto; color: var(--l-text-3); }
.t2-icons { display: flex; align-items: center; gap: 2px; }
.ledger .t2-iconbtn {
  position: relative;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: var(--l-text-2);
}
.ledger .t2-iconbtn:hover { color: var(--l-text); background: var(--l-surface); }
.t2-iconbtn .l-bell-dot { position: absolute; top: 9px; right: 10px; }
.t2-avatar {
  width: 32px;
  height: 32px;
  margin-left: 4px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  /* Тот же язык, что у крупного кружка профиля .l-account-avatar: мягкая
     акцентная подложка и «чернила» — во всех темах контраст проверен тестом.
     Почти чёрный l-gray-950 владелец забраковал: мрачно и текст терялся. */
  background: var(--l-accent-soft);
  color: var(--l-accent-ink);
  font-size: 11px;
  font-weight: 600;
}
.t2-appbar-head {
  min-height: 46px;
  margin-top: 6px;
  padding: 0 4px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
}
.t2-appbar-title { margin: 0; font-size: 25px; font-weight: 700; letter-spacing: -.035em; line-height: 1.1; }
.t2-appbar-count { font-family: var(--l-mono); font-size: 12px; color: var(--l-text-3); letter-spacing: -.01em; }
/* Хлебная крошка подраздела настроек: маленькая строка «Настройки ›» над
   крупным названием модуля. Крупным её делать нельзя — «Настройки ›
   Уведомления» в 25px не влезает в 375px. Цель нажатия добирается паддингом. */
/* .ledger-префикс — перебить глобальное `.ledger a { color: accent }`:
   крошка — служебная навигация, акцентной она спорила бы с заголовком. */
.ledger .l-crumb {
  color: var(--l-text-3);
  font-size: 12.5px;
  font-weight: 600;
  text-decoration: none;
  padding: 6px 0;
  margin: -6px 0;
}
.ledger .l-crumb:hover { color: var(--l-text-2); text-decoration: underline; }
.l-crumb-sep { color: var(--l-text-3); font-size: 12.5px; }
/* В шторочной шапке крошка стоит в одну строку с названием страницы. */

/* ── Нижняя навигация кабинета ──────────────────────────────────────────── */
.t2-tabbar {
  position: fixed;
  inset: auto 0 0 0;
  z-index: calc(var(--l-z-pop) + 6);
  padding: 6px 6px calc(6px + env(safe-area-inset-bottom));
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 2px;
  border-top: 1px solid var(--l-border);
  background: color-mix(in srgb, var(--l-surface) 92%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(1.2);
  backdrop-filter: blur(18px) saturate(1.2);
}
.ledger .t2-tab {
  min-height: 50px;
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 3px;
  border-radius: 12px;
  /* Подпись вкладки — основная навигация, а не пояснение: третичный цвет давал
     на 10.5px всего 3.2–3.8:1. Вторичный держит 4.8:1 и выше во всех темах. */
  color: var(--l-text-2);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: -.01em;
}
.ledger .t2-tab.is-active { color: var(--l-accent-ink); background: var(--l-accent-soft); }
.t2-tab-ic { position: relative; display: grid; place-items: center; }
.t2-tab-dot {
  position: absolute;
  top: -2px;
  right: -6px;
  min-width: 15px;
  height: 15px;
  padding: 0 4px;
  display: grid;
  place-items: center;
  border: 2px solid var(--l-surface);
  border-radius: var(--l-r-full);
  background: var(--l-danger);
  color: var(--l-on-danger);
  font-family: var(--l-mono);
  font-size: 9px;
  font-weight: 600;
}

/* ── Шторка: кабинет сверху, профиль снизу ─────────────────────────────────── */
/* Метка в шапке меню заливная: шапка стоит на фоне самого меню, и мягкий
   акцент на нём терял контраст. */
.t2-tenant-head .t2-tenant-mark { background: var(--l-accent); color: var(--l-on-accent); }
/* Эмодзи цветное само по себе — заливной акцент под ним превращается в пятно.
   Возвращаем мягкую подложку, как у остальных мест показа метки. */
.t2-tenant-head .t2-tenant-mark.is-emoji { background: var(--l-accent-soft); }
.t2-tenant-head .t2-tenant-name { font-size: 14px; }
.ledger .t2-drawer-foot {
  width: 100%;
  min-height: 56px;
  padding: 10px;
  display: flex;
  align-items: center;
  gap: 10px;
  border: 0;
  border-radius: var(--l-r-md);
  background: transparent;
  color: var(--l-sidebar-strong);
  font: inherit;
  text-align: left;
}
.ledger .t2-drawer-foot:hover { background: var(--l-sidebar-hover); }
.t2-drawer-foot-copy { min-width: 0; flex: 1 1 auto; display: grid; gap: 2px; }
.t2-drawer-foot-copy strong { font-size: 13.5px; font-weight: 600; letter-spacing: -.01em; }
.t2-drawer-foot-copy small { color: var(--l-sidebar-text); font-size: 11.5px; }
.t2-drawer-days {
  flex: 0 0 auto;
  padding: 3px 9px;
  border-radius: var(--l-r-full);
  background: color-mix(in srgb, var(--l-accent) 22%, transparent);
  color: var(--l-sidebar-strong);
  font-family: var(--l-mono);
  font-size: 11.5px;
  font-weight: 600;
}

/* ── Настройки: строка с переключателем и выбор режима навигации ───────────── */
.t2-setrow {
  min-height: 56px;
  padding: 11px 14px;
  display: flex;
  align-items: center;
  gap: 12px;
  border-top: 1px solid var(--l-hairline);
}
.t2-setrow:first-of-type { border-top: 0; }
.t2-setrow-copy { min-width: 0; flex: 1 1 auto; display: grid; gap: 2px; }
.t2-setrow-copy strong { font-size: 13.5px; font-weight: 550; letter-spacing: -.01em; }
.t2-setrow-copy small { color: var(--l-text-3); font-size: 11.5px; line-height: 1.4; }
.ledger .t2-switch {
  position: relative;
  width: 46px;
  height: 28px;
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  border-radius: var(--l-r-full);
  background: var(--l-gray-300);
  transition: background 140ms ease;
}
.ledger .t2-switch.is-on { background: var(--l-accent); }
.t2-switch::before {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--l-surface);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .22);
  transition: transform 140ms ease;
}
.t2-switch.is-on::before { transform: translateX(18px); }
.t2-switch::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 46px;
  height: 44px;
}

.t2-navpick { padding: 12px 14px 14px; display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.ledger .t2-navpick-opt {
  padding: 9px;
  display: grid;
  gap: 8px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  background: var(--l-surface);
  color: var(--l-text);
  font: inherit;
  text-align: left;
}
.ledger .t2-navpick-opt.is-picked {
  border-color: var(--l-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--l-accent) 12%, transparent);
}
.t2-navpick-pic {
  height: 92px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--l-r-sm);
  background: var(--l-bg);
  box-shadow: inset 0 0 0 1px var(--l-hairline);
}
.t2-navpick-bar { height: 13px; flex: 0 0 auto; background: var(--l-gray-200); }
.t2-navpick-body { flex: 1 1 auto; display: flex; gap: 3px; padding: 5px; }
.t2-navpick-lines { flex: 1 1 auto; display: grid; gap: 4px; align-content: start; }
.t2-navpick-lines i { height: 6px; border-radius: 2px; background: var(--l-gray-200); }
.t2-navpick-rail { width: 22px; flex: 0 0 auto; border-radius: 2px; background: var(--l-accent-soft); }
.t2-navpick-tabs { height: 15px; flex: 0 0 auto; display: flex; gap: 3px; padding: 3px; background: var(--l-accent-soft); }
.t2-navpick-tabs i { flex: 1 1 0; border-radius: 2px; background: color-mix(in srgb, var(--l-accent) 40%, transparent); }
.t2-navpick-label { display: flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; }
.t2-navpick-note { color: var(--l-text-3); font-size: 11px; line-height: 1.35; }
.t2-navpick-opt .t2-radio { margin-left: auto; width: 18px; height: 18px; }

/* ── Отклонения от дизайн-проекта и склейка с существующим шеллом ──────────── */
/* Шапка и панель лежат в разметке всегда (один шелл на все страницы), поэтому
   по умолчанию они спрятаны, а показываются только в мобильном режиме tabs.
   Правила идут после самих компонентов: у них та же специфичность. */
.t2-appbar,
.t2-tabbar { display: none; }
/* Дни пробного периода на ПК живут в топбаре — в подвале рельсы это был бы
   тот же счётчик второй раз. */
.t2-drawer-days { display: none; }
/* Профиль в подвале — общий блок шторки и рельсы: аватар с именем стоит внизу
   меню в обоих размерах экрана. В свёрнутой рельсе от него остаётся аватар,
   подписанный подсказкой рельса. */
.ledger .t2-drawer-foot { flex: 1 0 100%; margin-bottom: 2px; }
/* 72px рельса: аватар занимает всю ширину подвала, поэтому боковые поля
   отдаём ему целиком — иначе кружок ужимался бы до овала.
   Только широкие экраны: класс l-collapsed переживает поворот телефона в
   localStorage (свернули рельсу в лендскейпе — портретная ШТОРКА получала
   свёрнутый подвал: один аватар без имени и дыра по высоте). */
@media (min-width: 721px) {
  html.l-collapsed .l-sidebar-foot { padding-inline: 0; }
  html.l-collapsed .t2-drawer-foot { justify-content: center; padding-inline: 0; }
  html.l-collapsed .t2-drawer-foot .t2-avatar { flex: 0 0 auto; margin: 0; }
  html.l-collapsed .t2-drawer-foot .t2-drawer-foot-copy { display: none; }
}
/* Пять пунктов — предельный случай; у сотрудника разделов бывает меньше, и
   пять жёстких колонок сжимали бы подписи впустую. Число колонок приходит
   из разметки: там же, где считается сам список пунктов. */
.t2-tabbar { grid-template-columns: repeat(var(--t2-tab-count, 5), 1fr); }
/* Дизайн-проект ссылается на .t2-radio внутри выбора режима, но описывает
   его только у тарифов (кружок с точкой). Здесь это галочка: она стоит у
   выбранного режима и держит своё место у невыбранного, иначе подпись
   прыгала бы при переключении. */
.t2-navpick-opt .t2-radio { border: 0; color: var(--l-accent); visibility: hidden; }
.t2-navpick-opt.is-picked .t2-radio { visibility: visible; }
.t2-navpick-opt .t2-radio::after { content: none; }
/* Заголовок шапки — <h1>, а ссылка-бренд слева от иконок не должна тянуться. */
.t2-appbar-gap { flex: 1 1 auto; }
/* --l-gray-200 темами не переопределяется: в «Полночи» и «Карбоне» полосы
   макета остались бы светло-серыми на тёмном фоне. Макет — схема экрана, а не
   картинка, поэтому берём цвет текста с малой непрозрачностью: он есть в
   каждой теме и всегда контрастен своему фону. */
.t2-navpick-bar,
.t2-navpick-lines i { background: color-mix(in srgb, var(--l-text) 14%, transparent); }
/* На ПК две миниатюры во всю ширину панели читаются как баннеры — держим их
   в размере телефона, каким они и притворяются. */
@media (min-width: 721px) {
  .t2-navpick { max-width: 420px; }
}

/* ============================================================================
   Слой кабинета 2.0 (t2-) — строка управления, списки-строки и полосы
   Перенос из дизайн-системы Ledger Mobile DS. На телефоне лента видов, лента
   разделов и открытая панель фильтров складываются в одну строку: сегмент вида
   значками, до трёх чипов и значок фильтров. Сводные списки («Есть
   задолженность», отчёт по категориям) читаются строками с суммой и долей, а
   не таблицей. Цвета — только семантические токены, поэтому блок живёт во всех
   темах.
   ========================================================================== */

/* ── Одна строка управления вместо трёх ─────────────────────────────────── */
.t2-ctl {
  margin: 0 0 12px;
  padding: 8px 0 9px;
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--l-bg);
}
.t2-ctl-seg {
  flex: 0 0 auto;
  display: flex;
  padding: 2px;
  gap: 2px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface);
}
.ledger .t2-ctl-seg a {
  width: 44px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 7px;
  color: var(--l-text-3);
}
.ledger .t2-ctl-seg a.is-active { background: var(--l-accent-soft); color: var(--l-accent-ink); }
.ledger .t2-chip {
  min-height: 38px;
  padding: 0 12px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-full);
  background: var(--l-surface);
  color: var(--l-text-2);
  font: inherit;
  font-size: 13px;
}
.ledger .t2-chip.is-set {
  border-color: color-mix(in srgb, var(--l-accent) 40%, var(--l-border));
  background: var(--l-accent-soft);
  color: var(--l-accent-ink);
  font-weight: 600;
}
/* Текст берём из «чернил» опасности, а не из самой заливки: у тёмных тем
   --l-danger светлый и на --l-danger-soft давал 3.97–4.21:1. */
.ledger .t2-chip.is-attn {
  border-color: color-mix(in srgb, var(--l-danger) 34%, var(--l-border));
  background: var(--l-danger-soft);
  color: var(--l-danger-ink);
  font-weight: 600;
}
.t2-chip-n { font-family: var(--l-mono); font-size: 12px; }
.t2-ctl-spacer { flex: 1 1 auto; }
/* Сегмент вида и значок фильтров закреплены по краям строки, а чипы между
   ними листаются вбок: на 375px «Просрочено · N» и раздел рядом с сегментом
   уже не помещаются, а переносить строку управления нельзя — она одна. */
.t2-ctl-chips {
  min-width: 0;
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  overflow-x: auto;
  scrollbar-width: none;
}
.t2-ctl-chips::-webkit-scrollbar { display: none; width: 0; height: 0; }
.t2-ctl-chips > * { flex: 0 0 auto; }
.ledger .t2-chip { white-space: nowrap; }

/* ── Секция-карточка со строками (сводки, задолженность) ────────────────── */
.t2-sec {
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  background: var(--l-surface);
  box-shadow: var(--l-shadow-card);
  overflow: hidden;
}
.t2-sec-head {
  min-height: 46px;
  padding: 10px 14px;
  display: flex;
  align-items: center;
  gap: 8px;
  border-bottom: 1px solid var(--l-hairline);
}
.t2-sec-head h2 { margin: 0; font-size: 13.5px; font-weight: 650; letter-spacing: -.01em; }
.t2-sec-n {
  padding: 1px 7px;
  border-radius: var(--l-r-full);
  background: var(--l-gray-150);
  color: var(--l-text-2);
  font-family: var(--l-mono);
  font-size: 11px;
}
.ledger .t2-sec-link { margin-left: auto; font-size: 12.5px; font-weight: 600; }
.t2-sec-foot {
  min-height: 44px;
  padding: 0 14px;
  display: flex;
  align-items: center;
  border-top: 1px solid var(--l-hairline);
  background: color-mix(in srgb, var(--l-gray-100) 60%, transparent);
  font-size: 12.5px;
}
.ledger .t2-sec-foot a { min-height: 44px; flex: 1 1 auto; display: flex; align-items: center; font-weight: 550; }
.t2-line {
  min-height: 52px;
  padding: 11px 14px;
  display: flex;
  align-items: center;
  gap: 11px;
  border-top: 1px solid var(--l-hairline);
  color: var(--l-text);
}
.t2-line:first-of-type { border-top: 0; }
.ledger a.t2-line { color: var(--l-text); }
.ledger a.t2-line:hover { background: var(--l-surface-hover); }
.t2-line-main { min-width: 0; flex: 1 1 auto; display: grid; gap: 2px; }
.t2-line-main strong {
  overflow: hidden;
  font-size: 13.5px;
  font-weight: 550;
  letter-spacing: -.01em;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.t2-line-meta { display: flex; align-items: center; gap: 6px; color: var(--l-text-3); font-size: 11.5px; }
.t2-line-meta .is-overdue { color: var(--l-danger); font-weight: 600; }
.t2-line-sum {
  flex: 0 0 auto;
  font-family: var(--l-mono);
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: -.03em;
}
.t2-line-sum.is-in { color: var(--l-accent-ink); }
.t2-line-sum.is-out { color: var(--l-danger); }

/* ── Отчёты: полосы по разрезу вместо широкой таблицы ───────────────────── */
.t2-rep { padding: 12px 14px; display: grid; gap: 11px; border-top: 1px solid var(--l-hairline); }
.t2-rep:first-of-type { border-top: 0; }
.t2-rep-top { display: flex; align-items: baseline; gap: 8px; font-size: 13.5px; }
.t2-rep-top strong { font-weight: 550; letter-spacing: -.01em; }
.t2-rep-top .l-mono { margin-left: auto; font-size: 13.5px; font-weight: 500; letter-spacing: -.03em; }
.t2-rep-top small { color: var(--l-text-3); font-family: var(--l-mono); font-size: 11.5px; }
.t2-rep-bar { height: 8px; overflow: hidden; border-radius: var(--l-r-full); background: var(--l-gray-150); }
.t2-rep-bar i { display: block; height: 100%; border-radius: var(--l-r-full); background: var(--l-accent); }
.t2-rep-bar.is-out i { background: var(--l-danger); }

/* Мета-счётчики задачи: SVG вместо эмодзи ☑ / 💬 — кегль и цвет системного
   шрифта всегда мимо. Один штрих с остальной иконографикой (currentColor).
   Отступ между значком и числом даёт gap, а не пробел в разметке: пробел
   внутри inline-flex схлопывается. */
.l-tmeta { display: inline-flex; align-items: center; gap: 4px; }
.l-tmeta svg { width: 12px; height: 12px; flex: 0 0 auto; opacity: .8; }
.l-tcard-foot .l-tmeta svg,
.l-trow-meta .l-tmeta svg { margin-right: 1px; }

/* Круг исполнителя: .l-trow-meta button { min-height: 28px } мобильного блока
   растягивал .l-avatar 22×22 в овал. Круг 28×28 + прозрачная цель нажатия 40px. */
.l-trow-meta button.l-avatar {
  position: relative;
  width: 28px;
  height: 28px;
  min-height: 28px;
  padding: 0;
  font-size: 10px;
}
.l-trow-meta button.l-avatar::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 40px;
  height: 40px;
}

/* ── Отклонения от дизайн-проекта и склейка с существующим шеллом ────────── */
/* Строка управления — мобильный компонент: на ПК остаются лента видов и
   развёрнутая панель фильтров, где места хватает. Разметка лежит в шаблоне
   всегда, показывает её мобильный блок @media (max-width: 720px) ниже. */
.t2-ctl { display: none; }
/* Включённый чип «требует действия» (просроченные) заливается целиком: мягкий
   фон .is-attn от .is-set неотличим, и было непонятно, срез включён или нет.
   Повторное касание снимает фильтр — адрес у чипа переключающий. */
.ledger .t2-chip.is-attn.is-set {
  border-color: var(--l-danger);
  background: var(--l-danger);
  color: var(--l-on-danger);
}
/* Чип-значок (фильтры) подписи не имеет — цель нажатия держим шириной. */
.ledger .t2-chip--ic { min-width: 44px; padding: 0 10px; justify-content: center; }
/* Шеврон чипа-выбора подсказывает поповер и не спорит с подписью. */
.t2-chip-chev { flex: 0 0 auto; opacity: .6; }
/* Полосы отчёта — только на телефоне: на ПК та же цифра стоит в таблице ДДС
   рядом с помесячной разбивкой, и вторая её подача была бы шумом. */
.t2-reps { display: none; }
/* Задолженность стоит над реестром контрагентов в обоих размерах экрана:
   колонки долга в таблице нет, и взять эту цифру больше негде. */
.l-cp-debts { margin-bottom: 18px; }
.l-cp-debts .t2-sec-link { color: var(--l-danger); letter-spacing: -.02em; }

/* ── Цели нажатия 44px без правки метрик дизайн-проекта ───────────────────── */
/* Значки шапки (40), аватар (32), «Все →» (18) и значки вида (44×40) меньше
   44px по высоте: метрики пришли из дизайн-проекта и менять их не нужно —
   палец ловит прозрачный прямоугольник, как у .t2-switch и круга исполнителя. */
.ledger .t2-iconbtn,
.t2-appbar .t2-avatar,
.ledger .t2-sec-link,
.ledger .t2-ctl-seg a { position: relative; }
.ledger .t2-iconbtn::after,
.t2-appbar .t2-avatar::after,
.ledger .t2-sec-link::after,
.ledger .t2-ctl-seg a::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 100%;
  min-width: 44px;
  height: 44px;
}
/* Чипы живут в горизонтальной ленте: overflow-x там обрезает и по вертикали,
   поэтому прозрачную цель не подвесить — ленте даём внутренний зазор 3px и
   тут же снимаем его отрицательным полем, чтобы высота строки не поехала. */
.t2-ctl-chips { padding-block: 3px; margin-block: -3px; }
.ledger .t2-ctl .t2-chip { position: relative; }
.ledger .t2-ctl .t2-chip::after {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 100%;
  height: 44px;
}

/* ============================================================================
   Слой кабинета 2.0 (t2-) — экран «Сегодня»
   Перенос из дизайн-системы Ledger Mobile DS. Карточка свободных денег со
   спарклайном, красная плашка просрочки, плотный ряд операции и раскладка
   рабочего стола (плитки + две колонки). Секции-карточки (.t2-sec) и строки
   списка (.t2-line) переиспользуются из блока выше — своих копий здесь нет.
   ========================================================================== */

.t2-today { display: grid; gap: 12px; }

/* ── Свободные деньги ───────────────────────────────────────────────────── */
.t2-balance {
  padding: 16px 16px 14px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  background: var(--l-surface);
  box-shadow: var(--l-shadow-card);
}
.t2-balance-label {
  color: var(--l-text-3);
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.t2-balance-value {
  margin-top: 4px;
  font-family: var(--l-mono);
  font-size: 30px;
  font-weight: 500;
  letter-spacing: -.045em;
  font-variant-numeric: tabular-nums;
}
.t2-balance-value .cur { margin-left: 4px; font-size: 17px; color: var(--l-text-3); }
.t2-balance-split {
  margin-top: 13px;
  padding-top: 12px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  border-top: 1px solid var(--l-hairline);
}
.t2-balance-cell { display: grid; gap: 2px; }
.t2-balance-cell span { color: var(--l-text-3); font-size: 11px; font-weight: 600; }
.t2-balance-cell strong {
  font-family: var(--l-mono);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -.03em;
}
.t2-balance-cell.is-in strong { color: var(--l-accent-ink); }
.t2-balance-cell.is-out strong { color: var(--l-danger); }
.t2-spark { margin-top: 12px; display: flex; align-items: flex-end; gap: 3px; height: 34px; }
/* Прошлые столбики: 22% акцента на полотне карточки — 1.33:1, полоса пропадала
   в «Изумруде» и «Карбоне». 30% держит различимость во всех темах. */
.t2-spark i { flex: 1 1 0; border-radius: 2px 2px 0 0; background: color-mix(in srgb, var(--l-accent) 30%, transparent); }
.t2-spark i.is-now { background: var(--l-accent); }

/* ── Точка этапа в строке списка ────────────────────────────────────────── */
.t2-dot { width: 7px; height: 7px; flex: 0 0 auto; border-radius: 50%; background: var(--dot-c, var(--l-text-3)); }

/* ── Строка «требует действия» ──────────────────────────────────────────────
   Была красной плашкой с заливкой — владелец счёл её тяжёлой. Теперь это
   тонкая текстовая строка: красная точка + текст + сумма + ссылка «Разобрать».
   Без фона и рамки, чтобы не спорить с плитками вокруг. */
.t2-attn {
  padding: 2px 4px;
  display: flex;
  align-items: center;
  gap: 9px;
  color: var(--l-text);
  font-size: 12.5px;
  font-weight: 550;
}
.t2-attn-dot {
  width: 8px;
  height: 8px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--l-danger);
}
/* Сумма не переносится: на 320px «63 000 ₽» роняло символ валюты на свою строку. */
.t2-attn strong {
  font-family: var(--l-mono);
  font-weight: 600;
  white-space: nowrap;
  color: var(--l-danger-ink);
}
.t2-attn-link {
  flex: 0 0 auto;
  color: var(--l-accent-ink);
  font-weight: 600;
  text-decoration: none;
  /* Цель нажатия: сама строка тонкая, добираем высоту паддингом ссылки. */
  padding: 8px 2px;
  margin: -8px 0;
}
.t2-attn-link:hover { text-decoration: underline; }

/* ── Плотный ряд операции ───────────────────────────────────────────────── */
.t2-oprow {
  min-height: 58px;
  padding: 11px 14px;
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) auto;
  align-items: center;
  gap: 11px;
  border-top: 1px solid var(--l-hairline);
}
.t2-oprow:first-of-type { border-top: 0; }
.ledger a.t2-oprow { color: var(--l-text); }
.ledger a.t2-oprow:hover { background: var(--l-surface-hover); }
.t2-oprow-date { display: grid; justify-items: center; font-family: var(--l-mono); line-height: 1.15; }
.t2-oprow-date b { font-size: 13.5px; font-weight: 600; letter-spacing: -.03em; }
.t2-oprow-date span { color: var(--l-text-3); font-size: 10px; }

/* ── Раскладка рабочего стола ───────────────────────────────────────────── */
.t2-dsk-cols { display: grid; grid-template-columns: 1.35fr 1fr; gap: 16px; align-items: start; }
.t2-dsk-tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 16px; }

/* ── Отклонения от дизайн-проекта и склейка с существующим шеллом ────────── */
/* Колонка рабочего стола: в дизайн-проекте .t2-dsk-cols описан без внутреннего
   контейнера, но секций в каждой колонке несколько, и им нужен свой поток. */
.t2-dsk-col { display: grid; gap: 12px; align-content: start; }
/* Плиток бывает три, а не четыре: кабинет без модуля «Документы» не ждёт
   оплаты. Фиксированные четыре колонки оставили бы пустое место, поэтому
   auto-fit — на широком экране он даёт ровно ту же сетку из четырёх. */
.t2-dsk-tiles { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
/* Плитка прихода/расхода — то же значение, что в сплите карточки, поэтому
   цвет описан у самой суммы: в дизайн-проекте он есть только у .t2-balance-cell. */
.t2-balance-value.is-in { color: var(--l-accent-ink); }
.t2-balance-value.is-out { color: var(--l-danger); }
.t2-balance-note { margin-top: 7px; color: var(--l-text-3); font-size: 11.5px; line-height: 1.35; }
/* На рабочем столе приход и расход стоят отдельными плитками — сплит внутри
   карточки повторил бы те же два числа рядом. На телефоне наоборот: плиток
   нет, и сплит — единственное место, где эти числа видно. */
@media (min-width: 721px) {
  .t2-dsk-tiles .t2-balance-split { display: none; }
}
/* Спейсер прижимает «Разобрать» к правому краю строки просрочки. */
.t2-attn .l-spacer { flex: 1 1 auto; }
/* Подвал секции умеет не только ссылку: «Скопировать ссылку приглашения» —
   действие, и оно обязано быть кнопкой, а не ссылкой в никуда. */
.ledger .t2-sec-foot button {
  min-height: 44px;
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--l-accent-ink);
  font: inherit;
  font-size: 12.5px;
  font-weight: 550;
  text-align: left;
  cursor: pointer;
}
/* Приветствие пустого кабинета — не пустой белый экран на первом входе. */
.t2-hello { padding: 18px 16px; }
.t2-hello h2 { margin: 0 0 6px; font-size: 16px; font-weight: 650; letter-spacing: -.015em; }
.t2-hello p { margin: 0; color: var(--l-text-2); font-size: 13px; line-height: 1.5; }
/* Пустая секция говорит словами, а не пустотой: «Задач на сегодня нет». */
.t2-line-empty { color: var(--l-text-3); font-size: 12.5px; }
/* Метастрока строки обзора не переносится: вторая строка ломала бы ритм 52px,
   а на 375px бейдж с деталью норовят развалиться на три ряда. */
.t2-today .t2-line-meta { min-width: 0; overflow: hidden; white-space: nowrap; }
.t2-today .t2-line-meta > * { flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; }
.t2-today .t2-line-meta .l-badge { flex: 0 0 auto; padding: 2px 9px; font-size: 11.5px; }
.t2-today .t2-line-meta .l-badge::before { width: 6px; height: 6px; }

@media (max-width: 720px) {
  /* Телефон (макет 3b): одна колонка, плитки прихода/расхода живут в сплите
     карточки, «Последние операции» и «Партнёрка» на телефон не выносятся —
     это обзор дня, а не рабочий стол. */
  .t2-dsk-tiles { grid-template-columns: 1fr; margin-bottom: 0; }
  .t2-dsk-tiles > .t2-balance ~ .t2-balance { display: none; }
  .t2-dsk-cols,
  .t2-dsk-col { display: contents; }
  /* .ledger в селекторе — чтобы правило перевешивало собственный display
     кнопки (.ledger .l-btn): «Разобрать» это ссылка-кнопка. */
  .ledger .t2-dsk-only,
  .t2-dsk-only { display: none; }
}

@media (max-width: 360px) {
  /* 320px: сумма в 30px с символом валюты уже не помещается в строку. */
  .t2-balance-value { font-size: 26px; }
  .t2-balance-value .cur { font-size: 15px; }
}

/* ============================================================================
   Слой кабинета 2.0 (t2-) — чек-лист первых шагов

   Живёт на двух экранах: полным списком в хабе настроек и коротким (три
   ближайших незакрытых шага) на «Сегодня». Панель — обычная .l-panel, свои
   тут только шапка, кружки-галочки и ритм строк: каждая строка ссылка, и на
   телефоне она обязана нажиматься по всей высоте, отсюда min-height 44px.
   ========================================================================== */

.t2-onb-head {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 4px;
}
.t2-onb-title { margin: 0; font-size: 13.5px; font-weight: 650; letter-spacing: -.01em; }
.t2-onb-count {
  padding: 1px 7px;
  border-radius: var(--l-r-full);
  background: var(--l-gray-150);
  color: var(--l-text-2);
  font-size: 11px;
}
/* «Настрою потом» уходит вправо: это отказ, а не второе главное действие. */
.t2-onb-hide { margin-left: auto; display: flex; }
.t2-onb-list { margin: 0; padding: 0; list-style: none; }
.ledger a.t2-onb-step {
  min-height: 44px;
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--l-text);
  font-size: 13.5px;
  line-height: 1.3;
}
.ledger a.t2-onb-step:hover { color: var(--l-accent-ink); }
.t2-onb-mark { flex: 0 0 auto; color: var(--l-text-3); }
/* Сделанный шаг остаётся ссылкой — в него возвращаются что-то поправить, но
   глазами он уже не работа: гасим текст и оставляем зачёркивание. */
.t2-onb-step.is-done .t2-onb-mark { color: var(--l-accent); }
.t2-onb-step.is-done .t2-onb-step-title { color: var(--l-text-3); text-decoration: line-through; }
/* Короткий вариант на «Сегодня» стоит в сетке .t2-today со своим шагом 12px —
   собственный нижний отступ панели там лишний. */
.t2-today .t2-onb { margin-bottom: 0; }
.ledger .t2-onb-all {
  min-height: 44px;
  display: flex;
  align-items: center;
  font-size: 12.5px;
  font-weight: 550;
}

/* ============================================================================
   Слой кабинета 2.0 (t2-) — ПК: топбар кабинета и панель чипов
   Перенос из дизайн-системы Ledger Mobile DS (блок «ПК-версия»). Оба
   компонента существуют только на широком экране: на телефоне ту же работу
   делают шапка кабинета (.t2-appbar) и строка управления (.t2-ctl), поэтому
   почти весь блок живёт внутри @media (min-width: 721px) — на телефоне у него
   не должно быть ни веса, ни побочных эффектов.
   Поля глобального поиска (⌘K) из дизайн-проекта здесь нет: самого поиска в
   приложении ещё нет, и полоса-заглушка обещала бы несуществующее (BACKLOG).
   ========================================================================== */

/* Топбар лежит в разметке всегда (шелл один на все размеры экрана), поэтому по
   умолчанию он спрятан: на телефоне его работу делает шапка кабинета. */
.t2-topbar { display: none; }
/* Панель чипов рисуется поверх формы фильтров и только с JavaScript: чипы
   открывают поповеры. Без JS в карточке остаются исходные селекты — форма
   работает и без единой строки скрипта. */
.t2-filters-set { display: none; }
/* Отдельная карточка среза («Регулярные»): формы там нет, а переключать срез
   надо. На телефоне срез живёт чипом строки управления — карточки нет. */
.t2-filters--scope { display: none; }

@media (min-width: 721px) {
  /* ── Топбар кабинета ──────────────────────────────────────────────────── */
  /* Топбар — третий элемент сетки .l-app, поэтому колонку и ряд расставляем
     явно: при автоматической раскладке .l-main уехал бы под рельсу. Ряды
     меняем только там, где топбар реально есть: он рендерится не всегда
     (см. комментарий в l-shell-top.ejs). */
  .l-app:has(> .t2-topbar) { grid-template-rows: auto 1fr; }
  .l-app:has(> .t2-topbar) .l-sidebar { grid-row: 1 / -1; }
  .l-app:has(> .t2-topbar) .l-main { grid-column: 2; grid-row: 2; }
  .t2-topbar {
    display: flex;
    position: sticky;
    top: 0;
    z-index: calc(var(--l-z-pop) - 40);
    grid-column: 2;
    padding: 10px 34px;
    align-items: center;
    gap: 14px;
    border-bottom: 1px solid var(--l-border);
    background: color-mix(in srgb, var(--l-bg) 90%, transparent);
    -webkit-backdrop-filter: blur(18px) saturate(1.2);
    backdrop-filter: blur(18px) saturate(1.2);
  }
  .t2-topbar-spacer { flex: 1 1 auto; }
  /* Переключателя кабинетов здесь больше нет: он живёт в шапке меню, а вторая
     такая же кнопка на том же экране только дробила внимание. Топбар остался
     ради одной вещи — бейджа пробного периода. */
  .ledger .t2-topbar-trial {
    min-height: 34px;
    padding: 0 12px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    border: 1px solid color-mix(in srgb, var(--l-accent) 34%, var(--l-border));
    border-radius: var(--l-r-full);
    background: var(--l-accent-soft);
    color: var(--l-accent-ink);
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
  }
  .t2-topbar-trial .l-mono { font-size: 13px; }
  /* Последняя неделя пробного периода — тот же янтарь, что у остальных
     предупреждений приложения: цвет уже означает «скоро кончится». */
  .ledger .t2-topbar-trial.is-warn {
    border-color: color-mix(in srgb, var(--l-warn) 40%, var(--l-border));
    background: var(--l-warn-soft);
    color: var(--l-warn);
  }
  /* Полоса «осталось N дней» и бейдж говорят одно и то же. Там, где есть
     топбар, полоса лишняя; на телефоне топбара нет — там она и работает. */
  .l-app:has(> .t2-topbar) .l-banner--trial { display: none; }

  /* ── Задачи: панель чипов вместо ряда селектов ────────────────────────── */
  /* Карточку рисует сама форма фильтров: поле поиска обязано остаться её
     ребёнком (на телефоне форма целиком сворачивается в панель и поиск уезжает
     туда), поэтому отдельного контейнера у панели нет. */
  .t2-filters {
    margin: 0 0 16px;
    padding: 10px 12px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 9px;
    border: 1px solid var(--l-border);
    border-radius: var(--l-r-lg);
    background: var(--l-surface);
  }
  .t2-filters--scope { display: flex; }
  html.l-js .t2-filters-set { display: contents; }
  /* Селекты, ссылка просроченных и сброс на ПК заменены чипами — в карточке
     они были бы теми же фильтрами во второй раз. Поиск отсюда уехал в шапку,
     поэтому мобильная панель на ПК скрыта целиком. */
  html.l-js .l-task-filter-form .l-filter-panel { display: none; }

  /* Поиск в шапке страницы — рядом с «Настроить» и «+ Задача», как в заметках.
     Размеры не переопределяем: поле должно быть тем же самым. */
  .l-tasks-head-search:empty { display: none; }
  .l-topbar .l-tasks-search { flex: 0 1 auto; margin-right: 2px; }

  /* Переключатель панели фильтров. Свёрнутая панель отдаёт задачам её высоту,
     поэтому состояние запоминается: человек один раз решил, как ему работать. */
  .l-task-filter-toggle {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    min-height: 34px;
    padding: 0 10px;
    border: 1px solid var(--l-border);
    border-radius: var(--l-r-md);
    background: var(--l-surface);
    color: var(--l-text-2);
    font-size: 12.5px;
    cursor: pointer;
    transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
  }
  .l-task-filter-toggle:hover { border-color: var(--l-gray-300); color: var(--l-text); }
  .l-task-filter-toggle:focus-visible {
    outline: none;
    border-color: var(--l-accent);
    box-shadow: 0 0 0 3px var(--l-accent-soft);
  }
  /* Выбранные фильтры видны и при свёрнутой панели: иначе сужённый список
     выглядел бы как весь список. */
  .l-task-filter-toggle.is-set {
    border-color: transparent;
    background: var(--l-accent-soft);
    color: var(--l-accent-ink);
  }
  .l-task-filter-count {
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: var(--l-accent);
    color: var(--l-on-accent);
    font-size: 10.5px;
    font-weight: 600;
  }
  .l-task-filter-chev { flex: 0 0 auto; opacity: .6; transition: transform 140ms ease; }
  .l-task-filter-toggle[aria-expanded="false"] .l-task-filter-chev { transform: rotate(-90deg); }
  html.l-js .l-task-filter-form.is-collapsed { display: none; }
  /* Без JS сворачивать нечем — кнопка была бы обманом. */
  html:not(.l-js) .l-task-filter-toggle { display: none; }
  .t2-filters-label {
    color: var(--l-text-3);
    font-size: 10.5px;
    font-weight: 650;
    letter-spacing: .08em;
    text-transform: uppercase;
  }
  .t2-filters-sep { width: 1px; height: 24px; background: var(--l-hairline); }
  .ledger .t2-filters .t2-chip { min-height: 34px; font-size: 12.5px; }
  /* Сброс прижат к правому краю карточки: он относится ко всей строке, а не к
     соседнему чипу. */
  .ledger .t2-filters .t2-filters-reset { margin-left: auto; }
}

/* редактор строк услуг */
.l-items { width: 100%; border-collapse: collapse; }
.l-items th {
  padding: 0 8px 7px 0;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--l-text-3);
  text-align: left;
}
.l-items th.num { text-align: right; }
.l-items td { padding: 3px 8px 3px 0; vertical-align: middle; }
.l-items .l-input { padding: 7px 10px; font-size: 13px; }
.l-items .sum-cell {
  font-family: var(--l-mono);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  font-weight: 500;
  text-align: right;
  white-space: nowrap;
  padding-right: 0;
}
.l-row-del {
  appearance: none;
  border: 0;
  background: transparent;
  width: 28px; height: 28px;
  border-radius: var(--l-r-sm);
  color: var(--l-text-3);
  cursor: pointer;
  font-size: 14px;
}
.l-row-del:hover { background: var(--l-red-100); color: var(--l-danger); }
/* Итог документа. Метрики взяты у плитки .l-tile: крупное число карточки
   должно читаться так же, как крупные числа дашбордов, иначе «Итого» выглядит
   отдельным виджетом. Левый край — потому что глаз возвращается к началу
   строки таблицы, а не к правому полю: прижатый вправо итог терялся. */
.l-total {
  margin-top: 14px;
  padding-top: 13px;
  border-top: 1px solid var(--l-hairline);
}
.l-total-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--l-text-3);
  margin-bottom: 6px;
}
.l-total-value { font-size: 21px; font-weight: 500; }
/* Мета — «без НДС» и режим н/о: тихая строка, спорить с суммой не должна.
   Flex с зазором: бейдж режима вплотную к тексту читался как одно слово. */
.l-total-meta {
  margin-top: 5px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 12.5px;
  color: var(--l-text-3);
}

/* ============================================================================
   Баннеры (корзина, предупреждения)
   ========================================================================== */
.l-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px 16px;
  border: 1px solid #E8D5A8;
  background: var(--l-warn-soft);
  color: var(--l-warn);
  border-radius: var(--l-r-lg);
  font-size: 13.5px;
  margin-bottom: 14px;
}
.l-banner .l-spacer { flex: 1; }
/* Красная полоса: срок кончился и правки выключены. Это не предупреждение
   «скоро», а состояние кабинета, поэтому цвет опасности, а не янтарь.
   Граница выводится из токена темы — жёсткий #E8D5A8 базового баннера здесь
   дал бы песочную рамку вокруг красного. */
.l-banner--danger {
  border-color: color-mix(in srgb, var(--l-danger) 34%, var(--l-border));
  background: var(--l-danger-soft);
  color: var(--l-danger);
}
/* Промо-полоса: подарок, а не тревога — акцент темы вместо янтаря/красного.
   Только токены: в тёмных темах accent-soft/accent-ink уже согласованы. */
.l-banner--promo {
  border-color: color-mix(in srgb, var(--l-accent) 30%, var(--l-border));
  background: var(--l-accent-soft);
  color: var(--l-accent-ink);
}
.l-banner--promo strong { display: block; font-weight: 650; }

/* ============================================================================
   Bulk-бар (плавающий снизу)
   ========================================================================== */
.l-bulkbar {
  position: fixed;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px 9px 18px;
  background: var(--l-gray-950);
  color: #E4E6E8;
  border-radius: var(--l-r-full);
  box-shadow: 0 8px 30px rgba(23,25,29,.3);
  z-index: calc(var(--l-z-pop) + 10);
  font-size: 13px;
}
.l-bulkbar[hidden] { display: none; }
.l-bulkbar-summary {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.l-bulkbar .count { font-weight: 600; }
.l-bulkbar .l-btn {
  border-color: rgba(255,255,255,.16);
  background: transparent;
  color: #E4E6E8;
  padding: 6px 12px;
  font-size: 12.5px;
}
.l-bulkbar .l-btn:hover { background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.3); color: #fff; }
.l-bulkbar .l-btn--danger { color: #FCA5A5; }
.l-bulkbar .l-btn--danger:hover { background: rgba(179,38,30,.25); color: #FECACA; }

/* чекбоксы строк и общий выбор — одинаковы во всех браузерах и темах */
:where(.l-rowcheck, .l-rowcheck-master, #l-check-all) {
  appearance: none;
  -webkit-appearance: none;
  display: inline-grid;
  place-content: center;
  width: 16px;
  height: 16px;
  margin: 0;
  border: 1.5px solid var(--l-gray-400);
  border-radius: 4px;
  background: var(--l-surface);
  color: var(--l-on-accent);
  vertical-align: middle;
  cursor: pointer;
  transition: border-color 100ms ease, background 100ms ease, box-shadow 100ms ease;
}
:where(.l-rowcheck, .l-rowcheck-master, #l-check-all)::before {
  content: "";
  width: 4px;
  height: 8px;
  border: solid currentColor;
  border-width: 0 2px 2px 0;
  transform: translateY(-1px) rotate(45deg) scale(0);
  transition: transform 90ms ease;
}
:where(.l-rowcheck, .l-rowcheck-master, #l-check-all):hover {
  border-color: var(--l-accent);
}
:where(.l-rowcheck, .l-rowcheck-master, #l-check-all):checked,
:where(.l-rowcheck, .l-rowcheck-master, #l-check-all):indeterminate {
  border-color: var(--l-accent);
  background: var(--l-accent);
}
:where(.l-rowcheck, .l-rowcheck-master, #l-check-all):checked::before {
  transform: translateY(-1px) rotate(45deg) scale(1);
}
:where(.l-rowcheck, .l-rowcheck-master, #l-check-all):indeterminate::before {
  width: 8px;
  height: 2px;
  border: 0;
  border-radius: 1px;
  background: currentColor;
  transform: none;
}
:where(.l-rowcheck, .l-rowcheck-master, #l-check-all):focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--l-accent) 18%, transparent);
}

/* ============================================================================
   Модал подтверждения
   ========================================================================== */
.l-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(23, 25, 29, 0.45);
  backdrop-filter: blur(3px);
  z-index: calc(var(--l-z-pop) + 100);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  /* Подложка прокручивается сама — страховка на случай, если содержимое
     модалки не сможет ужаться (длинный список, крупный шрифт системы). */
  overflow-y: auto;
}
.l-modal {
  background: var(--l-surface);
  border-radius: var(--l-r-lg);
  box-shadow: var(--l-shadow-pop);
  padding: 22px;
  max-width: 400px;
  width: 100%;
  /* Базовый кламп, а не только для телефона: на низком окне (лендскейп, 400px
     высоты) модалка «Отправить на почту» центрировалась с отрицательным top —
     заголовок и кнопки уходили за экран без возможности прокрутки. */
  max-height: calc(100dvh - 40px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.l-modal h3 { margin: 0 0 8px; font-size: 15.5px; }
.l-modal p { margin: 0 0 18px; font-size: 13.5px; color: var(--l-text-2); }
.l-modal .actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 18px; }
.l-modal.l-task-create-modal {
  max-width: 520px;
  padding: 18px;
}
.l-task-create-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}
.l-modal .l-task-create-head h3 { margin: 0; }
.l-task-create-head .l-iconbtn { margin-left: auto; }
.l-task-create-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 44px;
  gap: 8px;
  align-items: stretch;
}
.l-task-create-row .l-input { width: 100%; min-width: 0; }
.l-task-create-submit {
  width: 44px;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  justify-content: center;
}
.ledger .l-btn--danger-solid { background: var(--l-danger); border-color: var(--l-danger); color: var(--l-on-danger); }
.ledger .l-btn--danger-solid:hover { background: var(--l-danger-ink); border-color: var(--l-danger-ink); color: var(--l-on-danger); }

/* ============================================================================
   Появление всплывающих слоёв
   ========================================================================== */
/* Поповеры, выпадающие меню, модалки и подложка шторки переключаются атрибутом
   hidden, то есть идут из display:none. @starting-style задаёт стартовый кадр
   такого перехода; браузеры без поддержки показывают слой сразу — как раньше.
   Переход объявлен ТОЛЬКО на видимом состоянии: при скрытии действует базовое
   правило без transition, поэтому закрытие остаётся мгновенным — на это
   рассчитывают click-outside и переоткрытие поповера на другой кнопке.
   Глобальный prefers-reduced-motion выключает transition целиком. */
.l-pop:not([hidden]),
.l-dd-menu:not([hidden]) {
  transition:
    opacity 130ms ease,
    transform 130ms ease,
    display 130ms allow-discrete;
}
@starting-style {
  .l-pop:not([hidden]),
  .l-dd-menu:not([hidden]) {
    opacity: 0;
    transform: translateY(-4px);
  }
}
.l-modal-overlay:not([hidden]) {
  transition: opacity 140ms ease, display 140ms allow-discrete;
}
@starting-style {
  .l-modal-overlay:not([hidden]) { opacity: 0; }
}
.l-modal-overlay:not([hidden]) .l-modal {
  transition: opacity 140ms ease, transform 140ms ease;
}
@starting-style {
  .l-modal-overlay:not([hidden]) .l-modal { opacity: 0; transform: scale(.98); }
}
.l-drawer-backdrop:not([hidden]) {
  transition: opacity 140ms ease, display 140ms allow-discrete;
}
@starting-style {
  .l-drawer-backdrop:not([hidden]) { opacity: 0; }
}

/* ============================================================================
   Неблокирующие уведомления
   ========================================================================== */
.l-toast-stack {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: calc(var(--l-z-pop) + 80);
  width: min(360px, calc(100vw - 24px));
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  pointer-events: none;
}
/* Попап секретной ссылки на телефоне доходит почти до низа экрана, а тост
   «Ссылка готова…» висит шесть секунд ровно над кнопками «Копировать» и
   «Отозвать». Пока попап открыт, поднимаем стопку тостов над ним: сообщение
   остаётся видимым, а действия — нажимаемыми. */
body:has(.l-note-share-pop:not([hidden])) .l-toast-stack,
body:has(.l-note-remind-pop:not([hidden])) .l-toast-stack,
body:has(.l-note-tags-pop:not([hidden])) .l-toast-stack {
  bottom: auto;
  top: calc(8px + env(safe-area-inset-top));
}
.l-toast {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 10px 10px 10px 14px;
  border: 1px solid color-mix(in srgb, var(--l-border) 65%, transparent);
  border-radius: var(--l-r-md);
  background: var(--l-gray-950);
  color: #F5F6F7;
  box-shadow: var(--l-shadow-pop);
  font-size: 13px;
  line-height: 1.35;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 160ms ease, transform 160ms ease;
  pointer-events: auto;
}
.l-toast.is-visible { opacity: 1; transform: translateY(0); }
.l-toast.is-leaving { opacity: 0; transform: translateY(8px); }
.l-toast.is-error { border-color: color-mix(in srgb, var(--l-danger) 65%, transparent); }
.l-toast-text { min-width: 0; flex: 1; }
.l-toast-action,
.l-toast-close {
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.l-toast-action {
  padding: 4px 6px;
  border-radius: var(--l-r-sm);
  color: #9FE3C5;
  font-weight: 600;
  white-space: nowrap;
}
.l-toast-action:hover,
.l-toast-action:focus-visible { background: rgba(255,255,255,.09); color: #C5F4DF; }
.l-toast-action:disabled { opacity: .55; cursor: wait; }
.l-toast-close {
  width: 26px;
  height: 26px;
  padding: 0;
  border-radius: 50%;
  color: #AEB4BC;
  font-size: 18px;
  line-height: 24px;
}
.l-toast-close:hover,
.l-toast-close:focus-visible { background: rgba(255,255,255,.09); color: #fff; }
.is-task-removing {
  opacity: 0 !important;
  transform: scale(.985);
  transition: opacity 150ms ease, transform 150ms ease !important;
  pointer-events: none !important;
}
@media (max-width: 640px) {
  .l-toast-stack { right: 12px; bottom: 12px; }
}

/* ============================================================================
   Загрузка файлов (карточка ИП)
   ========================================================================== */
.l-upload {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border: 1px dashed var(--l-gray-300);
  border-radius: var(--l-r-md);
  background: color-mix(in srgb, var(--l-surface-hover) 72%, var(--l-surface));
  transition: border-color 140ms ease, background 140ms ease, box-shadow 140ms ease;
}
.l-upload img { max-height: 44px; max-width: 120px; border-radius: 4px; }
.l-upload .meta { font-size: 12px; color: var(--l-text-3); flex: 1; }
.l-upload.is-dragover {
  border-color: var(--l-accent);
  background: color-mix(in srgb, var(--l-accent) 7%, var(--l-surface));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--l-accent) 18%, transparent);
}
.l-file-picker {
  position: relative;
  width: min(100%, 330px);
  min-width: 250px;
  min-height: 42px;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 5px 7px 5px 5px;
  border: 1px solid var(--l-border);
  border-radius: 11px;
  background: var(--l-surface);
  box-shadow: 0 1px 1px color-mix(in srgb, var(--l-text) 4%, transparent);
  transition: border-color 140ms ease, box-shadow 140ms ease, background 140ms ease;
}
.l-file-picker:focus-within {
  border-color: var(--l-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--l-accent) 13%, transparent);
}
.l-file-picker.is-selected {
  border-color: color-mix(in srgb, var(--l-accent) 32%, var(--l-border));
  background: color-mix(in srgb, var(--l-accent) 3%, var(--l-surface));
}
.l-file-native {
  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;
  opacity: 0 !important;
  pointer-events: none !important;
}
.l-file-choose {
  flex: 0 0 auto;
  min-height: 32px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 10px;
  border: 0;
  border-radius: 8px;
  background: var(--l-accent-soft);
  color: var(--l-accent-ink);
  font: inherit;
  font-size: 12px;
  font-weight: 650;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, transform 120ms ease;
}
.l-file-choose:hover {
  background: color-mix(in srgb, var(--l-accent) 16%, var(--l-surface));
}
.l-file-choose:active { transform: translateY(1px); }
.l-file-choose:focus-visible {
  outline: 2px solid var(--l-accent);
  outline-offset: 2px;
}
.l-file-choose svg,
.l-file-clear svg { pointer-events: none; }
.l-file-selection {
  min-width: 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.l-file-name {
  overflow: hidden;
  color: var(--l-text-3);
  font-size: 11.5px;
  line-height: 1.25;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-file-picker.is-selected .l-file-name {
  color: var(--l-text);
  font-weight: 550;
}
.l-file-size {
  color: var(--l-text-3);
  font-size: 9.5px;
  line-height: 1.2;
}
.l-file-clear {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--l-text-3);
  cursor: pointer;
}
.l-file-clear[hidden] { display: none; }
.l-file-clear:hover,
.l-file-clear:focus-visible {
  outline: none;
  background: var(--l-danger-soft);
  color: var(--l-danger);
}
@media (max-width: 720px) {
  .l-upload { align-items: flex-start; flex-wrap: wrap; }
  .l-file-picker { width: 100%; min-width: 0; }
}

/* карточки документов */
.l-inline-form { display: inline; }
.is-cancelled-page .l-panel { opacity: 0.72; }
.is-cancelled-page .l-panel:first-child { opacity: 1; }

/* ============================================================================
   Баланс группы договора + иконки отправки
   ========================================================================== */
.l-ct-balance {
  font-size: 11.5px;
  color: var(--l-text-3);
  white-space: nowrap;
}
.l-ct-ok {
  color: var(--l-accent);
  font-weight: 700;
  font-size: 13px;
  cursor: default;
}

/* иконка отправки: конверт / ЭДО */
.l-sent {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  color: var(--l-text-3);
  flex: 0 0 auto;
  cursor: default;
}
.l-sent--edo {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.05em;
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--l-accent-soft);
  color: var(--l-accent-ink);
}
.l-sent:hover, .l-sent:focus-visible { color: var(--l-text-2); }

/* Тултип по data-tip — рисуется JS-ом в position:fixed (не режется overflow-контейнерами) */
.l-tip {
  position: fixed;
  z-index: calc(var(--l-z-pop) + 50);
  padding: 6px 10px;
  border-radius: var(--l-r-sm);
  background: var(--l-gray-950);
  color: #E4E6E8;
  font-family: var(--l-font);
  font-size: 11.5px;
  font-weight: 500;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: var(--l-shadow-pop);
}
.l-tip::after {
  content: '';
  position: absolute;
  top: 100%;
  left: var(--tip-arrow, 50%);
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: var(--l-gray-950);
}
/* Появление без задержки, но не рывком: системный title ждал секунду, а резкий
   показ на каждом проходе мыши по рельсу дёргал глаз. */
.l-tip { animation: l-tip-in 120ms cubic-bezier(.2, .7, .3, 1) both; }
@keyframes l-tip-in {
  from { opacity: 0; transform: translateY(3px); }
  to { opacity: 1; transform: none; }
}
/* Подсказка пункта свёрнутого меню: справа от значка, стрелка смотрит на него,
   выезд из-под рельса подхватывает направление взгляда. */
.l-tip--right {
  animation-name: l-tip-in-right;
  font-size: 12px;
  padding: 7px 11px;
}
.l-tip--right::after {
  top: var(--tip-arrow, 50%);
  left: auto;
  right: 100%;
  transform: translateY(-50%);
  border-top-color: transparent;
  border-right-color: var(--l-gray-950);
}
@keyframes l-tip-in-right {
  from { opacity: 0; transform: translateX(-5px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .l-tip { animation-duration: 1ms; }
}

/* чекбокс в строке группового вида */
.l-doc .l-rowcheck { margin-right: 2px; flex: 0 0 auto; }

/* ============================================================================
   Кастомные дропдауны (.l-dd)
   ========================================================================== */
.l-dd { position: relative; display: inline-block; max-width: 100%; }
.l-dd--form { display: block; }
.l-dd .l-dd-native {
  position: absolute !important;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}
.l-dd-btn {
  appearance: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 30px 7px 12px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface);
  font: inherit;
  font-size: 13px;
  color: var(--l-text-2);
  cursor: pointer;
  max-width: 230px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  position: relative;
  transition: border-color 120ms ease, background 120ms ease;
  text-align: left;
}
.l-dd--form .l-dd-btn {
  display: flex;
  width: 100%;
  max-width: none;
  padding: 9px 32px 9px 12px;
  font-size: 13.5px;
  color: var(--l-text);
}
/* Подпись отдельным элементом: анонимный текстовый узел flex-кнопки не
   сжимается (min-width: auto) и вылезал под стрелку вместо многоточия. */
.l-dd-btn-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-dd-btn::after {
  content: '';
  position: absolute;
  right: 11px;
  top: 50%;
  width: 10px; height: 6px;
  transform: translateY(-50%);
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center;
  opacity: .6;
  transition: transform 120ms ease;
}
.l-dd-btn.is-open::after { transform: translateY(-50%) rotate(180deg); }
.l-dd-btn:hover { border-color: var(--l-gray-300); }
.l-dd-btn.is-set { color: var(--l-text); border-color: var(--l-gray-300); font-weight: 500; }
.l-dd-btn.is-open { border-color: var(--l-accent); }
/* Кнопка заменяет спрятанный select: выключенное поле должно и выглядеть
   выключенным, иначе тап по нему молча ничего не делает. */
.l-dd-btn:disabled,
.l-dd-btn:disabled.is-set {
  color: var(--l-text-3);
  border-color: var(--l-border);
  background: var(--l-surface);
  opacity: .62;
  cursor: default;
}
.l-dd-btn:disabled:hover { border-color: var(--l-border); }
.l-dd-menu {
  position: absolute;
  z-index: var(--l-z-pop);
  top: calc(100% + 5px);
  left: 0;
  min-width: 100%;
  max-width: 320px;
  background: var(--l-surface);
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  box-shadow: var(--l-shadow-pop);
  padding: 5px;
  max-height: 320px;
  overflow-y: auto;
}
.l-dd-list { max-height: 240px; overflow-y: auto; }
.l-dd-group {
  margin: 5px 6px 3px;
  padding: 6px 8px 4px;
  border-top: 1px solid var(--l-hairline);
  color: var(--l-text-3);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
}
.l-dd-group:first-child { margin-top: 0; border-top: 0; }
.l-dd-group[hidden] { display: none; }
.l-dd-item {
  display: block;
  width: 100%;
  appearance: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  border: 0;
  background: transparent;
  padding: 7px 10px 7px 28px;
  border-radius: var(--l-r-sm);
  font: inherit;
  font-size: 13px;
  color: var(--l-text);
  cursor: pointer;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  position: relative;
}
.l-dd-item[hidden] { display: none; }
.l-dd-item:hover { background: var(--l-gray-150); }
.l-dd-item.is-active { background: var(--l-accent-soft); color: var(--l-accent-ink); font-weight: 500; }
.l-dd-item.is-active::before {
  content: '';
  position: absolute;
  left: 9px; top: 50%;
  width: 10px; height: 6px;
  transform: translateY(-60%) rotate(-45deg);
  border-left: 1.8px solid currentColor;
  border-bottom: 1.8px solid currentColor;
}
.l-dd-search { padding: 3px 3px 7px; border-bottom: 1px solid var(--l-hairline); margin-bottom: 5px; }
.l-dd-search input {
  width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-sm);
  background: var(--l-surface);
  color: var(--l-text);
  font: inherit;
  font-size: 13px;
}
.l-dd-search input:focus { outline: none; border-color: var(--l-accent); box-shadow: 0 0 0 3px var(--l-accent-soft); }

/* ============================================================================
   Свёрнутый сайдбар
   ========================================================================== */
.l-sidebar-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 auto;
  appearance: none;
  border: 0;
  background: transparent;
  padding: 8px 10px;
  border-radius: var(--l-r-sm);
  color: var(--l-sidebar-text);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
}
.l-sidebar-toggle:hover { background: var(--l-sidebar-hover); color: var(--l-sidebar-strong); }
.l-sidebar-toggle svg { transition: transform 160ms ease; flex: 0 0 auto; }
html.l-collapsed .l-app { grid-template-columns: 72px 1fr; }
html.l-collapsed .l-sidebar { padding-left: 10px; padding-right: 10px; }
html.l-collapsed .l-nav-title,
html.l-collapsed .l-nav-item span,
html.l-collapsed .l-sidebar-toggle .lbl { display: none; }
/* Свёрнутая рельса: в шапке остаётся метка кабинета. Правила только для
   широких экранов — класс l-collapsed переживает поворот телефона в
   localStorage, и портретная ШТОРКА не должна получать свёрнутую шапку. */
@media (min-width: 721px) {
  html.l-collapsed .t2-tenant-head { justify-content: center; }
  html.l-collapsed .t2-tenant-home { flex: 0 0 auto; justify-content: center; padding: 7px; }
  html.l-collapsed .t2-tenant-head .t2-tenant-name,
  html.l-collapsed .t2-tenant-switch { display: none; }
}
html.l-collapsed .l-nav-item { justify-content: center; padding: 9px 0; }
html.l-collapsed .l-sidebar-toggle { justify-content: center; }
html.l-collapsed .l-sidebar-toggle svg { transform: rotate(180deg); }

/* свотч темы в поповере */
.l-theme-sw { display: inline-flex; gap: 3px; margin-right: 2px; flex: 0 0 auto; }
.l-theme-sw i {
  width: 11px; height: 11px;
  border-radius: 50%;
  border: 1px solid rgba(127,127,127,.35);
}

/* ============================================================================
   ТЕМЫ — только цветовые токены. Эталон разработки: default (Изумруд).
   Правило: переопределяем семантику + primitive-серые, использованные напрямую.
   ========================================================================== */

/* --- Астра · светлая, индиго ---------------------------------------------- */
html[data-theme="aster"] {
  --l-bg: #F5F6FA; --l-surface: #FFFFFF; --l-surface-hover: #F8F9FC;
  --l-border: #E4E6EF; --l-hairline: #EEF0F6;
  --l-text: #1A1C24; --l-text-2: #565B6B; --l-text-3: #8A8FA3;
  --l-accent: #4553C9; --l-accent-ink: #3641A8; --l-accent-soft: #E9EBFA;
  --l-on-accent: #fff; --l-on-danger: #fff; /* акцент тёмный — белый текст даёт 6.30:1 */
  --l-warn: #96660A; --l-warn-soft: #F9F1DC; --l-danger: #B3261E;
  --l-brass: #9BA3E8;
  --l-sidebar-bg: #FBFCFE; --l-sidebar-border: #E4E6EF; --l-sidebar-text: #5A5F72;
  --l-sidebar-strong: #1A1C24; --l-sidebar-title: #A7ABBD; --l-sidebar-hover: #EEF0F6;
  --l-sidebar-active-bg: #E9EBFA; --l-sidebar-active-tx: #3641A8;
  --l-gray-950: #14161F; --l-gray-300: #C7CAD8; --l-gray-150: #EEF0F6; --l-gray-100: #F5F6FA;
  --l-green-100: #E9EBFA; --l-green-600: #4553C9; --l-green-700: #3641A8;
}

/* --- Графит · тёмная, изумруд ---------------------------------------------- */
html[data-theme="graphite"] {
  --l-bg: #17191D; --l-surface: #1F2227; --l-surface-hover: #24272D;
  --l-border: #2E3238; --l-hairline: #282B31;
  --l-text: #E8EAEC; --l-text-2: #A6ABB2; --l-text-3: #767C84;
  --l-accent: #2FB68C; --l-accent-ink: #4CC9A2; --l-accent-soft: rgba(47,182,140,.16);
  /* Светлый акцент: белый текст дал бы 2.56:1. Чернила берём из собственного
     тёмного тона темы — 7.49:1 на акценте и 5.80:1 на опасной заливке. */
  --l-on-accent: #0D0F11; --l-on-danger: #0D0F11;
  --l-warn: #D9A94E; --l-warn-soft: rgba(217,169,78,.14); --l-danger: #E5655C;
  --l-danger-ink: #F08A82;
  --l-red-100: rgba(229,101,92,.15);
  --l-info: #7EA6FF;
  --l-brass: #C9A96A;
  --l-sidebar-bg: #101215; --l-sidebar-border: #23262B; --l-sidebar-text: #9CA1A7;
  --l-sidebar-strong: #F2F3F4; --l-sidebar-title: #5E646B; --l-sidebar-hover: rgba(255,255,255,.05);
  --l-sidebar-active-bg: rgba(47,182,140,.18); --l-sidebar-active-tx: #7ED9BC;
  --l-gray-950: #0D0F11; --l-gray-300: #4A5058; --l-gray-150: #282B31; --l-gray-100: #17191D;
  --l-green-100: rgba(47,182,140,.16); --l-green-600: #2FB68C; --l-green-700: #4CC9A2;
  --l-amber-100: rgba(217,169,78,.14); --l-amber-700: #D9A94E;
  --l-shadow-card: 0 1px 2px rgba(0,0,0,.3);
  --l-shadow-pop: 0 4px 24px rgba(0,0,0,.5), 0 1px 3px rgba(0,0,0,.4);
}

/* --- Полночь · тёмно-синяя, янтарь ----------------------------------------- */
html[data-theme="midnight"] {
  --l-bg: #101523; --l-surface: #171D2E; --l-surface-hover: #1C2335;
  --l-border: #262E45; --l-hairline: #20283C;
  --l-text: #E6E8F0; --l-text-2: #A3A9BE; --l-text-3: #6F7690;
  --l-accent: #E0A458; --l-accent-ink: #EAB979; --l-accent-soft: rgba(224,164,88,.15);
  /* Светлый акцент: белый текст дал бы 2.18:1. Чернила берём из собственного
     тёмного тона темы — 9.01:1 на акценте и 5.95:1 на опасной заливке. */
  --l-on-accent: #080B13; --l-on-danger: #080B13;
  --l-warn: #D9A94E; --l-warn-soft: rgba(217,169,78,.13); --l-danger: #E5655C;
  --l-danger-ink: #F08A82;
  --l-red-100: rgba(229,101,92,.15);
  --l-info: #7EA6FF;
  --l-brass: #E0A458;
  --l-sidebar-bg: #0B0F1A; --l-sidebar-border: #1D2438; --l-sidebar-text: #98A0B8;
  --l-sidebar-strong: #EFF1F7; --l-sidebar-title: #5A6280; --l-sidebar-hover: rgba(255,255,255,.05);
  --l-sidebar-active-bg: rgba(224,164,88,.16); --l-sidebar-active-tx: #EAB979;
  --l-gray-950: #080B13; --l-gray-300: #3E4763; --l-gray-150: #20283C; --l-gray-100: #101523;
  --l-green-100: rgba(224,164,88,.15); --l-green-600: #E0A458; --l-green-700: #EAB979;
  --l-amber-100: rgba(217,169,78,.13); --l-amber-700: #D9A94E;
  --l-shadow-card: 0 1px 2px rgba(0,0,0,.35);
  --l-shadow-pop: 0 4px 24px rgba(0,0,0,.55), 0 1px 3px rgba(0,0,0,.4);
}

/* --- Шалфей · спокойная оливково-зелёная ----------------------------------- */
html[data-theme="sage"] {
  --l-bg: #F3F5EF; --l-surface: #FDFDFB; --l-surface-hover: #F7F8F3;
  --l-border: #E3E6DC; --l-hairline: #ECEEE6;
  --l-text: #232A24; --l-text-2: #5C655D; --l-text-3: #8B9389;
  --l-accent: #4A7856; --l-accent-ink: #3A6144; --l-accent-soft: #E5EEE5;
  --l-on-accent: #fff; --l-on-danger: #fff; /* акцент тёмный — белый текст даёт 5.11:1 */
  --l-warn: #9A6B00; --l-warn-soft: #F7F0DC; --l-danger: #A8453A;
  --l-brass: #B7A77E;
  --l-sidebar-bg: #FBFCF8; --l-sidebar-border: #E3E6DC; --l-sidebar-text: #5C655D;
  --l-sidebar-strong: #232A24; --l-sidebar-title: #A2A99F; --l-sidebar-hover: #ECEEE6;
  --l-sidebar-active-bg: #E5EEE5; --l-sidebar-active-tx: #3A6144;
  --l-gray-950: #222922; --l-gray-300: #C4C9BC; --l-gray-150: #ECEEE6; --l-gray-100: #F3F5EF;
  --l-green-100: #E5EEE5; --l-green-600: #4A7856; --l-green-700: #3A6144;
}

/* --- Пион · тёплая пудра + малина-бордо ------------------------------------ */
html[data-theme="rose"] {
  --l-bg: #FAF5F4; --l-surface: #FFFFFF; --l-surface-hover: #FBF7F6;
  --l-border: #EFE2E1; --l-hairline: #F5EBEA;
  --l-text: #2B2124; --l-text-2: #6E5C61; --l-text-3: #9C8A8F;
  --l-accent: #A64D64; --l-accent-ink: #8C3C52; --l-accent-soft: #F6E7EB;
  --l-on-accent: #fff; --l-on-danger: #fff; /* акцент тёмный — белый текст даёт 5.43:1 */
  --l-warn: #9A6B00; --l-warn-soft: #F9F1DC; --l-danger: #B3261E;
  --l-brass: #D4A5A0;
  --l-sidebar-bg: #FFFDFD; --l-sidebar-border: #EFE2E1; --l-sidebar-text: #6E5C61;
  --l-sidebar-strong: #2B2124; --l-sidebar-title: #B3A3A8; --l-sidebar-hover: #F5EBEA;
  --l-sidebar-active-bg: #F6E7EB; --l-sidebar-active-tx: #8C3C52;
  --l-gray-950: #2A1F23; --l-gray-300: #D9C8C7; --l-gray-150: #F5EBEA; --l-gray-100: #FAF5F4;
  --l-green-100: #F6E7EB; --l-green-600: #A64D64; --l-green-700: #8C3C52;
}

/* --- Сталь · строгая холодная светлая -------------------------------------- */
html[data-theme="slate"] {
  --l-bg: #F1F3F6; --l-surface: #FFFFFF; --l-surface-hover: #F6F8FA;
  --l-border: #DEE3E9; --l-hairline: #E9EDF1;
  --l-text: #16191D; --l-text-2: #4C555F; --l-text-3: #7E8892;
  --l-accent: #33628C; --l-accent-ink: #274E71; --l-accent-soft: #E4ECF4;
  --l-on-accent: #fff; --l-on-danger: #fff; /* акцент тёмный — белый текст даёт 6.43:1 */
  --l-warn: #96660A; --l-warn-soft: #F5EEDA; --l-danger: #B3261E;
  --l-brass: #8FA6BC;
  --l-sidebar-bg: #FAFBFC; --l-sidebar-border: #DEE3E9; --l-sidebar-text: #4C555F;
  --l-sidebar-strong: #16191D; --l-sidebar-title: #99A2AC; --l-sidebar-hover: #E9EDF1;
  --l-sidebar-active-bg: #E4ECF4; --l-sidebar-active-tx: #274E71;
  --l-gray-950: #14181D; --l-gray-300: #C0C8D1; --l-gray-150: #E9EDF1; --l-gray-100: #F1F3F6;
  --l-green-100: #E4ECF4; --l-green-600: #33628C; --l-green-700: #274E71;
}

/* --- Карбон · тёмный, медно-оранжевый -------------------------------------- */
html[data-theme="carbon"] {
  --l-bg: #151719; --l-surface: #1C1F22; --l-surface-hover: #212429;
  --l-border: #2C3036; --l-hairline: #25282D;
  --l-text: #E9EAEB; --l-text-2: #A7ABB0; --l-text-3: #757A81;
  --l-accent: #E07A3F; --l-accent-ink: #EC9563; --l-accent-soft: rgba(224,122,63,.15);
  /* Светлый акцент: белый текст дал бы 2.99:1. Чернила берём из собственного
     тёмного тона темы — 6.52:1 на акценте и 5.89:1 на опасной заливке. */
  --l-on-accent: #0B0D0E; --l-on-danger: #0B0D0E;
  --l-warn: #D9A94E; --l-warn-soft: rgba(217,169,78,.13); --l-danger: #E5655C;
  --l-danger-ink: #F08A82;
  --l-red-100: rgba(229,101,92,.15);
  --l-info: #7EA6FF;
  --l-brass: #E07A3F;
  --l-sidebar-bg: #0F1113; --l-sidebar-border: #212429; --l-sidebar-text: #9599A0;
  --l-sidebar-strong: #F0F1F2; --l-sidebar-title: #5A5F66; --l-sidebar-hover: rgba(255,255,255,.05);
  --l-sidebar-active-bg: rgba(224,122,63,.16); --l-sidebar-active-tx: #EC9563;
  --l-gray-950: #0B0D0E; --l-gray-300: #474C54; --l-gray-150: #25282D; --l-gray-100: #151719;
  --l-green-100: rgba(224,122,63,.15); --l-green-600: #E07A3F; --l-green-700: #EC9563;
  --l-amber-100: rgba(217,169,78,.13); --l-amber-700: #D9A94E;
  --l-shadow-card: 0 1px 2px rgba(0,0,0,.35);
  --l-shadow-pop: 0 4px 24px rgba(0,0,0,.55), 0 1px 3px rgba(0,0,0,.4);
}

/* --- Галочка чек-листа заметок --------------------------------------------
   Она рисуется data-URI-картинкой поверх заливки акцентом, а внутри URL
   переменная не раскрывается — цвет обводки приходится зашивать в саму
   ссылку. Поэтому токеном делаем всю ссылку и переопределяем её ровно в тех
   трёх тёмных темах, где на светлом акценте нужны тёмные чернила. */
:root {
  --l-tick-mark: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5l3 3L12.5 5' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
html[data-theme="graphite"] {
  --l-tick-mark: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5l3 3L12.5 5' fill='none' stroke='%230D0F11' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
html[data-theme="midnight"] {
  --l-tick-mark: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5l3 3L12.5 5' fill='none' stroke='%23080B13' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
html[data-theme="carbon"] {
  --l-tick-mark: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5l3 3L12.5 5' fill='none' stroke='%230B0D0E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* --- Настройка колонок таблицы (кнопка «Колонки») ------------------------- */
.l-colpicker { position: relative; }
.l-colpicker summary { list-style: none; cursor: pointer; user-select: none; }
.l-colpicker summary::-webkit-details-marker { display: none; }
.l-colpicker-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 60;
  min-width: 240px;
  padding: 12px 14px;
  background: var(--l-surface);
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  box-shadow: var(--l-shadow-pop);
}
.l-colpicker-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  font-size: 13px;
}
.l-colpicker-row label { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.l-colpicker-row .l-cta { padding: 0 4px; }

/* --- Режим «во всю ширину» (класс l-wide на <html>) ----------------------- */
.l-wide .l-main { max-width: none; }

/* --- Онбординг-карточка (пустые состояния модулей, «быстрый старт») -------- */
.l-onboard {
  max-width: 560px;
  margin: 48px auto 0;
  padding: 36px 40px 32px;
  background: var(--l-surface);
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  box-shadow: var(--l-shadow-card);
}
.l-onboard-icon {
  width: 52px;
  height: 52px;
  margin: 0 auto 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 14px;
  background: var(--l-accent-soft);
  color: var(--l-accent-ink);
}
.l-onboard-title {
  margin: 0;
  text-align: center;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.l-onboard-sub {
  margin: 6px 0 24px;
  text-align: center;
  color: var(--l-text-3);
  font-size: 13.5px;
}
.l-onboard-steps {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.l-onboard-step {
  position: relative;
  display: flex;
  gap: 14px;
  padding: 10px 0;
}
/* соединительная линия между номерами шагов */
.l-onboard-step:not(:last-child)::before {
  content: '';
  position: absolute;
  left: 13px;
  top: 40px;
  bottom: -8px;
  width: 2px;
  background: var(--l-gray-150);
}
.l-onboard-num {
  flex: none;
  width: 27px;
  height: 27px;
  margin-top: 1px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--l-accent);
  color: var(--l-on-accent);
  font-size: 13px;
  font-weight: 600;
}
.l-onboard-step .t { font-weight: 600; font-size: 13.5px; margin-bottom: 2px; }
.l-onboard-step .d { color: var(--l-text-2); font-size: 13px; line-height: 1.55; }
.l-onboard-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
  margin-top: 26px;
}
@media (max-width: 960px) {
  .l-onboard { padding: 26px 20px; margin-top: 20px; }
  .l-onboard-actions { flex-direction: column; align-items: stretch; text-align: center; }
}

/* --- Доска: управление этапами --------------------------------------------- */
.l-dotbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 6px;
  margin: -6px;
  border: 0;
  background: transparent;
  cursor: pointer;
  border-radius: 50%;
}
.l-dotbtn:hover { background: var(--l-gray-150); }
.l-colmenu {
  opacity: 0;
  font-size: 15px;
  line-height: 1;
  padding: 0 4px;
  transition: opacity .12s;
}
.l-board-head:hover .l-colmenu,
.l-colmenu:focus-visible { opacity: 1; }
.l-board-addcol {
  flex: 0 0 170px;
  padding: 9px 12px;
  border: 1px dashed var(--l-border);
  border-radius: var(--l-r-lg);
  background: transparent;
  color: var(--l-text-3);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  text-align: center;
}
.l-board-addcol:hover { color: var(--l-text-2); border-color: var(--l-gray-300); background: var(--l-gray-100); }
.l-board-mobile-tabs { display: none; }

@media (max-width: 720px) {
  .l-task-empty { min-height: 390px; padding: 46px 20px 26px; }
  .l-task-empty h2 { font-size: 21px; }
  .l-task-empty-actions { width: 100%; flex-direction: column; }
  .l-task-empty-actions .l-btn { justify-content: center; }
  /* «По этим условиям задач нет»: «Сбросить фильтры» и «+ Новая задача» —
     две равные кнопки в один ряд, а не крестик над большой кнопкой. */
  .l-task-empty--filtered .l-task-empty-actions { flex-direction: row; }
  .l-task-empty--filtered .l-task-empty-actions .l-btn {
    flex: 1 1 0;
    min-width: 0;
    min-height: 44px;
  }
  .l-task-empty-guide { grid-template-columns: 1fr; margin-top: 30px; }
  .l-task-empty-step strong,
  .l-task-empty-step small { white-space: normal; }
  .l-tgroup.is-empty { grid-template-columns: 1fr; gap: 2px; }
  .l-tgroup.is-empty .l-inline-add-btn { text-align: left; }
}

/* палитра: слот = кружок-кнопка (клик — выбрать цвет);
   мини-пипетка в углу (hover) перекрашивает сам слот */
.l-piprow { display: flex; gap: 9px; flex-wrap: wrap; align-items: center; }
.l-pop-form.l-piprow { padding: 9px 12px; }
.l-pipwrap {
  position: relative;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid transparent;
  flex: none;
}
.l-pipwrap.is-active { border-color: var(--l-text); }
.l-pip-btn {
  position: absolute;
  inset: 0;
  border: 0;
  border-radius: 50%;
  background: var(--pip-c);
  cursor: pointer;
  padding: 0;
}
.l-pip-input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.l-pip-edit {
  position: absolute;
  right: -5px;
  top: -5px;
  width: 15px;
  height: 15px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  /* Кружок залит цветом текста, значит глиф должен быть цветом полотна:
     в тёмных темах --l-text светлый и белый карандаш пропадал. */
  background: var(--l-text);
  color: var(--l-surface);
  cursor: pointer;
  padding: 0;
  opacity: 0;
  transition: opacity .12s;
  box-shadow: 0 1px 3px rgba(0,0,0,.35);
}
.l-pipwrap:hover .l-pip-edit,
.l-pip-edit:focus-visible { opacity: 1; }

/* --- Отступы бейджей и формы-гриды справочников ----------------------------- */
/* бейдж после любого элемента/текста не липнет к нему */
* + .l-badge { margin-left: 4px; }
.l-grid3--form { gap: 10px 18px; align-items: end; }
.l-formcol { display: flex; align-items: center; gap: 16px; }
.l-iconbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  padding: 4px;
  border-radius: var(--l-r-sm);
  color: var(--l-text-3);
  cursor: pointer;
}
.l-iconbtn:hover { color: var(--l-text); background: var(--l-gray-100); }
.l-iconbtn--danger:hover { color: var(--l-danger); background: var(--l-danger-soft, var(--l-gray-100)); }
.l-drag-handle { cursor: grab; }
.l-row-dragging { opacity: .5; }

/* --- Редакторы справочников (этапы, участники, теги, категории) -------------- */
/* Кружок цвета и аватар живут в одной ячейке с названием: на десктопе это
   связывает цвет с именем, на телефоне карточка получает один заголовок. */
.l-rows-editor-name {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  min-width: 0;
}
.l-rows-editor-name > strong { min-width: 0; }
/* во время инлайн-переименования поле занимает всю свободную ширину ячейки */
.l-rows-editor-name > strong:has(.l-input) { flex: 1 1 auto; }
.l-rows-editor-name .l-badge { margin-left: 0; }
.l-rows-editor .l-status-dot { width: 14px; height: 14px; }
.l-rows-editor-slot { width: 30px; }

/* Порядок категорий операций */
.l-cat-table .l-cat-group + .l-cat-group .l-cat-parent td {
  border-top: 1px solid var(--l-hairline);
}
.l-cat-table .l-cat-parent td {
  background: color-mix(in srgb, var(--l-gray-100) 38%, transparent);
}
.l-cat-table .l-cat-child-name {
  padding-left: 22px;
  color: var(--l-text-2);
}
.l-cat-table .l-cat-child-handle { color: var(--l-text-3); }
.l-cat-table .l-cat-group.l-row-dragging,
.l-cat-table .l-cat-child.l-row-dragging {
  opacity: .52;
  filter: saturate(.72);
}
.l-cat-table:has(.l-row-dragging),
.l-cat-table:has(.l-row-dragging) * {
  cursor: grabbing !important;
}
.l-cat-table.is-saving,
.l-cat-table .is-saving { pointer-events: none; }
.l-checkitem [data-check-title] { cursor: text; }
.l-checkitem .l-input { flex: 1; }

/* --- Календарь задач -------------------------------------------------------- */
.l-calbar { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }
.l-caltitle { margin-left: 10px; font-size: 15px; }
.l-cal-month { overflow: hidden; }
.l-cal-dow {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  border-bottom: 1px solid var(--l-border);
  font-size: 11.5px;
  color: var(--l-text-3);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.l-cal-dow span { padding: 8px 10px; }
.l-cal-week {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  width: 100%;
  min-width: 0;
}
.l-cal-week + .l-cal-week { border-top: 1px solid var(--l-border); }
.l-cal-day {
  position: relative;
  min-width: 0;
  min-height: 108px;
  padding: 6px 6px 26px;
  border-right: 1px solid var(--l-border);
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: stretch;
  overflow: hidden;
}
.l-cal-day:last-child { border-right: 0; }
.l-cal-day.is-other { background: var(--l-gray-100); }
.l-cal-day.is-other .l-cal-daynum { opacity: .45; }
.l-cal-day.is-today .l-cal-daynum {
  background: var(--l-accent);
  color: var(--l-on-accent);
  border-radius: 50%;
}
.l-cal-daynum {
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 2px;
}
.l-calchip {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 2px 7px;
  border-radius: var(--l-r-sm);
  background: color-mix(in srgb, var(--chip-c) 14%, var(--l-surface));
  font-size: 12px;
  cursor: pointer;
  overflow: hidden;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  box-sizing: border-box;
}
.l-calchip .n { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.l-calchip .t { font-size: 11px; color: var(--l-text-2); flex: none; }
.l-calchip.is-done { opacity: .55; }
.l-calchip.is-done .n { text-decoration: line-through; }
.l-calchip.is-overdue { background: color-mix(in srgb, var(--l-danger) 13%, var(--l-surface)); }
.l-calchip.is-overdue .t { color: var(--l-danger); font-weight: 600; }
.l-calchip.is-cal-dragging { opacity: .5; pointer-events: none; }
.l-cal-more,
.l-cal-mobile-days { display: none; }
/* Месяц на телефоне: точки вместо текстовых плашек и список выбранного дня.
   Плашка 43×17 с шрифтом 9px нечитаема, а «+» в 25px не поймать пальцем —
   разметку строит tasks-cal.js, поэтому на широком экране всё как было. */
.l-cal-dots,
.l-cal-daylist { display: none; }
body.is-task-cal-dragging,
body.is-task-cal-dragging * { cursor: grabbing !important; }
.l-cal-add {
  position: absolute;
  left: 6px;
  bottom: 4px;
  border: 0;
  background: transparent;
  color: var(--l-text-3);
  cursor: pointer;
  font-size: 14px;
  padding: 0 5px;
  border-radius: var(--l-r-sm);
  opacity: 0;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
  transition: opacity 120ms ease, background 120ms ease;
}
.l-cal-add-label {
  max-width: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-width 140ms ease, opacity 120ms ease;
}
.l-cal-day.is-cal-create-hover,
.l-cal-alldaycell.is-cal-create-hover {
  background: color-mix(in srgb, var(--l-accent) 7%, transparent);
  cursor: cell;
}
.l-cal-day.is-cal-create-hover .l-cal-add,
.l-cal-alldaycell.is-cal-create-hover .l-cal-add,
.l-cal-add:focus-visible { opacity: 1; }
.l-cal-day.is-cal-create-hover .l-cal-add-label,
.l-cal-alldaycell.is-cal-create-hover .l-cal-add-label,
.l-cal-add:focus-visible .l-cal-add-label { max-width: 64px; opacity: 1; }
.l-cal-add:hover { background: var(--l-gray-150); color: var(--l-text); }
.l-cal-dropover { outline: 2px solid var(--l-accent); outline-offset: -2px; }

/* сетка часов (неделя/день) */
/* overflow: visible обязателен — иначе сетка сама становится скролл-портом,
   и липкая шапка дней прилипает к ней, а не к странице. Горизонтальной
   прокрутки у календаря нет: колонки — minmax(0, 1fr) и всегда ужимаются. */
.l-cal-grid { overflow: visible; }
.l-cal-grid-head, .l-cal-allday, .l-cal-grid-body {
  display: grid;
  grid-template-columns: 64px repeat(auto-fit, minmax(0, 1fr));
}
/* Подписи дней остаются на виду: сетка суток выше экрана, и при прокрутке
   страницы колонки теряли свои даты — было не понять, в каком дне событие. */
.l-cal-grid-head {
  position: sticky;
  top: 0;
  z-index: 4;
  background: var(--l-surface);
  border-radius: var(--l-r-lg) var(--l-r-lg) 0 0;
}
.l-cal-colhead {
  padding: 8px 10px;
  font-size: 12.5px;
  font-weight: 600;
  border-left: 1px solid var(--l-border);
}
.l-cal-colhead.is-today { color: var(--l-accent-ink); }
.l-cal-allday { border-top: 1px solid var(--l-border); border-bottom: 1px solid var(--l-border); }
.l-cal-grid.is-cal-dragging .l-cal-allday {
  background: color-mix(in srgb, var(--l-accent) 5%, transparent);
}
.l-cal-gutter-label { font-size: 11px; color: var(--l-text-3); padding: 6px 8px; }
.l-cal-alldaycell {
  position: relative;
  min-height: 44px;
  padding: 4px 4px 4px 6px;
  border-left: 1px solid var(--l-border);
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.l-cal-alldaycell .l-cal-add { position: static; align-self: flex-start; }
.l-cal-scroll {
  height: calc(var(--cal-window-hours) * 48px);
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
}
/* Двойная прокрутка: на невысоком экране сетка начиналась ниже сгиба, и до
   вечерних часов приходилось сначала листать страницу, потом саму сетку.
   Ограничиваем внутренний скроллер видимой высотой — хватает одного жеста
   внутри сетки. max() не даёт полосе схлопнуться на совсем низком окне. */
@media (max-width: 720px), (max-height: 620px) {
  .l-cal-scroll { max-height: max(190px, calc(100dvh - 210px)); }
}
.l-cal-hourlabel {
  height: 48px;
  font-size: 10.5px;
  color: var(--l-text-3);
  text-align: right;
  padding: 3px 8px 0 0;
  box-sizing: border-box;
}
.l-cal-col {
  position: relative;
  border-left: 1px solid var(--l-border);
  background-image: repeating-linear-gradient(to bottom, var(--l-border) 0 1px, transparent 1px 48px);
  background-position: 0 0;
  cursor: cell;
}
.l-cal-col.is-today { background-color: color-mix(in srgb, var(--l-accent) 4%, transparent); }
.l-cal-create-preview {
  position: absolute;
  left: 4px;
  width: calc(100% - 8px);
  z-index: 1;
  padding: 5px 8px;
  border: 1px dashed color-mix(in srgb, var(--l-accent) 70%, var(--l-border));
  border-radius: var(--l-r-sm);
  background: color-mix(in srgb, var(--l-accent) 11%, var(--l-surface));
  color: var(--l-accent-ink);
  font-size: 11.5px;
  font-weight: 600;
  pointer-events: none;
  overflow: hidden;
}
.l-cal-grid.is-cal-dragging .l-cal-create-preview { display: none; }
.l-calblock {
  position: absolute;
  left: 4px;
  width: calc(100% - 8px);
  height: max(18px, calc(var(--cal-event-height, 48px) - 3px));
  border-radius: var(--l-r-sm);
  background: color-mix(in srgb, var(--chip-c) 18%, var(--l-surface));
  padding: 3px 7px;
  font-size: 12px;
  overflow: hidden;
  cursor: grab;
  z-index: 2;
}
.l-calblock .t { display: block; font-size: 10.5px; color: var(--l-text-2); }
.l-calblock .n { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.l-calblock.is-done { opacity: .55; }
.l-calblock.is-overdue { background: color-mix(in srgb, var(--l-danger) 15%, var(--l-surface)); }
.l-calblock.is-overdue .t { color: var(--l-danger); font-weight: 600; }
.l-calblock.is-cal-dragging { opacity: .7; z-index: 5; box-shadow: var(--l-shadow-pop); pointer-events: none; }
.l-calchip.is-cal-revealed,
.l-calblock.is-cal-revealed { animation: l-cal-reveal 1.2s ease-out; }
.l-cal-drag-ghost {
  position: fixed !important;
  z-index: 1000 !important;
  pointer-events: none !important;
  margin: 0 !important;
  overflow: hidden !important;
  clip-path: inset(0 round var(--l-r-sm));
  -webkit-clip-path: inset(0 round var(--l-r-sm));
  -webkit-mask-image: -webkit-radial-gradient(white, black);
  opacity: .94;
  box-shadow: var(--l-shadow-pop);
  transform: rotate(.7deg);
  cursor: grabbing;
  transition: width 100ms ease, height 100ms ease;
}
@keyframes l-cal-reveal {
  0%, 35% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--l-accent) 55%, transparent); }
  100% { box-shadow: 0 0 0 0 transparent; }
}
.l-cal-resize {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 7px;
  cursor: ns-resize;
}
.l-pop:has(.l-pop-time-editor) { min-width: 310px; }
.l-pop-time-editor { padding: 7px 9px 9px; }
.l-pop-time-fields {
  display: grid;
  grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
  gap: 8px;
}
.l-pop-time-field { position: relative; min-width: 0; }
.l-pop-time-label {
  display: block;
  margin: 0 0 5px 2px;
  color: var(--l-text-3);
  font-size: 10.5px;
  font-weight: 600;
}
.l-pop-time-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  min-height: 39px;
  padding: 8px 11px;
  border: 1px solid var(--l-border);
  border-radius: 10px;
  background: var(--l-surface);
  color: var(--l-text-3);
  font-size: 14px;
  letter-spacing: .02em;
  cursor: pointer;
  transition: border-color 130ms ease, box-shadow 130ms ease, color 130ms ease, background 130ms ease;
}
.l-pop-time-trigger:hover {
  border-color: color-mix(in srgb, var(--l-accent) 38%, var(--l-border));
  background: color-mix(in srgb, var(--l-accent) 4%, var(--l-surface));
}
.l-pop-time-trigger:focus-visible,
.l-pop-time-trigger.is-open {
  outline: none;
  border-color: var(--l-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--l-accent) 14%, transparent);
}
.l-pop-time-trigger.is-set { color: var(--l-text); }
.l-pop-time-clock {
  position: relative;
  flex: 0 0 15px;
  width: 15px;
  height: 15px;
  border: 1.5px solid currentColor;
  border-radius: 50%;
}
.l-pop-time-clock::before,
.l-pop-time-clock::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 3px;
  width: 1.5px;
  height: 4px;
  border-radius: 1px;
  background: currentColor;
  transform-origin: 50% 100%;
}
.l-pop-time-clock::after {
  transform: rotate(120deg);
}
/* Меню часов — такой же плавающий слой, как календарь: fixed + расчёт позиции
   в ledger.js. Абсолютное позиционирование внутри поля обрезалось прокруткой
   поповера и уезжало за нижнюю границу окна (в лендскейпе «Готово» было
   недостижимо). z-index как у календаря: меню открывается и внутри модалки. */
.l-pop-clock-menu {
  position: fixed;
  z-index: calc(var(--l-z-pop) + 140);
  width: 236px;
  padding: 9px;
  border: 1px solid var(--l-border);
  border-radius: 13px;
  background: var(--l-surface);
  box-shadow: var(--l-shadow-pop);
  max-height: calc(100dvh - 16px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.l-clock-quicks {
  display: grid;
  grid-template-columns: 1.25fr repeat(3, 1fr);
  gap: 5px;
  margin-bottom: 8px;
}
.l-clock-quick {
  min-width: 0;
  padding: 6px 4px;
  border: 0;
  border-radius: 8px;
  background: var(--l-surface-2);
  color: var(--l-text-2);
  font: inherit;
  font-size: 10.5px;
  cursor: pointer;
}
.l-clock-quick:hover,
.l-clock-quick:focus-visible {
  outline: none;
  background: color-mix(in srgb, var(--l-accent) 11%, var(--l-surface-2));
  color: var(--l-accent);
}
.l-clock-columns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 7px;
}
.l-clock-column {
  min-width: 0;
  border: 1px solid var(--l-border-soft);
  border-radius: 10px;
  overflow: hidden;
  background: var(--l-surface-2);
}
.l-clock-heading {
  padding: 6px 8px 5px;
  border-bottom: 1px solid var(--l-border-soft);
  color: var(--l-text-3);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-align: center;
  text-transform: uppercase;
}
.l-clock-list {
  /* На низком окне колонки часов и минут ужимаются, чтобы «Готово» осталось
     на экране без вложенной прокрутки меню. Точную высоту под свободное место
     досчитывает ledger.js и кладёт в --l-clock-list-h. */
  height: var(--l-clock-list-h, clamp(96px, 24dvh, 146px));
  padding: 4px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}
.l-clock-item {
  display: block;
  width: 100%;
  padding: 6px 4px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--l-text-2);
  font-size: 12.5px;
  text-align: center;
  cursor: pointer;
}
.l-clock-item:hover,
.l-clock-item:focus-visible {
  outline: none;
  background: color-mix(in srgb, var(--l-accent) 8%, transparent);
  color: var(--l-text);
}
.l-clock-item.is-active {
  background: var(--l-accent);
  color: var(--l-on-accent);
  font-weight: 700;
}
.l-clock-done {
  width: 100%;
  margin-top: 8px;
  padding: 7px 8px;
  border: 0;
  border-radius: 9px;
  background: color-mix(in srgb, var(--l-accent) 10%, var(--l-surface));
  color: var(--l-accent);
  font: inherit;
  font-size: 11.5px;
  font-weight: 650;
  cursor: pointer;
}
.l-clock-done:hover,
.l-clock-done:focus-visible {
  outline: none;
  background: color-mix(in srgb, var(--l-accent) 16%, var(--l-surface));
}
.l-pop-time-field .l-dd { width: 100%; }
.l-pop-time-field .l-dd-btn {
  min-height: 39px;
  width: 100%;
  max-width: none;
  padding-top: 8px;
  padding-bottom: 8px;
  color: var(--l-text);
  font-size: 13px;
}
.l-pop-time-field .l-dd-menu { min-width: 170px !important; }
.l-pop-time-help {
  margin: 7px 2px 0;
  color: var(--l-text-3);
  font-size: 10.5px;
}
.l-pop-time-error {
  margin: 6px 2px 0;
  color: var(--l-danger);
  font-size: 11px;
}
.l-pop-time-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 9px;
}
.l-pop-time-actions .l-btn { padding: 6px 11px; font-size: 12.5px; }

/* --- Повторяющиеся задачи ---------------------------------------------------- */
.l-recur-row.is-paused { opacity: .55; }
.l-table tbody tr.l-recur-row:focus-visible {
  outline: 2px solid var(--l-accent);
  outline-offset: -3px;
}
.l-recur-title {
  color: var(--l-text);
  font-weight: 400;
}
.l-recur-project.is-set {
  padding-inline: 10px;
  border-color: transparent;
  background: transparent;
  color: var(--l-text);
}
.l-recur-project.is-set:hover,
.l-recur-project.is-set:focus-visible {
  padding-inline: 10px;
  border-color: color-mix(in srgb, var(--l-accent) 45%, var(--l-border));
  background: var(--l-accent-soft);
  color: var(--l-accent-ink);
}
.l-modal.l-recur-modal {
  width: min(720px, calc(100vw - 32px));
  max-width: 720px;
  margin: auto 0;
  padding: 0;
}
.l-recur-modal-overlay {
  align-items: flex-start;
  overflow-y: auto;
}
.l-recur-modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  padding: 22px 26px 18px;
  border-bottom: 1px solid var(--l-hairline);
}
.l-recur-modal-kicker,
.l-recur-section-title {
  color: var(--l-text-3);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.l-modal.l-recur-modal .l-recur-modal-head h3 {
  margin: 4px 0 3px;
  color: var(--l-text);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -.02em;
}
.l-modal.l-recur-modal .l-recur-modal-head p {
  margin: 0;
  color: var(--l-text-3);
  font-size: 12.5px;
}
.l-recur-modal-close {
  flex: 0 0 auto;
  margin: -4px -6px 0 0;
  font-size: 15px;
}
.l-recur-modal-body { padding: 16px 26px 18px; }
.l-recur-section + .l-recur-section {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--l-hairline);
}
.l-recur-section-title { margin-bottom: 9px; }
.ledger .l-recur-modal .l-label {
  margin: 10px 0 6px;
  font-family: var(--l-font);
  font-size: 10.5px;
}
.l-recur-modal .l-grid2 { gap: 0 18px; }
.l-recur-modal .l-grid2 + .l-grid2 { margin-top: 2px; }
.l-recur-modal .l-input,
.l-recur-modal .l-dd-btn {
  min-height: 42px;
  font-family: var(--l-font);
  font-size: 13.5px;
  font-weight: 400;
  line-height: 1.3;
}
.l-recur-modal .l-dd-btn.is-set { font-weight: 400; }
.l-recur-modal textarea.l-input { min-height: 60px; }
.l-recur-ahead {
  display: flex;
  align-items: center;
  gap: 9px;
}
.l-recur-ahead .l-input { width: 92px; }
.l-recur-ahead span {
  color: var(--l-text-3);
  font-size: 12.5px;
  white-space: nowrap;
}
.l-recur-time-fields {
  margin-top: 2px;
}
.l-recur-time-fields .l-task-time-picker,
.l-recur-time-fields .l-pop-time-field {
  min-width: 0;
}
.l-recur-sched { display: flex; align-items: center; gap: 12px; }
.l-recur-sched .l-dd { width: min(220px, 48%); }
.l-recur-sched .l-dd-btn { width: 100%; }
.l-recur-int { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--l-text-2); }
.l-recur-int .l-input { width: 72px; }
.l-recur-days { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.l-recur-days .l-check,
.l-recur-monthday .l-check { margin: 0; }
.l-recur-monthday { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.l-recur-monthday .l-input { width: 72px; }
.l-modal.l-recur-modal .l-recur-modal-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 15px 26px;
  border-top: 1px solid var(--l-hairline);
  background: var(--l-surface);
}
@media (max-width: 680px) {
  .l-modal.l-recur-modal { width: min(100%, calc(100vw - 20px)); }
  .l-recur-modal-head { padding: 18px 18px 15px; }
  .l-recur-modal-body { padding: 15px 18px 18px; }
  .l-recur-modal .l-grid2 { grid-template-columns: 1fr; }
  .l-recur-sched,
  .l-recur-monthday { align-items: stretch; flex-wrap: wrap; }
  .l-recur-sched .l-dd { width: 100%; }
  .l-modal.l-recur-modal .l-recur-modal-actions { padding: 13px 18px; }
}

/* ============================================================================
   Заметки — трёхпанельное рабочее пространство
   ========================================================================== */
body:has(.l-notes-app) .l-main {
  padding-bottom: 22px;
  overflow: hidden;
}
.l-notes-app {
  --notes-nav-w: 220px;
  --notes-list-w: 330px;
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 50px);
  min-width: 0;
}
/* Десктоп: всей цепочке высот нужна определённая величина, иначе прокручивается
   страница, а не текст заметки. С одним лишь min-height трек minmax(0, 1fr) в
   .l-note-editor-shell вырастает до полной высоты заметки, документ тянется
   следом, а Jodit (size-плагин меряет .jodit-container.offsetHeight) ставит
   .jodit-workplace ту же высоту — .jodit-wysiwyg никогда не переполняется и
   скроллера не даёт. Фиксируем высоту не арифметикой «100vh минус отступы»
   (они разные на 821–960px и шире), а самой .l-main: при box-sizing: border-box
   её height: 100vh уже включает паддинги, поэтому height: 100% у .l-notes-app
   ровно заполняет content-box. Полосы прокрутки страницы нет, а настоящим
   скроллером текста становится .jodit-wysiwyg.
   Мобильная раскладка (<= 820px) живёт по своей fixed-геометрии панели. */
@media (min-width: 821px) {
  body:has(.l-notes-app) .l-main { height: 100vh; }
  /* С топбаром над содержимым окно уже не равно колонке: высоту берём у самой
     строки сетки, иначе рабочее пространство заметок вылезало бы вниз ровно на
     высоту топбара и страница получала бы лишнюю прокрутку. */
  body:has(.l-notes-app) .l-app:has(> .t2-topbar) .l-main { height: 100%; }
  .l-notes-app {
    height: 100%;
    min-height: 0;
  }
}
.l-notes-head {
  display: flex;
  align-items: center;
  gap: 20px;
  min-height: 62px;
  padding-bottom: 15px;
}
.l-notes-subtitle {
  margin-top: 2px;
  color: var(--l-text-3);
  font-size: 12px;
}
.l-notes-head-tools {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-left: auto;
}
/* Поиск раздела. Одни правила на заметки и задачи: два одинаковых по смыслу
   поля обязаны выглядеть одинаково, а раздельные блоки рано или поздно
   разъезжаются по кеглю и высоте. Различия остаются только там, где отличается
   место: на телефоне поиск задач лежит в панели фильтров и растянут на всю
   ширину (см. .l-task-controls .l-tasks-search). */
.l-notes-search,
.l-tasks-search {
  display: flex;
  align-items: center;
  gap: 8px;
  width: min(360px, 30vw);
  min-height: 40px;
  padding: 0 10px 0 12px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  color: var(--l-text-3);
  background: var(--l-surface);
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.l-notes-search:focus-within,
.l-tasks-search:focus-within {
  border-color: var(--l-gray-300);
  box-shadow: none;
}
.l-notes-search input,
.l-tasks-search input {
  appearance: none;
  -webkit-appearance: none;
  min-width: 0;
  flex: 1;
  border: 0 !important;
  outline: 0 !important;
  box-shadow: none !important;
  color: var(--l-text);
  background: transparent;
  font: inherit;
}
.l-notes-search input::-webkit-search-cancel-button,
.l-tasks-search input::-webkit-search-cancel-button { display: none; }
.l-notes-search input::placeholder,
.l-tasks-search input::placeholder { color: var(--l-text-3); }
.l-notes-search kbd,
.l-tasks-search kbd {
  padding: 1px 6px;
  border: 1px solid var(--l-border);
  border-radius: 5px;
  color: var(--l-text-3);
  background: var(--l-bg);
  font: 10px var(--l-mono);
}
.l-notes-group {
  display: flex;
  align-items: center;
  min-height: 40px;
  padding-left: 11px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  color: var(--l-text-3);
  background: var(--l-surface);
  font-size: 11.5px;
}
.l-notes-group .l-dd { margin-left: 3px; }
.l-notes-group .l-dd-btn {
  min-height: 38px;
  max-width: 150px;
  padding: 0 29px 0 7px;
  border: 0;
  border-radius: calc(var(--l-r-md) - 2px);
  background: transparent;
  color: var(--l-text);
  font-size: 11.5px;
}
.l-notes-group .l-dd-btn:hover,
.l-notes-group .l-dd-btn.is-open {
  border-color: transparent;
  background: var(--l-surface-hover);
}
.l-notes-group .l-dd-menu { min-width: 170px; }
.l-notes-workspace {
  display: grid;
  grid-template-columns: var(--notes-nav-w) 5px var(--notes-list-w) 5px minmax(360px, 1fr);
  min-height: 0;
  flex: 1;
  overflow: hidden;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  background: var(--l-surface);
  box-shadow: var(--l-shadow-card);
}
.l-notes-nav,
.l-notes-list-pane,
.l-note-editor-pane { min-width: 0; min-height: 0; }
.l-notes-nav {
  position: relative;
  background: color-mix(in srgb, var(--l-bg) 62%, var(--l-surface));
}
.l-notes-nav-scroll {
  height: 100%;
  padding: 12px 9px 18px;
  overflow: auto;
}
.l-note-smart-list { padding-bottom: 10px; }
.l-note-nav-section {
  padding-top: 13px;
  border-top: 1px solid var(--l-hairline);
}
.l-note-nav-section + .l-note-nav-section { margin-top: 13px; }
.l-note-nav-caption {
  display: flex;
  align-items: center;
  min-height: 30px;
  padding: 0 8px;
  color: var(--l-text-3);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.l-note-nav-add {
  display: grid;
  width: 26px;
  height: 26px;
  margin-left: auto;
  place-items: center;
  border: 0;
  border-radius: var(--l-r-sm);
  color: var(--l-text-3);
  background: transparent;
  font: 18px/1 var(--l-font);
  cursor: pointer;
}
.l-note-nav-add:hover,
.l-note-nav-add:focus-visible { color: var(--l-accent-ink); background: var(--l-accent-soft); }
.l-note-nav-item-wrap {
  position: relative;
  display: flex;
  align-items: center;
}
.l-note-nav-row {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr) auto;
  align-items: center;
  gap: 7px;
  width: 100%;
  min-height: 34px;
  padding: 6px 8px;
  border: 0;
  border-radius: var(--l-r-sm);
  color: var(--l-text-2);
  background: transparent;
  text-align: left;
  font: inherit;
  cursor: pointer;
}
.l-note-nav-row:hover { color: var(--l-text); background: var(--l-surface-hover); }
.l-note-nav-row.is-active {
  color: var(--l-accent-ink);
  background: var(--l-note-active-bg, var(--l-accent-soft));
}
.l-note-nav-row b {
  overflow: hidden;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-note-nav-row i {
  color: var(--l-text-3);
  font-style: normal;
  font-size: 10.5px;
}
.l-note-nav-more {
  position: absolute;
  right: 4px;
  z-index: 2;
  display: none;
  width: 27px;
  height: 27px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  color: var(--l-text-3);
  background: color-mix(in srgb, var(--l-surface) 82%, transparent);
  font: 12px var(--l-font);
  cursor: pointer;
}
.l-note-nav-item-wrap:hover .l-note-nav-more,
.l-note-nav-more:focus-visible { display: block; }
.l-note-nav-more:hover { color: var(--l-danger); background: var(--l-danger-soft); }
.l-note-tag-color {
  position: absolute;
  top: 50%;
  left: 5px;
  z-index: 3;
  display: grid;
  width: 22px;
  height: 22px;
  padding: 0;
  place-items: center;
  border: 0;
  border-radius: var(--l-r-full);
  color: inherit;
  background: transparent;
  cursor: pointer;
  transform: translateY(-50%);
}
.l-note-tag-color:hover,
.l-note-tag-color:focus-visible {
  background: color-mix(in srgb, var(--tag-c) 14%, transparent);
  outline: 0;
}
.l-note-tag-color:hover .l-note-tag-dot,
.l-note-tag-color:focus-visible .l-note-tag-dot { transform: scale(1.28); }
.l-note-tag-dot {
  width: 8px;
  height: 8px;
  border-radius: var(--l-r-full);
  background: var(--tag-c, var(--l-text-3));
  transition: transform .12s ease;
}
.l-note-nav-muted {
  display: block;
  padding: 7px 9px 10px;
  color: var(--l-text-3);
  font-size: 11.5px;
  line-height: 1.45;
}
.l-note-folder-row {
  padding-left: calc(var(--folder-depth, 0) * 13px);
  border-radius: var(--l-r-sm);
}
.l-note-folder-row .l-note-nav-row { padding-left: 3px; }
.l-note-folder-drag {
  width: 13px;
  flex: 0 0 13px;
  color: transparent;
  font-size: 10px;
  cursor: grab;
}
.l-note-folder-row:hover .l-note-folder-drag { color: var(--l-text-3); }
.l-note-folder-row.is-dragging { opacity: .42; }
.l-note-folder-row.is-drop-before { box-shadow: inset 0 2px 0 var(--l-accent); }
.l-note-folder-row.is-drop-after { box-shadow: inset 0 -2px 0 var(--l-accent); }
.l-note-folder-row.is-drop-inside { background: var(--l-accent-soft); outline: 1px solid var(--l-accent); }
.l-note-folder-root-drop {
  display: none;
  margin: 5px 6px;
  padding: 6px;
  border: 1px dashed var(--l-border);
  border-radius: var(--l-r-sm);
  color: var(--l-text-3);
  text-align: center;
  font-size: 10.5px;
}
.l-note-folder-root:has(.is-dragging) .l-note-folder-root-drop { display: block; }
.l-note-folder-root-drop.is-drop-inside { color: var(--l-accent-ink); border-color: var(--l-accent); background: var(--l-accent-soft); }
.l-notes-resizer {
  position: relative;
  z-index: 5;
  width: 5px;
  cursor: col-resize;
  background: var(--l-surface);
}
.l-notes-resizer::after {
  content: '';
  position: absolute;
  inset: 0 2px;
  background: var(--l-hairline);
  transition: background 120ms ease, inset 120ms ease;
}
.l-notes-resizer:hover::after,
.is-notes-resizing .l-notes-resizer::after {
  inset: 0 1px;
  background: var(--l-accent);
}
.is-notes-resizing,
.is-notes-resizing * { cursor: col-resize !important; user-select: none !important; }
.l-notes-list-pane {
  display: flex;
  flex-direction: column;
  background: var(--l-surface);
}
.l-notes-mobilebar {
  display: none;
  align-items: center;
  gap: 8px;
  min-height: 45px;
  padding: 6px 11px;
  border-bottom: 1px solid var(--l-hairline);
  font-size: 13px;
  font-weight: 600;
}
.l-note-back {
  display: grid;
  width: 32px;
  height: 32px;
  padding: 0;
  place-items: center;
  border: 0;
  border-radius: var(--l-r-sm);
  color: var(--l-text-2);
  background: transparent;
  font: 17px var(--l-font);
  cursor: pointer;
}
.l-note-back:hover { color: var(--l-accent-ink); background: var(--l-accent-soft); }
.l-notes-list {
  height: 100%;
  padding: 11px 9px 30px;
  overflow: auto;
}
.l-note-group + .l-note-group { margin-top: 17px; }
.l-note-group h2 {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 6px 6px;
  color: var(--l-text-3);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .075em;
  text-transform: uppercase;
}
.l-note-group h2 span {
  font-family: var(--l-mono);
  font-size: 9.5px;
  font-weight: 400;
}
.l-note-card {
  display: block;
  width: 100%;
  padding: 11px 12px 10px;
  border: 1px solid transparent;
  border-radius: var(--l-r-md);
  color: var(--l-text);
  background: transparent;
  text-align: left;
  font: inherit;
  cursor: pointer;
  transition: background 110ms ease, border-color 110ms ease, box-shadow 110ms ease;
}
.l-note-card:hover { background: var(--l-surface-hover); border-color: var(--l-hairline); }
.l-note-card.is-active {
  border-color: transparent;
  background: var(--l-note-active-bg, var(--l-accent-soft));
  box-shadow: none;
}
.l-note-card-top {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.l-note-card-top strong {
  min-width: 0;
  flex: 1;
  overflow: hidden;
  font-size: 13.5px;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-note-card-top strong b {
  margin-right: 6px;
  color: var(--l-accent);
  font-size: 9px;
}
.l-note-card-top time {
  flex: 0 0 auto;
  color: var(--l-text-3);
  font: 10px var(--l-mono);
}
/* Признак действующей ссылки: тише даты и без своей области нажатия — карточка
   остаётся одной кнопкой. */
.l-note-card-share {
  display: inline-flex;
  flex: 0 0 auto;
  align-self: center;
  color: var(--l-text-3);
}
.l-note-card-excerpt {
  display: block;
  min-height: 18px;
  margin-top: 4px;
  overflow: hidden;
  color: var(--l-text-2);
  font-size: 11.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-note-card-excerpt em { color: var(--l-text-3); font-style: normal; }
.l-note-card mark {
  padding: 0 1px;
  border-radius: 2px;
  color: inherit;
  background: var(--l-warn-soft);
}
.l-note-card-meta {
  display: flex;
  align-items: center;
  gap: 5px;
  min-height: 18px;
  margin-top: 6px;
  overflow: hidden;
}
.l-note-card-meta span,
.l-note-card-meta i {
  display: inline-flex;
  align-items: center;
  max-width: 45%;
  padding: 2px 6px;
  overflow: hidden;
  border-radius: var(--l-r-full);
  color: var(--l-text-3);
  background: var(--l-bg);
  font-size: 9.5px;
  font-style: normal;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-note-card-meta i {
  color: color-mix(in srgb, var(--tag-c) 72%, var(--l-text));
  background: color-mix(in srgb, var(--tag-c) 12%, var(--l-surface));
}
.l-note-list-empty,
.l-note-editor-empty,
.l-note-history-empty {
  display: flex;
  height: 100%;
  min-height: 260px;
  padding: 28px;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  color: var(--l-text-3);
  text-align: center;
}
.l-note-list-empty strong,
.l-note-editor-empty strong,
.l-note-history-empty strong {
  margin: 8px 0 4px;
  color: var(--l-text-2);
  font-size: 14px;
  font-weight: 600;
}
.l-note-list-empty > span:not(.l-note-empty-spark),
.l-note-editor-empty > span,
.l-note-history-empty span { max-width: 280px; font-size: 11.5px; }
.l-note-list-empty .l-btn,
.l-note-editor-empty .l-btn { margin-top: 15px; }
.l-note-empty-spark { color: var(--l-accent); font-size: 24px; }
.l-note-empty-icon {
  display: grid;
  width: 70px;
  height: 70px;
  place-items: center;
  border: 1px solid var(--l-border);
  border-radius: 22px;
  color: var(--l-accent);
  background: linear-gradient(145deg, var(--l-surface), var(--l-accent-soft));
  box-shadow: var(--l-shadow-card);
}
.l-note-editor-pane {
  position: relative;
  overflow: hidden;
  background: var(--l-surface);
}
/* Подложка нужна только мобильной выдвижной панели редактора. */
.l-notes-backdrop { display: none; }
.l-note-editor-shell {
  position: relative;
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  height: 100%;
}
.l-note-editor-head {
  display: flex;
  align-items: center;
  min-height: 40px;
  padding: 4px 12px 2px 18px;
}
.l-note-editor-head .l-note-back { display: none; }
.l-note-editor-head > .l-spacer { flex: 1; }
.l-note-save-state {
  color: var(--l-text-3);
  font-size: 10.5px;
}
.l-note-save-state[data-tone="ok"] { color: var(--l-accent-ink); }
.l-note-save-state[data-tone="warn"] { color: var(--l-warn); }
.l-note-save-state[data-tone="error"] { color: var(--l-danger); }
.l-note-tool {
  display: grid;
  width: 32px;
  height: 32px;
  padding: 0;
  place-items: center;
  border: 0;
  border-radius: var(--l-r-sm);
  color: var(--l-text-3);
  background: transparent;
  font: 17px/1 var(--l-font);
  cursor: pointer;
}
.l-note-tool:hover,
.l-note-tool:focus-visible,
.l-note-tool.is-active { color: var(--l-accent-ink); background: var(--l-accent-soft); }
.l-note-tool.is-danger:hover { color: var(--l-danger); background: var(--l-danger-soft); }
/* Ссылкой значковая кнопка выглядит так же, как кнопкой: общий `.ledger a`
   иначе красит её акцентом (шапка карточки задачи — «Открыть отдельной
   страницей»). */
.ledger a.l-note-tool { color: var(--l-text-3); }
.ledger a.l-note-tool:hover,
.ledger a.l-note-tool:focus-visible { color: var(--l-accent-ink); }
/* «Поделиться» держит is-active всё время, пока у заметки есть публичная
   ссылка. Постоянная заливка читалась бы как нажатая кнопка, поэтому от
   активного состояния остаётся только акцентный цвет значка; фон возвращается
   на наведении, с клавиатуры и при открытом попапе. */
.l-note-editor-head [data-note-share-button].is-active { background: transparent; }
.l-note-editor-head [data-note-share-button].is-active:hover,
.l-note-editor-head [data-note-share-button].is-active:focus-visible,
.l-note-editor-head [data-note-share-button][aria-expanded="true"] { background: var(--l-accent-soft); }
/* Кнопка «Ещё» собирает редкие действия шапки и нужна только на телефоне. */
.l-note-more { display: none; }
.l-note-focus-toggle { gap: 7px; }
.l-note-focus-toggle > span,
.l-note-focus-exit-icon { display: none; }
.l-notes-app.is-focus-mode .l-note-focus-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  padding: 0 10px;
  color: var(--l-accent-ink);
  background: var(--l-accent-soft);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}
.l-notes-app.is-focus-mode .l-note-focus-toggle > span,
.l-notes-app.is-focus-mode .l-note-focus-exit-icon { display: block; }
.l-notes-app.is-focus-mode .l-note-focus-enter-icon { display: none; }
.l-note-pin-icon { display: block; flex: none; }
.l-note-pin-mark {
  display: inline-flex;
  margin-right: 5px;
  color: var(--l-accent-ink);
  vertical-align: -2px;
}
.l-note-pin-mark .l-note-pin-icon { width: 12px; height: 12px; }
.l-note-nav-row .l-note-pin-icon { width: 15px; height: 15px; }
.l-note-section-icon { display: block; flex: none; }
.l-note-nav-row .l-note-section-icon { width: 15px; height: 15px; }
.l-note-folder-icon {
  display: block;
  width: 15px;
  height: 15px;
}
.l-note-meta {
  position: relative;
  z-index: 12;
  display: grid;
  /* Четыре поля в узкой панели редактора не встают в одну строку: раскладку
     считает auto-fit — от 4 колонок на широком экране до 2 в выдвижной панели. */
  grid-template-columns: repeat(auto-fit, minmax(145px, 1fr));
  gap: 9px;
  padding: 5px 18px 11px;
  background: transparent;
}
.l-note-meta label,
.l-note-tags-field,
.l-note-remind-field { min-width: 0; }
.l-note-meta label > span,
.l-note-tags-field > span,
.l-note-remind-field > span {
  display: block;
  margin: 0 0 3px 2px;
  color: var(--l-text-3);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.l-note-meta .l-dd { display: block; width: 100%; }
.l-note-meta .l-dd-btn,
.l-note-tags-button {
  width: 100%;
  min-height: 34px;
  padding: 5px 28px 5px 9px;
  overflow: hidden;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-sm);
  outline: 0;
  color: var(--l-text-2);
  background: var(--l-surface);
  font: 11.5px var(--l-font);
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}
.l-note-meta .l-dd-btn:hover,
.l-note-tags-button:hover { border-color: var(--l-gray-300); color: var(--l-text); }
.l-note-meta .l-dd-btn:focus-visible,
.l-note-meta .l-dd-btn.is-open,
.l-note-tags-button:focus-visible {
  border-color: var(--l-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--l-accent) 12%, transparent);
}
.l-note-tags-button:disabled { opacity: .55; cursor: default; }
.l-note-meta .l-dd-menu { min-width: 100% !important; max-width: min(360px, 92vw); }
.l-note-tags-field { position: relative; }
.l-note-tags-button {
  display: flex;
  align-items: center;
  gap: 5px;
  padding-right: 8px;
  text-align: left;
}
.l-note-tags-button > span {
  display: flex;
  min-width: 0;
  flex: 1;
  gap: 4px;
  overflow: hidden;
}
.l-note-tags-button i,
.l-note-tags-label i {
  max-width: 90px;
  padding: 1px 6px;
  overflow: hidden;
  border-radius: var(--l-r-full);
  color: color-mix(in srgb, var(--tag-c) 72%, var(--l-text));
  background: color-mix(in srgb, var(--tag-c) 12%, var(--l-surface));
  font-size: 9.5px;
  font-style: normal;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-note-tags-pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: var(--l-z-pop);
  width: min(270px, 70vw);
  padding: 8px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface);
  box-shadow: var(--l-shadow-pop);
  max-height: min(72dvh, 480px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.l-note-tags-pop-title {
  padding: 4px 7px 7px;
  color: var(--l-text-3);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.l-note-tags-options {
  max-height: 220px;
  overflow: auto;
}
.l-note-tags-options label {
  display: flex;
  min-height: 32px;
  padding: 5px 7px;
  align-items: center;
  gap: 8px;
  border-radius: var(--l-r-sm);
  color: var(--l-text-2);
  cursor: pointer;
}
.l-note-tags-options label:hover { color: var(--l-text); background: var(--l-surface-hover); }
.l-note-tags-options input { accent-color: var(--l-accent); }
.l-note-tags-new {
  width: 100%;
  margin-top: 6px;
  padding: 7px;
  border: 0;
  border-top: 1px solid var(--l-hairline);
  color: var(--l-accent-ink);
  background: transparent;
  text-align: left;
  font: 11.5px var(--l-font);
  cursor: pointer;
}
/* --- Напоминание по заметке ---------------------------------------------- */
.l-note-remind-field { position: relative; }
.l-note-remind-button { justify-content: space-between; }
.l-note-remind-button > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.l-note-remind-button svg { flex: 0 0 auto; color: var(--l-text-3); }
.l-note-remind-button.is-set {
  border-color: color-mix(in srgb, var(--l-accent) 42%, var(--l-border));
  color: var(--l-accent-ink);
  font-family: var(--l-mono);
}
.l-note-remind-button.is-set svg { color: var(--l-accent); }
.l-note-remind-pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: var(--l-z-pop);
  width: min(300px, 84vw);
  padding: 8px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface);
  box-shadow: var(--l-shadow-pop);
  max-height: min(72dvh, 520px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.l-note-remind-quicks {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 5px;
  margin-bottom: 9px;
}
.l-note-remind-fields {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: 8px;
}
.l-note-remind-fields .l-date { width: 100%; }
.l-note-remind-fields .l-date-btn { min-height: 32px; font-size: 12px; }
.l-note-remind-actions {
  display: flex;
  margin-top: 10px;
  gap: 7px;
}
.l-note-remind-actions .l-btn { padding: 6px 11px; font-size: 12.5px; }
.l-note-remind-clear { color: var(--l-danger); }
.l-note-remind-pop .l-pop-time-error { margin-top: 7px; }

/* Попап секретной ссылки. Живёт в .l-note-editor-shell, а не в шапке
   редактора: на телефоне шапка сама прокручивается и обрезала бы попап. */
.l-note-share-pop {
  position: absolute;
  top: 40px;
  right: 12px;
  z-index: calc(var(--l-z-pop) + 10);
  width: min(330px, calc(100vw - 24px));
  padding: 13px 14px 12px;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  background: var(--l-surface);
  box-shadow: var(--l-shadow-pop);
}
.l-note-share-title {
  margin-bottom: 4px;
  color: var(--l-text-3);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.l-note-share-hint {
  margin: 0 0 11px;
  color: var(--l-text-2);
  font-size: 11.5px;
  line-height: 1.45;
}
.l-note-share-field { margin-bottom: 12px; }
.l-note-share-label {
  display: block;
  margin: 0 0 4px 2px;
  color: var(--l-text-3);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.l-note-share-field .l-input { width: 100%; }
/* Срок — число дней в свободном поле. Стрелки счётчика убраны: они спорят с
   подписью «дней» и на телефоне всё равно бесполезны. */
.l-note-share-days .l-input {
  padding-right: 56px;
  appearance: textfield;
  -moz-appearance: textfield;
}
.l-note-share-days .l-input::-webkit-outer-spin-button,
.l-note-share-days .l-input::-webkit-inner-spin-button {
  margin: 0;
  -webkit-appearance: none;
}
.l-note-share-days > span { font-size: 11.5px; }
.l-note-share-field .l-field-help { margin-left: 2px; }
.l-note-share-pop .l-note-share-url {
  width: 100%;
  margin-bottom: 7px;
  font-size: 11.5px;
}
.l-note-share-expiry {
  margin-bottom: 11px;
  color: var(--l-text-2);
  font-size: 11px;
}
.l-note-share-expiry.is-expired { color: var(--l-danger); }
/* Публикация в поиске — отдельная строка со своей рамкой: это не оттенок
   «доступа по ссылке», а другое решение с другими последствиями. */
.l-note-share-pub {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin-bottom: 11px;
  padding: 9px 10px;
  border: 1px solid var(--l-hairline);
  border-radius: var(--l-r-sm);
  cursor: pointer;
}
.l-note-share-pub:hover { border-color: var(--l-border); }
.l-note-share-pub.is-locked { cursor: default; opacity: .72; }
.l-note-share-pub .l-check-toggle { flex: none; margin-top: 1px; }
.l-note-share-pub-copy { display: grid; gap: 2px; }
.l-note-share-pub-title { color: var(--l-text); font-size: 12.5px; font-weight: 600; }
.l-note-share-pub-hint { color: var(--l-text-3); font-size: 11px; line-height: 1.4; }
.l-note-share-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.l-note-share-actions .l-btn { padding: 6px 11px; font-size: 12px; }
/* Главное действие занимает свою строку: пока ссылки нет — «Создать ссылку»,
   после создания — системное «Поделиться». */
.l-note-share-actions .l-note-share-native,
.l-note-share-actions .l-note-share-main {
  flex: 1 0 100%;
  justify-content: center;
  min-height: 34px;
}
.l-note-share-actions .l-note-share-revoke { margin-left: auto; }
.ledger .l-note-share-actions .l-note-share-revoke { color: var(--l-danger); }
.ledger .l-note-share-actions .l-note-share-revoke:hover {
  border-color: var(--l-danger);
  background: var(--l-danger-soft);
  color: var(--l-danger);
}
.l-note-share-loading {
  padding: 6px 0 2px;
  color: var(--l-text-3);
  font-size: 11.5px;
}
.l-note-tag-modal { max-width: 430px; }
.l-note-tag-modal-field {
  display: block;
  margin-top: 16px;
}
.l-note-tag-modal-field > span {
  display: block;
  margin: 0 0 7px 2px;
  color: var(--l-text-3);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.l-note-tag-modal-field .l-input { width: 100%; }
.l-note-tag-modal-field .l-input.is-invalid {
  border-color: var(--l-danger);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--l-danger) 13%, transparent);
}
.l-note-tag-palette {
  gap: 12px;
  padding: 6px 1px;
}
.l-note-tag-modal-field small {
  display: block;
  margin-top: 8px;
  color: var(--l-text-3);
  font-size: 10.5px;
  line-height: 1.45;
}
.l-note-editor-wrap {
  min-height: 0;
  /* Полотно — ячейка сетки, и её автоматический минимум равен min-content: без
     нуля широкая таблица растягивала весь редактор, а панель обрезала лишнее
     насовсем. С min-width: 0 дорожка держит ширину экрана, а таблица
     прокручивается внутри своей полосы. */
  min-width: 0;
  /* clip, а не hidden: hidden браузер прокручивает программно при фокусе
     (scroll-into-view каретки), и на телефоне этот сдвиг нельзя откатить
     пальцем — первые строки заметки «пропадают» под шапкой. */
  overflow: clip;
}
.l-note-editor-foot {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 30px;
  padding: 5px 18px;
  color: var(--l-text-3);
  background: var(--l-surface);
  font-size: 9.5px;
}
.l-note-editor-foot .l-spacer { flex: 1; }
.l-note-editor-foot [data-note-updated] {
  margin-left: auto;
  font-family: var(--l-mono);
  white-space: nowrap;
}

/* Плавающая кнопка «во весь экран»: на узких ширинах в шапке редактора нет
   места для текстового переключателя панелей. */
.l-note-expand-fab {
  position: absolute;
  right: 14px;
  bottom: 46px;
  z-index: 30;
  display: none;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--l-border);
  border-radius: 50%;
  color: var(--l-text-2);
  background: var(--l-surface);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--l-gray-950) 16%, transparent);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.l-note-expand-fab:hover,
.l-note-expand-fab:focus-visible {
  color: var(--l-text);
  border-color: var(--l-gray-300);
}
.l-note-expand-fab.is-active {
  color: var(--l-accent-ink);
  border-color: var(--l-accent);
  background: var(--l-accent-soft);
}
.l-note-expand-fab .l-fab-collapse { display: none; }
.l-note-expand-fab.is-active .l-fab-collapse { display: block; }
.l-note-expand-fab.is-active .l-fab-expand { display: none; }
@media (max-width: 1000px) {
  .l-note-expand-fab { display: inline-flex; }
  .l-notes-app.is-keyboard .l-note-expand-fab { display: none; }
}

/* Пока открыт попап заметки (напоминание, теги, ссылка), плавающие кнопки
   прячем: они висят в том же нижнем углу поверх попапа (z-index 30) и
   перехватывали нажатие на «Сохранить» — палец попадал в кнопку, а не в
   попап. Скрыть — честнее, чем менять слои: над попапом им делать нечего. */
.l-notes-app:has(.l-note-remind-pop:not([hidden])) .l-note-expand-fab,
.l-notes-app:has(.l-note-remind-pop:not([hidden])) .l-note-insert-fab,
.l-notes-app:has(.l-note-tags-pop:not([hidden])) .l-note-expand-fab,
.l-notes-app:has(.l-note-tags-pop:not([hidden])) .l-note-insert-fab,
.l-notes-app:has(.l-note-share-pop:not([hidden])) .l-note-expand-fab,
.l-notes-app:has(.l-note-share-pop:not([hidden])) .l-note-insert-fab {
  display: none;
}

/* Кнопка «+»: на телефоне панели инструментов нет, и блоки (заголовок, списки,
   таблица, разделитель) вставляются отсюда. Показываем её только в режиме
   «во весь экран», где полотну хватает места; при открытой клавиатуре она
   намеренно остаётся видимой — вставляют как раз во время набора. */
.l-note-insert-fab {
  position: absolute;
  left: 14px;
  bottom: 46px;
  z-index: 30;
  display: none;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--l-accent);
  border-radius: 50%;
  color: var(--l-on-accent);
  background: var(--l-accent);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--l-gray-950) 16%, transparent);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.l-note-insert-fab:hover,
.l-note-insert-fab:focus-visible {
  border-color: var(--l-accent-ink);
  background: var(--l-accent-ink);
}
.l-note-insert-fab:disabled {
  opacity: .4;
  cursor: default;
}
@media (max-width: 820px) {
  .l-notes-app.is-editor-max .l-note-insert-fab { display: inline-flex; }
}

@media (min-width: 821px) {
  .l-notes-app.is-focus-mode .l-notes-workspace {
    grid-template-columns: minmax(0, 1fr);
  }
  .l-notes-app.is-focus-mode .l-notes-nav,
  .l-notes-app.is-focus-mode .l-notes-list-pane,
  .l-notes-app.is-focus-mode .l-notes-resizer {
    display: none;
  }
  .l-notes-app.is-focus-mode .l-note-editor-pane { grid-column: 1; }
}

/* Jodit наследует Ledger вместо собственной светлой темы. */
/* Прокручивается только сам wysiwyg; workplace защищаем от программной
   прокрутки при фокусе (clip нельзя сдвинуть даже scroll-into-view). */
.l-note-editor-wrap .jodit-container:not(.jodit_inline) .jodit-workplace { overflow: clip; }
.l-note-editor-wrap .jodit-container:not(.jodit_inline) {
  display: flex;
  height: 100% !important;
  flex-direction: column;
  border: 0;
  border-radius: 0;
  color: var(--l-text);
  background: var(--l-surface);
  font-family: var(--l-font);
  box-shadow: none !important;
}
.l-note-editor-wrap .jodit-status-bar,
.l-note-editor-wrap .jodit-editor__resize {
  display: none !important;
}
/* Панель инструментов существует только от 821px: на телефоне редактор
   создаётся с toolbar: false, поэтому и правила для неё живут в этом
   медиазапросе — иначе overflow: visible снова победил бы мобильные. */
@media (min-width: 821px) {
  .l-note-editor-wrap .jodit-toolbar__box,
  .l-note-editor-wrap .jodit-toolbar__box:not(:empty) {
    flex: 0 0 auto;
    overflow: visible !important;
    border: 0 !important;
    border-bottom: 1px solid var(--l-hairline) !important;
    border-radius: 0 !important;
    background: transparent !important;
    background-image: none !important;
    box-shadow: none !important;
  }
}
.l-note-editor-wrap .jodit-toolbar-editor-collection {
  --jd-color-button-background-hover: transparent;
  --jd-color-button-background-hover-opacity40: transparent;
  --jd-color-button-background-hover-opacity60: transparent;
  --jd-color-background-button-hover: transparent;
  --jd-color-background-button-hover-opacity30: transparent;
  padding: 5px 12px !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  background-image: none !important;
  box-shadow: none !important;
}
.l-note-editor-wrap .jodit-toolbar-editor-collection .jodit-ui-group,
.l-note-editor-wrap .jodit-toolbar-editor-collection .jodit-toolbar-button,
.l-note-editor-wrap .jodit-toolbar-editor-collection .jodit-toolbar-button__button,
.l-note-editor-wrap .jodit-toolbar-editor-collection .jodit-toolbar-button__trigger {
  background: transparent !important;
  background-image: none !important;
  box-shadow: none !important;
}
.l-note-editor-wrap .jodit-toolbar-button__button {
  min-width: 30px;
  height: 30px;
  border-radius: 6px;
  color: var(--l-text-2);
}
.l-note-editor-wrap .jodit-toolbar-button__button:hover,
.l-note-editor-wrap .jodit-toolbar-button_trigger_true .jodit-toolbar-button__button,
.l-note-editor-wrap .jodit-toolbar-button_active .jodit-toolbar-button__button,
.l-note-editor-wrap .jodit-toolbar-button__button[aria-pressed='true'] {
  color: var(--l-accent-ink);
  background: transparent !important;
  box-shadow: none !important;
}
.l-note-editor-wrap .jodit-toolbar-button__button:focus-visible {
  outline: 1px solid var(--l-accent) !important;
  outline-offset: -2px;
  background: transparent !important;
}
.l-note-editor-wrap .jodit-toolbar-button__button svg {
  fill: currentColor;
  stroke: currentColor;
}
.l-note-editor-wrap .jodit-toolbar-button__trigger { border-color: var(--l-text-3) transparent transparent; }
.l-note-editor-wrap .jodit-toolbar__separator {
  border-color: var(--l-hairline) !important;
  opacity: .72;
}
.l-note-editor-wrap .jodit-workplace {
  min-height: 0 !important;
  flex: 1;
  border: 0;
  background: var(--l-surface);
}
.l-note-editor-wrap .jodit-wysiwyg {
  min-height: 100%;
  padding: 38px clamp(36px, 5vw, 72px) 90px !important;
  color: var(--l-text);
  background: var(--l-surface);
  font-family: var(--l-font);
  font-size: 16px;
  line-height: 1.65;
  caret-color: var(--l-accent);
}
.l-note-editor-wrap .jodit-placeholder {
  padding: 38px clamp(36px, 5vw, 72px) !important;
  color: var(--l-text-3) !important;
  font-family: var(--l-font) !important;
}
.l-note-editor-wrap .jodit-wysiwyg h1 {
  margin: 0 0 .6em;
  font-size: 29px;
  line-height: 1.18;
  letter-spacing: -.025em;
}
.l-note-editor-wrap .jodit-wysiwyg h2 { margin: 1.1em 0 .45em; font-size: 23px; line-height: 1.25; }
.l-note-editor-wrap .jodit-wysiwyg h3 { margin: 1em 0 .4em; font-size: 18px; line-height: 1.3; }
.l-note-editor-wrap .jodit-wysiwyg p { margin: 0 0 .8em; }
.l-note-editor-wrap .jodit-wysiwyg > .l-note-title-line {
  margin: 0 0 .72em;
  font-size: clamp(21px, 1.75vw, 24px);
  font-weight: 550;
  line-height: 1.22;
  letter-spacing: -.018em;
}
.l-note-editor-wrap .jodit-wysiwyg blockquote {
  margin: 1em 0;
  padding: 8px 16px;
  border-radius: var(--l-r-sm);
  color: var(--l-text-2);
  background: var(--l-accent-soft);
}
.l-note-editor-wrap .jodit-wysiwyg pre,
.l-note-editor-wrap .jodit-wysiwyg code {
  border-radius: var(--l-r-sm);
  background: var(--l-bg);
  font-family: var(--l-mono);
}
.l-note-editor-wrap .jodit-wysiwyg pre { padding: 13px 15px; overflow: auto; }
.l-note-editor-wrap .jodit-wysiwyg code { padding: 1px 4px; font-size: .88em; }
.l-note-editor-wrap .jodit-wysiwyg a { color: var(--l-accent-ink); text-decoration-thickness: 1px; text-underline-offset: 2px; }
.l-note-editor-wrap .jodit-wysiwyg hr { margin: 1.4em 0; border: 0; border-top: 1px solid var(--l-border); }
.l-note-editor-wrap .jodit-wysiwyg table {
  width: 100%;
  margin: 1em 0;
  border-collapse: separate;
  border-spacing: 0;
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-md);
  overflow: hidden;
}
/* Ячейки рисуем только правой и нижней гранью, внешнюю рамку даёт сама
   таблица. Заводское правило Jodit «.jodit-wysiwyg table tr td { border: 1px
   solid var(--jd-color-border) }» оставляло верхнюю и левую грани серыми
   (#dadada): в светлой теме это почти не видно, в тёмных ячейки светились
   белёсой сеткой. Сбрасываем border целиком и на всякий случай переопределяем
   саму переменную Jodit — тогда любая его разметка берёт цвет Ledger. */
.l-note-editor-wrap .jodit-container { --jd-color-border: var(--l-border); }
.l-note-editor-wrap .jodit-wysiwyg th,
.l-note-editor-wrap .jodit-wysiwyg td {
  min-width: 60px;
  padding: 8px 10px;
  border: 0;
  border-right: 1px solid var(--l-border);
  border-bottom: 1px solid var(--l-border);
  vertical-align: top;
}
.l-note-editor-wrap .jodit-wysiwyg th { background: var(--l-bg); font-weight: 600; }
.l-note-editor-wrap .jodit-wysiwyg tr:last-child > * { border-bottom: 0; }
.l-note-editor-wrap .jodit-wysiwyg tr > *:last-child { border-right: 0; }
.l-note-editor-wrap .jodit-wysiwyg .l-note-checklist {
  margin: .35em 0 1em;
  padding: 0;
  list-style: none;
}
.l-note-editor-wrap .jodit-wysiwyg .l-note-checklist li {
  position: relative;
  min-height: 27px;
  margin: .18em 0;
  padding-left: 28px;
}
/* Квадратик рисует псевдоэлемент: настоящий <input> в разметке ломал удаление
   пунктов и выход из списка по Enter. Селектор привязан к [data-checked], чтобы
   старый пункт до миграции не показывал пустую рамку без состояния. */
.l-note-editor-wrap .jodit-wysiwyg .l-note-checklist li[data-checked]::before {
  content: '';
  position: absolute;
  top: .34em;
  left: 0;
  width: 17px;
  height: 17px;
  box-sizing: border-box;
  border: 1.5px solid var(--l-border);
  border-radius: 4px;
  background: var(--l-surface);
  cursor: pointer;
}
.l-note-editor-wrap .jodit-wysiwyg .l-note-checklist li[data-checked="1"]::before {
  border-color: var(--l-accent);
  background: var(--l-accent) var(--l-tick-mark) center / 11px no-repeat;
  opacity: .72;
}
/* Всплывающие меню Jodit (в том числе меню ячейки таблицы) живут в отдельном
   .jodit-popup-container вне .l-note-editor-wrap, поэтому тему им задаём по
   собственным классам. Контейнер — только слой, ему нужны переменные Jodit:
   иначе рамки внутри меню остаются заводскими #dadada и в тёмных темах
   светятся. Высоту ограничиваем вьюпортом — в ландшафте меню было выше окна. */
.jodit-popup-container {
  --jd-color-border: var(--l-border);
  --jd-color-separator: var(--l-hairline);
  --jd-color-text: var(--l-text);
  --jd-color-icon: var(--l-text-2);
  --jd-color-panel: var(--l-surface);
  --jd-color-background-default: var(--l-surface);
  font-family: var(--l-font);
}
.jodit-popup,
.jodit-dialog__panel,
.jodit-ui-group,
.jodit-select__popup {
  color: var(--l-text) !important;
  border-color: var(--l-border) !important;
  background: var(--l-surface) !important;
  box-shadow: var(--l-shadow-pop) !important;
  font-family: var(--l-font) !important;
}
.jodit-popup {
  max-width: calc(100vw - 16px);
  max-height: calc(100dvh - 16px);
  overflow: auto;
  overscroll-behavior: contain;
  border-radius: var(--l-r-md) !important;
}
.jodit-popup .jodit-toolbar-editor-collection,
.jodit-popup .jodit-ui-group {
  padding: 4px !important;
  border: 0 !important;
  box-shadow: none !important;
}
.jodit-popup .jodit-toolbar-button__button,
.jodit-popup .jodit-ui-button__button {
  border-radius: var(--l-r-sm) !important;
}
.jodit-popup .jodit-toolbar-button__button:hover,
.jodit-popup .jodit-ui-button__button:hover {
  color: var(--l-accent-ink) !important;
  background: var(--l-accent-soft) !important;
}
.jodit-popup .jodit-toolbar-button__trigger { border-color: var(--l-text-3) transparent transparent; }
/* Пальцем в меню ячейки таблицы попадать нечем: стрелки подменю у Jodit
   16×32. На сенсорном вводе и на телефонной ширине даём им полноценную цель. */
@media (pointer: coarse), (max-width: 820px) {
  .jodit-popup .jodit-toolbar-button,
  .jodit-popup .jodit-toolbar-button__button,
  .jodit-popup .jodit-ui-button__button {
    min-width: 40px;
    min-height: 40px;
  }
  .jodit-popup .jodit-toolbar-button__trigger {
    min-width: 28px;
    min-height: 40px;
  }
}
.jodit-popup__content,
.jodit-dialog__content,
.jodit-dialog__header,
.jodit-dialog__footer { color: var(--l-text) !important; background: var(--l-surface) !important; border-color: var(--l-border) !important; }
.jodit-ui-input__input,
.jodit-ui-text-area__input,
.jodit-ui-select__input {
  color: var(--l-text) !important;
  border-color: var(--l-border) !important;
  background: var(--l-surface) !important;
  font-family: var(--l-font) !important;
}
.jodit-ui-button__button { color: var(--l-text-2) !important; background: var(--l-surface) !important; }
.jodit-ui-button__button:hover { color: var(--l-accent-ink) !important; background: var(--l-accent-soft) !important; }
/* На телефоне всплывающее меню выделения — единственная панель форматирования,
   поэтому её кнопкам нужна полноценная цель нажатия. */
@media (max-width: 820px) {
  .jodit-popup .jodit-toolbar-button__button,
  .jodit-popup .jodit-ui-button__button {
    min-width: 40px;
    min-height: 40px;
  }
}
.l-note-history {
  position: absolute;
  inset: 0 0 0 auto;
  z-index: 30;
  width: min(360px, 92%);
  border-left: 1px solid var(--l-border);
  background: var(--l-surface);
  box-shadow: var(--l-shadow-pop);
}
.l-note-history-head {
  display: flex;
  min-height: 48px;
  padding: 8px 11px 8px 16px;
  align-items: center;
  border-bottom: 1px solid var(--l-hairline);
}
.l-note-history-head strong { font-size: 13.5px; font-weight: 600; }
.l-note-history-head .l-note-tool { margin-left: auto; }
.l-note-history-list {
  height: calc(100% - 48px);
  padding: 11px;
  overflow: auto;
}
.l-note-history-loading { padding: 25px; color: var(--l-text-3); text-align: center; }
.l-note-revision {
  padding: 12px;
  border: 1px solid var(--l-hairline);
  border-radius: var(--l-r-md);
  background: var(--l-surface);
}
.l-note-revision + .l-note-revision { margin-top: 8px; }
.l-note-revision time { display: block; color: var(--l-text-3); font: 9.5px var(--l-mono); }
.l-note-revision strong { display: block; margin-top: 5px; font-size: 12.5px; font-weight: 600; }
.l-note-revision p {
  display: -webkit-box;
  margin: 4px 0 9px;
  overflow: hidden;
  color: var(--l-text-2);
  font-size: 11px;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}
.l-note-revision .l-btn { padding: 5px 9px; font-size: 11px; }

@media (max-width: 1180px) {
  .l-notes-head-tools { gap: 7px; }
  .l-notes-group > span { display: none; }
  .l-notes-group { padding-left: 2px; }
  .l-notes-workspace { --notes-nav-w: 200px; --notes-list-w: 300px; }
  .l-note-editor-wrap .jodit-wysiwyg { padding-left: 32px !important; padding-right: 32px !important; }
}
/* Низкий экран (ландшафт телефона, окно 850×400): по ширине это по-прежнему
   раскладка с тремя панелями, а по высоте на редактор остаётся ~95px. Панель
   инструментов переносилась на четыре ряда, поля заметки занимали две строки,
   а поля полотна (38px сверху, 90px снизу) не помещались в его собственную
   высоту — при box-sizing: border-box полотно не может стать ниже своих полей,
   и оно вылезало из обрезанного workplace. Здесь: ряд кнопок один и листается
   вбок (меню Jodit живут в .jodit-popup-container с position: fixed, поэтому
   прокрутка их не обрезает), поля заметки — одна прокручиваемая строка,
   поля полотна ужаты. Тогда высота полотна равна высоте workplace, и текст
   прокручивается ровно в видимой области. */
@media (min-width: 821px) and (max-height: 560px) {
  .l-note-editor-wrap .jodit-toolbar-editor-collection {
    overflow-x: auto;
    overflow-y: visible;
    scrollbar-width: none;
  }
  .l-note-editor-wrap .jodit-toolbar-editor-collection::-webkit-scrollbar { height: 0; }
  .l-note-editor-wrap .jodit-toolbar-editor-collection .jodit-ui-group { flex-wrap: nowrap !important; }
  .l-note-meta {
    grid-template-columns: repeat(4, minmax(145px, 1fr));
    padding-block: 3px 7px;
    overflow-x: auto;
    scrollbar-width: thin;
  }
  .l-note-editor-wrap .jodit-wysiwyg {
    padding: 12px clamp(20px, 3vw, 40px) 18px !important;
    scroll-padding-bottom: 18px;
  }
  .l-note-editor-wrap .jodit-placeholder { padding: 12px clamp(20px, 3vw, 40px) !important; }
}
@media (max-width: 820px) {
  body:has(.l-notes-app) .l-main { padding: 14px 12px 20px; overflow: visible; }
  .l-notes-app { min-height: calc(100vh - 28px); }
  .l-notes-head { flex-wrap: wrap; gap: 10px; padding: 0 2px 11px; }
  .l-notes-head > div:first-child { display: none; }
  .l-notes-head-tools { width: 100%; margin: 0; }
  .l-notes-search { width: auto; flex: 1; }
  .l-notes-search kbd { display: none; }
  .l-notes-group {
    min-width: 0;
    flex: 0 1 118px;
    padding-left: 0;
  }
  .l-notes-group > span { display: none; }
  .l-notes-group .l-dd { width: 100%; margin: 0; }
  .l-notes-group .l-dd-btn {
    width: 100%;
    max-width: none;
    padding-left: 10px;
  }
  .l-notes-workspace {
    position: relative;
    display: block;
    min-height: calc(100vh - 82px);
  }
  .l-notes-resizer { display: none; }
  .l-notes-nav,
  .l-notes-list-pane {
    position: absolute;
    inset: 0;
    display: none;
    background: var(--l-surface);
  }
  .l-notes-list-pane { display: flex; }
  .l-notes-mobilebar { display: flex; }
  .l-notes-app.is-mobile-nav .l-notes-nav { display: block; z-index: 20; }
  /* Редактор на телефоне — отдельный слой ровно по визуальному вьюпорту:
     экранная клавиатура сдвигает его, а не перекрывает. Слой выше мобильной
     шапки (--l-z-pop - 40), но ниже попапов, тостов и модальных окон.
     Закрытая панель остаётся в этом слое (за краем экрана), чтобы открытие и
     закрытие анимировались, а жест «назад» тянул её пальцем. */
  .l-note-editor-pane {
    position: fixed;
    top: var(--notes-viewport-top, 0px);
    right: 0;
    bottom: auto;
    left: auto;
    z-index: calc(var(--l-z-pop) - 20);
    display: block;
    width: min(92%, 560px);
    height: var(--notes-viewport-h, 100dvh);
    border-radius: 0;
    transform: translateX(103%);
    visibility: hidden;
    pointer-events: none;
    /* Горизонтальную прокрутку панели забирает жест «назад», вертикальная
       прокрутка и масштабирование щипком остаются системными. */
    touch-action: pan-y pinch-zoom;
    transition: transform .26s ease, visibility 0s .26s;
  }
  .l-notes-app.is-mobile-editor .l-note-editor-pane {
    position: fixed;
    height: var(--notes-viewport-h, 100dvh);
    transform: translateX(0);
    visibility: visible;
    pointer-events: auto;
    box-shadow: -18px 0 40px color-mix(in srgb, var(--l-gray-950) 18%, transparent);
    transition: transform .26s ease;
  }
  .l-notes-app.is-editor-max .l-note-editor-pane { width: 100%; }
  /* Во весь экран: поля заметки (проект, папка, напоминание, теги) уходят,
     чтобы заголовок стоял под самой шапкой. Скрыть блок мало — сетка оболочки
     сдвинула бы полотно в чужую дорожку, поэтому меняем и шаблон строк.
     Правила is-keyboard ниже по файлу перекрывают этот шаблон своим. */
  .l-notes-app.is-editor-max .l-note-meta { display: none; }
  .l-notes-app.is-editor-max .l-note-editor-shell { grid-template-rows: auto minmax(0, 1fr) auto; }
  /* Кнопка «+» висит над полотном (44px + 46px от низа) — нижний отступ
     текста больше её габарита, иначе вставленный блок прячется под ней. */
  .l-notes-app.is-editor-max .l-note-editor-wrap .jodit-wysiwyg { padding-bottom: 110px !important; }
  /* Горизонтальная прокрутка внутри редактора важнее жеста «назад». */
  .l-note-editor-pane .l-note-editor-head,
  .l-note-editor-pane .jodit-wysiwyg table { touch-action: auto; }
  .l-notes-backdrop {
    position: fixed;
    inset: 0;
    z-index: calc(var(--l-z-pop) - 30);
    display: block;
    background: color-mix(in srgb, var(--l-gray-950) 32%, transparent);
    opacity: 0;
    pointer-events: none;
    transition: opacity .26s ease;
  }
  .l-notes-app.is-mobile-editor .l-notes-backdrop {
    opacity: 1;
    pointer-events: auto;
  }
  body:has(.l-notes-app.is-mobile-editor) { overflow: hidden; }
  /* При открытой клавиатуре в сетке остаются только шапка и полотно. */
  .l-notes-app.is-keyboard .l-note-editor-shell { grid-template-rows: auto minmax(0, 1fr); }
  .l-notes-app.is-keyboard .l-note-meta,
  .l-notes-app.is-keyboard .l-note-editor-foot { display: none; }
  .l-notes-app.is-keyboard .l-note-editor-head {
    min-height: 42px;
    padding-top: 2px;
    padding-bottom: 0;
  }
  .l-note-editor-head .l-note-back { display: grid; margin-right: 5px; }
  .l-note-focus-toggle { display: none; }
  .l-note-editor-head { padding-left: 8px; }
  /* Шапка на телефоне держит только «назад», статус сохранения, «поделиться»
     и «ещё»: остальные действия открывает меню ⋯ (notes.js). */
  .l-note-editor-head [data-note-pin],
  .l-note-editor-head [data-note-history],
  .l-note-editor-head [data-note-duplicate],
  .l-note-editor-head [data-note-archive],
  .l-note-editor-head [data-note-trash] { display: none; }
  .l-note-more { display: grid; }
  /* Четыре поля ложатся сеткой 2×2: проект/папка сверху, напоминание/теги снизу. */
  .l-note-meta { grid-template-columns: 1fr 1fr; }
  .l-note-editor-wrap .jodit-workplace { scroll-padding-bottom: 90px; }
  .l-note-editor-wrap .jodit-wysiwyg {
    padding: 25px 20px 70px !important;
    font-size: 15px;
    scroll-padding-bottom: 90px;
  }
  .l-note-editor-wrap .jodit-placeholder { padding: 25px 20px !important; }
}
@media (max-width: 480px) {
  .l-notes-head .l-btn { padding-left: 10px; padding-right: 10px; gap: 0; }
  .l-notes-head .l-btn .l-btn-label { display: none; }
  .l-notes-head .l-btn .l-btn-glyph { width: 18px; height: 18px; }
  .l-notes-head-tools { flex-wrap: wrap; }
  .l-notes-search { flex-basis: calc(100% - 52px); }
  .l-notes-group { flex: 1 1 calc(100% - 52px); order: 3; }
  .l-note-meta { grid-template-columns: 1fr; }
  .l-note-editor-head { gap: 1px; }
  .l-note-editor-head .l-note-tool { width: 30px; }
  .l-note-editor-foot [data-note-updated] { display: none; }
}
/* ==========================================================================
   Публичная страница заметки /s/<token>
   Отдельный документ без каркаса приложения: только шапка с логотипом,
   карточка с текстом заметки и подпись. Тема — светлый Emerald по умолчанию.
   ========================================================================== */
.l-public-page {
  min-height: 100%;
  background: var(--l-bg);
}
.l-public-note {
  max-width: 760px;
  margin: 0 auto;
  padding: clamp(18px, 4vw, 40px) clamp(14px, 4vw, 24px) clamp(28px, 6vw, 56px);
}
.l-public-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: clamp(14px, 3vw, 22px);
}
.l-public-brand {
  display: inline-flex;
  flex: none;
  align-items: center;
}
.l-public-brand img {
  display: block;
  width: auto;
  height: clamp(26px, 5vw, 32px);
}
.l-public-cta { margin-left: auto; }
.l-public-card {
  margin-bottom: clamp(16px, 3vw, 24px);
  padding: clamp(20px, 5vw, 48px);
}
/* Подпись автора — только у опубликованной страницы. Метка повторяет метку
   кабинета в меню: эмодзи, если владелец его выбрал, иначе буквы названия.
   Загруженную картинку сюда не тянем: её отдача закрыта членством в кабинете,
   и открывать её ради подписи значило бы расширить доступ к чужому файлу. */
.l-public-author {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 14px;
}
.l-public-author-mark {
  display: grid;
  place-items: center;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: var(--l-accent-soft);
  color: var(--l-accent-ink);
  font-family: var(--l-mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .02em;
}
.l-public-author-mark.is-emoji {
  font-family: inherit;
  font-size: 17px;
  line-height: 1;
  letter-spacing: normal;
}
.l-public-author-name {
  color: var(--l-text-2);
  font-size: 13.5px;
  font-weight: 600;
}
.l-public-title {
  margin: 0 0 6px;
  font-size: clamp(26px, 4.4vw, 34px);
  font-weight: 550;
  line-height: 1.16;
  letter-spacing: -.024em;
}
.l-public-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  margin-bottom: clamp(18px, 3vw, 26px);
  color: var(--l-text-3);
  font-size: 13px;
}
.l-public-dot { color: var(--l-text-3); }
.l-public-prose {
  color: var(--l-text);
  font-size: 16px;
  line-height: 1.65;
  overflow-wrap: anywhere;
}
.l-public-prose > *:first-child { margin-top: 0; }
.l-public-prose > *:last-child { margin-bottom: 0; }
.l-public-prose p { margin: 0 0 .8em; }
.l-public-prose h1 { margin: 1.3em 0 .5em; font-size: 25px; line-height: 1.2; letter-spacing: -.02em; }
.l-public-prose h2 { margin: 1.2em 0 .45em; font-size: 21px; line-height: 1.25; }
.l-public-prose h3 { margin: 1.1em 0 .4em; font-size: 17px; line-height: 1.3; }
.l-public-prose ul,
.l-public-prose ol { margin: 0 0 1em; padding-left: 1.4em; }
.l-public-prose li { margin: .2em 0; }
.l-public-prose blockquote {
  margin: 1em 0;
  padding: 8px 16px;
  border-left: 3px solid var(--l-accent);
  border-radius: 0 var(--l-r-sm) var(--l-r-sm) 0;
  color: var(--l-text-2);
  background: var(--l-accent-soft);
}
.l-public-prose pre,
.l-public-prose code {
  border-radius: var(--l-r-sm);
  background: var(--l-bg);
  font-family: var(--l-mono);
}
.l-public-prose pre { margin: 1em 0; padding: 13px 15px; overflow-x: auto; }
.l-public-prose code { padding: 1px 4px; font-size: .88em; }
.l-public-prose pre code { padding: 0; background: transparent; }
.l-public-prose a { color: var(--l-accent-ink); text-decoration: underline; text-underline-offset: 2px; }
.l-public-prose hr { margin: 1.6em 0; border: 0; border-top: 1px solid var(--l-hairline); }
.l-public-prose img { max-width: 100%; height: auto; border-radius: 8px; }
/* Таблица прокручивается внутри своей полосы: страница по горизонтали не едет. */
.l-public-prose table {
  display: block;
  width: 100%;
  max-width: 100%;
  margin: 1em 0;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  border-collapse: collapse;
}
/* Та же поправка, что и в редакторе: без неё строки блочной таблицы образуют
   анонимную таблицу шириной по содержимому и узкая таблица жалась к левому
   краю. Широкая по-прежнему прокручивается внутри своей полосы. */
.l-public-prose table:not(:has(thead, tfoot, colgroup, caption)) > tbody {
  display: table;
  width: 100%;
}
.l-public-prose th,
.l-public-prose td {
  min-width: 80px;
  padding: 8px 10px;
  border: 1px solid var(--l-hairline);
  vertical-align: top;
  text-align: left;
}
.l-public-prose th { background: var(--l-bg); font-weight: 600; }
.l-public-prose li > input[type="checkbox"] {
  width: 16px;
  height: 16px;
  margin: 0 8px 0 0;
  accent-color: var(--l-accent);
  vertical-align: -2px;
  pointer-events: none;
}
.l-public-prose .l-note-checklist { padding-left: 0; list-style: none; }
/* Новый формат чек-листа: состояние в атрибуте, квадратик — псевдоэлемент.
   Страница только для чтения, поэтому курсор остаётся обычным. Отступ вешаем
   только на пункты нового формата: у старых, ещё не пересохранённых заметок
   место под квадратик занимает сам <input> из правила выше. */
.l-public-prose .l-note-checklist li[data-checked] { position: relative; padding-left: 26px; }
.l-public-prose .l-note-checklist li[data-checked]::before {
  content: '';
  position: absolute;
  top: .28em;
  left: 0;
  width: 16px;
  height: 16px;
  box-sizing: border-box;
  border: 1.5px solid var(--l-border);
  border-radius: 4px;
  background: var(--l-surface);
}
.l-public-prose .l-note-checklist li[data-checked="1"]::before {
  border-color: var(--l-accent);
  background: var(--l-accent) var(--l-tick-mark) center / 10px no-repeat;
  opacity: .72;
}
.l-public-message { text-align: center; }
.l-public-message-icon {
  display: grid;
  width: 60px;
  height: 60px;
  margin: 6px auto 16px;
  place-items: center;
  border-radius: var(--l-r-full);
  color: var(--l-text-3);
  background: var(--l-bg);
}
.l-public-message-copy {
  margin: 8px 0 20px;
  color: var(--l-text-2);
  font-size: 14px;
  line-height: 1.55;
}
/* Кнопка «Поделиться» под текстом: страницу читают, чтобы переслать дальше, —
   искать адресную строку на телефоне ради этого не должно быть нужно. */
.l-public-share {
  margin-top: clamp(22px, 4vw, 32px);
  padding-top: clamp(16px, 3vw, 22px);
  border-top: 1px solid var(--l-hairline);
}
.ledger .l-public-share-btn { gap: 8px; }

/* Продающий блок. Появляется только у опубликованных страниц и только под
   текстом: человек пришёл читать заметку, а не рекламу. */
.l-public-promo {
  margin-bottom: clamp(16px, 3vw, 24px);
  padding: clamp(22px, 5vw, 36px);
  border: 1px solid var(--l-border);
  border-radius: var(--l-r-lg);
  background:
    radial-gradient(circle at 8% 0%, color-mix(in srgb, var(--l-accent) 12%, transparent), transparent 46%),
    var(--l-surface);
}
.l-public-promo-eyebrow {
  margin-bottom: 8px;
  color: var(--l-accent-ink);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
}
.l-public-promo-title {
  margin: 0 0 10px;
  font-size: clamp(19px, 3vw, 24px);
  font-weight: 550;
  line-height: 1.22;
  letter-spacing: -.02em;
}
.l-public-promo-copy {
  margin: 0 0 16px;
  max-width: 56ch;
  color: var(--l-text-2);
  font-size: 14.5px;
  line-height: 1.55;
}
.l-public-promo-list {
  margin: 0 0 20px;
  padding: 0;
  display: grid;
  gap: 8px;
  list-style: none;
  color: var(--l-text-2);
  font-size: 14px;
}
/* Галочка рисуется псевдоэлементом: маркер списка здесь читается как перечень
   ограничений, а не как перечень того, что уже работает. */
.l-public-promo-list li {
  position: relative;
  padding-left: 24px;
  line-height: 1.45;
}
.l-public-promo-list li::before {
  content: "";
  position: absolute;
  top: .42em;
  left: 4px;
  width: 9px;
  height: 5px;
  border: 2px solid var(--l-accent);
  border-top: 0;
  border-right: 0;
  transform: rotate(-45deg);
}
.ledger .l-public-promo-cta { min-height: 44px; padding-inline: 22px; font-size: 15px; }
.l-public-promo-note {
  margin-top: 10px;
  color: var(--l-text-3);
  font-size: 12.5px;
}

.l-public-foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 16px;
  color: var(--l-text-3);
  font-size: 13px;
  text-align: center;
}
.ledger .l-public-foot a { color: var(--l-text-2); text-decoration: underline; text-underline-offset: 2px; }
.ledger .l-public-foot a:hover { color: var(--l-accent-ink); }
/* Жалоба — не призыв к действию: нужна тем, кому нужна, и не спорит с промо. */
.ledger a.l-public-report { color: var(--l-text-3); font-size: 12.5px; }
.ledger a.l-public-report:hover { color: var(--l-danger); }

/* ==========================================================================
   Вход
   ========================================================================== */
.l-login-page {
  min-height: 100vh;
  background:
    radial-gradient(circle at 12% 12%, color-mix(in srgb, var(--l-accent) 10%, transparent), transparent 34%),
    radial-gradient(circle at 88% 84%, color-mix(in srgb, var(--l-accent) 5%, transparent), transparent 30%),
    var(--l-bg);
}
.l-login-shell {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: clamp(24px, 5vw, 64px);
}
.l-login-layout {
  display: grid;
  grid-template-columns: minmax(300px, 1.05fr) minmax(350px, .95fr);
  width: min(100%, 900px);
  min-height: 520px;
  overflow: hidden;
  border: 1px solid var(--l-border);
  border-radius: 28px;
  background: var(--l-surface);
  box-shadow: 0 24px 70px color-mix(in srgb, var(--l-gray-950) 13%, transparent);
}
.l-login-intro {
  display: flex;
  min-width: 0;
  padding: clamp(42px, 6vw, 72px);
  flex-direction: column;
  justify-content: center;
  background:
    linear-gradient(145deg, color-mix(in srgb, var(--l-accent-soft) 72%, var(--l-surface)), var(--l-surface));
}
.l-login-card {
  display: flex;
  min-width: 0;
  padding: clamp(42px, 5vw, 64px);
  flex-direction: column;
  justify-content: center;
  background: var(--l-surface);
}
.l-login-logo {
  --l-brand-ink: var(--l-text);
  display: block;
  width: min(100%, 300px);
  height: auto;
  margin: 0;
}
.l-login-tagline {
  margin: 10px 0 0;
  color: var(--l-text-2);
  font-size: 15px;
  letter-spacing: .01em;
}
.l-login-intro-copy {
  max-width: 330px;
  margin: 46px 0 0;
  color: var(--l-text-2);
  font-size: 15px;
  line-height: 1.65;
}
.l-login-heading > span {
  display: block;
  margin-bottom: 10px;
  color: var(--l-accent-ink);
  font-size: 11px;
  font-weight: 650;
  letter-spacing: .09em;
  text-transform: uppercase;
}
.l-login-card h1 {
  margin: 0;
  color: var(--l-text);
  font-size: clamp(26px, 3vw, 32px);
  font-weight: 650;
  line-height: 1.14;
  letter-spacing: -.025em;
}
.l-login-copy {
  margin: 10px 0 30px;
  color: var(--l-text-2);
  font-size: 13.5px;
  line-height: 1.55;
}
.l-login-form {
  display: grid;
  gap: 8px;
}
.l-login-form > label:not(.l-login-remember) {
  margin: 10px 0 2px;
  color: var(--l-text-2);
  font-size: 12.5px;
  font-weight: 550;
}
.l-login-form .l-input {
  width: 100%;
  min-height: 48px;
  padding: 11px 14px;
  border-radius: 12px;
  font-size: 15px;
}
.l-login-form .l-input::placeholder {
  color: color-mix(in srgb, var(--l-text-3) 72%, transparent);
}
.l-login-error {
  margin: -12px 0 16px;
  padding: 11px 12px;
  border-radius: 10px;
  /* Мягкая красная подложка: у тёмных тем --l-danger светлый и давал 4.32:1. */
  color: var(--l-danger-ink);
  background: color-mix(in srgb, var(--l-danger) 9%, transparent);
  font-size: 13px;
}
.l-login-remember {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 36px;
  margin: 10px 0 12px;
  color: var(--l-text-2);
  font-size: 12.5px;
  cursor: pointer;
}
.l-login-submit {
  display: flex;
  width: 100%;
  min-height: 48px;
  align-items: center;
  justify-content: center;
  border-radius: 12px !important;
  font-size: 14px !important;
}
.l-login-notice {
  margin: -12px 0 16px;
  padding: 11px 12px;
  border-radius: 10px;
  color: var(--l-accent-ink);
  background: var(--l-accent-soft);
  font-size: 13px;
}
/* Плашка приглашения: «+15» слева, объяснение справа. */
.l-login-badge {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: -12px 0 18px;
  padding: 11px 12px;
  border: 1px solid color-mix(in srgb, var(--l-accent) 26%, transparent);
  border-radius: 10px;
  /* Вторичный цвет на мягком акценте давал в «Изумруде» 4.15:1. */
  color: var(--l-text);
  background: var(--l-accent-soft);
  font-size: 12.5px;
  line-height: 1.45;
}
.l-login-badge strong {
  flex: none;
  color: var(--l-accent-ink);
  font-size: 15px;
  font-weight: 650;
}
.l-login-optional { color: var(--l-text-3); font-weight: 400; }
.l-login-terms { min-height: 44px; }
.l-login-alt {
  margin: 18px 0 0;
  color: var(--l-text-3);
  font-size: 12.5px;
  text-align: center;
}
.ledger .l-login-alt a {
  color: var(--l-accent-ink);
  text-decoration: none;
}
.ledger .l-login-alt a:hover { text-decoration: underline; text-underline-offset: 2px; }
.l-login-alt-sep { margin: 0 6px; color: var(--l-text-3); }
.l-sidebar-logout { margin-left: auto; }
.l-sidebar-logout button {
  display: grid;
  width: 30px;
  height: 30px;
  place-items: center;
  border: 0;
  border-radius: 8px;
  color: var(--l-sidebar-muted);
  background: transparent;
  cursor: pointer;
}
.l-sidebar-logout button:hover {
  color: var(--l-sidebar-text);
  background: var(--l-sidebar-hover);
}

@media (max-width: 760px) {
  .l-login-shell {
    align-items: start;
    padding: max(26px, env(safe-area-inset-top)) 18px max(26px, env(safe-area-inset-bottom));
  }
  .l-login-layout {
    display: block;
    width: min(100%, 460px);
    min-height: 0;
    overflow: visible;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
  }
  .l-login-intro {
    padding: 14px 4px 32px;
    align-items: flex-start;
    background: transparent;
  }
  .l-login-logo { width: 190px; }
  .l-login-tagline { margin-top: 6px; font-size: 12.5px; }
  .l-login-intro-copy { display: none; }
  .l-login-card {
    padding: 26px 22px 22px;
    border: 1px solid var(--l-border);
    border-radius: 20px;
    box-shadow: var(--l-shadow-card);
  }
  .l-login-card h1 { font-size: 26px; }
  .l-login-copy { margin-bottom: 22px; }
}

/* ==========================================================================
   Мобильный рабочий каркас и общие рабочие поверхности
   ========================================================================== */
.l-mobile-shellbar,
.l-mobile-nav-backdrop { display: none; }

/* Три панели заметок в 850px не помещались: колонка редактора требовала
   минимум 360px, ширины навигации и списка приходят из localStorage, и правый
   край редактора с полями «Напоминание» и «Теги» уезжал за экран вместе с их
   попапами. Ниже 821px раскладка и так становится одноколоночной, поэтому
   диапазон узкий: здесь ширины считаются от свободного места, а не из
   сохранённых значений. */
@media (min-width: 821px) and (max-width: 960px) {
  .l-notes-workspace {
    grid-template-columns: minmax(0, 168px) 5px minmax(0, 232px) 5px minmax(0, 1fr);
  }
}

@media (min-width: 721px) and (max-width: 960px) {
  /* Рельс в 64px: подписи спрятаны, поэтому счётчик встаёт меткой у верхнего
     угла иконки — как точка колокольчика в свёрнутом сайдбаре. Обводка цветом
     сайдбара отделяет метку от самой иконки. */
  .l-sidebar .l-nav-badge,
  html.l-collapsed .l-sidebar .l-nav-badge,
  html.l-collapsed .l-sidebar #l-bell-btn .l-nav-badge {
    display: inline-flex;
    position: absolute;
    top: 2px;
    right: 7px;
    min-width: 16px;
    width: auto;
    height: 16px;
    margin: 0;
    padding: 0 4px;
    align-items: center;
    justify-content: center;
    border: 2px solid var(--l-sidebar-bg);
    border-radius: var(--l-r-full);
    font-size: 9.5px;
    line-height: 1;
  }
  .l-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .l-tile + .l-tile {
    border-top: 0;
    border-left: 1px solid var(--l-hairline);
  }
  .l-tile:nth-child(odd) { border-left: 0; }
  .l-tile:nth-child(n + 3) { border-top: 1px solid var(--l-hairline); }
}

@media (max-width: 720px) {
  html,
  body.ledger {
    min-width: 320px;
    min-height: 100%;
  }

  /* Навигационные ленты листаются пальцем без полосы прокрутки — как нативные
     сегмент-контролы. О скрытом «хвосте» подсказывает лёгкий нудж (ledger.js).
     Контентные области (таблицы, доска) остаются с нативной overlay-полосой:
     она видна только во время прокрутки и сама растворяется. */
  .l-viewbar,
  .l-tiles,
  .l-filter-panel > .l-seg,
  .l-board-mobile-tabs,
  .l-cal-mobile-days,
  .l-notes-head-tools {
    scrollbar-width: none;
  }
  .l-viewbar::-webkit-scrollbar,
  .l-tiles::-webkit-scrollbar,
  .l-filter-panel > .l-seg::-webkit-scrollbar,
  .l-board-mobile-tabs::-webkit-scrollbar,
  .l-cal-mobile-days::-webkit-scrollbar,
  .l-notes-head-tools::-webkit-scrollbar {
    display: none;
    width: 0;
    height: 0;
  }
  .l-board { scrollbar-width: none; scrollbar-color: auto; }
  .l-board::-webkit-scrollbar { display: none; width: 0; height: 0; }
  html.l-mobile-nav-open,
  html.l-mobile-nav-open body { overflow: hidden; }

  .l-app,
  html.l-collapsed .l-app {
    display: block;
    min-height: 100dvh;
  }
  .l-mobile-shellbar {
    position: sticky;
    top: 0;
    z-index: calc(var(--l-z-pop) - 40);
    display: grid;
    /* бургер · логотип · контекст · единая группа действий */
    grid-template-columns: 44px 52px minmax(0, 1fr) auto;
    min-height: calc(58px + env(safe-area-inset-top));
    padding: env(safe-area-inset-top) 12px 0 8px;
    align-items: center;
    gap: 6px;
    border-bottom: 1px solid color-mix(in srgb, var(--l-border) 82%, transparent);
    background: color-mix(in srgb, var(--l-bg) 88%, transparent);
    -webkit-backdrop-filter: blur(18px) saturate(1.2);
    backdrop-filter: blur(18px) saturate(1.2);
  }
  .l-mobile-menu-btn {
    display: grid;
    width: 44px;
    height: 44px;
    padding: 0;
    place-items: center;
    border: 0;
    border-radius: 12px;
    color: var(--l-text-2);
    background: transparent;
  }
  .l-mobile-menu-btn:hover,
  .l-mobile-menu-btn:focus-visible {
    color: var(--l-text);
    background: var(--l-surface);
  }
  .l-mobile-brand {
    --l-brand-ink: var(--l-text);
    display: grid;
    width: 50px;
    place-items: center;
    color: inherit;
  }
  .l-mobile-context {
    min-width: 0;
    padding-right: 6px;
    overflow: hidden;
    color: var(--l-text-2);
    font-size: 12.5px;
    font-weight: 550;
    text-align: right;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .l-mobile-shell-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0;
  }
  .l-mobile-bell { position: relative; }
  /* .ledger a красит ссылки акцентом — шестерёнка остаётся значком шапки */
  .ledger .l-mobile-gear,
  .ledger a.l-mobile-gear { justify-self: end; color: var(--l-text-2); }
  .ledger a.l-mobile-gear:hover,
  .ledger a.l-mobile-gear:focus-visible { color: var(--l-text); background: var(--l-surface); }

  /* ========================================================================
     Два режима навигации (см. секцию «Слой кабинета 2.0 (t2-)» выше).
     html.l-nav-tabs — панель снизу и двухрядная шапка, режим по умолчанию.
     html.l-nav-drawer — прежняя строка с бургером и выдвижная шторка.
     body.l-has-tabs ставит сервер: если человеку доступно меньше двух
     разделов, панель из пяти пунктов вырождается, поэтому её нет вовсе и
     режим принудительно шторочный — правила ниже все требуют этот класс.
     ====================================================================== */
  html.l-nav-tabs body.l-has-tabs .l-mobile-shellbar { display: none; }
  html.l-nav-tabs body.l-has-tabs .t2-appbar { display: block; }
  html.l-nav-tabs body.l-has-tabs .t2-tabbar { display: grid; }
  /* Дизайн-проект поднимает низ контента и FAB по наличию панели в разметке
     (селектор с :has). У нас панель лежит в разметке всегда, а видима только
     в режиме tabs — поэтому гейт по классу режима: иначе отступ в 96px съедал
     бы экран и в режиме шторки, где панели нет. Правило 8 дизайн-системы: ни
     один экран не прибит к панели, она только отодвигает нижнюю границу. */
  html.l-nav-tabs body.l-has-tabs .l-main { padding-bottom: calc(96px + env(safe-area-inset-bottom)); }
  html.l-nav-tabs body.l-has-tabs .l-create-fab { bottom: calc(84px + env(safe-area-inset-bottom)); }
  /* html.l-nav-both — «оба меню»: нижняя панель ПЛЮС строка с бургером.
     Шапка остаётся шторочной (.l-mobile-shellbar видна по умолчанию,
     .t2-appbar скрыта) — двух шапок и двух колокольчиков не появляется,
     добавляется только панель и её отступы. */
  html.l-nav-both body.l-has-tabs .t2-tabbar { display: grid; }
  html.l-nav-both body.l-has-tabs .l-main { padding-bottom: calc(96px + env(safe-area-inset-bottom)); }
  html.l-nav-both body.l-has-tabs .l-create-fab { bottom: calc(84px + env(safe-area-inset-bottom)); }
  /* Заметки: редактор — фиксированный лист на всю высоту экрана, панель снизу
     ложится ПОВЕРХ него. Плавающие кнопки («во весь экран» и «+») с базовых
     46px поднимаем на высоту панели (62px + safe-area), иначе они прячутся
     под ней; полотну в фулскрине добавляем столько же воздуха снизу, чтобы
     последние строки текста не оказались под поднятой кнопкой «+». */
  html.l-nav-tabs body.l-has-tabs .l-note-expand-fab,
  html.l-nav-tabs body.l-has-tabs .l-note-insert-fab,
  html.l-nav-both body.l-has-tabs .l-note-expand-fab,
  html.l-nav-both body.l-has-tabs .l-note-insert-fab {
    bottom: calc(108px + env(safe-area-inset-bottom));
  }
  html.l-nav-tabs body.l-has-tabs .l-notes-app.is-editor-max .l-note-editor-wrap .jodit-wysiwyg,
  html.l-nav-both body.l-has-tabs .l-notes-app.is-editor-max .l-note-editor-wrap .jodit-wysiwyg {
    padding-bottom: 176px !important;
  }
  /* Шторка в режиме tabs остаётся рабочей (её открывают из «Ещё» и с
     клавиатуры), но собственный блок профиля показываем в обоих режимах:
     шторка одна на оба. */
  .ledger .l-sidebar .t2-drawer-foot { display: flex; }
  .l-sidebar .t2-drawer-days { display: inline-block; }
  /* Подвал шторки — строка с кнопками; профиль встаёт над ней своей строкой. */
  .l-sidebar .l-sidebar-foot,
  html.l-collapsed .l-sidebar .l-sidebar-foot { flex-wrap: wrap; row-gap: 4px; }
  .l-sidebar .t2-drawer-foot { order: -1; }
  /* Кнопка «+» — настройка устройства: кому она мешает, тот её выключает.
     Селектор перекрывает display:inline-flex у самих кнопок разделов. */
  html.l-no-fab body.ledger .l-create-fab { display: none; }
  /* Плотность списков: строка задачи ужимается за счёт воздуха, а не целей
     нажатия — сама строка остаётся не ниже 44px, чипы остаются нажимаемыми. */
  html.l-compact .l-trow { min-height: 44px; padding: 5px 10px; gap: 3px 8px; }
  html.l-compact .l-trow-meta { margin-top: 0; }
  html.l-compact .l-trow-meta button,
  html.l-compact .l-trow-meta .l-tmeta { min-height: 24px; padding: 2px 6px; }
  html.l-compact .l-tcard { padding: 7px 10px; }
  html.l-compact .l-tgroup-body { gap: 6px; }
  /* Узкий телефон: пять подписей по 10.5px в 320px помещаются только без
     собственных отступов у панели. */
  @media (max-width: 360px) {
    .t2-tabbar { padding-left: 2px; padding-right: 2px; gap: 0; }
    .ledger .t2-tab { font-size: 10px; }
    .t2-appbar { padding-left: 10px; padding-right: 10px; }
    .t2-appbar-title { font-size: 22px; }
  }
  /* Широкий телефон в альбомной ориентации: экран низкий, две строки шапки и
     панель забирают половину. Шапку сжимаем в одну строку заголовка. */
  @media (max-height: 460px) {
    .t2-appbar { padding-top: calc(env(safe-area-inset-top) + 4px); padding-bottom: 6px; }
    .t2-appbar-top { min-height: 44px; }
    .t2-appbar-head { min-height: 0; margin-top: 2px; }
    .t2-appbar-title { font-size: 19px; }
    .ledger .t2-tab { min-height: 42px; }
    html.l-nav-tabs body.l-has-tabs .l-main { padding-bottom: calc(84px + env(safe-area-inset-bottom)); }
  }

  /* Хаб настроек: на телефоне карточки читаются одной колонкой. */
  .l-setgrid { grid-template-columns: 1fr; }
  /* Настройки задач переехали в шестерёнку шапки — текстовая кнопка дублирует. */
  .ledger .l-tasks-topbar-settings { display: none; }
  /* Шапка раздела в выдвижной панели держится сверху при прокрутке.
     Правила именно под #settings-drawer: общий .l-drawer трогать нельзя. */
  #settings-drawer .l-setdrawer-head {
    position: sticky;
    top: calc(0px - var(--drawer-safe-top));
    z-index: 8;
    min-height: 58px;
    margin: calc(0px - var(--drawer-safe-top)) -14px 12px;
    padding: max(12px, env(safe-area-inset-top)) 14px 8px;
    background: color-mix(in srgb, var(--l-surface) 94%, transparent);
    border-bottom: 1px solid var(--l-hairline);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
  }
  #settings-drawer .l-panel { padding: 14px; }

  .l-sidebar,
  html.l-collapsed .l-sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: calc(var(--l-z-pop) + 20);
    width: min(84vw, 320px);
    height: 100dvh;
    padding: max(20px, env(safe-area-inset-top)) 14px max(16px, env(safe-area-inset-bottom));
    gap: 14px;
    /* Шторка листается целиком: раньше скроллилось только меню, а профиль был
       прибит к низу и отнимал высоту у самих разделов. В профиль заходят
       изредка, между разделами переключаются весь день — пусть подвал уезжает
       вверх вместе с пунктами. */
    overflow-y: auto;
    overscroll-behavior: contain;
    visibility: hidden;
    transform: translateX(-104%);
    box-shadow: 24px 0 60px rgba(0, 0, 0, .2);
    transition: transform 180ms ease, visibility 180ms step-end;
  }
  html.l-mobile-nav-open .l-sidebar {
    visibility: visible;
    transform: translateX(0);
    transition: transform 180ms ease, visibility 0s;
  }
  /* Шторка — не рельса: место под название есть, и кабинет надо назвать.
     Перебиваем правила рельсы 64px, которые начинаются с той же 960px. */
  .l-sidebar .t2-tenant-head,
  html.l-collapsed .l-sidebar .t2-tenant-head { justify-content: flex-start; }
  .ledger .l-sidebar .t2-tenant-home,
  html.l-collapsed .l-sidebar .t2-tenant-home { flex: 1 1 auto; justify-content: flex-start; padding: 7px 8px; }
  .l-sidebar .t2-tenant-head .t2-tenant-name,
  html.l-collapsed .l-sidebar .t2-tenant-head .t2-tenant-name { display: block; }
  .ledger .l-sidebar .t2-tenant-switch,
  html.l-collapsed .l-sidebar .t2-tenant-switch { display: grid; }
  /* Меню перестаёт быть собственным скроллером и растёт по содержимому.
     Заодно схлопывается его распорка (flex:1 перед колоколом): в рельсе ПК она
     прижимает колокол и тему к низу, в шторке гнала бы пустоту. */
  .l-sidebar .l-nav {
    flex: 0 0 auto;
    min-height: auto;
    padding-right: 2px;
    overflow: visible;
  }
  /* Растворяющаяся кромка говорила «меню прокручивается» — теперь прокрутка у
     шторки целиком, и гаснущий последний пункт только путал бы. */
  .l-sidebar .l-nav.is-scrollable:not(.is-scroll-end) {
    -webkit-mask-image: none;
    mask-image: none;
  }
  .l-sidebar .l-nav-title,
  html.l-collapsed .l-sidebar .l-nav-title { display: block; padding-top: 15px; }
  .l-sidebar .l-nav-item,
  html.l-collapsed .l-sidebar .l-nav-item {
    min-height: 42px;
    padding: 9px 11px;
    justify-content: flex-start;
    font-size: 14px;
  }
  .l-sidebar .l-nav-item span,
  html.l-collapsed .l-sidebar .l-nav-item span { display: inline; }
  .l-sidebar .l-nav-badge,
  html.l-collapsed .l-sidebar .l-nav-badge { display: inline-flex; }
  .l-sidebar .l-sidebar-foot,
  html.l-collapsed .l-sidebar .l-sidebar-foot {
    display: flex;
    margin-top: 10px;
    padding: 8px 8px 0;
    align-items: center;
    border-top: 1px solid var(--l-sidebar-border);
  }
  .l-sidebar .l-sidebar-toggle { display: none; }
  .l-mobile-nav-backdrop {
    position: fixed;
    inset: 0 0 0 min(84vw, 320px);
    z-index: calc(var(--l-z-pop) + 10);
    display: block;
    padding: 0;
    border: 0;
    background: rgba(8, 10, 12, .48);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 180ms ease, visibility 180ms step-end;
  }
  html.l-mobile-nav-open .l-mobile-nav-backdrop {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: opacity 180ms ease, visibility 0s;
  }

  .l-main {
    width: 100%;
    max-width: none;
    min-width: 0;
    padding: 18px 14px calc(34px + env(safe-area-inset-bottom));
  }
  .l-mobile-ghost-topbar { display: none; }
  body:has(.l-task-controls) .l-main,
  body:has(.l-op-create-fab) .l-main,
  body:has(.l-project-create-fab) .l-main,
  body:has(.l-setgrid) .l-main {
    padding-top: 12px;
  }
  .l-main > * { min-width: 0; max-width: 100%; }
  .l-topbar {
    min-height: 42px;
    margin-bottom: 16px;
    flex-wrap: wrap;
    column-gap: 8px;
    row-gap: 10px;
  }
  .l-topbar .l-title {
    min-width: 130px;
    flex: 1 1 150px;
    font-size: 20px;
  }
  /* Заголовок страницы, дословно повторяющий подпись в мобильной шапке
     («Задачи» над «Задачи»), съедал строку на маленьком экране. Дубль
     размечает ledger.js — в шаблонах признака совпадения нет. */
  .l-title.is-shell-dup { display: none; }
  /* Заголовок спрятан как дубль подписи в шапке — стрелка «›» указывала бы в
     пустоту. Остаётся ссылка «Настройки» рядом со стрелкой «назад». */
  .l-pagehead-copy:has(> .l-title.is-shell-dup) .l-crumb-sep { display: none; }
  .l-topbar .l-spacer { display: none; }
  .ledger .l-btn {
    min-height: 44px;
    padding: 9px 12px;
    justify-content: center;
  }
  .l-create-fab {
    position: fixed;
    right: 16px;
    bottom: max(22px, calc(env(safe-area-inset-bottom) + 6px));
    z-index: calc(var(--l-z-pop) + 5);
    width: 56px;
    height: 56px;
    padding: 0;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--l-accent);
    border-radius: 50%;
    color: var(--l-on-accent);
    background: var(--l-accent);
    box-shadow: 0 10px 28px color-mix(in srgb, var(--l-gray-950) 24%, transparent);
    cursor: pointer;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
  }
  .ledger a.l-create-fab { color: var(--l-on-accent); }
  .l-create-fab:hover,
  .l-create-fab:focus-visible,
  .ledger a.l-create-fab:hover,
  .ledger a.l-create-fab:focus-visible {
    border-color: var(--l-accent-ink);
    color: var(--l-on-accent);
    background: var(--l-accent-ink);
  }
  .l-notes-create-fab,
  .l-task-create-fab,
  .l-op-create-fab,
  .l-project-create-fab { display: inline-flex; }
  .l-notes-app.is-mobile-editor .l-notes-create-fab,
  body:has(#l-bulkbar:not([hidden])) .l-create-fab,
  body:has(.l-drawer.is-open) .l-create-fab,
  body:has(.l-modal-overlay:not([hidden])) .l-create-fab {
    display: none;
  }
  .l-notes-new-top,
  .l-task-new-top,
  .l-op-new-top,
  .l-project-new-top { display: none !important; }
  .l-pagehead {
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 8px;
  }
  .l-pagehead > div:not(.l-spacer) { min-width: 0; }
  .l-pagehead .l-spacer { display: none; }
  .l-pagehead .l-title { max-width: calc(100vw - 92px); }
  .l-pagehead > .l-btn,
  .l-pagehead > .l-inline-form,
  .l-pagehead > form:not(.l-inline-form) {
    min-width: 0;
    flex: 1 1 140px;
  }
  .l-pagehead > .l-btn { white-space: normal; }
  .l-pagehead .l-doc-desktop-action,
  .l-doc-desktop-delete { display: none !important; }
  .l-doc-mobile-actions {
    margin: -8px 0 14px;
    display: flex;
    justify-content: flex-end;
    gap: 8px;
  }
  .l-doc-mobile-actions .l-iconbtn {
    width: 44px;
    height: 44px;
    min-width: 44px;
    min-height: 44px;
    border-radius: 12px;
  }
  .l-doc-mobile-actions .l-iconbtn:disabled {
    opacity: .38;
    cursor: default;
  }
  .l-doc-mobile-downloads { display: block; }
  .l-doc-download-actions {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
  }
  .l-doc-download-actions .l-btn { min-width: 0; }
  .l-doc-party-inn {
    display: block;
    margin: 3px 0 0;
  }
  /* Подсказка о ненастроенном канале — всегда со своей строки. На широком
     телефоне она умещалась справа от «Отправить по ЭДО» и читалась как
     подпись именно к этой кнопке, хотя относится к почте. */
  .l-send-hint {
    flex: 1 0 100%;
    margin-top: 2px;
  }
  .l-doc-send-log,
  .l-doc-send-log tbody {
    display: block;
    width: 100%;
    min-width: 0;
  }
  .l-doc-send-log thead { display: none; }
  .l-doc-send-log tbody {
    display: grid;
    gap: 8px;
  }
  .l-doc-send-log tbody tr,
  .l-doc-send-log tbody tr:hover {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 7px 10px;
    width: 100%;
    min-width: 0;
    padding: 11px 12px;
    border: 1px solid var(--l-hairline);
    border-radius: var(--l-r-md);
    background: var(--l-surface);
  }
  .l-doc-send-log tbody td {
    display: block;
    min-width: 0;
    padding: 0;
    border: 0;
    background: transparent;
  }
  .l-doc-send-log .l-doc-send-to {
    grid-column: 1 / -1;
    grid-row: 1;
    overflow-wrap: anywhere;
    color: var(--l-text);
    font-size: 13px;
    font-weight: 600;
  }
  .l-doc-send-log .l-doc-send-time {
    grid-column: 1;
    grid-row: 2;
    white-space: nowrap;
  }
  .l-doc-send-log .l-doc-send-channel {
    grid-column: 2;
    grid-row: 2;
    color: var(--l-text-3);
    font-size: 12px;
  }
  .l-doc-send-log .l-doc-send-status {
    grid-column: 3;
    grid-row: 2;
  }
  .l-doc-sign-form {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: stretch;
    gap: 9px;
  }
  .l-doc-sign-form .l-select,
  .l-doc-sign-form input[type="date"] {
    width: 100%;
    min-width: 0;
  }
  .l-doc-sign-save-state {
    min-width: 0;
    min-height: 17px;
  }
  /* Итог: 21px на 375 упирался в край панели вместе с символом валюты. */
  .l-total-value { font-size: 19px; }
  /* Формы оплаты на телефоне: поля в колонку, значки — рядом справа.
     Размер цели нажатия у значков даёт общее правило .l-iconbtn (44×44). */
  .l-payform {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 8px;
  }
  .l-payform .l-date,
  .l-payform input[type="date"],
  .l-payform input[type="number"],
  .l-payform .l-select {
    grid-column: 1;
    width: 100%;
    min-width: 0;
  }
  .l-payform .l-date-btn { min-width: 0; }
  /* Значки — вторым столбцом справа от полей: отдельной строкой под формой
     они отрывались от того, что подтверждают. Прижаты к низу, а не по центру:
     подтверждают введённую сумму — последнее поле, и «висящая» между полями
     галочка выглядела случайной. */
  .l-payform-tools {
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: end;
    flex-direction: column;
    gap: 4px;
  }
  .l-pay-actions,
  .l-pay-actions form,
  .l-doc-service-actions {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 9px;
  }
  .l-pay-actions .l-date,
  .l-pay-actions input[type="date"],
  .l-pay-actions select,
  .l-pay-actions .l-btn,
  .l-doc-service-actions .l-btn,
  .l-doc-service-actions .l-inline-form {
    width: 100%;
    min-width: 0;
  }
  /* Распорка внутри колонки превратилась бы в пустую строку. */
  .l-doc-service-gap { display: none; }
  .l-doc-period-seg { display: none !important; }
  .l-filter-panel > .l-dd:has(> .l-doc-period-select) {
    display: block;
    min-width: 0;
  }

  .l-tiles {
    display: flex;
    margin: 0 -14px 16px;
    padding: 0 14px 4px;
    gap: 9px;
    overflow-x: auto;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    scroll-padding-inline: 14px;
    scroll-snap-type: x proximity;
  }
  .l-tile,
  .l-tile + .l-tile {
    min-width: min(76vw, 280px);
    padding: 15px 17px;
    border: 1px solid var(--l-border);
    border-radius: var(--l-r-lg);
    background: var(--l-surface);
    scroll-snap-align: start;
  }
  .l-tile-value { font-size: 20px; }

  /* Сводка «приход · расход · сальдо»: лентой на экран влезала одна плитка,
     а цифры нужны все три сразу. Складываем их в одну карточку строками
     «подпись — значение» без горизонтальной прокрутки.
     Селекторы двухклассовые: правила ≤420 (.l-tiles, .l-tile) идут ниже
     по файлу и перебиваются именно специфичностью. */
  .l-tiles.l-tiles--rows {
    display: block;
    margin: 0 0 16px;
    padding: 0;
    overflow: visible;
    border: 1px solid var(--l-border);
    border-radius: var(--l-r-lg);
    background: var(--l-surface);
    box-shadow: var(--l-shadow-card);
    scroll-snap-type: none;
  }
  .l-tiles--rows .l-tile,
  .l-tiles--rows .l-tile + .l-tile {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 12px;
    min-width: 0;
    padding: 11px 16px;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
  }
  .l-tiles--rows .l-tile + .l-tile { border-top: 1px solid var(--l-hairline); }
  .l-tiles--rows .l-tile-label { margin-bottom: 0; }
  .l-tiles--rows .l-tile-value { font-size: 15.5px; text-align: right; }
  .l-tiles--rows .l-tile-value .cur { font-size: 12px; }

  .l-filters {
    align-items: stretch;
    gap: 8px;
  }
  html.l-js [data-mobile-filters]:not(.l-filter-shell) > :not(input[type="hidden"]):not([data-filter-always]) {
    display: none;
  }
  html.l-js [data-mobile-filters]:not(.l-filter-shell)::after {
    content: "Фильтры и группировка";
    min-height: 44px;
    padding: 8px 11px;
    display: flex;
    align-items: center;
    flex: 1 0 100%;
    border: 1px solid var(--l-border);
    border-radius: var(--l-r-md);
    background: var(--l-surface);
    color: var(--l-text);
    font-size: 13px;
    font-weight: 600;
  }
  .l-filter-shell {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 8px;
    margin-bottom: 16px;
  }
  .l-filter-shell > input[type="hidden"] { display: none; }
  .l-filter-shell [data-filter-always] {
    width: 100%;
    max-width: none;
    min-width: 0;
  }
  .l-filter-mobile-section {
    min-width: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    overflow: visible;
    border: 1px solid var(--l-border);
    border-radius: var(--l-r-md);
    background: var(--l-surface);
  }
  .l-filter-mobile-head {
    display: flex;
    min-width: 0;
    align-items: center;
    gap: 0;
  }
  .l-filter-toggle {
    min-width: 0;
    min-height: 44px;
    padding: 8px 11px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex: 1;
    border: 0;
    border-radius: 0;
    background: transparent;
    color: var(--l-text);
    font: inherit;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
  }
  .l-filter-toggle-copy {
    min-width: 0;
    display: grid;
    gap: 2px;
  }
  .l-filter-toggle-title {
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
  }
  .l-filter-toggle-summary {
    min-width: 0;
    overflow: hidden;
    color: var(--l-text-3);
    font-size: 11.5px;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* Состояние панели показывает только шеврон: подпись «Открыть/Свернуть»
     дублировала его и съедала место у сводки выбранных фильтров. Кружок в
     30px — комфортная иконочная зона внутри 44px-строки, нажимается вся
     строка тоггла. Словесное состояние ушло в aria-label (ledger.js). */
  .l-filter-toggle-action {
    width: 30px;
    height: 30px;
    display: inline-grid;
    place-items: center;
    flex: 0 0 auto;
    border-radius: var(--l-r-full);
    background: var(--l-gray-150);
    color: var(--l-text-2);
  }
  .l-filter-toggle-chevron {
    display: grid;
    color: var(--l-text-3);
    transition: transform 140ms ease;
  }
  .l-filter-shell.is-filter-open .l-filter-toggle-chevron { transform: rotate(180deg); }
  .l-filter-panel {
    display: none;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
    min-width: 0;
    padding: 10px;
    border: 0;
    border-top: 1px solid var(--l-hairline);
    /* Панель — последний блок внутри скруглённой секции. С квадратными углами
       её непрозрачный фон закрашивал скругление и рамку .l-filter-mobile-section
       снизу. Минус 1px — толщина рамки секции. */
    border-radius: 0 0 calc(var(--l-r-md) - 1px) calc(var(--l-r-md) - 1px);
    background: color-mix(in srgb, var(--l-surface) 88%, var(--l-bg));
  }
/* Раскрытие панели: display:none → grid, стартовый кадр даёт @starting-style.
   Сворачивание мгновенное — transition объявлен только на открытом состоянии. */
.l-filter-shell.is-filter-open .l-filter-panel {
  display: grid;
  transition:
    opacity 140ms ease,
    transform 140ms ease,
    display 140ms allow-discrete;
}
@starting-style {
  .l-filter-shell.is-filter-open .l-filter-panel {
    opacity: 0;
    transform: translateY(-4px);
  }
}
.l-filter-shell.is-filter-pending {
  pointer-events: none;
  opacity: .72;
}
.l-filter-shell.is-filter-pending .l-filter-toggle-chevron {
  animation: l-filter-pending 700ms linear infinite;
}
@keyframes l-filter-pending {
  to { transform: rotate(360deg); }
}
  .l-filter-panel > * {
    width: 100%;
    max-width: none;
    min-width: 0;
    margin: 0;
  }
  .l-filter-panel > [data-filter-size="full"],
  .l-filter-panel > .l-seg { grid-column: 1 / -1; }
  .l-filter-panel > [data-filter-size="short"] {
    width: auto;
    justify-self: start;
  }
  .ledger .l-filter-panel > .l-filter-reset {
    grid-column: 1 / -1;
    width: 44px;
    height: 44px;
    justify-self: end;
    margin-top: 2px;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
  }
  .l-filter-panel .l-dd-btn,
  .l-filter-panel .l-select { width: 100%; min-height: 44px; }
  .l-filter-panel .l-dd-btn {
    max-width: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .l-filter-panel > .l-seg {
    width: 100%;
    overflow-x: auto;
    white-space: nowrap;
  }
  .l-filter-panel > .l-seg > * { flex: 1 0 auto; text-align: center; }
  .l-filters:not(.l-filter-shell) > .l-select,
  .l-filters:not(.l-filter-shell) > .l-dd {
    width: calc(50% - 4px);
    max-width: none;
    flex: 1 1 calc(50% - 4px);
  }
  .l-filters:not(.l-filter-shell) > .l-dd .l-dd-btn { width: 100%; min-height: 44px; }
  .l-filters:not(.l-filter-shell) > .l-attn { min-height: 44px; }
  .l-filters:not(.l-filter-shell) > .l-input,
  .l-filters:not(.l-filter-shell) > input[type="search"] {
    width: 100%;
    max-width: none;
    min-height: 44px;
    flex: 1 0 100%;
  }
  /* Обычные ленты видов переносятся на строки, если не помещаются. Панель задач
     ниже получает собственную компактную сетку: разделы, иконки видов + поиск,
     затем единый блок фильтров. */
  .l-viewbar {
    margin-inline: -14px;
    padding: 0 14px 2px;
    align-items: stretch;
    flex-wrap: wrap;
    gap: 8px;
    overflow-x: visible;
    scroll-padding-inline: 14px;
  }
  .l-viewbar .l-seg {
    flex: 1 0 100%;
    display: flex;
    white-space: nowrap;
  }
  /* gap, а не пробел в разметке: inline-flex схлопывает пробельный узел между
     подписью и счётчиком, и «Клиенты 4» читались как «Клиенты4». */
  .l-viewbar .l-seg > * { flex: 1 1 0; gap: 5px; text-align: center; min-height: 36px; display: inline-flex; align-items: center; justify-content: center; }
  .l-viewbar .l-spacer { display: none; }
  /* Выбор колонок относится к таблице, а на телефоне вместо неё карточки:
     кнопка вела в панель, которая ни на что не влияет, и обрезалась краем. */
  .l-colpicker { display: none; }
  /* Табличный вид на телефоне скрыт (tasks.js уводит с ?view=table на список). */
  .l-viewbar [data-view="table"] { display: none; }
  /* ========================================================================
     Одна строка управления (t2-ctl). Правило 1 дизайн-системы: на телефоне
     над списком стоит ровно одна полоса. Вид — сегмент значками 44×40,
     раздел и просроченные — чипы, поиск и все селекты уходят за значок
     фильтров. Прежняя сетка из ленты разделов, ленты видов и открытого
     поиска занимала три строки и уводила первую задачу за 190px от верха.
     ====================================================================== */
  /* Полоса плотнее эталона на 4px сверху и снизу: с шапкой кабинета над ней
     воздуха и так достаточно, а замер «≤160px до первой строки данных» на
     iPhone SE держится только так. Цели нажатия внутри не меняются. */
  .t2-ctl { display: flex; padding: 6px 0 7px; margin-bottom: 6px; }
  .l-task-controls { display: block; margin-bottom: 0; }
  /* Ленты видов и разделов остаются разметкой ПК: на телефоне их заменяет
     строка управления, поэтому здесь они не рисуются вовсе. */
  .l-task-controls .l-task-viewbar { display: none; }
  .l-task-controls .l-tasks-search {
    width: 100%;
    max-width: none;
    min-width: 0;
    min-height: 44px;
    margin: 0;
  }
  /* Клавиатурная подсказка на телефоне ни о чём не говорит — как и в заметках. */
  .l-tasks-search kbd { display: none; }
  /* Просроченные стоят чипом в самой строке управления — внутри панели это
     был бы второй такой же фильтр. */
  .l-filter-shell--ext .l-task-overdue-filter { display: none; }
  /* Панель фильтров открывает чип-значок строки управления, поэтому
     собственная полоса-переключатель секции здесь не нужна, а рамку и фон
     берёт на себя сама панель. */
  .l-filter-shell--ext { margin-bottom: 0; }
  .l-filter-shell--ext.is-filter-open { margin-bottom: 16px; }
  .l-filter-shell--ext .l-filter-mobile-head { display: none; }
  .l-filter-shell--ext .l-filter-mobile-section { border: 0; background: none; }
  .l-filter-shell--ext .l-filter-panel {
    border: 1px solid var(--l-border);
    border-radius: var(--l-r-md);
  }
  /* Экран со строкой управления отдаёт ей воздух шапки: иначе шапка (129px),
     поле .l-main (12px) и сама строка (63px) уводят первую строку данных за
     190px. Правило «до первой строки данных ≤160px» держится этой четвёркой. */
  html.l-nav-tabs body.l-has-tabs:has(.t2-ctl) .l-main { padding-top: 0; }
  body:has(.t2-ctl) .t2-appbar { padding-bottom: 4px; }
  body:has(.t2-ctl) .t2-appbar-top { min-height: 44px; }
  body:has(.t2-ctl) .t2-appbar-head { min-height: 34px; margin-top: 2px; }
  /* Число просроченных стоит чипом в строке управления — в шапке это дубль. */
  body:has(.t2-ctl) .t2-appbar-count { display: none; }
  /* Полосы отчёта заменяют широкую таблицу ДДС на телефоне. */
  .t2-reps { display: grid; gap: 12px; margin-bottom: 14px; }
  .l-op-period-seg { display: none !important; }
  .l-filter-panel > .l-dd:has(> .l-op-period-select) {
    display: block;
    width: 100%;
  }

  .l-panel {
    padding: 17px 16px;
    border-radius: 13px;
  }
  .l-grid2,
  .l-grid3,
  .l-account-form .l-grid3,
  .l-org-contact-grid { grid-template-columns: minmax(0, 1fr); }
  /* В одну колонку каждый ряд сетки становится отдельным полем: 12px row-gap
     десктопа здесь мало — поля и их подсказки сливались в один столбец. */
  .l-grid2,
  .l-grid3 { row-gap: 14px; }
  /* Чекбоксы на телефоне — каждый со своей строки и во всю ширину: тап-цель
     шире, а подряд идущие правила не читаются одной строкой. */
  .l-check { display: flex; }
  .l-grid2 > div[style*="grid-column"],
  .l-grid3 > div[style*="grid-column"],
  .l-org-contact-grid .l-org-contact-website { grid-column: auto !important; }
  .l-form-actions {
    align-items: stretch;
    flex-wrap: wrap;
  }
  .l-form-actions .l-btn { flex: 1 1 140px; }
  /* формы справочников: чекбокс и кнопка «Добавить» перестают тесниться в строку */
  .l-grid3--form .l-formcol {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .l-grid3--form .l-formcol .l-check { margin-top: 2px; }
  .l-grid3--form .l-formcol .l-btn {
    width: 100%;
    min-height: 44px;
    justify-content: center;
  }
  .l-account-email { align-items: flex-start; flex-direction: column; gap: 2px; }
  .l-banner { align-items: flex-start; flex-direction: column; }
  .l-banner .l-btn,
  .l-banner .l-inline-form,
  .l-banner .l-inline-form .l-btn { width: 100%; }

  .l-money-overview {
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
    margin-bottom: 24px;
  }
  .l-money-card {
    height: auto;
    padding: 16px 14px;
  }
  .l-money-card-head {
    margin-bottom: 12px;
    gap: 10px;
  }
  .l-money-head-value { font-size: 15px; }
  .l-money-account-group-head,
  .l-money-account-row { gap: 9px; }
  .ledger a.l-money-account-row {
    min-height: 48px;
    padding-inline: 7px;
  }
  .l-money-setup {
    min-height: 0;
    padding: 16px;
  }
  .l-money-setup-actions { width: 100%; }
  .l-money-setup-actions .l-btn { flex: 1 1 130px; }
  .ledger a.l-money-list-row {
    min-height: 52px;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: 8px;
  }
  .ledger a.l-money-list-row--debt {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .l-money-receivable-summary strong { font-size: 12.5px; }
  .l-money-debt-side strong { font-size: 11.5px; }
  .l-money-section-head {
    margin-bottom: 11px;
    align-items: stretch;
    flex-direction: column;
    gap: 11px;
  }
  .l-turnover-periods {
    width: 100%;
    display: flex;
  }
  .l-turnover-periods > * {
    min-height: 40px;
    flex: 1 1 0;
    text-align: center;
  }
  .l-turnover-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
  }
  .l-turnover-card,
  .l-turnover-card.is-total {
    grid-column: auto;
    padding: 15px 14px;
  }
  .l-turnover-row {
    min-height: 37px;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 12px;
  }
  .l-turnover-row > *:not(:first-child) { text-align: right; }
  [data-turnover-active="month"] [data-turnover-cell]:not([data-turnover-cell="month"]),
  [data-turnover-active="quarter"] [data-turnover-cell]:not([data-turnover-cell="quarter"]),
  [data-turnover-active="year"] [data-turnover-cell]:not([data-turnover-cell="year"]) {
    display: none;
  }

  .l-table-card {
    position: relative;
    max-width: 100%;
    overflow-x: auto;
    overscroll-behavior-inline: contain;
    -webkit-overflow-scrolling: touch;
  }
  .l-table {
    width: max-content;
    min-width: 100%;
  }
  .l-table th,
  .l-table td { padding: 11px 12px; }
  .l-table tbody tr { min-height: 46px; }
  .l-table-card:has([data-mobile-scroll])::after {
    content: '';
    position: sticky;
    right: 0;
    float: right;
    width: 18px;
    height: 100%;
    margin-top: calc(-100% + 1px);
    pointer-events: none;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--l-bg) 58%, transparent));
  }
  [data-mobile-scroll] th:first-child,
  [data-mobile-scroll] td:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--l-surface);
    box-shadow: 1px 0 var(--l-hairline);
  }
  [data-mobile-scroll] thead th:first-child { z-index: 3; }
  .l-table-card:has(.l-mobile-cards) {
    overflow: visible;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
  }
  .l-mobile-cards,
  .l-mobile-cards tbody {
    width: 100%;
    min-width: 0;
    display: block;
  }
  .l-mobile-cards thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
  .l-mobile-cards tbody {
    display: grid;
    gap: 10px;
  }
  .l-mobile-cards tbody tr {
    position: relative;
    min-width: 0;
    min-height: 0;
    padding: 14px;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 11px 14px;
    border: 1px solid var(--l-border);
    border-radius: var(--l-r-lg);
    background: var(--l-surface);
    box-shadow: var(--l-shadow-card);
  }
  .l-mobile-cards tbody tr:hover { background: var(--l-surface-hover); }
  .l-mobile-cards tbody td,
  .l-mobile-cards tbody th {
    min-width: 0;
    padding: 0;
    display: block;
    border: 0;
    text-align: left;
    overflow-wrap: anywhere;
  }
  .l-mobile-cards tbody td::before,
  .l-mobile-cards tbody th::before {
    content: attr(data-mobile-label);
    min-height: 14px;
    margin-bottom: 3px;
    display: block;
    color: var(--l-text-3);
    font: 650 9.5px/1.2 var(--l-font);
    letter-spacing: .065em;
    text-transform: uppercase;
  }
  .l-mobile-cards tbody td:not([data-mobile-label])::before,
  .l-mobile-cards tbody th:not([data-mobile-label])::before { display: none; }
  .l-mobile-cards .is-mobile-primary {
    order: -1;
    grid-column: 1 / -1;
    padding-right: 38px;
    color: var(--l-text);
    font-size: 14px;
  }
  .l-mobile-cards .is-mobile-primary::before { display: none; }
  .l-mobile-cards .is-mobile-check {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    z-index: 2;
  }
  .l-mobile-cards .is-mobile-check::before { display: none; }
  /* Отметка строки на телефоне: рисунок 22px вместо 16px, а цель нажатия — не
     меньше 40px прозрачным ::after (тот же приём, что у круга «готово»).
     ::before у чекбокса занят галочкой, поэтому мишень именно на ::after.
     Атрибут [type="checkbox"] в селекторе обязателен: базовое правило
     .ledger input[type="checkbox"] специфичнее пары классов и иначе
     возвращало бы 16px (так и не срабатывал прежний .l-doc .l-rowcheck). */
  .ledger input[type="checkbox"].l-rowcheck,
  .ledger input[type="checkbox"].l-rowcheck-master {
    position: relative;
    width: 22px;
    height: 22px;
  }
  .ledger input[type="checkbox"].l-rowcheck::after,
  .ledger input[type="checkbox"].l-rowcheck-master::after {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: max(100%, 40px);
    height: max(100%, 40px);
  }
  .l-mobile-cards .is-mobile-actions {
    order: 10;
    grid-column: 1 / -1;
    min-height: 38px;
    padding-top: 8px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    border-top: 1px solid var(--l-hairline);
  }
  .l-mobile-cards .is-mobile-actions::before { display: none; }
  .l-mobile-cards .is-mobile-actions .l-inline-form { display: inline-flex; }
  .l-mobile-cards .is-mobile-actions [style*="margin-left"] { margin-left: 0 !important; }
  /* Текстовые действия карточки («Изменить», «В архив», «Подтвердить») были
     ссылками высотой 19–27px и стояли впритык — палец попадал в соседнюю.
     Значки свои 44×44 получают отдельным правилом .l-iconbtn. */
  .l-mobile-cards:not(.l-cards-compact) .is-mobile-actions a,
  .l-mobile-cards:not(.l-cards-compact) .is-mobile-actions button:not(.l-iconbtn) {
    min-height: 40px;
    padding-inline: 6px;
    display: inline-flex;
    align-items: center;
  }
  .l-mobile-cards .is-mobile-reorder {
    order: 9;
    grid-column: 1 / -1;
    min-height: 38px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
  }
  .l-mobile-cards .is-mobile-reorder::before { display: none; }
  .l-mobile-cards .num { text-align: left; }
  /* Сумма документа в карточке: значение, подпись «оплачено» и полоса — один
     левый столбик. В таблице .l-amt прижимает содержимое вправо, и в карточке
     подпись улетала к противоположному краю от суммы, а полоса растягивалась
     во всю ширину карточки — блок переставал читаться как одно целое. */
  .l-mobile-cards .l-amt {
    display: block;
    width: 100%;
    min-width: 0;
    text-align: left;
  }
  .l-mobile-cards .l-amt-sub { margin-top: 3px; }
  .l-mobile-cards .l-paybar {
    max-width: 132px;
    margin-top: 6px;
  }
  /* «Доход по налогам»: контроль лимитов — стопка прогресс-баров, а не
     значение столбца. В карточке он занимает всю ширину и идёт без подписи,
     потому что подписи стоят внутри самих строк лимита. JS проставляет
     data-mobile-label из thead всем ячейкам, поэтому подпись гасится в CSS. */
  .l-mobile-cards td.l-tax-limits-cell {
    grid-column: 1 / -1;
    min-width: 0;
    margin-top: 2px;
  }
  .l-mobile-cards tbody td.l-tax-limits-cell::before { content: none; }
  /* Нулевые режимы в карточке — шум: у одного ИП обычно занят один режим. */
  .l-mobile-cards td.is-zero { display: none; }
  /* Компактная карточка операций: контрагент и сумма в заголовке, затем
     дата с кассой, проект и однострочное примечание. Категория остаётся
     desktop-колонкой: на телефоне тип уже читается по цвету заголовка. */
  .l-cards-compact tbody tr {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    padding: 10px 12px;
  }
  .l-cards-compact tbody td::before,
  .l-cards-compact tbody th::before { display: none; }
  .l-cards-compact tbody td { line-height: 1.35; }
  /* Явный перенос после заголовка не зависит от длины контрагента. */
  .l-cards-compact tbody tr::before {
    content: '';
    flex: 0 0 100%;
    height: 0;
    order: 3;
  }
  /* Бейджи и «Выбрать проект» ужимаются до высоты строки реквизитов, иначе
     они одни задают высоту всей строки. */
  .l-cards-compact .l-inline-choice { min-height: 21px; padding: 1px 8px; }
  .l-cards-compact tbody .l-badge { gap: 5px; padding: 1px 8px; font-size: 11px; }
  .l-cards-compact tbody .l-badge::before { width: 5px; height: 5px; }
  .l-cards-compact .l-op-party-desktop,
  .l-cards-compact .l-planner-operation-desktop { display: none; }
  .l-cards-compact .l-op-party.l-op-tone--income { color: var(--l-accent-ink); }
  .l-cards-compact .l-op-party.l-op-tone--expense { color: var(--l-danger); }
  .l-cards-compact .l-op-party.l-op-tone--transfer { color: var(--l-info); }
  .l-cards-compact .l-op-party-mobile,
  .l-cards-compact .l-op-mobile-flags,
  .l-cards-compact .l-planner-card-date { display: inline-flex; }
  .l-cards-compact .l-op-mobile-flags { align-items: center; gap: 5px; }
  .l-cards-compact .l-op-mobile-flags a { font-size: 11px; }
  /* Нулевая основа держит сумму на одной строке с контрагентом: длинное название
     переносится внутри своей ячейки, а не выталкивает сумму на новый ряд. */
  .l-cards-compact .is-mobile-primary {
    order: 1;
    flex: 1 1 0;
    min-width: 0;
    padding-right: 0;
    font-size: 14px;
    font-weight: 650;
  }
  .l-cards-compact td[data-mobile-label="Сумма"] {
    order: 2;
    flex: 0 0 auto;
    margin-left: auto;
    padding-right: 32px;
    font-size: 14.5px;
    font-weight: 600;
    text-align: right;
  }
  /* Дата и касса делят одну строку; проект получает собственную. */
  .l-cards-compact td[data-mobile-label="Дата"],
  .l-cards-compact td[data-mobile-label="Касса"],
  .l-cards-compact td[data-mobile-label="Проект"] {
    min-width: 0;
    color: var(--l-text-3);
    font-size: 12px;
  }
  .l-cards-compact td[data-mobile-label="Дата"] {
    order: 4;
    flex: 0 0 auto;
    white-space: nowrap;
  }
  .l-cards-compact td[data-mobile-label="Касса"] {
    order: 5;
    flex: 1 1 0;
  }
  .l-cards-compact td[data-mobile-label="Проект"] {
    order: 6;
    flex: 0 0 100%;
  }
  .l-cards-compact td[data-mobile-label="Проект"] .l-inline-choice { max-width: 100%; }
  .l-cards-operations td[data-mobile-label="Категория"] { display: none; }
  .l-cards-compact td[data-mobile-label="Примечание"] {
    order: 7;
    flex: 1 1 0;
    min-width: 0;
    max-width: none !important;
    overflow: hidden !important;
    text-overflow: ellipsis;
    white-space: nowrap !important;
    color: var(--l-text-3);
    font-size: 12px;
  }
  .l-cards-compact td[data-mobile-label="Примечание"]:empty { display: none; }
  /* Действия заканчиваются на том же правом крае, что и верхний чекбокс. */
  .l-cards-compact .is-mobile-actions {
    order: 8;
    flex: 0 0 auto;
    min-height: 0;
    margin-left: auto;
    padding-top: 0;
    align-items: center;
    gap: 2px;
    border-top: 0;
  }
  .l-cards-compact .is-mobile-check {
    top: 4px;
    right: 4px;
  }
  /* --- Календарь платежей ---------------------------------------------------
     Карточка того же компактного вида, что у реестра операций, плюс лента
     даты как заголовок группы: колонка «Дата» в каждой карточке повторяла
     одно и то же и съедала строку. */
  /* «сейчас …» стоит под итогом справа, в колонке значений строки-плитки. */
  .l-tiles--plan .l-tile-sub { grid-column: 2; text-align: right; }
  /* На desktop даты остаются лентами. В мобильной карточке дата стоит рядом
     с кассой, поэтому отдельная лента была бы повтором. */
  .l-mobile-cards tr.l-planner-day,
  .l-mobile-cards tr.l-planner-day:hover {
    display: none;
  }
  .l-cards-planner .l-planner-account {
    order: 4;
    flex: 0 0 100%;
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--l-text-3);
    font-size: 12px;
  }
  .l-cards-planner .l-planner-card-date { align-items: center; gap: 5px; white-space: nowrap; }
  .l-cards-planner td[data-mobile-label="Проект"] { order: 5; }
  .l-cards-compact.l-cards-planner .l-planner-note {
    order: 6;
    flex: 0 0 100%;
  }
  .l-cards-planner tbody td:empty { display: none; }
  .l-cards-planner .l-planner-balance { display: none; }
  .l-cards-compact.l-cards-planner .l-op-party,
  .l-cards-planner .l-op-amount,
  .l-cards-planner td[data-mobile-label="Проект"],
  .l-cards-planner td[data-mobile-label="Проект"] a { color: var(--l-text-3); }
  .l-cards-planner .is-mobile-actions { order: 7; }
  .l-cards-planner .is-mobile-actions .l-op-status {
    min-height: 40px;
    display: inline-flex;
    align-items: center;
  }
  /* Кассовый разрыв: на телефоне красится карточка целиком — ячейки
     прозрачные, иначе полоса цвета шла бы кусками по ленте. */
  .l-mobile-cards tr.l-row-gap,
  .l-mobile-cards tr.l-row-gap:hover { background: var(--l-danger-soft); }
  .l-mobile-cards tr.l-row-gap td { background: transparent; }
  .l-doc-items-table .is-mobile-seq { display: none; }
  .l-doc-items-table .is-mobile-primary {
    padding-right: 0;
    font-size: 13.5px;
    line-height: 1.4;
  }
  /* Редакторы справочников: карточка = «цвет + название», счётчик и одна нижняя
     полоса, где слева стрелки порядка, а справа действия строки. */
  .l-panel .l-rows-editor tbody tr {
    border-color: var(--l-hairline);
    box-shadow: none;
  }
  /* левая колонка ужимается до стрелок порядка — действиям строки остаётся
     максимум ширины (везде это значки 44×44, включая категории) */
  .l-mobile-cards.l-rows-editor tbody tr { grid-template-columns: auto minmax(0, 1fr); }
  /* пустой счётчик и слот под ручку у закреплённого этапа не держат место */
  .l-rows-editor tbody td:empty,
  .l-rows-editor td.l-rows-editor-slot { display: none; }
  .l-rows-editor .is-mobile-primary { padding-right: 0; }
  /* Счётчик занимал левую половину отдельной строки, и справа от него над
     значками действий висела пустая полоса ~40px. Он читается подписью под
     названием: одна строка во всю ширину, подпись и число рядом. */
  .l-rows-editor tbody td[data-mobile-label]:not(:empty):not(.is-mobile-actions):not(.is-mobile-reorder) {
    grid-column: 1 / -1;
    display: flex;
    align-items: baseline;
    gap: 6px;
  }
  .l-rows-editor tbody td[data-mobile-label]:not(:empty):not(.is-mobile-actions):not(.is-mobile-reorder)::before {
    min-height: 0;
    margin-bottom: 0;
  }
  .l-rows-editor .is-mobile-primary .l-iconbtn {
    min-width: 36px;
    min-height: 36px;
    margin-block: -5px;
  }
  .l-rows-editor tbody tr:has(.is-mobile-actions)::after {
    content: '';
    order: 9;
    grid-column: 1 / -1;
    height: 1px;
    background: var(--l-hairline);
  }
  .l-rows-editor .is-mobile-reorder,
  .l-rows-editor .is-mobile-actions {
    order: 10;
    min-height: 44px;
    padding-top: 0;
    border-top: 0;
  }
  .l-rows-editor .is-mobile-reorder {
    grid-column: 1;
    justify-content: flex-start;
  }
  .l-rows-editor .is-mobile-actions {
    grid-column: 2;
    flex-wrap: wrap;
  }
  .l-rows-editor tbody tr:not(:has(.is-mobile-reorder)) .is-mobile-actions {
    grid-column: 1 / -1;
  }
  .l-rows-editor .l-mobile-order-controls { margin-left: 0; }
  /* Категории: подсветка и разделители строк — приём таблицы, в карточках лишний;
     вложенная статья отступает от родителя. */
  .l-rows-editor .l-cat-parent td,
  .l-rows-editor .l-cat-group + .l-cat-group .l-cat-parent td {
    background: transparent;
    border-top: 0;
  }
  .l-rows-editor .l-cat-child { margin-left: 12px; }
  .l-rows-editor .l-cat-child-name { padding-left: 0; }
  .l-doc-meta-panel .l-kv {
    grid-template-columns: minmax(0, 1fr);
    gap: 3px;
  }
  .l-doc-meta-panel .l-kv .k:not(:first-child) { margin-top: 10px; }
  /* Явный модификатор той же механики — для страниц без l-doc-meta-panel
     (приглашение): ключ над значением, чипы и длинные строки во всю ширину. */
  .l-kv--stack {
    grid-template-columns: minmax(0, 1fr);
    gap: 3px;
  }
  .l-kv--stack .k:not(:first-child) { margin-top: 10px; }
  .l-doc-meta-panel .l-doc-badges { margin-top: 2px; }
  .l-mobile-cards .l-select,
  .l-mobile-cards .l-dd { width: 100%; max-width: none; }
  .l-mobile-cards .l-dd-btn { width: 100%; }
  .l-mobile-order-controls {
    margin-left: 4px;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    vertical-align: middle;
  }
  .l-mobile-order-controls button {
    width: 36px;
    height: 36px;
    padding: 0;
    border: 1px solid var(--l-border);
    border-radius: 9px;
    background: var(--l-surface);
    color: var(--l-text-2);
    font: 600 17px/1 var(--l-font);
  }
  .l-mobile-order-controls button:disabled { opacity: .28; }
  .l-drag-handle { touch-action: none; }
  .l-items-panel,
  .l-panel:has(.l-items) { min-width: 0; overflow: hidden; }
  .l-items,
  .l-items tbody { width: 100%; min-width: 0; display: block; }
  .l-items thead { display: none; }
  .l-items tbody {
    display: grid;
    gap: 10px;
  }
  .l-items tbody tr {
    position: relative;
    padding: 13px;
    display: grid;
    grid-template-columns: minmax(0, .65fr) minmax(0, .8fr) minmax(0, 1fr);
    gap: 10px;
    border: 1px solid var(--l-border);
    border-radius: var(--l-r-md);
    background: var(--l-bg);
  }
  .l-items tbody td {
    min-width: 0;
    width: auto !important;
    padding: 0;
    display: block;
  }
  .l-items tbody td:first-child {
    grid-column: 1 / -1;
    padding-right: 34px;
  }
  .l-items tbody td::before {
    content: attr(data-mobile-label);
    margin: 0 0 4px 2px;
    display: block;
    color: var(--l-text-3);
    font: 650 9px/1.2 var(--l-font);
    letter-spacing: .06em;
    text-transform: uppercase;
  }
  .l-items tbody td:not([data-mobile-label])::before { display: none; }
  .l-items .sum-cell {
    padding: 11px 8px 0;
    align-self: end;
    text-align: left;
  }
  .l-items tbody td:last-child {
    position: absolute;
    top: 10px;
    right: 8px;
  }
  .l-items .l-row-del {
    width: 36px;
    height: 36px;
    opacity: 1;
  }
  .l-items input.l-input { width: 100%; min-width: 0; max-width: 100%; }
  #l-add-row { width: 100%; }
  .l-directory-tools { align-items: stretch; }
  .l-live-search { width: 100%; flex: 1 1 auto; }
  .l-live-search-count { display: none; }

  .l-modal-overlay {
    padding: 0;
    align-items: flex-end;
  }
  .l-modal,
  .l-modal.l-op-modal,
  .l-modal.l-recur-modal {
    width: 100%;
    max-width: none;
    max-height: min(92dvh, 820px);
    margin: 0;
    border-radius: 20px 20px 0 0;
    overflow-y: auto;
  }
  /* Липкая первая колонка таблиц (z-index 2, у thead — 3) рисовалась поверх
     липкого футера модалки: в налоговом календаре столбец «Платёж» налезал на
     «Добавить в план» и «Отмена». Футер поднят выше обоих слоёв. */
  .l-modal .actions {
    position: sticky;
    bottom: 0;
    z-index: 4;
    margin-inline: -20px;
    padding: 14px 20px max(14px, env(safe-area-inset-bottom));
    background: var(--l-surface);
    border-top: 1px solid var(--l-hairline);
  }
  .l-modal.l-op-modal .l-op-actions,
  .l-modal.l-recur-modal .l-recur-modal-actions {
    padding-bottom: max(13px, env(safe-area-inset-bottom));
  }
  /* Два «Сохранить…» словами занимали всю ширину футера и уезжали в столбец.
     На телефоне они становятся значками 44×44 и стоят в один ряд справа. */
  .l-modal.l-op-modal .l-op-actions {
    flex-wrap: nowrap;
    justify-content: flex-end;
  }
  .l-modal.l-op-modal .l-op-actions .l-btn > span { display: none; }
  .l-modal.l-op-modal .l-op-actions .l-btn {
    flex: 0 0 auto;
    width: auto;
    min-width: 44px;
    min-height: 44px;
    padding: 0 12px;
    justify-content: center;
    gap: 0;
  }
  .l-modal.l-op-modal .l-op-actions .l-btn svg { width: 19px; height: 19px; }
  .l-pop {
    max-width: calc(100vw - 20px);
    max-height: min(70dvh, 560px);
    overflow-y: auto;
  }
  .l-dd-menu {
    max-width: calc(100vw - 20px);
    max-height: min(62dvh, 460px);
  }
  .l-bulkbar {
    right: 10px;
    bottom: max(10px, env(safe-area-inset-bottom));
    left: 10px;
    width: auto;
    max-width: none;
    max-height: calc(100dvh - 20px - env(safe-area-inset-bottom));
    padding: 10px;
    align-items: stretch;
    gap: 8px;
    flex-wrap: wrap;
    overflow-y: auto;
    border-radius: 18px;
    transform: none;
  }
  .l-bulkbar > .l-bulkbar-summary {
    min-height: 44px;
    padding: 0 52px 0 4px;
    display: flex;
    align-items: center;
    flex: 1 0 100%;
  }
  .l-bulkbar .l-btn:not([data-bulk="clear"]) {
    min-width: 0;
    min-height: 42px;
    flex: 1 1 100px;
    justify-content: center;
    white-space: normal;
  }
  .l-bulkbar [data-bulk="clear"] {
    position: absolute;
    top: 12px;
    right: 10px;
    width: 40px;
    height: 40px;
    min-width: 40px;
    min-height: 40px;
    padding: 0;
    display: inline-grid;
    place-items: center;
    border-radius: 10px;
    line-height: 1;
  }
  /* Карточка задачи не занимает экран целиком: слева остаётся полоса подложки,
     по которой панель закрывается касанием (как в редакторе заметки). */
  .l-drawer {
    --drawer-safe-top: max(12px, env(safe-area-inset-top));
    top: 0;
    right: 0;
    bottom: 0;
    left: auto;
    width: min(92%, 560px);
    height: 100dvh;
    max-width: none;
    padding: var(--drawer-safe-top) 14px env(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
    border-left: 1px solid var(--l-border);
    overscroll-behavior: contain;
  }
  .l-drawer .l-tcardfull-head {
    position: sticky;
    top: calc(0px - var(--drawer-safe-top));
    z-index: 8;
    min-height: 58px;
    margin: calc(0px - var(--drawer-safe-top)) -14px 12px;
    padding: max(12px, env(safe-area-inset-top)) 14px 8px;
    background: color-mix(in srgb, var(--l-surface) 94%, transparent);
    border-bottom: 1px solid var(--l-hairline);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
  }
  /* Мета карточки задачи — одинаково в выдвижной панели и на /tasks/:id.
     Подпись сжимается до значка: словом она занимала 92px из 375, и срок
     «26.07 · 14:30 — 90 мин» переносился на три строки. */
  .l-tcardfull-meta {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
  }
  .l-tmetarow {
    min-height: 40px;
    align-items: flex-start;
  }
  .l-tmetarow .k {
    width: 28px;
    flex: 0 0 28px;
    padding-top: 9px;
    color: var(--l-text-3);
  }
  .l-tmetarow .k > svg { display: block; }
  .l-tmetarow .k > span { display: none; }
  .l-tmetarow button,
  .l-tmetarow a {
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    white-space: normal;
    text-align: left;
  }
  /* Полная карточка задачи (/tasks/:id) — та же вёрстка, что и в выдвижной
     панели: удаление пункта чек-листа должно быть видно и там. */
  .l-drawer .l-checkitem-del,
  .l-tcardpage .l-checkitem-del { min-width: 40px; min-height: 40px; opacity: .68; }
  /* Без hover значки правки и удаления показываются постоянно. */
  .l-comment-tools { opacity: 1; }
  .l-comment-tools .l-comment-tool { width: 36px; height: 36px; min-width: 36px; min-height: 36px; }
  .l-comment-form .l-send { width: 44px; height: 44px; }
  /* Подвал карточки — обычный конец содержимого, не закреплённая полоса:
     закреплённый вариант съедал место у длинных карточек и перекрывал текст. */
  .l-drawer .l-tcardfull-foot {
    padding-bottom: max(12px, env(safe-area-inset-bottom));
    flex-wrap: wrap;
  }
  .l-drawer .l-tcardfull-foot > span:first-child { width: 100%; }
  .l-drawer .l-tcardfull-foot .l-spacer { display: none; }
  .l-drawer .l-tcardfull-foot .l-btn {
    min-height: 44px;
    flex: 0 1 auto;
  }

  .l-board {
    margin-inline: -14px;
    padding: 2px 14px 14px;
    scroll-padding-inline: 14px;
    scroll-snap-type: x proximity;
  }
  /* Колонка уже вьюпорта на 88px: справа виден край следующего этапа —
     подсказка, что доска листается, и цель для переноса карточки пальцем. */
  .l-board-col {
    width: calc(100vw - 88px);
    flex: 0 0 calc(100vw - 88px);
    min-width: calc(100vw - 88px);
    max-width: calc(100vw - 88px);
    scroll-snap-align: start;
  }
  .l-board-mobile-tabs {
    margin: 0 -14px 8px;
    padding: 0 14px 4px;
    display: flex;
    gap: 7px;
    overflow-x: auto;
    scroll-padding-inline: 14px;
  }
  .l-board-mobile-tabs button {
    min-height: 40px;
    max-width: 210px;
    padding: 7px 10px;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    flex: 0 0 auto;
    border: 1px solid var(--l-border);
    border-radius: var(--l-r-full);
    background: var(--l-surface);
    color: var(--l-text-2);
    font: 500 12px/1.2 var(--l-font);
  }
  .l-board-mobile-tabs button > span:nth-child(2) {
    max-width: 130px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .l-board-mobile-tabs button small { color: var(--l-text-3); font-size: 10px; }
  .l-board-mobile-tabs button.is-active {
    border-color: color-mix(in srgb, var(--l-accent) 36%, var(--l-border));
    background: var(--l-accent-soft);
    color: var(--l-accent-ink);
  }
  .l-colmenu { opacity: 1; }
  /* Компактная строка: сама строка — тап-мишень 44px+, поэтому чекбокс и
     мета-чипы уменьшены до вторичных размеров, а высоту задают отступы,
     а не min-height заголовка. Ряды разделяет зазор группы (8px ниже).
     Обычная плотность — 52px, режим «компактные строки» опускает пол до 44px:
     это минимум цели нажатия, ниже опускаться нельзя. */
  .l-trow {
    min-height: 52px;
    padding: 9px 10px;
    display: grid;
    grid-template-columns: 36px minmax(0, 1fr);
    gap: 5px 8px;
    align-items: center;
    cursor: pointer;
  }
  .l-trow .l-done-check {
    width: 24px;
    height: 24px;
    margin: 0 6px;
  }
  .l-trow .l-done-check.is-on::after {
    left: 7px;
    top: 3px;
    width: 5px;
    height: 10px;
  }
  .l-trow-title {
    overflow: hidden;
    font-size: 14px;
    line-height: 1.35;
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .l-trow-meta {
    grid-column: 1 / -1;
    min-width: 0;
    margin: 2px 0 0 36px;
    display: flex;
    flex-wrap: wrap;
    gap: 4px 6px;
  }
  .l-trow-meta button,
  .l-trow-meta .l-tmeta {
    min-height: 28px;
    padding: 4px 6px;
    display: inline-flex;
    align-items: center;
    font-size: 11px;
  }
  .l-tgroup-body { gap: 8px; }
  .l-trow .l-tproject.is-empty,
  .l-trow .l-tdue.is-empty { opacity: .72; }
  /* Массовый выбор в списке: чекбоксы живут в разметке всегда, но появляются
     только в режиме выбора (долгое нажатие по строке) — иначе на телефоне
     панель массовых действий была недостижима вовсе, она держалась на
     табличном виде, который на телефоне скрыт. Чекбокс встаёт на место круга
     «готово», поэтому строка не перестраивается и не прыгает. */
  /* Отметка встаёт на место круга «готово» и держит его размер: 16px базового
     чекбокса на сенсорном экране не поймать. */
  .ledger .l-trow .l-rowcheck { margin: 0 6px; width: 22px; height: 22px; }
  .l-tgroups.is-select-mode .l-trow .l-done-check { display: none; }
  .ledger .l-tgroups.is-select-mode .l-trow .l-rowcheck { display: inline-grid; }
  .l-tgroups.is-select-mode .l-trow { cursor: default; }
  .l-tgroups.is-select-mode .l-trow:has(.l-rowcheck:checked) {
    border-color: color-mix(in srgb, var(--l-accent) 45%, var(--l-border));
    background: var(--l-accent-soft);
  }
  /* В режиме выбора нажатие по строке переключает отметку, а не открывает
     карточку: мета-кнопки внутри строки не должны перехватывать касание. */
  .l-tgroups.is-select-mode .l-trow-meta { pointer-events: none; }
  .l-tgroup-head {
    position: sticky;
    top: calc(58px + env(safe-area-inset-top));
    z-index: 2;
    min-height: 40px;
    margin: 0 -4px 6px;
    padding: 6px 4px;
    background: var(--l-bg);
  }
  .l-inline-add-btn { min-height: 44px; }
  .l-task-empty { min-height: 360px; padding-top: 34px; }

  .l-cp { overflow: visible; }
  .l-cp-head {
    padding: 13px 14px 10px;
    align-items: flex-start;
    flex-wrap: wrap;
  }
  .l-cp-name {
    flex: 1 1 180px;
    overflow-wrap: anywhere;
  }
  .l-cp-head .l-spacer { display: none; }
  .l-attn-chip { white-space: normal; }
  .l-ct-head {
    padding: 10px 14px 8px;
    align-items: flex-start;
    flex-wrap: wrap;
  }
  .l-ct-head .l-spacer { display: none; }
  .l-ct-label {
    min-height: 36px;
    max-width: 100%;
    text-align: left;
    overflow-wrap: anywhere;
  }
  .l-ct-status { min-height: 36px; }
  .l-ct-balance {
    width: 100%;
    white-space: normal;
  }
  .l-ct-head .l-cta,
  .l-ct-head .l-wait { max-width: 100%; white-space: normal; }
  .l-doc {
    position: relative;
    margin: 0 10px 9px;
    padding: 12px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 8px 10px;
    border: 1px solid var(--l-border) !important;
    border-radius: var(--l-r-md);
    background: var(--l-surface);
  }
  .l-doc-id {
    grid-column: 1 / -1;
    min-height: 36px;
    padding-right: 6px;
    flex-wrap: wrap;
  }
  .l-doc-date {
    display: block;
    grid-column: 1;
    grid-row: 2;
  }
  .l-doc > span:empty { display: none; }
  .l-doc .l-amt {
    grid-column: 2;
    grid-row: 2;
    min-width: 0;
  }
  .l-doc .l-status {
    grid-column: 1 / -1;
    min-height: 40px;
    justify-self: stretch;
    justify-content: flex-start;
    text-align: left;
  }
  .l-mobile-cards td[data-mobile-label="Статус"],
  .l-mobile-cards td[data-mobile-label="Статус"] > * {
    justify-content: flex-start;
    text-align: left;
  }
  .l-doc .l-act-cell {
    display: flex;
    grid-column: 1 / -1;
  }
  .l-doc .l-rowcheck {
    width: 22px;
    height: 22px;
  }

  .l-calbar {
    display: grid;
    grid-template-columns: 1fr auto auto auto 1fr;
    align-items: center;
    gap: 8px;
  }
  .l-calbar .l-caltitle {
    grid-column: 1 / -1;
    grid-row: 1;
    width: 100%;
    text-align: center;
  }
  .l-calbar .l-seg {
    grid-column: 1 / -1;
    grid-row: 2;
    width: 100%;
  }
  .l-calbar .l-seg > * { flex: 1; text-align: center; }
  .l-calbar .l-spacer { display: none; }
  .l-calbar > .l-btn:nth-of-type(1) { grid-column: 2; grid-row: 3; }
  .l-calbar > .l-btn:nth-of-type(2) { grid-column: 3; grid-row: 3; }
  .l-calbar > .l-btn:nth-of-type(3) { grid-column: 4; grid-row: 3; }
  .l-cal-month {
    max-width: 100%;
    overflow: hidden;
  }
  .l-cal-month > .l-cal-dow,
  .l-cal-month > .l-cal-week { min-width: 0; }
  .l-cal-dow span {
    padding: 7px 1px;
    text-align: center;
    font-size: 9px;
  }
  .l-cal-day {
    min-height: 82px;
    padding: 4px 3px 20px;
    gap: 2px;
  }
  .l-cal-daynum {
    width: 20px;
    height: 20px;
    margin: 0;
    font-size: 10.5px;
  }
  .l-cal-day .l-calchip {
    min-height: 17px;
    padding: 1px 3px;
    gap: 2px;
    border-radius: 4px;
    font-size: 9px;
  }
  .l-cal-day .l-calchip .t { display: none; }
  .l-cal-day .l-calchip.is-mobile-extra { display: none !important; }
  .l-cal-more {
    position: absolute;
    right: 3px;
    bottom: 5px;
    display: inline-flex;
    color: var(--l-text-3);
    font: 600 9px/1 var(--l-font);
    text-decoration: none;
  }
  .l-cal-day .l-cal-add {
    left: 1px;
    bottom: 0;
    min-width: 25px;
    min-height: 25px;
    padding: 0 4px;
    opacity: .45;
  }
  .l-cal-day:has(.l-cal-more) .l-cal-add { display: none; }

  /* Месяц на телефоне: вместо нечитаемых плашек 43×17 со шрифтом 9px — точки
     по числу задач, а сам список открывается под сеткой по нажатию на день.
     Режим включает tasks-cal.js классом is-mobile-days: без скрипта остаётся
     прежняя раскладка с мини-плашками, ничего не пропадает. */
  .l-cal-month.is-mobile-days .l-cal-day {
    min-height: 56px;
    padding: 4px 3px;
    cursor: pointer;
  }
  .l-cal-month.is-mobile-days .l-calchip,
  .l-cal-month.is-mobile-days .l-cal-more,
  .l-cal-month.is-mobile-days .l-cal-add { display: none !important; }
  .l-cal-month.is-mobile-days .l-cal-day.is-cal-selected {
    position: relative;
    background: var(--l-accent-soft);
    box-shadow: none;
  }
  .l-cal-month.is-mobile-days .l-cal-day.is-cal-selected::after {
    content: '';
    position: absolute;
    inset: 3px;
    z-index: 2;
    border: 1.5px solid var(--l-accent);
    border-radius: 10px;
    pointer-events: none;
  }
  .l-cal-dots {
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    justify-content: center;
    gap: 3px;
    min-height: 10px;
    pointer-events: none;
  }
  .l-cal-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--dot-c, var(--l-gray-400));
  }
  .l-cal-dot.is-done { opacity: .4; }
  .l-cal-dot.is-overdue { background: var(--l-danger); }
  .l-cal-dots-more { font: 600 9px/1 var(--l-font); color: var(--l-text-3); }
  .l-cal-daylist { display: block; margin-top: 14px; }
  .l-cal-daylist-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
    font-size: 13.5px;
    font-weight: 600;
  }
  .l-cal-daylist-head .l-cal-daylist-add {
    margin-left: auto;
    min-height: 40px;
    padding: 0 12px;
  }
  .l-cal-daylist-rows { display: flex; flex-direction: column; gap: 6px; }
  .l-cal-daylist-row {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-height: 44px;
    padding: 8px 10px;
    border: 1px solid var(--l-border);
    border-left: 3px solid var(--chip-c, var(--l-gray-400));
    border-radius: var(--l-r-md);
    background: var(--l-surface);
    color: var(--l-text);
    font: inherit;
    font-size: 13.5px;
    text-align: left;
    cursor: pointer;
  }
  .l-cal-daylist-row .t { flex: 0 0 auto; font-size: 12px; color: var(--l-text-2); }
  .l-cal-daylist-row .n { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
  .l-cal-daylist-row.is-done .n { text-decoration: line-through; color: var(--l-text-3); }
  .l-cal-daylist-row.is-overdue .t { color: var(--l-danger); font-weight: 600; }
  .l-cal-daylist-empty { color: var(--l-text-3); font-size: 13px; padding: 6px 2px; }

  .l-cal-grid { max-width: 100%; overflow: visible; }
  /* Шапка дней прилипает под мобильной панелью раздела — тем же отступом,
     что и заголовок группы списка (.l-tgroup-head). */
  .l-cal-grid-head { top: calc(58px + env(safe-area-inset-top)); }
  .l-cal-mobile-days {
    margin: 0 -14px 8px;
    padding: 0 14px 4px;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(46px, 1fr);
    gap: 5px;
    overflow-x: auto;
    scroll-padding-inline: 14px;
  }
  .l-cal-mobile-days button {
    min-height: 52px;
    padding: 6px 4px;
    display: grid;
    place-items: center;
    gap: 2px;
    border: 1px solid transparent;
    border-radius: 12px;
    background: transparent;
    color: var(--l-text-3);
    font: inherit;
  }
  .l-cal-mobile-days button span { font-size: 9px; text-transform: uppercase; }
  .l-cal-mobile-days button strong { font: 600 14px/1 var(--l-mono); }
  .l-cal-mobile-days button.is-active {
    border-color: color-mix(in srgb, var(--l-accent) 34%, var(--l-border));
    background: var(--l-accent-soft);
    color: var(--l-accent-ink);
  }
  .l-cal-grid--week > .l-cal-grid-head,
  .l-cal-grid--week > .l-cal-allday,
  .l-cal-grid--week .l-cal-grid-body {
    min-width: 0;
    grid-template-columns: 54px minmax(0, 1fr);
  }
  .l-cal-grid--week .l-cal-colhead:not(.is-mobile-selected),
  .l-cal-grid--week [data-cal-allday]:not(.is-mobile-selected),
  .l-cal-grid--week [data-cal-col]:not(.is-mobile-selected) { display: none; }
  .l-cal-grid--day > .l-cal-grid-head,
  .l-cal-grid--day > .l-cal-allday,
  .l-cal-grid--day .l-cal-grid-body { min-width: 0; }
  .l-cal-gutter { width: 54px; }
  .l-cal-gutter-label { font-size: 9px; }

  body:has(.l-notes-app) .l-main { padding: 12px 10px max(16px, env(safe-area-inset-bottom)); }
  .l-notes-head-tools {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
    margin: 0;
  }
  .l-notes-head-tools .l-notes-search,
  .l-notes-head-tools .l-notes-group {
    width: 100%;
    min-width: 0;
    order: initial;
  }
  .l-notes-head-tools .l-notes-group { padding-left: 0; }
  /* Рабочая область — ровно остаток экрана, и ни пикселем больше. Раньше её
     высота считалась вычитанием константы (142px), а реальный отступ сверху
     складывается из шапки оболочки, полей .l-main и шапки заметок и доходит до
     205px: накладка «Папки» (position: absolute; inset: 0) уходила на 45px за
     нижний край, страница получала вторую прокрутку, а нижние теги нельзя было
     достать, не прокрутив документ. Теперь высоту задаёт сам .l-notes-app —
     вьюпорт минус шапка оболочки и поля .l-main, — а панели получают её через
     flex, и единственный скроллер снова внутренний. */
  .l-notes-app {
    height: calc(var(--notes-viewport-h, 100dvh) - 70px - env(safe-area-inset-top) - max(16px, env(safe-area-inset-bottom)));
    min-height: 0;
  }
  .l-notes-workspace { min-height: 0; }
  .l-notes-head { padding-inline: 2px; }
  .l-notes-nav,
  .l-notes-list-pane { border-radius: 13px; overflow: hidden; }
  .l-note-editor-head { min-height: 50px; }
  /* Шапка редактора здесь выше: попап ссылки опускается под неё. */
  .l-note-share-pop { top: 54px; }
  .l-note-meta { padding: 10px 12px 12px; }
  .l-note-editor-wrap .jodit-wysiwyg {
    padding: 24px 18px 72px !important;
    font-size: 15px;
    overflow-wrap: anywhere;
  }
  .l-note-editor-wrap .jodit-wysiwyg table {
    max-width: 100%;
    display: block;
    overflow-x: auto;
    overscroll-behavior-inline: contain;
    -webkit-overflow-scrolling: touch;
  }
  /* display: block забирает у таблицы табличный контекст: строки собираются в
     анонимную таблицу шириной по содержимому, поэтому пустая таблица 2×2
     съёживалась в узкую полоску внутри рамки во всю ширину — та самая «пустая
     обводка». Возвращаем телу таблицы табличное отображение и растягиваем его.
     Ширина 100% для таблицы — минимум: содержимое шире по-прежнему вылезает и
     прокручивается внутри блока. Таблицы с thead/tfoot/colgroup/caption не
     трогаем: там все группы строк попадают в одну анонимную таблицу и колонки
     совпадают, а отдельный display: table у tbody их бы рассинхронизировал. */
  .l-note-editor-wrap .jodit-wysiwyg table:not(:has(thead, tfoot, colgroup, caption)) > tbody {
    display: table;
    width: 100%;
  }
  .l-note-editor-wrap .jodit-placeholder { padding: 24px 18px !important; }
  .l-note-editor-foot { padding-inline: 12px; }
  /* Попапы Jodit живут внутри выдвижной панели редактора (она fixed и потому
     становится их системой координат), поэтому ширину ограничиваем и по ней:
     то, что шире панели, обрезалось бы её overflow. */
  .jodit-popup,
  .jodit-dialog__panel,
  .jodit-select__popup {
    max-width: min(calc(100vw - 16px), calc(100% - 12px)) !important;
    max-height: calc(var(--notes-viewport-h, 100dvh) - 16px) !important;
    overflow: auto !important;
  }

  .l-iconbtn,
  .l-note-tool,
  .l-note-back,
  .l-dotbtn {
    min-width: 44px;
    min-height: 44px;
  }
}

/* Сенсорный ввод: hover нет, поэтому пипетка перекраски слота палитры видна
   всегда и получает полноценную цель нажатия.
   Тот же принцип для остальных «появляющихся по наведению» кнопок: правки в
   ветке комментариев, удаления пункта чек-листа, меню колонки доски, кнопки
   «＋» в календаре и пустого поля проекта. Раньше они открывались только в
   мобильном блоке ≤720px, и на планшете или телефоне в лендскейпе (721–960px)
   действие было недоступно вовсе. Ширина экрана здесь ни при чём — важно
   отсутствие курсора, поэтому условие именно hover: none. */
@media (hover: none) {
  .l-piprow { gap: 14px; }
  .l-pipwrap {
    width: 32px;
    height: 32px;
  }
  .l-pip-edit {
    opacity: 1;
    right: -4px;
    top: -4px;
    width: 20px;
    height: 20px;
  }
  .l-comment-tools { opacity: 1; }
  .l-checkitem-del { opacity: .68; }
  .l-colmenu { opacity: 1; }
  /* Круг «готово» остаётся мелким по рисунку (24px в списке, 17px на доске),
     а нажимается по зоне не меньше 40px: прозрачный ::before растягивает
     мишень, не трогая внешний вид. Запас скромный — ~8px по сторонам, чтобы
     касание рядом с кругом по-прежнему открывало карточку. */
  .l-trow .l-done-check::before,
  .l-tcard .l-done-check::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: max(100%, 40px);
    height: max(100%, 40px);
  }
  /* Точка «прочитано/непрочитано» в ленте уведомлений остаётся маленькой по
     рисунку (24px), а нажимается по зоне не меньше 40px. */
  .l-notif-toggle::after {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: max(100%, 40px);
    height: max(100%, 40px);
  }
  /* Подпись у «＋» остаётся скрытой: на таче она была бы в каждой ячейке. */
  .l-cal-add { opacity: .5; }
  .l-tproject.is-empty { opacity: .72; }
}

/* На таче и на узких экранах у ленты уведомлений собственного скролла нет —
   прокручивается только сам лист .l-pop. Вложенный max-height рисовал ДВЕ
   полосы прокрутки рядом; остаётся одна нативная overlay-полоса, которая
   появляется на время жеста и гаснет (кастомные полосы проекта живут под
   @media (hover:hover) and (pointer:fine) и тач не трогают).
   overflow обязан стать visible: контейнер с overflow:auto, которому некуда
   прокручиваться, вместе с overscroll-behavior:contain «съедал» жест и не
   отдавал его родительскому .l-pop — лента переставала листаться вовсе. */
@media (hover: none), (max-width: 720px) {
  .l-notif-list {
    max-height: none;
    overflow-y: visible;
    overscroll-behavior: auto;
  }
}

/* При полном сайдбаре в промежуточной ширине три финансовые карточки уже
   становятся слишком узкими для точных сумм. Складываем их раньше мобильного
   брейкпоинта, не меняя desktop-таблицу периодов внутри оборотов. */
@media (min-width: 721px) and (max-width: 1180px) {
  .l-money-overview { grid-template-columns: minmax(0, 1fr); }
  .l-turnover-grid { grid-template-columns: minmax(0, 1fr); }
  .l-turnover-card.is-total { grid-column: auto; }
}

/* Порядок строк на телефоне меняют стрелками ↑/↓ (ledger.js), ручка
   перетаскивания в карточке не нужна. */
@media (max-width: 720px) and (hover: none) {
  .l-rows-editor .is-mobile-reorder .l-drag-handle { display: none; }
}

@media (max-width: 420px) {
  .l-main { padding-inline: 12px; }
  .l-topbar .l-title { flex-basis: 100%; }
  .l-topbar .l-btn { flex: 1 1 auto; }
  .l-filters:not(.l-filter-shell) > .l-select,
  .l-filters:not(.l-filter-shell) > .l-dd { width: calc(50% - 4px); flex-basis: calc(50% - 4px); }
  .l-filter-toggle {
    grid-template-columns: minmax(0, 1fr) auto auto;
  }
  .l-filter-toggle-summary { grid-column: 1 / -1; grid-row: 2; }
  .l-tiles,
  .l-viewbar,
  .l-board,
  .l-board-mobile-tabs,
  .l-cal-mobile-days { margin-inline: -12px; padding-inline: 12px; }
  .l-tile { min-width: 82vw; }
  .l-panel { padding: 16px 14px; }
  .l-mobile-cards tbody tr { grid-template-columns: minmax(0, 1fr) minmax(0, .8fr); }
  /* Футер операции исключён: его кнопки уже сжаты до значков и остаются рядом. */
  .l-modal .actions:not(.l-op-actions) { flex-direction: column-reverse; }
  .l-modal .actions:not(.l-op-actions) .l-btn { width: 100%; }
}

@media (min-width: 721px) and (max-width: 900px) {
  .l-viewbar {
    max-width: 100%;
    overflow-x: auto;
    overscroll-behavior-inline: contain;
    scrollbar-width: none;
  }
  .l-viewbar::-webkit-scrollbar { display: none; width: 0; height: 0; }
  .l-viewbar > * { flex: 0 0 auto; }
}

@media (max-width: 520px) {
  /* Нижний край всплывающих листов. Панель быстрого доступа прибита к body, а
     лист заметки лежит в контексте наложения редактора — поэтому z-index её не
     перебивает ни при каком значении, и лист приходится просто не заводить под
     панель. Высота панели: 6 + 50 + 6 = 62px, плюс её безопасная зона и 10px
     воздуха. */
  :root { --l-sheet-bottom: max(10px, env(safe-area-inset-bottom)); }
  html.l-nav-tabs body.l-has-tabs,
  html.l-nav-both body.l-has-tabs { --l-sheet-bottom: calc(72px + env(safe-area-inset-bottom)); }
  .l-pop,
  .l-note-share-pop,
  .l-note-remind-pop {
    inset: auto 10px var(--l-sheet-bottom) 10px !important;
    width: auto !important;
    max-width: none !important;
    max-height: min(66dvh, 520px);
    padding: 8px;
    overflow-y: auto;
    border-radius: 16px;
  }
  /* Нижний лист выезжает снизу вверх, а не «падает» на 4px сверху. */
  @starting-style {
    .l-pop:not([hidden]) { opacity: 0; transform: translateY(8px); }
  }
  /* Попапы заметки становятся нижним листом внутри выдвижной панели редактора. */
  .l-note-share-pop,
  .l-note-remind-pop { position: fixed; padding: 14px 14px 16px; }
  /* В нижнем листе действия делят строку поровну — попадать пальцем проще. */
  .l-note-share-actions .l-btn { min-height: 40px; flex: 1; }
  .l-note-share-actions .l-note-share-native,
  .l-note-share-actions .l-note-share-main { min-height: 44px; }
  .l-note-remind-actions .l-btn { min-height: 40px; flex: 1; }
  .l-note-remind-quicks .l-clock-quick { min-height: 38px; }
  .l-pop .l-pop-item { min-height: 44px; }
  .l-pop[data-for="notifications"] .l-notif-main { min-height: 44px; }
  /* Базовой .l-btn (padding 8px + 13.5px) хватает лишь на ~38px — до пальца
     дотягиваем так же, как остальные цели в нижнем листе. */
  .l-pop[data-for="notifications"] .l-notif-actions .l-btn { min-height: 44px; }
  .l-dd-menu {
    width: auto;
    max-width: calc(100vw - 16px);
    max-height: min(64dvh, 480px);
    border-radius: 12px;
  }
  .l-dd-item { min-height: 44px; }
}
