/* ═══════════════ БАЗА ═══════════════
   Зона: дизайн-токены :root (обе темы), сброс и типографика, общие элементы
   управления (.btn, .fchip, .tag, .empty, .grid, .ring, микрофон «голос везде»),
   шапка .hdr и переключатель проектов, боковая панель .side и её потроха,
   нижняя навигация, раскладка .shell / .wrap / .screen / .two-col, глобальные
   полосы (.newsbar, .pickbar), тосты, скелет и крутилка, FAB и панель помощника.
   ПРАВИЛО РАЗРЕЗА: этот файл правит ОДИН агент за раз и только свою зону.
   Подключается ПЕРВЫМ — всё остальное перебивает написанное здесь. */

/* ═════════════ «ТИХАЯ ДОСКА» — дизайн-токены (бриф дизайн-директора) ═════════════ */
:root{
  /* ═══ ПЕРЕСЧЁТ ПОД AA 4.5:1 (перенос «Моё», §4 ПЕРЕНОС_МОЁ_В_ПЛАТФОРМУ.md) ═══
     Старые значения давали 23 пары ниже 4.5:1 в светлой теме (st-new 3.01,
     st-done 3.01, st-review 3.12, alarm 3.39, ink-2 4.47 на фоне). Ниже —
     набор, у которого 0 провалов на шести фонах светлой и шести тёмной.
     Это правка дизайн-закона «Тихая доска» для ВСЕЙ платформы, не одного экрана.
     Откат: вернуть закомментированные справа исходные значения. */
  --bg:#FAFAF8;            /* было #ECE8E1 — «бумага», первая ступень */
  --surface:#F4F3EF;       /* было #F6F3EE — вторая ступень */
  --card:#FFFFFF;          /* НОВОЕ — третья ступень: строка списка/карточка */
  --surface-2:#F1EDE6;     /* вложенная поверхность/колонка */
  --line:#E4E0D8;          /* было #DCD6CC — иерархия тенью, а не рамкой */
  --line-2:#EFECE5;        /* НОВОЕ — разделитель строк внутренней тенью */
  --ink:#2B2A27;           /* текст основной */
  --ink-2:#67635A;         /* было #6E695F (4.47 — не дотягивал до AA) */
  --ink-3:#6B675E;         /* НОВОЕ — третья ступень серого, подписи 11px */
  --accent:#3B5B7A;        /* единственный сине-стальной акцент */
  --accent-hover:#31506B;  /* было #4A6E92 — наведение обязано быть ТЕМНЕЕ */
  --accent-soft:#E4EAF1;   /* было #E1E7EE — мягкая заливка акцента */
  --accent-ghost:#F0F3F7;  /* НОВОЕ — подсветка строки под пальцем */
  --on-accent:#FFFFFF;     /* НОВОЕ — текст НА акценте (в тёмной теме тёмный!) */
  --r1:6px; --r2:10px; --r3:14px;   /* НОВОЕ — три радиуса стола; старые не трогаем */
  /* ═════ ШКАЛА ОТСТУПОВ — единственная на платформе ═════
     Шесть значений, все кратны 4. Число вне списка — брак.
     Округление старого кода: к ближайшему, ровно посередине — к меньшему.
     Заведена 31.08: в base.css и board.css насчитали 27 разных чисел отступов,
     из-за чего каждая новая полоса вставала на свою высоту и на свой левый край,
     и доска читалась как «вырвали куски и вставили как попало». */
  --s1:4px;   /* внутри элемента: точка↔текст, значок↔подпись */
  --s2:8px;   /* соседи одного рода: чип↔чип, карточка↔карточка */
  --s3:12px;  /* группы в полосе; поле малого контейнера (.col, .tcard) */
  --s4:16px;  /* между полосами; поле страницы; поле крупного контейнера */
  --s5:24px;  /* блоки разного рода */
  --s6:32px;  /* раздел: содержимое ↔ «Опасная зона», низ страницы */
  --h-row:44px;   /* высота ЛЮБОГО ОРГАНА УПРАВЛЕНИЯ и ЛЮБОЙ полосы управления */
  /* ⚠️ ДВЕ ВЫСОТЫ, А НЕ ОДНА. --h-row — норма касания §3, и она про ОРГАНЫ:
     кнопки, чипы, переключатели, поля. Строка ДАННЫХ (задача в таймлайне, строка
     списка, шапка столбцов) органом не является и держит --h-data.
     Заведена 01.09 по замеру: строку таймлайна подняли с 30 до 44 «ради §3», и
     на одиннадцати видимых строках это +154 px пустоты на том же содержимом.
     Владелец дословно: «на боевой компактнее — компактность восприятия
     информации пропала». Плотность данных важнее ровного числа в отчёте. */
  --h-data:30px;  /* высота СТРОКИ ДАННЫХ: таймлайн, шапка списка */
  --r-pill:999px; /* де-факто уже токен: писался руками 13 раз */
  /* ═════ ТРИ НЕЗАВИСИМЫХ КАНАЛА (docs/design/РЕШЕНИЯ_ЭКРАНЫ.md §0) ═════
     ЗАЛИВКА = статус (ровно 3 значения). ОБВОДКА И ЗНАЧОК = срок. ДЛИНА = сколько сделано.
     Ни один элемент не несёт две переменные сразу. Терракота НИКОГДА не заменяет
     статусный цвет — только добавляется поверх. */
  /* канал A — СТАТУС. Приглушённые, НИКОГДА не чистые RGB. Ровно три. */
  --st-new:#6B675D;        /* было #8A8579 (3.01) — Надо / новая, серый */
  --st-prog:#46698C;       /* В работе — сине-стальной, СДВИНУТ от --accent (§1.6) */
  --st-review:#7A6440;     /* было #9A7F4E (3.12) — На проверке, янтарно-песочный */
  --st-done:#5F6955;       /* было #7C8A6F (3.01) — Готово, шалфейный */
  --st-new-bg:#E8E4DC; --st-prog-bg:#E1E7EE; --st-review-bg:#EFE6D4; --st-done-bg:#E6EADF; --st-fire-bg:#F0E1DA;
  /* канал B — СРОК (терракота). Три интенсивности ОДНОГО тона. */
  --alarm:#94543E;         /* было #B4694E (3.39) — просрочено, плотная заливка чипа */
  --alarm-bg:#F5E8E1;      /* было #F0E1DA — срок сегодня, мягкая заливка */
  --alarm-line:#D2A18A;    /* срок скоро / обводка признака просрочки */
  --danger:#B4694E;        /* тот же хекс, другой СМЫСЛ: деструктив и ошибки */
  --st-fire:var(--alarm);  /* АЛИАС переходного периода — НЕ УДАЛЯТЬ до волны 4 */
  --r-card:16px; --r-btn:10px; --r-drawer:20px;
  --sh-1:0 1px 2px rgba(35,30,20,.06);
  --sh-2:0 1px 2px rgba(35,30,20,.05), 0 6px 16px rgba(35,30,20,.08);
  --sh-3:0 2px 6px rgba(35,30,20,.08), 0 18px 40px rgba(35,30,20,.14);
  --sh-press:inset 0 2px 6px rgba(0,0,0,.14);
  --font:"Inter","Manrope","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif;
  --ease:cubic-bezier(.22,.61,.36,1);
  --nav-h:64px;
  /* ═══ ОКНО КАРТОЧКИ ЗАДАЧИ (01.09) — одно число на всю платформу ═══
     Владелец 01.09: «чтобы у нас был комфортный размер окна для карточки; размер
     чата — чтобы он прокручивался и карточка не росла от чата». Считаем от
     РАБОЧЕГО ПРОЁМА, а не от экрана: липкая шапка (--hdr-h, меряется живьём) и
     нижняя навигация (--nav-h) забирают 177 px всегда, и карточка, посчитанная
     от голого экрана, ушла бы низом под навигацию.
     48 px — полоса доски под карточкой: «не на всю страницу» буквально, видно,
     что карточка лежит НА доске, а не заменила её.
     Потолок 720 — то же число, что у докнутой панели (.drawer.docked,
     height:min(70vh,720px)): одна платформа — один размер, как с --shell-w.
     Без него на мониторе 2560×1440 карточка растянулась бы на 1215 px, а мера
     строки и «комфортный размер» кончаются гораздо раньше.
     Пол 280 — предохранитель для вырожденно низкого окна; выше проёма он не
     поднимается, поэтому композер карточки не уезжает за нижний край.
     svh, а не dvh: адресная строка мобильного браузера дёргает dvh десятками
     раз за прокрутку (см. комментарий у watchHdrH), и высота карточки дышала бы
     под пальцем — §8 «раскладка не перерисовывается под руками». */
  --kartochka-zazor:48px;
  --kartochka-okno:clamp(280px, calc(100svh - var(--hdr-h) - var(--nav-h) - var(--kartochka-zazor)), 720px);
  --side-w:264px;
  /* ширина рабочего поля — одно число на всю платформу. Раньше 1424 было вбито
     руками в .shell и в .drawer.docked; разъезжались при любой правке. */
  --shell-w:1424px;
  /* высота шапки. Меряется живьём (app.js watchHdrH) — шапка двухстрочная и
     плавает: крошки переносятся, появляется «Назад», на телефоне safe-area.
     Нужна боковой панели: она fixed и обязана начинаться ПОД шапкой. */
  --hdr-h:0px;
  /* ═════ ЕДИНАЯ ТАБЛИЦА СЛОЁВ (z-index) — см. отчёт по навигации v2 ═════
     40  .hdr            шапка (крошки/переключатель)
     45  .botnav         нижняя навигация (8 вкладок, не трогаем)
     46  .fab             кнопка-помощник поверх нижней навигации
     60  .pmenu           старая выпадашка проектов (как была)
     63  .scrim2          подложка боковой панели (моб.)
     66  .side            боковая панель-дублёр (новая, «фиксация»)
     70  .scrim           подложка панели задачи/проблемы
     80  .drawer          панель задачи/проблемы/форм
     82  #chatScrim       подложка чата — специально НАД .drawer, чтобы
                          помощника можно было открыть поверх открытой задачи
     84  .chatpanel       чат-помощник — самый верхний рабочий слой
     86  .kartokno        окно сдачи карточки — своим узлом в body, выше всего
                          рабочего: под ним лежит карточка, а решение об отправке
                          принимают глядя на отчёт, а не на чужой экран
     100 .toast-wrap      тосты — всегда видны, выше всего            */
  --z-hdr:40; --z-botnav:45; --z-fab:46; --z-pmenu:60;
  --z-side-scrim:63; --z-side:66;
  --z-scrim:70; --z-drawer:80;
  --z-chat-scrim:82; --z-chat:84;
  --z-kartokno:86;
  --z-toast:100;
}
:root[data-theme="dark"]{
  --bg:#1B1A17; --surface:#232120; --card:#282624; --surface-2:#282624; --line:#37342E; --line-2:#2E2B27;
  --ink:#ECE8E1; --ink-2:#B3AB9C; --ink-3:#9A9384;
  --accent:#7CA0C4; --accent-hover:#93B2D0; --accent-soft:#222D38; --accent-ghost:#20272E;
  /* ⚠️ Белый на акценте тёмной темы даёт 2.73 — запрещено. Считал по WCAG 2.1.
     Тёмный #1B1A17 на том же акценте даёт 6.37. */
  --on-accent:#1B1A17;
  --st-new:#9A9384; --st-prog:#8AACCB; --st-review:#D0B47C; --st-done:#A7BA96;
  --st-new-bg:#2C2A26; --st-prog-bg:#293643; --st-review-bg:#37301F; --st-done-bg:#2A3128; --st-fire-bg:#382822;
  --alarm:#E09877; --alarm-bg:#3A2921; --alarm-line:#8C5741; --danger:#CE8064;
  --st-fire:var(--alarm);
  --sh-1:0 1px 2px rgba(0,0,0,.35);
  --sh-2:0 1px 2px rgba(0,0,0,.35), 0 6px 16px rgba(0,0,0,.4);
  --sh-3:0 2px 6px rgba(0,0,0,.4), 0 18px 40px rgba(0,0,0,.5);
  --sh-press:inset 0 2px 6px rgba(255,255,255,.10);
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --bg:#1B1A17; --surface:#232120; --card:#282624; --surface-2:#282624; --line:#37342E; --line-2:#2E2B27;
    --ink:#ECE8E1; --ink-2:#B3AB9C; --ink-3:#9A9384;
    --accent:#7CA0C4; --accent-hover:#93B2D0; --accent-soft:#222D38; --accent-ghost:#20272E;
    --on-accent:#1B1A17;
    --st-new:#9A9384; --st-prog:#8AACCB; --st-review:#D0B47C; --st-done:#A7BA96;
    --st-new-bg:#2C2A26; --st-prog-bg:#293643; --st-review-bg:#37301F; --st-done-bg:#2A3128; --st-fire-bg:#382822;
    --alarm:#E09877; --alarm-bg:#3A2921; --alarm-line:#8C5741; --danger:#CE8064;
    --st-fire:var(--alarm);
    --sh-1:0 1px 2px rgba(0,0,0,.35);
    --sh-2:0 1px 2px rgba(0,0,0,.35), 0 6px 16px rgba(0,0,0,.4);
    --sh-3:0 2px 6px rgba(0,0,0,.4), 0 18px 40px rgba(0,0,0,.5);
    --sh-press:inset 0 2px 6px rgba(255,255,255,.10);
  }
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;padding:0}
body{
  font-family:var(--font); background:var(--bg); color:var(--ink);
  font-size:15px; line-height:1.4; font-weight:400;
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
  padding-bottom:calc(var(--nav-h) + env(safe-area-inset-bottom));
}
button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit;font-size:inherit}
input,textarea,select{font-family:inherit;font-size:15px;color:var(--ink)}
.tnum{font-variant-numeric:tabular-nums;font-weight:600}
::-webkit-scrollbar{width:9px;height:9px}
::-webkit-scrollbar-thumb{background:var(--line);border-radius:9px}

