:root{--bg:#0f1017;--panel:#1b1d27;--line:#2b2e3c;--ink:#d7d8e0;--dim:#8a8ea3;
      --accent:#c8a24a;--ok:#5fae7a;--bad:#c96a6a;}
*{box-sizing:border-box;}
html,body{margin:0;height:100%;background:var(--bg);color:var(--ink);
  font:15px/1.5 -apple-system,Segoe UI,Roboto,sans-serif;overflow:hidden;}
#game{position:fixed;inset:0;}
/* Жесты обслуживает игра (game.js::_initTouch): без touch-action браузер сначала прокрутит
   страницу и отмасштабирует её сам, и до сцены щипок не доедет. */
#game canvas{display:block;margin:auto;touch-action:none;}
button{background:#242736;color:var(--ink);border:1px solid var(--line);border-radius:7px;
  padding:8px 13px;cursor:pointer;font-size:14px;}
button:hover{border-color:var(--accent);}
input,select,textarea{background:#0f1017;color:var(--ink);border:1px solid var(--line);
  border-radius:7px;padding:9px;width:100%;font-size:14px;}
.overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;
  background:rgba(8,9,14,.72);z-index:20;}
.card{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:20px;
  width:min(380px,92vw);}
.card h2{margin:0 0 4px;color:var(--accent);letter-spacing:2px;font-size:20px;}
.card .sub{color:var(--dim);font-size:13px;margin-bottom:14px;}
.row{display:flex;gap:8px;margin-bottom:8px;}
.hint{color:var(--dim);font-size:12px;}
.err{color:var(--bad);font-size:13px;min-height:18px;}
/* Юридическая сноска на экране входа: 18+ и конклюдентный акцепт. Мелко, но читаемо —
   это не декор, а обязательное информирование. */
.legalNote{margin-top:12px;padding-top:11px;border-top:1px solid var(--line);
  color:var(--dim);font-size:11.5px;line-height:1.55;}
.legalNote a{color:var(--accent);}
/* Путь назад с экрана входа: до авторизации на сайт иначе не выйти. */
.backSite{margin-top:10px;text-align:center;font-size:12px;}
.backSite a{color:var(--dim);text-decoration:none;}
.backSite a:hover{color:var(--accent);}
.age{display:inline-block;border:1px solid var(--accent);color:var(--accent);border-radius:4px;
  padding:0 5px;font-size:11px;letter-spacing:.5px;}

/* ================= карточка входа (вход · регистрация · восстановление) =================
   ⚠️ Оверлей входа — ПРОКРУЧИВАЕМЫЙ, в отличие от общего .overlay. Общий центрирует содержимое
   (align-items:center), и содержимое выше экрана обрезается С ОБЕИХ сторон, докрутить нельзя.
   Карточка входа выросла: две вкладки, три поля, подсказка, кнопка Google и юридическая сноска —
   на 360×640 с выехавшей клавиатурой ей остаётся около 300 px, и без прокрутки зарегистрироваться
   с телефона было бы физически невозможно. Общий .overlay не трогаем: на нём держатся заставка
   и модальные окна, которым прокрутка не нужна.
   `margin:auto 0` вместо align-items:center — так карточка центрируется, пока помещается, и
   честно уезжает вверх, когда перестала (у align-items:center верх уходит в недосягаемое). */
.overlay.auth{align-items:flex-start;overflow-y:auto;
  padding:calc(16px + env(safe-area-inset-top)) 12px calc(16px + env(safe-area-inset-bottom));}
.overlay.auth .card{margin:auto 0;}
.authTabs{margin:12px 0 14px;}
.authTabs .nbtab{padding:9px 6px;font-size:13.5px;}
/* Поле пароля с глазом: кнопка внутри рамки, поле уступает ей место справа. */
.pwrow{position:relative;}
.pwrow input{padding-right:42px;}
.eye{position:absolute;right:2px;top:2px;bottom:2px;width:38px;padding:0;
  background:none;border:none;color:var(--dim);font-size:15px;line-height:1;cursor:pointer;}
.eye:hover{color:var(--accent);background:none;}
/* Живая подсказка о пароле. Отдельно от .err: это не ошибка, а состояние — красным здесь
   человека ругали бы за то, что он ещё печатает. */
.fhint{min-height:16px;font-size:12px;color:var(--dim);margin:-2px 0 6px;}
.fhint.bad{color:var(--bad);}
.fhint.ok{color:var(--ok);}
/* Пустая подсказка не занимает места: на вкладке «Вход» её не бывает вовсе, и зарезервированная
   строка отрывала бы кнопку от полей без всякой причины. Место под ОШИБКУ (.err) резервируем
   по-прежнему — она появляется и исчезает на одной и той же форме, и прыжок кнопки под пальцем
   куда неприятнее пустой строки. */
.fhint:empty{min-height:0;margin:0;}
/* Фокус — в цвет карточки. Системная рамка здесь белая и на золоте выглядит чужой; убирать её
   насовсем нельзя (с клавиатуры иначе не видно, где ты), поэтому заменяем, а не отключаем. */
.overlay.auth input:focus-visible{outline:2px solid var(--accent);outline-offset:0;
  border-color:var(--accent);}
/* Одна кнопка во всю ширину вместо двух рядом: пара «войти | регистрация» и была тем самым
   «смешанным функционалом», в котором терялся игрок. */
.authGo{width:100%;padding:11px;font-size:15px;font-weight:600;
  background:var(--accent);color:#171922;border-color:var(--accent);}
.authGo:hover:not(:disabled){filter:brightness(1.08);}
.authGo:disabled{opacity:.6;cursor:default;}
.authAlt{min-height:20px;margin-top:9px;text-align:center;}
.authAlt:empty{min-height:0;margin-top:0;}
.linkBtn{background:none;border:none;padding:2px 4px;color:var(--dim);font-size:12.5px;
  text-decoration:underline;text-underline-offset:2px;cursor:pointer;}
.linkBtn:hover{color:var(--accent);background:none;border-color:transparent;}
/* Выход из тупика подсвечивается ровно тогда, когда в тупик уткнулись (пароль не подошёл). */
.linkBtn.hot{color:var(--accent);}
.authDone{font-size:13.5px;line-height:1.55;margin:10px 0 14px;}
.authDone b{color:var(--accent);font-weight:600;}
.authDone.dim{color:var(--dim);font-size:12.5px;}
.gitem{padding:9px;border:1px solid var(--line);border-radius:8px;margin-bottom:6px;cursor:pointer;}
.gitem:hover{border-color:var(--accent);background:#232635;}

/* ================= органы управления поверх фона: HUD в игре и шапка «Дел» =================
   Один язык на обе страницы (владелец, 09.08.2026, пункт 15). До этого HUD был
   rgba(20,22,32,.86) / радиус 7 / шрифт 14, а шапка «Дел» — rgba(…,.72) / радиус 8 / шрифт 13,
   и одинаковые по смыслу элементы («выйти» и «⚙», ник и заголовок дела) выглядели в меню и в
   бою по-разному.
   Высота ряда — ровно 34 px (13.5 × line-height 18 + 2×7 padding + 2 рамки): под неё уже
   подогнаны кнопки и ползунок панели звука (.audbtn), которая живёт и там, и там. */
#hud button:not(.manaPlus),.gsel-out,.manaChip{
  background:rgba(20,22,32,.8);border:1px solid var(--line);color:#cbc7bb;
  border-radius:9px;padding:7px 13px;font-size:13.5px;line-height:18px;
  cursor:pointer;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);}
#hud button:not(.manaPlus):hover,.gsel-out:hover{border-color:var(--accent);color:#fff;}
/* Чип маны — пилюля: это не кнопка, а показание, и форма говорит об этом раньше подписи.
   Кнопка кабинета (.gsel-cab) намеренно осталась прямоугольной — она как раз кнопка. */
.manaChip{border-radius:999px;}

/* ---- счётчик маны: ОДИН элемент на обе поверхности ----
   Раньше это были два разных чипа: пилюля «⟡ 12,0 маны» на экране дел и прямоугольный badge
   «мана: ⟡ 12,0» в HUD. Разметку обоих пишет UI.setMana — правится только там и здесь. */
.manaChip{display:inline-flex;align-items:center;gap:7px;color:#e7e3d8;white-space:nowrap;
  padding:4px 5px 4px 13px;cursor:default;}
.manaChip b{color:var(--accent);font-variant-numeric:tabular-nums;}
/* Золотой «＋» — ВНУТРИ чипа, а не отдельной кнопкой рядом: покупка это продолжение счётчика
   (владелец, 09.08.2026). 24 px держат общую высоту ряда 34; пальцу его растит блок hover:none.
   Из общего правила кнопок он исключён явным :not(.manaPlus) — иначе в HUD (там он <button>)
   селектор с id перебивал бы золото серым фоном, и чип в игре снова отличался бы от «Дел». */
