/* GOLDJAXE Scribe · components.css — P1 UI-компоненты (стиль Synology, только токены tokens.css).
   Подключать ПОСЛЕ tokens.css. Все селекторы префиксованы: sc-, app-, dtable-.
   Внимание: не писать «*<слэш>» внутри комментария — это закрывает его досрочно, и
   следующее правило съедается парсером (так уже терялся весь блок .app-shell). */

/* ═══════════════ app-shell ═══════════════ */
/* ═══════════════════════════════════════════════════════════════════════════
   GOLDJAXE Scribe · app-shell — каркас-оболочка админки (topbar + sidebar + main)
   Стиль Synology DSM: плотно, малые радиусы, 1px-границы, золото — единственный
   акцент и экономно. Только токены из tokens.css; тёмная тема наследуется сама.
   Селекторы с префиксом .app-* — не конфликтуют с .card/.btn/.hdr/.pcard/.t/.k.
   Файл: static/app-shell.css (подключать ПОСЛЕ tokens.css).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Каркас: сетка topbar(во всю ширину) / sidebar / main ─────────────────── */
.app-shell{
  /* локальная переменная компонента (не токен).
     Шли вниз от 88px (под знак 56px): такая полоса на широком экране читалась
     тяжелее содержимого — у нас в шапке 4 пункта навигации и 3 кнопки, а не
     насыщенный навигатор лендинга, поэтому лишняя высота выглядела пустой.
     73px — знак 48px плюс по 12,5px воздуха (66% высоты против 57% у канона
     .eco-header 77px). Ниже 68px не опускать: подчёркивание активного пункта
     начинает касаться нижнего края полосы. */
  --app-topbar-h: 73px;

  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;           /* корректная высота на мобильных с адрес-баром */
  background: transparent;      /* фон держит body (там аура тёмной темы) */
  color: var(--c-ink);
  font-family: var(--font-sans);
}
.app-shell *,
.app-shell *::before,
.app-shell *::after{ box-sizing: border-box; } /* локально, не глобальный reset */

/* 🔴 Липкая шапка НЕ должна накрывать то, к чему перешли. Замер 15.08.2026:
   на телефоне после перехода по якорю (ссылка «к содержимому», вкладки с #hash,
   возврат к строке списка) первая строка уезжала под шапку на все 72px — то
   есть человек попадал ровно туда, где ничего не видно.
   scroll-margin-top на самих целях, а не scroll-padding на контейнере: прокрутку
   ведёт документ, и у него же должен быть отступ; вдобавок правило переживает
   смену высоты шапки — значение берётся из той же переменной, что и высота. */
.app-shell :target,
.app-shell [id]{ scroll-margin-top: calc(var(--app-topbar-h) + var(--sp-3)); }

/* ── Верхняя панель — BRAND-IMMUTABLE (тёмная в обеих темах, канон .eco-header).
     Шапка = лицо экосистемы GOLDJAXE: тёмный обсидиан + золотой wordmark.
     Все элементы шапки живут на --hdr-* переменных, НЕ на общих --c-ink. ── */
.app-topbar{
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  height: var(--app-topbar-h);
  padding: 0 var(--sp-4);
  background: var(--hdr-bg);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--hdr-line);
}
/* ── Знак + слово в шапке · канон .eco-header эталона .ai ────────────────────
   Куб 56px + wordmark Space Mono 17.5 + подпись продукта JetBrains Mono.
   Куб — знак ХОЛДИНГА и главная доминанта; имя продукта живёт в скобках рядом,
   назначение продукта — подписью снизу. Иконка микрофона из шапки убрана: два
   знака подряд спорят друг с другом, а место знака холдинга не отдаётся никому.
   Микрофон переехал в статус-плашку рабочей зоны, где он несёт смысл. */
.app-topbar__brand{
  display: inline-flex;
  align-items: center;
  gap: 14px;                       /* канон .eco-logo */
  text-decoration: none;
  white-space: nowrap;
  min-width: 0;
}
.app-cube{
  width: 48px;
  height: 48px;
  flex: none;
  object-fit: contain;
  filter: drop-shadow(0 0 12px rgba(235,197,84,.35));
  transition: filter .35s ease;
}
.app-topbar__brand:hover .app-cube{
  filter: drop-shadow(0 0 20px rgba(235,197,84,.55)) drop-shadow(0 0 34px rgba(235,197,84,.18));
}
.app-topbar__brandtext{ display: flex; flex-direction: column; min-width: 0; }
.app-wordmark{
  font-family: var(--font-brand);
  font-weight: 700;
  /* 18.5 против канонных 17.5: рядом со знаком 48px слово должно держать вес,
     иначе текстовый блок «прилипает» к кубу и композиция читается однобокой. */
  font-size: 18.5px;
  letter-spacing: .07em;
  line-height: 1;
  color: var(--hdr-ink);
}
/* Канон: имя холдинга — золотом, имя продукта в скобках — белым (эталон .ai). */
.app-wordmark .gold{ color: var(--hdr-gold); }
.app-wordmark .br{ color: var(--hdr-ink); }
.app-subline{
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--hdr-ink-3);
  margin-top: 5px;
  line-height: 1;
}
/* Название организации — на месте подписи продукта (третьей строки шапка не
   держит). Живёт ЗДЕСЬ, а не в admin.css: тот грузится не на всех страницах, и
   на «Загрузке» название оставалось без стилей — синим подчёркнутым, потому что
   весь брендблок обёрнут в <a>.

   Цвет приглушённый, не золото: золото в шапке принадлежит имени холдинга, и
   второй золотой элемент рядом спорит со знаком за внимание. Имя организации —
   справочная строка «в чьём контуре ты работаешь», а не акцент. */
.app-orgname{
  font-family: var(--font-mono);
  /* Набор — как у подписи продукта (паспорт: JBM 13 w700, трекинг 1.82px): она стоит
     на том же месте и читается в том же ритме. Мельче и тоньше строка выглядела
     служебной сноской, хотя отвечает на важный вопрос — в чьём контуре ты работаешь. */
  font-weight: 700;
  font-size: 13px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--hdr-ink-3);
  margin-top: 5px;
  line-height: 1;
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-decoration: none;   /* брендблок — ссылка; подчёркивание наследуется */
}
.app-topbar__spacer{ flex: 1 1 auto; min-width: 0; }

.app-topbar__right{
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
}

/* ── Живой статус своей записи (GS-149) ───────────────────────────────────────
   Виден только вне главной — на главной ход показан крупно, и второй индикатор
   был бы тем же статусом дважды (канон П5). Разметку ставит base.html.
   Токены --hdr-*: шапка BRAND-IMMUTABLE, тёмная во всех трёх темах, и обычные
   --c-* дали бы на ней тёмное на тёмном. */
.app-live{
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 40px; padding: 0 11px; min-width: 0;
  border: 1px solid var(--hdr-gold-line);
  background: var(--hdr-gold-bg);
  color: var(--hdr-gold);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono); font-size: 12px; font-weight: 700;
  text-decoration: none; white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.app-live[hidden]{ display: none; }
.app-live:hover{ border-color: var(--hdr-gold); }
.app-live:focus-visible{ outline: 1px solid var(--hdr-gold); outline-offset: 2px; }
/* Название режем многоточием, а не переносим: шапка обязана держать одну высоту
   на всех страницах, а «Еженедельная планёрка руководителей» её распирает.
   На узком экране остаётся точка и обрезанное имя — понять «идёт» этого хватает. */
.app-live__t{ overflow: hidden; text-overflow: ellipsis; max-width: 30vw; }
/* Точка наследует общий .pulse (1,4 с), но в шапке ей нужен цвет шапки:
   --c-warn на тёмном фоне читается хуже золота. */
.app-live .pulse{ background: var(--hdr-gold); box-shadow: 0 0 7px var(--hdr-gold); }
/* На очень узком экране имя уступает место аватару: рядом с ним статус и
   квадрат учётной записи не помещались, и шапка начинала переносить строку. */
@media (max-width: 400px){
  .app-live__t{ max-width: 22vw; }
}
/* ── Учётная запись в шапке: адрес = кнопка меню, «Выйти» внутри ──────────────
   До 11.08.2026 здесь стояли три элемента подряд: [◐ тема] [почта] [Выйти] —
   кнопка, справочный текст, снова кнопка. Текст между двумя действиями читается
   как сбой ритма, а на узком экране почта скрывалась и оставались два безымянных
   значка. Свёрнуто в одно меню: адрес — вход, выход — пункт внутри.

   Высота 44px, а не 36: это тач-цель (GOL-366). Кнопка стоит у самого края
   экрана, где палец промахивается чаще всего. */
/* Адреса рядом с аватаром больше нет (25.08.2026) — кнопка стала квадратной
   тач-целью 44×44 на ЛЮБОЙ ширине, а не только на телефоне. Адрес виден в первой
   строке панели; в шапке он повторял её же и на широком экране растягивал кнопку
   до 260px ради сведений, которые нужны раз в сессию. */
.app-acct__btn{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--hdr-ink-2);
  cursor: pointer;
  transition: border-color .15s, color .15s, background .15s;
}
.app-acct__btn:hover{ border-color: var(--hdr-gold-line); color: var(--hdr-gold); background: var(--hdr-gold-bg); }
.app-acct__btn:focus-visible{ outline: none; box-shadow: var(--focus-ring); }
.app-acct__btn[aria-expanded="true"]{ border-color: var(--hdr-gold-line); color: var(--hdr-gold); }

/* 48px там, где ввод ПАЛЬЦЕМ (GS-138). Норма холдинга — 48: одним числом
   перекрывает WCAG AA (24), WCAG AAA (44) и Material (48). Прежние 44 брались
   по Apple HIG и норме не дотягивали.

   🔴 Граница по СПОСОБУ ВВОДА, а не по ширине окна: у ноутбука с сенсорным
   экраном ширина десктопная, а палец тот же. Под мышью (pointer: fine) 44px
   остаются — курсор наводится точнее пальца, и раздувать шапку там незачем. */
@media (pointer: coarse){
  .app-acct__btn{ width: 48px; height: 48px; }
}

/* Буква адреса в КВАДРАТЕ, а не в круге (25.08.2026). Вся геометрия продукта
   прямоугольная: --radius-md и --radius-lg равны нулю, карточки, поля и кнопки
   держат углы, знак — куб. Аватар был единственной окружностью на экране и
   читался как заимствование из чужого интерфейса.
   --radius-sm (3px), а не ноль: тот же радиус, что у кнопок рядом, — квадрат со
   срезом в волос, а не острый угол, который на 28px выглядит сколом.
   На телефоне буква остаётся одна — вместе с ней у кнопки сохраняется смысл
   «это про меня», чего не давала безымянная иконка выхода. */
/* 🔴 КРУГЛЫЙ, БЕЗ ЗОЛОТОЙ РАМКИ (решение владельца 29.08.2026).

   Прежний комментарий здесь доказывал обратное: «вся геометрия продукта
   прямоугольная, круг читался как заимствование». Это та же ошибка чтения
   канона, что была со значками состояния. П1 «Круглое — предмет, прямоугольное —
   поверхность» относит АВАТАР к круглому — прямо, отдельной строкой таблицы,
   вместе с главной кнопкой и значком-статусом. Прямоугольны панели, карточки,
   поля, списки, таблицы, вкладки, то есть поверхности. Аватар — предмет,
   он обозначает человека, а не служит подложкой.

   По рамке решение менялось дважды. GS-111: золото убрано — золото в шапке это
   бренд (знак, wordmark) и активное действие, а аватар — метка «это я», не
   действие. 31.08.2026 владелец вернул тонкое золото обратно: нейтральная
   плашка сливалась с тёмной шапкой и не читалась. Компромисс — приглушённая
   обводка --hdr-gold-line (40% золота): граница видна, спора со знаком бренда
   нет. И увеличена до 36px — 30px на тёмном терялись. */
.app-acct__ava{
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px;
  border-radius: var(--radius-pill);
  background: var(--hdr-surface);
  border: 1px solid var(--hdr-gold-line);
  color: var(--hdr-ink-2);
  font-size: 15px; font-weight: 700; line-height: 1;
}
/* Панель аккаунта шире обычного меню: в ней живут адрес, темы и языки, а не
   один список. 210px хватает и самому длинному пункту, и адресу без переносов. */
.app-acct__pop{ min-inline-size: 210px; }
/* Адрес внутри панели: кнопка показывает только букву, и без этой строки не
   видно, под какой учётной записью сидишь. */
.app-acct__who{
  display: block;
  padding: 7px 10px 8px;
  margin-bottom: 3px;
  border-bottom: 1px solid var(--c-line);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .04em;
  color: var(--c-ink-4);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 260px;
}
/* «Выйти» отделён чертой от настроек: необратимое действие не должно стоять
   вплотную к безобидному переключению темы, где палец идёт по инерции. */
.app-logout-form{
  display: flex; margin: 0;
  margin-block-start: 3px;
  padding-block-start: 4px;
  border-block-start: 1px solid var(--c-line);
}
/* 🔴 В ШТОРКЕ ЧЕРТУ РИСУЕТ <hr>, И ВТОРАЯ ЗДЕСЬ ЛИШНЯЯ (GS-383, 12.09.2026).
   Одна и та же форма стоит в ДВУХ местах: в меню аккаунта на десктопе, где
   своей черты нет и граница выше необходима, и в мобильной шторке, где перед
   ней уже стоит `.app-sheet__hr`. В шторке линии складывались и рисовались
   двумя параллельными полосами с зазором в 7px (замечание владельца по снимку:
   «два подчёркивания, это дефект»). Снимаем границу только там, где её роль
   уже исполняет разделитель, — правило для меню остаётся нетронутым. */
.app-sheet .app-logout-form{
  border-block-start: 0;
  padding-block-start: 0;
  margin-block-start: 0;
}
/* Пункт «Выйти» держит форму пунктов .gx-menu__pop, но живёт внутри <form> —
   селектор прямого потомка до него не достаёт, поэтому правила повторены. */
.app-acct__out{
  display: flex; align-items: center; gap: 8px;
  width: 100%;
  padding: 9px 10px;
  background: none; border: 0;
  border-radius: var(--radius-sm);
  font: inherit; font-size: 13.5px;
  color: var(--c-ink-2);
  text-align: start;
  white-space: nowrap;
  cursor: pointer;
  transition: background .13s ease, color .13s ease;
}
.app-acct__out:hover{ background: var(--c-gold-bg); color: var(--c-gold); }
.app-acct__out:focus-visible{ outline: none; box-shadow: var(--focus-ring); }
.app-acct__out .ic-sm{ flex: none; }

/* Кнопка темы внутри тёмной brand-шапки — светлая на тёмном всегда */
.app-topbar .app-theme{ color: var(--hdr-ink-2); border-color: var(--hdr-line); }
.app-topbar .app-theme:hover{ background: var(--hdr-gold-bg); color: var(--hdr-gold); border-color: var(--hdr-gold-line); }

/* ── Гамбургер (в наборе иконок нет «menu» — рисуем 3 полосы на CSS) ───────── */
.app-burger{
  display: none;                /* виден только в off-canvas режиме (мобильный) */
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  margin-left: -10px;
  padding: 0;
  color: var(--hdr-ink);
  background: none;
  border: 0;
  border-radius: var(--radius-sm);   /* иконочная кнопка-гамбургер — канон sm (4px) */
  cursor: pointer;
}
.app-burger:hover{ background: var(--hdr-surface); color: var(--hdr-gold); }
.app-burger__box{
  position: relative;
  display: block;
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: background .18s ease;
}
.app-burger__box::before,
.app-burger__box::after{
  content: "";
  position: absolute;
  left: 0;
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform .2s ease;
}
.app-burger__box::before{ top: -6px; }
.app-burger__box::after{ top: 6px; }
.app-shell.is-nav-open .app-burger__box{ background: transparent; }
.app-shell.is-nav-open .app-burger__box::before{ transform: translateY(6px) rotate(45deg); }
.app-shell.is-nav-open .app-burger__box::after{ transform: translateY(-6px) rotate(-45deg); }

/* ── Навигация в хедере — терминальные капс-ссылки с золотым подчёркиванием
     (адаптация .ai-nav-link эталона .ai; JetBrains Mono — кириллица ОК) ────── */
.app-nav{ display: flex; align-items: stretch; align-self: stretch; gap: 0; }
.app-nav a{
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 0 14px;
  border-radius: 0;   /* терминальные капс-ссылки с золотым индикатором — острый край намеренно (не кнопка) */
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .10em;
  text-transform: uppercase;
  color: var(--hdr-ink-2);
  text-decoration: none;
  white-space: nowrap;
  transition: color .2s ease, background .2s ease;
}
.app-nav a::after{
  content: '';
  position: absolute;
  left: 12px; right: 12px; bottom: 0;
  height: 2px;
  background: var(--hdr-gold);
  box-shadow: 0 0 6px var(--hdr-gold), 0 0 12px rgba(235,197,84,.45);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform .24s ease;
}
.app-nav a .ic{ flex: none; color: var(--hdr-ink-3); transition: color .2s ease; }
.app-nav__label{ min-width: 0; }
.app-nav a:hover{ color: var(--hdr-gold); background: var(--hdr-gold-bg); }
.app-nav a:hover .ic{ color: var(--hdr-gold); }
.app-nav a:hover::after{ transform: scaleX(1); }
/* активный пункт: золото + светящееся подчёркивание */
.app-nav a.is-active{ background: transparent; color: var(--hdr-gold); }
.app-nav a.is-active::after{ transform: scaleX(1); }
.app-nav a.is-active .ic{ color: var(--hdr-gold); }

/* ── Область контента (обычный поток — страница скроллится нативно) ─────────── */
.app-main{
  flex: 1 1 auto;
  min-width: 0;                 /* не даём широкому контенту распирать флекс */
  background: transparent;      /* фон держит body (аура тёмной темы) */
}

/* ── Подвал: версия развёрнутого кода ──────────────────────────────────────── */
/* Здесь, а не в admin.css: подвал — элемент каркаса base.html, а admin.css
   подключается не на всех страницах (блок stylesheets переопределяется), и
   правило оттуда молча не доехало бы до части экранов. Зафиксированное правило
   проекта: стили base.html живут только в components.css. */
.app-footer{
  /* .app-shell — колонка с min-height 100dvh, .app-main тянется flex:1 —
     значит подвал сам прижимается к низу на коротких страницах, без position
     и без хаков вроде margin-top:auto на пустой распорке. */
  flex: none;
  display: flex;
  justify-content: center;
  align-items: center;
  /* Юр-ссылки встали рядом с версией (20.08.2026). Перенос разрешён: на узком
     экране строка «v1.22.0 · Оферта · Обработка данных» не помещается в 320px,
     и без wrap подвал начинал горизонтальную прокрутку всей страницы. */
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-4) var(--sp-4) var(--sp-5);
  background: transparent;      /* фон держит body, как у .app-main */
}
/* Юридические документы. Кегль и цвет — как у версии: это служебный слой, он не
   должен соревноваться за внимание с рабочими разделами страницы. */
.app-footer__legal{
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
}
.app-footer__legal a{
  font-size: 12px;
  color: var(--c-ink-3);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color .15s, border-color .15s;
}
.app-footer__legal a:hover{
  color: var(--c-gold-strong);
  border-bottom-color: var(--c-gold-line);
}
.app-footer__legal a:focus-visible{ outline: none; box-shadow: var(--focus-ring); }
.app-footer__ver{
  /* 12px — пол шкалы кегля (docs/dev/frontend.md): ниже не опускаемся нигде.
     Служебная строка, но всё же читаемая человеком, а не глиф в кружке.
     Цвет --c-ink-3, а не --c-ink-4: подвал лежит на холсте --c-bg, самой
     светлой подложке страницы, и мерить контраст надо по ней — на ней
     приглушённый токен проходит норму 4.5, блёклый уже нет. */
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.4;
  letter-spacing: .02em;
  color: var(--c-ink-3);
  user-select: all;             /* версию копируют в задачу — выделяем целиком по клику */
}
/* Адрес поддержки (GS-248). Кегль и цвет — как у версии и юр-ссылок: подвал
   остаётся служебным слоем и не соревнуется за внимание с рабочими разделами.
   Подпись «Поддержка:» приглушена, сам адрес — обычная ссылка подвала, потому
   что нажимают именно его. */
.app-footer__sup{
  font-size: 12px;
  line-height: 1.4;
  color: var(--c-ink-3);
}
.app-footer__sup a{
  color: var(--c-ink-3);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color .15s, border-color .15s;
  /* Адрес копируют в почтовый клиент — выделяем целиком по двойному клику,
     как версию сборки строкой выше. */
  user-select: all;
}
.app-footer__sup a:hover{
  color: var(--c-gold-strong);
  border-bottom-color: var(--c-gold-line);
}
.app-footer__sup a:focus-visible{ outline: none; box-shadow: var(--focus-ring); }

/* ── Затемнение под off-canvas (только мобильный) ──────────────────────────── */
.app-backdrop{
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(20, 28, 40, .42);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .2s ease, visibility 0s linear .2s;
}
.app-shell.is-nav-open .app-backdrop{
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity .2s ease;
}

/* ── Ссылка «к содержимому» для клавиатуры ─────────────────────────────────── */
.app-skip{
  position: absolute;
  left: var(--sp-2);
  top: -48px;
  z-index: 60;
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--c-ink);
  background: var(--c-surface);
  border: 1px solid var(--c-line-strong);
  border-radius: var(--radius-sm);
  text-decoration: none;
  box-shadow: var(--elev-2);
  transition: top .15s ease;
}
.app-skip:focus{ top: var(--sp-2); }
/* Возвращаем токен-фокус-ринг поверх собственной тени: базовый box-shadow .app-skip
   (app-shell.css грузится позже tokens.css, равная специфичность) иначе перебивал
   глобальный :focus-visible{ box-shadow: var(--focus-ring) } из tokens.css. */
.app-skip:focus-visible{ box-shadow: var(--focus-ring), var(--elev-2); }

/* ── Адаптив: навигация → выпадающая панель под хедером по гамбургеру ───────── */
/* ── Сворачивание меню в бургер ────────────────────────────────────────────
   Порог 1200, а не прежние 760/1060: при 3-4 пунктах у админа шапка не
   помещалась задолго до 760. Замер — почта ужималась до огрызка «a…» (18px на
   761px), а подчёркивание активного пункта заезжало под логотип. На 1060 это
   лечилось не до конца: в диапазоне 1061–1150 горизонтальное меню уже
   разворачивалось, но места ему не хватало — закрывающая скобка вордмарка
   «GOLDJAXE [ SCRIBE ]» срезалась и сталкивалась с иконкой «Загрузка», а почта
   висела обрезанной «qa@goldja…». Замер по шагам: на 1151 на главной ещё
   оставался клип в 1px, чисто становится с 1201. Ниже 1200 меню уходит
   в бургер целиком.
   ВАЖНО: здесь только сворачивание. Мобильная подача знака (две строки,
   иконка вместо «Выйти») живёт отдельным блоком с порогом 760 — на планшете
   900px она была бы неуместна.
   При смене порога — синхронно правь NAV_BREAKPOINT в components.js
   (сторож: tests/test_nav_breakpoint.py). */