/* ═════════════ ШАПКА: крошки + переключатель проектов ═════════════ */
.hdr{position:sticky;top:0;z-index:var(--z-hdr);background:color-mix(in srgb,var(--bg) 88%,transparent);
  backdrop-filter:blur(10px);border-bottom:1px solid var(--line);
  padding:calc(env(safe-area-inset-top) + var(--s2)) 0 var(--s2)}
/* ⚠️ ОДНА КОЛОНКА НА ШАПКУ И НА ТЕЛО. Было max-width:1400 у шапки против
   --shell-w 1424 у тела и поле 16 на самой .hdr — левый край шапки и левый край
   доски расходились на 3.5 px в любом окне шире 1456. Владелец 31.08 читал это
   как «вставили как попало». Теперь ограничение ширины и поле берутся из тех же
   двух чисел, что у .shell/.wrap, и края совпадают вычислением, а не подгонкой. */
.hdr-in{max-width:var(--shell-w);margin:0 auto;padding:0 var(--s4);
  display:flex;flex-direction:column;gap:var(--s2)}
.hdr-top{display:flex;align-items:center;gap:10px;min-width:0}
.brand{display:flex;align-items:center;justify-content:center;gap:9px;height:44px;flex:none}
.brand .logo{width:30px;height:30px;border-radius:9px;background:var(--accent);color:var(--on-accent);
  display:grid;place-items:center;font-weight:600;font-size:15px;box-shadow:var(--sh-1)}
.brand b{font-size:16px;font-weight:600;letter-spacing:.2px;white-space:nowrap}
.hdr-sp{margin-left:auto}
/* Правка 16.08 (tasks/portfel-lyudi-vertikalno.md): было overflow-x:auto —
   на 390 px крошки уезжали ползунком за край, тот же брак, что в портфеле.
   Строка остаётся одной постоянной высоты (это шапка, ей и так нельзя расти),
   ползунка нет: лишнее не сворачивается в «ещё N» (глубина пути и так
   максимум 4 шага — считать нечего), а обрезается многоточием. Текущий шаг
   (.here) не режется никогда — это ответ на вопрос «где я», обрезать его
   недопустимо; корень (.root) тоже цел — без него не вернуться на портфель
   одним кликом. Ужимается средний, необязательный шаг пути.
   Правка tasks/shapka-na-390-krosha-i-tach-celi.md: на 390 крошка обрезалась
   НЕ текстом (flex-shrink:0 у .crumb.root это и так держал), а тем, что сам
   nav#crumbs — flex-item с min-width:0 внутри .hdr-top — сжимался соседями
   (герб, четыре иконки шапки) до 17px и обрезАл единственного ребёнка через
   overflow:hidden. Лечится не текстом крошки, а соседями: герб на узких
   экранах схлопывается до иконки (см. медиа ниже), а не самой крошкой. */
.crumbs{display:flex;align-items:stretch;height:44px;gap:5px;overflow:hidden;
  font-size:13px;font-weight:500;color:var(--ink-2);min-width:0;flex:1}
.crumb{display:inline-flex;align-items:center;background:none;padding:4px 6px;border-radius:7px;
  white-space:nowrap;color:var(--ink-2);transition:background .15s,color .15s;font-weight:500;
  overflow:hidden;text-overflow:ellipsis;min-width:0;flex-shrink:3;max-width:170px}
.crumb:hover{background:var(--surface);color:var(--ink)}
.crumb.here{color:var(--ink);font-weight:600;flex-shrink:1;max-width:none}
.crumb.root{gap:5px;flex-shrink:0}
/* ⚠️ --ink-3, А НЕ --line. Разделитель крошек был покрашен ТОКЕНОМ РАМКИ: 1.26:1
   к фону — единственная пара ниже AA, которую сторож находил на доске каждый
   прогон (§8 №14 требует ноль). Громче крошек он от этого не становится:
   замерено живьём, --ink-3 #6B675E и --ink-2 #67635A — один и тот же серый,
   то есть «›» встаёт вровень с неактивной крошкой, а не над ней. */
.crumb-sep{align-self:center;color:var(--ink-3);flex:none;font-size:12px}
.iconbtn{height:44px;min-width:44px;padding:0 11px;border-radius:var(--r-btn);background:var(--surface);
  box-shadow:var(--sh-1);display:inline-flex;align-items:center;justify-content:center;gap:6px;
  font-size:13px;font-weight:600;color:var(--ink-2);transition:transform .16s var(--ease),background .2s;flex:none}
.iconbtn:hover{background:var(--surface-2)}
.iconbtn:active{transform:scale(.93)}
.iconbtn svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.iconbtn.primary{background:var(--accent);color:var(--on-accent);position:relative}
.iconbtn.primary:hover{background:var(--accent-hover)}
.iconbtn.primary .hdr-badge{position:absolute;top:-5px;right:-5px;min-width:16px;height:16px;padding:0 4px;
  border-radius:999px;background:var(--st-fire);color:var(--on-accent);font-size:9.5px;font-weight:700;
  display:none;align-items:center;justify-content:center;box-shadow:0 0 0 2px var(--bg)}
.iconbtn.primary .hdr-badge.show{display:flex}
.nt-lbl{display:inline}
@media(max-width:767px){.nt-lbl{display:none}}
/* на самых узких телефонах 4 иконки-кнопки (Помощник/Задача/язык/тема) рядом с гербом
   и крошками физически не помещаются без горизонтального оверфлоу шапки (баг с
   375px) — на такой ширине помощник и так под рукой: круглая кнопка внизу справа
   и пункт «Помощник» в нижней панели никуда не делись, прячем только дубль в шапке */
