/* ------------------------------------------------------------------ *
 *  Админка KoDG — светлая тема.
 *
 *  Гамма привязана к сайту: красный бренда #ec0707 остаётся, а «хром»
 *  #1b2835 из фона переехал в цвет текста — так связь с сайтом видна,
 *  и при этом читать длинные таблицы на светлом легче.
 *
 *  ⚠️ Все цвета — только через переменные ниже. Раньше половина была
 *  вписана прямо в правила (#fff как «яркий текст», белые полупрозрачные
 *  подсветки, чёрные тени), и сменить тему было нельзя, не перебрав
 *  сорок мест. Теперь тема — это один блок :root.
 *
 *  ⚠️ Красный на светлом должен ТЕМНЕТЬ при наведении, а не светлеть:
 *  прежний #ff3a33 годился на тёмном фоне, на белом он бледнеет и теряет
 *  контраст. Поэтому --accent-h теперь темнее основного.
 * ------------------------------------------------------------------ */
:root{
  /* поверхности */
  --bg:#eef1f5; --panel:#ffffff; --panel2:#ffffff;
  --line:#dde3ea; --line2:#c6d0da;

  /* текст: основной — «хром» сайта, он же самый контрастный */
  /* ⚠️ `--muted` замерен по контрасту: при #6b7c8d выходило 4,29 к белому —
     ниже нормы 4,5 для обычного текста, а им набраны подписи под цифрами
     и мелкие пояснения. Затемнён до 5,2. */
  --text:#1b2835; --text2:#41566b; --muted:#5d6f81;
  --text-strong:#0f1720;          /* где раньше стоял #fff — акцентный текст */

  /* бренд */
  --accent:#ec0707; --accent-h:#bf0505; --on-accent:#ffffff;
  --accent-soft:rgba(236,7,7,.09);

  /* смысловые: на светлом фоне нужны темнее, иначе не читаются */
  --good:#1c7a4a; --good-bg:rgba(28,122,74,.10);
  --warn:#8a5d00; --warn-bg:rgba(224,166,58,.18);
  --bad:#c0271f;  --bad-bg:rgba(192,39,31,.09);

  /* подсветки и тени */
  --hover:rgba(15,23,32,.05); --hover2:rgba(15,23,32,.08);
  --shadow-lg:0 10px 28px rgba(27,40,53,.14);
  --backdrop:rgba(27,40,53,.42);
  --gate-bg:linear-gradient(180deg,#f7f9fb 0%,#e7ecf2 100%);

  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--text);font:15px/1.55 var(--sans)}
a{color:var(--text2);text-decoration:none}
a:hover{color:var(--accent-h)}
h1,h2{font-weight:600;letter-spacing:-.01em}
code,.mono{font-family:var(--mono);font-size:.92em}
.muted{color:var(--muted)}
.small{font-size:12.5px}
.nowrap{white-space:nowrap}

/* ---------- шапка: одна строка, прилипает к верху ---------- */
.ah{background:var(--panel2);border-bottom:2px solid var(--accent);position:sticky;top:0;z-index:30}
.ah-in{max-width:1280px;margin:0 auto;padding:0 20px;display:flex;align-items:center;gap:22px;min-height:54px}
.ah-brand{font:600 20px/1 Georgia,serif;color:var(--text-strong);display:flex;flex-direction:column;gap:3px;white-space:nowrap}
.ah-brand small{font:11px/1 var(--sans);color:var(--muted);letter-spacing:.14em;text-transform:uppercase}

/* верхний уровень — разделы */
.ah-nav{display:flex;gap:2px;margin-right:auto}
.ah-sec{position:relative}
.ah-sec > a{padding:8px 12px;border-radius:4px 4px 0 0;font-size:14px;display:flex;align-items:center;gap:7px;
  white-space:nowrap}
.ah-sec > a b{font-weight:400;font-size:10px;opacity:.55;margin-left:1px}
.ah-sec > a:hover{background:var(--hover);color:var(--text-strong)}
.ah-sec > a.on{background:var(--panel);color:var(--text-strong);box-shadow:inset 0 -2px 0 var(--accent)}
.ah-nav i{font-style:normal;opacity:.75}

/* второй уровень — выпадает при наведении и с клавиатуры */
.ah-drop{position:absolute;top:100%;left:0;min-width:210px;background:var(--panel);
  border:1px solid var(--line);border-top:2px solid var(--accent);border-radius:0 4px 4px 4px;
  padding:5px;display:none;box-shadow:var(--shadow-lg);z-index:40}
.ah-sec:hover > .ah-drop,
.ah-sec:focus-within > .ah-drop{display:block}
.ah-drop a{display:block;padding:7px 11px;border-radius:3px;font-size:13.5px;white-space:nowrap}
.ah-drop a:hover{background:var(--hover2);color:var(--text-strong)}
.ah-drop a.on{color:var(--accent);background:var(--accent-soft);box-shadow:inset 2px 0 0 var(--accent)}

/* Третий уровень: в выпадающем списке пункты разложены по группам.
   У раздела «Клан» их двенадцать — сплошным столбцом не читались,
   поэтому несколько групп раскладываются колонками. */