.manaPlus{flex:none;width:24px;height:24px;padding:0;border-radius:999px;
  display:flex;align-items:center;justify-content:center;
  background:rgba(200,162,74,.16);border:1px solid rgba(200,162,74,.55);color:var(--accent);
  font-size:16px;line-height:1;cursor:pointer;}
.manaPlus:hover{background:var(--accent);border-color:var(--accent);color:#141019;}

/* HUD */
#hud{position:fixed;top:calc(10px + env(safe-area-inset-top));left:0;right:0;
  display:flex;gap:10px;align-items:center;z-index:10;pointer-events:none;
  padding:0 calc(14px + env(safe-area-inset-right)) 0 calc(14px + env(safe-area-inset-left));}
#hud .badge{background:rgba(20,22,32,.8);border:1px solid var(--line);border-radius:9px;
  padding:6px 11px;pointer-events:auto;}
/* Заголовок дела ограничен по ширине: иначе длинное название разносит левую группу HUD
   (название + мана) под центрированную панель музыки. */
#hud .title{color:var(--accent);max-width:32vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
#hud .spacer{flex:1;}
#hud button{pointer-events:auto;white-space:nowrap;}
#hud .manaChip{pointer-events:auto;}
/* Сжимается только заголовок дела (у него многоточие) — кнопки при узком окне остаются целыми,
   а не переносят текст внутри себя. */
#hud>*{flex:none;}
#hud .title{flex-shrink:1;min-width:0;}

/* ---- звук (#8): тот же язык, что у остальных элементов HUD ----
   Один и тот же узел живёт в двух местах: в игре UI.dockAudio переносит его в #hud, и раскладку
   держит общий flex — поэтому панель звука больше НЕ «залезает» на кнопки при смене масштаба.
   Вне игры (вход, выбор дела) HUD скрыт, и панель висит в левом нижнем углу: единственный угол,
   свободный на ВСЕХ экранах меню (сверху — шапка «Дел» с ником и маной, в центре — карточка). */
#audioBar{display:flex;align-items:center;gap:6px;pointer-events:auto;}
/* ⚠️ `:not(.in-menu)` обязателен. Класс .in-menu вешается, когда панель переезжает в меню ⚙, но
   в DOM она при этом остаётся `position:fixed` из этого правила — и продолжала висеть в левом
   нижнем углу экрана, хотя её узел лежит внутри меню в правом верхнем. Пользователь видел третью
   панель звука неизвестно откуда (жалоба владельца 05.09.2026). На телефоне это было так же и
   до переноса — просто там угол пустой и на глаза не бросалось. */
#audioBar:not(.in-hud):not(.in-menu){position:fixed;z-index:45;
  left:calc(14px + env(safe-area-inset-left));bottom:calc(14px + env(safe-area-inset-bottom));}
/* В меню ⚙ панель — обычная строка меню: те же поля и та же высота, что у .gearRow рядом,
   иначе звук выглядел бы вставкой из другого интерфейса. */
#audioBar.in-menu{position:static;width:100%;padding:5px 11px;gap:8px;}
#audioBar.in-menu .audvol{flex:1;}
/* 34 px — ровно высота кнопок HUD («дело», «схема», «обвинить»): у них она набирается из padding и
   строки, у иконок и ползунка своего текста нет, поэтому задана числом. */
/* Фон и скругление — те же, что у общего блока органов управления: панель звука живёт и в HUD,
   и в шапке «Дел», и любое расхождение видно на обеих страницах сразу (приёмка сравнивает
   .audbtn и .audvol с кнопкой «обвинить»). */
.audbtn{background:rgba(20,22,32,.8);border:1px solid var(--line);border-radius:9px;color:var(--ink);
  width:34px;height:34px;padding:0;font-size:15px;line-height:1;cursor:pointer;}
.audbtn:hover{border-color:var(--accent);}
.audvol{display:flex;align-items:center;height:34px;padding:0 10px;
  background:rgba(20,22,32,.8);border:1px solid var(--line);border-radius:9px;}
/* Ползунок — скруглённая «пилюля», заливка градиентом (её красит paintVol), «точки» не видно. */
#audVol{-webkit-appearance:none;appearance:none;width:64px;height:6px;padding:0;border:none;
  border-radius:999px;background:#3a3f55;outline:none;cursor:pointer;}
#audVol::-webkit-slider-runnable-track{-webkit-appearance:none;height:6px;border-radius:999px;background:transparent;}
#audVol::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:14px;height:14px;
  background:transparent;border:none;cursor:pointer;margin-top:-4px;}
#audVol::-moz-range-track{height:6px;border-radius:999px;background:transparent;}
#audVol::-moz-range-thumb{width:14px;height:14px;background:transparent;border:none;cursor:pointer;}
#prompt{position:fixed;bottom:calc(24px + env(safe-area-inset-bottom));left:0;right:0;
  text-align:center;z-index:10;color:var(--accent);text-shadow:0 1px 3px #000;display:none;}

/* ---- джойстик: появляется под пальцем на левой половине экрана (game.js::_initTouch) ----
   Живёт в DOM, а не в канве: это орган управления в CSS-пикселях, он не должен ни масштабироваться
   зумом карты, ни мылиться разрешением рендера. Событий не ловит — их слушает сама канва. */
#stick{position:fixed;z-index:12;width:0;height:0;pointer-events:none;touch-action:none;}
#stick .stick-ring,#stick .stick-knob{position:absolute;left:0;top:0;border-radius:50%;}
#stick .stick-ring{width:104px;height:104px;transform:translate(-50%,-50%);
  border:2px solid rgba(200,162,74,.42);background:rgba(15,16,23,.30);}
#stick .stick-knob{width:46px;height:46px;transform:translate(-50%,-50%);
  background:rgba(200,162,74,.55);box-shadow:0 2px 12px rgba(0,0,0,.55);}

/* Зум карты для мыши (пункт 30). Показывается только там, где щипка нет: у сенсорного экрана свой
   жест, и кнопки там лишние. Прячем ПО УКАЗАТЕЛЮ, а не по ширине окна — планшет широкий, но
   управляется пальцем. Скрыт вместе с HUD: #hud{display:none} вне партии кнопок не касается,
   поэтому за видимость отвечает класс на body, который ставит UI при входе в игру и снимает при
   выходе. */
#zoomBox{position:fixed;right:calc(14px + env(safe-area-inset-right));top:50%;transform:translateY(-50%);
  z-index:12;display:none;flex-direction:column;gap:6px;}
body.in-game #zoomBox{display:flex;}
#zoomBox button{width:38px;height:38px;padding:0;font-size:17px;line-height:1;
  background:rgba(20,22,32,.8);border:1px solid var(--line);color:#cbc7bb;border-radius:9px;
  cursor:pointer;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);}
#zoomBox button:hover{border-color:rgba(200,162,74,.55);color:var(--accent);}
@media (hover:none) and (pointer:coarse){ body.in-game #zoomBox{display:none;} }

/* Имена над персонажами. Живут в DOM, а НЕ в канве: Phaser рисует сцену в CSS-пикселях, и на
   retina браузер растягивает всю канву вдвое — мелкий шрифт от этого мылится сильнее всего.
   DOM-текст рисуется в родном разрешении экрана. Слой ниже HUD (10) и панели диалога (15). */
#npcNames{position:fixed;inset:0;z-index:5;pointer-events:none;overflow:hidden;
  font-family:Georgia,"Times New Roman",serif;}
/* Прозрачность считает game.js (дистанция + гашение у верхней кромки) и пишет инлайном каждый кадр,
   поэтому её тут НЕТ и она не в transition — иначе анимация гналась бы за покадровым значением. */
.nname{position:absolute;left:0;top:0;transform:translate(-50%,-100%);white-space:nowrap;
  text-align:center;will-change:transform,opacity;transition:color .18s ease;
  /* вместо чёрной плашки — тёмное гало: читается на траве, воде и стенах, но не режет кадр */
  text-shadow:0 1px 2px rgba(0,0,0,.95),0 0 4px rgba(0,0,0,.85),0 0 10px rgba(0,0,0,.5);}