@media(max-width:400px){#hdrAssistantBtn{display:none}}
/* tasks/shapka-na-390-krosha-i-tach-celi.md: на той же ширине, где иконки шапки
   лишились подписи (.nt-lbl выше), герб схлопывается до одной иконки 44×44 —
   это и есть «сжать соседей, а не текст» из задания: освобождает крошке
   ровно те ~90px, которых ей не хватало на 390 (было 17×25 при 94×25 текста).
   Зазор между элементами шапки тоже уже (10→6), крошке не мешает — у самих
   крошек внутренний gap:5px, разница на глаз не видна.
   Контроль ux 16.08 (та же карточка, «Причина возврата 2»): граница 520 рвёт
   компенсацию раньше, чем перестаёт быть нужна — .iconbtn 38→44 (+10px в
   строку шапки) ломает полосу 521–641 заново (hscroll на 521, обрезка глубже
   на 640). Замер по всей полосе 390–767 показал ту же обрезку до 640px —
   граница сдвинута до 767, чтобы компенсация держала всю полосу целиком. */
@media(max-width:767px){
  .hdr-top{gap:6px}
  .brand{width:44px;gap:0}
  .brand b{display:none}
  /* ⚠️ И КОРЕНЬ КРОШЕК — ТОЖЕ ИКОНКОЙ, по той же причине и на той же ширине.
     Замер сторожа на 375: nav#crumbs коробка 87×44, содержимое 120×44 — резалось
     на 33 px. Виновата корневая крошка: она flex-shrink:0 (иначе на портфель не
     вернуться одним нажатием) и со словом занимала 94 px из 87, отведённых всей
     строке. Текущий шаг при этом ужимался до 12 px — то есть исчезал совсем, а он
     и есть ответ на вопрос «где я». Домик остаётся кнопкой 44×44 с тем же
     действием, имя ей держат title/aria-label. Разделитель сразу за домиком снят:
     между иконкой и первым словом он ничего не разделяет, а контраст у него 1.26
     при норме 4.5 (замер сторожа). Поля крошек ужаты на 2 px — ровно эти пиксели
     и уходят текущему шагу. Глубже второго шага «›» остаются на месте. */
  .crumbs{gap:4px}
  .crumb{padding:4px 4px}
  .crumb.root{width:44px;padding:0;justify-content:center;gap:0}
  .crumb.root .nm{display:none}
  .crumb.root + .crumb-sep{display:none}
  /* ⚠️ ИМЯ — ТОЛЬКО ПОСЛЕДНЕЙ КРОШКЕ. Домик и разделители несжимаемы, и на пути
     «проект › объект › этап» их 74 px (44 домик + два «›» по 5 + пять зазоров по 4)
     при 87 px, отведённых всей строке на 375. Трём именам оставалось 13 px при
     минимуме 8 px на каждое: строка вылезала за край на ~5 px, а все три имени
     превращались в голое многоточие — то есть путь переставал отвечать даже на
     вопрос «где я».
     Средние ступени убраны вместе со своими разделителями: они и так есть на
     экране — проект стоит в переключателе проектов строкой ниже (.pswitch), а
     объект и этап написаны в заголовке экрана («Этап · объект» + h1). Остаётся
     домик и текущий шаг — разделителей на узком экране не остаётся ни одного,
     и весь остаток строки достаётся имени текущего шага.
     Счёт на 375: домик 44 + зазор 4 + крошка 39 = 87 ровно, под имя 39 − 8 полей = 31 px.
     Резаться нечему: сжимаемая крошка на строке ровно одна. */
  .crumbs .crumb:not(.root):not(.here){display:none}
  .crumbs .crumb:not(.root):not(.here) + .crumb-sep{display:none}
  /* Портфель как ТЕКУЩИЙ экран: домик рядом со словом «Портфель» — вторая правда
     об одном и том же, и вдвоём они опять не влезают. Остаётся слово. */
  .crumb.root.here{width:auto;padding:4px 4px}
  .crumb.root.here svg{display:none}
  .crumb.root.here .nm{display:inline}
}
.hdr-bottom{display:flex;align-items:center;gap:9px;min-width:0}
/* 44, а не 34: §3 — тач-цель любого нажимаемого элемента 44×44. Строка шапки от
   этого не растёт, в ней уже стоит переключатель проектов той же высоты. */
.backbtn{height:44px;padding:0 12px 0 9px;border-radius:var(--r-btn);background:var(--surface);
  box-shadow:var(--sh-1);display:inline-flex;align-items:center;gap:5px;font-size:13px;font-weight:600;
  color:var(--ink);flex:none;transition:transform .16s var(--ease)}
.backbtn:active{transform:scale(.94)}
.backbtn svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
.backbtn[hidden]{display:none}

/* переключатель проектов */
.pswitch{position:relative}
.pswitch .cur{height:44px;padding:0 11px;border-radius:var(--r-btn);background:var(--surface);
  box-shadow:var(--sh-1);display:inline-flex;align-items:center;gap:7px;font-size:13px;font-weight:600;max-width:230px}
.pswitch .cur .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pswitch .cur svg{width:15px;height:15px;stroke:var(--ink-2);fill:none;stroke-width:2;flex:none}
.pmenu{position:absolute;top:calc(100% + 6px);left:0;z-index:var(--z-pmenu);min-width:250px;background:var(--surface);
  border:1px solid var(--line);border-radius:14px;box-shadow:var(--sh-3);padding:6px;display:none}
.pmenu.open{display:block;animation:pop .16s var(--ease)}
.pmenu button{width:100%;text-align:left;padding:9px 11px;border-radius:9px;display:flex;align-items:center;gap:9px;
  font-size:14px;font-weight:500;transition:background .14s}
.pmenu button:hover{background:var(--surface-2)}
.pmenu button.on{color:var(--accent);font-weight:600}
.pmenu .sep{height:1px;background:var(--line);margin:6px 4px}
.pmenu .add{color:var(--accent);font-weight:600}
@keyframes pop{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}

/* ═════════════ LAYOUT ═════════════ */
.shell{display:flex;align-items:flex-start;max-width:var(--shell-w);margin:0 auto}
/* Правка владельца 9 августа: «панель прыгает не на свободное место, а двигает
   всё остальное». Ширина рабочего поля НЕ ЗАВИСИТ от панели — ни одного правила
   вида «.side.open + .wrap» здесь больше нет и быть не должно. Панель вынесена
   из потока (position:fixed, см. блок «БОКОВАЯ ПАНЕЛЬ»), поэтому доска стоит на
   месте: left и width у .wrap совпадают до пикселя, открыта панель или закрыта. */
.wrap{flex:1;min-width:0;margin:0 auto;padding:var(--s4) var(--s4) var(--s6)}
.screen{animation:enter .22s var(--ease)}
.screen.back{animation:enterBack .22s var(--ease)}
@keyframes enter{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes enterBack{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
.screen-head{display:flex;align-items:flex-end;gap:var(--s3);flex-wrap:wrap;margin-bottom:var(--s3)}
.screen-head .tt{min-width:0}
.eyebrow{font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-2);margin-bottom:4px;display:flex;align-items:center;gap:7px}
.badge-over{font-size:10px;font-weight:600;letter-spacing:.06em;color:var(--accent);
  background:var(--accent-soft);padding:2px 7px;border-radius:6px;text-transform:none}
h1.scr{font-size:25px;font-weight:600;letter-spacing:-.01em;margin:0;line-height:1.15}
.screen-head .act{margin-left:auto;display:flex;gap:var(--s2);flex-wrap:wrap}
/* ═══ СВОБОДНАЯ СЕРЕДИНА ШАПКИ ЭКРАНА ═══
   Владелец 31.08: «задействовать свободную центральную часть верхней панели».
   Слева имя экрана, справа кнопки, между ними на 1440 пустовало ~600 px — туда
   уехали вкладки проекта, и своя строка в 66 px им больше не нужна. Три поля
   auto (слева от середины, справа от неё и у .act) делят свободное место, так
   что середина стоит посередине, а не прижата к кнопкам.
   На узком экране .screen-head переносит середину на свою строку — там ей
   отдаётся вся ширина: три слова вкладок иначе не встают в ряд. */
.screen-head .hcentr{margin-inline:auto;min-width:0}
@media(max-width:900px){
  .screen-head .hcentr{width:100%;margin:0}
  .screen-head .hcentr .seg{width:100%}
}

/* ═══ ПОЛОСА УПРАВЛЕНИЯ ДОСКИ (.screen-head.upr) ═══
   Один ряд органов управления, высота --h-row у самой полосы и у каждого её
   ребёнка. Порядок слотов закреплён и не меняется никогда:
     [вкладки проекта] [вид: Доска·Таймлайн·Список] ←распорка→ [План·N] [.act]
   Полоса НЕ растёт от содержимого. auto-полей внутри нет: margin-left:auto в
   переносящейся полосе прижимает элемент к краю СВОЕЙ НОВОЙ СТРОКИ и рвёт ряд —
   его место заняла распорка .rast (flex:1), которая схлопывается в ноль.
   ⚠️ Блок стоит ПОСЛЕ медиа-запроса выше намеренно: у .upr .hcentr и
   .screen-head .hcentr одинаковая специфичность (0,2,0), и написанный раньше
   margin-inline:auto утащил бы вкладки обратно в середину. */
.screen-head.upr{align-items:center;gap:var(--s3);row-gap:var(--s3);margin-bottom:var(--s3)}
.screen-head.upr>*{min-height:var(--h-row)}
.screen-head.upr .hcentr{margin:0}
.screen-head.upr .act{margin-left:0;gap:var(--s2);flex-wrap:nowrap}
/* ⚠️ ПОДПИСЬ В ЭТОЙ ПОЛОСЕ НЕ ПЕРЕНОСИТСЯ. У .btn высота 44 ЖЁСТКАЯ, а перенос
   строки внутри кнопки высоту не двигает — вторая строка просто вылезает из
   коробки. Пока у .act был flex-wrap:wrap, длинная пара кнопок расходилась на
   два ряда и брак не показывался; с nowrap рядом он вылез сразу: на экране
   объекта «Удалить объект» + «Задача на объект» = 162 + 8 + 174 = 344 при 343
   доступных на 375 (Segoe UI Semibold 14/600; на Inter контроль намерил 352).
   Поэтому подписи в полосе НЕ переносим, а держим их короткими — «Задача»
   вместо «Задача на объект»: экран и так называется «ОБЪЕКТ · <имя>», слово
   «объект» в кнопке повторяет заголовок. После правки RU 162+8+105 = 275,
   ID 138+8+97 = 243 — влезает и на 375 (343), и на 360 (328). */
.screen-head.upr .act .btn{white-space:nowrap}
.rast{flex:1 1 0;min-width:0;align-self:stretch}
/* раскладка плана — не телефонная работа: на узком экране кнопка уходит,
   действие остаётся доступным с компьютера (§7 «мёртвых кнопок нет» не
   нарушается: кнопка не молчит, её просто нет там, где ей нечего делать) */
@media(max-width:759px){.screen-head.upr .pk-desk{display:none}}

.btn{height:44px;padding:0 17px;border-radius:var(--r-btn);font-size:14px;font-weight:600;
  display:inline-flex;align-items:center;gap:8px;transition:transform .16s var(--ease),background .2s,box-shadow .2s}
.btn:active{transform:scale(.96)}
.btn svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
.btn.primary{background:var(--accent);color:var(--on-accent);box-shadow:var(--sh-2)}
.btn.primary:hover{background:var(--accent-hover)}
.btn.ghost{background:var(--surface);color:var(--ink);box-shadow:var(--sh-1)}
.btn.ghost:hover{background:var(--surface-2)}
.btn.danger{background:var(--st-fire-bg);color:var(--st-fire)}

/* сегмент-контрол */
/* ⚠️ padding:0, А НЕ 3. Три пикселя поля превращали сегмент в орган высотой 50
   при кнопке 44 — и это был ЕДИНСТВЕННЫЙ источник разнобоя полос управления
   (50 против 44) сразу на шести экранах. Дорожка никуда не делась: фон
   --surface-2 и внутренняя тень остались, активная кнопка светлее дорожки.
   Тач-цель не тронута — кнопка как была 44.
   БОКОВОЕ ПОЛЕ 12 (--s3), А НЕ 13: тринадцати в шкале отступов нет (§3, шкала
   4/8/12/16/24). Счёт перед правкой (Segoe UI Semibold 13/600): переключатель
   вида RU 286 → 280, ID 269 → 263 — только уже, ничего не рвёт; самая узкая
   кнопка на платформе «Всё» в архиве 46.9 → 44.9, тач-цель §3 (≥44) держит. */
.seg{display:inline-flex;background:var(--surface-2);border-radius:var(--r-btn);padding:0;box-shadow:var(--sh-1) inset;gap:0}
.seg button{height:var(--h-row);padding:0 var(--s3);border-radius:var(--r-btn);font-size:13px;font-weight:600;color:var(--ink-2);transition:.15s}
.seg button.on{background:var(--surface);color:var(--ink);box-shadow:var(--sh-1)}

/* ПЕРЕКЛЮЧАТЕЛЬ ВИДА ДОСКИ (Доска · Таймлайн · Список) — разметка uiVidSeg.
   На широком экране это слова, как и было. На телефоне (тот же порог 700, что
   у ряда чипов «Моего») слова уходят и остаются значки: полоса из трёх слов
   вставала на 375 отдельной строкой в 58 px и опускала первую колонку доски
   с 434 на 492 — замер живой, getBoundingClientRect. Подпись не пропадает: она
   остаётся в aria-label и title парой RU/ID из словаря (§5).
   ТАЧ-ЦЕЛЬ НЕ ТРОГАЕМ: min-width наравне с height 44 — от кнопки-значка
   остаётся ровно 44×44 (§3), как у .mfnotesb рядом. */
.segvid button{display:inline-flex;align-items:center;justify-content:center;gap:6px}
.segvid .vsi{display:none;align-items:center}
.segvid button svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round}
@media(max-width:700px){
  .segvid button{min-width:44px;padding:0 8px}
  .segvid .vsi{display:inline-flex}
  .segvid .vsl{display:none}
}

/* ═════════════ ПОЛОСА-СВОДКА (портфель / проект) ═════════════ */
.summary{display:flex;flex-wrap:wrap;align-items:center;gap:12px 26px;background:var(--surface);
  border-radius:var(--r-card);box-shadow:var(--sh-2);padding:16px 20px;margin-bottom:20px}
.summary .mt{display:flex;flex-direction:column;gap:2px}
.summary .mt .v{font-size:23px;line-height:1}
.summary .mt .l{font-size:12px;font-weight:500;color:var(--ink-2)}
.summary .mt.fire .v{color:var(--st-fire)}
.summary .ai{margin-left:auto;max-width:420px;display:flex;align-items:center;gap:11px;
  background:var(--accent-soft);border-radius:12px;padding:10px 14px;cursor:pointer;transition:transform .16s var(--ease)}
.summary .ai:hover{transform:translateY(-1px)}
.summary .ai .k{width:30px;height:30px;border-radius:8px;background:var(--accent);color:var(--on-accent);display:grid;place-items:center;font-weight:600;font-size:12px;flex:none}
.summary .ai .tx{font-size:12.5px;color:var(--ink);line-height:1.35;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.summary .ai .tx b{color:var(--accent);font-weight:600}

/* ═════════════ СЕТКА КАРТОЧЕК ═════════════ */
.grid{display:grid;gap:16px;grid-template-columns:1fr}
@media(min-width:640px){.grid{grid-template-columns:repeat(2,1fr)}}
@media(min-width:980px){.grid.cols3{grid-template-columns:repeat(3,1fr)}}
/* grid-item по умолчанию min-width:auto — не даёт треку сжаться уже контента (нельзя
   перенести строку типа «до 2026-07-26 · Fallen & Darto»), из-за этого на 375px
   карточка вылезала за край экрана (баг тестировщиков). Явный min-width:0 чинит трек. */
.grid > *{min-width:0}

/* совмещение «статус + просрочено»: точка остаётся СВОЕГО статусного цвета,
   терракота приходит кольцом снаружи. Два факта — два носителя (§1.4) */
.sdot.od, .health .dot.od, .obj-row .dot.od, .pfolder-h .dot.od{box-shadow:0 0 0 2px var(--alarm-line)}

/* прогресс-кольцо */
.ring{position:relative;display:grid;place-items:center}
.ring svg{transform:rotate(-90deg)}
.ring .pct{position:absolute;font-variant-numeric:tabular-nums;font-weight:600;color:var(--ink)}

/* ТЗ 5.6: min-height 44 — тач-цель по закону стиля (было 34, брак) */
.fchip{min-height:44px;padding:0 14px;border-radius:999px;background:var(--surface);box-shadow:var(--sh-1);
  font-size:13px;font-weight:600;color:var(--ink-2);display:inline-flex;align-items:center;gap:6px;transition:.15s}
.fchip:hover{background:var(--surface-2)}
.fchip.on{background:var(--accent);color:var(--on-accent)}
/* ⚠️ height:44, А НЕ 22. Выпадашка сидела в чипе высотой 44, а нажималась
   только своими 22 — сторож считал это тремя промахами §3 на каждом прогоне
   доски, и палец на телефоне промахивался мимо середины чипа. Чип от этого не
   растёт: у .fchip нет вертикального поля, а align-items:center держит строку. */
.fchip select{background:none;border:none;font-weight:600;color:inherit;outline:none;cursor:pointer;
  max-width:150px;height:var(--h-row,44px)}
.fchip.on select{color:var(--on-accent)}
.fchip select option{color:var(--ink);background:var(--surface)}

/* ── ПОЛОСА «НОВОЕ»: платформа сама говорит, что пришло, без F5 ── */
.newsbar{position:fixed;left:50%;transform:translateX(-50%) translateY(-14px);
  top:calc(env(safe-area-inset-top,0px) + 12px);z-index:80;display:none;align-items:center;gap:12px;
  padding:11px 14px;border-radius:14px;background:var(--surface);box-shadow:var(--sh-3);
  border:1px solid var(--accent);max-width:calc(100vw - 24px);opacity:0;
  transition:opacity .25s var(--ease),transform .25s var(--ease)}
.newsbar.show{display:flex;opacity:1;transform:translateX(-50%) translateY(0)}
/* ⚠️ ПУЛЬСА ЗДЕСЬ БЫТЬ НЕ МОЖЕТ. Точка мигала бесконечно (1 → .35 каждые
   1.6 с) — регламент §8 запрещает мигающее прямо, а сторож вёрстки из-за
   бесконечной анимации объявлял весь замер экрана недостоверным. Полоса
   заметна и без пульса: она всплывает поверх экрана и обведена акцентом. */
.newsbar .dot{width:9px;height:9px;border-radius:50%;background:var(--accent);flex:none}
/* ⚠️ ДВЕ СТРОКИ, А НЕ ОДНА. «Вам поручили N» — это про МЕНЯ, а «новых задач: N» —
   про всю платформу; склеенные через « · » в одну строку они на 375 обрезались бы
   многоточием ровно на личной половине. Владелец просил отклик, а не тишину. */
.newsbar .txs{display:flex;flex-direction:column;gap:2px;min-width:0}
.newsbar .tx{font-size:13.5px;font-weight:600;color:var(--ink);min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.newsbar .tx.mine{color:var(--accent);font-weight:700}

/* ── ТОЧКА «НОВОЕ» перед названием: доска, список, таймлайн ──
   Один и тот же признак на трёх экранах (см. tochkaNovoe, obshee.vid.js).
   Не кликается и ничего не заслоняет: стоит В ПОТОКЕ перед именем, а не поверх.
   Цвет — существующий --accent, новых в проекте не заводят. */
.novoe-tochka{display:inline-block;flex:none;width:7px;height:7px;border-radius:50%;
  background:var(--accent);margin-right:6px;vertical-align:middle}
.newsbar button{min-height:40px;padding:0 13px;border-radius:11px;font-weight:600;font-size:13px;white-space:nowrap}

.pickbar{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(env(safe-area-inset-bottom,0px) + 84px);
  z-index:70;display:none;align-items:center;gap:12px;padding:11px 14px;border-radius:14px;
  background:var(--surface);box-shadow:var(--sh-3);border:1px solid var(--line);max-width:calc(100vw - 24px)}
.pickbar.show{display:flex}
.pickbar .cnt{font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
.pickbar button{min-height:44px;padding:0 14px;border-radius:11px;font-weight:600;font-size:13.5px;white-space:nowrap}

/* ═════════════ ТЕГИ ═════════════ */
.tags{display:flex;gap:4px;flex-wrap:wrap;margin-top:7px}
.tag{font-size:10.5px;font-weight:600;padding:2px 8px;border-radius:999px;background:var(--surface-2);
  color:var(--ink-2);cursor:pointer;transition:background .14s,color .14s;line-height:1.5}
.tag:hover{background:var(--accent-soft);color:var(--accent)}
.tag.on{background:var(--accent);color:var(--on-accent)}
.kv .tags{margin-top:0}

/* пустое состояние */
.empty{text-align:center;padding:48px 20px;background:var(--surface);border-radius:var(--r-card);box-shadow:var(--sh-1)}
.empty .em-ic{width:54px;height:54px;border-radius:16px;background:var(--accent-soft);color:var(--accent);
  display:grid;place-items:center;margin:0 auto 14px}
.empty .em-ic svg{width:26px;height:26px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.empty h3{font-size:17px;font-weight:600;margin:0 0 6px}
.empty p{color:var(--ink-2);font-size:14px;margin:0 0 18px;max-width:340px;margin-inline:auto}

/* --s5 (24), А НЕ --s6 (32): на бою здесь 26, а по правилу шкалы «к ближайшему»
   26 округляется к 24, не к 32. Округлили не в ту сторону — заголовок раздела
   отъедал по 8 px сверху на каждом разделе экрана. */
.section-t{font-size:13px;font-weight:600;letter-spacing:.02em;color:var(--ink-2);margin:var(--s5) 0 var(--s3);
  display:flex;align-items:center;gap:8px}
.section-t .n{font-variant-numeric:tabular-nums;color:var(--ink-2);font-weight:600}

.two-col{display:grid;gap:16px;grid-template-columns:1fr}
/* открыта карточка задачи внутри двухколоночного экрана: колонки складываются
   в ОДНУ и утекают вниз — карточке вся ширина (просьба владельца: «должны
   полностью обтекать и утекать вниз, по бокам не хватает места») */
.two-col.cardopen{grid-template-columns:1fr !important}
.grid.cardopen{grid-template-columns:1fr !important}
@media(min-width:920px){.two-col{grid-template-columns:1.4fr 1fr}}
.two-col > *{min-width:0}

/* ═════════════ БОКОВАЯ ПАНЕЛЬ (навигация-дублёр «Проекты слева») ═════════════
   ДОБАВЛЕНА рядом со старым .pswitch (шапка), ничего из него не убрано.
   Источник истины — тот же State.projectId/State.view, что и у .pswitch,
   поэтому оба способа навигации всегда показывают один и тот же выбор. */
/* ТЗ 5.1 (карточка 697): бургер виден на ВСЕХ ширинах — панель по умолчанию
   скрыта везде, и без бургера её было бы не открыть на компьютере */
.burger{display:inline-flex;height:38px;width:38px;border-radius:var(--r-btn);background:var(--surface);
  box-shadow:var(--sh-1);align-items:center;justify-content:center;flex:none;min-width:44px;min-height:44px}
.burger svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round}
/* ═══ БОКОВАЯ ПАНЕЛЬ — правки владельца 9 августа (четыре захода подряд) ═══
   Дословно и по пунктам, чтобы следующий не сломал заново:

   1) «панель прыгает не на свободное место, а двигает всё остальное»,
      «ОСТАВЬ ДОСКУ В ПОКОЕ, оставь остальные поля» →
      ⚠️ ЖЕЛЕЗНЫЙ ЗАПРЕТ: ради панели НЕ ТРОГАЕМ .shell / .wrap / .board / .col —
      ни max-width, ни padding, ни margin, ни резервирования полосы. Панель
      вынесена из потока (position:fixed), поэтому сдвинуть доску ей физически
      нечем. Правил вида «.side.open + .wrap{…}» тут нет и быть не должно.
      Проверяется замером: left/width у .wrap и всех .col совпадают до пикселя
      при открытой и закрытой панели.
   2) «анимацию без выебонов, без выездов… нажал — появилась, нажал — исчезла» →
      transition:none. Ничего не едет и не тает: мгновенно.
   3) «появились полосы, показывающие сетку» → ни border, ни outline. Это была
      border-right: при width:0 от панели оставалась ровно рамка — вертикальная
      линия 1px во всю высоту экрана. Разделителя-линии нет вовсе.
   4) «не должно выглядеть как окно чуть поверх… до сих пор чуть заступает
      краем чёрного окна… фон тёмный и как будто сверху этот фон» → на широком
      экране (см. @media ниже) панель вписана в свободное поле СЛЕВА ОТ ДОСКИ,
      не заходит на неё ни на пиксель, и у неё нет ни своего фона, ни тени.

   visibility, а не только opacity: закрытая панель не должна ловить щелчки и
   попадать в Tab (внутри неё <input> поиска). Видимого следа она не оставляет.

   Это правило — узкий экран (шторка поверх, с затемнением .scrim2, закрывается
   тапом мимо и сама после перехода). На широком его перекрывает @media ниже. */
.side{position:fixed;top:var(--hdr-h);left:0;z-index:var(--z-side);
  width:min(300px,84vw);height:calc(100dvh - var(--hdr-h));max-height:none;
  background:var(--bg);
  box-shadow:none;border:0;                 /* п.2 и п.3: ни тени-«окна», ни полос */
  /* contain ОСТАЁТСЯ: это шторка ПОВЕРХ экрана (fixed, с затемнением .scrim2,
     закрывается тапом мимо). Под ней лежит чужой экран — докрутив список
     проектов, палец не должен уезжать в доску за спиной панели. */
  overflow-y:auto;overscroll-behavior:contain;
  padding:14px 10px 90px 12px;
  transition:none;                          /* п.2: никакой анимации, нигде */
  opacity:0;visibility:hidden}
.side.open{opacity:1;visibility:visible}

/* ═══ ШИРОКИЙ ЭКРАН: панель живёт В ПОЛЕ СТРАНИЦЫ, доска не шевелится ═══
   «У нас есть сбоку место — в него и впиши!», «место есть сбоку — до самого
   конца экрана».  Это поле — отступ центрирования .shell плюс левый padding
   .wrap (16px, ровно до первой колонки):

       свободное поле = (ширина окна − --shell-w)/2 + 16px

   Панель занимает РОВНО его и не больше --side-w. Ширина считается, а не
   задаётся руками, поэтому правый край панели ≤ левого края первой колонки
   ВСЕГДА, при любой ширине окна — «заступить краем» ей нечем.
   50% у fixed считается от окна БЕЗ полосы прокрутки — от того же, от чего
   .shell центрируется через margin:auto, поэтому края сходятся точно.
   Замер 9.08 на экране владельца (1920, clientWidth 1911):
       левый край первой колонки 259.5 · правый край панели 259.5 · перекрытие 0.

   Порог 1792px = --shell-w 1424 + 2×(200−16): это самое узкое окно, где в поле
   помещается хотя бы 200px панели (владелец разрешил сузить до 200–220).
   Ниже порога поля физически нет (на 1440px — 19.5px, полоска), и панель
   работает шторкой по правилу выше: накрыть доску или сузить её выбора нет,
   а двигать доску запрещено. Подробности — в отчёте. */
@media (min-width:1792px){
  .side{width:min(var(--side-w), calc(50% - var(--shell-w)/2 + 16px));
    /* часть страницы, а не всплывшее окно: своей плашки-фона нет */
    background:transparent}
  .scrim2{display:none!important}   /* нечего затемнять: панель ничего не накрывает */
}
.side-search{position:relative;margin:0 0 10px}
.side-search input{width:100%;height:44px;border-radius:999px;border:1px solid var(--line);
  background:var(--surface);padding:0 14px 0 36px;box-shadow:var(--sh-1);outline:none}
.side-search input:focus{border-color:var(--accent)}
.side-search svg{position:absolute;left:12px;top:14px;width:16px;height:16px;stroke:var(--ink-2);fill:none;stroke-width:2;pointer-events:none}
.side-home{display:flex;align-items:center;gap:10px;padding:11px 10px;min-height:44px;border-radius:11px;font-weight:600;
  color:var(--ink);margin-bottom:6px;width:100%;text-align:left;transition:background .15s}
.side-home svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;flex:none}
.side-home.on,.side-home:hover{background:var(--accent-soft);color:var(--accent)}
.side-sec-t{font-size:11px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--ink-2);
  padding:14px 10px 6px;display:flex;align-items:center;gap:6px}
.side-sec-t .n{font-weight:600;font-variant-numeric:tabular-nums}
.pfolder{border-radius:12px;margin-bottom:2px}
/* Строка проекта разделена на две кнопки (просьба владельца): левая (.pf-nav)
   переносит в проект, правая стрелка (.pf-chev) только раскрывает список. */
.pfolder-h{display:flex;align-items:center;width:100%;min-height:44px;border-radius:11px;
  text-align:left;transition:background .15s}
.pfolder-h:hover{background:var(--surface)}
.pf-nav{flex:1;min-width:0;display:flex;align-items:center;gap:9px;padding:10px 4px 10px 10px;
  min-height:44px;border-radius:11px 0 0 11px;text-align:left;background:transparent;color:inherit;font:inherit}
.pf-chev{flex:none;width:44px;min-height:44px;display:grid;place-items:center;border-radius:0 11px 11px 0;
  background:transparent;color:var(--ink-2)}   /* 44px — тач-цель по регламенту (§3) */
.pf-chev:hover{background:var(--surface-2);color:var(--accent)}
.pfolder.open>.pfolder-h{background:var(--accent-soft);color:var(--accent);font-weight:700}
.pfolder.active>.pfolder-h{box-shadow:inset 3px 0 0 var(--accent)}
.pfolder-h .fic{flex:none;width:18px;height:18px;color:var(--ink-2)}
.pfolder-h .fic svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.pfolder.open>.pfolder-h .fic{color:var(--accent)}
.pfolder-h .ring{flex:none}
.pfolder-h .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13.5px;font-weight:600}
.pfolder-h .dot{width:7px;height:7px;border-radius:50%;flex:none}
.pfolder-h .chev{flex:none;width:14px;height:14px;color:var(--ink-2);transition:transform .18s var(--ease)}
.pfolder-h .chev svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
.pfolder.open>.pfolder-h .chev{transform:rotate(90deg)}
.pfolder-body{max-height:0;overflow:hidden;transition:max-height .22s var(--ease)}
.pfolder.open>.pfolder-body{max-height:600px}
.obj-row{display:flex;align-items:center;gap:8px;width:100%;text-align:left;padding:9px 8px 9px 36px;min-height:44px;
  border-radius:9px;font-size:13px;color:var(--ink-2)}
.obj-row:hover{background:var(--surface);color:var(--ink)}
.obj-row.on{background:var(--surface-2);color:var(--ink);font-weight:600}
.obj-row .dot{width:6px;height:6px;border-radius:50%;flex:none}
.obj-row .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.obj-row .cc{margin-left:auto;font-size:11px;color:var(--ink-2);font-variant-numeric:tabular-nums}
.obj-row .cc.fire{color:var(--st-fire);font-weight:700}
.side-flat{display:flex;align-items:center;gap:9px;width:100%;text-align:left;padding:10px;min-height:44px;border-radius:10px;
  font-size:13.5px;font-weight:600;color:var(--ink-2)}
.side-flat:hover{background:var(--surface);color:var(--ink)}
.side-flat svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;flex:none}
.side-flat .chev{margin-left:auto;color:var(--ink-2);transition:transform .18s var(--ease)}
.side-empty{padding:8px 10px;color:var(--ink-2);font-size:12.5px}
/* затемнение под шторкой на узком экране — тап мимо закрывает.
   top:var(--hdr-h) — шапку не затемняем и не перекрываем: бургер остаётся
   виден и нажимаем, им же панель и закрывают.
   transition:none — «никакой анимации» (владелец, 9 августа) относится и к
   затемнению: гасло 200 мс и читалось как «окно уезжает». На широком экране
   затемнения нет вовсе, см. @media (min-width:1792px) выше. */