@media (max-width: 1200px){
  .app-burger{ display: inline-flex; }
  .app-topbar{ gap: var(--sp-2); }
  /* Правил для .app-acct__mail и padding кнопки здесь больше нет: адрес ушёл из
     шапки в панель (25.08.2026), а кнопка теперь 44×44 на любой ширине —
     схлопывать нечего. */
}

@media (max-width: 760px){
  /* 🔴 56px вместо 72px (замечание владельца 30.08.2026: «хедер огромный,
     функционала у него практически нет, а места мало — весь функционал внизу»).

     Довод верный: вся навигация на телефоне живёт в нижней панели, а шапка
     держит знак и аватар. Замер на 412×915: шапка 72 + панель 65 + заголовок
     карточки 76 = 213px, почти четверть экрана до первого органа управления.

     56px — не произвольное число: это 44px тач-цели аватара плюс по 6px
     воздуха сверху и снизу. Ниже опускать нельзя — кнопка перестанет
     дотягивать до нормы холдинга.

     Знак трогать не пришлось: замер на 320px (самый узкий из поддерживаемых)
     дал 34px при шапке 56 — двухстрочная надпись, поставленная 13.08.2026,
     помещается с запасом. Переполнения нет ни по ширине, ни по высоте. */
  .app-shell{ --app-topbar-h: 56px; }
  /* Знак и слово УМЕНЬШЕНЫ (замечание владельца 13.08.2026: «шапка немного
     разъезжается»). Прежний расчёт «блок занимает 331px из 390, запас есть»
     держался на странице БЕЗ бургера бокового меню. В админке слева стоит
     бургер, справа три кнопки (тема, язык, учётная запись) — и на 390 слову
     18px уже не хватало места: «[ SCRIBE ]» ломался ПОПОЛАМ, знак уезжал в три
     строки высотой 58px. На 320 и 360 к этому добавлялся горизонтальный скролл,
     то есть страница физически шире экрана.

     Замер до правки (admin/pipelines): 320/360/390 — три строки, на 320 и 360
     ещё и скролл. После: две строки на всех ширинах от 320, скролла нет.

     Куб 40px вместо 48: он остаётся доминантой знака (кнопки рядом — 44px), но
     перестаёт съедать ширину, которой не хватает слову. Слово 16/14 вместо
     18/16 — «GOLDJAXE» и «[ SCRIBE ]» умещаются каждое в свою строку целиком,
     а это и есть условие читаемости: разорванное пополам имя продукта хуже
     мелкого. */
  .app-topbar__brand{ gap: 9px; }
  .app-cube{ width: 40px; height: 40px; }
  .app-topbar__brandtext{ align-items: center; }
  .app-wordmark{ font-size: 16px; white-space: normal; text-align: center; line-height: 1.05; }
  .app-wordmark .gold{ white-space: nowrap; }
  /* nowrap на обеих частях — то самое, чего не хватало: без него перенос идёт
     ВНУТРИ «[ SCRIBE ]», и скобка остаётся на отдельной строке. */
  .app-wordmark .br{
    display: block; margin-top: 5px; font-size: 14px;
    letter-spacing: .1em; white-space: nowrap;
  }
  /* Подпись продукта и имя организации — только на десктопе: знак здесь уже
     занимает две строки, третья ломает шапку (именно так имя организации и
     вылезало на телефоне отдельной строкой). Потери нет: в кабинете и на
     «Организации» имя стоит заголовком страницы, а в режиме «от лица» контур
     держит красная полоса под шапкой. */
  .app-subline,
  .app-orgname{ display: none; }
  /* Размер кнопки учётной записи здесь больше не задаётся: 44×44 она держит на
     всех ширинах (см. .app-acct__btn выше). Расширять зону нажатия
     псевдоэлементом не нужно — сама кнопка уже тач-цель нужного размера, а за
     ней меню, а не немедленный выход. */
}

/* ── Совсем узкие экраны (iPhone SE и подобные) ──────────────────────────────
   На 320px шапка не помещалась даже после уменьшения знака: сумма «бургер +
   знак + тема + язык + учётная запись» давала документ шириной 335px, то есть
   горизонтальный скролл на КАЖДОЙ странице. Замер показал, что за край уходит
   кнопка учётной записи — знак тут уже не виноват, не хватало 15px на всех
   участников строки.

   Отнимаем эти пиксели у знака, а не у кнопок: кнопки — тач-цели, ужимать их
   ниже 44px нельзя (промах пальцем дороже мелкого логотипа). Знак же остаётся
   узнаваемым и в 34px — это по-прежнему куб, а не точка. */
@media (max-width: 380px){
  .app-topbar__brand{ gap: 7px; }
  .app-cube{ width: 34px; height: 34px; }
  /* 14/13 — нижняя граница паспорта, ниже не опускаемся даже здесь: 12px в
     интерфейсе приложения нет вовсе. Недостающие пиксели берём трекингом и
     размером знака, а не кеглем. */
  .app-wordmark{ font-size: 14px; letter-spacing: .04em; }
  .app-wordmark .br{ font-size: 13px; margin-top: 4px; letter-spacing: .06em; }
  /* Зазоры шапки — минимальные: каждый лишний пиксель здесь выталкивает
     последнюю кнопку за экран. */
  .app-topbar{ gap: 6px; padding-inline: 8px; }
  /* Отрицательный отступ бургера (оптическое выравнивание на широком экране)
     здесь вычитается из и без того урезанного padding — кнопка уходила левее
     нуля, а вся строка вместе с ней за правый край. На 320px оптика дешевле
     горизонтального скролла. */
  .app-burger{ margin-left: 0; width: 44px; }
  /* Зазор ВНУТРИ правой группы. Прежде он и выталкивал последнюю кнопку за
     экран: три кнопки (тема, язык, учётная запись) с gap:12px переполняли
     собственный контейнер. С 25.08.2026 кнопка в группе одна — тема и язык ушли
     в меню аккаунта, и переполняться нечему. Правило оставлено как страховка на
     случай, если в группу вернётся второй элемент: 3px здесь ничего не стоят.
     Правило .app-lang__btn убрано вместе с самой кнопкой языка. */
  .app-topbar__right{ gap: 3px; }
}

/* Выпадающая панель работает везде, где есть бургер — то есть с 1200, а не с 760:
   иначе на планшете кнопка бургера показывалась бы, а меню по ней не открывалось. */
@media (max-width: 1200px){
  /* Выпадающая панель — продолжение тёмной brand-шапки (канон ai-mobile-menu).
     position:fixed (не absolute с минус-отступами) — иначе скрытая панель
     распирает layout за правый край и даёт горизонтальный скролл на мобиле. */
  .app-nav{
    position: fixed;
    top: var(--app-topbar-h);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    align-self: auto;
    gap: 0;
    padding: var(--sp-2) 0;
    background: rgba(12,12,15,.98);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--hdr-line);
    box-shadow: 0 18px 40px rgba(0,0,0,.5);
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;             /* свёрнуто — вне порядка табуляции */
    pointer-events: none;
    transition: opacity .18s ease, transform .18s ease, visibility 0s linear .18s;
    z-index: 45;
  }
  .app-shell.is-nav-open .app-nav{
    transform: translateY(0);
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: opacity .18s ease, transform .18s ease;
  }
  .app-nav a{
    min-height: 48px;               /* touch-таргет ≥48 (канон mobile) */
    padding: 0 var(--sp-6);
    font-size: 13px;
    border-bottom: 1px solid rgba(255,255,255,.06);
    transition: color .2s ease, background .2s ease, padding-left .2s ease;
  }
  .app-nav a:last-child{ border-bottom: 0; }
  .app-nav a::after{ display: none; }           /* подчёркивание — только на десктопе */
  .app-nav a:hover{ padding-left: calc(var(--sp-6) + 6px); }
  .app-nav a.is-active{ color: var(--hdr-gold); background: var(--hdr-gold-bg); }
}

@media (min-width: 1201px){
  .app-backdrop{ display: none; }   /* на десктопе оверлей не нужен */
  .app-burger{ display: none; }
}

/* ── Уважение к prefers-reduced-motion ─────────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  .app-nav,
  .app-backdrop,
  .app-nav a,
  .app-burger__box,
  .app-burger__box::before,
  .app-burger__box::after,
  .app-acct__btn,
  .app-acct__out,
  .app-theme,
  .app-skip{
    transition: none !important;
  }
}
/* ═══════════════ data-table ═══════════════ */
/* ─────────────────────────────────────────────────────────────────────────────
   GOLDJAXE Scribe — компонент «data-table» (.dtable)
   Плотная дата-таблица уровня Synology DSM. Только токены из tokens.css, единый
   акцент — золото, экономно. Светлая/тёмная тема наследуется автоматически.
   Все селекторы префиксованы .dtable* — не пересекаются с .card/.btn/.seg/.t/.k.
   ───────────────────────────────────────────────────────────────────────────── */

/* Компонент-обёртка: [data-dtable] вешается сюда (панель + скролл-контейнер) */
.dtable-comp { display: flex; flex-direction: column; gap: var(--sp-2); }

/* ── Скролл-контейнер: горизонтальный адаптив + вертикальный скролл ───────────
   overflow:auto → thead position:sticky пришпиливается к верху этого контейнера.
   max-height даёт прокручиваемую область данных со «липким» заголовком; при
   коротком списке скролла нет и заголовок просто стоит сверху. Снять кап —
   модификатор .dtable-wrap.is-flush. */
.dtable-wrap {
  overflow: auto;
  max-block-size: 70vh;
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-1);
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
.dtable-wrap.is-flush { max-block-size: none; }
.dtable-wrap:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ── Таблица ───────────────────────────────────────────────────────────────── */
.dtable {
  inline-size: 100%;
  border-collapse: separate; /* separate → sticky thead без «съезда» границ */
  border-spacing: 0;
  font-family: var(--font-sans);
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--c-ink);
}

.dtable th,
.dtable td {
  text-align: start;
  padding: 10px 14px;
  border-block-end: 1px solid var(--c-line);
  vertical-align: middle;
  white-space: nowrap;
}
.dtable tbody tr:last-child > td { border-block-end: 0; }

/* Заголовок — липкий, терминальные капсы JetBrains Mono (фирменный слой данных) */
.dtable thead th {
  position: sticky;
  inset-block-start: 0;
  z-index: 2;
  background: var(--c-surface-2);
  color: var(--c-ink-3);
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: .09em;
  border-block-end: 1px solid var(--c-line-strong);
  user-select: none;
}

/* Тело строк */
.dtable tbody tr { transition: background .12s ease; }
.dtable tbody tr:hover { background: var(--c-surface-2); }
.dtable tbody tr[data-selected] { background: var(--c-gold-bg); }
.dtable tbody tr[data-selected]:hover { background: var(--c-gold-bg); }
.dtable tbody td { color: var(--c-ink-2); }
.dtable tbody td:first-child,
.dtable tbody td .dtable__primary { color: var(--c-ink); font-weight: 500; }

/* Числовые ячейки — моноширинные цифры, выравнивание вправо */
.dtable th.num,
.dtable td.num {
  text-align: end;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* Ссылки внутри ячеек.
   Цвет обычного текста, НЕ золото. Золотом красилась КАЖДАЯ ссылка таблицы, и
   на списке из десятка организаций акцентным оказывался весь столбец разом —
   акцент, который стоит везде, не выделяет ничего, а список превращается в
   ёлку. Название и так узнаётся как ссылка: оно жирнее соседних ячеек, стоит в
   главной колонке и подчёркивается под курсором.
   Золото возвращается на наведении и фокусе — там оно указывает ровно на одну
   строку, ту, с которой человек сейчас работает. */
.dtable a {
  color: inherit;
  text-decoration: none;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border-radius: var(--radius-xs);
  transition: color .15s;
}
.dtable a:hover { color: var(--c-gold-strong); text-decoration: underline; }
.dtable a:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ── Кнопка-сортировщик в заголовке ──────────────────────────────────────────
   <button> внутри <th data-sort-type> — фокусируемый, клавиатурно доступный.
   Состояние сортировки хранится в th[aria-sort]. */
.dtable-sort {
  all: unset;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  inline-size: 100%;
  cursor: pointer;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  border-radius: var(--radius-xs);
  transition: color .12s ease;
}
.dtable-sort:hover { color: var(--c-ink); }
.dtable-sort:focus-visible { outline: none; box-shadow: var(--focus-ring); }
/* Кликабельна вся строка (GS-140, канон П8). Курсор и подсветка — единственный
   признак, по которому об этом можно догадаться: без них правило работает, но
   человек продолжает целиться в текст ссылки.
   На телефоне наведения нет вовсе, поэтому :active обязателен — отклик на
   нажатие подтверждает, что попал. */
.dtable tr[data-row-href]{ cursor: pointer; }
.dtable tr[data-row-href]:hover{ background: var(--c-surface-2); }
.dtable tr[data-row-href]:active{ background: var(--c-surface-3); }

/* Зона нажатия под палец (GS-140). Замер 27.08.2026: высота 19px при норме 48 —
   заголовок колонки промахивается чаще всего, потому что цель узкая по высоте
   и стоит вплотную к соседней.

   Через min-height, а не padding: `all: unset` снял внутренние отступы, и
   вернуть их значило бы заново собирать вид кнопки. Ширину не трогаем —
   inline-size: 100% уже растянул её на всю ячейку. */
@media (pointer: coarse){
  .dtable-sort{ min-block-size: 48px; }
}
.dtable th.num .dtable-sort { justify-content: flex-end; }

/* Индикатор — двойной каре́т, рисуется без иконок (в наборе нет стрелок) */
.dtable-sort__ind {
  position: relative;
  inline-size: 8px;
  block-size: 14px;
  flex: none;
  color: var(--c-ink-4);
}
.dtable-sort__ind::before,
.dtable-sort__ind::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  margin-inline: auto;
  inline-size: 0;
  block-size: 0;
  border-inline: 4px solid transparent;
}
.dtable-sort__ind::before { inset-block-start: 2px; border-block-end: 5px solid currentColor; }
.dtable-sort__ind::after  { inset-block-end: 2px;  border-block-start: 5px solid currentColor; }

/* tri-state: none (тускло) / ascending (верхний каре́т золотой) / descending */
.dtable th[aria-sort="none"] .dtable-sort__ind { opacity: .55; }
.dtable th[aria-sort="none"] .dtable-sort:hover .dtable-sort__ind { opacity: .9; }
.dtable th[aria-sort="ascending"]  .dtable-sort__ind { color: var(--c-gold); }
.dtable th[aria-sort="ascending"]  .dtable-sort__ind::after  { color: var(--c-ink-4); opacity: .4; }
.dtable th[aria-sort="descending"] .dtable-sort__ind { color: var(--c-gold); }
.dtable th[aria-sort="descending"] .dtable-sort__ind::before { color: var(--c-ink-4); opacity: .4; }

/* ── Колонка выбора ──────────────────────────────────────────────────────────── */
.dtable__cell-check { inline-size: 1%; padding-inline: 14px; text-align: center; }
.dtable__cell-check .dtable-sort { display: none; }

.dtable__check,
.dtable__check-all {
  inline-size: 16px;
  block-size: 16px;
  margin: 0;
  cursor: pointer;
  accent-color: var(--c-gold);
  vertical-align: middle;
}
.dtable__check:focus-visible,
.dtable__check-all:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-xs);
}
.dtable__check:disabled,
.dtable__check-all:disabled { cursor: default; opacity: .5; }

/* Колонка действий — прижата вправо */
.dtable__cell-actions { text-align: end; inline-size: 1%; white-space: nowrap; }
.dtable__cell-actions .dtable-actions { display: inline-flex; gap: var(--sp-2); justify-content: flex-end; }

/* ── Мобильный адаптив: таблица → карточки (≤720px) ──────────────────────────────
   На узком экране .dtable расползалась вширь (nowrap + overflow:auto → горизонтальный
   скролл, длинные названия обрезались). Здесь строка становится карточкой: thead
   скрыт, каждая ячейка — «подпись → значение» (подпись из data-label на <td>), а
   название встречи (.dtable__primary) занимает всю ширину и ПЕРЕНОСИТСЯ. Скролла вбок
   больше нет. data-label задаётся в шаблонах (my_reports/admin_list).
   Брейкпоинт 720px — синхронен со схлопыванием карточек проектов в админке
   (иначе на планшете 641-720 таблица оставалась со скроллом). Тач-цели — канон
   холдинга 48px (ссылка названия и кнопка удаления получают hit-area через padding). */
@media (max-width: 720px) {
  .dtable-wrap { overflow: visible; max-block-size: none; border: 0; box-shadow: none; background: transparent; }
  .dtable { display: block; font-size: 14px; }
  /* Липкий заголовок скрыт визуально, доступность сохранена; сортировка — десктопная.
     🔴 Обрезать РОДИТЕЛЯ недостаточно: clip:rect() режет только отрисовку, а <tr>
     внутри остаётся display:table-row и держит ширину всех колонок. Замер
     15.08.2026: thead сжат до 1px, а строка внутри — 389px при вьюпорте 360, и
     именно она давала горизонтальную прокрутку всей страницы. Табличная строка
     не подчиняется ни overflow:hidden, ни clip-path родителя, поэтому её саму
     переводим в блок и обнуляем ширину. */
  .dtable thead { position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
  .dtable thead tr { display: block; width: 1px; overflow: hidden; }
  .dtable thead th { display: block; width: 1px; padding: 0; border: 0; }
  .dtable tbody { display: block; }
  /* Ноль просмотров в карточке не показываем (GS-140). Замер 27.08.2026:
     строка «Просмотры 0» занимала 24px из 137 и сообщала ОТСУТСТВИЕ события.
     Молчание — верное умолчание: ноль виден по тому, что строки нет.
     На широком экране колонка остаётся — там это часть таблицы, и дыра в
     столбце читалась бы как потеря данных. Сортировка не страдает:
     data-sort-value на месте. */
  .dtable .views-cell.is-zero { display: none; }
  /* Пустая ячейка (например, длительность неизвестна) не занимает высоту:
     :empty сюда не подходит — внутри пробелы разметки, поэтому меряем по
     отсутствию data-label, который шаблон ставит только при наличии значения. */
  .dtable tbody td:not([data-label]):empty { display: none; }
  .dtable tbody tr {
    display: block;
    position: relative;                                          /* якорь для кнопки удаления */
    background: var(--c-surface);
    border: 1px solid var(--c-line);
    border-radius: var(--radius-md);
    box-shadow: var(--elev-1);
    padding: 10px 13px;
    margin-block-end: 8px;
  }
  .dtable tbody tr:last-child { margin-block-end: 0; }
  .dtable tbody tr:hover { background: var(--c-surface); }        /* без hover-заливки на тач */
  .dtable tbody td {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 2.5px 0;                                             /* плотнее — список записей компактный */
    border: 0;
    white-space: normal;                                          /* снимаем nowrap — перенос разрешён */
    text-align: end;
    box-sizing: border-box;
  }
  /* Подпись колонки перед значением — только у ячеек с data-label (иначе пустой
     псевдоэлемент ломал бы space-between; исключения .dtable__primary/actions теперь
     не нужны — у них нет data-label и ::before не создаётся). Цвет ink-2 — читаемее. */
  .dtable tbody td[data-label]::before {
    content: attr(data-label);
    flex: none;
    font-family: var(--font-mono);
    font-size: 12px;        /* пол шкалы: подпись колонки — единственный ориентир
                               в карточке, мелким кеглем читалась как шум */
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--c-ink-2);
    text-align: start;
  }
  /* Название встречи — во всю ширину карточки, крупнее, переносится. Значок
     способа .who остаётся в ряд с названием — flex с выравниванием по верху. */
  .dtable tbody td.dtable__primary {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    text-align: start;
    font-size: 15px;
    font-weight: 600;
    padding-block-end: 6px;
    padding-inline-end: 46px;                                    /* место под absolute-блок действий в углу (одна иконка) */
    margin-block-end: 4px;
    border-block-end: 1px solid var(--c-line);
  }
  /* На /my кнопки удаления нет — отступ под неё не нужен (только когда есть actions). */
  .dtable tbody tr:not(:has(.dtable__cell-actions)) td.dtable__primary { padding-inline-end: 0; }
  /* В админке действий два (ключ + корзина) — отступ вдвое, иначе название заезжает под них. */
  .dtable tbody tr:has(.dtable__cell-actions .dtable__row-act):has(.dtable__cell-actions .dtable__row-del)
    td.dtable__primary { padding-inline-end: 90px; }
  /* Значок способа — вровень с первой строкой названия (надзор и «Отчёты»).
     🔴 float, а не отступ сверху: на этой ширине ячейка НЕ флекс, а блок
     (admin.css, «Ключ переноса» — так флаг замка не отрывается к правому краю
     на двухстрочном названии). Прежние `align-self` и `margin-top: 9px` были
     рассчитаны на флекс и в блочном потоке лишь сдвигали значок вниз: первая
     строка обтекала его, а ВТОРАЯ подтекала под низ и обрезалась. Замер на
     360px (GS-345): вторая строка начиналась с 26px при значке до 46px.
     float заставляет обтекать все строки сразу. */
  .dtable tbody td.dtable__primary .who { flex: none; float: inline-start; margin: 3px 8px 0 0; }
  /* Ссылка названия — тап-цель ≥44px (канон для inline-ссылок): текст по центру
     hit-area. Компактнее прежних 48px, список записей плотнее. Слитные строки рвутся. */
  .dtable tbody td.dtable__primary a.title-link {
    display: flex;
    align-items: center;
    flex: 1 1 auto;
    min-block-size: 44px;
    padding-block: 3px;
    white-space: normal;
    word-break: break-word;
  }
  /* Числовые ячейки — как обычные строки карточки */
  .dtable td.num { text-align: end; }
  /* Отметку времени НЕ рвём посередине. Родитель снимает nowrap (перенос нужен
     длинному названию встречи), и дата со временем вставала как «2026-08-23» +
     «06:28» на следующей строке — одна отметка читалась как две.

     🔴 ТОЛЬКО НА ЗНАЧЕНИИ, НЕ НА ЯЧЕЙКЕ. nowrap на самой td убирает перенос у
     ВСЕЙ строки карточки, включая подпись из ::before, и флекс-ячейка ужимается
     по содержимому: при ширине карточки 388px ячейка стала 160px, а
     space-between развалился — значение уехало к подписи вместо правого края.
     Замерено на «Встречах организации» 23.08.2026. */
  .dtable tbody td.num > span[data-utc] { white-space: nowrap; }
  /* Ячейка действий (админка): во всю ширину карточки (сброс десктопного
     inline-size:1%, иначе ячейка схлопывалась и кнопка вылезала за край),
     кнопка удаления вправо и тач-цель 48×48. */
  /* Кнопка удаления — в правом-верхнем углу карточки (absolute), не занимает
     свою строку и не наезжает на данные: список записей максимально компактный. */
  /* Действий может быть два (ключ «доступ» + корзина). Строим их флекс-строкой в
     углу карточки: раньше ячейка была inline-контейнером, элементы разносило
     собственным margin-inline-start и ключ наезжал на текст названия. */
  .dtable td.dtable__cell-actions {
    position: absolute; inset-block-start: 8px; inset-inline-end: 10px;
    display: flex; align-items: center; justify-content: flex-end; gap: 2px;
    inline-size: auto; padding: 0; margin: 0;
  }
  .dtable td.dtable__cell-actions::before { content: none; }
  .dtable td.dtable__cell-actions .dtable__row-del,
  .dtable td.dtable__cell-actions .dtable__row-act {
    margin: 0;                                                   /* отступ задаёт gap контейнера */
    min-inline-size: 40px;
    min-block-size: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

/* ── Справка по «?» ────────────────────────────────────────────────────────────
   Кнопка .help-q + всплывающая .help-pop (текст берётся из data-help). Раньше жила
   внутри admin_edit.html, из-за чего подсказки нельзя было ставить на других экранах. */
.help-q {
  position: relative;                          /* якорь для расширенной зоны нажатия */
  display: inline-flex; align-items: center; justify-content: center;
  flex: none;                                  /* во flex-строке не сжимается в овал */
  width: 16px; height: 16px;
  margin-left: 5px; padding: 0;
  border: none; border-radius: 50%;
  background: var(--c-surface-3);
  /* --c-ink-2, а не --c-ink-3: знак сидит на светлой плитке --c-surface-3, где
     приглушённый токен даёт 4.41 при норме 4.5 (на карточке он же — 5.69).
     Кегль 12px тут законен — это глиф в кружке, а не текст. */
  color: var(--c-ink-2);
  /* Семейство задаём явно: у <button> свой браузерный дефолт, и глиф
     набирался Arial — единственное чужое семейство на всех экранах. Глиф мелкий,
     но именно в мелком чужая гарнитура заметнее всего: другая толщина, другая точка.
     Засечная гарнитура для «i» намеренно: моноширинная строчная «i» — это палочка
     с точкой без засечек, в кружке 16px она читается как «l» или как мусор.
     Serif даёт узнаваемый глиф информации, тот же, что во всех современных
     интерфейсах. */
  font-family: Georgia, "Times New Roman", serif;
  font-size: 12px; font-weight: 700; line-height: 1;
  /* Оптическая компенсация: строчная «i» у serif-гарнитур сидит выше центра
     кружка из-за точки — без сдвига глиф «висит». */
  padding-bottom: 1px;
  cursor: pointer; vertical-align: middle;
  transition: background .15s, color .15s;
}
/* Зона нажатия ≥24px (WCAG 2.5.8) при визуальном размере 16px: сам кружок
   раздувать нельзя — он стоит в строке заголовка и ломал бы ритм. Псевдоэлемент
   не влияет на поток и не перехватывает hover соседей: он строго по центру. */
.help-q::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 24px; height: 24px;
  transform: translate(-50%, -50%);
}
/* 48px под пальцем — норма холдинга (GS-139): одним числом перекрывает WCAG AA
   (24), WCAG AAA (44) и Material (48). Прежние 44 брались по Apple HIG.
   Граница по способу ввода, а не по ширине: у сенсорного ноутбука ширина
   десктопная, а палец тот же. */
@media (pointer: coarse){
  .help-q::after{ width: 48px; height: 48px; }
}
.help-q:hover,
.help-q[aria-expanded="true"] { background: var(--c-gold-bg); color: var(--c-gold); }
.help-q:focus-visible { box-shadow: var(--focus-ring); outline: none; }
/* 🔴 ПАРНОЕ ПРАВИЛО К display:inline-flex — без него [hidden] НЕ РАБОТАЕТ (GS-175).
   У формы канала «i» рядом с «Куда» скрывается JS-ом для видов без text (email,
   webhook — components.js apply()), но display:inline-flex выше перебивает
   браузерное [hidden]{display:none}: кнопка оставалась видимой и кликабельной,
   а popup открывался пустым — data-help у неё никогда не было. */
.help-q[hidden] { display: none; }
/* Связка «последнее слово + ?»: кнопка — inline-flex, то есть для переносчика
   строк это отдельное слово, и на узком экране она уезжала вниз одна. Оборачиваем
   её вместе с предшествующим словом и запрещаем перенос ВНУТРИ группы; строка
   по-прежнему переносится по пробелу перед группой, так что длинный заголовок
   не выпирает за край. */
.nowrap-q{ white-space: nowrap; }
/* Скрим фокуса — затемняет + блюрит фон, выделяя открытую подсказку/поповер
   (канон академии). Общий для .help-pop и .preset-popover; ставится под ними
   (z-index 999 < 1000). Клик по нему закрывает подсказку. */
.gx-scrim {
  position: fixed; inset: 0; z-index: 999;
  background: rgba(10,10,12,.52);
  -webkit-backdrop-filter: blur(7px);
  backdrop-filter: blur(7px);
  opacity: 0;
  visibility: hidden;              /* погашенный скрим НЕ перехватывает клики */
  pointer-events: none;
  transition: opacity .16s ease, visibility .16s ease;
}
.gx-scrim.is-on { opacity: 1; visibility: visible; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) { .gx-scrim { transition: none; } }

/* 🔴 Подсказка, ВЫЗВАННАЯ ИЗ МОДАЛКИ, затемняет и её тоже (17.08.2026).
   Скрим стоял на z-index 999, модалка — на 1000: слой ложился ПОД окно и
   блюрил только страницу за ним. На экране это выглядело сломанным — тёмный
   размытый фон по краям и резкое окно посередине, поверх которого висит
   подсказка (замечание владельца по скриншоту).
   Поднимаем оба слоя выше окна, когда модалка открыта: подсказка объясняет
   поле формы, и подсвечивать она должна форму, а не страницу под ней.
   Селектор по состоянию оверлея, а не постоянный: вне модалки прежний порядок
   верен — там скрим гасит именно страницу. */
body:has(.sc-modal-overlay.is-open) .gx-scrim { z-index: 1100; }
body:has(.sc-modal-overlay.is-open) .help-pop { z-index: 1101; }

.help-pop {
  position: fixed; z-index: 1000;
  max-width: 320px;
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-2);
  padding: 12px 14px;
  font-size: 13.5px; font-weight: 400; line-height: 1.55;
  color: var(--c-ink-2);
  /* Переводы строк из data-help сохраняются: длинные подсказки (условия доступа
     на главной) — это список пунктов, а схлопнутый в абзац список не читается.
     pre-line, не pre: обычные переносы по ширине по-прежнему работают. */
  white-space: pre-line;
}
/* Hover-тултип [data-tip] — тот же вид, поуже (короткие пояснения).

   pointer-events: none — подсказка не ловит курсор. Мигания она не давала и без
   этого (узел лежит в body, а не внутри элемента, поэтому наведение на неё не
   читается как уход с носителя), но перехватывать клики по тому, что под ней,
   ей тем более незачем: она поясняет страницу, а не заслоняет. Свойство пришло
   из инлайн-копии отчёта, когда копию убирали в пользу общего механизма
   (GS-254) — единственное, чем копия отличалась по делу. */