.nname b{display:block;font-weight:400;font-size:13px;letter-spacing:.05em;color:#e8e1cf;}
.nname i{display:none;font-style:normal;font-size:11px;letter-spacing:.02em;color:#bdb49c;}
.nname.near b{color:var(--accent);}
.nname.near i{display:block;}                      /* роль показываем только когда в шаге разговора */
.nname.mate b{color:#a8c6ea;}                      /* партнёры по коопу — холодный оттенок */

/* Перф-оверлей (клавиша F). Инструмент, не интерфейс: включается вручную и по умолчанию скрыт. */
#perfHud{position:fixed;left:12px;bottom:12px;z-index:49;pointer-events:none;white-space:pre;
  font:12px/1.45 ui-monospace,SFMono-Regular,Menlo,monospace;color:#9fe0a8;
  background:rgba(10,12,18,.82);border:1px solid var(--line);border-radius:8px;padding:7px 10px;}

/* dialogue panel */
#dialogue{position:fixed;right:0;top:0;bottom:0;width:min(440px,94vw);background:var(--panel);
  border-left:1px solid var(--line);z-index:15;display:none;flex-direction:column;}
#dialogue .dhead{position:relative;height:210px;padding:0;border-bottom:1px solid var(--line);overflow:hidden;background:#12131b;}
#dialogue .portrait{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:50% 8%;display:block;}
#dialogue .dhead-grad{position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(15,16,23,.12) 0%,rgba(15,16,23,0) 38%,rgba(15,16,23,.72) 78%,rgba(15,16,23,.94) 100%);}
#dialogue .dhead-meta{position:absolute;left:16px;right:16px;bottom:12px;z-index:1;}
#dialogue .dname{font-weight:600;font-size:22px;font-family:Georgia,serif;color:#f0ecdf;text-shadow:0 2px 8px rgba(0,0,0,.7);}
#dialogue .drole{color:#cbb98a;font-size:13px;font-style:italic;text-shadow:0 1px 6px rgba(0,0,0,.8);}
#dialogue #dClose{position:absolute;top:9px;right:10px;z-index:2;width:30px;height:30px;padding:0;
  background:rgba(15,16,23,.6);border:1px solid rgba(200,162,74,.3);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);}
#dialogue .log{flex:1;overflow:auto;padding:12px;display:flex;flex-direction:column;gap:8px;}
#dialogue .msg{padding:8px 10px;border-radius:9px;max-width:88%;white-space:pre-wrap;}
#dialogue .msg.me{align-self:flex-end;background:#233;}
#dialogue .msg.npc{align-self:flex-start;background:#20232f;border:1px solid var(--line);}
#dialogue .who{color:var(--accent);font-size:11px;}
#dialogue .dinput{display:flex;gap:8px;padding:12px;border-top:1px solid var(--line);}
#dialogue .dhint{padding:0 12px 10px;}

/* notebook + accuse (bottom-left slide) */
.tray{position:fixed;left:12px;bottom:calc(12px + env(safe-area-inset-bottom));width:min(340px,90vw);
  max-height:60vh;max-height:60dvh;overflow:auto;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px;z-index:15;display:none;}
.tray h3{margin:2px 0 10px;font-size:12px;color:var(--dim);text-transform:uppercase;letter-spacing:1px;}
.ev{padding:7px 9px;border-bottom:1px solid var(--line);font-size:13px;}
.ev b{color:var(--accent);}
.tag{display:inline-block;background:#2a2d3c;border:1px solid var(--line);border-radius:6px;
  padding:2px 7px;margin:2px;font-size:12px;}