.scrim2{position:fixed;top:var(--hdr-h);left:0;right:0;bottom:0;background:rgba(20,18,14,.38);z-index:var(--z-side-scrim);opacity:0;pointer-events:none;transition:none}
.scrim2.on{opacity:1;pointer-events:auto}

/* НА НИЗКОМ ЭКРАНЕ ПОЛОСА ДОСКИ ПОД КАРТОЧКОЙ ВДВОЕ УЖЕ.
   48 px — это 9 % экрана в 533 px и всего 4 % в 900. Замер 01.09 на карточке в
   28 реплик: при зазоре 48 чату на 911×512 доставалось 137 px = 47,8 % окна,
   ниже порога §6.2; при 24 — 164 px = 52,7 %. Полоса доски при этом видна и
   там, и там: «карточка лежит НА доске» читается с 24 px не хуже. */
@media(max-height:699px){ :root{--kartochka-zazor:24px} }

/* ═════════════ НИЖНЯЯ НАВИГАЦИЯ (mobile) ═════════════ */
.botnav{position:fixed;left:0;right:0;bottom:0;z-index:var(--z-botnav);height:calc(var(--nav-h) + env(safe-area-inset-bottom));
  padding-bottom:env(safe-area-inset-bottom);background:color-mix(in srgb,var(--bg) 90%,transparent);
  backdrop-filter:blur(12px);border-top:1px solid var(--line);display:flex;
  /* фикс «панель уезжает при скролле на мобильном» (подтверждено двумя тестировщиками):
     принудительный GPU-слой держит position:fixed стабильной на iOS/старом Android во время инерционного скролла */
  transform:translateZ(0);-webkit-transform:translateZ(0);backface-visibility:hidden;will-change:transform}