.ah-drop.cols{display:none;min-width:auto}
.ah-sec:hover > .ah-drop.cols,
.ah-sec:focus-within > .ah-drop.cols{display:flex;gap:18px}
.ah-col{min-width:170px}
.ah-col-t{display:block;padding:6px 11px 4px;font-size:10.5px;letter-spacing:.11em;
  text-transform:uppercase;color:var(--muted);border-bottom:1px solid var(--line);margin-bottom:4px}

.ah-me{display:flex;align-items:center;gap:12px;font-size:13px;color:var(--muted);white-space:nowrap}
.ah-out{border:1px solid var(--line);border-radius:3px;padding:4px 10px}
.ah-out:hover{border-color:var(--accent)}

/* Кнопка меню. На большом экране её нет: разделы и так все на виду.
   Галочки (кнопки меню и раскрытия разделов) не показываем нигде — они только
   хранят состояние. */
.ah-burger{display:none}
.ah-burger-i,.ah-sec-i,.ah-sec-x{position:absolute;opacity:0;pointer-events:none}

/* узкий экран: разделы прячутся под кнопку, а не разъезжаются в три строки */
@media (max-width:900px){
  /* Отступ сверху и снизу задан явно: без него кнопка меню прижималась
     к самому верху шапки вплотную к логотипу. */
  .ah-in{gap:10px;padding:8px 12px;flex-wrap:wrap;min-height:52px;align-content:center}
  .ah-brand{order:1}
  .ah-me{order:2;margin-left:auto;font-size:12.5px}

  /* Кнопка меню — у правого края и по центру строки, а не вплотную к логотипу. */
  /* ⚠️ `margin:0` обязательно: кнопка — это <label>, а у ярлыков формы задан
     `margin-bottom:14px`. С ним кнопка занимала строку целиком и вставала выше
     «выйти» ровно на половину этого отступа. */
  .ah-burger{order:3;display:inline-flex;align-items:center;justify-content:center;
    align-self:center;margin:0;width:40px;height:36px;border:1px solid var(--line);
    border-radius:4px;color:var(--text2);font-size:18px;cursor:pointer;user-select:none}
  .ah-burger:hover{border-color:var(--accent);color:var(--text-strong)}
  .ah-burger-i:checked ~ .ah-burger{border-color:var(--accent);color:var(--text-strong);background:var(--hover)}

  /* Меню открывается галочкой, без единой строки скрипта: на телефоне
     оно должно работать и когда js ещё не догрузился. */
  .ah-nav{display:none;order:4;width:100%;flex-direction:column;gap:0;margin-right:0;
    padding:6px 0 8px;border-top:1px solid var(--line);max-height:70vh;overflow-y:auto;
    -webkit-overflow-scrolling:touch}
  .ah-burger-i:checked ~ .ah-nav{display:flex}

  /* Раздел: слева ссылка, справа треугольник-раскрывашка, под ними — страницы.
     Меню многоуровневое, потому что второй строки шапки на телефоне больше нет. */
  .ah-sec{position:static;display:flex;flex-wrap:wrap;align-items:stretch;
    border-bottom:1px solid var(--line)}
  .ah-sec:last-child{border-bottom:0}
  .ah-sec > a{flex:1 1 auto;min-width:0;padding:11px 6px;border-radius:0;font-size:15px}
  .ah-sec > a b{display:none}
  .ah-sec > a.on{background:transparent;box-shadow:inset 3px 0 0 var(--accent);padding-left:10px}

  /* Треугольник — отдельная зона нажатия: по названию раздела уходим на его
     страницу, по треугольнику раскрываем список, не покидая текущей. */
  .ah-sec-x{position:static;opacity:1;pointer-events:auto;margin:0;
    display:flex;align-items:center;justify-content:center;flex:0 0 52px;
    color:var(--text2);font-size:20px;line-height:1;cursor:pointer;user-select:none;
    transition:transform .12s}
  .ah-sec .ah-sec-i:checked ~ .ah-sec-x{color:var(--text-strong);transform:rotate(180deg)}

  /* ⚠️ Раскрыт только тот раздел, где сейчас находимся (галочка проставлена
     в шаблоне). Все разделы разом — это меню высотой в два метра, пролистать
     такое нельзя; поэтому именно гармошка, а не развёрнутый список. */
  .ah-sec:hover > .ah-drop,
  .ah-sec:focus-within > .ah-drop,
  .ah-sec:hover > .ah-drop.cols,
  .ah-sec:focus-within > .ah-drop.cols{display:none}
  .ah-drop,.ah-drop.cols{position:static;order:9;width:100%;min-width:0;padding:2px 0 8px;
    background:var(--hover);border:0;border-radius:0;box-shadow:none}
  .ah-sec .ah-sec-i:checked ~ .ah-drop{display:block}
  .ah-sec .ah-sec-i:checked ~ .ah-drop.cols{display:flex;flex-direction:column;gap:0}
  .ah-col{min-width:0}
  .ah-col-t{padding:8px 16px 4px;border-bottom:0}
  .ah-drop a{padding:9px 16px 9px 22px;font-size:14px;white-space:normal;border-radius:0}
}

/* ---------- каркас ---------- */
.aw{max-width:1280px;margin:0 auto;padding:24px 20px 60px}
.a-h1{font-size:24px;margin:0 0 18px}
.af{max-width:1280px;margin:0 auto;padding:0 20px 30px;color:var(--muted);font-size:12.5px}
.flash{background:var(--good-bg);border:1px solid var(--good);color:var(--good);
  padding:9px 14px;border-radius:4px;margin-bottom:18px;font-size:14px}