.verdict{padding:10px;border-radius:8px;margin-top:8px;}
.verdict.ok{background:#1c2b22;border:1px solid var(--ok);}
.verdict.no{background:#2b1c1c;border:1px solid var(--bad);}
label.slot{display:block;color:var(--dim);font-size:12px;margin:8px 0 3px;}

/* google auth block (по образцу coin-safe) */
.divider{display:flex;align-items:center;gap:10px;color:var(--dim);font-size:12px;margin:14px 0 10px;}
.divider::before,.divider::after{content:"";flex:1;height:1px;background:var(--line);}
.gblock{border:1px solid var(--line);border-radius:9px;background:#161822;padding:12px;}
.gblock .glabel{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--ink);margin-bottom:10px;}
.gblock .gbtn{display:flex;justify-content:center;min-height:40px;}

/* блокнот: табы + провенанс записи (п.10) */
.nbtabs{display:flex;gap:4px;margin-bottom:8px;}
.nbtab{flex:1;padding:6px 3px;font-size:12px;text-align:center;cursor:pointer;border:1px solid var(--line);
  border-radius:7px;background:#171922;color:var(--dim);}
.nbtab.on{background:#242736;color:var(--ink);border-color:var(--accent);}
.nbtab .cnt{opacity:.55;font-size:11px;}
.ev .prov{display:block;margin-top:3px;font-size:11px;color:var(--dim);line-height:1.35;}
.ev .prov b{color:var(--accent);font-weight:600;}

/* Граф расследования (п.11) — центр-модалка, доска карточек + SVG-связи */
#graph{position:fixed;inset:0;z-index:65;background:rgba(6,7,12,.72);align-items:center;justify-content:center;display:none;}
.graph-panel{position:relative;width:min(1120px,95vw);height:88vh;display:flex;flex-direction:column;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;box-shadow:0 14px 48px rgba(0,0,0,.55);}
.graph-panel .ghead{display:flex;align-items:center;gap:8px;padding:16px 20px 8px;}
.graph-panel .ghead h2{flex:1;margin:0;color:var(--accent);font-family:Georgia,serif;font-size:20px;}
.graph-panel .ghead .sub{color:var(--dim);font-size:12px;}
/* Прогресс дела (пункт 25) — в шапке схемы и над текстом дела. Досчитанный до конца счётчик
   загорается золотом: это единственный честный сигнал «здесь искать больше нечего». */
.gprog{display:flex;gap:6px;flex-wrap:wrap;align-items:center;}
.gprog:empty{display:none;}
.gprogPart{display:inline-flex;gap:4px;align-items:center;white-space:nowrap;background:#171922;
  border:1px solid var(--line);border-radius:999px;padding:2px 9px;color:var(--dim);font-size:12px;}
.gprogPart b{color:#cbc7bb;font-variant-numeric:tabular-nums;}
.gprogPart.done,.gprogPart.done b{color:var(--accent);}
.gprogPart.done{border-color:var(--accent);}
/* Заголовок раздела внутри окна «Дело» (пункт 49). Мелкий и капсом, а не второй крупный
   заголовок: он делит текст, но не спорит со словом «Дело» в шапке окна. */
#brBody .brSec{margin:16px 0 6px;color:var(--accent);font-family:Georgia,serif;font-size:12px;
  font-weight:700;letter-spacing:.08em;text-transform:uppercase;}
#brBody .brSec:first-child{margin-top:0;}
/* Подпись счётчика (пункт 49). Приглушена намеренно: она поясняет плашки, а не спорит с ними. */
.gprogLbl{color:var(--dim);font-size:12px;white-space:nowrap;}
#brProgress{display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin:-6px 0 14px;}
#brProgress:empty{display:none;}
.graph-board{position:relative;flex:1;overflow:hidden;}
.graph-grid{position:absolute;inset:0;z-index:1;}
svg.gedges{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:visible;}
/* карточка-узел на кольце: компактная, по наведению раскрывается поверх соседей */
.gnode{position:absolute;transform:translate(-50%,-50%);width:150px;background:#171922;border:1px solid var(--line);
  border-radius:10px;padding:6px 8px;z-index:2;transition:width .12s,opacity .12s,border-color .12s,box-shadow .12s;}
.gnode .grow{display:flex;gap:7px;align-items:center;}
.gnode.dim{opacity:.5;border-style:dashed;}
.gnode.removed{border-color:#5a3a3a;}
.gnode.conn{border-color:var(--accent);}
.gnode:hover,.gnode.open{width:240px;opacity:1;z-index:5;border-color:var(--accent);box-shadow:0 8px 26px rgba(0,0,0,.6);}
.gnode .gpic{width:36px;height:36px;border-radius:8px;object-fit:cover;object-position:50% 12%;flex:none;background:#222;}
.gnode .gname{font-size:12px;font-weight:600;color:#f0ecdf;line-height:1.12;}
.gnode .gsub{font-size:11px;color:var(--dim);margin-top:2px;}
.gnode-detail{display:none;margin-top:7px;padding-top:7px;border-top:1px solid var(--line);max-height:230px;overflow:auto;}
.gnode:hover .gnode-detail,.gnode.open .gnode-detail{display:block;}   /* пальцем не наводят — тап */
/* Профессия — в свёрнутой карточке под именем (пункт 26). min-width:0 обязателен: без него
   flex-элемент не сжимается и длинная роль растягивает карточку вместо многоточия. */
.gnode .gid{min-width:0;}
.gnode .grole{color:var(--dim);font-size:10.5px;font-style:italic;line-height:1.2;margin-top:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
/* Подписанные разделы раскрытой карточки: место у находки постоянное, пустой раздел — «—». */
.gsec{margin-top:6px;}
.gsec:first-child{margin-top:0;}
.gsecT{font-size:9.5px;letter-spacing:.7px;text-transform:uppercase;color:#6d7085;margin-bottom:2px;}
.gdline{margin:4px 0;}
.gchip{font-size:11px;padding:3px 7px;border-radius:6px;display:inline-block;}
.gchip.motive{background:#2a2440;border:1px solid #4a3f6f;color:#d3c9ea;}
.gchip.method{background:#24302a;border:1px solid #3f6f5a;color:#cfe6d8;}
.gsrc{font-size:10px;color:var(--dim);margin:1px 0 2px;}
.gfact{font-size:11px;color:#bfc2d0;padding:3px 0;border-top:1px dashed var(--line);}
.gsec .gfact:first-of-type{border-top:none;padding-top:0;}   /* под подписью раздела черта лишняя */
.gmsg.none{color:#6d7085;font-size:11px;}
.gbadge{display:inline-block;font-size:10px;color:var(--bad);border:1px solid #5a3a3a;border-radius:5px;padding:0 5px;margin-bottom:3px;}
path.gedge{fill:none;stroke:var(--accent);stroke-width:1.3;opacity:.32;transition:opacity .15s,stroke-width .15s;}
path.gedge.hl{opacity:.95;stroke-width:2.3;}

/* ============ подсказки (пункт 24) ============ */
/* Цена стоит НА кнопке, а не рядом: платят Маной, и человек должен видеть сумму в тот момент,
   когда решает нажать, — не в подписи снизу и не в подтверждении после. */
/* Высота окна ФИКСИРОВАНА, а не «по содержимому с потолком»: раньше каждая купленная подсказка
   растягивала окно вниз, и оно дёргалось под курсором (жалоба владельца 11.08.2026). Теперь
   размер один и тот же с первой подсказки до последней.
   min() с dvh, а не 82vh: на телефоне vh считается по «большому» окну, без адресной строки, и
   низ окна уезжал бы за экран (та же ловушка, что у #hud — см. HOWTO_web_layout).
   Прокручивается ТОЛЬКО список: шапка с кнопкой покупки обязана оставаться на месте, иначе
   после каждой покупки её приходится доскролливать обратно.
   ⚠️ vh ДУБЛИРУЕТ dvh НЕ ДЛЯ КРАСОТЫ. Браузер без поддержки dvh отбрасывает min(560px,82dvh)
   ЦЕЛИКОМ — высота становится auto, .hintList перестаёт прокручиваться (flex:1 1 auto скроллит
   только при заданной высоте родителя), окно перерастает экран, и крестик уезжает за край:
   закрыть подсказки можно только перезагрузкой. Найдено 07.09.2026 при выводе требований к
   браузеру для витрины — это было единственное место без запасной строки. */
.hintBox{position:relative;display:flex;flex-direction:column;overflow:hidden;
  width:90%;max-width:540px;height:min(560px,82vh);height:min(560px,82dvh);
  background:#15171f;border:1px solid #3a3f55;border-radius:14px;padding:22px 24px;
  box-shadow:0 14px 48px rgba(0,0,0,.55);}
.hintHead{flex:none;}
.hintLead{color:var(--dim);font-size:12.5px;line-height:1.5;margin:0 0 14px;}
.hintBuy{display:flex;flex-direction:column;gap:8px;}
.hintBtn{display:flex;align-items:center;gap:10px;flex-wrap:wrap;width:100%;text-align:left;
  background:#1b1d27;border:1px solid #343850;border-radius:10px;padding:11px 14px;cursor:pointer;
  color:#e7e3d8;font-size:14px;font-family:inherit;}
.hintBtn:hover:not(:disabled){border-color:var(--accent);}
.hintBtn:disabled{opacity:.55;cursor:not-allowed;}
.hintBtnT{flex:1;}
.hintBtnN{color:var(--dim);font-size:12.5px;}
.hintBtnC{color:var(--accent);font-weight:600;font-variant-numeric:tabular-nums;white-space:nowrap;}
/* Причина занимает всю ширину под строкой кнопки: погасшая кнопка обязана объяснить, почему. */
.hintWhy{flex-basis:100%;color:#8a8ea3;font-size:11.5px;line-height:1.4;}
.hintListT{margin:16px 0 8px;color:var(--dim);font-size:11px;letter-spacing:.7px;text-transform:uppercase;}
/* min-height:0 обязателен: без него флекс-элемент не сжимается ниже своего содержимого, список
   распирает окно изнутри и прокручивается не он, а всё окно — ровно то, от чего уходим.
   padding-right отводит место полосе прокрутки, чтобы она не легла на текст подсказки. */
.hintList{flex:1 1 auto;min-height:0;overflow-y:auto;display:flex;flex-direction:column;
  padding-right:6px;margin-right:-6px;}
.hintList>*{flex:none;}                 /* карточки не сжимаются в высоту — они прокручиваются */
.hintCard{background:#171922;border:1px solid var(--line);border-left:3px solid var(--accent);
  border-radius:8px;padding:9px 12px;margin-bottom:8px;}
.hintCard.accuse{border-left-color:var(--bad);}
.hintCardH{color:var(--dim);font-size:11px;margin-bottom:4px;font-variant-numeric:tabular-nums;}
.hintStep{color:#cbc7bb;font-size:13.5px;line-height:1.5;margin-top:3px;}
.hintStep b{color:var(--accent);}
.hintNone{margin:auto 0;padding:0 6px;color:#6f7386;font-size:12.5px;line-height:1.5;text-align:center;}

/* ============ экран выбора дел (атмосферный список) ============ */
.gsel{position:fixed;inset:0;z-index:20;display:flex;flex-direction:column;overflow:hidden;}
.gsel-bg{position:absolute;inset:0;z-index:0;
  background:linear-gradient(180deg,rgba(9,10,15,.6) 0%,rgba(9,10,15,.48) 32%,rgba(9,10,15,.85) 100%),
    url("/assets/map/village_iso.webp?v=5b54ee6284") center/cover no-repeat;}
.gsel-bg::after{content:"";position:absolute;inset:0;pointer-events:none;
  box-shadow:inset 0 0 230px 46px rgba(6,7,12,.78);}
/* Шапка переносится по строкам: на телефоне ник, мана, покупка, «на сайт» и «выйти» в одну
   строку не встают, и без переноса кнопка выхода уезжала за правый край экрана — с телефона
   было не выйти из аккаунта. Отступы по бокам учитывают вырез (safe-area) в альбомной ориентации. */
.gsel-top{position:relative;z-index:2;display:flex;align-items:center;justify-content:space-between;
  gap:8px 10px;flex-wrap:wrap;
  padding:15px calc(20px + env(safe-area-inset-right)) 15px calc(20px + env(safe-area-inset-left));}
/* clamp вместо медиазапроса: на 390 px заголовок в 22 px рвался на три строки. */
.gsel-brand{font-family:Georgia,serif;font-size:clamp(17px,5vw,22px);color:#efe9d8;letter-spacing:.4px;
  white-space:nowrap;text-shadow:0 2px 14px rgba(0,0,0,.75);}
.gsel-brand span{color:var(--accent);}
.gsel-acct{display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:8px 10px;}
/* Геометрию ника, маны и кнопок шапки задаёт общий блок «органы управления поверх фона» —
   здесь только то, чем чип отличается от кнопки. */
/* Кнопка кабинета — единственный орган в шапке рядом с чипом маны. Стиль берёт из общего блока
   «органы управления поверх фона» (селектор .gsel-out в начале файла), поэтому она читается как
   кнопка, а не как ссылка: именно этим и была прежняя строчка «Личный кабинет» в подвале. */
.gsel-cab{display:inline-flex;align-items:center;gap:7px;white-space:nowrap;max-width:46vw;}
.gsel-cab .ic{width:15px;height:15px;flex:none;fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;}
.gsel-cab-n{overflow:hidden;text-overflow:ellipsis;color:#efe9d8;}
.gsel-nick-inp{background:#0f1017;border:1px solid var(--accent);border-radius:7px;padding:4px 8px;
  color:#ece7da;font-size:13px;width:150px;}
/* Ссылка «На сайт» носит класс кнопки — у ссылки нет её отступов и она подчёркнута по умолчанию. */
/* Полосу под панель звука держит теперь подвал (.gsel-foot) — он же и есть низ страницы. */
.gsel-body{position:relative;z-index:1;flex:1;display:flex;align-items:center;justify-content:center;
  padding:8px calc(16px + env(safe-area-inset-right)) 8px calc(16px + env(safe-area-inset-left));
  overflow:auto;}
/* Панель не может быть выше окна. Её высота складывается из вкладок, списка, кнопок и настроек
   аккаунта, и на невысоком окне (900×760) сумма перерастала экран: .gsel-body центрирует панель, и
   верх уезжал ПОД шапку с ником и маной — до них было не добраться. Поэтому панель — колонка с
   потолком по окну, а сжимается в ней список (у остальных блоков flex:none). */
.gsel-panel{width:min(560px,94vw);background:rgba(15,16,23,.72);border:1px solid rgba(200,162,74,.16);
  border-radius:16px;padding:22px;-webkit-backdrop-filter:blur(9px);backdrop-filter:blur(9px);box-shadow:0 26px 74px rgba(0,0,0,.58);
  max-height:100%;display:flex;flex-direction:column;min-height:0;}
/* Все три вкладки лежат в ОДНОЙ ячейке грида и остаются в потоке: панель всегда высотой с самую
   высокую из них. Пока неактивные вкладки убирались через display:none, панель меняла высоту при
   каждом переключении («Мои дела» 301 px, «Выбрать дело» 577 px), а .gsel-body центрирует её — и
   вместе с высотой прыгал верхний край, то есть всё содержимое (пункт 24). Прячем видимостью:
   из потока элемент не выпадает, но и кликов с фокусом не ловит. */
/* grid-template-rows задан ЯВНО и равен minmax(0,1fr), а не оставлен автоматическим. Ряд размера
   `auto` не сжимается ниже содержимого: даже когда сам грид ужат до высоты панели, ряд остаётся
   высотой с самую длинную вкладку и вылезает наружу вместе с сейвами и кнопками «Новое дело» /
   «Кооп-дело» (жалоба владельца 11.08.2026 — при 12 сейвах список уходил на 370 px за карточку,
   кнопки на 424). minmax(0,1fr) делает высоту ряда определённой — и внутри вкладки начинает
   работать прокрутка списка. */
.gsel-tabbody{display:grid;grid-template-rows:minmax(0,1fr);flex:1 1 auto;min-height:0;}
.gsel-tabbody>*{grid-area:1/1;min-height:0;}
.gsel-tabbody>.off{visibility:hidden;pointer-events:none;}
#tabSaves,#tabCases,#tabEvo{display:flex;flex-direction:column;min-height:0;}
/* :not(.gsel-tabbody) — не косметика. У `.gsel-panel>*` и `.gsel-tabbody` одинаковая
   специфичность (один класс), и правило ниже по файлу молча отменяло `flex:1 1 auto` у самого
   тела вкладок: единственный сжимаемый блок панели переставал сжиматься, и всё содержимое
   вываливалось за карточку. */
.gsel-panel>*:not(.gsel-tabbody),#tabSaves>*,#tabCases>*{flex:none;}
#tabSaves,#tabCases,#tabEvo{flex:1 1 auto;}
.evo-soon{margin-top:auto;margin-bottom:auto;}   /* короткая вкладка не липнет к верху высокой панели */
.gsel-head h2{margin:0;color:#efe9d8;font-family:Georgia,serif;font-size:22px;font-weight:600;}
.gsel-head .hint{margin:2px 0 14px;}
/* Потолка в vh у списка НЕТ намеренно: высоту держит .gsel-panel{max-height:100%} через flex, а
   vh на телефоне врёт — адресная строка браузера то появляется, то исчезает, и низ уезжал за
   экран (при html{overflow:hidden} страница это не выправит). */
/* padding/margin по правому краю — тот же приём, что в окне подсказок: полоса прокрутки встаёт в
   поле панели, а не поверх карточек дела. */
#glist{display:flex;flex-direction:column;gap:8px;margin-bottom:14px;overflow-y:auto;
  flex:1 1 auto;min-height:76px;padding-right:6px;margin-right:-6px;}
/* Карточки в списках НЕ сжимаются: оба списка — колоночные флексы, а флекс-элемент по умолчанию
   ужимается под контейнер. От этого на невысоком окне у карточек съезжало за край название с датой
   и обрезалась обложка. Список вместо этого прокручивается (overflow:auto у него уже есть). */
#glist>*,#clist>*{flex:none;}
/* Полоса прокрутки В СТИЛЕ ИГРЫ — золотая на прозрачном, вместо системной серой. Видимая, а не
   «появляется при движении»: она здесь единственный признак того, что список длиннее окна.
   Класс общий: где в игре есть прокрутка, там и эта полоса (списки дел, окно подсказок). */
.wscroll{scrollbar-width:thin;scrollbar-color:rgba(200,162,74,.45) transparent;}
.wscroll::-webkit-scrollbar{width:9px;}
.wscroll::-webkit-scrollbar-track{background:transparent;}
.wscroll::-webkit-scrollbar-thumb{
  background:rgba(200,162,74,.42);border-radius:999px;border:2px solid transparent;
  background-clip:content-box;}
.wscroll::-webkit-scrollbar-thumb:hover{background:rgba(200,162,74,.7);
  background-clip:content-box;}

/* Подвал ВСЕЙ страницы «Дела»: рассылка, документы, удаление аккаунта. Раньше жил внутри панели
   и отнимал у списка дел ~86 px.
   padding-left разводит подвал с панелью звука: она висит отдельным position:fixed в левом нижнем
   углу (#audioBar, 14 px от края + ~170 px ширины) и переносить её сюда нельзя — узел переживает
   смену экранов, а #stage переписывается целиком. На узком экране места слева нет, и содержимое
   встаёт НАД баром (см. медиазапрос ниже). */
/* ⚠️ min-height держит ПОЛ панели, а не красоту подвала. Пол экрану задаёт панель звука
   (#audioBar: 14 px от низа + 34 px высоты = 48 px), а не текст подвала: подвал в колонке
   последний, и панель дел стоит ровно на нём. Пока в подвале жили галка с подписью в две строки
   и ряд ссылок, высоты хватало случайно; 05.09.2026 подвал ужался до одной кнопки — и панель
   тут же наехала на бар на 900×760 и 760×700 (поймал hud_layout_check). */
.gsel-foot{position:relative;z-index:2;flex:none;
  min-height:calc(48px + env(safe-area-inset-bottom));display:flex;align-items:center;
  padding:9px calc(20px + env(safe-area-inset-right)) calc(12px + env(safe-area-inset-bottom)) 196px;
  background:linear-gradient(180deg,rgba(9,10,15,0),rgba(9,10,15,.62));}
.gsel-settings{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:6px 18px;
  width:100%;}
/* рассылка слева, ссылки прижаты вправо; на узком экране строка переносится */
.setRow{display:flex;flex:1 1 300px;gap:8px;align-items:flex-start;color:#cbc7bb;font-size:12.5px;
  line-height:1.4;cursor:pointer;}
.setRow input{margin-top:2px;flex:none;width:auto;}
.setHint{display:block;color:var(--dim);font-size:11px;margin-top:2px;}
.setLinks{flex:none;color:var(--dim);font-size:11.5px;}
.setLinks a{color:var(--dim);}
.setLinks a:hover{color:var(--accent);}
/* ⚠️ Только внутри .setLinks. Раньше это правило было глобальным (.linkBtn) и стояло НИЖЕ такого
   же правила карточки входа — то есть перебивало его: кнопкам входа доставались padding:0 и
   font:inherit от подвала «Дел». Обратная сторона того же обмена видна на телефоне: правило
   `.linkBtn{font-size:13.5px}` из блока ≤520 писалось под тач-цель 44 px на входе, а цепляло
   подвал, где соседние ссылки набраны 11.5 px, — «Удалить аккаунт» выглядела крупнее остальных
   и рвала строку (замечание владельца 05.09.2026, и вдобавок риск задеть её случайно). */
.setLinks .linkBtn{background:none;border:none;padding:0;color:var(--dim);font:inherit;cursor:pointer;
  text-decoration:underline;}
.setLinks .linkBtn:hover{color:var(--bad);border-color:transparent;}

/* ---------- окно отмены обвинения (кооп) ----------
   Полоса поверх игры, а не строка в лотке «обвинить»: остановить объявление должен успеть ЛЮБОЙ
   участник, а лоток у него, скорее всего, закрыт. z-index ниже модалок (они важнее) и выше HUD.
   Кнопка «Отменить» — тач-цель, а не ссылка: пятнадцать секунд промахиваться некогда. */
#accWindow{position:fixed;left:0;right:0;top:calc(10px + env(safe-area-inset-top));z-index:66;
  display:flex;justify-content:center;pointer-events:none;padding:0 12px;}
.accw-in{pointer-events:auto;display:flex;align-items:center;gap:12px;max-width:min(520px,94vw);
  background:rgba(24,18,14,.94);border:1px solid var(--accent);border-radius:11px;
  padding:9px 12px;box-shadow:0 12px 34px rgba(0,0,0,.55);font-size:13.5px;color:#e7e3d8;}
.accw-in b{color:var(--accent);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.accw-t{flex:none;min-width:26px;text-align:center;font-variant-numeric:tabular-nums;
  color:var(--dim);border:1px solid var(--line);border-radius:7px;padding:2px 6px;}
.accw-x{flex:none;background:rgba(201,106,106,.16);border:1px solid rgba(201,106,106,.6);
  color:#e6a3a3;border-radius:8px;padding:7px 12px;font-size:13px;cursor:pointer;}
.accw-x:hover{background:rgba(201,106,106,.28);color:#fff;}
@media(max-width:520px){
  .accw-in{gap:8px;padding:8px 10px;font-size:12.5px;}
  .accw-x{padding:8px 10px;}
}

/* ---------- личный кабинет ----------
   Один вход вместо четырёх органов в подвале «Дел»: галка рассылки с подписью в две строки, две
   ссылки и «Удалить аккаунт» съедали высоту у списка дел, а опасная кнопка стояла в ряду обычных
   (замечание владельца 05.09.2026). Размеры и потолок высоты повторяют .delBox: там уже решены
   vh/dvh на телефоне, прокрутка внутри и тач-цель крестика. */
/* ⚠️ Высота ФИКСИРОВАНА, а прокрутка живёт внутри содержимого. Пока окно росло по содержимому,
   переключение вкладок дёргало его: «Аккаунт» — пять строк, «Мана» — три и крупное число,
   «Платежи» — сколько заказов, столько строк. Окно центрировано, поэтому прыгал и верхний край
   (жалоба владельца 05.09.2026). Ровно та же болезнь и то же лечение, что у вкладок экрана
   «Дела» (.gsel-tabbody): там высоту держит grid-ячейка, здесь — фиксированная высота окна.
   dvh дублирует vh: на телефоне vh считается по «большому» окну без адресной строки. */
.cabBox{max-width:520px;width:100%;height:min(520px,88vh);height:min(520px,88dvh);
  display:flex;flex-direction:column;background:#15171f;
  border:1px solid #3a3f55;border-radius:14px;padding:20px 22px 22px;position:relative;
  box-shadow:0 16px 44px rgba(0,0,0,.6);}
.cabBox h2{margin:0 0 12px;color:#e7e3d8;font-family:Georgia,serif;font-size:20px;letter-spacing:0;}
.cabX{position:absolute;top:8px;right:8px;width:36px;height:36px;background:none;border:none;
  color:var(--dim);font-size:17px;line-height:1;cursor:pointer;border-radius:9px;}
.cabX:hover{color:#e7e3d8;background:rgba(255,255,255,.06);}
/* Вкладки колонкой слева (решение владельца 05.09.2026). minmax(0,1fr) у содержимого
   обязателен: без него длинный код заказа в «Платежах» распирал бы колонку и окно уезжало
   вправо. */
.cab-split{display:grid;grid-template-columns:124px minmax(0,1fr);gap:16px;align-items:stretch;
  flex:1 1 auto;min-height:0;}
.cab-tabs{flex-direction:column;gap:2px;border-bottom:none;align-self:start;}
.cab-tabs .nbtab{text-align:left;width:100%;}
/* Прокручивается ТОЛЬКО содержимое: min-height:0 обязателен, иначе grid-ячейка размера auto не
   сжимается ниже содержимого и длинный список «Платежей» распирал бы окно, а не прокручивался. */
.cab-body{overflow-y:auto;min-height:0;padding-right:4px;}
/* На 360 px колонка в 124 px оставила бы содержимому меньше двухсот — строки «Платежей» с датой,
   суммой и ссылкой на чек туда не встают. Поэтому на телефоне тот же список ложится строкой
   сверху; разметка одна, меняется только направление. */
@media(max-width:520px){
  .cab-split{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr);gap:10px;}
  .cab-tabs{flex-direction:row;flex-wrap:wrap;}
  .cab-tabs .nbtab{width:auto;}
}
.cab-row{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:11px 0;
  border-bottom:1px dashed #262a38;font-size:13.5px;color:#cbc7bb;}
.cab-row:last-child{border-bottom:none;}
.cab-row b{display:block;color:#e7e3d8;font-weight:600;}
.cab-click{cursor:pointer;}
.cab-click input{flex:none;width:auto;margin:0;}
.cab-sub{display:block;color:var(--dim);font-size:11.5px;line-height:1.5;margin-top:2px;}
.cab-num{flex:none;color:#cbc7bb;font-variant-numeric:tabular-nums;white-space:nowrap;}
.cab-big{font-family:Georgia,serif;font-size:30px;color:var(--accent);line-height:1.1;margin:2px 0 12px;
  font-variant-numeric:tabular-nums;}
.cab-big .cab-sub{display:inline;font-family:inherit;font-size:13px;color:var(--dim);}
.cab-danger{color:#c98a8a;}
.cab-act{margin-top:14px;}
.cab-empty{color:var(--dim);font-size:13.5px;padding:18px 0;}
/* Пальцем. Галка сама по себе 13 px, а «Удалить» — строка в 18 px: обе меньше минимума 28 px
   (HOWTO_web_layout §1), и поймала это приёмка cabinet_check.py, а не глаз. Строку целиком
   нажать можно и так — она <label>, — но органу управления полагается быть цельным. */
@media (hover:none) and (pointer:coarse){
  .cab-click input{width:28px;height:28px;}
  .cab-row .linkBtn,.cab-row a{display:inline-block;padding:8px 10px;}
  .cabX{width:40px;height:40px;}
}

/* Окно удаления аккаунта. Не confirmModal: оферта требует показать остаток, судьбу денег и
   перечень того, что уйдёт и что сохранится, — «вы уверены?» этого не вмещает. */
/* max-height дублируется в dvh: на телефоне vh считается по «большому» окну без адресной строки,
   и низ окна с кнопками уезжал за экран. Браузер без поддержки dvh просто игнорирует вторую строку. */
.delBox{max-width:520px;width:100%;max-height:92vh;max-height:92dvh;overflow:auto;background:#15171f;
  border:1px solid #3a3f55;border-radius:14px;padding:22px 24px;box-shadow:0 16px 44px rgba(0,0,0,.6);}
.delBox h2{margin:0 0 10px;color:#e7e3d8;font-family:Georgia,serif;font-size:20px;letter-spacing:0;}
.delBox p{color:#cbc7bb;font-size:13.5px;line-height:1.55;margin:0 0 10px;}
.delBox b{color:#e7e3d8;}
.delWarn{border-left:2px solid var(--accent);padding-left:11px;}
.delLists{color:var(--dim);font-size:12.5px;}
.delField{display:block;margin:12px 0 4px;}
.delField span{display:block;color:var(--dim);font-size:12px;margin-bottom:4px;}
.delFb{min-height:17px;font-size:12.5px;color:var(--dim);}
.delFb.bad{color:var(--bad);}
.delBtns{display:flex;gap:8px;justify-content:flex-end;flex-wrap:wrap;margin-top:8px;}
.delBtns .danger{background:#c0504e;border-color:#c0504e;color:#fff;font-weight:600;}
.delHint{color:var(--dim);font-size:11.5px;margin-top:9px;}

.save{display:flex;align-items:center;gap:10px;padding:11px 13px;border:1px solid var(--line);
  border-radius:11px;background:rgba(27,29,39,.62);cursor:pointer;transition:border-color .12s,background .12s;}
.save:hover{border-color:var(--accent);background:rgba(35,38,53,.82);}
/* Строка сейва с обложкой оформлена как карточка дела: картинка доходит до края, поэтому свой
   padding строка отдаёт содержимому (у .ccard тот же приём — overflow:hidden и нулевой padding). */
.save.has-cover{padding:0;overflow:hidden;}
.save.has-cover>*:not(.save-cover){margin:11px 0;}
.save.has-cover .save-actions{margin-right:13px;}
.save-cover{flex:none;align-self:stretch;width:74px;min-height:62px;margin-right:3px;
  background:#12141c center/cover no-repeat;border-right:1px solid var(--line);}
.save-main{flex:1;min-width:0;}
.save-title{font-family:Georgia,serif;font-size:16px;color:#ece7da;}
.save-meta{color:var(--dim);font-size:12px;margin-top:2px;}
.save-players{color:#8fb0c8;font-size:12px;margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
/* Статус и прогресс — одним блоком: так они переезжают вместе, и на телефоне их не приходится
   раскладывать по сетке поодиночке (строка сейва там становится grid, см. медиазапрос). */
.save-side{flex:0 0 auto;display:flex;align-items:center;gap:9px;}
.save-badge{flex:0 0 auto;font-size:11.5px;border-radius:999px;padding:3px 10px;border:1px solid;white-space:nowrap;}
/* Прогресс дела: ⚖️ и 🗝️ одно под другим, справа от статуса (пункт 38).
   tabular-nums — чтобы «2/5» и «11/12» не дёргали колонку по ширине при разных числах. */
.save-prog{flex:0 0 auto;display:flex;flex-direction:column;gap:2px;min-width:44px;}
.save-prog-l{display:flex;align-items:center;gap:4px;color:var(--dim);font-size:11.5px;
  line-height:1.25;font-variant-numeric:tabular-nums;white-space:nowrap;}
.save-prog-l b{color:#c3bfb2;font-weight:600;}
.save-prog-l.done b{color:var(--accent);}       /* набрано полностью — золотом, как в схеме */
.badge-coop{color:#8fd0b0;border-color:rgba(95,174,122,.5);background:rgba(95,174,122,.13);}
.badge-solo{color:#d1bd8c;border-color:rgba(200,162,74,.42);background:rgba(200,162,74,.1);}
.save-actions{flex:0 0 auto;display:flex;gap:2px;opacity:0;transition:opacity .12s;}
.save:hover .save-actions{opacity:1;}
.save-actions button{background:none;border:none;cursor:pointer;padding:4px 6px;border-radius:6px;
  line-height:0;display:flex;align-items:center;justify-content:center;}
/* Контур одной толщины на обе иконки. Раньше это были глифы ✎ (U+270E, рисуется шрифтом) и
   🗑 (U+1F5D1, подхватывается цветным эмодзи): разный вес, разная метрика, разный оптический
   центр — «выровнять» их было нечем (замечание 05.09.2026). */
.save-actions .ic{width:17px;height:17px;display:block;fill:none;stroke:currentColor;
  stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;}
.save-edit{color:#9aa0b2;}
.save-edit:hover{color:var(--accent);background:rgba(200,162,74,.12);}
.save-del{color:#a86a6a;}
.save-del:hover{color:#e08a8a;background:rgba(201,106,106,.15);}
.save-rename{width:100%;font-family:Georgia,serif;font-size:15px;background:#0f1017;
  border:1px solid var(--accent);border-radius:7px;padding:6px 8px;color:#ece7da;}
.gsel-actions{display:flex;gap:8px;}
.gsel-new{flex:1;background:var(--accent);color:#141019;border:none;border-radius:9px;padding:11px;
  font-weight:600;font-size:14px;cursor:pointer;}
.gsel-new:hover{filter:brightness(1.07);}
.gsel-coop{flex:1;background:rgba(27,29,39,.82);color:#dcd8cc;border:1px solid var(--line);
  border-radius:9px;padding:11px;font-size:14px;cursor:pointer;}
.gsel-coop:hover{border-color:var(--accent);color:#fff;}
/* ---- выбор дела: вкладки + карточки дел (каталог) ---- */
.gsel-tabs{margin-bottom:12px;}
.nbtab.tab-soon{opacity:.62;}

#clist{display:flex;flex-direction:column;gap:9px;overflow-y:auto;       /* потолка в vh нет — см. #glist */
  flex:1 1 auto;min-height:96px;padding-right:6px;margin-right:-6px;}
.ccard{display:flex;gap:0;border:1px solid var(--line);border-radius:12px;overflow:hidden;
  background:rgba(27,29,39,.62);cursor:pointer;transition:border-color .15s,background .15s;}
.ccard:hover{border-color:var(--accent);background:rgba(35,38,52,.78);}
.ccard.dim{opacity:.55;border-style:dashed;}          /* та же идиома «недоступно», что у узлов графа */
.ccard.dim:hover{opacity:.72;}
.ccover{flex:none;width:104px;background:#12141c center/cover no-repeat;border-right:1px solid var(--line);}
.cbody{flex:1;min-width:0;padding:11px 13px;}
.ctitle{font-family:Georgia,serif;font-size:15.5px;color:#e7e3d8;line-height:1.2;
  display:flex;align-items:center;gap:7px;flex-wrap:wrap;}
.cbadge{font-size:10px;text-transform:uppercase;letter-spacing:.04em;padding:2px 7px;border-radius:6px;
  border:1px solid;white-space:nowrap;}
.cbadge.free{color:var(--ok);border-color:rgba(95,174,122,.45);background:rgba(95,174,122,.1);}
.cbadge.lock{color:var(--accent);border-color:rgba(200,162,74,.45);background:rgba(200,162,74,.1);}
.cbadge.soon{color:var(--dim);border-color:var(--line);background:rgba(255,255,255,.03);}
/* ⓘ — единственное, что рассказывает о деле на карточке; текст уехал в модалку брифинга.
   margin-left:auto прижимает её к правому краю строки названия (.ctitle — flex). */
.cinfo{flex:none;margin-left:auto;width:20px;height:20px;border-radius:50%;padding:0;
  background:none;border:1px solid var(--line);color:var(--dim);font-family:Georgia,serif;
  font-size:12.5px;font-style:italic;line-height:1;cursor:pointer;}
.cinfo:hover{color:var(--accent);border-color:var(--accent);background:rgba(200,162,74,.12);}
.cfaces{margin-top:8px;display:flex;align-items:center;gap:4px;}
.cface{width:22px;height:22px;border-radius:50%;object-fit:cover;border:1px solid var(--line);
  background:#262835;margin-right:-7px;}
.ccount{margin-left:14px;font-size:11px;color:var(--dim);}

.evo-soon{text-align:center;padding:26px 18px;border:1px dashed var(--line);border-radius:12px;
  background:rgba(20,22,31,.5);}
.evo-ico{font-size:30px;opacity:.65;}
.evo-t{margin-top:8px;font-family:Georgia,serif;font-size:17px;color:#e7e3d8;}
.evo-d{margin:7px auto 0;max-width:420px;font-size:12.5px;color:var(--dim);line-height:1.55;}

/* ================= телефон (одна точка перелома на весь клиент — 520 px) ================= */
@media (max-width:520px){
  .gsel-actions{flex-direction:column;}
  /* Шапка на телефоне встаёт в три строки (заголовок + два ряда чипов) — держим её компактной,
     каждые лишние 20 px тут отнимаются у списка дел. */
  .gsel-top{padding:8px 12px;gap:6px;}
  .gsel-out,.manaChip{padding:5px 10px;font-size:12.5px;}
  .manaChip{padding:3px 4px 3px 11px;}           /* внутри «＋» — вертикальные поля держит он */
  .gsel-panel{padding:14px;border-radius:14px;}
  .gsel-head h2{font-size:19px;}
  .gsel-head .hint{margin-bottom:10px;}
  /* Подвал: слева места под панель звука нет, поэтому содержимое встаёт НАД ней (34 px бара +
     14 px от края). См. #audioBar. */
  .gsel-foot{padding:7px 14px calc(50px + env(safe-area-inset-bottom)) 14px;}
  .gsel-settings{gap:7px;}
  .setRow{flex:1 1 100%;}
  .setHint{font-size:10.5px;}
  /* Строка сейва — сетка в две линии: иначе сжимался только .save-main (у бейджа и кнопок
     flex:0 0 auto), название вставало в четыре строки, а высота строки доходила до 175 px. */
  .save{display:grid;grid-template-columns:auto 1fr auto;align-items:center;column-gap:10px;row-gap:2px;}
  .save-cover{grid-row:1/3;width:66px;}
  .save-main{grid-column:2;grid-row:1;}
  .save-title{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  /* Блок «статус + прогресс» занимает ту же ячейку, где раньше стоял один бейдж. На 360 px
     статус и прогресс в один ряд не помещаются вместе с названием дела, поэтому здесь они
     встают друг под друга: справа получается столбик «Одиночное / ⚖️ / 🗝️». */
  .save-side{grid-column:3;grid-row:1;justify-self:end;flex-direction:column;
    align-items:flex-end;gap:3px;}
  .save-actions{grid-column:2/4;grid-row:2;justify-self:end;opacity:1;}
  /* На телефоне столбик и так узкий — прогресс кладём в строку, чтобы не растить высоту сейва.
     Резерв ширины здесь не нужен: блок стоит ПОД бейджем, лесенки быть не может. */
  .save-prog{flex-direction:row;gap:8px;min-width:0;}
  .save-prog:empty{display:none;}
  .save.has-cover>*:not(.save-cover){margin:8px 0;}
  .save.has-cover .save-actions{margin:0 13px 8px 0;}
  /* Карточка дела: обложка уже, тело плотнее; бейдж «бесплатно/нужна мана» переносится под
     название сам — у .ctitle уже стоит flex-wrap.
     ⓘ прибита к верхнему правому углу: при переносе строки она уезжала то в строку названия, то
     на отдельную — у соседних карточек кнопка оказывалась на разной высоте. */
  .ccover{width:74px;}
  .cbody{padding:9px 11px;position:relative;}
  .ctitle{font-size:14.5px;padding-right:34px;}
  .cinfo{position:absolute;top:8px;right:8px;margin-left:0;}
  .cfaces{margin-top:6px;}
  /* iOS сам зумит страницу при фокусе на поле мельче 16 px — вёрстка скачет на форме входа и
     при переименовании сейва. */
  input,select,textarea{font-size:16px;}

  /* Карточка входа с пальца: цель нажатия не меньше 44 px, поля крупнее, поля оверлея уже —
     иначе на 360 px карточка теряет по 24 px ширины ни на что. */
  .overlay.auth{padding:calc(12px + env(safe-area-inset-top)) 8px calc(12px + env(safe-area-inset-bottom));}
  .authTabs .nbtab{padding:12px 6px;font-size:14px;}
  .authGo{padding:13px;font-size:16px;}
  /* Поля входа выше обычных: глаз живёт ВНУТРИ рамки пароля и не может быть выше поля, а
     34 px под палец — это промах. 12 px по вертикали дают полю 45 px, глазу — 41 px. */
  .overlay.auth input{padding-top:12px;padding-bottom:12px;}
  .pwrow input{padding-right:46px;}
  .eye{width:42px;font-size:17px;}
  .overlay.auth .linkBtn{padding:8px 6px;font-size:13.5px;}

  /* ---------- игра на телефоне (пункт 14) ----------
     HUD в одну строку помещается ТОЛЬКО иконками: с подписями он вылезал за экран на 457 px, и
     «обвинить», «схема», звук и ⚙ были недостижимы — дело нельзя было ни закончить, ни покинуть.
     Прячем подписи и заголовок дела (он есть за 🔍), панель звука уезжает в меню ⚙ (UI.dockAudio).
     Перенос строки оставлен страховкой: если кнопок станет больше, они уедут вниз, а не за край. */
  #hud{gap:6px;flex-wrap:wrap;
    padding:0 calc(8px + env(safe-area-inset-right)) 0 calc(8px + env(safe-area-inset-left));}
  #hud .lbl,#hud .title{display:none;}
  /* 8 px по бокам, а не 10: на 360 px пятая иконка с ⚙ переносились во вторую строку, а ⚙ в
     одиночестве под HUD выглядит как ошибка. Считано: 16 полей + 58 мана + 37 «＋» + 5×38 + 42
     зазоров = 343 из 360. */
  #hud button:not(.manaPlus){padding:8px 8px;font-size:16px;line-height:1;}
  #hud .badge{padding:6px 9px;font-size:13px;}
  /* Чип маны в HUD собирается по тем же правилам, что и на экране дел, но без подписи «маны»
     (её прячет #hud .lbl) — иначе строка иконок перестаёт помещаться в 360 px. */
  #hud .manaChip{padding:3px 4px 3px 10px;font-size:13px;gap:5px;}

  /* Диалог — во всю ширину: полоски карты в 23 px всё равно не видно, а текст важнее. Портрет
     ниже: на 844 px высоты шапка в 210 px съедала четверть экрана. */
  #dialogue{width:100%;border-left:none;}
  #dialogue .dhead{height:150px;}
  #dialogue #dClose{width:36px;height:36px;}
  #dialogue .dinput{padding:10px;}
  #dialogue .dinput button{min-width:44px;}

  /* Граф — списком: 13 карточек по 150 px на кольце в доске 370 px налезали друг на друга и
     срезались краями. Рёбра между карточками списка бессмысленны — их не рисуем (layoutGraph). */
  .graph-panel{width:96vw;height:88vh;height:88dvh;}
  /* Заголовок переносится в две строки, поэтому ✕ прибит к углу — иначе он оказывался посреди
     подписи «с кем говорил · что нашёл». */
  .graph-panel .ghead{flex-wrap:wrap;padding:12px 52px 6px 14px;position:relative;}
  .graph-panel .ghead #grClose{position:absolute;top:6px;right:8px;width:36px;height:36px;}
  .graph-board{overflow:auto;}
  .graph-grid{position:static;display:flex;flex-direction:column;gap:8px;padding:10px;}
  .gnode,.gnode:hover,.gnode.open{position:static;transform:none;width:auto;}
  svg.gedges{display:none;}
}

/* ==== сенсорный ввод: то, что зависит от наведения, а не от ширины (планшет широкий, но пальцем
   по нему тоже не наводят) ==== */
@media (hover:none) and (pointer:coarse){
  .kbdOnly{display:none;}                        /* «Enter — отправить» пальцу ничего не говорит */
  .save-actions{opacity:1;}                      /* «показать по наведению» пальцем недостижимо */
  .cinfo{width:30px;height:30px;font-size:15px;}
  .save-actions button{padding:6px 9px;}
  .save-actions .ic{width:19px;height:19px;}
  /* «＋» в чипе маны — единственная точка входа в покупку: пальцем в 24 px не попасть.
     28 px (нижняя граница тач-цели) + узкие поля чипа = прежняя высота ряда. */
  .manaPlus{width:28px;height:28px;font-size:17px;}
  .manaChip{padding:2px 3px 2px 12px;}
}

/* --- получение маны (M6): карточки пакетов в модалке PAY.open --- */
.payGrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:9px;margin-bottom:14px}
.payCard{position:relative;background:#1b1d27;border:1px solid #343850;border-radius:11px;
  padding:13px 12px;cursor:pointer;text-align:center;transition:border-color .12s,background .12s}
.payCard:hover{border-color:#4a4f6a}
.payCard.on{border-color:var(--accent);background:#242a1e}
.payCard:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.payBadge{position:absolute;top:-8px;left:50%;transform:translateX(-50%);white-space:nowrap;
  background:var(--accent);color:#141019;font-size:10px;border-radius:999px;padding:2px 8px}
.payMana{font-family:Georgia,serif;color:#e7e3d8;font-size:16px;margin-bottom:3px}
.payHint{color:var(--dim);font-size:11px;margin-bottom:7px}
.payPrice{color:var(--accent);font-size:17px;font-weight:600}
.payField{display:block;margin-bottom:12px}
.payField span{display:block;color:var(--dim);font-size:12px;margin-bottom:4px}
.payField input{width:100%;box-sizing:border-box}
/* Согласия — одним аккуратным блоком, а не четырьмя галками подряд: стену из «принимаю» никто
   не читает, а согласие вслепую хуже отсутствия согласия. Договорные документы подтверждаются
   одной галкой (реестр отдаёт их группой), рекламное — отдельно, за разделителем. */
.payChecks{display:flex;flex-direction:column;gap:9px;background:rgba(20,22,32,.5);
  border:1px solid var(--line);border-radius:11px;padding:12px 13px}
.payCheck{display:flex;gap:9px;align-items:flex-start;color:#cbc7bb;font-size:12.5px;line-height:1.45;cursor:pointer}
/* width:auto ОБЯЗАТЕЛЕН: общее правило input{width:100%} относится и к чекбоксу, а с flex:none он
   занимал всю ширину окна и выталкивал подпись согласия ЗА его край — прочитать, что принимаешь,
   было нельзя. Ровно тем же лечится .setRow input в подвале «Дел». */
.payCheck input{margin-top:2px;flex:none;width:auto}
.payCheck span{min-width:0}
.payCheck a{color:var(--accent)}
.payOptional{margin-top:2px;padding-top:11px;border-top:1px solid var(--line);color:var(--dim)}
/* Пояснение под чекбоксом (рекламное согласие: «добровольно, не условие покупки»). Приходит
   из реестра документов вместе с подписью — своей строки в разметке у него нет. */
.payCheckNote{display:block;margin-top:3px;color:var(--dim);font-size:11.5px;line-height:1.4}
.payNote{color:var(--dim);font-size:12px;margin-top:9px}
.payNote a{color:var(--accent)}
/* 18+ над кнопкой оплаты (436-ФЗ, consents.md §5.2) — заметнее обычного примечания */
.payAge{color:#cbc7bb;border-top:1px solid var(--line);padding-top:9px}
/* Политика ПД — строка ПОД кнопкой «Оплатить» (consents.md §1.4): это информирование, а не
   согласие, поэтому у неё нет галки и она не спорит по весу с блоком согласий. */
.payUnder{margin-top:12px;padding-top:10px;border-top:1px solid var(--line);font-size:11.5px}
.payFb{min-height:17px;margin-top:9px;font-size:12.5px;color:var(--dim);transition:opacity .15s}
.payFb.bad{color:var(--bad)}
/* Витрина: строка на месте кнопки «Оплатить». Занимает её вес и её положение, чтобы человек
   искал кнопку не глазами по всему окну, а прочитал ответ там же, где ждал действие. */
.paySoon{margin-top:10px;padding:10px 12px;border:1px dashed var(--line);border-radius:9px;
  background:rgba(200,162,74,.07);color:#e7e3d8;font-size:13px;line-height:1.45}

/* Выпадающий список в кабинете (переключатель языка). Тот же скин, что у списков в меню-шестерёнке:
   у них общий вид, но разные предки, и одним селектором это не покрыть. */
.cab-sel{background:#12141c;border:1px solid #343850;color:#cbc7bb;border-radius:7px;
  padding:6px 8px;font-size:13px;cursor:pointer}