.botnav button{flex:1 1 0;min-width:44px;min-height:44px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  color:var(--ink-2);font-size:10.5px;font-weight:600;transition:color .15s;position:relative}
.botnav button span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.botnav button svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.botnav button.on{color:var(--accent)}
.botnav button .over-b{position:absolute;top:7px;right:calc(50% - 22px);min-width:16px;height:16px;padding:0 4px;
  background:var(--st-fire);color:var(--on-accent);border-radius:9px;font-size:10px;font-weight:600;display:grid;place-items:center;font-variant-numeric:tabular-nums}
/* ПОЛОСА НЕ УЖЕ СВОЕГО СОДЕРЖИМОГО (WCAG 2.2 SC 1.4.4 / 1.4.10).
   Было `max-width:520px`. У Создателя внизу одиннадцать пунктов, содержимое
   полосы просит 728 px, а потолок 520 делил их поровну (`flex:1 1 0` из общего
   правила выше) на 11 кнопок по 47 px. Коробка подписи выходила 35.3 px при
   нужных 38–77.5 — многоточием обрезало 8 подписей из 11 по-русски и 7 из 11
   по-индонезийски. Замер 03.09.2026, localhost, окно 1280×800. Обрезанная
   подпись — потеря содержания, а не украшение.
   На телефоне (screens.css, @media max-width:759px) этой беды нет, и лечим мы
   ровно тем же приёмом, каким там: кнопка берёт СВОЮ ширину (`flex:1 0 auto`,
   пол 62 px), а полоса прокручивается ВНУТРИ себя. Кнопки не сужаем — §3
   регламента и SC 2.5.8 (44×44); расширяем полосу: потолок 820 px при
   содержимом 728. Запас 92 px раздаётся кнопкам поровну (flex-grow), и самой
   тесной подписи («Портфель» / «Portofolio») остаётся 13.6 px сверх её ширины
   по-русски и 20.0 px по-индонезийски (замер 03.09.2026, окно 1280×800,
   одиннадцать пунктов). Что не влезло — уезжает в прокрутку самой полосы,
   страница горизонтально не растёт (§10). Потолок 760–820 px — та же прокрутка.
   Края-подсказки продублированы здесь намеренно: правила kray-l/kray-r в
   screens.css заперты в телефонный медиазапрос, а классы им ставит botnavKrai()
   на любой ширине. Без этих трёх строк на 760–800 px за краем молча прятались
   бы кнопки. */