.hint{color:var(--muted);font-size:13.5px;max-width:80ch}
.hint a{color:var(--text2);text-decoration:underline}

/* ---------- цифры ---------- */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:5px;overflow:hidden;margin-bottom:26px}
.stat{background:var(--panel);padding:14px 16px}
.stat .v{font-size:23px;font-weight:600;font-variant-numeric:tabular-nums}
.stat .v small{font-size:13px;font-weight:400;color:var(--muted)}
.stat .k{font-size:12.5px;color:var(--muted);margin-top:4px}
.stat.warn .v{color:var(--warn)}
.stat.bad .v{color:var(--bad)}

/* ---------- колонки ---------- */
.cols{display:grid;grid-template-columns:1fr 1fr;gap:26px;align-items:start}
.cols.narrow-left{grid-template-columns:320px 1fr}
.cols h2{font-size:16px;margin:0 0 10px}
@media (max-width:900px){.cols,.cols.narrow-left{grid-template-columns:1fr}}
/* ⚠️ Колонке сетки нужно разрешить сжиматься: по умолчанию у неё
   `min-width:auto`, то есть она не уже своего содержимого — и широкая таблица
   растягивала колонку, а вместе с ней и всю страницу, даже когда сама таблица
   уже лежала в своей прокрутке. */
.cols > *{min-width:0}

/* ---------- таблицы ---------- */
/* Широкую таблицу кладём в свою прокрутку, иначе она растягивает страницу
   и вбок едет всё разом — на телефоне это выглядит как сломанная вёрстка.
   Обёртку ставит admin.js: так не пришлось править полсотни шаблонов.
   ⚠️ Принудительной ширины таблице тут не задаём — см. ниже, у самой .t-scroll. */

h2{font-size:17px;margin:26px 0 10px}
.t{width:100%;border-collapse:collapse;background:var(--panel);border:1px solid var(--line);
  border-radius:5px;overflow:hidden;font-size:14px;margin-bottom:8px}
.t th{background:var(--panel2);text-align:left;padding:8px 12px;font-size:12px;
  text-transform:uppercase;letter-spacing:.05em;color:var(--text2);border-bottom:1px solid var(--line)}
.t td{padding:8px 12px;border-bottom:1px solid var(--line);vertical-align:top}
.t tr:last-child td{border-bottom:0}
.t tr:hover td{background:var(--hover)}
.t tr.on td{background:rgba(236,7,7,.10)}

/* Широкая таблица в своей рамке: прокручивается она сама, а не вся страница.
   Без этого список чатов с десятью столбцами растягивал документ, и вместе
   с таблицей уезжали шапка и меню.
   ⚠️ Ширину таблице НЕ навязываем. Было `min-width:820px` на все таблицы разом —
   и на большом экране узкая таблица из трёх столбцов в колонке шириной ~600 px
   тоже уезжала под прокрутку, обрезая последний столбец («идёт 26 мин» в сводке).
   Нижнюю границу задаёт сама таблица: заголовки не переносятся (правило ниже),
   поэтому по-настоящему широкий список упирается в них и получает прокрутку сам,
   а таблица, которая помещается, просто помещается. */
.t-scroll{max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;margin-bottom:8px}
.t-scroll > .t{margin-bottom:0}
/* Заголовок столбца в одну строку: он и есть минимальная ширина столбца.
   Без этого столбцы сминаются в лапшу из отдельных букв. */
.t th{white-space:nowrap}

/* ---------- таблицы на телефоне: столбик карточек ---------- */
/* Строка таблицы на экране 390 px не читается ни в каком виде: либо she едет
   вбок под прокруткой, либо столбцы сминаются. Поэтому на телефоне таблица
   перестаёт быть таблицей — каждая строка становится карточкой, а ячейки
   выстраиваются в столбик. Подпись ячейки берётся из заголовка столбца:
   её проставляет admin.js в `data-l`, руками в шаблонах ничего не размечено. */
@media (max-width:700px){
  .t-scroll{overflow-x:visible}
  .t-scroll > .t{min-width:0}
  .t{border:0;background:transparent;margin-bottom:14px}
  .t thead{display:none}
  .t tbody,.t tr,.t td{display:block;width:auto}
  .t tr{background:var(--panel);border:1px solid var(--line);border-radius:5px;
    margin-bottom:8px;padding:4px 0}
  .t tr:hover td,.t tr:last-child td{background:transparent}
  .t tr.on{border-color:var(--accent)}
  .t tr.on td{background:transparent}
  .t td{border-bottom:0;padding:5px 12px;display:flex;flex-wrap:wrap;gap:4px 10px;
    align-items:baseline;min-width:0}
  .t td:empty{display:none}
  /* В карточке ширины на «не переносить» нет: длинное значение уезжало за
     правый край экрана. Внутри ячейки переносим всё, включая коды и адреса. */
  .t td.nowrap,.t td .nowrap,.t td .mono,.t td code{white-space:normal;overflow-wrap:anywhere}
  .t td > *{max-width:100%}
  /* Подпись столбца слева, значение справа — как в карточке, а не как в таблице. */
  .t td[data-l]::before{content:attr(data-l);flex:0 0 38%;color:var(--muted);
    font-size:11px;letter-spacing:.05em;text-transform:uppercase;line-height:1.5}
  .t td.n{text-align:left}
  /* Первая ячейка — заголовок карточки: подпись ей не нужна. */
  .t td:first-child{font-weight:600;border-bottom:1px solid var(--line);
    margin-bottom:4px;padding-bottom:8px}
  .t td:first-child::before{display:none}
  .t tr.group{background:var(--panel2)}
  .t tr.group td{border-bottom:0;font-weight:600}
}
.t tr.group td{background:var(--panel2);font-size:12px;text-transform:uppercase;
  letter-spacing:.06em;color:var(--muted)}