.tip-pop { max-width: 260px; padding: 9px 12px; pointer-events: none; }
[data-tip] { cursor: help; }

/* Подсказка достаётся с клавиатуры (GS-254). Носитель подсказки — часто <span>,
   у которого своей обводки нет: без этого правила фокус на значке не виден
   вовсе, и человек не понимает, где находится. */
[data-tip][tabindex]:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-xs); }

/* Тач-цель значка-подсказки (GS-254, канон холдинга — 48px под палец).
   Сами значки 13-14px: попасть пальцем в такую цель нельзя, а расширять их
   видимый размер значит перекроить строку таблицы. Поэтому область касания
   растёт псевдоэлементом — вид и поток не меняются, промахи исчезают.

   Только под pointer: coarse — под мышью прозрачная накладка 44px перекрывала
   бы соседние ссылки в той же строке. */
@media (pointer: coarse){
  .rflag[data-tip], .src-file[data-tip], .who[data-tip],
  .chan__secret[data-tip], .arow__rate[data-tip], .arow__count[data-tip] {
    position: relative;
  }
  .rflag[data-tip]::after, .who[data-tip]::after,
  .chan__secret[data-tip]::after, .arow__rate[data-tip]::after,
  .arow__count[data-tip]::after {
    content: "";
    position: absolute;
    inset: 50% auto auto 50%;
    inline-size: 44px; block-size: 44px;
    transform: translate(-50%, -50%);
  }
}

/* Удаление строки — приглушено по умолчанию, краснеет при наведении: разрушающее
   действие не должно притягивать взгляд в каждой строке таблицы. */
.dtable__row-del {
  margin-inline-start: var(--sp-3);
  padding: 4px;
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  background: none;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--c-ink-4);
  cursor: pointer;
  transition: color .14s ease, background .14s ease;
}
.dtable__row-del:hover { color: var(--c-danger); background: var(--c-danger-bg); }
.dtable__row-del:focus-visible { box-shadow: var(--focus-ring); outline: none; }

/* Нейтральное действие в строке (не удаление): «доступ к встрече». Форма та же,
   что у корзины, — иконки в строке должны быть одного размера и веса. */
/* Класс писался под <a>, но живёт и на <button> (кнопки в формах строки).
   У кнопки есть СВОЙ фон и рамка от браузера — светло-серые. В тёмной теме
   это давало серый квадрат вместо значка: сама иконка рисовалась верно, её
   просто не было видно на чужой подложке. Гасим явно. */
.dtable__row-act {
  margin-inline-start: var(--sp-3);
  padding: 4px;
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  border: 0;
  background: none;
  font: inherit;
  cursor: pointer;
  border-radius: var(--radius-sm);
  color: var(--c-ink-4);
  text-decoration: none;
  transition: color .14s ease, background .14s ease;
}
.dtable__row-act:hover { color: var(--c-gold); background: var(--c-gold-bg); }
.dtable__row-act:focus-visible { box-shadow: var(--focus-ring); outline: none; }

/* Значки состояния рядом с названием встречи: закрыта паролем, есть срок. */
.rflag {
  display: inline-flex;
  align-items: center;
  margin-inline-start: 6px;
  color: var(--c-ink-4);
  vertical-align: middle;
}

/* Имя исходного файла под названием встречи (GS, жалоба владельца 04.09.2026).
   Заголовок от нейросети рвёт связь с загруженным файлом, и при пакетной
   загрузке человек не понимает, какая запись из какого файла. Показывается не
   всегда — правило молчания на сервере (meetingtitle.source_hint).

   🔴 flex-basis: 100% — не украшение, а условие видимости. Ячейка .dtable__primary
   объявлена display:flex (admin.css), и без принудительного переноса подпись
   встала бы ЧЕТВЁРТОЙ КОЛОНКОЙ в один ряд с названием и флагами, отъехав к
   правому краю. На страницах admin:reports и my:all ячейка переопределена в
   display:block — там basis игнорируется, и работает display:block ниже. Оба
   режима обязаны давать строку под названием.

   Моноширинный — потому что имена файлов СРАВНИВАЮТ посимвольно («запись_1»
   против «запись_11»), а это и есть работа, ради которой подпись добавлена.
   Пропорциональный шрифт такому сравнению мешает. */
.src-file {
  display: block;
  flex-basis: 100%;
  margin-block-start: 2px;
  font-family: var(--font-mono, monospace);
  font-size: 12px;                 /* на ступень ниже вторичного (13px): подпись не спорит с названием */
  line-height: 1.35;
  color: var(--c-ink-3);
  overflow-wrap: anywhere;         /* длинное имя без пробелов не растягивает колонку */
}

/* ── Панель массовых действий ──────────────────────────────────────────────── */
.dtable-toolbar {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  padding: 8px 12px;
  background: var(--c-gold-bg);
  border: 1px solid var(--c-gold-line);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-1);
  transform-origin: top;
  animation: dtable-tb-in .16s ease;
}
.dtable-toolbar[hidden] { display: none; }
@keyframes dtable-tb-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

.dtable-toolbar__count {
  font-size: 13px;
  font-weight: 600;
  color: var(--c-gold-strong);
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
}
.dtable-toolbar__count [data-dt-count] { font-variant-numeric: tabular-nums; }
.dtable-toolbar__spacer { flex: 1 1 auto; }
.dtable-toolbar__actions { display: inline-flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }

/* Кнопки панели: нейтральные «чипы» + danger-вариант. Своё имя, чтобы не задеть .btn */
.dtable-tb__btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  font: 600 13px/1 var(--font-sans);
  color: var(--c-ink);
  background: var(--c-surface);
  border: 1px solid var(--c-line-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
  white-space: nowrap;
  transition: border-color .12s ease, color .12s ease, background .12s ease;
}
.dtable-tb__btn:hover { border-color: var(--c-gold); color: var(--c-gold); }
.dtable-tb__btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.dtable-tb__btn--danger { color: var(--c-danger); border-color: var(--c-danger-line); }
.dtable-tb__btn--danger:hover { background: var(--c-danger-bg); border-color: var(--c-danger); color: var(--c-danger); }
.dtable-tb__btn--ghost {
  border-color: transparent;
  background: transparent;
  color: var(--c-ink-3);
  padding-inline: 8px;
}
.dtable-tb__btn--ghost:hover { color: var(--c-ink); background: var(--c-surface-3); }

/* ── Пустое состояние ──────────────────────────────────────────────────────── */
.dtable-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-10) var(--sp-6);
  text-align: center;
  color: var(--c-ink-3);
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-1);
}
.dtable-empty__ic { color: var(--c-ink-4); }
.dtable-empty__title { color: var(--c-ink-2); font-weight: 600; font-size: 14.5px; }
.dtable-empty__sub { font-size: 13px; max-inline-size: 42ch; }

/* Ячейка-статус — терминальная плашка: 1px рамка + капс-моно (фирменный язык).
   Размер уменьшен с 13px/.07em: бейдж — подпись к строке, а не заголовок, и в
   прежнем кегле он спорил с названием организации рядом. */
/* Кегль 12px — пол шкалы холдинга. Было 11: бейдж состояния («пробный»,
   «внутренняя») читается в таблице бегло и мелким терялся; трекинг оставлен,
   он на 12-м кегле уже не распирает ячейку. */
/* Базовый чип — КЛИЕНТСКИЙ: скруглённый, обычным начертанием (GS-383).
   Капс-моно снят вместе с острым краем: терминальная гарнитура — часть того же
   служебного языка, и оставлять её на скруглённой таблетке значило бы смешать
   два приёма в одном элементе. Кегль 12px сохранён — он читается в плотной
   строке и не спорит с именем рядом. */
.dtable-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .01em;
  line-height: 1.45;
  border-radius: var(--radius-pill);
  border: 1px solid var(--c-line-strong);
  background: var(--c-surface-3);
  color: var(--c-ink-2);
}
/* 🔴 ТЕРМИНАЛЬНЫЙ ВАРИАНТ — ТОЛЬКО АДМИНКА. Возвращает язык Synology DSM:
   острый край, капс-моно, разрядка. Ставится классом в `admin_*.html`, а не
   селектором по странице: список страниц разошёлся бы с реальностью на первом
   же новом экране надзора. */
.dtable-badge--term {
  padding: 2px 7px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
  border-radius: 0;
}
/* ═══════════════════════════════════════════════════════════════════════════
   🔴 ФОРМА ЧИПА ЗАВИСИТ ОТ СЛОЯ, А НЕ ОТ ЭКРАНА (GS-383, решение владельца
   12.09.2026)

   Чипы разошлись по форме: на главной — скруглённые таблетки, в разделе
   «Организация» — прямоугольники с рамкой и капс-моно. Одно и то же (состояние)
   говорилось на двух языках, и человек видел оба.

   Сводить можно было в любую сторону. Выбрано СКРУГЛЕНИЕ у клиента — решение
   владельца: «на главной были закруглённые чипы, и это выглядело здорово, оно
   как раз придавало нашей квадратности некий шарм». Довод сильный и не
   вкусовой: канон П1 бережёт круг у ОРГАНОВ УПРАВЛЕНИЯ, чтобы круглая кнопка
   «+» читалась как кнопка. Чип не нажимают — спутать его с кнопкой нельзя, и
   скругление тут не размывает приём, а даёт точку контраста на квадратной
   сетке.

   Граница проходит по СЛОЮ ПРОДУКТА:

     • КЛИЕНТСКИЕ экраны (главная, «Организация», отчёт, оплата) — скруглённый
       чип. Это лицо сервиса, его видит покупатель.
     • АДМИНКА (`admin_*.html`) — терминальный прямоугольник с капс-моно и
       рамкой, язык Synology DSM. Служебный слой, где плотность и строгость
       уместны, а клиент туда не заходит вовсе.

   Именно СЛОЙ, а не «страница»: `.dtable-badge` живёт и там, и там, поэтому
   скругление задаётся базовому классу, а острый край возвращается в админке
   классом `.dtable-badge--term`. Иначе правило пришлось бы держать списком
   страниц, и первый же новый экран его нарушил бы.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════════════════
   🔴 ДВА УРОВНЯ ЧИПА: СОСТОЯНИЕ И ПОМЕТКА (GS-383, 12.09.2026)

   До этой правки оба набирались одинаково — рамка, заливка, капс-моно 12px, —
   и на карточке участника «ВЛАДЕЛЕЦ» с «ЭТО ВЫ» весили больше самой почты.
   Замечание владельца по снимку: «чип выглядит больше, чем сама надпись, а чип
   обычно второстепенная информация». Там же названа развилка: плашка «ПРОБНЫЙ
   ДОСТУП» в шапке органична, «потому что она сообщает о чём-то важном», а
   пометки участника — нет.

   Отсюда правило, а не разовая правка:

     • СОСТОЯНИЕ (`.dtable-badge`) — то, что может ПОМЕНЯТЬСЯ и требует
       внимания: пробный доступ, отозвана, канал выключен. Коробка с рамкой,
       цвет у тревожных. Это «посмотри сюда».
     • ПОМЕТКА (`.dtable-badge--quiet`) — неизменный факт о строке, который
       лишь уточняет: владелец, это вы, по умолчанию. Коробки нет вовсе —
       ни рамки, ни заливки. Это «к сведению».

   Почему у пометки снята именно КОРОБКА, а не уменьшен кегль. Вес чипу даёт
   не размер букв, а замкнутый контур: рамка с заливкой читается как отдельный
   предмет на карточке и конкурирует с текстом рядом. Сняв коробку, пометка
   становится подписью — тем, чем и является. Кегль при этом можно оставить
   прежним, и мелкий нечитаемый текст не появляется.

   Форму оба берут у своего слоя (см. блок выше): у клиента скруглённую, в
   админке терминальную. Уровень — про ВЕС, слой — про ФОРМУ, и путать их
   нельзя: тихая пометка в админке останется прямоугольной, а громкое
   состояние у клиента — скруглённым.
   ═══════════════════════════════════════════════════════════════════════════ */
.dtable-badge--quiet {
  border-color: transparent;
  background: transparent;
  color: var(--c-ink-3);
  padding-inline: 0;
  /* Промежуток между соседними пометками даёт разделитель, а не рамка: без
     коробок «ВЛАДЕЛЕЦ ЭТО ВЫ» слились бы в одну строку. Точка-разделитель —
     тот же приём, что в подзаголовке «Организация · Владелец». */
  gap: 0;
}
.dtable-badge--quiet + .dtable-badge--quiet::before {
  content: "·";
  margin-inline-end: 7px;
  color: var(--c-ink-4);
}

/* Цветной бейдж — только там, где состояние ТРЕБУЕТ ДЕЙСТВИЯ надзора.
   «Активна» и «Пробный» — норма и большинство строк списка; крашеные, они
   давали четыре акцентных цвета в одной таблице, и по-настоящему тревожная
   строка терялась среди зелёных и синих. Норму рисуем нейтрально, цвет
   оставляем предупреждению и отказу. */
.dtable-badge--info,
.dtable-badge--success { background: var(--c-surface-3); color: var(--c-ink-2); border-color: var(--c-line-strong); }
.dtable-badge--warn    { background: var(--c-warn-bg);    color: var(--c-warn);    border-color: color-mix(in srgb, var(--c-warn) 35%, transparent); }
.dtable-badge--danger  { background: var(--c-danger-bg);  color: var(--c-danger);  border-color: color-mix(in srgb, var(--c-danger) 35%, transparent); }