@media(min-width:760px){
  .botnav{max-width:min(100%,820px);margin:0 auto;border-radius:16px 16px 0 0;
    overflow-x:auto;overflow-y:hidden;scrollbar-width:none}
  .botnav::-webkit-scrollbar{display:none}
  .botnav button{flex:1 0 auto;min-width:62px;padding:0 6px}
  .botnav.kray-r::after,.botnav.kray-l::before{content:"";position:fixed;top:0;bottom:0;
    width:26px;pointer-events:none;z-index:1}
  .botnav.kray-r::after{right:0;background:linear-gradient(to left,var(--bg),transparent)}
  .botnav.kray-l::before{left:0;background:linear-gradient(to right,var(--bg),transparent)}
}

/* ═════════════ ОТПРАВКА ИДЁТ: КНОПКА ПОГАШЕНА ═════════════
   pointer-events:none обязателен вдобавок к disabled — на тач-экране второй тык
   успевает уйти в DOM до того, как атрибут применится к отрисовке. */
button.sending{opacity:.45;pointer-events:none;cursor:default}

/* ═════════════ TOAST ═════════════ */
.toast-wrap{position:fixed;left:0;right:0;bottom:calc(var(--nav-h) + 16px);z-index:var(--z-toast);display:flex;flex-direction:column;align-items:center;gap:8px;pointer-events:none}
.toast{background:var(--accent);color:var(--on-accent);padding:11px 18px;border-radius:12px;box-shadow:var(--sh-3);
  font-size:13.5px;font-weight:500;max-width:90vw;animation:toastIn .22s var(--ease)}
.toast.warn{background:var(--st-fire)}
@keyframes toastIn{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}

/* skeleton */
.skel{background:var(--surface);border-radius:var(--r-card);box-shadow:var(--sh-1);height:118px;position:relative;overflow:hidden}
.skel::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,transparent,var(--surface-2),transparent);animation:sh 1.2s infinite}
@keyframes sh{from{transform:translateX(-100%)}to{transform:translateX(100%)}}

/* Крутилка показывается НЕ СРАЗУ: данные приходят примерно за 400 мс, и если
   мигнуть спиннером на долю секунды — это и читается как «страница мигает».
   Держим её невидимой первые 350 мс: успели загрузиться — человек её не увидел
   вовсе, не успели — она мягко проявится. */