.t .n{text-align:right;font-variant-numeric:tabular-nums}
/* Отрицательный итог по счёту виден сразу, без вчитывания в знак минуса */
.t .minus{color:var(--bad)}
.t details summary{cursor:pointer;color:var(--text2)}
.t pre{margin:8px 0 0;background:var(--panel2);border:1px solid var(--line);border-radius:4px;
  padding:10px;font:12px/1.5 var(--mono);white-space:pre-wrap;max-height:340px;overflow:auto}

/* Журнал действий: цветная отметка слева вместо плашки на каждой строке.
   Зелёная — что-то завели, красная — удалили, жёлтая — переключили или
   тронули доступ. Плашки в столбце «что сделал» читались бы хуже самого текста. */
.t td.au{border-left:3px solid var(--line2);padding-left:9px}
.t td.au-good{border-left-color:var(--good)}
.t td.au-warn{border-left-color:var(--warn)}
.t td.au-bad{border-left-color:var(--bad)}

/* ---------- чипы ---------- */
.chip{display:inline-block;font-size:11px;letter-spacing:.05em;text-transform:uppercase;
  padding:1px 7px;border-radius:3px;white-space:nowrap}
.chip.good{background:var(--good-bg);color:var(--good)}
.chip.warn{background:var(--warn-bg);color:var(--warn)}
.chip.bad{background:var(--bad-bg);color:var(--bad)}
.chip.mute{background:var(--hover2);color:var(--muted)}

/* ---------- вкладки ---------- */
/* ⚠️ Перенос обязателен: у flex-строки он по умолчанию выключен, и восемь
   вкладок «Людей» не влезали в экран — страница растягивалась по ширине
   и на телефоне, и на узком окне. */
.tabs{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:18px;border-bottom:1px solid var(--line)}
.tabs a{padding:9px 15px;font-size:14px;border-bottom:2px solid transparent;margin-bottom:-1px;
  white-space:nowrap}
.tabs a.on{color:var(--text-strong);border-bottom-color:var(--accent)}
/* Вкладок бывает восемь («Люди»), и в столбик они съедали пол-экрана.
   ⚠️ Блок стоит здесь, а не в общем @media выше по файлу: тот идёт раньше
   правил вкладок и проигрывал бы им по порядку. */
@media (max-width:700px){
  .tabs{gap:6px}
  .tabs a{padding:6px 10px;font-size:13px}
}

/* ---------- формы ---------- */
label{display:block;margin-bottom:14px;font-size:13.5px;color:var(--text2)}
label .hint{display:block;margin:2px 0 4px}
input,select,textarea{width:100%;background:var(--panel2);color:var(--text);
  border:1px solid var(--line);border-radius:4px;padding:9px 11px;font:14px var(--sans)}
textarea{font:13.5px/1.6 var(--sans);resize:vertical}
input:focus,select:focus,textarea:focus{outline:0;border-color:var(--accent)}
/* Галочку и переключатель не растягиваем: правило ширины ниже пишется для
   текстовых полей, и без этой оговорки чекбокс раздувался до 9em, а подпись
   уезжала от него на полторы сотни пикселей. */
input[type=checkbox],input[type=radio]{width:auto;min-width:0;flex:none;margin:0}
.chk{display:inline-flex;align-items:center;gap:8px;cursor:pointer;user-select:none}
.chk input{margin:0}

/* Переключатель «включено/выключено».
   Системная галочка в ряду с высокими полями выглядела случайной, и по ней не
   читалось состояние: рядом с надписью «включено» галочка могла стоять снятой.
   Здесь состояние видно и цветом, и положением, и подписью. */
.switch{display:inline-flex;align-items:center;gap:10px;margin-bottom:0;cursor:pointer;
  user-select:none;padding:6px 12px 6px 10px;border:1px solid var(--line);border-radius:5px;
  background:var(--panel2);white-space:nowrap}
.switch:hover{border-color:var(--line2)}
.switch:focus-within{border-color:var(--accent)}
.switch input{position:absolute;opacity:0;width:0;height:0}
.switch .sw{position:relative;flex:none;width:38px;height:20px;border-radius:11px;
  background:var(--line2);transition:background .15s}
.switch .sw::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;
  border-radius:50%;background:var(--on-accent);transition:transform .15s}
.switch input:checked + .sw{background:var(--good)}
.switch input:checked + .sw::after{transform:translateX(18px)}
.switch .on,.switch .off{font-size:13.5px}
.switch .on{display:none;color:var(--good)}
.switch .off{color:var(--muted)}
.switch input:checked ~ .on{display:inline}
.switch input:checked ~ .off{display:none}