/* Визуально скрытый, но доступный скринридеру текст (капшн/подписи строк) */
.dtable-sr {
  position: absolute !important;
  inline-size: 1px; block-size: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

/* ── Адаптив ───────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  .dtable th, .dtable td { padding: 9px 10px; }
  .dtable { font-size: 13px; }
  .dtable-toolbar { position: sticky; inset-block-start: 0; z-index: 3; }
}

/* ── prefers-reduced-motion ────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .dtable tbody tr,
  .dtable-sort,
  .dtable-tb__btn { transition: none; }
  .dtable-toolbar { animation: none; }
  .dtable-wrap { scroll-behavior: auto; }
}
/* ═══════════════ sc-toast ═══════════════ */
/* ═══════════════════════════════════════════════════════════════════════════
   GOLDJAXE Scribe · sc-toast — тост-уведомления (стиль Synology DSM)
   Зависит ТОЛЬКО от токенов из /static/tokens.css. Цвета/тему не переопределяет.
   Префикс .sc-toast* — не конфликтует с .card/.btn/.seg/.t/.k/.pcard/.hdr.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Контейнер-стек — один на страницу, создаётся лениво из JS (id=scToaster) */
.sc-toaster{
  position:fixed;
  top:var(--sp-4);
  right:var(--sp-4);
  z-index:9999;
  display:flex;
  flex-direction:column;
  gap:var(--sp-2);
  width:min(380px, calc(100vw - var(--sp-8)));
  max-height:100vh;
  pointer-events:none;          /* сквозные клики в промежутках стека */
}
.sc-toaster > *{ pointer-events:auto; }

@media (max-width:520px){
  .sc-toaster{ top:var(--sp-3); right:var(--sp-3); left:var(--sp-3); width:auto; }
}

/* Тост */
/* Заливка семантическим фоном, а не белая карточка с полоской (решение владельца
   15.08.2026: «сделать серьёзнее, в нашем стиле»). Три следствия:
   — уведомление читается как ОДИН объект нужного тона, а не как карточка со
     служебной чёрточкой: цвет виден боковым зрением, до чтения текста;
   — акцент слева 4px вместо 3: на заливке тонкая полоса теряется;
   — кегль 14/13.5 вместо 13.5/13 — это сообщение о результате действия, а не
     сноска; на 13px оно читалось как служебная строка.
   Фон берётся из *-bg токенов (они полупрозрачные) — поэтому одинаково работает
   в светлой и обеих тёмных темах, без отдельных наборов значений. */
.sc-toast{
  --sc-accent: var(--c-info);
  --sc-fill: var(--c-info-bg);
  position:relative;
  display:flex;
  align-items:flex-start;
  gap:var(--sp-3);
  padding:var(--sp-4);
  /* Заливка кладётся слоем поверх подложки: *-bg токены полупрозрачны, и на
     var(--c-surface) они дают нужный тон в любой теме. */
  background-color:var(--c-surface);
  background-image:linear-gradient(var(--sc-fill), var(--sc-fill));
  border:1px solid var(--c-line);
  border-left:4px solid var(--sc-accent);   /* семантический акцент слева */
  border-radius:var(--radius-md);
  box-shadow:var(--elev-2);
  color:var(--c-ink);
  overflow:hidden;
  opacity:0;
  transform:translateX(12px);
  transition:opacity .22s ease, transform .22s ease;
}
.sc-toast.is-in{  opacity:1; transform:translateX(0);  }
.sc-toast.is-out{ opacity:0; transform:translateX(12px); }

.sc-toast--success{ --sc-accent: var(--c-success); --sc-fill: var(--c-success-bg); }
.sc-toast--info{    --sc-accent: var(--c-info);    --sc-fill: var(--c-info-bg); }
.sc-toast--warn{    --sc-accent: var(--c-warn);    --sc-fill: var(--c-warn-bg); }
.sc-toast--danger{  --sc-accent: var(--c-danger);  --sc-fill: var(--c-danger-bg); }

/* Ведущая иконка (наследует акцент варианта). :empty — сворачивается без gap-остатка */
.sc-toast__icon{
  flex:0 0 auto;
  display:flex;
  margin-top:1px;
  color:var(--sc-accent);
}
.sc-toast__icon:empty{ display:none; }
.sc-toast__icon svg{ width:18px; height:18px; }

/* Текст */
.sc-toast__body{ flex:1 1 auto; min-width:0; }
.sc-toast__title{
  font-size:14px; font-weight:700; line-height:1.35;
  color:var(--c-ink); letter-spacing:-0.1px;
}
.sc-toast__msg{
  font-size:13.5px; line-height:1.5; color:var(--c-ink);
  overflow-wrap:anywhere;
}
.sc-toast__title + .sc-toast__msg{ margin-top:3px; }

/* Кнопка закрытия (× = plus, повёрнутый на 45°; текстовый фолбэк — если иконок нет) */
.sc-toast__close{
  flex:0 0 auto;
  width:24px; height:24px;
  margin:-2px -2px 0 0;
  padding:0;
  display:inline-flex; align-items:center; justify-content:center;
  border:0; border-radius:var(--radius-xs);
  background:transparent; color:var(--c-ink-3);
  cursor:pointer;
  transition:background .15s ease, color .15s ease;
}
.sc-toast__close:hover{ background:var(--c-surface-3); color:var(--c-ink); }
.sc-toast__close:focus-visible{ box-shadow:var(--focus-ring); }  /* золотое кольцо из токенов */
.sc-toast__close svg{ width:16px; height:16px; transform:rotate(45deg); }
.sc-toast__x{ font-size:19px; line-height:1; }

/* Полоса авто-скрытия (линейно убывает; на паузе — замирает вместе с JS-таймером) */
.sc-toast__timer{
  position:absolute; left:0; bottom:0;
  width:100%; height:2px;
  background:var(--sc-accent);
  opacity:.45;
  transform:scaleX(1);
  transform-origin:left center;
}
.sc-toast__timer--run{ animation:sc-toast-timer var(--sc-timer,5000ms) linear forwards; }
.sc-toast.is-paused .sc-toast__timer--run{ animation-play-state:paused; }
@keyframes sc-toast-timer{ from{ transform:scaleX(1); } to{ transform:scaleX(0); } }

/* prefers-reduced-motion: без сдвигов и без бегущей полосы, только мягкое проявление */
@media (prefers-reduced-motion: reduce){
  .sc-toast{ transition:opacity .14s ease; transform:none; }
  .sc-toast.is-in,
  .sc-toast.is-out{ transform:none; }
  .sc-toast__timer{ display:none; }
  .sc-toast__timer--run{ animation:none; }
}
/* ═══════════════ segmented-tabs ═══════════════ */
/* ═══════════════════════════════════════════════════════════════════════════
   GOLDJAXE Scribe — segmented-tabs
   Сегмент-контрол (.sc-seg) + вкладки (.sc-tabs). Все селекторы с префиксом sc-,
   чтобы не конфликтовать с .card/.btn/.seg/.t/.k/.pcard/.hdr.
   Только токены из tokens.css. Светлая/тёмная тема наследуются автоматически.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Сегмент-контрол (пилюля-подложка, активная кнопка — приподнятая карточка) ── */
.sc-seg{
  display:inline-flex;
  gap:2px;
  padding:3px;
  background:var(--c-surface-3);
  border:1px solid var(--c-line);
  border-radius:var(--radius-md);
  max-width:100%;
  overflow-x:auto;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:none;
}
.sc-seg::-webkit-scrollbar{ display:none; }

.sc-seg > button{
  -webkit-appearance:none; appearance:none;
  flex:0 0 auto;
  display:inline-flex; align-items:center; justify-content:center; gap:6px;
  padding:6px 14px;
  border:0;
  border-radius:var(--radius-sm);
  background:transparent;
  color:var(--c-ink-3);
  font:600 13px/1 var(--font-sans);
  letter-spacing:-.1px;
  white-space:nowrap;
  cursor:pointer;
  transition:color .15s, background .15s, box-shadow .15s;
}
.sc-seg > button:hover:not(:disabled):not([aria-checked="true"]):not([aria-selected="true"]){
  color:var(--c-ink-2);
}
.sc-seg > button[aria-checked="true"],
.sc-seg > button[aria-selected="true"]{
  background:var(--c-surface);
  color:var(--c-ink);
  box-shadow:var(--elev-1);
}
.sc-seg > button:disabled{ opacity:.45; cursor:not-allowed; }
.sc-seg > button:focus-visible{ outline:none; box-shadow:var(--focus-ring); }
.sc-seg > button[aria-checked="true"]:focus-visible,
.sc-seg > button[aria-selected="true"]:focus-visible{ box-shadow:var(--elev-1), var(--focus-ring); }

/* модификатор: тянуть кнопки на всю ширину контейнера */
.sc-seg--block{ display:flex; width:100%; }
.sc-seg--block > button{ flex:1 1 0; }

/* ── Вкладки (горизонтальные, золотой нижний индикатор) ──────────────────────── */
.sc-tabs{ display:block; }

.sc-tabs__list{
  display:flex;
  gap:var(--sp-1);
  padding:3px 3px 0;
  border-bottom:1px solid var(--c-line);
  overflow-x:auto;
  overflow-y:hidden;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:thin;
}

.sc-tab{
  -webkit-appearance:none; appearance:none;
  position:relative;
  flex:0 0 auto;
  display:inline-flex; align-items:center; gap:7px;
  padding:9px 14px 11px;
  border:0;
  border-radius:var(--radius-sm) var(--radius-sm) 0 0;
  background:transparent;
  color:var(--c-ink-3);
  font:600 14px/1 var(--font-sans);
  letter-spacing:-.1px;
  white-space:nowrap;
  cursor:pointer;
  transition:color .15s, background .15s;
}
/* Палец толще курсора: на сенсорном вводе корешок добирается до 44px — ниже
   этого промахи становятся обычным делом. Правило под @media (pointer:coarse),
   а не под шириной экрана: дело в способе ввода, а не в размере окна (планшет
   в альбомной ориентации шире телефона, а палец тот же). Мышиный указатель
   оставляем компактным — там 38px попадаются без промаха. */
@media (pointer:coarse){
  .sc-tab{ min-height:44px; padding-top:0; padding-bottom:0; }
}

.sc-tab:hover:not(:disabled):not([aria-selected="true"]){
  color:var(--c-ink);
  background:var(--c-surface-2);
}
.sc-tab[aria-selected="true"]{ color:var(--c-ink); }
.sc-tab:disabled{ opacity:.45; cursor:not-allowed; }
.sc-tab:focus-visible{ outline:none; box-shadow:var(--focus-ring); }

/* золотой индикатор активной вкладки — лежит на 1px-линии списка */
.sc-tab::after{
  content:"";
  position:absolute; left:8px; right:8px; bottom:0; height:2px;
  border-radius:2px 2px 0 0;
  background:transparent;
  transition:background .15s;
}
.sc-tab[aria-selected="true"]::after{ background:var(--c-gold); }

/* необязательный счётчик на вкладке/сегменте.
   Кегль 12px (пол шкалы) и цвет --c-ink-2: счётчик сидит на светлой плитке
   --c-surface-3, где приглушённый токен давал 4.41 при норме 4.5. Высота
   поднята до 20px, иначе 12-й кегль подпирает края пилюли. */
.sc-tab__count, .sc-seg__count{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:20px; height:20px; padding:0 6px;
  border-radius:var(--radius-pill);
  background:var(--c-surface-3);
  color:var(--c-ink-2);
  font:600 12px/1 var(--font-sans);
}
.sc-tab[aria-selected="true"] .sc-tab__count,
.sc-seg > button[aria-checked="true"] .sc-seg__count,
.sc-seg > button[aria-selected="true"] .sc-seg__count{
  background:var(--c-gold-bg); color:var(--c-gold-strong);
}

/* Ноль найденного при активном поиске: счётчик гаснет, но НЕ пропадает —
   пропавший корешок сдвигает остальные, и человек теряет место. Показываем,
   что вкладка проверена и пуста. */
.sc-tab__count.is-zero{
  background:transparent; color:var(--c-ink-4);
  box-shadow:inset 0 0 0 1px var(--c-line);
}
.sc-tab[aria-selected="true"] .sc-tab__count.is-zero{
  background:transparent; color:var(--c-ink-4);
}

/* иконки внутри — наследуют цвет текста; чуть приглушены у неактивных */
.sc-seg > button:not([aria-checked="true"]):not([aria-selected="true"]) .ic,
.sc-tab:not([aria-selected="true"]) .ic{ opacity:.85; }

/* ── Панели вкладок ──────────────────────────────────────────────────────────── */
.sc-tabpanel{
  padding-top:var(--sp-4);
  animation:sc-fade .18s ease both;
}
.sc-tabpanel[hidden]{ display:none; }
.sc-tabpanel:focus-visible{ outline:none; box-shadow:var(--focus-ring); border-radius:var(--radius-sm); }

@keyframes sc-fade{ from{ opacity:0 } to{ opacity:1 } }

/* ── Меньше движения ─────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  .sc-seg > button, .sc-tab, .sc-tab::after{ transition:none; }
  .sc-tabpanel{ animation:none; }
}
/* ═══════════════ form-controls ═══════════════ */
/* ============================================================================
   GOLDJAXE Scribe — form-controls (единый набор). Стиль Synology DSM: плотно,
   малые радиусы, опора на 1px-границы, золото — единственный акцент, экономно.

   Все значения — токены из static/tokens.css. Светлая/тёмная тема наследуются
   автоматически (никаких prefers-color-scheme здесь). Префикс .sc- — чтобы
   не конфликтовать с существующими .card/.btn/.seg/.t/.k/.pcard/.hdr.

   Единственный намеренный литерал — #211a06 (тёмный текст на золотой кнопке):
   золото светлое в обеих темах, поэтому текст обязан оставаться тёмным всегда
   (совпадает с легаси .btn.save / .btn-primary). Всё остальное — через токены.
   ========================================================================== */

/* ── Раскладка формы ──────────────────────────────────────────────────────── */
.sc-form   { display: flex; flex-direction: column; gap: var(--sp-4); min-width: 0; }
.sc-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4); }
@media (max-width: 560px) { .sc-grid-2 { grid-template-columns: 1fr; } }

/* ── Поле: подпись + контрол + подсказка/ошибка ───────────────────────────── */
.sc-field { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }

.sc-label {
  font-size: 13px; font-weight: 600; color: var(--c-ink-2);
  letter-spacing: .1px; line-height: 1.35;
}
.sc-label .sc-optional,
.sc-label .sc-hint { font-weight: 400; color: var(--c-ink-4); font-size: 13px; margin-left: 4px; }
.sc-req { color: var(--c-danger); margin-left: 2px; font-weight: 600; }

/* ── Базовый контрол: input / textarea / select ───────────────────────────── */
.sc-input,
.sc-textarea,
.sc-select__el {
  width: 100%;
  font-family: inherit;
  font-size: 14px;
  line-height: 1.45;
  color: var(--c-ink);
  background: var(--c-surface-2);
  border: 1px solid var(--c-line-strong);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  transition: border-color .15s, box-shadow .15s, background .15s;
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
}
.sc-input::placeholder,
.sc-textarea::placeholder { color: var(--c-ink-4); }

.sc-input:hover:not(:disabled):not([readonly]),
.sc-textarea:hover:not(:disabled):not([readonly]),
.sc-select__el:hover:not(:disabled) { border-color: var(--c-ink-4); }

.sc-input:focus,       .sc-input:focus-visible,
.sc-textarea:focus,    .sc-textarea:focus-visible,
.sc-select__el:focus,  .sc-select__el:focus-visible {
  outline: none;
  border-color: var(--c-gold);
  background: var(--c-surface);
  box-shadow: var(--focus-ring);
}

.sc-textarea { resize: vertical; min-height: 92px; line-height: 1.5; }
.sc-input.sc-mono,
.sc-textarea.sc-mono { font-family: var(--font-mono); font-size: 13px; }

/* размер sm */
.sc-input--sm,
.sc-textarea--sm,
.sc-select--sm .sc-select__el { padding: 7px 10px; font-size: 13px; border-radius: var(--radius-xs); }

/* disabled / readonly */
.sc-input:disabled,
.sc-textarea:disabled,
.sc-select__el:disabled { opacity: .55; cursor: not-allowed; background: var(--c-surface-3); }
.sc-input[readonly],
.sc-textarea[readonly] { background: var(--c-surface-3); color: var(--c-ink-2); cursor: default; }

/* невалидное состояние (aria-invalid или .is-error на .sc-field) */
.sc-input[aria-invalid="true"],
.sc-textarea[aria-invalid="true"],
.sc-select__el[aria-invalid="true"],
.sc-field.is-error .sc-input,
.sc-field.is-error .sc-textarea,
.sc-field.is-error .sc-select__el { border-color: var(--c-danger); background: var(--c-surface); }
.sc-field.is-error .sc-inputwrap__lead { color: var(--c-danger); }

/* ── Поле с ведущей иконкой и/или хвостовой кнопкой ────────────────────────── */
.sc-inputwrap { position: relative; display: block; }
.sc-inputwrap__lead,
.sc-inputwrap__trail {
  position: absolute; top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--c-ink-3);
}
.sc-inputwrap__lead  { left: 11px; pointer-events: none; transition: color .15s; }
.sc-inputwrap__trail { right: 6px; }
.sc-inputwrap:focus-within .sc-inputwrap__lead { color: var(--c-gold); }

.sc-input--lead  { padding-left: 38px; }
.sc-input--trail { padding-right: 40px; }

/* хвостовая кнопка-действие внутри поля (напр. показать пароль) */
.sc-input-action {
  border: 0; background: transparent; cursor: pointer;
  color: var(--c-ink-3); padding: 6px; border-radius: var(--radius-xs);
  display: inline-flex; transition: color .15s, background .15s;
}
.sc-input-action:hover { color: var(--c-gold); background: var(--c-surface-3); }
.sc-input-action:focus-visible { outline: none; box-shadow: var(--focus-ring); color: var(--c-gold); }

/* ── Select со своей стрелкой (чеврон из границ — цвет через токен) ────────── */
.sc-select { position: relative; display: block; }
.sc-select__el { padding-right: 34px; cursor: pointer; }
.sc-select__el option { color: var(--c-ink); background: var(--c-surface); }
.sc-select::after {
  content: ""; position: absolute; right: 14px; top: 50%; margin-top: -5px;
  width: 7px; height: 7px;
  border-right: 1.6px solid var(--c-ink-3);
  border-bottom: 1.6px solid var(--c-ink-3);
  transform: rotate(45deg);
  pointer-events: none; transition: border-color .15s;
}
.sc-select:hover::after       { border-color: var(--c-ink-2); }
.sc-select:focus-within::after { border-color: var(--c-gold); }
.sc-select:has(.sc-select__el:disabled)::after { opacity: .5; }

/* ── Checkbox / Radio (нативные, accent-color = золото) ────────────────────── */
.sc-check {
  display: inline-flex; align-items: flex-start; gap: var(--sp-2);
  font-size: 14px; line-height: 1.4; color: var(--c-ink); cursor: pointer;
}
.sc-check__box {
  flex: none; width: 16px; height: 16px; margin-top: 1px;
  accent-color: var(--c-gold); cursor: pointer;
}
.sc-check__box:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-xs); }
.sc-check__text { min-width: 0; }
.sc-check__text .sc-optional,
.sc-check__text .sc-hint { color: var(--c-ink-4); }
.sc-check:has(.sc-check__box:disabled) { color: var(--c-ink-4); cursor: not-allowed; }
.sc-check__box:disabled { cursor: not-allowed; }