.spin{width:26px;height:26px;border:3px solid var(--line);border-top-color:var(--accent);border-radius:50%;animation:spin .7s linear infinite, spinShow .25s ease-out .35s both;margin:40px auto}
@keyframes spinShow{from{opacity:0}to{opacity:1}}
/* контент проявляется, а не выпрыгивает */
#screen.fresh{animation:screenIn .18s ease-out both}
@keyframes screenIn{from{opacity:.35}to{opacity:1}}
@media(prefers-reduced-motion:reduce){.spin{animation:spin .7s linear infinite}#screen.fresh{animation:none}}
@keyframes spin{to{transform:rotate(360deg)}}

/* ═════════════ FAB + ЧАТ-ПАНЕЛЬ ПОМОЩНИКА ═════════════ */
.fab{position:fixed;right:16px;bottom:calc(var(--nav-h) + env(safe-area-inset-bottom) + 14px);z-index:var(--z-fab);
  width:56px;height:56px;border-radius:18px;background:var(--accent);color:var(--on-accent);box-shadow:var(--sh-3);
  display:grid;place-items:center;transition:transform .2s var(--ease),background .2s,opacity .2s}
.fab:hover{background:var(--accent-hover)}
.fab:active{transform:scale(.92)}
.fab svg{width:26px;height:26px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.fab .fab-badge{position:absolute;top:-4px;right:-4px;min-width:20px;height:20px;padding:0 5px;background:var(--st-fire);
  color:var(--on-accent);border-radius:11px;font-size:11px;font-weight:600;place-items:center;font-variant-numeric:tabular-nums;
  box-shadow:var(--sh-1);display:none}
.fab .fab-badge.show{display:grid}
.fab.hidden{transform:scale(0);opacity:0;pointer-events:none}
@media(min-width:760px){.fab{right:24px;bottom:24px}}
/* ПОКА ОТКРЫТА КАРТОЧКА-ОКНО, КРУЖОК ПОМОЩНИКА УБИРАЕТСЯ.
   Замер 01.09 до правки: «+» (56×56, fixed, слой 46) лежал на правом нижнем
   углу композера — 37×44 на 375, 45×20 на 853 и 45×56 на открытом листе сдачи;
   палец попадал в помощника вместо «Отправить». Двигать некуда: полоса ответа
   занимает всю ширину внизу окна, любое смещение кладёт кружок на переписку, а
   привязка «спрячем только там, где не влезает» держалась бы на арифметике
   `зазор ≥ 90 − nav`, то есть ломалась бы от любой правки зазора.
   display:none, а не прежний приём .fab.hidden (scale(0)+opacity:0): тот
   оставляет коробку 56×56 в раскладке и на замере, и сторож вёрстки видел бы
   наложение там, где глазом чисто.
   Это не «убрали возможность» (§7): помощник и его счётчик возвращаются тем же
   касанием, которым карточку сворачивают — крестик в шапке карточки закреплён и
   виден всегда, «Свернуть» лежит внизу. А внутри самой карточки живёт её
   собственный чат: два поля ввода в одном углу экрана — это столкновение двух
   разговоров, а не доступность. */
body.kartochka-otkryta .fab{display:none}

.chatpanel{position:fixed;z-index:var(--z-chat);background:var(--surface);box-shadow:var(--sh-3);display:flex;flex-direction:column;
  transition:transform .26s var(--ease)}
.chatpanel{top:0;right:0;height:100%;width:min(420px,96vw);border-radius:var(--r-drawer) 0 0 var(--r-drawer);transform:translateX(105%)}
.chatpanel.open{transform:none}
@media(max-width:759px){
  .chatpanel{top:auto;bottom:0;left:0;right:0;width:100%;height:85vh;
    border-radius:var(--r-drawer) var(--r-drawer) 0 0;transform:translateY(105%)}
  .chatpanel.open{transform:none}
}
/* подложка чата — своя, между .drawer(80) и .chatpanel(84), чтобы чат можно
   было открыть поверх уже открытой задачи, не теряя и не пряча её панель */
#chatScrim{z-index:var(--z-chat-scrim)}
.chat-h{display:flex;align-items:center;gap:11px;padding:14px 16px;border-bottom:1px solid var(--line);flex:none}
.chat-h .av{width:34px;height:34px;border-radius:10px;background:var(--accent);color:var(--on-accent);display:grid;place-items:center;flex:none;box-shadow:var(--sh-1)}
.chat-h .av svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.chat-h .ht{min-width:0;flex:1}
.chat-h .ht b{font-size:15px;font-weight:600;display:block;line-height:1.2}
.chat-h .ht .sc{font-size:11.5px;color:var(--ink-2);font-weight:500}
.chat-h .x{width:34px;height:34px;border-radius:10px;background:var(--surface-2);display:grid;place-items:center;flex:none}
.chat-h .x svg{width:18px;height:18px;stroke:var(--ink-2);fill:none;stroke-width:2.2;stroke-linecap:round}
.chat-scope{display:flex;align-items:center;gap:8px;padding:9px 16px;border-bottom:1px solid var(--line);flex:none;font-size:12px;color:var(--ink-2);font-weight:500}
.chat-scope svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2;flex:none}
.chat-scope select{background:var(--surface-2);border:1px solid var(--line);border-radius:8px;padding:5px 8px;font-size:12px;font-weight:600;color:var(--ink);outline:none;cursor:pointer;max-width:220px}
.chat-scope select option{color:var(--ink);background:var(--surface)}
.chat-msgs{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:11px}
.bubble{max-width:85%;padding:10px 13px;border-radius:14px;font-size:14px;line-height:1.42;box-shadow:var(--sh-1);white-space:pre-wrap;word-wrap:break-word;overflow-wrap:anywhere}
.bubble.ai{align-self:flex-start;background:var(--surface-2);color:var(--ink);border-bottom-left-radius:5px}
.bubble.me{align-self:flex-end;background:var(--accent);color:var(--on-accent);border-bottom-right-radius:5px}
.bubble.typing{color:var(--ink-2);font-style:italic}
/* кнопка перевода на сообщении чата (POST /api/assistant/translate, серверный кэш) */
/* ⚠️ ПАЛЕЦ ПОЛУЧАЕТ 44, А ВИД ОСТАЁТСЯ ПРЕЖНИМ. Кнопка «оригинал / перевод»
   стоит под КАЖДОЙ репликой — и в чате помощника, и в ленте карточки. Сторож
   вёрстки мерил 71×20 и 64.9×20 при норме 44 (регламент §3): для бригады это
   переключатель языка, то есть кнопка, по которой жмут чаще прочих.
   ⚠️ ОТРИЦАТЕЛЬНЫХ ПОЛЕЙ ЗДЕСЬ БОЛЬШЕ НЕТ, И ЭТО ПРОВЕРЕНО СТОРОЖЕМ. Первая
   попытка растила коробку до 44 и гасила прирост полями «в минус» — сторож тут
   же дал три НАЛОЖЕНИЯ: у кнопки есть фон, и плашка налезала на текст реплики
   под ней (71×5). background-clip:content-box не спасает — сторож смотрит на
   backgroundColor, а не на то, где краска легла. Значит место кнопке нужно
   настоящее: высоту даёт она сама, а строка-хозяйка под неё раздвигается
   (.tc-comment-h в card.css). Плюс 24 px на реплику — честная цена за палец. */
.tr-btn{align-self:flex-start;font-size:10.5px;font-weight:700;letter-spacing:.05em;color:var(--ink-2);
  background:var(--surface-2);border-radius:9px;padding:0 12px;min-height:44px;
  display:inline-flex;align-items:center;transition:background .15s,color .15s}
.tr-btn:hover{background:var(--accent-soft);color:var(--accent)}
.tr-btn.me{align-self:flex-end}
.tr-btn:disabled{opacity:.5}
.bubble-tr{align-self:flex-start;max-width:85%;padding:8px 13px;border-radius:12px;font-size:13px;line-height:1.42;
  color:var(--ink-2);background:var(--surface);border:1px solid var(--line);border-left:3px solid var(--accent);
  white-space:pre-wrap;overflow-wrap:anywhere;margin-top:-6px}
.bubble-tr.me{align-self:flex-end;border-left:1px solid var(--line);border-right:3px solid var(--accent)}
.chat-empty{margin:auto;text-align:center;color:var(--ink-2);font-size:13.5px;padding:20px;max-width:290px}
.chat-empty .em-ic{width:52px;height:52px;border-radius:16px;background:var(--accent-soft);color:var(--accent);display:grid;place-items:center;margin:0 auto 13px}
.chat-empty .em-ic svg{width:25px;height:25px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}

/* карточка предлагаемой задачи в ленте */
.ptask{align-self:stretch;width:100%;background:var(--surface);border:1px solid var(--line);border-radius:14px;box-shadow:var(--sh-2);padding:13px;border-left:3px solid var(--accent)}
.ptask.confirmed{border-left-color:var(--st-done)}
.ptask.rejected{opacity:.5}
.ptask .pt-tag{font-size:10px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--accent);margin-bottom:6px;display:flex;align-items:center;gap:6px}
.ptask .pt-tag svg{width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}
.ptask.confirmed .pt-tag{color:var(--st-done)}
.ptask .pt-title{font-size:14.5px;font-weight:600;line-height:1.3;margin-bottom:4px}
.ptask .pt-trans{font-size:12.5px;color:var(--ink-2);margin-bottom:8px}
.ptask .pt-meta{display:flex;flex-wrap:wrap;gap:5px 6px;font-size:11.5px;color:var(--ink-2);font-weight:500;margin-bottom:11px}
.ptask .pt-meta span{background:var(--surface-2);padding:3px 8px;border-radius:7px}
.ptask .pt-acts{display:flex;gap:7px;flex-wrap:wrap}
.ptask .pt-acts button{height:34px;padding:0 13px;border-radius:9px;font-size:12.5px;font-weight:600;display:inline-flex;align-items:center;gap:5px;transition:transform .16s var(--ease),background .2s}
.ptask .pt-acts button:active{transform:scale(.95)}
.ptask .pt-acts .pbtn-ok{background:var(--accent);color:var(--on-accent);box-shadow:var(--sh-1)}
.ptask .pt-acts .pbtn-ok:hover{background:var(--accent-hover)}
.ptask .pt-acts .pbtn-ok svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
.ptask .pt-acts .pbtn-edit{background:var(--surface-2);color:var(--ink)}
.ptask .pt-acts .pbtn-rej{background:var(--surface-2);color:var(--ink-2)}
.ptask .pt-link{font-size:12.5px;font-weight:600;color:var(--accent);display:inline-flex;align-items:center;gap:5px;background:none;padding:2px 0}
.ptask .pt-edit{display:flex;flex-direction:column;gap:8px;margin-bottom:11px}
.ptask .pt-edit label{font-size:10px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-2);margin-bottom:-4px}
.ptask .pt-edit input,.ptask .pt-edit select{width:100%;background:var(--surface-2);border:1px solid var(--line);border-radius:8px;padding:8px 10px;font-size:13px;outline:none;transition:border .15s}
.ptask .pt-edit input:focus,.ptask .pt-edit select:focus{border-color:var(--accent)}
.ptask .pt-edit .r2{display:grid;grid-template-columns:1fr 1fr;gap:8px}

/* блок «Сделано» — реально выполненные действия помощника */
.act-block{align-self:flex-start;max-width:92%;display:flex;flex-direction:column;gap:4px;background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:8px;box-shadow:var(--sh-1)}
.act-row{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:500;padding:6px 8px;border-radius:8px;color:var(--ink);text-align:left;width:100%;transition:background .15s}
.act-row.clickable{cursor:pointer}
.act-row.clickable:hover{background:var(--surface-2)}
.act-row .a-ic{width:16px;height:16px;flex:none;color:var(--st-done)}
.act-row .a-ic svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
.act-row.fail .a-ic{color:var(--st-fire)}
.act-row .a-tx{flex:1;min-width:0}

/* плашка честности: ИИ недоступен / ошибка */
.chat-warn{align-self:stretch;display:flex;align-items:flex-start;gap:8px;background:color-mix(in srgb, var(--st-fire) 14%, var(--surface));border:1px solid var(--st-fire);border-radius:12px;padding:9px 11px;font-size:12.5px;color:var(--ink);line-height:1.4}
.chat-warn svg{width:16px;height:16px;flex:none;stroke:var(--st-fire);fill:none;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;margin-top:1px}

.chat-input{display:flex;gap:8px;align-items:flex-end;padding:12px 14px calc(12px + env(safe-area-inset-bottom));border-top:1px solid var(--line);flex:none}
.chat-input textarea{flex:1;background:var(--surface-2);border:1px solid var(--line);border-radius:12px;padding:10px 13px;
  resize:none;max-height:120px;min-height:44px;outline:none;transition:border .15s,box-shadow .15s;line-height:1.4}
.chat-input textarea:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.chat-input .send{width:44px;height:44px;border-radius:12px;background:var(--accent);color:var(--on-accent);display:grid;place-items:center;flex:none;box-shadow:var(--sh-2);transition:transform .16s var(--ease),background .2s}
.chat-input .send:hover{background:var(--accent-hover)}
.chat-input .send:active{transform:scale(.9)}
.chat-input .send:disabled{opacity:.5;pointer-events:none}
.chat-input .send svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

/* ═════════════ ГОЛОС ВЕЗДЕ (ночной мандат 04-08) ═════════════
   Владелец: «Если ты вводишь задачу — должен быть голосовой ввод. Если ты пишешь
   текст — должен быть голосовой ввод». Две формы одного и того же:
   .vt      — крупная кнопка в форме «＋ Задача» (первым элементом, ≥56px)
   .mic-s   — маленький микрофон в любом текстовом поле (тач-цель 44px)
   .vsug    — кнопки-подсказки вместо пустого поля («а если не понял — кнопочку дал»)
   Механика общая — объект Voice в скрипте, разметка — micBtn()/micWrap(). */
.vt{display:flex;align-items:center;gap:14px;background:var(--accent-soft);
  border:1px solid var(--line);border-radius:14px;padding:13px 14px;margin-bottom:12px}
.vt-mic{flex:none;width:64px;height:64px;border-radius:50%;background:var(--accent);color:var(--on-accent);
  display:grid;place-items:center;box-shadow:var(--sh-2);transition:transform .16s var(--ease),background .2s}