/* Чип-переключатель в списках: то же состояние, но кликабельное */
button.chip{border:1px solid transparent;cursor:pointer;font:inherit;font-size:11.5px;
  padding:3px 9px;line-height:1.5}
button.chip:hover{filter:brightness(1.25);border-color:currentColor}

/* Список с поиском: чатов шесть десятков, простым выпадающим списком не обойтись */
.picker-search{margin-bottom:6px;width:100%}
.picker{max-height:230px;overflow-y:auto;border:1px solid var(--line);border-radius:5px;
  background:var(--panel2);padding:4px}
.picker-item{display:flex;align-items:center;gap:9px;margin:0;padding:6px 9px;border-radius:4px;
  cursor:pointer;font-size:13.5px;color:var(--text2)}
.picker-item:hover{background:var(--hover);color:var(--text-strong)}
.picker-item input{margin:0;flex:none}
.picker-item span:first-of-type{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.picker-item.hidden{display:none}
/* Две равные колонки: списки названий и кодов заполняют по половине формы */
.row-form.cols2{align-items:flex-start}
.row-form.cols2 > .ilabel{min-width:0}
.row-form.cols2 textarea{width:100%;min-width:0}

.picker-add{display:flex;gap:8px;margin-top:7px}
.picker-add input{flex:1;min-width:0}
.picker-add button{flex:none}
.picker-add input.bad{border-color:var(--bad);color:var(--bad)}
.picker-empty{padding:10px;color:var(--muted);font-size:13px}

/* Шаги в длинной форме: без них поля сливаются в сплошную простыню */
.form-step{margin:22px 0 12px;padding-top:14px;border-top:1px solid var(--line);
  font-size:13px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}
.form-step:first-of-type{margin-top:16px}

/* Пояснение под значком: текст всплывает по наведению и с клавиатуры,
   а не занимает место в форме, когда всё и так понятно. */
.i{display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;
  border:1px solid var(--line2);border-radius:50%;font:italic 600 10px/1 Georgia,serif;
  color:var(--muted);cursor:help;position:relative;vertical-align:middle;margin-left:4px}
.i:hover,.i:focus{border-color:var(--accent);color:var(--accent-h);outline:0}
/* Подсказка не должна вылезать за край экрана. Ширина задаётся с оглядкой на
   узкие окна, а горизонтальный сдвиг ставит скрипт: он меряет, куда попадает
   всплывашка, и подтягивает её обратно (--tip-x). Если сверху места нет —
   вешается класс .tip-below и подсказка уходит под значок. */
.i::after{content:attr(data-tip);position:absolute;left:50%;bottom:calc(100% + 8px);
  transform:translateX(calc(-50% + var(--tip-x, 0px)));
  width:min(300px, calc(100vw - 24px));max-width:300px;padding:9px 12px;border-radius:5px;
  /* ⚠️ Фон тёмный в обеих темах — значит, и текст светлый всегда. Был var(--text2):
     в светлой теме он тёмный, и подсказку было не прочесть. */
  background:#0f1720;border:1px solid var(--line2);color:#e6ebf1;
  font:13px/1.5 var(--sans);font-style:normal;text-align:left;white-space:normal;
  opacity:0;visibility:hidden;transition:opacity .12s;z-index:60;
  box-shadow:var(--shadow-lg)}
.i:hover::after,.i:focus::after{opacity:1;visibility:visible}
.i.tip-below::after{bottom:auto;top:calc(100% + 8px)}

/* Условия по характеристикам: строка «что — знак — сколько» */
.cond{display:flex;gap:8px;align-items:center;margin-bottom:7px}
.cond select,.cond input{flex:none;min-width:0}
/* Ширины задаём по имени поля, а не по месту в строке: слева появилась связка,
   и «первый select» перестал быть тем, что нужно тянуть. */
.cond select[name^="prop_path"]{flex:1;min-width:16em}
.cond select[name^="prop_op"]{width:4.5em}
.cond input[name^="prop_val"]{width:9em}
.cond-join{width:5em;flex:none;min-width:0}

/* Строка действия: вид, чат, бот, свой текст */
.cond.act{flex-wrap:nowrap}
.cond.act select,.cond.act input{flex:none;min-width:0}
.cond.act .act-kind{width:12em}
.cond.act .act-chat{flex:1;min-width:10em}
.cond.act .act-bot{width:9em}
.cond.act .act-text{flex:1;min-width:10em}
.cond.act .act-forward{width:11em}
.cond.act .act-options{width:12em}
.cond.act .act-open{width:12em}

/* Адресат уведомления — строка в две полосы: сверху способ и чат, снизу текст */
.cond.act.stack{flex-wrap:wrap}
.cond.act.stack .act-kind{width:16em}
.cond.act.stack .act-text{flex:1 1 100%;min-height:3.2em;width:100%}
.cond.act.stack .act-options{flex:1 1 60%;width:auto}
.cond.act.stack .cond-del{margin-left:auto}

/* Ручка перестановки: порядок строк меняет смысл, значит его надо уметь менять */
.cond-grip{flex:none;width:16px;text-align:center;cursor:grab;color:var(--muted);
  font-size:14px;line-height:1;user-select:none;border-radius:3px}
.cond-grip:hover,.cond-grip:focus{color:var(--accent-h);outline:0;background:var(--hover)}
.cond.dragging{opacity:.45}
.grip-cell{width:26px;padding-right:0}
tr[data-id].dragging{opacity:.45}
tbody.sortable tr[data-id]{cursor:default}
tbody.sort-failed{outline:1px solid var(--bad)}
.conds .cond{border-radius:4px}
.cond-none{margin:2px 0 0}

/* Строка условия по ценам длиннее: две величины, знак, множитель и время */
.cond.price{flex-wrap:nowrap}
.cond.price select{flex:none;min-width:0}
.cond.price select[name^="price_left"],
.cond.price select[name^="price_right"]{flex:1;min-width:10em}
.cond.price select[name^="price_scale"]{width:7.5em}
.cond.price select[name^="price_op"]{width:4.5em}
.cond.price input.price-within{width:5.5em}
.cond.price input.price-sum{width:8em}
.cond.price input.price-mult{width:4.5em}
.cond-unit{display:inline-flex;align-items:center;gap:5px;flex:none;margin:0;
  font-size:12.5px;color:var(--muted)}
.cond.price input.price-within{width:4.5em}

.cond-del{flex:none;width:32px;height:36px;border:1px solid var(--line);border-radius:4px;
  background:var(--panel2);color:var(--muted);cursor:pointer;font-size:16px;line-height:1}
.cond-del:hover{border-color:var(--bad);color:var(--bad)}

/* Подсказки при поиске предмета по названию */
.suggest{display:none;border:1px solid var(--line);border-top:0;border-radius:0 0 5px 5px;
  background:var(--panel2);max-height:220px;overflow-y:auto;margin-top:-6px;margin-bottom:6px}
.suggest.on{display:block}
.suggest div{padding:7px 11px;cursor:pointer;font-size:13.5px;display:flex;gap:10px;align-items:baseline}
.suggest div:hover{background:var(--hover);color:var(--text-strong)}
.suggest .code{font-family:var(--mono);font-size:11.5px;color:var(--muted)}
button,.btn{background:var(--accent);color:var(--on-accent);border:0;border-radius:4px;padding:9px 18px;
  font:600 14px var(--sans);cursor:pointer;display:inline-block}
button:hover,.btn:hover{background:var(--accent-h);color:var(--on-accent)}
button.ghost,.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--text2)}
button.ghost:hover,.btn.ghost:hover{border-color:var(--accent);color:var(--accent);background:transparent}
button.mini,.mini{font-size:12px;padding:4px 10px;font-weight:500}
/* Кнопка сразу за плашкой («идёт 26 мин» → «лог»): вплотную они читались
   как один элемент. */
