/* Три колонки: слева агент, проекты и чаты, в центре одна или две панели чата, справа файлы. */

/* Тема (REQ-39): каждый цвет задан парой light-dark(светлая, тёмная), выбирает её color-scheme.
   По умолчанию тема системы, явный выбор theme.js ставит атрибутом data-theme на <html>. */
:root { color-scheme: light dark; }
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

:root {
  --bg: light-dark(#f3f4f6, #16181d);
  --panel: light-dark(#ffffff, #1d2026);
  --panel2: light-dark(#eceef2, #22262d);
  --line: light-dark(#d5d9e0, #2c313a);
  --text: light-dark(#1d2129, #e6e8ec);
  --dim: light-dark(#5d6777, #9aa3b2);
  --accent: light-dark(#2f5fd0, #7aa2f7);
  --ok: light-dark(#3b7a2a, #8ec07c);
  --warn: light-dark(#9a5f00, #e0af68);
  --err: light-dark(#c42e4a, #f7768e);
  --on-accent: light-dark(#ffffff, #11131a); /* текст на кнопке цвета акцента */
  --shadow: light-dark(rgba(0, 0, 0, .16), rgba(0, 0, 0, .45));
  --hl-k: light-dark(#7c3aed, #bb9af7);
  --hl-s: light-dark(#3b7a2a, #9ece6a);
  --hl-n: light-dark(#b45309, #ff9e64);
  --hl-c: light-dark(#6b7280, #737aa2);
  --hl-t: light-dark(#0e7490, #2ac3de);
  --term-bg: #11131a; /* терминал тёмный в обеих темах: TUI агента рисует цвета под тёмный фон */
  --mono: ui-monospace, "JetBrains Mono", "Fira Code", Menlo, Consolas, monospace;
  --left: 280px;
  --right: 300px;

  /* Шкала: новые правила берут размеры отсюда, а не подбирают по месту. */
  --fs-xs: 11px;   /* подписи, заголовки секций */
  --fs-sm: 12px;   /* вторичный текст, моноширинное в списках */
  --fs-md: 13px;   /* служебные строки ленты, меню */
  --fs-base: 14px; /* текст */
  --fs-lg: 16px;   /* заголовки окон, поле ввода на телефоне */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-6: 24px;
  --r-xs: 4px;     /* код в строке, метки */
  --r-sm: 6px;     /* мелкие кнопки */
  --r-md: 8px;     /* кнопки, меню, поля */
  --r-lg: 14px;    /* поле ввода, карточки, окна */
  --r-pill: 999px;
  --tint-accent: color-mix(in srgb, var(--accent) 10%, transparent);
  --head-h: 56px;  /* высота шапки панели: две строки заголовка, отступы и линия */
}

* { box-sizing: border-box; }

/* Атрибут hidden должен побеждать любое наше правило display. */
[hidden] { display: none !important; }

/* --app-height ставит JS по visualViewport: 100vh и 100dvh не знают о клавиатуре телефона. */
html { height: 100%; }

body {
  margin: 0;
  height: var(--app-height, 100dvh);
  overflow: hidden;
  background: var(--bg);
  color: var(--text);
  font: var(--fs-base)/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;
}

button { font: inherit; color: inherit; }
/* Фокус с клавиатуры виден везде. Поля, у которых фокус показан рамкой, гасят outline своим правилом. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Полосы прокрутки в тон теме. */
* { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
.list { list-style: none; margin: 0; padding: 0; }
.empty { padding: 20px 14px; color: var(--dim); font-size: var(--fs-md); }

#app {
  height: 100%;
  display: grid;
  grid-template-columns: var(--left) minmax(0, 1fr) var(--right);
}

/* ---------- боковые колонки ---------- */

aside {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--panel);
  border: 0 solid var(--line);
}
#left { border-right-width: 1px; padding-top: env(safe-area-inset-top); }
#right { border-left-width: 1px; padding-top: env(safe-area-inset-top); }

.section { display: flex; flex-direction: column; min-height: 0; border-bottom: 1px solid var(--line); }
.section:last-child { border-bottom: none; padding-bottom: env(safe-area-inset-bottom); }
.section-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px 6px;
  color: var(--dim);
  font-size: var(--fs-xs);
  letter-spacing: .06em;
  text-transform: uppercase;
}
.section-head .grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.section-head button {
  background: none; border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 0 7px; color: var(--dim); font-size: var(--fs-sm); cursor: pointer;
}
.section-head button:hover { color: var(--text); border-color: var(--dim); }
.scroll { overflow-y: auto; min-height: 0; overscroll-behavior: contain; }

.pane-tag { display: inline-flex; align-items: center; justify-content: center; border-radius: var(--r-xs); padding: 2px; }
.pane-tag.a { background: var(--accent); color: var(--bg); }
.pane-tag.b { background: var(--warn); color: var(--bg); }
.pane-tag svg { display: block; }

/* Блок агента: сетка в три колонки, чтобы полосы и проценты стояли в одних слотах. */
#agent { flex: none; }
#agent .rows {
  padding: 0 12px 4px;
  display: grid;
  grid-template-columns: 64px 1fr auto;
  gap: 4px 10px;
  align-items: center;
  font-size: var(--fs-md);
}
#agent .k { color: var(--dim); }
#agent .v {
  grid-column: 2 / 4; min-width: 0; text-align: right;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#agent .v small { color: var(--dim); font-size: var(--fs-sm); }
/* Восклицательный знак у агента, чья версия не сверена с вебом. */
#agent .untested {
  background: none; border: none; padding: 0 0 0 4px; cursor: pointer;
  color: var(--warn); font: inherit; font-weight: 700;
}
/* Ключ у агента, которому нужен вход. */
#agent .need-login {
  background: none; border: none; padding: 0 0 0 6px; cursor: pointer; color: var(--err); vertical-align: -2px;
}
#agent .v.dim { grid-column: 1 / 4; text-align: left; color: var(--dim); }
#agent .num { font-family: var(--mono); font-size: var(--fs-sm); text-align: right; min-width: 3.5em; }
#agent .num.warn { color: var(--warn); }
#agent .num.err { color: var(--err); }
#agent .num.gone { color: var(--dim); }
#agent .reset { grid-column: 2 / 4; margin-top: -3px; color: var(--dim); font-size: var(--fs-xs); }

/* Модель и режим - кликабельный текст с пунктиром, стрелкой и курсором. */
.pick {
  grid-column: 2 / 4; justify-self: end; max-width: 100%;
  display: flex; align-items: center; gap: 4px;
  background: none; border: none; padding: 0;
  font-size: var(--fs-md); cursor: pointer; text-align: left;
}
.pick span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border-bottom: 1px dotted var(--dim); }
.pick::after { content: "▾"; color: var(--dim); font-size: 10px; }
.pick:hover span, .pick.open span { color: var(--accent); border-bottom-color: var(--accent); }
.pick.danger span { color: var(--err); }

/* Заглушка значения, которого пока нет, нажатие объясняет почему. */
button.stub {
  justify-self: end; background: none; border: none; padding: 0; cursor: pointer;
  color: var(--dim); font-size: var(--fs-sm); border-bottom: 1px dashed var(--line);
}
button.stub:hover { color: var(--text); }

.bar { height: 4px; background: var(--line); border-radius: 2px; overflow: hidden; }
.bar i { display: block; height: 100%; background: var(--ok); }
.bar i.warn { background: var(--warn); }
.bar i.err { background: var(--err); }
#agent .fresh { padding: 2px 12px 8px; color: var(--dim); font-size: var(--fs-xs); text-align: right; min-height: 8px; }
#agent .fresh:empty { padding: 0 0 6px; }
/* Устаревшие числа: агент давно не спрашивал их у своего API. */
#agent .fresh.stale { color: var(--warn); }

#projects { flex: 0 1 40%; }
#chats { flex: 1 1 0; }


/* Проект - одна строка: с одной сессией она и есть сессия, с несколькими - счётчик и раскрытие. */
.proj, .item {
  position: relative;
  display: flex; align-items: center; gap: 8px;
  padding: 5px 12px; cursor: pointer; border-left: 2px solid transparent;
}
.proj:hover, .item:hover { background: var(--panel2); }
.proj.sel, .item.sel { background: var(--panel2); border-left-color: var(--accent); }
.proj.sel-b, .item.sel-b { border-left-color: var(--warn); }
.proj .body { flex: 1; min-width: 0; }
.proj .name { display: block; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.proj .path {
  display: block; color: var(--dim); font-size: var(--fs-xs); font-family: var(--mono);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.proj .mach { color: var(--text); }
.proj .gone { color: var(--warn); }
.proj .count {
  font-size: var(--fs-xs); font-family: var(--mono); color: var(--dim);
  border: 1px solid var(--line); border-radius: var(--r-pill); padding: 0 6px;
}
.proj .count.a { border-color: var(--accent); color: var(--accent); }
.proj .count.b { border-color: var(--warn); color: var(--warn); }
.proj .chev { color: var(--dim); font-size: var(--fs-xs); width: 10px; }
.proj > .m, .item > .m { color: var(--dim); font-size: var(--fs-sm); white-space: nowrap; flex: none; }
.proj > .m.wait, .item > .m.wait { color: var(--warn); }
/* Точка состояния агента: работает - мигает акцентом, ждёт человека - горит предупреждением,
   в фоне идут задачи - кольцо акцента. */
.st { display: inline-block; flex: none; width: 7px; height: 7px; margin-right: 6px; border-radius: 50%; vertical-align: middle; }
.st.busy { background: var(--accent); animation: blink 1.2s infinite; }
.st.wait { background: var(--warn); }
.st.tasks { box-shadow: inset 0 0 0 1.5px var(--accent); }
.sessions .item { padding-left: 30px; }
.item .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.item .t.faint { color: var(--dim); }
/* Поиск чата в шапке секции занимает не больше половины ширины. */
.section-head .grow:has(+ .find:not([hidden])) { flex: 0 1 auto; max-width: 50%; }
.section-head .find {
  flex: 1 1 60px; min-width: 60px; box-sizing: border-box;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 1px 7px; font: inherit; font-size: var(--fs-sm);
  text-transform: none; letter-spacing: normal;
}
.section-head .find:focus { outline: none; border-color: var(--accent); }
.section-head .find-btn { display: inline-flex; align-items: center; align-self: stretch; gap: 4px; }
.section-head .find-btn.on { color: var(--accent); border-color: var(--accent); }
.section-head .find-btn .label { text-transform: none; letter-spacing: normal; max-width: 90px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.section-head .find-btn .label:empty { display: none; }
.section-head .find-btn svg { display: block; }
.list li.none { padding: 6px 12px; color: var(--dim); font-size: var(--fs-md); }
/* Строка корзины прижата к низу блока чатов, список над ней прокручивается. */
#chats .scroll { flex: 1 1 0; }
#chat-trash { flex: none; border-top: 1px solid var(--line); padding: 4px 0; }
.trash .trash-list { list-style: none; margin: 6px 0; padding: 0 16px; overflow-y: auto; }
.trash .trash-list li { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px solid var(--line); }
.trash .trash-list li.none { color: var(--dim); font-size: var(--fs-md); border: none; }
.trash .what { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.trash .what .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.trash .what .t.faint, .trash .what .m { color: var(--dim); }
.trash .what .m { font-size: var(--fs-sm); }
.trash .trash-list button { flex: none; background: var(--panel2); border: 1px solid var(--line); border-radius: var(--r-md); padding: 4px 10px; cursor: pointer; }
.trash .trash-list button.danger { color: var(--err); }

/* Кнопка действий лежит поверх хвоста строки и появляется при наведении, на сенсорном - у выбранной строки. */
.grip { color: var(--dim); cursor: grab; width: 0; overflow: hidden; margin-right: -8px; transition: width .1s; flex: none; }
.proj:hover .grip { width: 10px; margin-right: 0; }
.more {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  background: var(--panel2); border: none; border-radius: var(--r-xs); color: var(--dim); cursor: pointer;
  padding: 2px 6px; font-size: 15px; line-height: 1; display: none;
}
.more:hover { color: var(--text); background: var(--line); }
.proj:hover > .more, .item:hover > .more, .more.open { display: block; }
.proj:hover > :is(.m, .count, .chev, .pane-tag),
.item:hover > :is(.m, .pane-tag),
.row-open > :is(.m, .count, .chev, .pane-tag) { visibility: hidden; }
@media (hover: none) {
  .grip { display: none; }
  .more { display: none; }
  :is(.proj.sel, .item.sel) > .more { display: block; }
  :is(.proj.sel, .item.sel) > :is(.m, .count, .chev, .pane-tag) { visibility: hidden; }
}
.pgroup.dragging { opacity: .4; }
/* Группа проектов: заголовок как у секции, сворачивается нажатием. */
.fhead {
  position: relative; display: flex; align-items: center; gap: 6px;
  padding: 8px 12px 4px; cursor: pointer; user-select: none;
  color: var(--dim); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .06em;
}
.fhead:hover { color: var(--text); }
.fhead .chev { width: 10px; font-size: var(--fs-xs); }
.fhead .fname { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fhead .count { font-family: var(--mono); text-transform: none; letter-spacing: 0; }
.fhead:hover > .more { display: block; }
.fhead:hover > .count, .fhead.row-open > .count { visibility: hidden; }
.fhead.drop-into { box-shadow: inset 0 0 0 1px var(--accent); color: var(--accent); }
.folder + .pgroup, .pgroup + .folder, .folder + .folder { border-top: 1px solid var(--line); }
.pgroup.drop-before { box-shadow: inset 0 2px 0 var(--accent); }
.pgroup.drop-after { box-shadow: inset 0 -2px 0 var(--accent); }
.rename {
  width: 100%; font: inherit; color: var(--text); background: var(--bg);
  border: 1px solid var(--accent); border-radius: var(--r-xs); padding: 0 4px;
}

/* Правая колонка: файлы и подключённое. */
#files { flex: 1 1 0; }
#attached { flex: none; max-height: 40%; overflow: auto; }
#attached-box { padding-bottom: 14px; }
.attached li { position: relative; display: flex; gap: 8px; align-items: baseline; padding: 3px 12px; font-size: var(--fs-sm); cursor: pointer; }
/* ⋯ встаёт поверх хвоста строки, как у чатов; на сенсорном его нет, нажатие и так открывает меню. */
.attached li:hover > .more { display: block; }
.attached li:hover > small, .attached li.row-open > small { visibility: hidden; }
@media (hover: none) { .attached li > .more { display: none !important; } }
.attached li:hover, .attached li.row-open { background: var(--panel2); }
.attached .kind { flex: none; width: 46px; color: var(--dim); font-size: var(--fs-xs); }
.attached .main { font-family: var(--mono); font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attached small { margin-left: auto; flex: none; color: var(--dim); font-size: var(--fs-xs); max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#attached .empty { padding: 4px 12px; }
.seg { display: flex; margin: 4px 12px 8px; border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; flex: none; }
.seg button { flex: 1; background: none; border: none; padding: 5px 0; color: var(--dim); cursor: pointer; font-size: var(--fs-md); }
.seg button.on { background: var(--panel2); color: var(--text); }
.tree { font-family: var(--mono); font-size: var(--fs-sm); padding-bottom: 8px; }
.tree li { display: flex; gap: 6px; align-items: center; padding: 2px 12px; white-space: nowrap; }
.tree .dir { color: var(--dim); overflow: hidden; text-overflow: ellipsis; padding-top: 6px; }
.tree .file { cursor: pointer; }
.tree .file:hover { background: var(--panel2); }
.tree .fname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.tree .cnt { margin-left: auto; font-size: var(--fs-xs); color: var(--dim); }
.tree .st { width: 12px; margin-left: 6px; font: 600 var(--fs-xs) var(--mono); text-align: right; color: var(--warn); }
.tree .st-A { color: var(--ok); }
.tree .st-D { color: var(--err); }
.tree .node { cursor: pointer; color: var(--dim); padding-top: 2px; }
.tree .node:hover { color: var(--text); }
.tree.all .st { margin-left: auto; }
.tree .tw { display: inline-block; width: 12px; font-size: 10px; }
.tree .gone .fname { text-decoration: line-through; opacity: .6; }
.stub-box { padding: 4px 12px 12px; color: var(--dim); font-size: var(--fs-sm); }
.stub-box p { margin: 0 0 6px; }
.stub-box code { font-family: var(--mono); font-size: var(--fs-sm); color: var(--text); }
button.link { background: none; border: none; padding: 0; color: var(--accent); cursor: pointer; font-size: var(--fs-sm); }

/* ---------- меню ---------- */

.menu {
  position: fixed; z-index: 40; min-width: 180px; max-width: min(360px, 92vw);
  margin: 0; padding: 4px 0; list-style: none;
  background: var(--panel2); border: 1px solid var(--line); border-radius: var(--r-md);
  box-shadow: 0 8px 24px var(--shadow); font-size: var(--fs-md);
}
.menu li { padding: 6px 12px; cursor: pointer; display: flex; gap: 8px; align-items: baseline; }
.menu li:hover { background: var(--line); }
.menu .check { width: 1em; flex: none; color: var(--accent); }
.menu li.danger { color: var(--err); }
.menu li.off { opacity: .45; cursor: default; }
.menu li.off:hover { background: none; }
.menu li.sep { height: 1px; padding: 0; margin: 4px 0; background: var(--line); cursor: default; }
.menu li.head { color: var(--dim); font-size: var(--fs-xs); cursor: default; padding-bottom: 2px; }
.menu li.head:hover { background: none; }
.menu .txt { display: flex; flex-direction: column; min-width: 0; }
.menu small { color: var(--dim); font-size: var(--fs-xs); }
.menu .sym { font-family: var(--mono); color: var(--accent); width: 2em; flex: none; text-align: center; }

/* Поиск по чату: строка под шапкой, совпадения списком под ней. */
.search {
  flex: none; display: flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-bottom: 1px solid var(--line); background: var(--panel);
}
.search-q {
  flex: 1; min-width: 0; padding: 5px 10px; font: inherit;
  background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: var(--r-md);
}
.search-q:focus { outline: none; border-color: var(--accent); }
.search-scope, .search-close {
  flex: none; padding: 4px 10px; border: 1px solid var(--line); border-radius: var(--r-md);
  background: none; color: var(--dim); cursor: pointer; font-size: var(--fs-sm);
}
.search-scope.on { color: var(--accent); border-color: var(--accent); }
.search-close { padding: 2px 9px; font-size: 16px; }
.search-count { flex: none; color: var(--dim); font-size: var(--fs-sm); white-space: nowrap; }
.hits {
  flex: none; max-height: 35%; overflow-y: auto;
  border-bottom: 1px solid var(--line); background: var(--panel);
}
.hit { display: flex; gap: 8px; align-items: baseline; padding: 4px 12px; cursor: pointer; font-size: var(--fs-md); }
.hit:hover, .hit.on { background: var(--panel2); }
.hit.mine { border-left: 2px solid var(--accent); }
.hit .hchat { flex: none; max-width: 30%; color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hit .hwhen { flex: none; color: var(--dim); font-size: var(--fs-sm); }
.hit .hsnip { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hit mark, mark.found { background: color-mix(in srgb, var(--warn) 35%, transparent); color: inherit; border-radius: 2px; }

/* Список своих сообщений бывает длинным. */
.menu.mine-menu { max-height: 60vh; overflow-y: auto; max-width: min(420px, 92vw); }

/* ---------- центр ---------- */

#center { display: flex; min-width: 0; min-height: 0; }
.pane {
  flex: 1; min-width: 0; min-height: 0;
  display: flex; flex-direction: column;
  border-top: 2px solid transparent;
}
.pane + .pane { border-left: 1px solid var(--line); }
#center.split .pane.active { border-top-color: var(--accent); }
#center.split .pane.b.active { border-top-color: var(--warn); }

.pane-head {
  flex: none; display: flex; align-items: center; gap: 4px;
  min-height: var(--head-h);
  padding: max(8px, env(safe-area-inset-top)) 12px 8px;
  border-bottom: 1px solid var(--line); background: var(--panel);
}
.pane-head .title { flex: 1; min-width: 0; margin-left: 4px; }
.pane-head .heading, .pane-head .sub { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pane-head .sub { color: var(--dim); font-size: var(--fs-sm); }
.pane-head .state { color: var(--dim); font-size: var(--fs-sm); max-width: 30%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pane-head .state.err { color: var(--err); }
.icon {
  background: none; border: 1px solid transparent; border-radius: var(--r-md);
  width: 32px; height: 32px; cursor: pointer; color: var(--dim); flex: none;
  display: inline-flex; align-items: center; justify-content: center;
}
/* Кнопки шапки без рамки, рамка только у включённой: так видно, что открыто. */
.icon:hover { color: var(--text); background: var(--panel2); }
.icon.on { color: var(--text); border-color: var(--line); }
.icon svg { display: block; }
.drawer-l, .drawer-r, .swap { display: none; }

/* Прокручивается только лента, min-height: 0 даёт flex-ребёнку сжаться. */
.scroller { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.feed, .live { max-width: 900px; margin: 0 auto; }
.feed { padding: 8px 0; }
.empty-pane { display: flex; height: 100%; align-items: center; justify-content: center; color: var(--dim); padding: 20px; text-align: center; }

/* Переносится всё, своя прокрутка только у кода и таблиц. */
.ev { padding: 8px 14px; overflow-wrap: anywhere; }
.ev .when { color: var(--dim); font-size: var(--fs-xs); font-family: var(--mono); }
/* Сообщение человека - облачко по ширине текста справа: отличается от ответов, не растягиваясь плашкой. */
.ev.user {
  width: fit-content; max-width: 85%;
  background: var(--tint-accent); border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius: var(--r-lg);
}
/* Сообщение, к которому перешли из списка своих. */
.ev.hit { animation: hit 1.6s ease-out; }
@keyframes hit { from { box-shadow: inset 0 0 0 2px var(--accent); } to { box-shadow: inset 0 0 0 2px transparent; } }
.ev.assistant { border-left: 2px solid transparent; }
.ev.thinking { color: var(--dim); font-style: italic; }
.ev .text { white-space: pre-wrap; overflow-wrap: anywhere; margin-top: 2px; }
.ev.tool, .ev.result, .ev.notice { position: relative; padding-top: 3px; padding-bottom: 3px; font-family: var(--mono); font-size: var(--fs-md); color: var(--dim); }
.ev.tool .tname, .group-head .tname { color: var(--accent); }
.ev.result.failed { color: var(--err); }
/* У служебных строк время не в начале, а справа и при наведении: секунды у каждой строки были шумом. */
:is(.ev.tool, .ev.result, .ev.notice) .when, .group-head > .when {
  position: absolute; right: 14px; top: 3px; padding-left: 8px;
  background: var(--bg); visibility: hidden;
}
@media (hover: hover) {
  :is(.ev.tool, .ev.result, .ev.notice, .group-head):hover .when { visibility: visible; }
}

/* Подряд идущие действия и служебные записи - одна строка, раскрывается нажатием. */
.group-head {
  position: relative; display: flex; align-items: baseline; gap: 8px;
  padding: 3px 14px; cursor: pointer; user-select: none;
  font-family: var(--mono); font-size: var(--fs-md); color: var(--dim);
}
.group-head:hover { color: var(--text); }
.group-head .fold-mark { flex: none; color: var(--accent); }
.group-head .gcount { flex: none; }
.group-head .gerr { flex: none; color: var(--err); }
.group-head .glast { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.group-head .glast::before { content: '· '; }
.group-body { margin: 0 0 4px 19px; border-left: 2px solid var(--line); }
.group-body > .ev { padding-left: 12px; }
.ev.recap { margin: 8px 14px; border: 1px dashed var(--line); border-radius: var(--r-md); color: var(--dim); }
.ev.recap > .when { margin-right: 4px; }
.ev.recap .text { color: var(--text); }
.ev.notice .fold-head { cursor: pointer; }
.ev.notice .fold-mark { color: var(--accent); }
/* Развёрнутая запись читается как обычный текст, сводка - как ответ агента. */
.ev.notice .fold-body { margin: 6px 0 0 12px; padding-left: 10px; border-left: 2px solid var(--line); }
.ev.notice .fold-body .md { font: var(--fs-base)/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; color: var(--text); }
.ev .cut { color: var(--warn); font-size: var(--fs-sm); }
.ev.user, .ev.assistant { position: relative; }
/* Сообщение человека отделено от ответов агента воздухом и прижато вправо. */
.ev.user { margin: 14px 14px 14px auto; }
/* Кнопки на одной вертикали: у ответа агента по краю текста (отступ блока 14px), у облачка
   человека по его краю, а облачко отодвинуто от края ленты на те же 14px. */
.ev-actions { position: absolute; top: 100%; right: 14px; display: flex; }
/* У облачка текст кончается у самой рамки: кнопку отодвигаем вниз, чтобы её фон не лёг на облачко.
   1px в обоих отступах - рамка облачка. */
.ev.user > .ev-actions { top: calc(100% + 5px); right: -1px; }
.ev-actions button.copy { height: 24px; }
/* С мышью кнопки сообщения видны при наведении на него, место под ними держится всегда.
   На телефоне наведения нет, там они видны постоянно. */
@media (hover: hover) {
  .ev-actions { opacity: 0; transition: opacity .15s; }
  .ev:hover > .ev-actions, .ev-actions:focus-within { opacity: 1; }
}
/* Кнопки сообщения стоят под блоком, а не в нём (REQ-35): блок не растёт, место даёт отступ
   до следующего. Соседние отступы схлопываются, поэтому у кнопки (24px) отступ с запасом. */
.ev:has(> .ev-actions) { margin-bottom: 24px; }
.ev.user:has(> .ev-actions) { margin-bottom: 38px; }
.ev:has(> .ev-actions) + .ev.user { margin-top: 38px; }
/* Кнопка копирования: под сообщением и в углу блока кода. Без наведения на телефоне, поэтому видна всегда, но тихо. */
button.copy {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0; border: 0; border-radius: var(--r-sm);
  background: none; color: var(--dim); opacity: .55; cursor: pointer;
}
button.copy:hover, button.copy:focus-visible { opacity: 1; background: var(--panel2); }
.md .code-block > button.copy { position: absolute; top: 4px; right: 4px; background: var(--panel); }

/* Отправленное, но ещё не появившееся в транскрипте. */
.ev.local { opacity: .6; }
.ev.local .text::after { content: ' ⏳'; }
/* Не появившееся в транскрипте слишком долго. */
.ev.local.lost { opacity: 1; border-color: var(--err); }
.ev.local.lost .text::after { content: ' ⚠ не подтвердилось'; color: var(--err); }

/* Ответ, пока он пишется, стоит последним в ленте. */
.live .ev.assistant { border-left-color: var(--accent); opacity: .85; }

/* Запросы разрешений стоят над полем ввода: туда смотрят, когда отвечают агенту, и при прокрутке
   ленты они не уходят. Видна одна карточка, остальные за счётчиком. */
.pending { max-height: calc(var(--app-height, 100dvh) * .5); overflow-y: auto; overscroll-behavior: contain; }
/* Карточка вопроса собрана как поле ввода: нейтральная рамка и фон, внимание - цветом заголовка. */
.ask {
  position: relative;
  max-width: 900px;
  margin: 8px auto;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--panel);
}
.pending .ask { margin: 0 0 8px; }
.ask .what { font-family: var(--mono); font-size: var(--fs-md); overflow-wrap: anywhere; }
/* Вопрос человеку - обычный текст, моноширинным остаются команды и пути. */
.ask .what.say { font-family: inherit; font-size: var(--fs-base); }
.ask .who { color: var(--warn); font-size: var(--fs-sm); margin-bottom: 4px; }
.ask-nav { position: absolute; top: 6px; right: 8px; display: flex; align-items: center; gap: 2px; color: var(--dim); font-size: var(--fs-sm); }
.ask .ask-nav button { flex: none; width: 26px; height: 24px; padding: 0; border: none; background: none; color: var(--dim); font-size: 16px; line-height: 1; }
.ask .ask-nav button:hover { color: var(--text); background: var(--panel2); }
.ask:has(> .ask-nav) .who { padding-right: 100px; }
/* Кнопки решения справа и не во всю ширину, как в окнах; на телефоне - во всю, под палец. */
.ask .buttons { display: flex; justify-content: flex-end; gap: 8px; margin-top: 10px; }
.ask .buttons button { flex: 0 1 180px; }
/* Длинная форма прокручивается, а кнопки решения остаются видны. */
.pending .ask .buttons { position: sticky; bottom: 0; margin-top: 2px; padding: 8px 0 2px; background: var(--panel); }
@media (max-width: 820px) { .ask .buttons button { flex: 1; } }
.ask button {
  flex: 1; padding: 8px; border-radius: var(--r-md); font: inherit; cursor: pointer;
  border: 1px solid var(--line); background: var(--panel2); color: var(--text);
}
.ask button:hover:not(:disabled) { border-color: var(--dim); }
.ask button:disabled { opacity: .5; cursor: default; }
/* Главное действие залито, как кнопка отправки, отказ - цветом текста, как опасные пункты меню. */
.ask .allow { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.ask .allow:hover:not(:disabled) { border-color: var(--text); }
.ask .deny { color: var(--err); }
.ask .always {
  display: block; width: 100%; margin-top: 8px;
  color: var(--dim); overflow-wrap: anywhere; font-size: var(--fs-sm); text-align: left;
}
.ask .always:hover:not(:disabled) { color: var(--text); }
.ask .q { margin-top: 8px; }
.ask .q .qh { color: var(--dim); font-size: var(--fs-sm); }
.ask .opts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.ask .opts button {
  flex: none;
  /* Длинное описание варианта переносится, а не уводит кнопку за край. */
  max-width: 100%;
  white-space: normal;
  text-align: left;
}
.ask .opts button.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, transparent); }
.ask .opts button small { display: block; color: var(--dim); font-size: var(--fs-xs); }
.ask .own {
  width: 100%; margin-top: 6px; padding: 6px 8px;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--r-md); font: inherit;
}
/* Фокус рамкой, как у остальных полей: outline выходит за поле, и его низ закрывали
   прилипшие кнопки карточки. */
.ask .own:focus { outline: none; border-color: var(--accent); }
.ask details { margin-top: 6px; color: var(--dim); font-size: var(--fs-sm); }
.ask .dlines { max-height: 30vh; overflow: auto; margin: 4px 0 0; white-space: pre-wrap; font-size: var(--fs-sm); }
.ask .link { display: block; margin-top: 6px; overflow-wrap: anywhere; color: var(--accent); }
.ask .check { display: block; margin-top: 6px; }
/* План на одобрение со своей прокруткой, чтобы кнопки оставались на экране. */
.ask .plan { max-height: 45vh; overflow-y: auto; margin-top: 6px; }

/* Поле ввода с управлением сжимается вместе с панелью и стоит прямо на фоне ленты. */
.composer {
  flex: none; position: relative;
  padding: 4px 10px max(10px, env(safe-area-inset-bottom));
}
.composer-inner { max-width: 900px; margin: 0 auto; }

/* Кнопка в конец ленты висит над полем ввода у правого края, пока лента прокручена вверх: по центру
   она закрывала текст. */
.to-bottom {
  position: absolute; bottom: 100%; right: 16px; margin-bottom: 8px; z-index: 1;
  width: 28px; height: 28px; border-radius: 50%; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); background: var(--panel2); color: var(--dim);
  box-shadow: 0 2px 8px var(--shadow);
}
.to-bottom:hover { color: var(--text); }
.to-bottom[hidden] { display: none; }

/* Строка состояния над полем ввода: работа агента, фоновые задачи и очередь в одну строку. */
.status {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  padding: 0 4px 6px; color: var(--dim); font-size: var(--fs-md);
}
.status:not(:has(> :not([hidden]))) { display: none; }
.working { flex: none; max-width: 100%; display: flex; align-items: center; gap: 8px; min-width: 0; color: var(--accent); }
/* В узкой строке первым сжимается второстепенное: задачи и очередь, а не «агент работает». */
.status > .tasks, .status > .queue-chip { flex-shrink: 100; }
.working-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dots { display: inline-flex; gap: 4px; }
.dots i { width: 5px; height: 5px; border-radius: 50%; background: currentColor; animation: blink 1.2s infinite; }
.dots i:nth-child(2) { animation-delay: .2s; }
.dots i:nth-child(3) { animation-delay: .4s; }
@keyframes blink {
  0%, 60%, 100% { opacity: .25; }
  30% { opacity: 1; }
}
/* Мигание - раздражитель, а смысл несёт и просто видимая строка. */
@media (prefers-reduced-motion: reduce) {
  .dots i, .st.busy { animation: none; opacity: 1; }
}

.tasks { flex: 0 1 auto; min-width: 0; font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.working:not([hidden]) + .tasks::before { content: '· '; }

/* Очередь агента: отправленное во время хода, пока он его не прочитал. В строке состояния -
   первое сообщение или их число, по нажатию - список. */
.queue-chip {
  flex: 0 1 auto; max-width: 50%; margin-left: auto;
  padding: 1px 10px; border: 1px dashed var(--line); border-radius: var(--r-pill);
  background: none; color: var(--dim); font-size: var(--fs-sm); cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.queue-chip:hover { color: var(--text); border-color: var(--dim); }
.agent-queue { padding: 0 4px 6px; font-size: var(--fs-md); }
.agent-queue .qi {
  margin-top: 4px; padding: 4px 10px; border: 1px dashed var(--line); border-radius: var(--r-md);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Отложенная отправка: заметная и отменяемая полоска. */
.queued {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  padding-bottom: 6px; color: var(--warn); font-size: var(--fs-md);
}
.unqueue {
  border: 1px solid var(--warn); border-radius: var(--r-sm); background: none;
  color: var(--warn); padding: 2px 8px; cursor: pointer;
}

.compose {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "plus field send"; align-items: end; gap: 0 4px;
  padding: 4px; border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--panel);
}
.compose:focus-within { border-color: var(--accent); }
/* Текст не влез в строку между кнопками: поле на всю ширину, кнопки под ним, решает resizeInput. */
.compose.tall { grid-template-areas: "field field field" "plus . send"; }
/* Файл тащат на поле ввода: подсветка, куда его можно бросить. */
.compose.drop { outline: 2px dashed var(--accent); outline-offset: 4px; }

/* Меню «+»: команда, файл, прерывание хода. */
.plus, .send {
  flex: none; width: 28px; height: 28px; margin: 3px; border-radius: 50%; cursor: pointer;
  border: none; background: none; color: var(--dim);
  font-size: 20px; line-height: 1;
}
.plus { grid-area: plus; }
.plus:hover, .plus.open { color: var(--text); background: var(--panel2); }
.send { grid-area: send; background: var(--accent); color: var(--on-accent); font-size: 18px; }
.send:disabled { opacity: .45; cursor: default; }
/* Пустое поле с подсказкой агента: кнопка берёт подсказку в поле, а не отправляет. */
.compose.suggest .send { background: var(--panel2); color: var(--accent); }

/* Фон у формы, а поле прозрачное, чтобы просвечивала подсказка дополнения. */
.field { grid-area: field; position: relative; min-width: 0; }
.field textarea {
  display: block; width: 100%; resize: none; max-height: 40vh;
  padding: 6px 6px; border: none; background: none; color: var(--text); font: inherit; line-height: 22px;
}
.field textarea:focus { outline: none; }

/* Подсказка дополнения повторяет метрики поля, набранная часть в ней прозрачна. */
.ghost {
  position: absolute; inset: 0; padding: 6px 6px; font: inherit; line-height: 22px;
  color: transparent; white-space: pre-wrap; overflow-wrap: anywhere;
  overflow: hidden; pointer-events: none;
}
.ghost .rest { color: var(--dim); }

/* На телефоне поле под палец, а шрифт мельче 16px iOS при фокусе приближает страницу. */
@media (max-width: 820px) {
  .compose { padding: 5px; border-radius: 22px; }
  .field { font-size: var(--fs-lg); }
  .field textarea, .ghost { padding: 9px 8px; line-height: 24px; }
  .plus, .send { width: 38px; height: 38px; margin: 2px; font-size: 24px; }
  .to-bottom { width: 38px; height: 38px; }
  .to-bottom svg { width: 20px; height: 20px; }
  .send { font-size: 21px; }
}

/* Список команд и файлов над полем ввода, с прокруткой. */
.palette {
  /* От видимой высоты: 40vh не знают о клавиатуре, и верх списка уходил за край. */
  max-height: calc(var(--app-height, 100dvh) * .4); overflow-y: auto; margin-bottom: 6px;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg);
  overscroll-behavior: contain;
}
.cmd { display: flex; align-items: baseline; gap: 8px; padding: 8px 10px; border-bottom: 1px solid var(--line); cursor: pointer; }
.cmd:last-child { border-bottom: none; }
.cmd.on { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.cmd .nm { font-family: var(--mono); color: var(--accent); flex: none; }
.cmd .hint { font-family: var(--mono); color: var(--dim); font-size: var(--fs-sm); flex: none; }
.cmd .desc { color: var(--dim); font-size: var(--fs-sm); flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Откуда команда: своя и проектная помечаются, встроенная - нет. */
.cmd .from { font-size: var(--fs-xs); color: var(--warn); flex: none; }

/* ---------- всплывающее сообщение ---------- */

#toast {
  position: fixed; left: 50%; bottom: 96px; transform: translateX(-50%);
  z-index: 50; max-width: min(560px, 90vw);
  padding: 10px 14px; border-radius: var(--r-md);
  background: var(--err); color: var(--on-accent); font-size: var(--fs-base);
  box-shadow: 0 6px 24px var(--shadow);
  animation: toast-in .15s ease-out;
}
/* Пояснения и заглушки - спокойным цветом: это не ошибка. */
#toast.info { background: var(--panel2); color: var(--text); border: 1px solid var(--accent); }
@keyframes toast-in {
  from { opacity: 0; transform: translate(-50%, 6px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

/* ---------- разметка в ответах агента ---------- */
/* Отступы скромные: лента читается подряд. */
.md { white-space: normal; }
/* Markdown в просмотре файла: читается как документ, с полями. */
.vmd { padding: 12px 18px; max-width: 900px; font-size: var(--fs-base); }
.md > :first-child { margin-top: 0; }
.md > :last-child { margin-bottom: 0; }
.md p { margin: 0 0 8px; }
.md h3, .md h4, .md h5, .md h6 { margin: 14px 0 6px; font-size: var(--fs-base); line-height: 1.3; }
.md h3 { font-size: var(--fs-lg); }
.md ul, .md ol { margin: 0 0 8px; padding-left: 22px; }
.md li { margin: 2px 0; }
.md li > .code-block, .md li > ul, .md li > ol, .md li > p { margin: 4px 0; }
.md a { color: var(--accent); }
.md code {
  font-family: var(--mono); font-size: var(--fs-md);
  background: color-mix(in srgb, var(--text) 7%, transparent); padding: 1px 4px; border-radius: var(--r-xs);
  overflow-wrap: anywhere;
}
.md .code-block { position: relative; margin: 0 0 8px; }
.md pre {
  margin: 0; padding: 10px 12px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-md);
  overflow-x: auto;
}
.md pre code { background: none; padding: 0; font-size: var(--fs-md); line-height: 1.45; white-space: pre; tab-size: 4; }
/* Подсветка кода (hl.js), цвета из той же палитры, что и тема. */
.hl-k { color: var(--hl-k); }
.hl-s { color: var(--hl-s); }
.hl-n { color: var(--hl-n); }
.hl-c { color: var(--hl-c); font-style: italic; }
.hl-t { color: var(--hl-t); }
.hl-a { color: var(--accent); }
.hl-v { color: var(--warn); }
.hl-i { color: var(--ok); }
.hl-d { color: var(--err); }
.hl-h { color: var(--accent); }
.hl-m { color: var(--dim); font-weight: 600; }
.md blockquote { margin: 0 0 8px; padding-left: 10px; border-left: 2px solid var(--line); color: var(--dim); }
.md hr { margin: 12px 0; border: none; border-top: 1px solid var(--line); }
/* Широкая таблица прокручивается сама, а не растягивает страницу. */
.md-table { overflow-x: auto; margin: 0 0 8px; }
.md table { border-collapse: collapse; font-size: var(--fs-md); }
.md th, .md td { padding: 5px 10px; border: 1px solid var(--line); text-align: left; vertical-align: top; }
.md th { background: var(--panel); font-weight: 600; }

/* ---------- узкие экраны ---------- */

#scrim { position: fixed; inset: 0; background: #0007; z-index: 15; display: none; }

/* Средний экран: правая колонка выезжает по кнопке, левая на месте. */
@media (max-width: 1250px) {
  #app { grid-template-columns: var(--left) minmax(0, 1fr); }
  #right {
    position: fixed; top: 0; right: 0; bottom: 0; width: min(var(--right), 88vw); z-index: 20;
    transform: translateX(100%); transition: transform .2s; box-shadow: -8px 0 24px var(--shadow);
  }
  body.open-right #right { transform: none; }
  body.open-right #scrim { display: block; }
  .drawer-r { display: inline-block; }
}

/* Телефон: обе боковые выезжают поверх, видна только активная панель. */
@media (max-width: 820px) {
  #app { grid-template-columns: minmax(0, 1fr); }
  #left {
    position: fixed; top: 0; left: 0; bottom: 0; width: min(var(--left), 88vw); z-index: 20;
    transform: translateX(-100%); transition: transform .2s; box-shadow: 8px 0 24px var(--shadow);
  }
  body.open-left #left { transform: none; }
  body.open-left #scrim { display: block; }
  .drawer-l { display: inline-block; }
  .split-btn { display: none; }
  body.split .swap:not([hidden]) { display: inline-block; }
  #center.split .pane:not(.active) { display: none; }
  #center.split .pane.active { border-top-color: transparent; }
  .pane + .pane { border-left: none; }
  #toast { bottom: 80px; }
}

/* ---------- модальные окна: открытие проекта, подключение ---------- */

dialog.modal {
  width: min(520px, calc(100vw - 24px));
  max-height: calc(var(--app-height, 100dvh) - 24px);
  padding: 0;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
dialog.modal:not([open]) { display: none; }
dialog.modal::backdrop { background: rgba(0, 0, 0, .5); }
.modal h2 { margin: 0; padding: 14px 16px 6px; font-size: var(--fs-lg); font-weight: 600; }
.modal .seg { margin: 6px 16px; }
.modal .seg button:disabled { opacity: .4; cursor: default; }
.modal .hint { margin: 4px 16px; color: var(--dim); font-size: var(--fs-sm); }
.modal .hint.err { color: var(--err); }
.modal .actions { display: flex; justify-content: flex-end; gap: 8px; padding: 8px 16px 14px; }
.modal .actions button { background: var(--panel2); border: 1px solid var(--line); border-radius: var(--r-md); padding: 6px 14px; cursor: pointer; }
.modal .actions .primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.modal .actions button:disabled { opacity: .5; cursor: default; }
.modal input.path, .modal input.text {
  flex: 1; min-width: 0;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 7px 10px; font: var(--fs-base) var(--mono);
}
.modal input.path:focus, .modal input.text:focus { outline: none; border-color: var(--accent); }

/* Окно /usage: полосы лимитов, как в блоке агента, под каждой время сброса. */
.modal .usage-body { padding: 4px 16px 8px; overflow-y: auto; }
.usage-grid {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 6px 10px; align-items: center; font-size: var(--fs-md);
}
.usage-grid .k { color: var(--dim); }
.usage-grid .num { font-family: var(--mono); font-size: var(--fs-sm); text-align: right; min-width: 3.5em; }
.usage-grid .num.warn { color: var(--warn); }
.usage-grid .num.err { color: var(--err); }
.usage-grid .reset { grid-column: 2 / 4; margin-top: -4px; color: var(--dim); font-size: var(--fs-xs); }
.usage-body h3 { margin: 14px 0 6px; font-size: var(--fs-md); font-weight: 600; color: var(--dim); }
.usage-body .hint { margin: 10px 0 0; }

/* Высота постоянная, чтобы окно не прыгало при переходе между каталогами. */
dialog.open-project { height: min(600px, calc(var(--app-height, 100dvh) - 24px)); }
.open-project .pathrow { display: flex; gap: 6px; padding: 6px 16px; }
.open-project .go { background: var(--panel2); border: 1px solid var(--line); border-radius: var(--r-md); padding: 0 12px; cursor: pointer; }
.open-project .dirs { flex: 1; min-height: 120px; overflow-y: auto; margin: 4px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.open-project .dirs li { display: flex; align-items: baseline; gap: 8px; padding: 8px 16px; cursor: pointer; }
.open-project .dirs li:hover { background: var(--panel2); }
.open-project .dirs li .name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.open-project .dirs li small { color: var(--dim); font-size: var(--fs-sm); }
.open-project .dirs li.up .name { color: var(--dim); }
.open-project .dirs li.head { cursor: default; padding: 10px 16px 2px; color: var(--dim); font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: .04em; }
.open-project .dirs li.head:hover, .open-project .dirs li.none:hover { background: none; }
.open-project .dirs li.none { cursor: default; color: var(--dim); font-size: var(--fs-md); }

/* список выбора: секреты, бандлы */
.attach .form { padding: 4px 0; overflow-y: auto; }
.attach .choose { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); max-height: 260px; overflow-y: auto; }
.attach .choose li { display: flex; align-items: baseline; gap: 8px; padding: 8px 16px; cursor: pointer; }
.attach .choose li:hover { background: var(--panel2); }
.attach .choose li.on { background: var(--panel2); box-shadow: inset 3px 0 var(--accent); }
.attach .choose li.done { cursor: default; opacity: .5; }
.attach .choose li.done:hover { background: none; }
.attach .choose .name { flex: none; }
.attach .choose small { flex: 1; min-width: 0; color: var(--dim); font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attach .pinfield { display: flex; flex-direction: column; gap: 4px; padding: 6px 16px; font-size: var(--fs-sm); color: var(--dim); }
.attach .pinfield input { flex: none; }
.claude-login .pinfield { display: flex; flex-direction: column; gap: 4px; padding: 6px 16px; font-size: var(--fs-sm); color: var(--dim); }
.claude-login .login-link { display: flex; gap: 12px; align-items: center; padding: 6px 16px; }
.claude-login .login-link a { color: var(--accent); }
.claude-login .login-link button { background: var(--panel2); border: 1px solid var(--line); border-radius: var(--r-md); padding: 4px 10px; color: inherit; cursor: pointer; }
.attach .empty { margin: 8px 16px; color: var(--dim); font-size: var(--fs-md); }

/* ---------- просмотр файла ---------- */

dialog.viewer {
  width: min(1100px, calc(100vw - 24px));
  height: calc(var(--app-height, 100dvh) - 24px);
}
.viewer .vhead { display: flex; align-items: center; gap: 6px; padding: 10px 10px 4px 16px; }
.viewer .vtitle {
  flex: 1; min-width: 0; display: flex;
  font: var(--fs-md) var(--mono); white-space: nowrap; overflow: hidden;
}
/* Каталог режется, имя файла - нет: оно важнее. */
.viewer .vtitle span { color: var(--dim); overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.viewer .vtitle b { flex: none; font-weight: 600; }
.viewer .vbtn {
  flex: none; min-width: 32px; height: 30px; padding: 0 8px;
  background: var(--panel2); border: 1px solid var(--line); border-radius: var(--r-md);
  color: var(--dim); font: var(--fs-base) var(--mono); cursor: pointer;
}
.viewer .vbtn:hover, .viewer .vbtn.on { color: var(--text); border-color: var(--dim); }
.viewer .vbar { display: flex; align-items: center; gap: 8px; padding: 4px 10px 6px 16px; }
.viewer .vbar .seg { flex: 0 1 260px; margin: 0; }
.viewer .vbar .vbtn { margin-left: auto; }
.viewer .hint { margin: 2px 16px 6px; }
.viewer .vbody { flex: 1; min-height: 0; overflow: auto; border-top: 1px solid var(--line); background: var(--bg); overscroll-behavior: contain; }

.vcode { font: var(--fs-sm)/1.5 var(--mono); tab-size: 4; width: max-content; min-width: 100%; padding: 4px 0 12px; }
.vl { display: flex; align-items: flex-start; white-space: pre; }
.vl .ln {
  flex: none; width: 5ch; padding-right: 1ch; text-align: right; color: var(--dim); opacity: .6;
  user-select: none; position: sticky; left: 0; background: var(--bg);
}
.vdiff .vl .ln { width: 4.5ch; }
.vdiff .vl .ln + .ln { left: 4.5ch; }
.vl .sg { flex: none; width: 2ch; text-align: center; user-select: none; color: var(--dim); }
.vl .vc { flex: 1; padding-right: 16px; }
.vl.add { background: color-mix(in srgb, var(--ok) 12%, transparent); }
.vl.del { background: color-mix(in srgb, var(--err) 12%, transparent); }
.vl.add .ln { background: color-mix(in srgb, var(--ok) 10%, var(--bg)); }
.vl.del .ln { background: color-mix(in srgb, var(--err) 10%, var(--bg)); }
.vl.add .sg { color: var(--ok); }
.vl.del .sg { color: var(--err); }
.vl.hunk { color: var(--accent); padding-top: 6px; }
.vl.hunk .vc, .vl.meta .vc { opacity: .8; }
.vl.meta { color: var(--dim); }
.viewer.wrap .vcode { width: auto; }
.viewer.wrap .vl { white-space: pre-wrap; overflow-wrap: anywhere; }

@media (max-width: 820px) {
  dialog.viewer {
    width: 100vw; max-width: 100vw;
    height: var(--app-height, 100dvh); max-height: none;
    margin: 0; border: none; border-radius: 0;
    padding-top: env(safe-area-inset-top);
  }
}

/* ---------- веб-терминал ---------- */

dialog.term .tstate { flex: none; color: var(--dim); font-size: var(--fs-sm); margin-right: 4px; }
dialog.term .tnote { flex: none; color: var(--accent); font-size: var(--fs-sm); }
dialog.term .tnote .vbtn { font-size: var(--fs-sm); }
/* Ссылки с экрана: адрес обрезается, целиком он в подсказке и по нажатию. */
dialog.term .tlinks { flex: none; max-height: 30%; overflow-y: auto; padding: 4px 10px 6px 16px; border-top: 1px solid var(--line); }
dialog.term .tlink { display: flex; align-items: center; gap: 8px; padding: 2px 0; }
dialog.term .tlink a { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--mono); font-size: var(--fs-sm); color: var(--accent); }
dialog.term .tlink .vbtn { flex: none; font-size: var(--fs-sm); }
dialog.term .tbody {
  flex: 1; min-height: 0; padding: 6px 4px 4px 8px;
  border-top: 1px solid var(--line); background: var(--term-bg);
}
dialog.term .tkeys { display: flex; gap: 6px; padding: 6px 10px 8px; overflow-x: auto; }
dialog.term .tkeys .vbtn { font-size: var(--fs-sm); }
@media (max-width: 820px) {
  dialog.term { padding-bottom: env(safe-area-inset-bottom); }
}
/* Индикатор с открытым в терминале диалогом ведёт в терминал. */
.working.dialog { cursor: pointer; }
.working.dialog .working-text { text-decoration: underline dotted; }
/* Ход в другом чате сессии: приглушённо и без мигания, нажатие ведёт в тот чат. */
.working.elsewhere { color: var(--dim); cursor: pointer; }
.working.elsewhere .dots { display: none; }
.working.elsewhere .working-text { text-decoration: underline dotted; }

/* Упоминание файла «@»: на пальце видно всегда, с мышью при наведении поверх пометки изменения. */
.tree .at {
  flex: none; margin-left: 4px; padding: 2px 9px;
  background: none; border: 1px solid transparent; border-radius: var(--r-sm);
  color: var(--dim); font: var(--fs-sm) var(--mono); cursor: pointer;
}
@media (hover: none) {
  .tree li.file { padding-top: 3px; padding-bottom: 3px; }
}
@media (hover: hover) {
  .tree li.file { position: relative; }
  .tree .at {
    display: none; position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
    margin: 0; padding: 0 6px; line-height: 16px;
    background: var(--panel2); border-color: var(--line);
  }
  .tree .file:hover .at { display: block; }
  .tree .file:hover .st { visibility: hidden; }
  .tree .at:hover { color: var(--text); border-color: var(--dim); }
}

/* ---------- вход ---------- */

body.login-page { display: flex; align-items: center; justify-content: center; min-height: 100dvh; margin: 0; }
.login { width: min(340px, calc(100vw - 32px)); }
.login h1 { font-size: 20px; font-weight: 600; margin: 0 0 18px; }
.login form { display: flex; flex-direction: column; gap: 12px; }
.login label { display: flex; flex-direction: column; gap: 4px; color: var(--dim); font-size: var(--fs-sm); }
.login input {
  background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 8px 10px; font: inherit; font-size: var(--fs-lg);
}
.login input:focus { outline: none; border-color: var(--accent); }
.login button { margin-top: 6px; padding: 9px; border-radius: var(--r-md); border: 1px solid var(--accent); background: var(--accent); color: var(--bg); font: inherit; font-weight: 600; cursor: pointer; }
.login button:disabled { opacity: .5; cursor: default; }
.login .hint { color: var(--dim); font-size: var(--fs-md); line-height: 1.4; }
.login .hint.err { color: var(--err); }

/* Кто вошёл и тема: шапка правой колонки высотой с шапку панели, линии под ними совпадают,
   и строка не читается как часть «Файлов». */
#me {
  flex: none; display: flex; align-items: center; gap: 8px;
  min-height: calc(var(--head-h) + 2px); /* и полоса активной панели над шапкой */
  border-bottom: 1px solid var(--line); padding: 0 12px; font-size: var(--fs-sm);
}
#me .theme { margin-left: auto; }
#me button:not(.icon) { background: none; border: none; padding: 2px 0; color: var(--dim); font: inherit; cursor: pointer; }
#me button:not(.icon):hover { color: var(--text); }
.logins { padding: 0 16px; overflow-y: auto; }
.logins .login-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.logins .login-row:last-child { border-bottom: none; }
.logins .what { flex: 1; min-width: 0; }
.logins .what b { font-weight: 500; }
.logins .what small { display: block; color: var(--dim); font-size: var(--fs-sm); }
.logins .mark { color: var(--accent); font-size: var(--fs-sm); }