.vt-mic svg{width:28px;height:28px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.vt-mic:active{transform:scale(.94)}
.vt-mic.rec{background:var(--alarm);animation:vtpulse 1.25s infinite}
.vt-mic:disabled{opacity:.55;cursor:default}
@keyframes vtpulse{0%,100%{transform:scale(1)}50%{transform:scale(1.06)}}
.vt-txt{min-width:0;flex:1}
.vt-txt b{display:block;font-size:14px;font-weight:600;color:var(--ink);line-height:1.3}
.vt-txt .vt-hint{display:block;font-size:12px;color:var(--ink-2);margin-top:3px;line-height:1.35;word-break:break-word}
.vt-typed{display:none;gap:8px;align-items:center;margin:-4px 0 12px}
.vt-typed.on{display:flex}
.vt-typed input{flex:1;min-width:0;background:var(--surface-2);border:1px solid var(--line);
  border-radius:10px;padding:10px 12px;font:inherit;font-size:14px;color:var(--ink)}
.vt-typed input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.vt-link{font-size:12px;font-weight:600;color:var(--accent);background:none;padding:4px 0;text-decoration:underline;
  text-underline-offset:2px}
.vt-tr{display:none;font-size:12.5px;color:var(--ink-2);background:var(--surface-2);
  border-left:3px solid var(--accent);border-radius:9px;padding:8px 11px;margin:0 0 12px;
  white-space:pre-wrap;word-break:break-word}
.vt-tr.on{display:block}
/* кнопки-подсказки вместо пустого инпута */
.vsug{margin:-6px 0 13px}
.vsug-l{font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-2);margin-bottom:7px}
.vsug-row{display:flex;flex-wrap:wrap;gap:8px}
.vchip{min-height:44px;padding:0 14px;border-radius:11px;background:var(--surface);color:var(--ink);
  border:1px solid var(--line);font-size:13.5px;font-weight:600;box-shadow:var(--sh-1);
  display:inline-flex;align-items:center;gap:6px;max-width:100%;
  transition:transform .14s var(--ease),background .18s,border-color .18s}
.vchip:hover{background:var(--accent-soft);border-color:var(--accent)}
.vchip:active{transform:scale(.96)}
.vchip .s{font-size:11.5px;color:var(--ink-2);font-weight:500}
.vchip.soft{background:transparent;box-shadow:none;color:var(--ink-2);font-weight:500}
@keyframes vfill{0%{background:var(--accent-soft);border-color:var(--accent)}100%{}}
.vfilled{animation:vfill 1.1s var(--ease)}
/* маленький микрофон в любом текстовом поле */
.mic-s{flex:none;width:44px;height:44px;border-radius:12px;background:var(--surface-2);
  border:1px solid var(--line);color:var(--accent);display:grid;place-items:center;
  transition:transform .14s var(--ease),background .2s}
.mic-s svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.mic-s:hover{background:var(--accent-soft)}
.mic-s:active{transform:scale(.9)}
.mic-s.rec{background:var(--alarm);border-color:var(--alarm);color:var(--on-accent);animation:vtpulse 1.25s infinite}
.mic-s:disabled{opacity:.5;cursor:default}
.tc-comment-form .mic-s,.chat-input .mic-s{width:44px;height:44px}
/* микрофон, приклеенный к самостоятельной textarea (следующий шаг, причина возврата) */
.micwrap{position:relative}
.micwrap>textarea{padding-right:56px}
/* 44, а не 42: недобор двух пикселей ловил сторож в листе сдачи — а это орган
   управления, для него норма §3 обязательна */
.micwrap>.mic-s{position:absolute;right:6px;bottom:6px;width:44px;height:44px;border-radius:10px}
.mic-hint{font-size:11.5px;color:var(--ink-2);margin-top:5px;line-height:1.35;display:none;word-break:break-word}
.mic-hint.on{display:block}
/* выход из состояний «слушаю» и «разбираю»: до этой смены выйти было нечем */
.mic-cancel{min-height:44px;padding:0 12px;border:1px solid var(--line);border-radius:10px;
  background:var(--surface);color:var(--accent);font-size:12.5px;font-weight:600;
  display:inline-flex;align-items:center;margin-left:6px;vertical-align:middle}
.mic-cancel:active{transform:scale(.96)}

/* ПРИОРИТЕТ ЧИПАМИ В БЫСТРОЙ ФОРМЕ. Три слова в ряд вместо выпадашки: выпадашка —
   три касания, чип — одно. Тач-цель 44 px, как требует регламент. */
.qt-prio{display:flex;gap:8px;margin:10px 0 2px}
.qt-prio .qt-p{flex:1;min-height:44px;border:1px solid var(--line);border-radius:10px;
  background:var(--surface-2);color:var(--ink-2);font:inherit;font-size:14px;font-weight:600;
  cursor:pointer;transition:background .18s ease-out,color .18s ease-out,border-color .18s ease-out}
.qt-prio .qt-p:hover{border-color:var(--accent)}
.qt-prio .qt-p.on{background:var(--accent);border-color:var(--accent);color:#fff}

/* ═══════════ СРОК И «КТО ДЕЛАЕТ» КНОПКОЙ-ПОПАПОМ ═══════════
   Разметка та же, что у крошки карточки (<details class="tc3-pick"> + .pm):
   раскрытие попапа НЕ зовёт render(), поэтому набранное рядом название живо.
   Здесь только то, чем эти два попапа отличаются от крошки: у них есть подпись
   (в крошке был один карандаш), поэтому summary не квадрат, а строка. */
.kal-pick,.kto-pick{flex:none}
.tc3-pick.kal-pick>summary,.tc3-pick.kto-pick>summary{
  justify-content:flex-start;padding:0 10px;gap:6px;min-height:44px;
  background:var(--surface);border:1px solid var(--line);color:var(--ink-2);
  font-size:13px;font-weight:600;max-width:100%}
.tc3-pick.kal-pick>summary .nm,.tc3-pick.kto-pick>summary .nm{
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:120px}
.tc3-pick.kal-pick>summary .chv,.tc3-pick.kto-pick>summary .chv{flex:none;font-size:9px;opacity:.75}
.tc3-pick.kal-pick.has>summary,.tc3-pick.kto-pick.has>summary{color:var(--ink);border-color:var(--accent)}
/* галка «выбран» стоит всегда — так строка не дёргается при смене выбора */
.kto-pick .pm button svg{margin-left:auto;opacity:0}
.kto-pick .pm button.cur svg{opacity:1}

/* ── КАЛЕНДАРЬ: сегодня и следующие 30 дней, без листания ──
   Пять недель подряд от понедельника текущей недели. Своих месяцев и стрелок нет
   намеренно: дальняя дата берётся нативным полем в подвале, где есть и клавиатура.

   ⚠️ ШИРИНА ПОПАПА НЕ ЗАВИСИТ ОТ ТОГО, К ЧЕМУ ОН ПРИЦЕПЛЕН. Панель .pm тянется
   по хозяину (left:0;right:0), и в узкой полосе-черновике ячейка выходила 41 px
   на 375 и 43 на 390 — тач-норма §3 не пройдена. Считаем от требуемой клетки, а
   не от хозяина, и ЧЕСТНО ВЫЧИТАЕМ ПОЛОСУ ПРОКРУТКИ: на 375×667 календарь выше
   остатка экрана, а попап висит absolute и страницу не тянет — без своего скролла
   низ календаря был бы недосягаем, поэтому скролл здесь неизбежен.
   Счёт: клетка = (330 − 2×3 поля − 2 рамка − 13 полоса) / 7 = 44.14.
   Правый край попапа на 360 (Android бригады) — 359, влезает.
   Пояс на случай другой полосы прокрутки — min-width:44px у самой клетки ниже.

   ⚠️ ВЕС СЕЛЕКТОРА ВАЖНЕЕ ПОРЯДКА: card.css грузится ПОСЛЕ base.css, и его
   «.tc3-pick .pm» (тот же вес) перебивал здешние правила — попап жил с чужими
   полями 6 px и чужим max-height 48vh, а чипы и клетки получали от
   «.tc3-pick .pm button» width:100% и вставали столбиком в пять строк.
   Поэтому здесь везде вес выше: .tc3-pick.kal-pick и явный width:auto. */
.tc3-pick.kal-pick .pm{padding:3px;min-width:330px;max-width:calc(100vw - 12px);
  max-height:min(460px,74vh)}
.kal-pick .pm .kal-chips{display:flex;flex-wrap:wrap;gap:6px;padding:0 2px 8px}
.kal-pick .pm .kal-chips .vchip,.kal-pick .pm .kal-pod .vchip{width:auto}
.kal-pick .pm .kal-chips .vchip{padding:0 10px;gap:5px;font-size:13px}
.kal-pick .pm .kal-chips .vchip.on{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.kal-pick .pm .kal-chips .vchip.on .s{color:var(--on-accent)}
.kal-pick .pm .kal-h{display:flex;align-items:center;gap:8px;padding:2px 4px 6px;
  font-size:11.5px;font-weight:600;color:var(--ink-2)}
.kal-pick .pm .kal-h .kal-seg{margin-left:auto;min-height:44px;padding:0 12px;width:auto;
  border:1px solid var(--line);border-radius:var(--r2);background:var(--surface-2);
  color:var(--accent);font:inherit;font-size:12.5px;font-weight:600;cursor:pointer}
.kal-pick .pm .kal-wd,.kal-pick .pm .kal-g{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:0}
.kal-pick .pm .kal-wd{padding-bottom:2px}
.kal-pick .pm .kal-wd span{text-align:center;font-size:10.5px;font-weight:700;
  letter-spacing:.03em;color:var(--ink-2);text-transform:uppercase}
.kal-pick .pm .kal-g .kd{width:auto;min-width:44px;min-height:44px;padding:2px 0;border:0;border-radius:var(--r2);
  background:var(--surface-2);color:var(--ink);font:inherit;cursor:pointer;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:0;
  transition:background .16s var(--ease),color .16s var(--ease)}
.kal-pick .pm .kal-g .kd b{font-size:14px;font-weight:600;line-height:1.1}
.kal-pick .pm .kal-g .kd .mo{font-size:9.5px;font-weight:700;color:var(--ink-2);text-transform:uppercase}
.kal-pick .pm .kal-g .kd.pas{color:var(--ink-2);background:transparent}
.kal-pick .pm .kal-g .kd:hover{background:var(--accent-soft);color:var(--accent)}
.kal-pick .pm .kal-g .kd.td{box-shadow:inset 0 0 0 1.5px var(--accent);color:var(--accent)}
.kal-pick .pm .kal-g .kd.on{background:var(--accent);color:var(--on-accent)}
.kal-pick .pm .kal-g .kd.on .mo{color:var(--on-accent)}
.kal-pick .pm .kal-pod{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  border-top:1px solid var(--line);margin-top:8px;padding-top:8px}
.kal-pick .pm .kal-pod input[type=date]{flex:1;min-width:140px;min-height:44px;padding:0 10px;
  border:1px solid var(--line);border-radius:var(--r2);background:var(--surface);
  color:var(--ink);font:inherit;font-size:13.5px}

/* срок и «кто» в мини-форме создания: один ряд под чипами приоритета */
.qt-kogda{display:flex;gap:8px;flex-wrap:wrap;margin:10px 0 0;position:relative}