.chip + .btn{margin-left:8px}
a.btnlink{display:inline-block;background:var(--accent);color:var(--on-accent);border-radius:4px;padding:4px 10px;font-size:12px}
a.btnlink:hover{background:var(--accent-h);color:var(--on-accent)}
form.inline{display:inline}
/* Кнопка-действие над таблицей: без отступа она прилипала к её рамке */
p > form.inline{display:inline-block;margin-bottom:10px}

/* Отметки «что уходит в чат»: их бывает много, и перенос строки шёл без зазора */
.marks{display:inline-flex;flex-wrap:wrap;gap:4px}
.marks .chip{margin:0}
.row-form{display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap;margin-bottom:16px}
.row-form input:not([type=checkbox]):not([type=radio]),.row-form select{width:auto;min-width:9em}
.row-form label{margin-bottom:0}
.ilabel{font-size:12.5px}
/* Подпись с галочкой стоит в строке фильтров рядом с полями: без этого
   галочка вставала над текстом, как у обычного поля ввода. */
/* ⚠️ Подпись поля в ряду фильтров стоит НАД полем — всегда.
   По умолчанию текст подписи идёт в одну строку с полем, а поясняющий `.hint`
   (у него `display:block`) эту строку разрывает. Получалось, что у поля без
   пояснения подпись слева, у поля с пояснением — сверху, и ряд выглядел
   собранным наспех. Поясняющий текст здесь ставим в ту же строку, что и
   подпись: так у всех полей заголовок ровно одной высоты. */
/* ⚠️ Подпись НЕ выкладываем флексом: у флекс-элементов `display:inline`
   превращается в `block`, и поясняющий `.hint` вставал третьей строкой вместо
   того, чтобы идти в одну строку с подписью. Обычный блок: строка подписи,
   под ней поле. */
.row-form .ilabel{display:block;white-space:nowrap}
.row-form .ilabel > .hint{display:inline;margin:0}
/* Само поле уже поля-подписи быть может, а вот подпись переносить нельзя:
   иначе у одного столбца заголовок в две строки, у соседних в одну, и ряд
   стоит вразнобой. Ширину столбца задаёт та строка, что длиннее. */
/* Поле под подписью — блоком. ⚠️ Галочку исключаем: с `display:block` она
   уезжала на строку выше своей подписи. */
.row-form .ilabel > input:not([type=checkbox]):not([type=radio]),
.row-form .ilabel > select{display:block;margin-top:4px}