/* группа радио/чекбоксов */
.sc-fieldset { border: 0; padding: 0; margin: 0; min-width: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.sc-legend   { padding: 0; font-size: 13px; font-weight: 600; color: var(--c-ink-2); }
.sc-check-list          { display: flex; flex-direction: column; gap: var(--sp-2); }
.sc-check-list--inline  { flex-direction: row; flex-wrap: wrap; gap: var(--sp-4); }

/* ── Toggle-switch (чистый CSS поверх нативного checkbox) ──────────────────── */
.sc-switch {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  font-size: 14px; line-height: 1.4; color: var(--c-ink); cursor: pointer;
}
.sc-switch__input { /* доступный, но визуально скрытый чекбокс */
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.sc-switch__track {
  position: relative; flex: none; width: 38px; height: 22px;
  background: var(--c-surface-3);
  border: 1px solid var(--c-line-strong);
  border-radius: var(--radius-pill);
  transition: background .18s ease, border-color .18s ease;
}
.sc-switch__thumb {
  position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: 50%;
  box-shadow: var(--elev-2);
  transition: transform .18s ease;
}
.sc-switch__input:checked + .sc-switch__track { background: var(--c-gold); border-color: var(--c-gold); }
.sc-switch__input:checked + .sc-switch__track .sc-switch__thumb { transform: translateX(16px); }
.sc-switch__input:focus-visible + .sc-switch__track { box-shadow: var(--focus-ring); }
.sc-switch:has(.sc-switch__input:disabled) { cursor: not-allowed; }
.sc-switch__input:disabled + .sc-switch__track { opacity: .5; }
.sc-switch__text { min-width: 0; }

/* ── Кнопки ───────────────────────────────────────────────────────────────── */
.sc-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font-family: inherit; font-size: 14px; font-weight: 600; line-height: 1;
  letter-spacing: -.1px;
  padding: 10px 18px;                       /* размер md — по умолчанию */
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer; text-decoration: none; white-space: nowrap;
  -webkit-user-select: none; user-select: none;
  transition: background .15s, border-color .15s, color .15s, box-shadow .15s, transform .08s;
}
.sc-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.sc-btn:disabled,
.sc-btn.is-disabled { opacity: .45; cursor: not-allowed; box-shadow: none; pointer-events: none; }

/* ── Состояние отправки: кнопка гаснет и говорит, что делает ─────────────────
   Ставит components.js по [data-sending] на форме (см. там же, зачем).

   ВНИМАНИЕ, ПАРНЫЙ БЛОК. Те же правила есть в style.css — для .btn-primary на
   экранах входа. Дублирование сознательное: /login и /trial грузят только
   tokens+style, каркас — tokens+components, общего файла у них нет, а тащить
   весь каркас на экран входа ради двух десятков строк дороже. Меняешь здесь —
   поменяй и там.
   Кольцо крутится только там, где движение разрешено (prefers-reduced-motion). */
.btn-spin {
  display: none;
  flex: none;
  width: 15px; height: 15px;
  margin-right: 9px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  opacity: .75;
  animation: btn-spin .7s linear infinite;
}
.is-loading > .btn-spin { display: inline-block; }
/* Своя иконка кнопки на время отправки уходит: рядом с кольцом две картинки
   читаются как рябь. Смысл несут кольцо и подпись. Хелпер icon() отдаёт
   <svg class="ic|ic-sm|ic-lg"> прямым потомком кнопки (см. src/icons.py). */
.sc-btn.is-loading > svg[class^="ic"] { display: none; }
/* .sc-btn:disabled по умолчанию уходит в opacity .45 и pointer-events:none —
   при отправке это читалось бы как поломка. Здесь ожидание, а не отказ. */
.sc-btn.is-loading:disabled,
.btn-primary.is-loading:disabled { opacity: .8; cursor: progress; pointer-events: none; }

/* ── Кнопка-ИКОНКА в ожидании: кольцо ВМЕСТО значка (GS-337) ────────────────
   Кнопки без подписи (ключик доступа в отчёте и в списках записей) не могут
   показать ожидание так же, как обычные: подписи, которая несла бы смысл,
   рядом нет, а кольцо сбоку от значка растянуло бы кнопку и сдвинуло соседние
   в панели. Поэтому кольцо ЗАМЕНЯЕТ иконку, занимая её место.

   Зачем вообще: форма окна собирается за миллисекунды, но соединение — нет.
   Владелец 10.09.2026 поймал задержку под VPN и попросил показать, что кнопка
   не зависла. Без VPN задержки нет вовсе, поэтому индикатор появляется не
   сразу — см. задержку показа в manage.js: мигание кольца на быстрой сети
   само по себе читалось бы как сбой.

   Размер и отступ берём у самой иконки, а не фиксированные: ключик в отчёте
   16px (на телефоне 19px), в списках — 14px (.ic-sm). Жёсткое значение
   ломало бы выравнивание в одном из мест. */
.tbtn.is-loading > .btn-spin,
.dtable__row-act.is-loading > .btn-spin { display: inline-block; margin: 0; width: 1em; height: 1em; }
.tbtn.is-loading > svg[class^="ic"],
.dtable__row-act.is-loading > svg[class^="ic"] { display: none; }
/* Курсор говорит то же, что кольцо. Нажатия НЕ гасим: повторное открытие того
   же окна безвредно (openModal переиспользует оверлей), а мёртвая кнопка под
   пальцем читается как поломка — ровно то, чего правка и избегает. */
.tbtn.is-loading,
.dtable__row-act.is-loading { cursor: progress; }
@keyframes btn-spin { to { transform: rotate(360deg); } }
/* Без движения кольцо остаётся статичным знаком «идёт отправка» — сам факт
   ожидания несёт текст кнопки, вращение только подкрепляет его. */
@media (prefers-reduced-motion: reduce) {
  .btn-spin { animation: none; }
}

/* размеры */
.sc-btn--sm { padding: 7px 12px; font-size: 13px; gap: 6px; border-radius: var(--radius-sm); }
.sc-btn--md { padding: 10px 18px; font-size: 14px; }
.sc-btn--block { width: 100%; }
.sc-btn--icon { padding: 9px; gap: 0; }
.sc-btn--icon.sc-btn--sm { padding: 7px; }

/* primary — золотая заливка, тёмный текст (канон Макса --c-gold-contrast).
   Hover СВЕТЛЕЕТ до яркого стопа --c-gold-mid (не темнеет в бронзу) — тёмный
   текст остаётся читаемым; уход в --c-gold-strong давал тёмный-на-тёмном. */
.sc-btn--primary { background: var(--c-gold); color: var(--c-gold-contrast); border-color: var(--c-gold); box-shadow: var(--elev-1); }
.sc-btn--primary:hover:not(:disabled) { background: var(--c-gold-mid); border-color: var(--c-gold-mid); color: var(--c-gold-contrast); box-shadow: var(--elev-2); }
.sc-btn--primary:active:not(:disabled) { transform: translateY(1px); box-shadow: none; }

/* ghost — поверхность + граница, золото на hover */
.sc-btn--ghost { background: var(--c-surface); color: var(--c-ink); border-color: var(--c-line-strong); }
.sc-btn--ghost:hover:not(:disabled) { border-color: var(--c-gold); color: var(--c-gold); }
.sc-btn--ghost:active:not(:disabled) { background: var(--c-surface-3); }

/* danger — деструктивное, контурное */
.sc-btn--danger { background: var(--c-surface); color: var(--c-danger); border-color: var(--c-danger-line); }
.sc-btn--danger:hover:not(:disabled) { background: var(--c-danger-bg); border-color: var(--c-danger); }
.sc-btn--danger:active:not(:disabled) { transform: translateY(1px); }

/* subtle / text — без фона и границы */
.sc-btn--subtle { background: transparent; color: var(--c-ink-3); border-color: transparent; box-shadow: none; font-weight: 500; }
.sc-btn--subtle:hover:not(:disabled) { color: var(--c-ink); background: var(--c-surface-3); }

/* ряд кнопок */
.sc-btn-row { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }

/* ── Инлайн-подсказка / ошибка / успех под полем ──────────────────────────── */
.sc-help {
  font-size: 13.5px; line-height: 1.45; color: var(--c-ink-3);
  display: flex; align-items: flex-start; gap: 5px;
}
.sc-help .ic, .sc-help .ic-sm { margin-top: 1px; flex: none; }
.sc-help--error   { color: var(--c-danger);  }
.sc-help--success { color: var(--c-success); }
.sc-help--info    { color: var(--c-info);    }
.sc-help[hidden]  { display: none; }

/* ── prefers-reduced-motion ───────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .sc-input, .sc-textarea, .sc-select__el, .sc-select::after,
  .sc-switch__track, .sc-switch__thumb, .sc-btn, .sc-input-action,
  .sc-inputwrap__lead { transition: none; }
  .sc-btn--primary:active:not(:disabled),
  .sc-btn--danger:active:not(:disabled) { transform: none; }
}

/* ═══════════ NO-GPU · облегчённые эффекты для software-рендеринга (GAA-20) ══════
   Инлайн-детектор в <head> шаблонов вешает .no-gpu на <html>, если WebGL-renderer =
   swiftshader/llvmpipe/software (браузер без GPU-ускорения). Без композитора
   backdrop-filter:blur считается на CPU покадрово и фризит появление подсказок/меню.
   Снимаем blur, компенсируем более плотным фоном — визуально слой всё так же
   выделяется, но без покадрового пересчёта размытия. С GPU блок не действует. */
.no-gpu .gx-scrim {
  -webkit-backdrop-filter: none; backdrop-filter: none;
  background: rgba(10,10,12,.55);          /* плотнее вместо блюра */
}
.no-gpu .sc-modal-overlay {
  -webkit-backdrop-filter: none; backdrop-filter: none;
  background: rgba(16,20,28,.68);
}
.no-gpu .app-topbar {
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
@media (max-width: 1200px) {
  .no-gpu .app-nav {
    -webkit-backdrop-filter: none; backdrop-filter: none;
    background: rgba(12,12,15,1);
  }
}
/* ── Форма доступа к встрече (.sc-manage) ──────────────────────────────────────
   Одна и та же разметка живёт на странице /r/{token}/manage и внутри popup'а из
   списка отчётов, поэтому стили лежат здесь, а не в <style> шаблона: иначе в
   модалке форма приезжала бы без оформления. Всё скоуплено под .sc-manage —
   классы вроде .box/.row/.btn слишком общие, чтобы пускать их в глобальную
   область, где у списков свои .btn и .t. */
.sc-manage .facts { display: flex; flex-wrap: wrap; gap: 8px 18px;
  color: var(--c-ink-3); font-size: 13px; margin-bottom: 20px; }
.sc-manage .facts b { color: var(--c-ink); font-weight: 600; }
.sc-manage .facts svg { vertical-align: -2px; }

.sc-manage label { display: block; font-size: 13px; font-weight: 700; margin-bottom: 6px; }
.sc-manage label .hint { font-weight: 400; color: var(--c-ink-4); font-size: 13px; }
.sc-manage input[type=text],
.sc-manage input[type=password],
.sc-manage input[type=date],
.sc-manage input[type=search],
.sc-manage select {
  /* Контур элемента управления — 3:1 по WCAG 1.4.11, см. --c-control-line. */
  width: 100%; border: 1px solid var(--c-control-line); border-radius: var(--radius-sm);
  background: var(--c-surface); color: var(--c-ink);
  padding: 10px 12px; font: inherit; font-size: 14px;
  /* border-box обязателен: без него width:100% складывается с padding 12px и
     рамкой, и поле вылезает за край карточки на 26px. На отдельной странице это
     не проявлялось — там box-sizing задан глобально в <style> шаблона, а в
     модалке форма приезжает без него, и переполнение видно на «Названии
     встречи» и на списке проектов. Дублируем правило здесь, чтобы разметка
     не зависела от того, в какой контейнер её вставили. */
  box-sizing: border-box;
  /* Список проектов длинный («Клиент / переговоры · доступ: client») — без
     max-width браузер растягивает <select> под самый длинный пункт, игнорируя
     width:100%. */
  max-inline-size: 100%;
}
/* Фокус — канонический --focus-ring (тонкая линия в 1px плюс мягкое свечение),
   а НЕ своя обводка. Раньше здесь стояло `outline: 1px solid` с отступом, и оно
   давало два дефекта сразу:

   1. Кольцо вдвое толще канона. Рядом с полем в 1px рамки обводка выглядела
      наложенной поверх вёрстки, а не подсветкой поля;
   2. Селектор `input:focus` без типа цеплял ЛЮБОЙ input внутри формы — включая
      чекбоксы согласования в глоссарии. Квадрат 16×16 получал ту же обводку в
      2px с отступом, то есть кольцо толщиной в восьмую часть самого элемента.

   Типы перечислены поимённо, тем же списком, что и оформление выше: чекбоксам и
   радио подсветка положена своя (см. .sc-manage input[type=checkbox] ниже) —
   у них нет ни рамки поля, ни его размеров.

   border-color не трогаем. Прежнее `transparent` гасило рамку под обводкой,
   чтобы не читались две линии; с кольцом в 1px рамка нужна — без неё поле в
   фокусе теряет контур и «схлопывается» на глазах при переходе по табу. */
.sc-manage input[type=text]:focus,
.sc-manage input[type=password]:focus,
.sc-manage input[type=date]:focus,
.sc-manage input[type=search]:focus,
.sc-manage select:focus {
  outline: none; border-color: var(--c-gold); box-shadow: var(--focus-ring);
}
/* Чекбоксы и радио: кольцо по форме самого элемента, без отступа наружу —
   иначе подсветка наезжает на соседнюю строку списка. */
.sc-manage input[type=checkbox]:focus-visible,
.sc-manage input[type=radio]:focus-visible {
  outline: none; box-shadow: var(--focus-ring);
}

/* Рамку/фон/скругление задаёт .sc-card (карточка UI Kit) — здесь только
   внутренние отступы и ритм между блоками, иначе перебили бы подсветку. */
.sc-manage .box { padding: 14px 16px; margin-bottom: 18px; }
/* flex-wrap: длинная метка состояния («наследует пароль проекта») на узком экране
   не влезает рядом с заголовком — уходит на свою строку целиком, а не давит
   заголовок в столбик и не вылезает за рамку карточки. */
.sc-manage .box-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 8px 10px; font-size: 14px; margin-bottom: 12px; }
.sc-manage .box-head b { display: inline-flex; align-items: center; gap: 7px; }

/* nowrap снят: узкая карточка режет бейдж по краю. Перенос по словам + max-width
   держат его внутри рамки. */
.sc-manage .status { font-size: 13px; font-weight: 600; padding: 3px 10px;
  border-radius: var(--radius-pill); max-inline-size: 100%; overflow-wrap: break-word; }
.sc-manage .status.on { background: var(--c-gold-bg); color: var(--c-gold); }
.sc-manage .status.off { background: var(--c-surface-3); color: var(--c-ink-4); }
.sc-manage .status.warn { background: var(--c-surface-3); color: var(--c-gold-strong); }

/* flex-wrap по умолчанию, а не по медиазапросу: ряд пароля — это поле + «глаз» +
   «Сгенерировать» + «Копировать пароль», и в 570px внутренней ширины модалки они
   не помещаются НИКОГДА, даже на широком мониторе. Прежний перенос включался по
   ширине ЭКРАНА (560px), то есть в popup'е не срабатывал вовсе, и кнопки вылезали
   за рамку карточки. Ширина экрана здесь ни при чём — значение имеет ширина
   контейнера, а её медиазапросом не измерить. */
.sc-manage .row, .sc-manage .linkrow { display: flex; flex-wrap: wrap; gap: 8px; align-items: stretch; }
.sc-manage .linkrow { margin-bottom: 8px; }

/* Выбор проекта для переноса (GS-185). Список приезжает по требованию, поэтому
   в блоке три состояния: только текущий проект и кнопка «Выбрать» → список с
   поиском → пояснение под ними. Сетка одна на все три: кнопка исчезает после
   загрузки, поиск и пояснение до неё скрыты атрибутом hidden. */
.sc-manage .mvpick { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
/* 🔴 hidden обязан скрывать. У .minibtn задан display:flex, а он ПЕРЕБИВАЕТ
   атрибут hidden (у того лишь display:none из таблицы браузера, и правило класса
   выигрывает). Кнопка «Выбрать проект» с выставленным hidden оставалась на
   экране — выглядела как сломанный, ничего не делающий орган управления. */
.sc-manage .mvpick [hidden] { display: none !important; }
.sc-manage .mvpick [data-move-select] { flex: 1 1 240px; }
/* Поиск занимает всю ширину под списком: он появляется вместе с ним, и ставить
   его в тот же ряд значило бы сжать оба до нечитаемости на телефоне. */
.sc-manage .mvpick__q { flex: 1 1 100%; }
.sc-manage .mvpick__note { flex: 1 1 100%; margin: 0; font-size: 12.5px;
  color: var(--c-ink-4); }

/* Копирование ссылки — ЗНАЧОК ВНУТРИ поля, а не кнопка под ним (решение
   владельца 16.08.2026). Подпись «Копировать ссылку» занимала отдельную строку
   во всю ширину карточки, хотя действие очевидно из значка и стоит ровно там,
   где лежит то, что копируют. На телефоне это освобождает целую строку в блоке,
   ради которого модалку чаще всего и открывают.
   position:relative на .linkrow, кнопка позиционируется в правом торце поля;
   у поля справа отступ под неё, чтобы адрес не уезжал под значок. */
.sc-manage .linkrow { position: relative; }
.sc-manage .linkrow input { padding-inline-end: 44px; }
.sc-manage .linkrow .minibtn[data-copy-link]{
  position: absolute; inset-inline-end: 4px; top: 50%; transform: translateY(-50%);
  width: 36px; min-inline-size: 36px; height: 36px; min-block-size: 36px;
  padding: 0; justify-content: center; gap: 0;
  border-color: transparent; background: transparent; color: var(--c-ink-2);
}
.sc-manage .linkrow .minibtn[data-copy-link] .lbl{
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.sc-manage .linkrow .minibtn[data-copy-link]:hover{ background: var(--c-surface-3); color: var(--c-gold); }
/* Зона нажатия 44px при значке 36: тач-цель растим псевдоэлементом, чтобы
   кнопка не распирала поле (тот же приём, что у .help-q). */
.sc-manage .linkrow .minibtn[data-copy-link]::after{
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
/* Копирование пароля — в поле, зеркало правила из report_manage.html (GS-167).
   Механика .linkrow: обёртка относительная, значок в правом торце, подпись
   только читалке. Правится ПАРОЙ со страницей — форму рисуют двое. */
.sc-manage .pwrow{ position: relative; display: flex; flex: 1 1 240px; min-width: 0; }
.sc-manage .pwrow input{ flex: 1 1 auto; min-width: 0; padding-inline-end: 44px; }
.sc-manage .pwrow .minibtn[data-copy-pw]{
  position: absolute; inset-inline-end: 4px; top: 50%;
  transform: translateY(-50%); width: 36px; height: 36px; padding: 0;
  justify-content: center; gap: 0;
  border-color: transparent; background: transparent; color: var(--c-ink-4);
}
.sc-manage .pwrow .minibtn[data-copy-pw]:hover{
  background: var(--c-surface-3); color: var(--c-gold); border-color: transparent;
}
.sc-manage .pwrow .minibtn[data-copy-pw][disabled]{ opacity: .45; cursor: default; }
.sc-manage .pwrow .minibtn[data-copy-pw] .lbl{
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.sc-manage .pwrow .minibtn[data-copy-pw]::after{
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
/* Поле забирает строку целиком и толкает кнопки на следующую, как только им тесно.
   Без basis поле сжималось бы до нечитаемых 40-50px, лишь бы кнопки влезли рядом. */
.sc-manage .row input, .sc-manage .linkrow input { flex: 1 1 240px; min-width: 0; }
.sc-manage .linkrow input { font-family: var(--font-mono); font-size: 13px; }

.sc-manage .minibtn { flex: 0 1 auto; display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--c-line); background: var(--c-surface); color: var(--c-ink);
  border-radius: var(--radius-sm); padding: 8px 12px; font: inherit; font-size: 13px;
  font-weight: 600; cursor: pointer; white-space: nowrap; min-inline-size: 0;
  /* Кнопка-иконка обязана остаться нажимаемой (44px — норма для пальца), но
     ширину ей задаёт содержимое: «Копировать ссылку» шире «глаза» вчетверо. */
  min-block-size: 38px;
  transition: color .14s ease, border-color .14s ease; }
.sc-manage .minibtn:hover { border-color: var(--c-gold); color: var(--c-gold); }
.sc-manage .minibtn[aria-pressed="true"] { border-color: var(--c-gold); color: var(--c-gold); }
/* Пока поле пустое, копировать нечего: без приглушения кнопка выглядит рабочей. */
.sc-manage .minibtn:disabled { opacity: .45; cursor: not-allowed; }
.sc-manage .minibtn:disabled:hover { border-color: var(--c-line); color: var(--c-ink); }

.sc-manage .note { color: var(--c-ink-4); font-size: 13px; margin-top: 8px; }
.sc-manage .note.warn { color: var(--c-gold-strong); }
.sc-manage .chk { display: flex; align-items: center; gap: 8px; font-size: 13px;
  font-weight: 600; margin-top: 10px; cursor: pointer; }
.sc-manage .chk input { width: auto; margin: 0; }

/* align-items:stretch, а не center: если одна кнопка переносится в две строки
   (узкий экран, «Открыть встречу»), при center соседняя остаётся ниже её ростом —
   в футере получались две кнопки разной высоты. */
.sc-manage .bar { display: flex; gap: 10px; align-items: stretch; margin-top: 22px; }
.sc-manage .btn { display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  border-radius: var(--radius-sm); padding: 10px 18px; font: inherit; font-size: 14px;
  font-weight: 700; line-height: 1.25; cursor: pointer; text-decoration: none; text-align: center; }
.sc-manage .btn.save { background: var(--c-gold); color: var(--c-gold-contrast);
  border: 1px solid var(--c-gold); }
.sc-manage .btn.ghost { background: transparent; color: var(--c-ink-3);
  border: 1px solid var(--c-line); }
.sc-manage .btn.ghost:hover { color: var(--c-gold); border-color: var(--c-gold); }

/* Итог действия внутри popup'а. На отдельной странице такой блок рисует обёртка
   и стилизует свой <style>; в модалке обёртки нет, поэтому оформление живёт
   здесь — иначе сообщение «не поместилось в контекст» выводилось бы голым
   текстом ровно там, где его важнее всего заметить. */
.sc-manage .gl-flash { display: flex; align-items: center; gap: 8px;
  background: var(--c-gold-bg); color: var(--c-gold-strong);
  border: 1px solid var(--c-gold); border-radius: var(--radius-sm);
  padding: 10px 14px; margin-bottom: 16px; font-size: 13px; overflow-wrap: anywhere; }

/* ── Название встречи в заголовке окна (12.08.2026) ────────────────────────────
   Заменило отдельный блок «Название встречи» в настройках: поле для одного
   значения должно быть одно. Карандаш появляется только при наличии JS — без
   скриптов вместо строки заголовка показывается обычное поле ввода.

   Блок — контейнер на два состояния (строка с текстом ↔ поле правки), и отступ
   снизу задаётся ЕМУ, а не состояниям: так при переключении режима содержимое
   ниже не подпрыгивает. */
.sc-manage .mgtitle { margin-block-end: 14px; }
.sc-manage .mgtitle[hidden] { display: none; }
.sc-manage .mgtitle__row { display: flex; align-items: center; gap: 8px; }
.sc-manage .mgtitle__row[hidden] { display: none; }
.sc-manage .mgtitle__text { margin: 0; font-size: 16px; font-weight: 700;
  line-height: 1.3; color: var(--c-ink); letter-spacing: -.1px;
  /* Длинное имя не должно распирать окно и выталкивать карандаш за край. */
  min-inline-size: 0; overflow-wrap: anywhere; }
/* Карандаш держится приглушённым, пока на него не навели: это правка «раз в жизни
   записи», и постоянно тянуть к себе взгляд ей незачем. Размер 32px — иконка
   мелкая, но зона нажатия должна оставаться пальцевой. */
.sc-manage .mgtitle__edit { flex: 0 0 auto; display: inline-flex;
  align-items: center; justify-content: center;
  inline-size: 32px; block-size: 32px; padding: 0;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  background: transparent; color: var(--c-ink-4); cursor: pointer;
  transition: color .14s ease, background .14s ease, border-color .14s ease; }
.sc-manage .mgtitle__edit:hover { color: var(--c-gold); background: var(--c-surface-3);
  border-color: var(--c-line); }
.sc-manage .mgtitle__edit:focus-visible { outline: 1px solid var(--c-gold);
  outline-offset: 1px; color: var(--c-gold); }
.sc-manage .mgtitle__edit[hidden] { display: none; }
/* Поле правки названия. Отступ снизу несёт родительский .mgtitle — здесь его
   быть не должно, иначе при открытии правки блок вырастает и всё под ним
   сдвигается. */
.sc-manage .mgnamefield { margin-block-end: 0; }
.sc-manage .mgnamefield[hidden] { display: none; }

/* ── Вкладки «Доступ» / «Настройки» (GOL-3xx, 12.08.2026) ──────────────────────
   Полоса приходит из шаблона с hidden и раскрывается скриптом: без JS панели
   остаются развёрнутыми подряд, и нерабочих кнопок на экране не возникает.
   Стиль — подчёркивание активной, а не заливка-«таблетка»: заливок в этой форме
   уже две (золотая «Сохранить» и бейджи статусов), третья спорила бы с ними за
   внимание там, где акцент должен быть один. */
.sc-manage .mgtabs { margin-bottom: 18px; }
.sc-manage .mgtabs[hidden] { display: none; }
.sc-manage .mgtabs__list { display: flex; gap: 4px;
  border-block-end: 1px solid var(--c-line); }
.sc-manage .mgtab { position: relative; display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 14px; margin-block-end: -1px;
  border: 0; border-block-end: 2px solid transparent; background: none;
  color: var(--c-ink-3); font: inherit; font-size: 14px; font-weight: 600;
  cursor: pointer; white-space: nowrap;
  transition: color .14s ease, border-color .14s ease; }
.sc-manage .mgtab:hover { color: var(--c-ink); }
.sc-manage .mgtab[aria-selected="true"] { color: var(--c-gold); border-block-end-color: var(--c-gold); }
.sc-manage .mgtab:focus-visible { outline: 1px solid var(--c-gold); outline-offset: -2px;
  border-radius: var(--radius-sm); }
/* Точка у «Настроек» — есть непрочитанные предложения в глоссарий. Значок, а не
   число: точное количество видно на самой вкладке, а здесь важен лишь факт «там
   что-то ждёт». Цветом одним не сообщаем — точка держится рядом со словом,
   которое и так читается. */
.sc-manage .mgtab__dot { inline-size: 6px; block-size: 6px; border-radius: 50%;
  background: var(--c-gold); flex: 0 0 auto; }
.sc-manage .mgpanel[hidden] { display: none; }
/* Панель — не рамка и не отступ: она лишь группирует блоки, а всё оформление
   несут сами .box внутри. Фокус ей нужен для доступности (переход с вкладки),
   но обводку рисуем только при клавиатурном фокусе. */
.sc-manage .mgpanel:focus { outline: none; }
/* Отступ внутрь, а не наружу: панель занимает всю ширину формы, и кольцо с
   наружным отступом уходило за край карточки — читалось как рамка вокруг
   модалки, а не как фокус на панели. */
.sc-manage .mgpanel:focus-visible { outline: 1px solid var(--c-gold); outline-offset: -2px;
  border-radius: var(--radius-sm); }

/* Ряд кнопок, переехавший в футер модалки (manage.js → liftBar). Отступ сверху
   там лишний — его даёт padding футера, а разделительную черту рисует граница. */
.sc-manage-foot .bar--infoot { margin-top: 0; inline-size: 100%; justify-content: flex-end; }
/* Порядок в футере обратный разметке: в потоке страницы «Сохранить» идёт первой
   (главное действие сверху), а в правом нижнем углу главное действие обязано быть
   крайним справа — иначе оно теряется между вторичной кнопкой и краем окна. */
.sc-manage-foot .bar--infoot .btn.save { order: 2; }
.sc-manage-foot .bar--infoot .btn.ghost { order: 1; }


   Свёрнутый <details> в той же карточке доступа. Кегль нигде не ниже 13px, а
   служебные подписи держатся на --c-ink-3/--c-ink-4 — оба токена рассчитаны на
   контраст ≥4.5 к фону карточки; брать что-то бледнее ради «неброскости» нельзя:
   это единственное место, где человек читает найденные термины. */
.sc-manage .gl-box { padding: 0; }
.sc-manage .gl-sum { display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 14px 16px; cursor: pointer; font-size: 14px;
  list-style: none; user-select: none; }
/* Стрелку-маркер убираем в обоих движках и рисуем свою (см. ::after): дефолтный
   треугольник Safari стоит вплотную к тексту и не наследует цвет. */
.sc-manage .gl-sum::-webkit-details-marker { display: none; }
.sc-manage .gl-sum b { display: inline-flex; align-items: center; gap: 7px; }
.sc-manage .gl-sum::after { content: "▾"; color: var(--c-ink-3); font-size: 12px;
  margin-inline-start: auto; transition: transform .15s ease; }
.sc-manage .gl-box[open] .gl-sum::after { transform: rotate(180deg); }
.sc-manage .gl-sum:hover b { color: var(--c-gold); }
.sc-manage .gl-sum:focus-visible { outline: 1px solid var(--c-gold); outline-offset: -2px; }
.sc-manage .gl-intro { margin: 0 16px 12px; }
.sc-manage .gl-list { list-style: none; margin: 0; padding: 0 16px; }
/* Строка предложения: слева выбор с термином, справа пояснение. На узком экране
   пояснение уходит под термин — обрезать его нельзя, там смысл находки. */
.sc-manage .gl-item { display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 4px 12px; padding: 9px 0; border-block-start: 1px solid var(--c-line); }
.sc-manage .gl-item:first-child { border-block-start: 0; }
.sc-manage .gl-pick { display: inline-flex; align-items: baseline; gap: 8px;
  margin: 0; font-weight: 400; cursor: pointer; }
.sc-manage .gl-pick input { inline-size: 16px; block-size: 16px; flex: 0 0 auto;
  accent-color: var(--c-gold); cursor: pointer; }
.sc-manage .gl-term { font-weight: 700; font-size: 14px; overflow-wrap: anywhere; }
.sc-manage .gl-meta { display: inline-flex; flex-wrap: wrap; align-items: baseline;
  gap: 4px 8px; margin-inline-start: auto; font-size: 13px; color: var(--c-ink-3); }
.sc-manage .gl-tag { font-size: 12px; font-weight: 600; padding: 2px 8px;
  border-radius: var(--radius-pill); background: var(--c-gold-bg); color: var(--c-gold); }
/* Частое слово — находка слабее разнобоя написаний, и метка у неё нейтральная:
   золотом выделяем только то, что почти наверняка стоит принять. */
.sc-manage .gl-tag-q { background: var(--c-surface-3); color: var(--c-ink-3); }
.sc-manage .gl-vars { color: var(--c-ink-4); overflow-wrap: anywhere; }
.sc-manage .gl-cnt { color: var(--c-ink-4); white-space: nowrap; }
.sc-manage .gl-bar { margin: 16px 16px 0; }
.sc-manage .gl-box form > .note { margin: 8px 16px 16px; }

/* ── Уплотнение формы управления (GS-147) ──────────────────────────────────
   Вкладка «Доступ» на телефоне занимала около трёх экранов: пароль и срок —
   двумя карточками подряд, именные ссылки — всегда развёрнутой формой, области
   — вертикальным списком в рамке fieldset. */

/* Срок жизни — вторая секция карточки ограничений: тонкий разделитель вместо
   отдельной рамки с шапкой. Статус секции — в её мини-шапке. */
.sc-manage .lim-sec { margin-top: 16px; padding-top: 14px;
  border-block-start: 1px solid var(--c-line); }
.sc-manage .lim-head { display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 8px 10px; font-size: 13px; margin-bottom: 10px; }
.sc-manage .lim-head b { display: inline-flex; align-items: center; gap: 7px; }

/* ── Состояние доступа встречи (GS-305) ─────────────────────────────────────
   Первая строка панели «Доступ»: кто видит эту встречу СЕЙЧАС. Не карточка и
   не блок — строка, потому что это справка о положении дел, а не орган
   управления: на неё смотрят, её не нажимают.

   Цвет НЕ единственный признак состояния — рядом значок и слово (чек-лист
   канона поведения). Поэтому у «открыта» и «закрыта» разные подписи, а не
   разные оттенки одной. */
.sc-manage .mgstate { display: flex; align-items: flex-start; gap: 9px;
  padding: 10px 14px; margin-bottom: 12px; font-size: 13.5px; line-height: 1.45;
  border: 1px solid var(--c-line); border-radius: var(--radius-sm);
  background: var(--c-surface-2); }
.sc-manage .mgstate__icon { display: inline-flex; flex: none; margin-top: 1px;
  color: var(--c-ink-3); }
/* Длинное название организации и «выдано N именных ссылок» обязаны переноситься,
   а не растягивать окно (чек-лист: длинные строки не ломают сетку). */
.sc-manage .mgstate__text { min-inline-size: 0; overflow-wrap: anywhere; }
.sc-manage .mgstate__extra { color: var(--c-ink-3); }
/* «Настроено в проекте «Имя»» — отдельной строкой и мельче (GS-328): это ответ
   на вопрос «где поменять», а не часть самого состояния. Тот же приём, что у
   почты под именем организации в соседней колонке: подчинённое — ниже и тише.

   display:block, а не перенос пробелом: иначе при коротком состоянии строка
   прилипала бы к нему хвостом и читалась как продолжение фразы. */
.sc-manage .mgstate__where { display: block; margin-top: 3px;
  font-size: 12.5px; color: var(--c-ink-3); }
/* Ссылка на проект — обычная ссылка продукта, но подчёркнутая всегда: цвет
   здесь приглушён до --c-ink-3, и без подчёркивания она перестала бы читаться
   как кликабельная (канон: не полагаться на один цветовой признак). */
.sc-manage .mgstate__where a { color: inherit; text-decoration: underline;
  text-underline-offset: 2px; }
.sc-manage .mgstate__where a:hover { color: var(--c-ink); }
/* 🔴 ТАЧ-ЦЕЛЬ ПОД ПАЛЕЦ (канон: 48px, граница по СПОСОБУ ВВОДА, не по ширине).
   Замер на 390px: имя проекта — ссылка высотой 15px, промахнуться легче, чем
   попасть. Наращиваем вертикальные отступы только там, где ввод пальцем;
   на мыши курсор точнее, и раздувать строку незачем.

   inline-block обязателен: у строчного элемента padding не увеличивает
   занимаемую высоту, и цель осталась бы прежней при «исправленном» CSS —
   ровно тот случай, когда правка выглядит сделанной, а замер не меняется. */
@media (pointer: coarse) {
  .sc-manage .mgstate__where a { display: inline-block; padding: 15px 4px;
    margin: -15px -4px; }
}
/* Открытая наружу встреча выделяется золотом — тем же акцентом, что и остальные
   «требует внимания» в этом окне. Красного здесь нет намеренно: открытая по
   ссылке встреча — законное состояние, а не ошибка.

   🔴 ЗНАЧОК КРАСИМ --c-gold-strong, А НЕ --c-gold. Замер 07.09.2026: на светлой
   теме --c-gold даёт 2.05:1 против подложки — ниже 3:1, которые канон требует
   от графического элемента. --c-gold-strong объявлен во всех трёх темах именно
   как «золото, годное текстом»: 4.9 на светлой, 8.6 и 8.8 на тёмных.
   Рамке 2.05 достаточно — она чисто декоративная, состояние несут значок и
   слово. */
.sc-manage .mgstate--link { border-color: var(--c-gold); }
.sc-manage .mgstate--link .mgstate__icon { color: var(--c-gold-strong); }
.sc-manage .mgstate--expired .mgstate__icon,
.sc-manage .mgstate--locked .mgstate__icon { color: var(--c-gold-strong); }

/* ── Настройки выдачи — второй уровень (GS-308) ─────────────────────────────
   Строка-раскрывашка по образцу «Дополнительных параметров» в диалоге общего
   доступа Synology: сама по себе неброская, потому что нужна меньшинству, но
   на виду и с точным обещанием, что за ней лежит.
   Тач-цель 44px: строка кликабельна целиком (канон П8). */
.sc-manage .sh-adv { margin-block-end: 12px; }
.sc-manage .sh-adv__sum { display: flex; align-items: center; gap: 8px;
  min-block-size: 44px; cursor: pointer; list-style: none;
  font-size: 13px; color: var(--c-ink-2); user-select: none; }
.sc-manage .sh-adv__sum::-webkit-details-marker { display: none; }
.sc-manage .sh-adv__sum::after { content: "▾"; color: var(--c-ink-3);
  font-size: 12px; transition: transform .15s ease; }
.sc-manage .sh-adv[open] .sh-adv__sum::after { transform: rotate(180deg); }
.sc-manage .sh-adv__sum:hover { color: var(--c-gold); }
.sc-manage .sh-adv__sum:focus-visible { outline: 1px solid var(--c-gold);
  outline-offset: 2px; border-radius: var(--radius-sm); }
.sc-manage .sh-adv__body { padding-block-start: 4px; }

/* Что уйдёт по нажатию, если настройки не трогали. Стоит между настройками и
   кнопкой — там, где это читают ПЕРЕД нажатием, а не узнают после.

   🔴 ПРИ РАСКРЫТЫХ НАСТРОЙКАХ СТРОКА ПРЯЧЕТСЯ. Иначе она врёт ровно тому, кто
   только что отметил «расшифровку»: обещание «откроет только итоги» стоит под
   его собственным выбором и противоречит ему. Обещание про умолчание имеет
   смысл, пока умолчанием и пользуются. Замечено на скриншоте 07.09.2026. */
.sc-manage .sh-default { font-size: 12.5px; color: var(--c-ink-3);
  line-height: 1.45; margin-block-end: 10px; }
.sc-manage .sh-adv[open] + .sh-default { display: none; }

/* «Выдать ссылку» — ГЛАВНОЕ действие блока, и тач-цель у него по канону: 44px.
   Общий .btn в этом окне даёт 40px, чего хватает вторичным кнопкам, но не
   основному действию, которое жмут пальцем в спешке (замер 07.09.2026). */
.sc-manage .sh-new .bar .btn.save { min-block-size: 44px; }
/* На телефоне действие занимает строку целиком: так до него достаёт большой
   палец, и оно не соседствует вплотную с «Отозвать» соседней ссылки. */
@media (max-width: 480px) {
  .sc-manage .sh-new .bar .btn.save { inline-size: 100%; }
}

/* Именные ссылки в сворачиваемой карточке. Каркас наследует глоссарий
   (gl-box/gl-sum: padding:0 у карточки, summary-строка с шевроном) — здесь
   только отступы содержимого. */
.sc-manage .sh-box .sh-list { margin: 0; padding: 0 16px; list-style: none; }
.sc-manage .sh-item { padding: 10px 0; border-block-start: 1px solid var(--c-line); }
.sc-manage .sh-item:first-child { border-block-start: 0; }
.sc-manage .sh-meta { display: flex; flex-wrap: wrap; gap: 3px 14px;
  font-size: 12.5px; color: var(--c-ink-3); margin-top: 3px; }
.sc-manage .sh-revoke { margin-top: 8px; }
.sc-manage .sh-box .sh-new { padding: 0 16px 14px; }
.sc-manage .sh-box .sh-new .bar { margin-top: 14px; }

/* Второй уровень «+ Выдать ссылку» — когда список уже есть и форма под ним
   была бы постоянным хвостом. Summary — строка-действие, а не кнопка: она
   открывает форму здесь же, а не отправляет. */
.sc-manage .sh-new-wrap { margin: 4px 16px 14px; }
.sc-manage .sh-new-wrap > summary { display: inline-flex; align-items: center;
  gap: 7px; min-block-size: 44px; cursor: pointer; list-style: none;
  color: var(--c-gold-strong); font-weight: 700; font-size: 13.5px;
  -webkit-tap-highlight-color: transparent; }
.sc-manage .sh-new-wrap > summary::-webkit-details-marker { display: none; }
.sc-manage .sh-new-wrap > summary:hover { color: var(--c-gold); }
.sc-manage .sh-new-wrap > summary:focus-visible { outline: 1px solid var(--c-gold);
  outline-offset: 2px; }
.sc-manage .sh-new-wrap .sh-new { padding: 4px 0 0; }

/* Области именной ссылки — чипы в строку вместо вертикального списка в рамке.
   Чекбокс остаётся настоящим и видимым: отметку сообщает галочка, заливка —
   только подсветка (цвет не единственный признак состояния). */
.sc-manage .sh-scopes-pick { border: 0; margin: 0 0 12px; padding: 0; min-inline-size: 0; }
.sc-manage .sh-scopes-pick legend { font-size: 13px; font-weight: 700;
  margin-bottom: 8px; padding: 0; }
.sc-manage .sh-scopes-pick legend .hint { font-weight: 400; color: var(--c-ink-4); }
.sc-manage .sh-chips { display: flex; flex-wrap: wrap; gap: 8px; }
/* .sc-manage label даёт display:block и нижний отступ — чипу нужен
   inline-flex без него. */
.sc-manage .chip { display: inline-flex; align-items: center; gap: 8px;
  min-block-size: 40px; margin: 0; padding: 6px 14px;
  border: 1px solid var(--c-line); border-radius: var(--radius-sm);
  background: var(--c-surface); font-size: 13px; font-weight: 600; cursor: pointer;
  -webkit-tap-highlight-color: transparent; }
.sc-manage .chip input { inline-size: 16px; block-size: 16px; margin: 0;
  accent-color: var(--c-gold); cursor: pointer; }
.sc-manage .chip:has(input:checked) { border-color: var(--c-gold);
  background: var(--c-gold-bg); color: var(--c-gold-strong); }
.sc-manage .chip:focus-within { outline: 1px solid var(--c-gold); outline-offset: 1px; }

/* Состояние загрузки формы в popup'е */
.sc-manage-load { padding: 26px 4px; text-align: center; color: var(--c-ink-3); font-size: 14px; }
.sc-manage-load a { color: var(--c-gold); }

/* ── Название встречи, переехавшее в шапку окна (GS-174) ───────────────────────
   Переносит узел manage.js → liftTitle; здесь только оформление на новом месте.

   Шапка была служебной полосой: подпись «Управление встречей» на телефоне
   пряталась как лишняя, но сама полоса оставалась — пустой, высотой в палец, с
   крестиком, уехавшим в левый угол за неимением распорки. Название в шапке
   делает полосу содержательной: одна строка вместо двух, крестик прижат вправо.

   Блок обязан ужиматься (min-inline-size: 0) — иначе длинное имя распирает
   шапку и выталкивает крестик за край окна. */
.sc-modal-head .mgtitle--inhead { flex: 1 1 auto; min-inline-size: 0; margin-block-end: 0; }
/* Имя в шапке не переносится на третью строку: две — предел, дальше многоточие.
   Шапка не должна расти вместе с длиной названия, иначе она снова съест экран,
   ради чего всё и затевалось. Полное имя доступно в поле правки по карандашу. */
.sc-modal-head .mgtitle--inhead .mgtitle__text {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Поле правки в шапке занимает её целиком: правка идёт там, где стоит имя. */
.sc-modal-head .mgtitle--inhead .mgnamefield .sc-label { display: none; }
.sc-modal-head .mgtitle--inhead .mgnamefield .sc-input { inline-size: 100%; }

/* Служебная подпись «Управление встречей» СКРЫТА ВИЗУАЛЬНО НА ВСЕХ ШИРИНАХ
   (GS-174; на телефоне так было с 16.08.2026, теперь везде): заголовком служит
   само название встречи, стоящее теперь в этой же шапке, и две подписи подряд
   человек читает как ошибку вёрстки.

   🔴 УБИРАЕМ ИЗ ПОКАЗА, НО НЕ ИЗ РАЗМЕТКИ: на этом узле висит aria-labelledby
   окна, и удаление оставило бы модалку без доступного имени. Название встречи
   его не заменяет — оно приходит фрагментом позже и в разметке окна его нет. */
.sc-modal:has(.sc-manage) .sc-modal-title {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

@media (max-width: 560px) {
  /* flex-wrap уехал в базовое правило .row/.linkrow — он нужен не на узком
     экране, а в узком контейнере (модалка на широком мониторе). Здесь остаётся
     только то, что действительно зависит от размера экрана. */
  .sc-manage .minibtn { padding: 9px 12px; }
  /* Внизу остаётся ОДНО действие — «Сохранить» (решение владельца 16.08.2026).
     «Открыть встречу» уводит со страницы, не сохранив правок, и в паре с
     сохранением читалась как равнозначная альтернатива, хотя это выход, а не
     действие: две кнопки во всю ширину занимали нижнюю четверть экрана.
     Ссылка на встречу лежит выше — в поле, которое человек и пришёл копировать. */
  .sc-manage .bar .btn { flex: 1 1 0; min-inline-size: 0; padding-inline: 12px; }
  .sc-manage .bar .btn.ghost { display: none; }
  .sc-manage .bar .btn.save { flex: 1 1 100%; }
  /* Паспорт встречи — справка, а не то, ради чего открыли модалку. */
  .sc-manage .facts--desk { display: none; }
  /* Пальцевая зона крестика (GS-174). 28px хватало курсору, но не большому
     пальцу, а закрытие окна — самое частое действие на телефоне. */
  .sc-modal:has(.sc-manage) .sc-modal-x{ inline-size: 44px; block-size: 44px; }
  /* Вкладки на телефоне: подписи короткие, но вместе с иконками могут не влезть —
     разрешаем полосе прокручиваться вбок, а не ломаться в две строки. */
  .sc-manage .mgtabs__list { overflow-x: auto; scrollbar-width: none; }
  .sc-manage .mgtabs__list::-webkit-scrollbar { display: none; }
}

/* ── Карточки с подсветкой (перенос из UI Kit, eco-components.css v4.176) ──────
   Эталон: goldjaxe-ui-kit/src/css/eco-components.css, класс .service-card.
   По умолчанию карточка НЕ выделена; на hover — сдвиг на 2px влево-вверх и
   ЖЁСТКАЯ тень со сдвигом 8px 8px 0 (blur=0, эталон goldjaxe.org). Цвет тени
   задаёт модификатор .card-* через триплет --card-r/g/b: rgba() нужен именно
   три числа, поэтому цвет хранится числами, а не готовым значением.
   Перенесено как есть, без правок значений — иначе карточки в scribe разъедутся
   с остальной экосистемой. Из зависимостей эталона подменены только две:
   var(--bg-concrete) → var(--c-surface-2), var(--r-sm) → var(--radius-sm). */
.sc-card {
  position: relative;
  border: 1px solid var(--c-line);
  background: var(--c-surface-2);
  border-radius: var(--radius-sm);
  transition: transform .5s ease, box-shadow .5s ease, border-color .5s ease;
  --card-r: 235; --card-g: 197; --card-b: 84;      /* gold — brand default */
}
.sc-card:hover {
  transform: translate(-2px, -2px);
  border-color: rgba(var(--card-r), var(--card-g), var(--card-b), .55);
  box-shadow: 8px 8px 0 rgba(var(--card-r), var(--card-g), var(--card-b), .30);
}
/* Постоянная бренд-обводка (акцентный блок), брутал-тень остаётся на hover. */
.sc-card.is-featured {
  border-color: rgba(var(--card-r), var(--card-g), var(--card-b), .70);
  box-shadow: 0 0 0 1px rgba(var(--card-r), var(--card-g), var(--card-b), .30);
}
.sc-card.is-featured:hover {
  border-color: rgba(var(--card-r), var(--card-g), var(--card-b), .85);
  box-shadow: 0 0 0 1px rgba(var(--card-r), var(--card-g), var(--card-b), .30),
              8px 8px 0 rgba(var(--card-r), var(--card-g), var(--card-b), .30);
}
/* Блоки ФОРМЫ доступа (.box) переиспользуют оформление карточки витрины, но
   карточками не являются: они ничего не открывают, внутри поля и кнопки. Сдвиг на
   -2px с тенью 8px тут читался как поломка — блок уползал из-под курсора, пока
   человек вёл его к полю ввода. Гасим движение, оставляя подсветку рамки.

   Гашение отдельным правилом, а не правкой .sc-card: этот класс — часть общего
   набора компонентов, который приходит из ui-kit, и его определение перезапишется
   при обновлении. Привязка к .box, а не к .sc-manage — та же форма рендерится
   и в модалке, где контейнера .sc-manage нет. */
.box.sc-card { transition: border-color .2s ease; }
.box.sc-card:hover { transform: none; box-shadow: none; }
.box.sc-card.is-featured:hover {
  box-shadow: 0 0 0 1px rgba(var(--card-r), var(--card-g), var(--card-b), .30);
}

.card-gold    { --card-r: 235; --card-g: 197; --card-b: 84;  }  /* золото · brand default */
.card-red     { --card-r: 158; --card-g: 68;  --card-b: 68;  }  /* crimson · enterprise/vault */
.card-purple  { --card-r: 162; --card-g: 120; --card-b: 196; }  /* аметист · vision/VIP */
.card-blue    { --card-r: 69;  --card-g: 115; --card-b: 161; }  /* сталь · нейтральный */
.card-green   { --card-r: 34;  --card-g: 197; --card-b: 94;  }  /* изумруд · success */
.card-neutral { --card-r: 140; --card-g: 140; --card-b: 140; }  /* серый · без акцента */

/* На светлой теме тень плотнее: на белом фоне 0.30 теряется (как в эталоне). */
:root[data-theme="light"] .sc-card:hover,
:root[data-theme="light"] .sc-card.is-featured:hover {
  box-shadow: 8px 8px 0 rgba(var(--card-r), var(--card-g), var(--card-b), .40);
}
/* Повтор гашения для светлой темы: правило выше специфичнее и ниже по каскаду,
   без этого блоки формы получали тень обратно. */
:root[data-theme="light"] .box.sc-card:hover { box-shadow: none; }
:root[data-theme="light"] .box.sc-card.is-featured:hover {
  box-shadow: 0 0 0 1px rgba(var(--card-r), var(--card-g), var(--card-b), .30);
}

/* Сдвиг карточки не должен выпихивать соседей и резаться краем прокрутки. */
@media (prefers-reduced-motion: reduce) {
  .sc-card, .sc-card:hover { transition: none; transform: none; }
}

/* ═══════════════ app-side · боковая навигация ═══════════════ */
/* ═══════════════════════════════════════════════════════════════════════════
   Вторая колонка каркаса: разделы внутри страницы (в отличие от .app-nav в
   шапке — та про разделы сервиса). Комментарий в шапке файла обещал sidebar
   с самого начала, но его не было: страницы обходились одной колонкой.

   На телефоне колонка НЕ уходит в off-canvas: off-canvas уже занят главным
   меню (бургер), второй такой же ящик пользователь не найдёт. Вместо этого —
   горизонтальная полоса с прокруткой над содержимым: активный пункт виден
   сразу, остальные доезжают пальцем.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Обёртка «боковая колонка + рабочая зона». Без .has-side ведёт себя как
   обычный блок и вёрстку одноколоночных страниц не трогает. */
.app-body{
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  min-width: 0;
}
.app-shell.has-side .app-body{
  display: grid;
  /* 232px, а не 220: при 220 пункт с замком («Отчёты по компании» + значок)
     обрезался многоточием — подпись выключенного раздела и так требует
     объяснения, а обрезанная требует вдвое больше. */
  grid-template-columns: 232px minmax(0, 1fr);
  align-items: stretch;   /* колонка тянется на всю высоту, а не по содержимому */
}
/* min-width:0 обязателен: иначе широкая таблица в <main> распирает грид-колонку
   и вся страница получает горизонтальную прокрутку. */
.app-shell.has-side .app-main{ min-width: 0; }

.app-side{
  min-width: 0;
  padding: var(--sp-5) var(--sp-3) var(--sp-8);
  border-right: 1px solid var(--c-line);
  background: var(--c-surface);
  align-self: stretch;
}

.app-side__group{ margin-bottom: var(--sp-5); }
.app-side__group:last-child{ margin-bottom: 0; }

/* Кегль 13px — пол шкалы холдинга для ТЕКСТА (12px канон оставляет только
   глифам в кружках: «?», шевроны). Было 11px: капс-подпись группы читалась как
   мелкий шум, а на боковой панели это единственный ориентир «что за раздел».
   Трекинг ужат .16 → .12em: разрядка на большем кегле съедала бы ширину
   колонки 232px, ради которой подписи и держат в одну строку. */
.app-side__title{
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--c-ink-3);
  margin: 0 0 var(--sp-2);
  padding: 0 var(--sp-3);
}

/* Пункт: иконка + текст. Зона нажатия 44px — правило доступности, а не
   украшение: на телефоне полоса прокручивается пальцем, и промах по пункту
   уводит на чужой раздел. */
.app-side__link{
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 44px;
  padding: 0 var(--sp-3);
  position: relative;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--c-ink-2);
  text-decoration: none;
  border-radius: var(--radius-xs);
  transition: color .15s ease, background .15s ease;
}
.app-side__link svg{ width: 16px; height: 16px; flex: none; }
.app-side__link > span{ min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-side__link:hover{ color: var(--c-ink); background: var(--c-surface-2); }
.app-side__link:focus-visible{ outline: none; box-shadow: var(--focus-ring); }

/* Активный — золотая метка слева. Метка, а не заливка: заливкой раздел спорит
   с активным пунктом в шапке, а он в иерархии выше. */
.app-side__link.is-active{
  color: var(--c-gold-strong);
  background: var(--c-gold-bg);
}
.app-side__link.is-active::before{
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: 3px; height: 22px;
  transform: translateY(-50%);
  background: var(--c-gold);
}

/* Выключенный пункт (пробный режим) — <span>, а не <a>: ссылка, которая никуда
   не ведёт, обманывает и клавиатуру, и скринридер. Почему выключен — объясняет
   [data-tip] (тултип .tip-pop). */
.app-side__link.is-disabled{
  color: var(--c-ink-4);
  cursor: not-allowed;
  background: none;
}
.app-side__link.is-disabled:hover{ color: var(--c-ink-4); background: none; }
.app-side__lock{
  margin-left: auto;
  display: inline-flex;
  flex: none;
  color: var(--c-ink-4);
}
.app-side__lock svg{ width: 13px; height: 13px; }

/* Кегль 12px — пол шкалы; счётчик набран цифрами, поэтому 12 ему хватает, а
   подписи-словам рядом дано 13. Цвет поднят с --c-ink-3 до --c-ink-2: на
   подложке --c-surface-3 приглушённый давал 4.41 при норме 4.5 (замер WCAG 2.1
   с учётом прозрачности), на карточке он же даёт 5.69 — счётчик единственный
   живёт на светлой плитке, и общий токен для него оказался пограничным. */
.app-side__badge{
  margin-left: auto;
  flex: none;
  min-width: 20px;
  padding: 1px 6px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  text-align: center;
  color: var(--c-ink-2);
  background: var(--c-surface-3);
  border-radius: var(--radius-sm);
}
.app-side__link.is-active .app-side__badge{
  color: var(--c-gold-contrast);
  background: var(--c-gold);
}
/* Замок и счётчик вместе: счётчик уже занял margin-left:auto, замку остаётся
   обычный отступ, иначе они разъезжаются по краям строки. */
.app-side__badge + .app-side__lock{ margin-left: var(--sp-2); }

/* ── Телефон и планшет: колонка → горизонтальная полоса ────────────────────── */
@media (max-width: 900px){
  .app-shell.has-side .app-body{ display: flex; flex-direction: column; }

  /* 🔴 Не полоса с прокруткой, а ВЫПАДАЮЩИЙ СПИСОК (решение владельца
     16.08.2026). Полоса вмещала три пункта из девяти, остальные доезжали
     пальцем — и прокручивать её приходилось заново после каждого перехода.
     Вдобавок из неё не было видно, где ты: активный пункт мог стоять за краем.
     Теперь кнопка называет текущий раздел, а список открывается на месте —
     со всеми девятью пунктами и заголовками групп, которые в полосе прятались
     (в строку они не помещались). */
  .app-sidewrap{
    border-bottom: 1px solid var(--c-line);
    background: var(--c-surface);
  }
  .app-sidewrap__btn{
    display: flex; align-items: center; gap: var(--sp-2);
    min-block-size: 48px; padding: 0 var(--sp-4);
    font-family: var(--font-mono); font-size: 13px; font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase;
    color: var(--c-ink); cursor: pointer; list-style: none;
  }
  .app-sidewrap__btn::-webkit-details-marker{ display: none; }
  .app-sidewrap__cur{ flex: 1 1 auto; min-inline-size: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .app-sidewrap__chev{ flex: none; color: var(--c-ink-3);
    transition: transform .18s ease; }
  .app-sidewrap[open] .app-sidewrap__chev{ transform: rotate(180deg); }
  .app-sidewrap__btn:focus-visible{ box-shadow: var(--focus-ring); outline: none; }

  /* Раскрытый список — обычная колонка, как на десктопе: те же пункты, те же
     заголовки групп. Полоса и её горизонтальная прокрутка ушли целиком. */
  .app-side{
    display: block;
    padding: 0 var(--sp-3) var(--sp-3);
    border-right: 0;
    border-bottom: 0;
    max-block-size: 60vh;          /* длинный список не выталкивает содержимое */
    overflow-y: auto;
  }
  .app-side__group{ margin-bottom: var(--sp-3); }
  .app-side__link{ min-block-size: 44px; }   /* норма зоны нажатия */
}

/* Десктоп: кнопки нет, список стоит колонкой всегда.
   🔴 Раскрывает меню НЕ этот блок, а сторож в _admin_side.html. С 16 по
   18.08.2026 расчёт был на `display: contents` — и меню на десктопе пропало:
   колонка 232px оставалась (место в гриде занято), а пунктов в ней не было.
   Свёрнутый <details> прячет содержимое на уровне отрисовки, и стилями это не
   перебить: замером проверены и `display: block`, и `content-visibility` на
   .app-side — innerText оставался пуст. Рычаг один — атрибут `open`.
   🔴 Границу 901px править ПАРОЙ с matchMedia в _admin_side.html: разъедутся —
   на промежуточной ширине не будет ни кнопки, ни списка.

   `display: contents` при этом всё равно нужен: без него <details> сам занял бы
   ячейку грида, а .app-side поехал бы внутрь неё. */
@media (min-width: 901px){
  .app-sidewrap{ display: contents; }
  .app-sidewrap__btn{ display: none; }
}

@media (prefers-reduced-motion: reduce){
  .app-side__link{ transition: none; }
}

/* ═══════════════ sc-acc · аккордеон ═══════════════ */
/* ═══════════════════════════════════════════════════════════════════════════
   Обёртка над нативным <details> — без JS. Нативный элемент уже умеет всё, что
   нужно (клавиатура, состояние, поиск по странице в Chrome); самописный
   аккордеон на JS повторял бы это хуже.

   Разметка:
     <details class="sc-acc"><summary class="sc-acc__sum">Заголовок</summary>
       <div class="sc-acc__body">…</div></details>
   ═══════════════════════════════════════════════════════════════════════════ */
.sc-acc{
  border: 1px solid var(--c-line);
  border-radius: var(--radius-sm);
  background: var(--c-surface);
  margin-bottom: var(--sp-3);
}
.sc-acc[open]{ border-color: var(--c-line-strong); }

.sc-acc__sum{
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 44px;
  padding: var(--sp-2) var(--sp-4);
  font-size: 14px;
  font-weight: 600;
  color: var(--c-ink);
  cursor: pointer;
  list-style: none;                  /* убираем нативный треугольник */
  user-select: none;
}
.sc-acc__sum::-webkit-details-marker{ display: none; }
.sc-acc__sum:hover{ color: var(--c-gold-strong); }
.sc-acc__sum:focus-visible{ outline: none; box-shadow: var(--focus-ring); }

/* Стрелка — на псевдоэлементе, чтобы разметка оставалась чистой. */
.sc-acc__sum::after{
  content: "";
  margin-left: auto;
  flex: none;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--c-ink-3);
  border-bottom: 2px solid var(--c-ink-3);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .18s ease;
}
.sc-acc[open] > .sc-acc__sum::after{
  transform: rotate(-135deg) translate(-2px, -2px);
}
.sc-acc[open] > .sc-acc__sum{ border-bottom: 1px solid var(--c-line); }

.sc-acc__body{
  padding: var(--sp-4);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--c-ink-2);
}

@media (prefers-reduced-motion: reduce){
  .sc-acc__sum::after{ transition: none; }
}

/* ═══════════ Приветственные подсказки первого захода (GOL-353) ═══════════════
   Показываются один раз, поверх скрима .gx-scrim (z-index 999). Сама подсказка
   и подсвеченный элемент — над ним.

   Блюр здесь уместен, в отличие от hover-подсказок [data-tip]: там правило
   «подсказка поясняет страницу, а не заменяет её» — её человек вызвал сам.
   Здесь говорит продукт, и затемнение показывает, о каком месте экрана речь. */
.onb-pop {
  position: fixed; z-index: 1001;
  max-width: 340px; min-width: 260px;
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-2);
  padding: 14px 16px 12px;
}
.onb-text {
  font-size: 14px; line-height: 1.55; color: var(--c-ink-2);
  white-space: pre-line;          /* многострочный data-onb — списком, не абзацем */
}
.onb-row {
  display: flex; align-items: center; gap: 10px;
  margin-top: 12px; padding-top: 11px;
  border-top: 1px solid var(--c-line);
}
.onb-count { font-size: 12.5px; color: var(--c-ink-3); margin-right: auto; }
.onb-skip, .onb-next {
  font: inherit; font-size: 13.5px; cursor: pointer;
  padding: 7px 14px; border-radius: var(--radius-sm);
  min-height: 34px;               /* тач-цель: строка ниже добивает до 44 на телефоне */
  border: 1px solid transparent;
  transition: background .15s, color .15s, border-color .15s;
}
.onb-skip { background: none; border-color: var(--c-line); color: var(--c-ink-3); }
.onb-skip:hover { color: var(--c-ink-2); border-color: var(--c-ink-3); }
/* --c-gold-contrast, а не свой цвет: тот же токен, что у .sc-btn--primary. Он
   меняется вместе с темой, а вписанное сюда значение осталось бы тёмным на
   тёмном при переключении на Ночь. */
.onb-next { background: var(--c-gold); color: var(--c-gold-contrast);
  border-color: var(--c-gold); font-weight: 600; }
.onb-next:hover { filter: brightness(1.06); }
.onb-skip:focus-visible, .onb-next:focus-visible { box-shadow: var(--focus-ring); outline: none; }

/* Подсвеченный элемент поднимается НАД скримом — ради этого весь приём и нужен:
   человек видит, о чём речь, а не читает описание вслепую.

   Подложка обязательна. Без неё элемент на тёмном фоне (пункт шапки) остаётся
   тёмным и «поднятым» его не видно: скрим вокруг такого же цвета. Проверено
   в браузере — на снимке пункт «Организация» читался как случайное пятно.
   Поэтому под элемент кладётся фон страницы, а обводка идёт золотом. */
.onb-spot {
  position: relative; z-index: 1000;
  border-radius: var(--radius-sm);
  background: var(--c-surface);
  box-shadow: 0 0 0 3px var(--c-gold-bg), 0 0 0 2px var(--c-gold),
              0 6px 22px rgba(0,0,0,.28);
}
/* Ссылки шапки — светлый текст по тёмному фону: подложка страницы сделала бы их
   нечитаемыми. Им — золотая заливка шапки: элемент читается как выделенный, а
   текст остаётся светлым. Прозрачного фона мало: тёмный пункт на затемнённом
   фоне выглядит случайным пятном, а не тем, о чём говорит подсказка. */
.app-nav .onb-spot, .app-topbar .onb-spot {
  background: var(--hdr-gold-bg, rgba(201,163,50,.16));
}
@media (pointer: coarse) {
  .onb-skip, .onb-next { min-height: 44px; padding: 11px 16px; }
}
@media (max-width: 767px) {
  .onb-pop { max-width: calc(100vw - 24px); min-width: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .onb-skip, .onb-next { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   ПЕРЕХОД МЕЖДУ СТРАНИЦАМИ БЕЗ МИГАНИЯ НИЖНЕЙ ПАНЕЛИ (GS-166)

   Переход по нижнему меню — обычная браузерная навигация (полная перезагрузка
   HTML): SPA-перехват кликов рассматривали и отклонили — три целевые страницы
   (/my, /meetings, /team) держат критичный JS без делегирования на document
   (удаление отчёта и поиск на /my, весь контроль бота и live-статусы на
   /meetings, тарифы и смена роли на /team), и замена только #app-main без
   исполнения этих скриптов заново тихо ломает функциональность — то есть
   отдельный рефакторинг, а не безопасный узкий фикс.

   Cross-Document View Transitions решают именно жалобу «мигает» — браузер
   по-прежнему делает полную навигацию, но сам умеет плавно перетечь между
   двумя документами: элементы с одинаковым view-transition-name (тут —
   нижняя панель и подвал) не исчезают-и-появляются, а визуально остаются на
   месте. Ни одной строки JS, скрипты страниц не участвуют вовсе.

   Поддержка браузеров частичная (Chrome/Edge; Safari — нет) — там, где API
   нет, `@view-transition` просто игнорируется и переход остаётся таким же,
   как сейчас. Деградация естественная, ничего не ломается.
   ═══════════════════════════════════════════════════════════════════════════ */
@view-transition {
  navigation: auto;
}

/* Имя даём только там, где панель реально видна (≤1023px, см. блок GS-138
   ниже) — на десктопе .app-tabs уходит в display:none, и participate в
   переходе элемент, которого нет на экране, смысла не имеет. */
@media (max-width: 1023px) {
  .app-tabs { view-transition-name: app-tabs; }
}
.app-footer { view-transition-name: app-footer; }

@media (prefers-reduced-motion: reduce) {
  /* Дефолтная кросс-фейд анимация browser API тоже подчиняется этому запросу
     не везде одинаково — гасим явно, как и остальные переходы в файле. */
  ::view-transition-group(app-tabs),
  ::view-transition-group(app-footer) {
    animation: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   НИЖНЯЯ ПАНЕЛЬ ВКЛАДОК И ШТОРКИ (GS-138)
   Канон поведения: П1 круглое-предмет · П4 приоритет по частоте · П5 аватар и
   «Ещё» о разном · П7 обязательное поведение шторок · П10 плавающая кнопка.

   Три порога: ≤767 телефон · 768-1023 планшет · ≥1024 десктоп.
   Панель живёт на телефоне И планшете — планшет держат в руках, палец тот же.
   Граница проходит по способу ввода, а не по ширине окна.

   Бургер и верхнее меню НЕ трогаются: на десктопе (≥1024) панель скрыта, и
   навигация работает как прежде. Порог бургера 1200px остаётся своим —
   сторож tests/test_nav_breakpoint.py сверяет его с NAV_BREAKPOINT в JS.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Место под панель, иначе она накрывает последний элемент страницы.
   Высота панели (56px) + безопасная область телефона с жестовой навигацией. */
@media (max-width: 1023px){
  .app-shell.has-tabs .app-main{
    padding-bottom: calc(56px + var(--sp-5) + env(safe-area-inset-bottom));
  }
  .app-shell.has-tabs .app-footer{
    margin-bottom: calc(56px + env(safe-area-inset-bottom));
  }
}

.app-tabs{
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: grid; grid-template-columns: repeat(5, 1fr);
  background: var(--c-surface);
  border-top: 1px solid var(--c-line-strong);
  /* 🔴 Канон, числовые нормативы: без этого на iPhone с жестовой навигацией
     панель перекроет индикатор перехода на домашний экран. */
  padding-bottom: env(safe-area-inset-bottom);
  box-shadow: 0 -2px 12px rgba(0, 0, 0, .06);
}
.app-tabs__i{
  appearance: none; background: none; border: 0; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px;
  /* 48px — норма холдинга для пальца; 56 даёт запас под подпись. */
  min-height: 56px; padding: 6px 2px 8px;
  color: var(--c-ink-4); text-decoration: none;
  font-family: var(--font-sans); font-size: 10px; font-weight: 600;
  letter-spacing: -.1px; text-align: center; line-height: 1.15;
  -webkit-tap-highlight-color: transparent;
}
.app-tabs__i svg{ width: 22px; height: 22px; }
.app-tabs__i.is-active{ color: var(--c-gold-strong); }
.app-tabs__i:active{ background: var(--c-surface-3); }
.app-tabs__i:focus-visible{ outline: 1px solid var(--c-gold); outline-offset: -2px; }

/* Центральная кнопка — единственный круг в прямоугольной системе (канон П1).
   Скругляется только то, что «предмет», который берут в руки. Станет круглым
   что-то ещё — приём умрёт, и она перестанет читаться как кнопка. */
.app-tabs__i--add{ position: relative; }
.app-tabs__fab{
  width: 52px; height: 52px; margin-top: -18px;
  display: grid; place-items: center;
  border-radius: var(--radius-pill);
  background: var(--c-gold); color: var(--c-gold-contrast);
  border: 1px solid var(--c-gold-line);
  box-shadow: 0 6px 16px -4px rgba(153, 128, 24, .45), var(--elev-2);
  transition: transform .14s ease;
}
.app-tabs__fab svg{ width: 24px; height: 24px; }
.app-tabs__i--add:active .app-tabs__fab{ transform: scale(.94); }
.app-tabs__i--add .app-tabs__lbl{ margin-top: 1px; }

/* ── Шторка ───────────────────────────────────────────────────────────────
   Затемнение кликабельно на закрытие, фон под шторкой не прокручивается,
   свайп вниз и Esc закрывают, кнопка «назад» Android закрывает шторку,
   а не уводит со страницы. Всё это — обязательный список канона П7. */
.app-scrim{
  position: fixed; inset: 0; z-index: 100;
  background: rgba(16, 20, 28, .55);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  opacity: 0; transition: opacity .18s ease;
}
.app-scrim.is-on{ opacity: 1; }
.app-scrim[hidden]{ display: none; }

.app-sheet{
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 101;
  background: var(--c-surface);
  border-top: 1px solid var(--c-line-strong);
  box-shadow: var(--elev-3);
  transform: translateY(100%);
  transition: transform .24s cubic-bezier(.2, .7, .3, 1);
  max-height: 88dvh; overflow-y: auto;
}
.app-sheet.is-on{ transform: translateY(0); }
.app-sheet[hidden]{ display: none; }
.app-sheet__in{
  padding: var(--sp-3) var(--sp-4) calc(var(--sp-6) + env(safe-area-inset-bottom));
  max-width: 640px; margin: 0 auto;
}
/* Полоска-ухватка: показывает, что шторку можно потянуть вниз. */
.app-sheet__grip{
  width: 36px; height: 4px; border-radius: var(--radius-pill);
  background: var(--c-line-strong); margin: 0 auto var(--sp-4);
}
.app-sheet__h{ font-size: 15px; font-weight: 700; margin: 0 0 var(--sp-1); }
.app-sheet__sub{ font-size: 12px; color: var(--c-ink-3); margin: 0 0 var(--sp-4); }

/* Строки меню внутри шторки — кликабельна ВСЯ строка (канон П8). */
.app-sheet__row{
  display: flex; align-items: center; gap: var(--sp-3);
  width: 100%; min-height: 48px; padding: var(--sp-2) var(--sp-2);
  appearance: none; background: none; border: 0; cursor: pointer;
  color: var(--c-ink); text-decoration: none; text-align: left;
  font-family: var(--font-sans); font-size: 14px; font-weight: 600;
  -webkit-tap-highlight-color: transparent;
}
.app-sheet__row:active{ background: var(--c-surface-3); }
.app-sheet__row:focus-visible{ outline: 1px solid var(--c-gold); outline-offset: -2px; }
.app-sheet__row svg{ width: 18px; height: 18px; color: var(--c-ink-3); flex: none; }
.app-sheet__row.is-danger{ color: var(--c-danger); }
.app-sheet__row.is-danger svg{ color: var(--c-danger); }
.app-sheet__who{
  display: block; padding: 0 var(--sp-2) var(--sp-2);
  font-size: 12px; color: var(--c-ink-3); word-break: break-all;
}
.app-sheet__sect{
  display: block; padding: var(--sp-3) var(--sp-2) var(--sp-1);
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--c-ink-4);
}
.app-sheet__hr{ height: 1px; background: var(--c-line); margin: var(--sp-2) 0; border: 0; }
.app-sheet__mark{ margin-left: auto; opacity: 0; flex: none; }
.app-sheet__row[aria-checked="true"] .app-sheet__mark{ opacity: 1; }

/* ── Управление идущей встречей: пара «завершить + отменить» (GS-155) ────────
   🔴 ОДИН вид на ОБЕИХ страницах — главной и списке встреч (решение владельца
   31.08.2026: «кнопки должны быть одинаковые»). Живёт в components.css именно
   поэтому: у страницы встреч свои стили внутри шаблона, и второй набор правил
   разъехался бы с первым при первой же правке.

   🔴 Операции НЕ равнозначны, и раскладка обязана это показывать.
   «Завершить и расшифровать» сохраняет записанное; «Отменить без записи»
   выбрасывает его безвозвратно — сервер при отмене ещё и отзывает ключ приёма,
   чтобы бот не сдал запись, даже если успел. Две одинаковые кнопки рядом —
   приглашение к промаху ценой в потерянную встречу (закон Фиттса: опасное
   подальше от частого).

   Поэтому: созидательное — кнопкой во всю ширину, необратимое — тихой строкой
   под ней. Тот же приём, которым на главной разведены зона файла и источники. */
.meetacts{ display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-2); }
/* 🔴 ПАРНОЕ ПРАВИЛО К display:flex — без него [hidden] НЕ РАБОТАЕТ (GS-175).
   Браузерное [hidden]{display:none} слабее правила класса, поэтому блок с
   `display:flex` остаётся видимым, сколько бы JS ни ставил ему hidden.

   Стоило это ровно того, о чём предупреждает INHERITED_DISPLAY в
   tests/test_hidden_attribute_works.py: на главной «Завершить и расшифровать»
   висела с первого мига — до отправки бота и пока он шёл в комнату, — хотя
   botActsSync() честно ставил hidden по признакам сервера. Кнопка обещала
   расшифровку встречи, которой ещё не существовало, и вплотную сливалась с
   «Отправить бота» в один жёлтый прямоугольник (замечание владельца
   01.09.2026).

   Селектор с классом, а не голый [hidden]: специфичность обязана быть не ниже
   .meetacts, иначе правило снова проиграет. */
.meetacts[hidden]{ display: none; }
.meetacts__go{
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; min-height: 48px; padding: 10px 16px;
  background: var(--c-gold); color: var(--c-gold-contrast);
  border: 1px solid var(--c-gold-line); border-radius: var(--radius-sm);
  font-family: var(--font-sans); font-size: 15px; font-weight: 700;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.meetacts__go:hover{ background: var(--c-gold-mid); }
.meetacts__go:focus-visible{ outline: 1px solid var(--c-gold); outline-offset: 2px; }
.meetacts__go[disabled]{ opacity: .6; cursor: default; }
/* Отмена — строка, а не кнопка: цветом и весом видно, что это не главный путь.
   Тач-цель при этом полноценная (44px) — промахнуться по НЕЙ не страшно,
   страшно промахнуться ПО НЕЙ ВМЕСТО кнопки, а это решает разница в виде. */
.meetacts__cancel{
  display: inline-flex; align-items: center; justify-content: center;
  width: 100%; min-height: 44px; padding: 6px 12px;
  background: none; border: 0; cursor: pointer;
  color: var(--c-ink-3); font-family: var(--font-sans); font-size: 13.5px;
  text-decoration: underline; text-underline-offset: 3px;
  -webkit-tap-highlight-color: transparent;
}
.meetacts__cancel:hover{ color: var(--c-danger); }
.meetacts__cancel:focus-visible{ outline: 1px solid var(--c-danger); outline-offset: -2px; }
.meetacts__cancel[disabled]{ opacity: .6; cursor: default; }
.meetacts [hidden]{ display: none; }

/* ── Ссылка-переход «Отправить бота на встречу» (GS-155) ───────────────────
   Страница встреч показывает, КУДА бот отправлен; отправка живёт на главной.
   Чтобы не копировать форму, здесь — тихая ссылка-переход. Вид — как у
   .meetacts__cancel, но без подчёркивания: это не действие, а путь. */
.meetings__cta{ margin: 0 0 var(--sp-3); }
.meetings__cta-link{
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 6px 12px;
  color: var(--c-ink-3); font-family: var(--font-sans); font-size: 13.5px;
  text-decoration: none; border-radius: var(--radius-sm);
  -webkit-tap-highlight-color: transparent;
}
.meetings__cta-link:hover{ color: var(--c-gold-strong); }
.meetings__cta-link:focus-visible{ outline: 1px solid var(--c-gold); outline-offset: 2px; }

/* ── Шторка аккаунта (GS-146) ─────────────────────────────────────────────
   Карточка человека вверху шторки: знак крупнее, чем в шапке, — здесь есть
   место, и он подтверждает, под какой учётной записью сидишь. */
.app-sheet__acct{
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 0 var(--sp-2) var(--sp-3);
}
/* Круглый — как аватар в шапке (канон П1). Две метки одного человека на одном
   экране обязаны выглядеть одинаково: квадрат в шторке при круге в шапке
   читался бы как два разных элемента. Та же тонкая золотая обводка, что в
   шапке (31.08.2026) — приглушённая, не спорящая с брендом. */
.app-sheet__ava{
  width: 44px; height: 44px; flex: none;
  display: grid; place-items: center;
  background: var(--c-surface-3); border: 1px solid var(--hdr-gold-line);
  border-radius: var(--radius-pill);
  font-size: 17px; font-weight: 700;
  color: var(--c-ink-2);
}
.app-sheet__acctb{ min-width: 0; }
/* break-all, а не ellipsis: адрес почты обязан читаться целиком — по нему
   человек и опознаёт учётную запись. Обрезанный «serg…@» не отвечает ни на
   один вопрос, ради которого сюда зашли. */
.app-sheet__acctm{
  display: block; font-size: 14px; font-weight: 600; color: var(--c-ink);
  word-break: break-all;
}
.app-sheet__accto{
  display: block; margin-top: 2px;
  font-size: 12px; color: var(--c-ink-3);
}

/* Сегменты тем и языков. Кнопки во всю ширину поровну — палец попадает в любую
   без прицеливания (закон Фиттса), 48px по высоте держится min-height. */
.app-sheet__seg{
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: var(--sp-2); padding: 0 var(--sp-2);
}
.app-sheet__segb{
  min-height: 48px; padding: var(--sp-2) var(--sp-1);
  appearance: none; cursor: pointer;
  background: var(--c-surface-2); border: 1px solid var(--c-line);
  border-radius: var(--radius-sm);
  color: var(--c-ink-2); font-family: var(--font-sans);
  font-size: 13px; font-weight: 600;
  -webkit-tap-highlight-color: transparent;
}
.app-sheet__segb:active{ background: var(--c-surface-3); }
.app-sheet__segb:focus-visible{ outline: 1px solid var(--c-gold); outline-offset: -2px; }
/* Выбранное — золотой заливкой, а не галочкой: в сегментах галочка дублировала
   бы то, что уже сказано цветом, и съедала бы ширину подписи.
   🔴 Токен --c-gold-bg, а не выдуманный --c-gold-soft: несуществующая переменная
   молча уходит в fallback, и выбранный язык visually не отличался от прочих. */
.app-sheet__segb[aria-checked="true"]{
  background: var(--c-gold-bg);
  border-color: var(--c-gold-line);
  color: var(--c-gold-strong);
}

/* Аватар-кнопка телефона против выпадающего меню десктопа.
   Разводит ШИРИНА, а не pointer: на планшете с клавиатурой шторка тоже уместна —
   правило про размер экрана и дотягиваемость, а не про точность ввода. */
.app-acct-m{
  display: inline-grid; place-items: center;
  width: 40px; height: 40px; min-width: 40px;
  appearance: none; background: none; border: 0; padding: 0; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.app-acct-m:focus-visible{ outline: 1px solid var(--c-gold); outline-offset: 2px; }
/* Парное к своему display: без этого атрибут hidden на кнопке молча не сработал
   бы — та же ловушка, что поймали у .preset-grid на стенде 29.08.2026. */
.app-acct-m[hidden]{ display: none; }
@media (max-width: 1023px){
  .app-acct{ display: none; }
}
@media (min-width: 1024px){
  .app-acct-m{ display: none; }
}

/* ── ПЛАНШЕТ: панель остаётся, содержимое дышит ── */
@media (min-width: 768px) and (max-width: 1023px){
  .app-sheet__in{ padding: var(--sp-4) var(--sp-5) calc(var(--sp-6) + env(safe-area-inset-bottom)); }
}

/* ── ДЕСКТОП: панель уходит, навигация работает по-старому ──
   Подача меняется, состав — нет. Круглая кнопка остаётся телефону: здесь есть
   курсор, «палец» не нужен (канон П1). */
@media (min-width: 1024px){
  .app-tabs{ display: none; }
  .app-shell.has-tabs .app-main{ padding-bottom: var(--sp-6); }
  .app-shell.has-tabs .app-footer{ margin-bottom: 0; }

  /* Шторки становятся окнами по центру — содержимое то же. */
  .app-sheet{
    left: 50%; top: 50%; right: auto; bottom: auto;
    transform: translate(-50%, -46%) scale(.98);
    width: min(560px, calc(100vw - 64px));
    max-height: min(78vh, 720px);
    border: 1px solid var(--c-line-strong);
    box-shadow: var(--elev-3);
  }
  .app-sheet.is-on{ transform: translate(-50%, -50%) scale(1); }
  .app-sheet__grip{ display: none; }   /* тянуть нечего — это окно */
  .app-sheet__in{ padding: var(--sp-5) var(--sp-6) var(--sp-6); }
}

/* Уважение к системной настройке — обязательный пункт канона П7. */
@media (prefers-reduced-motion: reduce){
  .app-sheet, .app-scrim, .app-tabs__fab{ transition: none; }
}

/* ── Плитки шторки «Добавить» (GS-139) ─────────────────────────────────────
   🔴 КАНОН П2: иконка НЕ получает собственную подложку. Плитка уже коробка;
   второй прямоугольник внутри — «коробка в коробке», лишняя деталь, которая не
   несёт информации. Роль передаётся ЦВЕТОМ и размером: золотая иконка —
   первичное действие, серая — обычное.

   Прецедент: в первой версии прототипа иконки сидели в белых квадратах.
   Замечание владельца по скриншоту: «странная белая обводка, лишние детали». */
/* stretch — плитки одной высоты при разной длине подписи. Без него плитка с
   пояснением вырастала выше соседей (замер 27.08.2026), и ряд читался как
   «одна важнее двух», хотя все три равноправны. */
.app-tiles{
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-3);
  align-items: stretch;
  margin-bottom: var(--sp-3);
}
.app-tile{
  appearance: none; cursor: pointer;
  border: 1px solid var(--c-line); background: var(--c-surface-2);
  padding: var(--sp-3) var(--sp-2);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-2);
  /* 88px — заметно выше нормы 48: плитка и есть главное действие шторки. */
  min-height: 88px;
  font-family: var(--font-sans); font-size: 12px; font-weight: 600;
  color: var(--c-ink-2); text-align: center; line-height: 1.25;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: border-color .15s, background .15s;
}
.app-tile:active{ background: var(--c-surface-3); }
.app-tile:focus-visible{ outline: 1px solid var(--c-gold); outline-offset: -2px; }
.app-tile svg{ width: 26px; height: 26px; color: var(--c-ink-3); }
/* Первичное действие — золотом. Ради встреч сервис и покупают, поэтому две
   плитки выделены цветом, а не размером: разный размер читался бы как разная
   важность внутри одного ряда, хотя оба пути равноправны. */
.app-tile--hero{ border-color: var(--c-gold-line); background: var(--c-gold-bg); }
.app-tile--hero svg{ color: var(--c-gold-strong); }
.app-tile--hero:active{ background: var(--c-gold-bg); }
.app-tile__sub{
  font-size: 10px; font-weight: 500; color: var(--c-ink-4);
  line-height: 1.2;
}
/* Погашенная плитка при закрытом доступе. aria-disabled, а не disabled:
   настоящий disabled не отдаёт событий, и человек, не заметивший плашку,
   жмёт серую плитку, не получает НИЧЕГО и решает, что сломался сервис.
   Молчание хуже отказа — оно не называет причину и не предлагает выхода. */
.app-tile[aria-disabled="true"]{ opacity: .5; }

.app-sheet__hint{
  font-size: 11px; color: var(--c-ink-4); line-height: 1.4;
  margin: 0 0 var(--sp-2);
}

@media (min-width: 768px){
  .app-tile{ min-height: 104px; }
  .app-tiles{ gap: var(--sp-4); }
}

/* Кнопка «Показать ещё» под длинным списком (GS-140, канон П9).
   Во всю ширину — по Фиттсу ширина бесплатна, а попадание облегчает; стоит там,
   где человек упирается в конец списка, и палец уже внизу экрана. */
.list-more{
  display: block; width: 100%;
  min-height: 48px; margin: var(--sp-4) 0 var(--sp-2);
  appearance: none; cursor: pointer;
  background: var(--c-surface-2); border: 1px solid var(--c-line);
  color: var(--c-ink-2);
  font-family: var(--font-sans); font-size: 14px; font-weight: 600;
  -webkit-tap-highlight-color: transparent;
  transition: background .15s, border-color .15s;
}
.list-more:hover{ background: var(--c-surface-3); border-color: var(--c-line-strong); }
.list-more:active{ background: var(--c-surface-3); }
.list-more:focus-visible{ outline: 1px solid var(--c-gold); outline-offset: -2px; }
.list-more[hidden]{ display: none; }
.list-more__n{ color: var(--c-ink-4); font-weight: 500; }
.list-more__n:not(:empty)::before{ content: "+"; }

/* ═══ Поля ввода под пальцем: 16px против автозума iOS (GS-142) ═════════════
   🔴 Порог точный: 16px и выше — зума нет; 15px и ниже Safari на iOS
   масштабирует вьюпорт к полю. Хуже всего то, что страница ОСТАЁТСЯ
   увеличенной и после ухода из поля — вёрстка уезжает, и человек отзумливает
   вручную при каждом заполнении.

   ⛔ Лечить это через maximum-scale=1 / user-scalable=no НЕЛЬЗЯ: отключается
   масштабирование страницы, прямое нарушение WCAG 1.4.4. Правильное решение —
   именно 16px.

   Замер 27.08.2026 на странице управления встречей (390×844): восемь полей из
   тринадцати были 13-14px — пароль, срок ссылки, метка гостевой ссылки, поиск.
   Форма управления доступом — то место, где автозум особенно дорог: человек
   набирает пароль, промахивается по увеличенной вёрстке и не понимает, почему.

   Только под пальцем (pointer: coarse). Под мышью 13-14px остаются: там зума
   нет вовсе, а мелкий кегль держит форму компактной. Граница по способу ввода,
   а не по ширине окна — у сенсорного ноутбука ширина десктопная, палец тот же.

   min-height 48px — норма холдинга: поле это ещё и тач-цель. */
@media (pointer: coarse){
  .sc-manage input[type=text],
  .sc-manage input[type=password],
  .sc-manage input[type=date],
  .sc-manage input[type=search],
  .sc-manage input[type=email],
  .sc-manage input[type=url],
  .sc-manage textarea,
  .sc-manage select{
    font-size: 16px;
    min-height: 48px;
  }
  /* Чекбоксы областей доступа: сам квадратик 13px — цель, по которой палец
     промахивается. Растим квадратик и подпись рядом, чтобы нажималась вся
     строка (канон П8): подпись «Отчёт»/«Расшифровка» и есть то, во что целятся. */
  .sc-manage input[type=checkbox]{ inline-size: 20px; block-size: 20px; }
  .sc-manage .chk{ min-height: 48px; font-size: 15px; }
  /* Чипы областей (GS-147) — та же норма 48px под пальцем. */
  .sc-manage .chip{ min-block-size: 48px; }
}

/* Кнопки формы управления под пальцем (GS-142). Замер 27.08.2026: вкладки 41px,
   minibtn 40px, «Сохранить» 40px при норме холдинга 48.

   Растим сами кнопки, а не зону через ::after: здесь они стоят в ряд вплотную
   (вкладки «Доступ»/«Настройки», кнопки «показать»/«сгенерировать»/«копировать»
   у поля пароля), и невидимая зона накрыла бы соседнюю — палец попадал бы не
   туда, куда целится. Рост высоты раскладку не ломает: ряд и так однострочный. */
@media (pointer: coarse){
  .sc-manage .mgtab,
  .sc-manage .minibtn,
  .sc-manage .btn,
  .sc-manage button[type=submit]{ min-block-size: 48px; }
  /* Ссылка «назад» — тоже цель, а не подпись. */
  .sc-manage .backlink{ display: inline-flex; align-items: center; min-block-size: 48px; }

  /* Карандаш у названия встречи — исключение из правила выше: он стоит В СТРОКЕ
     с заголовком, и рост до 48px раздвинул бы её. Растим зону, не элемент.
     Кнопка копирования внутри поля ссылки свою зону уже имеет (44px, задана
     в шаблоне рядом с позиционированием) — второй раз её не трогаем. */
  .sc-manage .mgtitle__edit{ position: relative; }
  .sc-manage .mgtitle__edit::after{
    content: ""; position: absolute;
    top: 50%; left: 50%; inline-size: 48px; block-size: 48px;
    transform: translate(-50%, -50%);
  }

  /* Кнопки с одним значком («показать пароль») — 48px и по ширине: min-height
     дала высоту, но 40px по горизонтали остались, а палец промахивается по
     любой из сторон. Кнопки С ПОДПИСЬЮ («сгенерировать», «копировать») своей
     ширины набирают сами — их не трогаем, иначе строка кнопок переносится. */
  .sc-manage .minibtn:not(:has(.lbl)):empty,
  .sc-manage .minibtn[aria-pressed]{ min-inline-size: 48px; }

  /* Чекбокс областей доступа: цель — вся строка с подписью (канон П8).
     Сам квадратик 20px мал, но целятся не в него, а в слово «Отчёт». */
  .sc-manage label:has(> input[type=checkbox]),
  .sc-manage .chk{
    display: inline-flex; align-items: center; gap: 10px;
    min-block-size: 48px; cursor: pointer;
  }
}

/* ═══ ОБЩИЕ ЭЛЕМЕНТЫ ФОРМ ПОД ПАЛЬЦЕМ (GS-143) ═════════════════════════════
   Правило на весь продукт, а не на очередную страницу: .sc-input, .sc-select,
   .sc-tab и .sc-check используются в командах, встречах, проектах, админке.
   Чинить их по одной странице значило бы завести N копий одного решения,
   которые разъедутся — ровно это уже случилось с формой управления встречей,
   где стили живут в двух местах (см. GS-142).

   🔴 font-size 16px — против автозума iOS: 15px и ниже Safari масштабирует
   вьюпорт к полю и НЕ возвращает обратно. Замер 27.08.2026 на /team: поля
   канала оповещений были 13px.

   min-block-size 48px — норма холдинга для пальца. Только под pointer: coarse:
   под мышью прежние 35-44px остаются, там курсор точнее и форма компактнее. */
@media (pointer: coarse){
  .sc-input,
  .sc-select__el,
  .sc-textarea,
  input[type=text].sc-input,
  input[type=email].sc-input,
  input[type=url].sc-input{
    font-size: 16px;
    min-block-size: 48px;
  }
  /* Мелкий вариант поля тоже растёт: --sm задавал компактность ради десктопа,
     под пальцем она оборачивается промахом.
     У списка модификатор висит на ОБЁРТКЕ (.sc-select--sm), а кегль задан
     вложенному <select> — без этой строки высота выправлялась, а шрифт
     оставался 13px, и автозум никуда не девался (замер 27.08.2026). */
  .sc-input--sm{ min-block-size: 48px; font-size: 16px; }
  .sc-select--sm .sc-select__el{ font-size: 16px; }

  /* Вкладки разделов (Команда, Проекты, Каналы) — 44px до правки. */
  .sc-tab{ min-block-size: 48px; }

  /* 🔴 КНОПКА НЕ МЕЛЬЧЕ ПОЛЯ НАД НЕЙ (GS-225). Правила для .sc-btn здесь не
     было вовсе: поля этим же блоком росли до 48px, а кнопка оставалась 36px —
     и главное действие формы выглядело второстепенным рядом с тем, что человек
     только что заполнил. Замер 03.09.2026: «Создать» в окне нового проекта
     36px против поля 48px, «Добавить канал» на карточке проекта 36px.

     Правило ОБЩЕЕ, а не по страницам: .sc-btn живёт в организации, проектах,
     встречах и админке. Починка на одном экране завела бы N расходящихся копий
     — ровно так уже вышло с формой управления встречей (GS-142).

     Модификатор --sm тоже растёт: компактность задавалась ради десктопа, под
     пальцем она оборачивается промахом. Кегль поднимаем до 15px — подпись
     действия не должна быть мельче набранного текста; ширину не трогаем. */
  .sc-btn{ min-block-size: 48px; }
  .sc-btn--sm{ min-block-size: 48px; font-size: 15px; }

  /* Чекбокс с подписью: цель — вся строка, а не квадратик (канон П8). */
  .sc-check,
  label:has(> input[type=checkbox]):not(.app-sheet__row){
    display: inline-flex; align-items: center; gap: 10px;
    min-block-size: 48px;
  }
  input[type=checkbox]{ inline-size: 20px; block-size: 20px; }
}

/* ═══ БУРГЕР НЕ ДУБЛИРУЕТ НИЖНЮЮ ПАНЕЛЬ (GS-145) ═══════════════════════════
   🔴 Канон П5: два органа управления не открывают одно и то же. Замечание
   владельца 27.08.2026 по стенду: «бургер-меню дублируется с нижним меню».

   Так и было: бургер вёл на /, /my, /meetings, /team, /admin — ровно те же
   места, что вкладки панели и строки шторки «Ещё». Полное совпадение состава,
   два способа попасть в одно и то же. Это дефект внедрения панели (GS-138):
   новую навигацию добавили, старую убрать забыли.

   Где панель есть (≤1023) — бургера нет, навигация одна.
   Где панели нет (1024-1200, узкий десктоп) — бургер остаётся: там он
   единственный способ добраться до разделов, и порог 1200 сохраняется вместе
   с NAV_BREAKPOINT в components.js (сторож tests/test_nav_breakpoint.py).

   Скрываем ТОЛЬКО кнопку и выпадающую панель: сам <nav class="app-nav">
   остаётся в разметке и продолжает работать на десктопе ≥1201. Условие то же,
   что у самой панели (.has-tabs), — один признак на оба места, иначе разойдутся
   и получится либо две навигации, либо ни одной. */
@media (max-width: 1023px){
  .app-shell.has-tabs .app-burger{ display: none; }
  .app-shell.has-tabs .app-nav{ display: none; }
}

/* ── Строка «Обычно: <шаблон> · изменить» под карточкой проекта (GS-203) ─────
   и список выбора шаблона в окне (#tplModal). Классы rebuild-* совпадают со
   страницей отчёта НАМЕРЕННО: у отчёта свой автономный <style> (он не
   подключает components.css), и это его близнец для страниц каркаса — тот же
   приём, что у формы доступа (см. docs/dev/frontend.md про два набора стилей).
   Только токены: тёмная тема работает переопределением переменных. */
.preset-usual{
  margin-top: 4px; font-size: 12px; color: var(--c-ink-3);
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
}
.preset-usual--set{ color: var(--c-ink-2); font-weight: 600; }
/* Точка и действие («· выбрать», GS-217) — одним неразрывным узлом: при
   переносе в узкой карточке они уходят на вторую строку вместе, а не
   разлетаются («… ·» в конце одной строки и «выбрать» в начале другой).
   Точка вне текста кнопки — иначе она была бы подчёркнута вместе со словом. */
.preset-usual__act{ display: inline-flex; gap: 6px; white-space: nowrap; }
.preset-usual__sep{ color: var(--c-ink-4); font-weight: 400; }
.preset-usual__btn{
  position: relative;                     /* якорь зоны нажатия ниже */
  background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
  color: var(--c-ink-2); text-decoration: underline; text-underline-offset: 2px;
}
.preset-usual__btn:hover{ color: var(--c-ink); }
.preset-usual__btn:focus-visible{ outline: var(--focus-ring); }
/* Зона нажатия под пальцем — псевдоэлементом, а не размером кнопки (GS-225).
   Замер 03.09.2026: 49×15px, вдвое ниже нормы. Растить саму кнопку нельзя —
   это слово ВНУТРИ строки-подписи «Обычно: <шаблон> · выбрать», и высота
   разогнала бы строку. Псевдоэлемент не влияет на поток и стоит по центру, как
   у .help-q и .pc-act. Ширину не трогаем: слово шире 44px, растить нужно
   только высоту. */
@media (pointer: coarse){
  .preset-usual__btn::after{
    content: ""; position: absolute;
    top: 50%; left: 0; right: 0; height: 44px;
    transform: translateY(-50%);
  }
}

.rebuild-note{ margin: 0 0 var(--sp-4); color: var(--c-ink-2); font-size: 14px; }
.rebuild-list{
  border: 1px solid var(--c-line); padding: 0; margin: 0 0 var(--sp-4);
  max-height: min(48vh, 420px); overflow-y: auto;
}
.rebuild-opt{
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4); cursor: pointer;
  border-bottom: 1px solid var(--c-line);
}
.rebuild-opt:last-child{ border-bottom: 0; }
.rebuild-opt:hover{ background: var(--c-bg); }
.rebuild-opt input[type="radio"]{ margin-top: 3px; flex: none; }
.rebuild-opt input[type="radio"]:focus-visible{ outline: var(--focus-ring); }
.rebuild-opt__body{ display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rebuild-opt__name{ font-weight: 600; color: var(--c-ink); font-size: 14px; }
.rebuild-opt__short{ color: var(--c-ink-3); font-size: 12.5px; }

/* ── «Кому уходят итоги» на карточке проекта (GS-200) ────────────────────────
   Список = правда о рассылке (собирается тем же кодом, что доставка). Базовые
   получатели и каналы различаются подписью справа, а не цветом: цвет — не
   единственный носитель смысла. Только токены — обе темы бесплатно. */
.recip{ margin-top: var(--sp-6); border-top: 1px solid var(--c-line); padding-top: var(--sp-5); }
.recip__title{ margin: 0 0 var(--sp-3); font-size: 15px; color: var(--c-ink); display: flex; align-items: center; gap: 6px; }
.recip__list{ list-style: none; margin: 0 0 var(--sp-4); padding: 0; border: 1px solid var(--c-line); }
.recip__row{
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--c-line);
  font-size: 13.5px; flex-wrap: wrap;
}
.recip__row:last-child{ border-bottom: 0; }
.recip__who{ color: var(--c-ink); word-break: break-all; min-width: 0; }
.recip__you{ color: var(--c-ink-3); font-size: 12px; }
.recip__mask{ color: var(--c-ink-4); letter-spacing: 1px; }
.recip__base, .recip__chan{ color: var(--c-ink-3); font-size: 12.5px; flex: none; }
.recip__add{ margin-top: var(--sp-2); }
.recip__add > summary{
  cursor: pointer; color: var(--c-ink-2); font-size: 13.5px;
  text-decoration: underline; text-underline-offset: 2px; width: fit-content;
}
.recip__add > summary:focus-visible{ outline: var(--focus-ring); }
.recip__add[open] > summary{ margin-bottom: var(--sp-3); }