/* Галочка подписи над собой не имеет, поэтому её ровняем по нижнему краю ряда
   и даём высоту поля ввода — тогда она стоит на одной линии с полями. */
.ilabel.chk{display:flex;flex-direction:row;align-items:center;gap:7px;align-self:flex-end;
  min-height:38px;font-size:13.5px;white-space:normal}
/* Последний ряд формы: без зазора снизу, иначе под ним провал до таблицы */
.row-form.last{margin-bottom:0}
.card{background:var(--panel);border:1px solid var(--line);border-radius:6px;padding:20px 22px;margin-bottom:22px}
.card h2{margin-top:0}
.card.wide{max-width:820px}
/* Строки условий длинные — форме правила нужно больше места */
.card.wide.roomy{max-width:1060px}
.err{background:var(--bad-bg);border:1px solid var(--bad);color:var(--bad);
  padding:9px 12px;border-radius:4px;margin-bottom:14px;font-size:13.5px}

/* ---------- журнал ---------- */
pre.log{background:var(--panel2);border:1px solid var(--line);border-radius:5px;padding:14px;
  font:12.5px/1.6 var(--mono);white-space:pre-wrap;word-break:break-word;max-height:70vh;overflow:auto;color:var(--text2)}

/* ---------- вход ---------- */
body.plain{display:flex;align-items:center;justify-content:center;min-height:100vh;
  background:var(--gate-bg)}
.gate{width:100%;max-width:390px;padding:20px}
.gate-brand{text-align:center;margin-bottom:24px;font:600 30px/1 Georgia,serif;color:var(--text-strong)}
.gate-brand small{display:block;font:11px/1.6 var(--sans);color:var(--muted);
  letter-spacing:.18em;text-transform:uppercase;margin-top:6px}
.gate .card{margin-bottom:0}
.gate h2{margin:0 0 16px;font-size:19px}
.gate button{width:100%;margin-top:4px}
.gate .hint{text-align:center;margin:14px 0 0}

/* Отзыв, у которого адрес, машина или персонаж совпали с другим отзывом */
.t tbody tr.warnrow{background:var(--warn-bg)}
.t tbody tr.warnrow:hover{background:var(--warn-bg)}

/* автор закрыт для сайта — строка отзыва помечена красным */
tr.blockedrow{background:var(--bad-bg)}
tr.blockedrow:hover{background:var(--bad-bg)}

/* Строка «требует внимания» над сводкой: то, что ждёт человека, а не движок */
.todo{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 14px;
  padding:10px 14px;background:var(--panel);border:1px solid var(--line);border-radius:5px}
.todo-t{color:var(--muted);font-size:11px;letter-spacing:.1em;text-transform:uppercase;margin-right:4px}
.todo .chip{text-decoration:none}
.todo .chip:hover{filter:brightness(1.25)}
.todo .chip b{font-weight:700;margin-right:3px}

/* ================= Окно поверх страницы =================
   Своего окна в админке до сих пор не было: списки открывались отдельной
   страницей. Для мелочи вроде «какие у него подписки» это лишний переход,
   а браузерный <dialog> умеет ровно то, что нужно, и сам закрывается по Esc. */
/* ⚠️ Здесь стояло `var(--b, #2a3441)` — переменной `--b` не существует,
   и рамка всегда бралась из запасного тёмного цвета. */
dialog.k-modal{border:1px solid var(--line);border-radius:8px;padding:20px;
	max-width:min(900px, 92vw);background:var(--panel, #1b2430);color:inherit}
dialog.k-modal::backdrop{background:var(--backdrop)}
dialog.k-modal h3{margin:0 0 14px}
dialog.k-modal .t{margin-bottom:14px}
dialog.k-modal p{margin:0}

/* ---------- логин игрока: один вид на всех страницах ----------
   Значок склонности, значок клана (кликабельный), логин, уровень, «информация».
   Разметку даёт `Kodg\UserTag::render()`. Значки приходят из самой игры и
   имеют свой размер, поэтому выравниваем их по строке принудительно. */
.utag{display:inline-flex;align-items:center;gap:4px;white-space:nowrap;line-height:1}
.utag b{font-weight:600}
.utag a{color:inherit}
.utag a:hover b{color:var(--accent-h)}
/* ⚠️ Размеры — родные, как их отдаёт игра: склонность 12×15, эмблема клана
   24×15, «информация» 12×11. Я сперва задал склонности 12×12, и значок плющило.
   Проверять по naturalWidth/naturalHeight, а не на глаз. */
.utag-al{width:12px;height:15px;display:block}
.utag-kl img{width:24px;height:15px;display:block;border-radius:2px}
.utag-lv{color:var(--muted);font-size:12px}
/* ⚠️ «i» не гасим: это значок игры, и приглушённый он читался как выключенный. */
.utag-inf img{width:12px;height:11px;display:block}
/* Наш значок «в списке людей» — контуром, чтобы не спорил с пёстрыми
   значками склонности и клана. */
.utag-ppl{display:block;color:var(--muted);line-height:0}
.utag-ppl:hover{color:var(--accent)}

/* Кнопка-значок: там, где слово занимало полстроки, а нажимают редко.
   Смысл держится подсказкой (`title`) и подтверждением. */
.iconbtn{background:none;border:1px solid var(--line);border-radius:4px;padding:4px 6px;
  color:var(--muted);line-height:0;cursor:pointer;transition:.12s}
.iconbtn:hover{background:var(--hover);border-color:var(--line2)}
.iconbtn.bad:hover{color:var(--bad);border-color:var(--bad)}
.iconbtn.ok:hover{color:var(--good);border-color:var(--good)}

/* ---- метки под логином и действия значками ----
   ⚠️ В строку метки растягивали столбец на пол-экрана, и таблица уезжала
   за край вместе с кнопками. Своей строкой под именем они занимают ту же
   ширину, что и сам логин, и таблица помещается. */
.chips{display:flex;flex-wrap:wrap;gap:3px;margin-top:3px;white-space:normal}
.chips .chip{margin:0}

/* Действия — в ряд, без переносов: их два-четыре и они одинаковой ширины. */
.acts{display:flex;gap:4px;align-items:center}
.acts form{margin:0}

/* ---- карточка предмета (`kodg_item_card()`) ----
   Один вид на всю админку: «Оценка инвентаря», избранное аукциона,
   справочники предметов. Раньше правила жили прямо в шаблоне /inv, и когда
   тот же вид понадобился на других страницах, стили пришлось бы копировать.
   ⚠️ Карточкой показываем ПРЕДМЕТ, а не строку целиком: числовые столбцы
   остаются столбцами — их сравнивают глазом сверху вниз. */
.invt td{vertical-align:top}
.ic{display:flex;gap:10px;align-items:flex-start}
.ic-pic{width:44px;height:44px;flex:0 0 44px;object-fit:contain;border:1px solid var(--line);
  border-radius:4px;background:var(--bg)}
.ic-pic.nopic{display:block}
.ic-b{min-width:0}
.ic-n{font-weight:600;margin-bottom:2px}
.fact{display:block;font-size:12px;color:var(--muted)}
.fact b{color:var(--text2);font-weight:600}
.fact.soon b{color:var(--bad)}
/* Характеристики показываем целиком, не пряча за раскрывашкой: их и смотрят. */
.ic-par{margin-top:4px;font-size:12px;line-height:1.45;color:var(--text2)}
.ic-descr{margin-top:4px;font-size:12px;line-height:1.45;color:var(--muted)}
/* Надпись на подарке — курсивом и с полосой слева: это чужие слова,
   а не свойство предмета, и путать их не надо. */
.ic-note{margin-top:4px;padding-left:8px;border-left:2px solid var(--line2);
  font-size:12px;line-height:1.45;font-style:italic;color:var(--text2)}
.fed{font-size:11px;padding:0 4px;border:1px solid rgba(128,128,128,.4);border-radius:2px;
  vertical-align:2px;font-weight:400}

/* Форум в админке. Поле на всю ширину своей подписи в ряду формы раздела:
   обычное правило ряда даёт полям ширину по содержимому (min 9em). */
.row-form .ilabel.fill{min-width:0}
.row-form .ilabel.fill > input:not([type=checkbox]):not([type=radio]){width:100%;min-width:0}
/* Действия у темы — переносятся строкой, а не вылезают из таблицы: список «перенести…»
   с width:100% в ячейке без переноса раздвигал её, и «Удалить» уезжала за край */
.f-acts{display:flex;flex-wrap:nowrap;gap:6px;align-items:center}
@media (max-width:700px){.f-acts{flex-wrap:wrap}}
.f-acts form{margin:0}
.f-acts select{width:auto;min-width:0;max-width:12em;padding:6px 8px;font-size:13px}
.f-filter input[name=q]{min-width:16em}
.f-filter .chk{align-self:center}
tr[data-sec].dragging{opacity:.45}
/* Вложенный раздел: сдвинута вся ячейка — и название, и описание, слева линия вложенности.
   Раньше отступ был только у названия («— Цены»), а описание шло от края. */
.t td.f-sub{position:relative;padding-left:40px}
.t td.f-sub::before{content:'';position:absolute;left:18px;top:0;bottom:0;border-left:2px solid var(--line2)}
.t td.f-sub::after{content:'';position:absolute;left:18px;top:17px;width:12px;border-top:2px solid var(--line2)}

/* Спиритическая связь (/drivers): столбики боёв по неделям */
.dbars{display:flex;align-items:flex-end;gap:4px;height:180px;padding:8px 10px 0;background:var(--panel);border:1px solid var(--line);border-radius:6px}
.dbar{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;height:100%;min-width:0}
.dbar-b{display:block;width:100%;max-width:28px;min-height:1px;background:var(--accent);border-radius:3px 3px 0 0;opacity:.85}
.dbar-n{font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums}
.dbar-d{font-size:10px;color:var(--muted);padding:4px 0 6px;white-space:nowrap}
@media (max-width:700px){.dbar-d{font-size:0}.dbars{height:140px}}
.dpairs .dp-tg{width:30px;padding-right:0}
.dpairs .dp-tg .iconbtn{width:24px;height:24px;line-height:22px;padding:0;text-align:center}
.dpairs tbody.dp + tbody.dp{border-top:1px solid var(--line)}
.dpairs tbody.dp-open .dp-head{background:var(--hover)}
.dpairs tr.dp-sub td{background:var(--panel2);font-size:13px;padding-top:5px;padding-bottom:5px}
