/* ===== Dead Village — стиль интерфейса (мультяшный постапокалипсис) ===== */
:root {
  --wood: #5b3a1e; --wood2: #7a4f2a; --rust: #b5542a; --rust2: #d8733d;
  --bone: #efe6d2; --ink: #1c1712; --moss: #3f6b2f; --moss2: #5e9a45; --toxic: #7fd23a;
  --panel: rgba(28, 22, 16, 0.92); --panel2: rgba(46, 36, 26, 0.95);
  --gold: #e8b04a; --blue: #5ad0ff; --red: #d9442f;
}
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; height: 100%; overflow: hidden; background: #1a2414; font-family: "Segoe UI", Roboto, Arial, sans-serif; color: var(--bone); user-select: none; }
#app { position: fixed; inset: 0; }
#game { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; cursor: grab; }
#game:active { cursor: grabbing; }
.hidden { display: none !important; }
.bbmore { display: none; }   /* стрелки нижней панели — только на телефоне (см. @media 700px) */
#bottombar.hidden ~ .bbmore, body.inworld .bbmore { display: none !important; }
button { font-family: inherit; cursor: pointer; }
/* ---- полосы прокрутки ----
   Системная светлая полоса поперёк тёмного деревянного интерфейса выглядела чужеродно.
   Красим под дерево: тонкая, тёмный жёлоб, светлая «доска» бегунка. */
* { scrollbar-width: thin; scrollbar-color: #8a7448 rgba(0,0,0,0.3); }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: rgba(0,0,0,0.3); border-radius: 8px; }
::-webkit-scrollbar-thumb { background: linear-gradient(180deg, #9a8050, #5d4c2e); border-radius: 8px;
  border: 2px solid rgba(0,0,0,0.35); background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: linear-gradient(180deg, #b39760, #6f5b36); background-clip: padding-box; }
::-webkit-scrollbar-corner { background: transparent; }
code { font-family: Consolas, monospace; font-size: 12px; }

/* ---- верхняя панель ---- */
#topbar { position: absolute; top: 0; left: 0; right: 0; display: flex; gap: 6px; padding: 8px 10px; align-items: center; pointer-events: none; flex-wrap: wrap; }
#topbar > * { pointer-events: auto; }
.res { display: flex; align-items: center; gap: 6px; background: var(--panel); border: 2px solid var(--wood2); border-radius: 12px; padding: 4px 10px 4px 6px; min-width: 96px; box-shadow: 0 3px 0 rgba(0,0,0,0.4); }
.res.gem { min-width: 70px; }
/* Орда голодает: счётчик биомассы пульсирует красным. Голод стоит зомби, и молчать о нём нельзя. */
.res.starving { border-color: #c0392b !important; animation: starve 1.1s ease-in-out infinite; }
.res.lowfeed { border-color: #c0392b !important; }   /* припасов меньше чем на 2 часа — рамка, пока плашка сверху молчит (UI.warnGate) */
@keyframes starve { 0%, 100% { box-shadow: 0 0 0 rgba(192,57,43,0); } 50% { box-shadow: 0 0 14px rgba(192,57,43,.85); } }
.ricon { width: 26px; height: 26px; object-fit: contain; }
.remoji { font-size: 20px; line-height: 26px; width: 26px; text-align: center; }
.rnum { display: flex; flex-direction: column; line-height: 1.05; }
.rnum b { font-size: 15px; }
.rnum small { font-size: 10px; opacity: .65; }
.rnum b small { margin-left: 2px; font-weight: 500; }
.rnum .rate { color: #9fe07a; opacity: .95; font-weight: 600; }
.rnum.full b { color: var(--red); }
.spacer { flex: 1; }
.pill { background: var(--panel); border: 2px solid var(--wood2); border-radius: 12px; padding: 6px 12px; font-weight: 700; font-size: 14px; box-shadow: 0 3px 0 rgba(0,0,0,0.4); }

/* «Не все файлы скачались — Докачать» (Assets.offerBar, 25.09); top ставит UI.layoutTop */
#dlbar { position: absolute; top: 60px; left: 50%; transform: translateX(-50%); z-index: 7; display: flex; gap: 10px; align-items: center; background: rgba(30,14,8,0.92); border: 2px solid var(--rust2); border-radius: 12px; padding: 5px 6px 5px 14px; font-size: 13px; font-weight: 700; max-width: calc(100vw - 16px); white-space: nowrap; }
#dlbar span { overflow: hidden; text-overflow: ellipsis; }
#dlbar .btn { padding: 6px 12px; font-size: 13px; flex: 0 0 auto; }
#hint { position: absolute; top: 60px; left: 50%; transform: translateX(-50%); background: rgba(0,0,0,0.55); border-radius: 10px; padding: 6px 14px; font-size: 13px; max-width: 90vw; text-align: center; pointer-events: none; }
#hint.warn { background: rgba(110,22,12,0.88); border: 1px solid #e0503a; font-weight: 600; color: #ffc4b8; }   /* «Припасы кончились…» — важнее обучения */
#hint.go { pointer-events: auto; cursor: pointer; }   /* «склад полон — нажми»: открывает «Куда потратить» (отчёт 17-25) */
#hint.go:hover { border-color: #ff8a6e; background: rgba(130,30,16,0.95); }

/* ---- нижняя панель ---- */
#bottombar { position: absolute; bottom: 0; left: 0; right: 0; display: flex; justify-content: center; gap: 8px; padding: 10px; pointer-events: none; }
/* Все нижние кнопки одного роста и с подписью по центру: раньше кнопка со значком («Зомби») была
   выше остальных, а подписи стояли на разной высоте — ряд выглядел кривым. position: relative
   обязателен, иначе значок-счётчик (.badge) считает координаты от всей панели и ложится прямо на
   слово — именно так «!» налезала на «Кампанию». */
.bigbtn { pointer-events: auto; position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; min-width: 84px; min-height: 62px; padding: 8px 12px; border-radius: 14px; border: 3px solid var(--wood); background: linear-gradient(#8a5a30, #5b3a1e); color: var(--bone); font-weight: 800; font-size: 12px; text-shadow: 0 1px 0 #000; box-shadow: 0 4px 0 #2f1d0e, 0 6px 10px rgba(0,0,0,0.5); transition: transform .05s; }
.bigbtn .ico { font-size: 24px; }
.bigbtn:active { transform: translateY(3px); box-shadow: 0 1px 0 #2f1d0e; }
.bigbtn.attack { background: linear-gradient(#d9442f, #8d2417); border-color: #5a170e; min-width: 110px; }

/* ---- панель здания ---- */
#bpanel { position: absolute; left: 10px; bottom: 96px; width: 340px; max-width: calc(100vw - 20px); background: var(--panel2); border: 3px solid var(--wood2); border-radius: 16px; padding: 12px; box-shadow: 0 8px 24px rgba(0,0,0,0.6); max-height: calc(100vh - 200px); overflow: auto; }
#btitle { display: flex; gap: 10px; align-items: center; margin-bottom: 8px; padding-right: 34px; }
/* крестик панели здания — как у окон, чуть меньше (UI.closePanel) */
#bpanel .close { position: absolute; top: 8px; right: 8px; width: 30px; height: 30px; border-radius: 50%; border: 2px solid #2f1d0e; background: var(--red); font-size: 0; color: transparent; padding: 0; z-index: 1; }
#bpanel .close::before, #bpanel .close::after { content: ''; position: absolute; left: 50%; top: 50%; width: 14px; height: 3px; border-radius: 2px; background: #fff; }
#bpanel .close::before { transform: translate(-50%, -50%) rotate(45deg); }
#bpanel .close::after { transform: translate(-50%, -50%) rotate(-45deg); }
#bpanel .close:active { transform: scale(.92); filter: brightness(.9); }
#btitle .pic { width: 64px; height: 64px; object-fit: contain; }
#btitle .name { font-weight: 800; font-size: 17px; }
#btitle .sub { font-size: 12px; opacity: .75; }
.stat { display: flex; justify-content: space-between; gap: 10px; padding: 3px 0; border-bottom: 1px dashed rgba(255,255,255,0.1); font-size: 13px; }
.stat b { text-align: right; }
.stat .next { color: var(--toxic); font-style: normal; font-size: 12px; }
.desc { font-size: 12px; opacity: .75; margin: 8px 0; line-height: 1.35; }
/* Реплика жителя в его карточке: то же, что он сказал вслух на карте, но остаётся текстом —
   иначе кнопка «Поговорить» выглядит как будто ничего не делает. */
/* Крупная просьба жителя: заметный блок с двумя кнопками — это решение игрока, а не фон */
.vask { margin: 8px 0; padding: 9px 10px; border: 2px solid #b8873a; border-radius: 10px;
  background: rgba(184,135,58,0.16); display: flex; flex-direction: column; gap: 6px;
  animation: askpop .25s ease-out; }
.vask .vasktop { display: flex; align-items: baseline; gap: 8px; }
.vask .vaskwhat { font-size: 13px; }
.vask .vaskbtns { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.vask .vaskbtns .btn { width: 100%; }
@keyframes askpop { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: none; } }
.vsay { margin: 8px 0 4px; padding: 7px 10px; border-left: 3px solid #8fae5a; border-radius: 0 8px 8px 0;
  background: rgba(120,160,80,0.14); font-size: 13px; font-style: italic; line-height: 1.35;
  animation: saypop .22s ease-out; }
@keyframes saypop { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
/* Кнопки не должны липнуть друг к другу: между ними всегда виден просвет. */
/* Кнопки панели здания — ровной сеткой в две колонки, главное действие (улучшить / макс. уровень) во всю ширину.
   Раньше они шли строкой с переносом, каждая своей ширины, и лесенкой: «Снести» одна в последнем ряду, правый
   край вразнобой («кнопки разбросаны некрасиво» — просьба 22.09). */
#bbuttons { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
#bbuttons > .btn { width: 100%; margin: 0; min-width: 0; }
#bbuttons > .btn.up, #bbuttons > .btn.wide, #bbuttons > .btn:only-child { grid-column: 1 / -1; }

.btn { border: 2px solid #2f1d0e; border-radius: 10px; background: linear-gradient(#8a5a30, #5b3a1e); color: var(--bone); font-weight: 700; font-size: 13px; padding: 8px 12px; display: inline-flex; align-items: center; justify-content: center; text-align: center; gap: 6px; flex-wrap: wrap; box-shadow: 0 3px 0 #2f1d0e; text-shadow: 0 1px 0 #000; }
.btn:active { transform: translateY(2px); box-shadow: 0 1px 0 #2f1d0e; }
.btn.ok { background: linear-gradient(#6fb04a, #3f6b2f); }
.btn.bad { background: linear-gradient(#c9533a, #8d2417); }
.btn.up { background: linear-gradient(#4aa3c9, #2b6a8d); }
.btn.gem { background: linear-gradient(#5ad0ff, #2b7fa8); }
.btn.big { font-size: 16px; padding: 12px 22px; margin-top: 12px; width: 100%; justify-content: center; }
.btn.dis { filter: grayscale(.8) brightness(.7); }
.btn em { display: block; width: 100%; font-size: 11px; font-style: normal; color: #ffb3a7; text-align: center; }
.btn small { opacity: .8; font-weight: 500; }
.cost { display: inline-flex; align-items: center; gap: 3px; }
.cost .ricon { width: 18px; height: 18px; }
.stat .ricon, .btn .ricon, .resrow .ricon, .xrow .ricon, #b-loot .ricon, #tooltip .ricon, .muted .ricon { width: 16px; height: 16px; vertical-align: -3px; }
.cost .remoji { font-size: 14px; width: 18px; line-height: 18px; }
.cost.nope { color: #ff8a7a; }

/* ---- бар постановки ---- */
#placebar { position: absolute; bottom: 96px; left: 50%; transform: translateX(-50%); display: flex; gap: 8px; align-items: center; background: var(--panel2); border: 3px solid var(--wood2); border-radius: 14px; padding: 8px 12px; box-shadow: 0 8px 24px rgba(0,0,0,0.6); }
#place-info { font-size: 13px; font-weight: 700; max-width: 260px; }
#place-info small { font-weight: 400; opacity: .7; }

/* ---- HUD боя ---- */
#battlehud { position: absolute; inset: 0; pointer-events: none; }
#battlehud > * { pointer-events: auto; }
.btop { position: absolute; top: 60px; left: 10px; right: 10px; display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.bbox { background: var(--panel); border: 2px solid var(--wood2); border-radius: 10px; padding: 4px 12px; display: flex; flex-direction: column; align-items: center; min-width: 70px; }
.bbox small { font-size: 10px; opacity: .7; }
.bbox b { font-size: 15px; }
.bbox .bdmg { font-style: normal; font-size: 11px; opacity: .75; margin-left: 4px; }   /* сбитая прочность рядом с «Разрушено» */
.bbox.stars b { font-size: 22px; color: var(--gold); letter-spacing: 2px; }
.bbox.loot b { font-size: 13px; }
.bbox.loot b small { opacity: .6; font-size: 10px; }
#battle-hint { position: absolute; top: 112px; left: 50%; transform: translateX(-50%); font-size: 12px; background: rgba(0,0,0,0.5); padding: 4px 12px; border-radius: 8px; pointer-events: none; text-align: center; max-width: 90vw; }
.bbottom { position: absolute; bottom: 0; left: 0; right: 0; display: flex; align-items: flex-end; gap: 10px; padding: 10px; flex-wrap: wrap; }
#unitbar { display: flex; gap: 6px; flex: 1; overflow-x: auto; padding-bottom: 2px; }
/* Нижняя полоса боя — во всю ширину, а карточек зомби в ней бывает одна-две: пустое место полосы съедало нажатия
   по земле у нижнего края, куда как раз и высаживают (живой прогон 23.09: на телефоне тап по зоне высадки под
   полосой — «ничего»). Сама полоса нажатия пропускает, ловят только карточки и кнопки. */
#battlehud > .bbottom, #unitbar, .bbtns { pointer-events: none; }   /* #battlehud > * ниже включает всё — перебиваем тем же весом */
.bbottom > *:not(#unitbar):not(.bbtns), #unitbar > *, .bbtns > * { pointer-events: auto; }
.ucard { display: flex; flex-direction: column; align-items: center; width: 72px; min-width: 72px; padding: 6px 4px; border-radius: 12px; border: 3px solid var(--wood2); background: var(--panel2); cursor: pointer; box-shadow: 0 3px 0 rgba(0,0,0,0.5); }
.ucard .pic { width: 44px; height: 44px; object-fit: contain; }
.ucard b { font-size: 16px; }
.ucard small { font-size: 10px; opacity: .8; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 64px; }
.ucard.sel { border-color: var(--toxic); box-shadow: 0 0 12px var(--toxic); }
.ucard.dis { filter: grayscale(1) brightness(.6); pointer-events: none; }
.bbtns { display: flex; flex-direction: column; gap: 10px; }

/* ---- всплывающие ---- */
#toast { position: absolute; bottom: 110px; left: 50%; transform: translateX(-50%) translateY(20px); background: rgba(0,0,0,0.85); border: 2px solid var(--rust2); border-radius: 12px; padding: 10px 18px; font-weight: 700; opacity: 0; transition: .2s; pointer-events: none; max-width: 90vw; text-align: center; z-index: 50; }
#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
/* Ширина по тексту, но не шире 90 % экрана. Без width: max-content тост с left: 50% сжимался до половины
   экрана телефона и «Не хватает: Биомасса» ломалось на две строки. */
#toast { width: max-content; }
#toast .twhere { display: block; margin-top: 3px; font-size: 12px; font-weight: 500; opacity: .85; }   /* «Где взять: …» под «Не хватает» */
#toast .ricon, #toast .iicon, #toast img { width: 18px; height: 18px; vertical-align: -4px; }   /* награда пропуска в тосте (UI.toastHtml) */

/* ---- модальные ---- */
#modal { position: absolute; inset: 0; background: rgba(0,0,0,0.6); display: flex; align-items: center; justify-content: center; z-index: 40; padding: 10px; }
/* Прокручивается СОДЕРЖИМОЕ окна, а не само окно: крестик приклеен к рамке и всегда на виду.
   Раньше прокручивалась рамка вместе с крестиком, и в длинном окне (магазин на телефоне — 1947 px)
   после пары прокруток закрыть окно было нечем: ИИ-тестер «Телефон» так застрял в магазине насовсем. */
.modal-box { position: relative; background: var(--panel2); border: 3px solid var(--wood2); border-radius: 18px; padding: 18px; width: 420px; max-width: 100%; max-height: 92vh; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 12px 40px rgba(0,0,0,0.7); }
#modal-content { overflow: auto; min-height: 0; overscroll-behavior: contain; }
.modal-box.wide { width: 860px; }
/* Окно-замок (регистрация): закрыть нельзя, поэтому и крестика быть не должно — иначе игрок
   будет жать в него и думать, что игра зависла. */
.modal-box.gatebox:not(.free) .close { display: none; }   /* замок не закрыть; окна входа и аккаунта без замка (.free) — как обычные */
.modal-box.gatebox.free h2 { min-height: 44px; padding-right: 50px; }   /* заголовок короткий — без этого крестик ложился на первое поле */
/* ===== Окна аккаунта (замок «Заведи аккаунт», вход, «забыли пароль», смена пароля) — в стиле игры, 26.09 =====
   Было: белые поля браузера, системная галочка, «У меня уже есть аккаунт» вплотную под «Регистрацией» («не мог сделать
   это стилистически красивее и без слипающихся кнопок» — Андрей). Стало: тёмные вдавленные поля в деревянной рамке со
   значком слева (значок — на обёртке .fld: автозаполнение браузера стирает фон самого поля), своя галочка, картинка
   «я не робот» на отдельной плашке, ошибка — красной плашкой, запасные кнопки — ровным рядом с просветом. */
.modal-box.gatebox { width: 540px; max-height: 96vh; }   /* шире обычного окна: вступление короче по высоте, картинка «я не робот» встаёт
   в строку с полем; и чуть выше — на 1280×800 окно регистрации с ошибкой помещается без прокрутки */
.modal-box.gatebox .gate-intro { margin: 0; line-height: 1.4; }
.modal-box.gatebox .netbox { display: flex; flex-direction: column; gap: 8px; margin: 12px 0 2px; }
.modal-box.gatebox .fld { position: relative; }
.modal-box.gatebox .fld input { width: 100%; height: 42px; margin: 0; padding: 0 14px 0 42px; border: 2px solid #6b4526; border-radius: 10px;
  background: linear-gradient(180deg, #120b06, #21160c); color: var(--bone); font-family: inherit; font-size: 16px; font-weight: 600;
  box-shadow: inset 0 3px 8px rgba(0,0,0,0.7), 0 1px 0 rgba(255,236,200,0.07); outline: none;
  transition: border-color .15s, box-shadow .15s; -webkit-appearance: none; appearance: none; }
.modal-box.gatebox .fld input::placeholder { color: rgba(239,230,210,0.4); font-weight: 400; }
.modal-box.gatebox .fld input:focus { border-color: var(--gold); box-shadow: inset 0 3px 8px rgba(0,0,0,0.7), 0 0 0 3px rgba(232,176,74,0.22); }
/* автозаполнение браузера красит поле в светлое — перекрашиваем обратно тенью внутрь */
.modal-box.gatebox .fld input:-webkit-autofill { -webkit-text-fill-color: var(--bone); caret-color: var(--bone);
  box-shadow: inset 0 0 0 60px #1a1109, 0 1px 0 rgba(255,236,200,0.07); }
.modal-box.gatebox .fld::before { content: ''; position: absolute; left: 14px; top: 50%; width: 18px; height: 18px; margin-top: -9px;
  background: var(--gold); opacity: .75; pointer-events: none; z-index: 1;
  -webkit-mask: var(--ico) center / contain no-repeat; mask: var(--ico) center / contain no-repeat; }
.modal-box.gatebox .fld:focus-within::before { opacity: 1; }
.modal-box.gatebox .fld-user { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='7.5' r='4.3'/%3E%3Cpath d='M3.5 21.5c0-4.9 3.8-8 8.5-8s8.5 3.1 8.5 8z'/%3E%3C/svg%3E"); }
.modal-box.gatebox .fld-lock { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill-rule='evenodd' d='M7 10V7.5a5 5 0 0 1 10 0V10h1.2c.9 0 1.6.7 1.6 1.6v8.2c0 .9-.7 1.6-1.6 1.6H5.8c-.9 0-1.6-.7-1.6-1.6v-8.2c0-.9.7-1.6 1.6-1.6zm2.6 0h4.8V7.5a2.4 2.4 0 0 0-4.8 0zM12 13.3a1.7 1.7 0 0 0-.9 3.1v1.9h1.8v-1.9a1.7 1.7 0 0 0-.9-3.1z'/%3E%3C/svg%3E"); }
.modal-box.gatebox .fld-key { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill-rule='evenodd' d='M7.5 7a4.5 4.5 0 1 0 4.24 6H14v2.5h2.6V13h1.6v2.5h2.6V11h-9.06A4.5 4.5 0 0 0 7.5 7zm0 3a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3z'/%3E%3C/svg%3E"); }
.modal-box.gatebox .fld-url { --ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill-rule='evenodd' d='M12 2.5a9.5 9.5 0 1 0 0 19 9.5 9.5 0 0 0 0-19zm-1.4 2.3C9.4 6.4 8.7 8.6 8.6 11H4.8a7.3 7.3 0 0 1 5.8-6.2zm2.8 0A7.3 7.3 0 0 1 19.2 11h-3.8c-.1-2.4-.8-4.6-2-6.2zM10.8 11c.1-2.3.6-4.2 1.2-5.3.6 1.1 1.1 3 1.2 5.3zm-6 2h3.8c.1 2.4.8 4.6 2 6.2A7.3 7.3 0 0 1 4.8 13zm6 0h2.4c-.1 2.3-.6 4.2-1.2 5.3-.6-1.1-1.1-3-1.2-5.3zm4.6 0h3.8a7.3 7.3 0 0 1-5.8 6.2c1.2-1.6 1.9-3.8 2-6.2z'/%3E%3C/svg%3E"); }
/* цифры с картинки — крупно и по центру, без значка */
.modal-box.gatebox .fld-cap::before { display: none; }
.modal-box.gatebox .fld-cap input { padding: 0 12px; text-align: center; font-size: 22px; letter-spacing: .3em; }
.modal-box.gatebox .fld-cap input::placeholder { font-size: 15px; letter-spacing: normal; }
.modal-box.gatebox .gate-hint { margin: -2px 2px 2px; line-height: 1.4; }
/* галочка под соглашением: своя, крупная (палец попадает), ссылки — отдельно от неё */
.modal-box .agree { display: flex; gap: 12px; align-items: center; font-size: 14px; line-height: 1.4; cursor: pointer; margin-top: 2px;
  padding: 7px 12px; border-radius: 10px; background: rgba(0,0,0,0.22); border: 1px solid rgba(255,236,200,0.07); }
.modal-box .agree input[type=checkbox] { -webkit-appearance: none; appearance: none; width: 28px; height: 28px; flex: 0 0 28px; margin: 0;
  border: 2px solid #6b4526; border-radius: 7px; background: linear-gradient(180deg, #120b06, #21160c); box-shadow: inset 0 2px 5px rgba(0,0,0,0.7);
  cursor: pointer; display: grid; place-content: center; transition: background .15s, border-color .15s; }
.modal-box .agree input[type=checkbox]::after { content: ''; width: 16px; height: 16px; background: #10180a; transform: scale(0); transition: transform .12s;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9.2 16.6 4.6 12l-2.1 2.1 6.7 6.7L21.5 8.5l-2.1-2.1z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9.2 16.6 4.6 12l-2.1 2.1 6.7 6.7L21.5 8.5l-2.1-2.1z'/%3E%3C/svg%3E") center / contain no-repeat; }
.modal-box .agree input[type=checkbox]:checked { background: linear-gradient(#8fe04a, #4a8a24); border-color: #2d4a14; box-shadow: 0 0 0 3px rgba(127,210,58,0.2); }
.modal-box .agree input[type=checkbox]:checked::after { transform: scale(1); }
.modal-box .agree input[type=checkbox]:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.modal-box .agree a { color: var(--gold); }
/* нажал «Регистрация» без галочки — строка с галочкой подсвечена красным, видно, куда жать */
.modal-box .agree.need { border-color: rgba(217,68,47,0.75); box-shadow: 0 0 0 2px rgba(217,68,47,0.22); }
.modal-box .agree.need input[type=checkbox]:not(:checked) { border-color: #d9442f; }
/* картинка «я не робот» — на своей плашке: картинка и «другая картинка» рядом, поле для цифр под ними */
#capbox:empty { display: none; }
#capbox { padding: 8px 10px; border-radius: 12px; background: rgba(0,0,0,0.22); border: 1px solid rgba(255,236,200,0.07); }
.capt { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.capt img { width: 190px; max-width: calc(100% - 62px); height: 64px; object-fit: cover; border-radius: 8px; flex: 0 1 auto; box-shadow: 0 2px 6px rgba(0,0,0,0.5); order: 1; }
.capt .btn { width: 52px; height: 52px; min-width: 52px; padding: 0; font-size: 22px; flex: 0 0 auto; order: 2; }
.capt .fld-cap { flex: 1 1 100%; order: 3; }
/* широкое окно: всё одной строкой — картинка, поле, «другая картинка» (экономит строку по высоте) */
@media (min-width: 600px) { .capt { flex-wrap: nowrap; } .capt .fld-cap { flex: 1 1 auto; min-width: 0; order: 2; } .capt .btn { order: 3; } }
/* ошибка — красной плашкой, чтобы её не пропустили */
.modal-box.gatebox .gate-err { margin: 8px 0 0; padding: 6px 12px; border-radius: 10px; background: rgba(217,68,47,0.16); border: 1px solid rgba(217,68,47,0.5);
  color: #ffb3a6; font-size: 13px; line-height: 1.4; }
/* главная кнопка и запасные: ровный ряд с просветом, не впритык (одна запасная — во всю ширину, две — пополам) */
.modal-box.gatebox .btn.big.gate-go { margin-top: 12px; }
.modal-box.gatebox .gate-alt { display: flex; gap: 10px; margin-top: 10px; }
.modal-box.gatebox .gate-alt:empty { display: none; }
.modal-box.gatebox .gate-alt .btn { flex: 1 1 0; min-width: 0; min-height: 44px; margin: 0; }
@media (max-width: 340px) { .modal-box.gatebox .gate-alt { flex-direction: column; } }
.gate-ru { margin-top: 12px; padding-top: 9px; border-top: 1px dashed rgba(239,230,210,0.16); line-height: 1.45; }
/* невысокий экран (ноутбук 1366×768 с панелями браузера — ~650 px): то же окно плотнее, чтобы регистрация влезала целиком */
@media (max-height: 760px) {
  .modal-box.gatebox h2 { margin-bottom: 6px; font-size: 20px; }
  .modal-box.gatebox .gate-intro { font-size: 11.5px; line-height: 1.35; }
  .modal-box.gatebox .netbox { gap: 6px; margin-top: 8px; }
  .modal-box.gatebox .fld input { height: 38px; font-size: 15px; }
  .modal-box.gatebox .gate-hint { font-size: 11.5px; line-height: 1.3; }
  .modal-box .agree { padding: 5px 12px; font-size: 13px; }
  .modal-box .agree input[type=checkbox] { width: 24px; height: 24px; flex-basis: 24px; }
  #capbox { padding: 6px 8px; }
  .capt img { width: 150px; height: 50px; }
  .capt .btn { width: 44px; height: 44px; min-width: 44px; font-size: 19px; }
  .modal-box.gatebox .fld-cap input { font-size: 19px; }
  .modal-box.gatebox .btn.big.gate-go { margin-top: 8px; }
  .modal-box.gatebox .gate-alt { margin-top: 8px; }
  .modal-box.gatebox .gate-alt .btn { min-height: 38px; }
  .gate-ru { margin-top: 8px; padding-top: 6px; font-size: 11px; line-height: 1.35; }
}
/* документы в окне игры: текст terms.html / privacy.html */
.modal-box.legalbox { width: 720px; }
.legaltabs { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 44px 10px 0; }
.modal-box.gatebox:not(.free) .legaltabs { margin-right: 0; }   /* в замке крестика нет — место под него не нужно */
.legaltabs .btn { padding: 6px 10px; font-size: 13px; min-width: 0; }
.legaldoc { text-align: left; line-height: 1.5; font-size: 14px; background: rgba(0,0,0,0.22); border-radius: 10px; padding: 4px 14px 10px; margin-bottom: 8px; }
.modal-box .legaldoc h1 { font-size: 20px; color: var(--gold); margin: 10px 0 2px; }
.modal-box .legaldoc h2 { font-size: 16px; color: #b8e07a; margin: 16px 0 4px; text-shadow: none; }
.legaldoc .date { opacity: .7; font-size: 13px; margin-top: 0; }
.legaldoc ul { padding-left: 20px; margin: 4px 0; }
.legaldoc a, .legalfoot a { color: var(--gold); }
.legalfoot { margin: 0 0 8px; }
.modal-box h2 { margin: 0 0 10px; font-size: 22px; color: var(--gold); text-shadow: 0 2px 0 #000; }
#modal-content > h2:first-child { padding-right: 40px; }   /* длинный заголовок («Модуль: Пулемётное гнездо») не уходит под крестик окна */
.modal-box h3 { margin: 16px 0 6px; font-size: 15px; color: var(--rust2); }
/* крестик: flex-центрирование, иначе глиф стоит по базовой линии и висит выше середины */
/* Крестик рисуем двумя палочками, а не символом «×»: у символа своя посадка в шрифте, и он всегда
   стоял чуть ниже центра кружка. Палочки центрируются точно, в любом шрифте и на любом размере. */
.modal-box .close { position: absolute; top: 8px; right: 10px; width: 34px; height: 34px; border-radius: 50%; border: 2px solid #2f1d0e; background: var(--red); font-size: 0; color: transparent; padding: 0; }
.modal-box .close::before, .modal-box .close::after { content: ''; position: absolute; left: 50%; top: 50%; width: 16px; height: 3px; border-radius: 2px; background: #fff; }
.modal-box .close::before { transform: translate(-50%, -50%) rotate(45deg); }
.modal-box .close::after { transform: translate(-50%, -50%) rotate(-45deg); }
.modal-box .close:active { transform: scale(.92); filter: brightness(.9); }
.tabs { display: flex; gap: 8px; margin-bottom: 10px; flex-wrap: wrap; }
.tab { border: 2px solid var(--wood); background: rgba(0,0,0,0.3); color: var(--bone); border-radius: 10px; padding: 6px 12px; font-weight: 700; font-size: 13px; }
.tab.on { background: var(--rust); border-color: var(--rust2); }
/* Внутренний переключатель (виды перков): те же кнопки, но помельче — он второй в окне */
.tabs.sub { gap: 6px; margin: 10px 0 8px; }
.tabs.sub .tab { padding: 5px 10px; font-size: 12px; }
.tabs.sub .tab .ricon { width: 16px; height: 16px; vertical-align: -3px; }   /* «Куда потратить»: значок 26 px раздувал вкладки ресурсов в три ряда */
@media (max-width: 700px) { .tabs.sub .tab { padding: 5px 7px; } }   /* фильтр ленты убежища — в один ряд на телефоне */
.tabs.sub .tab small { opacity: .6; font-weight: 700; }
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.card { background: rgba(0,0,0,0.3); border: 2px solid var(--wood); border-radius: 12px; padding: 8px; display: flex; flex-direction: column; align-items: center; gap: 4px; cursor: pointer; text-align: center; transition: transform .08s; }
.card:hover { border-color: var(--rust2); box-shadow: 0 0 10px rgba(255,220,150,0.18); }
.card:not(.dis):active { transform: scale(.98); filter: brightness(1.12); }
.card.dis { opacity: .55; }
.card .pic { width: 80px; height: 80px; object-fit: contain; }
/* Магазин: картинка чуть меньше — вкладка «Стратегия» (12 построек, три ряда) не влезала в окно на
   17 px и заставляла листать (нашла автопроверка ИИ-тестеров). 70 px хватает, чтобы узнать постройку. */
.cards.shopcards .card .pic { width: 70px; height: 70px; }
.pic.ph { image-rendering: auto; }
.ck { filter: url(#chroma-key); } /* запасное вырезание пурпурного фона (file://), см. game.html */
.cname { font-weight: 800; font-size: 13px; }
.cname small { opacity: .7; font-weight: 500; }
.cinfo { font-size: 12px; display: flex; gap: 8px; align-items: center; }
.ccount { font-size: 11px; opacity: .7; }
.cerr { font-size: 11px; color: #ffb3a7; }
/* причина, почему разведку не отправить: крупно и рамкой в верху окна разведки */
.scoutwhy { margin: 8px 0 6px; padding: 8px 10px; border: 2px solid #8a3b2e; border-radius: 10px; background: rgba(120,30,20,.25); color: #ffd2c8; font-size: 13px; line-height: 1.35; }
.resrow b.nowrap { white-space: nowrap; }
a.inlink { color: var(--gold); text-decoration: underline dotted; }   /* ссылка внутри строки окна («что даёт звание →») */
.ultnone { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; margin: 8px 0 4px; padding: 10px; border: 2px dashed var(--wood2); border-radius: 12px; }
/* «рабочие заняты» — жёлтая пометка ожидания, карточка/кнопка не тухнут (тухнут только от ресурсов и штаба) */
.cbusy { font-size: 11px; color: #ffd66b; display: inline-flex; align-items: center; gap: 3px; background: rgba(255,190,40,0.12); border: 1px dashed rgba(255,214,107,0.55); border-radius: 8px; padding: 1px 7px; }
.tnode .cbusy { font-size: 10px; padding: 0 5px; }
.card.busy { border-style: dashed; }
/* Карточка мутации: слева зомби, справа — что изменится. Вертикальная раскладка оставляла
   полкарточки пустыми, а цифры жались в узкий столбик по центру. */
.cards.mut { grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); }
.card.mut { flex-direction: row; align-items: stretch; text-align: left; gap: 10px; padding: 10px; }
.card.mut .mpic { flex: 0 0 76px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; }
.card.mut .pic { width: 76px; height: 76px; }
/* Мутация «до → после»: слева зомби как сейчас, справа — каким он станет (с цветом новой ступени) */
.card.mut .mpic.two { flex: 0 0 auto; flex-direction: row; align-items: center; gap: 2px; }
.card.mut .mpic.two .pic { width: 62px; height: 62px; }
.card.mut .mone { display: flex; flex-direction: column; align-items: center; gap: 1px; }
.card.mut .mone small { font-size: 10px; opacity: .7; }
.card.mut .mone.next small { opacity: 1; color: var(--gold); font-weight: 700; }
.card.mut .mone.next .pic { filter: drop-shadow(0 0 6px rgba(255,212,94,.55)); }
.card.mut .marr { font-size: 18px; font-weight: 800; color: var(--gold); opacity: .85; }
/* На телефоне две картинки и колонка чисел в 400 px уже не помещаются: ужимаем картинки,
   разрешаем плашке ступени переноситься, а числам — сжиматься. */
@media (max-width: 560px) {
  .card.mut { gap: 6px; padding: 8px; }
  .card.mut .mpic.two .pic { width: 48px; height: 48px; }
  .card.mut .marr { font-size: 14px; }
  .card.mut .mbody { min-width: 0; }
  .card.mut .cname { display: flex; flex-wrap: wrap; align-items: center; gap: 3px; }
  .card.mut .ztier { white-space: normal; }
  .card.mut .zstats.grid { font-size: 11px; gap: 2px 6px; }
}
.card.mut .mup { font-size: 10px; font-weight: 800; color: #1a1a14; background: var(--gold); border-radius: 6px; padding: 1px 5px; }
.card.mut .mbody { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.card.mut .cinfo { justify-content: flex-start; }
.zstats.grid { display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; align-items: baseline; font-size: 12px; }
.zstats.grid b { justify-self: end; color: #e6e4d6; }
/* плашка ступени мутации: цвет тот же, что у ауры зомби в бою */
.uiconimg { width: 44px; height: 44px; object-fit: contain; }
.ztier { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;
  color: var(--tc); border: 1px solid var(--tc); border-radius: 6px; padding: 0 4px; white-space: nowrap; }
.btn em.busy { color: #ffd66b; }
.zstats { font-size: 11px; opacity: .85; }
.zstats .ricon { width: 15px; height: 15px; vertical-align: -3px; }
.zstats .next { font-style: normal; color: var(--toxic); }
.cdesc { font-size: 11px; opacity: .65; line-height: 1.3; }
.muted { opacity: .7; }
.small { font-size: 12px; }
.row { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px dashed rgba(255,255,255,0.1); }
.devrow { display: flex; gap: 6px; flex-wrap: wrap; }
/* Настройки: на широком экране — две колонки (ряды настроек, затем «онлайн» рядом с инструментами) */
@media (min-width: 760px) { .setgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 24px; align-items: start; } }
.setgrid .row .btn { padding-top: 5px; padding-bottom: 5px; }
.modal-box h2 + .setgrid { padding-top: 8px; }   /* первая строка правой колонки — под крестиком окна */
body.sk-btn .setgrid .row .btn { border-width: 8px; border-image-width: 8px; padding: 1px 4px; }   /* рамка кнопки тоньше — ряд ниже */
.setgrid .row { padding: 3px 0; }
.setgrid .netform input { padding: 6px 10px; }
/* План на следующий штаб над карточками магазина */
.hqplan { font-size: 13px; margin: -2px 0 10px; padding: 6px 10px; border: 1px dashed rgba(255,210,58,.45); border-radius: 8px; background: rgba(0,0,0,.25); line-height: 1.7; }
.netform { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; }
.netform input { padding: 8px 10px; border-radius: 8px; border: 2px solid var(--wood); background: rgba(0,0,0,0.35); color: var(--bone); font-size: 14px; }
.netform div { display: flex; gap: 6px; }
.capbar { position: relative; height: 26px; background: rgba(0,0,0,0.4); border: 2px solid var(--wood); border-radius: 8px; overflow: hidden; margin-bottom: 10px; }
.capbar .fill { position: absolute; left: 0; top: 0; bottom: 0; background: var(--moss2); }
.capbar .fillq { position: absolute; top: 0; bottom: 0; background: repeating-linear-gradient(45deg, #7fd23a55, #7fd23a55 6px, #0000 6px, #0000 12px); }
.capbar span { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 13px; text-shadow: 0 1px 2px #000; }
.armyrow { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; min-height: 40px; }
.unit { display: flex; flex-direction: column; align-items: center; background: rgba(0,0,0,0.3); border-radius: 10px; padding: 4px 8px; }
.unit .pic { width: 40px; height: 40px; object-fit: contain; }
.unit small { font-size: 10px; opacity: .75; }
.queue { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; font-size: 13px; }
.qitem { display: flex; flex-direction: column; align-items: center; cursor: pointer; }
.qitem .pic { width: 32px; height: 32px; object-fit: contain; }
.qitem small { font-size: 10px; }
/* очередь инкубатора группами: счётчик «×N» на картинке, общее время, крестик «очистить» */
.qitem { position: relative; }
.qitem .qn { position: absolute; right: -6px; top: -4px; font-size: 11px; font-weight: 800; background: var(--rust); border: 1px solid #2f1d0e; border-radius: 8px; padding: 0 4px; line-height: 14px; text-shadow: 0 1px 0 #000; }
.qtotal { font-size: 12px; opacity: .8; margin-left: 4px; }
.qclear { margin-left: auto; padding: 3px 8px; }
/* оптовые кнопки на карточке зомби */
.bulk { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; margin-top: 2px; }
.bulk .btn { padding: 3px 7px; font-size: 11px; }
.bulk .btn.max { flex: 1 1 100%; }                     /* «Макс N» — отдельной строкой на всю ширину карточки */
/* Ползунок «сколько вырастить» на карточке зомби */
.bulk .bslider { flex: 1 1 100%; -webkit-appearance: none; appearance: none; height: 18px; background: transparent; margin: 2px 0 0; cursor: pointer; }
.bulk .bslider::-webkit-slider-runnable-track { height: 8px; border-radius: 4px; background: rgba(0,0,0,0.45); border: 1px solid var(--wood); }
.bulk .bslider::-moz-range-track { height: 8px; border-radius: 4px; background: rgba(0,0,0,0.45); border: 1px solid var(--wood); }
.bulk .bslider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 18px; height: 18px; margin-top: -6px; border-radius: 50%; background: var(--moss2); border: 2px solid #12160f; box-shadow: 0 1px 0 #000; }
.bulk .bslider::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: var(--moss2); border: 2px solid #12160f; }
/* Пока тянут ползунок, карточка не должна «нажиматься» и подпрыгивать: из-за transform она уезжала
   из-под пальца, и значение скакало. */
.card:active:has(.bslider:active), .card:hover:has(.bslider:active) { transform: none; }
.bulk .bsinfo { flex: 1 1 100%; font-size: 11px; display: flex; gap: 6px; align-items: center; justify-content: center; flex-wrap: wrap; min-height: 16px; }
.bulk .bsinfo .bsn { color: var(--gold); font-size: 13px; }
/* «Вырастить» и «Макс N». У кнопок-картинок рамка по 11 px с каждой стороны, и в карточке шириной 150 px
   на подпись оставалось 58 и 19 px: «Вырастить» обрезалось, «Макс 25» ломалось в две строки
   (нашли ИИ-тестеры на 1280 и 400). Теперь подпись в одну строку, рамка тоньше, а если две кнопки
   рядом не помещаются — встают друг под другом во всю ширину карточки. */
.bulk .btn.bsgo, .bulk .btn.bsmax { flex: 1 1 auto; white-space: nowrap; }
body.sk-btn .bulk .btn { border-width: 7px; border-image-width: 7px; padding: 1px 4px; }
.bulk { row-gap: 5px; }
/* Журнал нападений: запись одной карточкой */
.logrow { border: 2px solid var(--wood); border-radius: 10px; padding: 6px 10px; margin-bottom: 6px; background: rgba(0,0,0,0.25); display: flex; flex-direction: column; gap: 4px; }
.logrow.raided { border-color: #8d3a2a; } .logrow.attack { border-color: #4a7a3a; } .logrow.raid { border-color: #5a5a8a; }
.logrow .lhead { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.logrow .lico { font-size: 16px; }
.logrow .lstars { color: var(--gold); letter-spacing: 2px; }
.logrow .armyrow { flex-wrap: wrap; gap: 4px; }
.logrow .unit { padding: 2px 4px; }
.logrow .btn { align-self: flex-start; }
.logrow .lloot .ricon { width: 16px; height: 16px; vertical-align: -3px; }
.logrow .lhead .lloot { margin-left: auto; }   /* добыча — справа в строке заголовка */
/* Легенда цветов уровней: видна только на разведке, гаснет вместе с подсветкой */
/* Легенда занимает свою строку над карточками зомби: в одном ряду с ними она на телефоне залезала на кнопки */
/* Легенда уровней вынута из потока и висит НАД нижней панелью. Пока она была flex-элементом
   с max-width: 94vw, строка ей не принадлежала целиком: карточки зомби ужимались в остаток
   и на широком экране уезжали за правый край. */
#lvl-legend { position: absolute; left: 50%; bottom: calc(100% - 8px); transform: translateX(-50%);
  width: max-content; display: flex; gap: 4px; align-items: center;
  background: rgba(14,17,12,0.78); border: 2px solid var(--wood); border-radius: 10px; padding: 4px 8px; pointer-events: none;
  transition: opacity .25s; max-width: 94vw; flex-wrap: wrap; justify-content: center; }
#lvl-legend .lgcap { font-size: 10px; color: #b9b09a; margin-right: 2px; }
#lvl-legend i { font-style: normal; font-size: 10px; font-weight: 700; color: #12160f; width: 16px; height: 16px; border-radius: 4px;
  display: flex; align-items: center; justify-content: center; text-shadow: none; }
@media (max-width: 560px) { #lvl-legend { padding: 3px 6px; } #lvl-legend i { width: 14px; height: 14px; font-size: 9px; } }
/* Чип ветки обороняющейся деревни в шапке боя */
.pathchip { display: inline-block; font-size: 10px; padding: 1px 6px; border: 1px solid; border-radius: 8px; vertical-align: middle; margin-left: 4px; opacity: .9; }
/* Роли зомби: заголовок группы, значок на карточке, цветная рамка в баре боя */
.rolehead { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; margin: 12px 0 4px; font-size: 14px; }
.rolehead small { font-weight: 400; font-size: 11px; }
.rolegrps { display: flex; flex-wrap: wrap; gap: 0 14px; align-items: flex-start; }
.rolegrp { min-width: 150px; }
.rolegrp.narrow .rolehead small { display: none; }   /* узкая группа — пояснение роли только в подсказке заголовка */
.rolegrp .cards { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.bcard .cdesc { flex: 1 1 auto; }   /* описание растягивается — ползунок и «Вырастить» у соседних карточек на одной линии */
.card.role-tank, .card.role-melee, .card.role-ranged, .card.role-special, .card.role-support { position: relative; }
/* Закрытые виды в окне орды — свёрнутый список мелких карточек под доступными */
.zlocked { margin: 14px 0 4px; }
.zlocked > summary { cursor: pointer; font-weight: 700; font-size: 14px; padding: 6px 2px; }
.zlocked > summary small { font-weight: 400; font-size: 11px; }
.cards.zmini { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 8px; margin-top: 6px; }
.card.zmini { padding: 6px 4px; gap: 2px; }
.card.zmini .pic { width: 52px; height: 52px; }
.card.zmini .cname { font-size: 12px; max-width: 100%; overflow-wrap: anywhere; hyphens: auto; }   /* «Гальванизированный» шире мелкой карточки */
.card.zmini .cerr { font-size: 10px; }
.rolebadge { position: absolute; top: 4px; left: 4px; width: 20px; height: 20px; border-radius: 50%; border: 2px solid #12160f; display: flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; }
.card.role-tank { border-color: #8a6a3a; } .card.role-ranged { border-color: #5ad0ff; }
.card.role-support { border-color: #ffd23a; } .card.role-special { border-color: #ff8a3c; }
.ucard.role-tank { border-color: #8a6a3a; } .ucard.role-ranged { border-color: #5ad0ff; }
.ucard.role-support { border-color: #ffd23a; } .ucard.role-special { border-color: #ff8a3c; }
/* Карточка доработки ветки */
.pmcard .ulvl { display: flex; gap: 4px; justify-content: center; margin: 4px 0; }
/* полосок стало пять (было три) — делаем их уже, чтобы ряд не упирался в край карточки на телефоне */
.pmcard .ulvl i { width: 18px; height: 8px; border-radius: 3px; background: rgba(0,0,0,0.5); border: 1px solid var(--wood); }
.pmcard .ulvl i.on { background: var(--gold); }
.pmcard .btn { width: 100%; justify-content: center; }
.pmcard .nw { white-space: nowrap; }
.pmcard .cinfo, .pmcard .pmcost { display: flex; flex-wrap: wrap; gap: 4px 8px; justify-content: center; width: 100%; font-size: 11px; }
.pmcard .zstats { font-size: 12px; }
/* Рюкзак: карточка ценности — что это, сколько и куда нести */
.bagcard { text-align: left; align-items: stretch; cursor: default; }
.bagcard .cname { text-align: center; }
.bagcard .bagn { color: var(--gold); font-size: 15px; }
.bagcard .cdesc { font-size: 11px; }
.bagcard .baguse { display: flex; flex-direction: column; gap: 3px; margin-top: auto; padding-top: 6px; width: 100%; }
.bagcard .baguse .btn { width: 100%; justify-content: center; font-size: 11px; padding: 5px 8px; }
#bag-info.has-badge { border-color: var(--gold); }
/* Карточка исследования штамма: полоса залитых доз */
.rcard .rbar { position: relative; width: 100%; height: 18px; border: 2px solid var(--wood); border-radius: 7px; background: rgba(0,0,0,0.45); overflow: hidden; }
.rcard .rbar .rfill { position: absolute; left: 0; top: 0; bottom: 0; background: linear-gradient(180deg, #9fe25a, #5ea62a); transition: width .2s; }
.rcard .rbar span { position: relative; display: block; text-align: center; font-size: 11px; line-height: 14px; text-shadow: 0 1px 0 #000; }
.rcard .btn { width: 100%; }
.rcard .zstats { font-size: 11px; line-height: 1.45; }
.rcard .nw { white-space: nowrap; }                    /* «1ч 18м» не должно ломаться посередине */
.rdone { margin-top: 8px; }
/* Строка «стоимость орды» над очередью инкубатора */
.armycost { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin: -4px 0 8px; }
.stars.big { font-size: 40px; color: var(--gold); text-align: center; text-shadow: 0 3px 0 #000; margin: 6px 0; letter-spacing: 6px; }
/* невзятая звезда — тусклая, не золотая (UI.starsHtml) */
.st.off { color: rgba(236, 226, 205, .22); text-shadow: none; }
.resrow { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px dashed rgba(255,255,255,0.1); font-size: 14px; }
/* Предложение скупщика в лавке: дорого ресурсами — платит батарейками */
.dealbox { border: 2px solid #8fd14f; border-radius: 10px; padding: 10px; margin: 8px 0; background: rgba(143,209,79,.10); }
.dealbox .dtitle { font-weight: 800; margin-bottom: 4px; }
.dealbox .dwhat { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 8px; }
.dealbox .arr { font-style: normal; opacity: .7; }

/* Достижения: карточка со ступенями-звёздочками и полосой прогресса */
.acard { text-align: center; padding: 6px; gap: 2px; }
.acard .capbar { align-self: stretch; }
/* кнопка «Забрать» и цена — внизу карточки: у «Держим оборону» название в две строки, и её «Забрать» стояла
   на 16 px ниже соседней (автопроверка отчёта 20-41) */
.acard > .btn, .acard > .cinfo { margin-top: auto; }
.achtop { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.achtop p { margin: 0; flex: 1 1 240px; }
.achtop .btn { flex: 0 0 auto; }   /* без этого полоска съёживалась в чёрточку и «0 / 1» не было видно */
.cards.achlist { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px; }
.acard .cname { font-size: 12px; }
@media (min-width: 760px) { .ptasks2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; align-items: start; } }
.ptblock h3 { margin-top: 6px; }
.acard .aico { font-size: 24px; line-height: 1.1; }
.acard.done { opacity: .65; }
.acard.ready { border-color: #8fd14f; box-shadow: 0 0 0 2px rgba(143,209,79,.25) inset; }
.astars { display: flex; gap: 4px; justify-content: center; margin: 3px 0; }
.astars i { width: 10px; height: 10px; border-radius: 50%; background: rgba(255,255,255,0.18); border: 1px solid rgba(0,0,0,.35); }
.astars i.on { background: #ffd23a; }
.capbar.sm { height: 18px; margin: 4px 0 6px; }
.capbar.sm span { font-size: 11px; }

/* Расходник пути во вкладке «Ульта»: значок, описание и кнопка заправки одной полосой */
.kitbox { display: flex; align-items: center; gap: 12px; padding: 10px; margin: 10px 0; border: 2px solid #6b5a3a; border-radius: 10px; background: rgba(0,0,0,0.18); }
.kitbox .kicon { font-size: 34px; line-height: 1; flex: 0 0 auto; }
.kitbox .kbody { flex: 1 1 auto; min-width: 0; }
.kitbox .kname { font-weight: 800; }
.kitbox .btn { flex: 0 0 auto; }
@media (max-width: 560px) { .kitbox { flex-wrap: wrap; } .kitbox .kbody { flex: 1 1 100%; order: 3; } }

/* Окно «Куда потратить» (клик по счётчику ресурса): строка — что купить, чем это будет и почём */
.spendsec { margin: 10px 0 2px; font-size: 12px; letter-spacing: 1px; text-transform: uppercase; opacity: .6; }
/* без отрицательных полей: строка не должна вылезать за ширину окна (появлялась горизонтальная прокрутка) */
.spendrow { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 7px 4px;
  border-bottom: 1px dashed rgba(255,255,255,0.1); font-size: 14px; border-radius: 6px; cursor: pointer; }
.spendrow:hover { background: rgba(255,255,255,0.06); }
.spendrow.dim { opacity: .55; cursor: default; }
.spendrow.dim:hover { background: none; }
.spendrow.waitrow { opacity: .8; }   /* хватает, но сразу не выйдет: рабочие заняты, загон полон (отчёт 17-25) */
.spendrow i.wait, .spendwait i.wait { font-style: normal; color: var(--rust2); }
.spendwait { margin: 2px 0 6px; }   /* общая причина ждать — одной строкой над списком, в строках только ⏳ (отчёт 20-41) */
.pgpre .btn.on { outline: 2px solid var(--gold); outline-offset: 1px; }   /* полигон: какой набор орды сейчас подставлен (отчёт 17-47) */
#b-loot .lfull, #b-loot .lfull small { color: #ff8a6e; }   /* склад полон — эта добыча пропадёт (отчёт 17-47) */
.spendrow .sn { display: flex; flex-direction: column; min-width: 0; }
.spendrow .sn small { font-size: 11px; opacity: .6; }
.spendrow b { display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.spendrow b small { font-size: 11px; }

.alist { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 2px 12px; }
.aitem { display: flex; gap: 6px; align-items: center; font-size: 12px; padding: 2px 0; opacity: .6; }
.aitem.ok, .aitem.req { opacity: 1; }
.aitem.req code { color: #ffb3a7; }

.bad-txt { color: #ff8a7a; }
#b-airdrop { position: absolute; top: 140px; left: 50%; transform: translateX(-50%); background: var(--panel); border: 2px solid var(--blue); border-radius: 10px; padding: 4px 12px; font-size: 13px; }
.pathhead { grid-column: 1 / -1; font-weight: 800; font-size: 15px; padding: 6px 4px 2px; border-bottom: 2px solid; margin-top: 4px; }
.pathhead small { display: block; font-weight: 400; font-size: 12px; color: var(--bone); opacity: .8; margin-top: 2px; line-height: 1.35; }
.ucard.strike { border-color: #ffe066; }
.ucard .pic.big { font-size: 34px; line-height: 44px; height: 44px; color: #ffe066; text-shadow: 0 0 10px #ffe066; }
.pathhead.steam { color: #d9a066; border-color: #b87333; }
.pathhead.diesel { color: #aab7bf; border-color: #5c6b73; }
.pathhead.cyber { color: #5fe0f0; border-color: #1fb5c9; }
.card.p-steam { border-color: #8a5a2a; } .card.p-diesel { border-color: #4a5860; } .card.p-cyber { border-color: #167f8c; }
.xrow { display: flex; justify-content: space-between; align-items: center; padding: 6px 0; border-bottom: 1px dashed rgba(255,255,255,0.1); font-size: 14px; }
.xrow span:last-child { display: flex; gap: 6px; flex: 0 0 auto; }
.xrow { gap: 8px; }
.xrow > span:first-child { flex: 1 1 auto; min-width: 0; }
.xrow .btn { min-width: 64px; justify-content: center; }   /* «×1» не сжимается в столбик рядом с «×10 · нужно 1000» */
.xrow .btn em { font-size: 10px; }
.xrow .exdisc { color: #ffb38a; font-weight: 700; white-space: nowrap; }   /* скидка лавки за избыток (MARKET.surplusK) */
.xrow .btn { max-width: 96px; } .xrow .btn em { white-space: normal; line-height: 1.15; }   /* «склад металла полон» — в две строки, а не шириной в пол-окна (отчёт 17-47) */
.xrow span:last-child { align-items: center; }   /* «×1» рядом с серой «×10 · влезет 1010» не растягивается на всю высоту строки */
.xrow .xwhy { display: block; color: #e0a07a; margin-top: 2px; }   /* одна причина на обе кнопки — строкой под курсом */
#tooltip .inl { display: inline; font-size: 12.5px; color: var(--bone); margin: 0; }

.res.pathres { min-width: 96px; }
/* min(360px, 100%) — иначе на телефоне колонка в 360 px шире самого окна, и карточки путей
   вылезали за край с обрезанным текстом */
.pathgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(360px, 100%), 1fr)); gap: 10px; }
.pathcard { border: 2px solid; border-radius: 14px; padding: 12px; background: rgba(0,0,0,0.3); display: flex; flex-direction: column; gap: 6px; }
.pathcard .pname { font-weight: 800; font-size: 17px; }
.pathcard .pwho { font-size: 12.5px; opacity: .85; line-height: 1.35; flex: 1; }
.pres { font-size: 12.5px; display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.pres .ricon { width: 18px; height: 18px; } .pres .remoji { font-size: 14px; width: 18px; line-height: 18px; }
.pbtns { display: flex; gap: 6px; flex-wrap: wrap; }
.pathtabs { display: flex; gap: 8px; flex-wrap: wrap; margin: 6px 0 10px; }
.ptab { border: 2px solid var(--wood); background: rgba(0,0,0,0.3); color: var(--bone); border-radius: 8px; padding: 4px 10px; font-size: 12px; font-weight: 700; opacity: .7; }
.ptab.on { opacity: 1; background: rgba(255,255,255,0.06); } .ptab.mine { opacity: 1; }
.ptab .pdot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 5px; vertical-align: 0; box-shadow: 0 0 0 1px rgba(0,0,0,.5); }
.treehead { border-left: 4px solid; padding: 6px 10px; margin-bottom: 10px; font-size: 13px; display: flex; flex-direction: column; gap: 4px; background: rgba(0,0,0,0.25); border-radius: 0 10px 10px 0; }
.treewrap { overflow: auto; padding: 6px 4px 12px; }
.tree { position: relative; }
.tree svg { position: absolute; left: 0; top: 0; pointer-events: none; }
.tnode { position: absolute; background: rgba(0,0,0,0.35); border: 3px solid var(--wood); border-radius: 12px; padding: 6px; display: flex; flex-direction: column; align-items: center; gap: 3px; text-align: center; cursor: pointer; transition: transform .08s; }
.tnode:hover { filter: brightness(1.12); }
.tnode:active { transform: scale(.98); }
.tnode .pic { width: 64px; height: 64px; object-fit: contain; }
.tnode.znode .pic { width: 48px; height: 48px; }
.tnode .cname { font-size: 12px; line-height: 1.2; overflow-wrap: anywhere; max-width: 100%; }
.tnode.locked { opacity: .5; filter: grayscale(.6); }
.tnode.avail { border-color: var(--rust2); box-shadow: 0 0 10px rgba(216,115,61,0.35); }
.tnode.built { background: rgba(255,255,255,0.06); }
.tnode.prod::before { content: '⛏'; position: absolute; top: 2px; right: 6px; font-size: 12px; opacity: .7; }
.tnode .tstate { font-size: 11px; font-weight: 700; }
.tnode .cerr { font-size: 10px; }

/* ---- подсказки при наведении ---- */
#tooltip { position: fixed; left: 0; top: 0; z-index: 90; max-width: 280px; padding: 9px 12px; border-radius: 10px;
  background: rgba(20, 16, 12, 0.96); border: 2px solid var(--rust2); box-shadow: 0 6px 20px rgba(0,0,0,0.6);
  font-size: 12.5px; line-height: 1.4; color: var(--bone); pointer-events: none; opacity: 0; transform: translateY(6px) scale(.97);
  transition: opacity .14s ease, transform .18s cubic-bezier(.2,1.25,.4,1); }
#tooltip.show { opacity: 1; transform: none; }
#tooltip b { display: block; font-size: 14px; color: var(--gold); margin-bottom: 2px; }
#tooltip .tsub { opacity: .75; font-size: 11.5px; margin-bottom: 4px; }
#tooltip .tdesc { opacity: .8; margin-top: 5px; font-style: italic; }
#tooltip small { opacity: .7; }

/* ---- загрузка ---- */
#loading { position: absolute; inset: 0; background: #12190f center/cover no-repeat; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; z-index: 100; transition: opacity .45s; }
#loading.gone { opacity: 0; pointer-events: none; }
#loading::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(8,12,6,.55), rgba(8,12,6,.25) 45%, rgba(8,12,6,.85)); opacity: 0; }
#loading.hasart::after { opacity: 1; }
#loading > * { position: relative; z-index: 1; }
#loading .prog { font-size: 13px; opacity: .55; letter-spacing: 1px; }
/* ---- шкала загрузки, которую тащит зомби ----
   Полоса — доска с хазард-полосами; залитая часть это то, что зомби уже дотащил. Сам он идёт по
   краю заливки, упирается и качается в такт шагам, за ним тянется верёвка. Всё нарисовано CSS:
   на экране загрузки картинок ещё нет, и зависеть от них тут нельзя. */
#loading .lbar { position: relative; width: min(460px, 78vw); height: 26px; border-radius: 14px;
  background: rgba(0,0,0,.45); border: 2px solid #2f3a24; box-shadow: inset 0 2px 6px rgba(0,0,0,.6); margin-top: 34px; }
#loading .lfill { position: absolute; left: 2px; top: 2px; bottom: 2px; width: 2%; border-radius: 12px;
  background: repeating-linear-gradient(115deg, #7fd23a 0 12px, #62a72c 12px 24px);
  box-shadow: 0 0 12px rgba(127,210,58,.5); transition: width .35s ease-out; }
/* Верёвка: короткий обрывок от руки зомби назад-вниз, к полосе. Раньше она тянулась во всю залитую
   часть шкалы и читалась не как верёвка, а как серая линия, прочерченная поперёк всего экрана. */
#loading .lrope { left: -26px; top: 20px; width: 30px; height: 3px; border-radius: 2px;
  background: #6b5326; border: none !important; box-shadow: 0 1px 0 rgba(255,255,255,.14);
  /* угол подобран так, чтобы дальний конец лёг на верх полосы, а ближний остался в руке:
     зомби стоит на полосе (bottom: 21px), поэтому верх полосы — это ~35 px в его системе координат */
  transform: rotate(-31deg); transform-origin: 100% 50%; }
/* сам зомби стоит НА полосе, у самого края заливки, и упирается */
#loading .lzomb { position: absolute; left: 2%; bottom: 21px; width: 30px; height: 40px; transition: left .35s ease-out;
  transform-origin: 50% 100%; animation: lzwalk .52s ease-in-out infinite; }
#loading .lzomb i { position: absolute; display: block; box-sizing: border-box; border: 2px solid #1b2609; }
#loading .lzomb .zh { left: 8px; top: 0; width: 17px; height: 16px; border-radius: 6px 7px 5px 5px; background: #8fbf5a; }
#loading .lzomb .zh::after { content: ''; position: absolute; left: 10px; top: 5px; width: 3px; height: 3px; background: #1b2609; border-radius: 50%; box-shadow: -6px 0 0 #1b2609; }
#loading .lzomb .zb { left: 6px; top: 14px; width: 19px; height: 16px; border-radius: 5px; background: #7a6440; }
#loading .lzomb .za { left: 0px; top: 15px; width: 16px; height: 5px; border-radius: 3px; background: #8fbf5a; transform: rotate(18deg); transform-origin: 100% 50%; }
#loading .lzomb .zl { top: 28px; width: 6px; height: 12px; border-radius: 3px; background: #46521f; transform-origin: 50% 0; }
#loading .lzomb .l1 { left: 9px; animation: lzleg .52s ease-in-out infinite alternate; }
#loading .lzomb .l2 { left: 17px; animation: lzleg .52s ease-in-out infinite alternate-reverse; }
@keyframes lzwalk { 0%, 100% { transform: translateY(0) rotate(-7deg); } 50% { transform: translateY(-3px) rotate(-11deg); } }
@keyframes lzleg { from { transform: rotate(20deg); } to { transform: rotate(-20deg); } }
#loading .lsay { font-size: 15px; opacity: .92; min-height: 22px; text-align: center; max-width: min(460px, 82vw);
  margin-top: 4px; transition: opacity .25s; }
#loading .lsay.sw { opacity: 0; }
@media (prefers-reduced-motion: reduce) { #loading .lzomb, #loading .lzomb .zl { animation: none; } }
/* Лого сгенерировано БЕЗ БУКВ (пустая доска) — название игра пишет поверх сама, по центру доски */
#loading .logo.img { text-shadow: none; position: relative; display: inline-block; line-height: 0; }
#loading .logo.img img { display: block; width: min(520px, 76vw); height: auto; filter: drop-shadow(0 6px 18px rgba(0,0,0,.7)) drop-shadow(0 0 34px rgba(127,210,58,.35)); }
/* Надпись вписывается в саму доску: её края на картинке — 28..75 % по ширине и 31..80 % по высоте.
   Размер шрифта подбирает UI.fitTitle, чтобы буквы не вылезали за доску на любом экране. */
#loading .logo .title, .logo .title { position: absolute; left: 28%; top: 31%; width: 47%; height: 49%;
  display: flex; align-items: center; justify-content: center; text-align: center; line-height: 1.02;
  transform: rotate(-1.2deg); font-weight: 900; letter-spacing: 2px; color: #dff0b4; white-space: nowrap;
  text-shadow: 0 2px 0 #10160c, 0 0 18px rgba(127,210,58,.55), 0 4px 10px rgba(0,0,0,.7); }
/* Заголовок без картинки (лого ещё не приехало или игра не завелась). На телефоне 48 px с разрядкой
   не влезают в ширину экрана — буквы срезало по краям, поэтому размер считаем от ширины. */
#loading .logo { font-size: min(48px, 10vw); font-weight: 900; letter-spacing: 4px; color: var(--toxic);
  text-shadow: 0 0 20px #7fd23a88, 0 4px 0 #000; max-width: 100%; padding: 0 10px; box-sizing: border-box; text-align: center; }
/* заставка в окне приветствия */
.splash { display: block; width: 100%; border-radius: 12px; margin: -4px 0 10px; box-shadow: 0 6px 18px rgba(0,0,0,.5); }

/* ---- мобильные ---- */
@media (max-width: 700px) {
  .res { min-width: 78px; padding: 3px 8px 3px 4px; }
  .rnum b { font-size: 13px; }
  .pill { padding: 4px 8px; font-size: 12px; }
  .bigbtn { min-width: 60px; min-height: 52px; padding: 6px 8px; font-size: 10px; }
  .bigbtn .ico { font-size: 20px; }
  .bigbtn.attack { min-width: 80px; }
  /* 62vh вместо 50: панель штаба с поставками не влезала в половину экрана и прокручивалась
     на ровном месте. Выше поднимать нельзя — под панелью нижний ряд кнопок, над ней верхние пилюли. */
  #app #bpanel { left: 6px; right: 6px; width: auto; bottom: calc(84px + env(safe-area-inset-bottom, 0px)); max-height: 62vh; }
  .modal-box { padding: 14px; }
  .cards { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
  .card .pic { width: 60px; height: 60px; }
  .cards.shopcards .card .pic { width: 60px; height: 60px; }   /* правило магазина выше сильнее — повторяем для телефона */
  .btop { top: 92px; }
  #battle-hint { top: 150px; }
  #b-airdrop { top: 178px; }
  #hint { top: 100px; font-size: 12px; }
  .stat b { text-align: right; max-width: 60%; }
  /* нижняя панель на телефоне — одной строкой с прокруткой: три ряда кнопок съедали треть экрана
     и залезали под панель здания (у неё bottom рассчитан на один ряд) */
  #app #bottombar { flex-wrap: nowrap; overflow-x: auto; justify-content: flex-start; gap: 6px; padding: 8px 6px; pointer-events: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  #bottombar::-webkit-scrollbar { display: none; }
  /* стрелки по краям прокручиваемой нижней панели (UI.bbArrows) */
  .bbmore { display: block; position: absolute; bottom: calc(10px + env(safe-area-inset-bottom, 0px)); z-index: 7; width: 30px; height: 52px; padding: 0;
    border: 2px solid var(--wood); border-radius: 12px; background: linear-gradient(#5b3a1e, #2f1d0e); color: var(--bone);
    font-size: 26px; font-weight: 800; line-height: 1; box-shadow: 0 2px 10px rgba(0,0,0,0.7); }
  .bbmore.r { right: 2px; }
  .bbmore.l { left: 2px; }
  .bbmore.dot::after { content: ''; position: absolute; top: 5px; right: 4px; width: 9px; height: 9px; border-radius: 50%; background: #e0503a; border: 1px solid #2f1d0e; }
  .bigbtn { flex: 0 0 auto; }
  .res small, .res .rate { display: none; }         /* без строк «+400/ч» — плашки ресурсов вдвое ниже */
  body.in-battle #topbar { display: none; }         /* в бою ресурсы не нужны — добыча и так в HUD; экономим полэкрана */
  /* пальцем: цели касания не меньше 40 px */
  .modal-box .close { width: 40px; height: 40px; }
  .modal-box .close::before, .modal-box .close::after { width: 19px; height: 3.5px; }
  .tab { padding: 9px 8px; font-size: 12px; }   /* по бокам уже: восемь вкладок «Орды» — в два ряда, а не в три */
  .tabs { gap: 6px; }
  .rolehead small { display: none; }              /* пояснение роли — во всплывающей подсказке заголовка */
  .modal-box h3.rolehead { margin: 4px 0 4px; }
  .zlocked { margin: 8px 0 2px; }
  .modal-box .capbar { margin-bottom: 6px; }
  .modal-box .hordeline { margin-bottom: 0; }
  .card.bcard .cdesc { display: none; }
  .btn { padding: 10px 12px; }
  .btn.small { padding: 7px 10px; }
  .qitem .pic { width: 40px; height: 40px; }
  .modal-box { max-height: calc(100vh - 20px); max-height: calc(100dvh - 20px); }
}
/* Вырезы и скруглённые углы телефонов (viewport-fit=cover): панели не лезут под чёлку и жест «домой» */
#topbar { padding-top: calc(8px + env(safe-area-inset-top, 0px)); padding-left: calc(10px + env(safe-area-inset-left, 0px)); padding-right: calc(10px + env(safe-area-inset-right, 0px)); }
#bottombar, .bbottom { padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px)); padding-left: calc(10px + env(safe-area-inset-left, 0px)); padding-right: calc(10px + env(safe-area-inset-right, 0px)); }
#bpanel { bottom: calc(96px + env(safe-area-inset-bottom, 0px)); }
/* Верхняя полоса на телефоне (живой прогон 23.09): на штабе 6 с щитом — четыре ряда плашек, 213 px из 800, четверть
   экрана под цифрами. Рамка плашек тоньше, значки 22 px, без распорки между ресурсами и пилюлями — три ряда, 139 px. */
@media (max-width: 560px) {
  #topbar { gap: 4px; padding-left: calc(6px + env(safe-area-inset-left, 0px)); padding-right: calc(6px + env(safe-area-inset-right, 0px)); }
  #topbar .spacer { display: none; }
  #topbar .res { min-width: 0; gap: 4px; }
  #topbar .ricon { width: 22px; height: 22px; }
  body.sk-hud #topbar .res, body.sk-hud #topbar .pill { border-width: 7px; border-image-width: 7px; padding: 0 5px 0 2px; }
  body.sk-hud #topbar .pill { padding: 0 5px; }
}
#placebar { bottom: calc(96px + env(safe-area-inset-bottom, 0px)); }
/* двойной тап по кнопкам не должен зумить страницу; прокрутка внутри окон остаётся */
body { touch-action: manipulation; }
.modal-box, #bpanel, #unitbar, #bottombar, .treewrap { touch-action: pan-x pan-y; }
/* Телефон. Три мелочи, которые на компьютере не видны, а на телефоне бесят:
   1) потянул окно вниз у верхнего края — браузер решил, что это «обновить страницу», и перезапустил игру.
      overscroll-behavior обрывает эту цепочку: прокрутка окна упирается в край и дальше не уходит;
   2) долгое нажатие на иконку в iPhone открывало меню «Сохранить картинку» — touch-callout;
   3) Safari до сих пор понимает запрет выделения текста только с приставкой -webkit-.
   Поля ввода (ник, пароль, чат) — исключение: там выделять и вставлять текст нужно. */
html, body { overscroll-behavior: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.modal-box, #modal-content, #bpanel, #unitbar, #bottombar, .treewrap, #world-card { overscroll-behavior: contain; }
input, textarea, [contenteditable="true"] { -webkit-user-select: text; user-select: text; -webkit-touch-callout: default; }


/* ===== Скин интерфейса из картинок assets/ui/skin_*.png (9-slice через border-image) =====
   Классы sk-* ставит на <body> UI.applySkin(), когда файл найден; без файла остаётся стиль, нарисованный CSS выше.
   Числа после url() — граница нарезки в пикселях картинки (slice), после « / » — толщина рамки на экране.
   Панели: skin_panel 512x512 (рамка 78px) и skin_panel_dark 256x256 (рамка 40px); кнопки: skin_button* 384x256 (рамка 56px);
   плашки ресурсов/HUD: skin_hud 512x288 (рамка 40px). Размеры и промпты — assets/ui/README.txt. */
:root {
  /* Источники скина. UI.applySkin подменяет их на копии с вырезанным розовым фоном (data:URL);
     если пиксели прочитать нельзя (открыто файлом), остаются эти исходные файлы. */
  /* Картинки скина сюда кладёт UI.applySkin — уже очищенные от пурпурного фона.
     Раньше здесь по умолчанию стояли сами файлы assets/ui/skin_*.png, и если очистка почему-то
     не срабатывала, 9-slice растягивал их пурпурную кайму в фиолетовый контур вокруг кнопок
     и карточек. Пусто — значит рамки просто не будет, а не будет фиолетовой. */
  --sk-panel: none;
  --sk-panel-dark: none;
  --sk-button: none;
  --sk-button-red: none;
  --sk-button-green: none;
  --sk-button-steel: none;
  --sk-hud: none;
}
body.sk-panel .modal-box, body.sk-panel #bpanel, body.sk-panel #placebar {
  background: none; border-radius: 0; border: 26px solid transparent; padding: 4px 8px 10px;
  border-image: var(--sk-panel) var(--sk-panel-slice, 78) fill / 26px stretch; box-shadow: 0 12px 40px rgba(0,0,0,0.7); }
body.sk-panel #placebar { padding: 0 6px; }
body.sk-panel .modal-box .close { top: 12px; right: 14px; }

body.sk-dark .card, body.sk-dark .ucard, body.sk-dark .unit, body.sk-dark #tooltip, body.sk-dark #toast, body.sk-dark #hint, body.sk-dark #battle-hint, body.sk-dark .treehead {
  background: none; border-radius: 0; border: 12px solid transparent; padding: 2px 4px;
  border-image: var(--sk-panel-dark) var(--sk-panel-dark-slice, 40) fill / 12px stretch; }
body.sk-dark .card:hover { filter: brightness(1.15); }
body.sk-dark .ucard.sel { box-shadow: 0 0 0 3px var(--toxic), 0 0 14px var(--toxic); }
body.sk-dark .ucard.strike { box-shadow: 0 0 0 3px #ffe066; }
body.sk-dark .card.p-steam { box-shadow: 0 0 0 2px #8a5a2a; } body.sk-dark .card.p-diesel { box-shadow: 0 0 0 2px #4a5860; } body.sk-dark .card.p-cyber { box-shadow: 0 0 0 2px #167f8c; }
body.sk-dark .treehead { border-left-width: 12px; }

body.sk-btn .btn, body.sk-btn .bigbtn {
  background: none; border-radius: 0; border: 14px solid transparent; padding: 0 4px;
  border-image: var(--sk-button) var(--sk-button-slice, 34) fill / 14px stretch; box-shadow: 0 4px 6px rgba(0,0,0,0.45); }
body.sk-btn .btn { border-width: 11px; border-image-width: 11px; padding: 0 3px; }
body.sk-btn .btn.big { padding: 4px 10px; }
body.sk-btn .btn:active, body.sk-btn .bigbtn:active { transform: translateY(2px); box-shadow: 0 1px 2px rgba(0,0,0,0.45); }
body.sk-btn.sk-btn-red .btn.bad, body.sk-btn.sk-btn-red .bigbtn.attack { border-image-source: var(--sk-button-red); border-image-slice: var(--sk-button-red-slice, 34) fill; }
body.sk-btn.sk-btn-green .btn.ok { border-image-source: var(--sk-button-green); border-image-slice: var(--sk-button-green-slice, 34) fill; }
body.sk-btn.sk-btn-steel .btn.up, body.sk-btn.sk-btn-steel .btn.gem { border-image-source: var(--sk-button-steel); border-image-slice: var(--sk-button-steel-slice, 34) fill; }
body.sk-btn.sk-hud .tab.on, body.sk-btn.sk-hud .ptab.on { border-image-source: var(--sk-button); border-image-slice: var(--sk-button-slice, 34) fill; filter: none; opacity: 1; }

body.sk-hud .res, body.sk-hud .pill, body.sk-hud .bbox, body.sk-hud #b-airdrop, body.sk-hud .tab, body.sk-hud .ptab {
  background: none; border-radius: 0; border: 10px solid transparent; padding: 0 4px;
  border-image: var(--sk-hud) var(--sk-hud-slice, 40) fill / 10px stretch; box-shadow: 0 3px 4px rgba(0,0,0,0.4); }
body.sk-hud .tab.on, body.sk-hud .ptab.on { filter: brightness(1.3) saturate(1.2); opacity: 1; }

/* ===== Надстройки: зелья, перки, Альфа, кампания, убежище ===== */
.bigbtn { position: relative; }
.bigbtn .badge.trip { background: #2d6a8a; white-space: nowrap; }      /* «Карта»: отряд в пути — таймер */
.bigbtn .badge.arrived { background: #3f8a2d; }   /* отряд на месте */
.bigbtn .badge { position: absolute; top: -6px; right: -6px; min-width: 20px; height: 20px; border-radius: 10px; background: var(--red); border: 2px solid #2f1d0e; color: #fff; font-size: 11px; line-height: 16px; text-align: center; padding: 0 4px; }
#bottombar { flex-wrap: wrap; }
.btn.small { padding: 5px 8px; font-size: 12px; box-shadow: 0 2px 0 #2f1d0e; }
.btn.small .pic { width: 22px; height: 22px; object-fit: contain; }
.btn.ability { background: linear-gradient(#ff9a3c, #b5541a); border-color: #4a2008; font-size: 15px; }
.btn.ability.dis { filter: grayscale(.6) brightness(.75); }
/* Кнопка ульты: пока копится — полоска заряда прямо в кнопке, набралась — кнопка «дышит» */
.btn.ult { position: relative; overflow: hidden; background: linear-gradient(#3b3b46, #1c1c22); border-color: #0d0d10; font-size: 15px; }
.btn.ult .ultfill { position: absolute; left: 0; top: 0; bottom: 0; opacity: .85; transition: width .2s; pointer-events: none; box-shadow: 2px 0 6px rgba(0,0,0,0.5); }
/* .dis обесцвечивает кнопку целиком — полоска заряда от этого пропадала, поэтому у ульты свой «выключенный» вид */
.btn.ult.dis { filter: none; opacity: .92; }
/* Подпись на кнопке ульты — строго по центру кнопки, значок отдельно у левого края: раньше
   «значок + слово» стояли парой, и слово уезжало вправо от середины. */
.btn.ult .ulttxt { position: relative; display: flex; align-items: center; justify-content: center; width: 100%; }
.btn.ult .ulttxt .uiconimg, .btn.ult .ulttxt .remoji { position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 26px; height: 26px; object-fit: contain; }
.btn.ult.rdy { animation: ult-pulse 1.1s ease-in-out infinite; }
@keyframes ult-pulse { 0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.45); } }
/* Карточка ульты в окне орды */
.ultcard { display: flex; gap: 12px; align-items: flex-start; background: rgba(0,0,0,0.3); border: 2px solid var(--wood); border-radius: 12px; padding: 10px; }
.ultcard .uicon { font-size: 44px; line-height: 1; }
.ultcard .ubody { flex: 1; min-width: 0; }
.ultcard .uname { font-size: 16px; font-weight: 700; }
.ultcard .ulvl { display: flex; gap: 4px; margin: 6px 0; }
/* и восемь у ульты (было пять) */
.ultcard .ulvl i { width: 16px; height: 8px; border-radius: 3px; background: rgba(0,0,0,0.5); border: 1px solid var(--wood); }
.ultcard .ulvl i.on { background: var(--gold); }
@media (max-width: 560px) { .ultcard { flex-direction: column; align-items: center; text-align: center; } }
.ok-txt { color: var(--toxic); }
.ucard.spell { border-color: #6a4a8a; }
.ucard.hero { border-color: #ff8a3c; box-shadow: 0 0 10px rgba(255,138,60,0.5); }
.ucard.clan { border-color: #7fb7ff; }
.ucard.super { border-color: #c04a9a; }
.pic.spell, .pic.perkph, .pic.slotph { display: flex; align-items: center; justify-content: center; border-radius: 50%; border: 3px solid var(--wood); background: rgba(0,0,0,0.35); }
.pic.slotph { font-size: 28px; opacity: .5; width: 40px; height: 40px; }
.card.on { border-color: var(--toxic); box-shadow: 0 0 10px rgba(127,210,58,0.35); }
.card.perk.locked { opacity: .7; }
.card.perk .pbtns { display: flex; gap: 4px; flex-wrap: wrap; justify-content: center; margin-top: auto; padding-top: 4px; }   /* кнопки прижаты к низу: в ряду карточек — на одной линии (автопроверка вёрстки, отчёт 14-30) */
.perkcards { grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); }
/* на телефоне — по две в ряд: одной колонкой вкладка «Перки» была в семь экранов (5446 px) */
@media (max-width: 560px) { .cards.perkcards { grid-template-columns: repeat(auto-fill, minmax(135px, 1fr)); } }
.slots { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin: 8px 0 4px; }
.slot { display: flex; flex-direction: column; align-items: center; gap: 3px; width: 104px; padding: 8px 4px; border-radius: 12px; border: 3px dashed var(--wood); background: rgba(0,0,0,0.25); font-size: 11px; text-align: center; }
.slot.on { border-style: solid; border-color: var(--toxic); cursor: pointer; }
.slot b { font-size: 11px; line-height: 1.2; }
/* два ряда слотов перков: общий и обороны */
/* Слоты командира и слоты обороны — рядом: порознь они съедали пол-окна перков до первой карты */
.slotwrap { display: flex; flex-wrap: wrap; gap: 8px; }
.slotwrap > .slotrow { flex: 1 1 320px; margin: 6px 0 2px; }
.slotrow { margin: 6px 0 2px; padding: 6px 8px 4px; border-radius: 12px; background: rgba(0,0,0,0.18); }
.slotrow.def { background: rgba(60,110,160,0.16); }
.slotrow .slottitle { font-weight: bold; font-size: 13px; }
.slotrow .slots { margin: 6px 0 2px; }
.slotrow.def .slot.on { border-color: #7fb8ff; }
.card.perk.def.on { box-shadow: 0 0 0 2px rgba(127,184,255,0.55) inset; }
/* уровни перка: пять кружков */
.pips { display: inline-flex; gap: 3px; margin: 2px 0 3px; }
.pips i { width: 8px; height: 8px; border-radius: 50%; border: 1px solid var(--wood); background: rgba(0,0,0,0.35); display: inline-block; }
.pips i.on { background: var(--toxic); border-color: var(--toxic); box-shadow: 0 0 4px rgba(120,255,120,0.6); }
.herobox { display: flex; gap: 16px; align-items: flex-start; }
.herobox > .pic { width: 150px; height: 150px; object-fit: contain; flex: none; }
.herobox.locked > .pic { width: 84px; height: 84px; opacity: .8; }   /* героя ещё нет — картинка поменьше: на телефоне две закрытые карточки не влезали */
.herobox.locked { margin-bottom: 10px; }
.herobox > div { flex: 1; }
.herobox h3 { margin-top: 0; }
.missions { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); }
.card.mission { position: relative; padding-top: 16px; }
.card.mission .cname { padding: 0 12px; }
.card.mission .mnum { position: absolute; top: -8px; left: -8px; width: 28px; height: 28px; border-radius: 50%; background: var(--rust); border: 2px solid #2f1d0e; font-weight: 800; font-size: 13px; display: flex; align-items: center; justify-content: center; }
/* В деревянной рамке (толщина 12 px) кружок номера садился внутрь карточки и срезал первые буквы длинных названий:
   «Лочная смена», «лектроловушки» («Новичок», отчёт 17-47). Кружок меньше и лежит на углу рамки, текст — правее него. */
.card.mission .mnum { top: -12px; left: -12px; width: 22px; height: 22px; font-size: 11px; z-index: 1; }
.card.mission .stars { color: var(--gold); font-size: 16px; letter-spacing: 2px; }
.card.mission.done { border-color: var(--gold); }
/* «← Назад» и «В бой» — в одну строку: в .bbtns (колонка панели здания) они вставали друг под другом во всю ширину */
.mbtns { display: flex; gap: 10px; margin-top: 12px; align-items: stretch; }
.mbtns .btn { flex: 0 0 auto; }
.mbtns .btn.big { flex: 1 1 auto; width: auto; margin: 0; }
.story { font-style: italic; line-height: 1.45; background: rgba(0,0,0,0.25); border-left: 3px solid var(--rust2); padding: 8px 10px; border-radius: 6px; }
.resrow.claimed { opacity: .55; }
.emb { display: inline-block; font-size: 22px; vertical-align: middle; width: 28px; height: 28px; object-fit: contain; }
.embrow { display: flex; gap: 4px; flex-wrap: wrap; }
.embtn { padding: 4px 8px; }
.clans .pic.big { font-size: 40px; display: flex; align-items: center; justify-content: center; }
.mtable { width: 100%; border-collapse: collapse; font-size: 13px; margin: 8px 0; }
.mtable th { text-align: left; font-size: 11px; opacity: .7; padding: 4px 6px; border-bottom: 1px solid rgba(255,255,255,0.2); }
.mtable td { padding: 4px 6px; border-bottom: 1px dashed rgba(255,255,255,0.1); }
.mtable tr.me td { color: var(--gold); font-weight: 700; }
.reqrow { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px dashed rgba(255,255,255,0.1); font-size: 13px; }
.reqrow .reqbtns { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.reqrow .stars { color: var(--gold); letter-spacing: 1px; }
.warhead { background: rgba(0,0,0,0.3); border: 2px solid var(--wood); border-radius: 12px; padding: 10px 12px; margin: 8px 0; text-align: center; }
.warhead .big { font-size: 26px; color: var(--gold); font-weight: 800; }
.warhead.win { border-color: var(--toxic); } .warhead.lose { border-color: var(--red); }
.wargrid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
/* ход войны: строка боя — время, кто кого, итог, повтор; наши атаки — зелёная кромка, по нам — красная */
.warlogs { display: flex; flex-direction: column; gap: 4px; max-height: 320px; overflow-y: auto; }
.warlog { display: grid; grid-template-columns: 42px 1fr auto minmax(40px, auto); align-items: center; gap: 8px; padding: 4px 8px; min-height: 36px;
  background: rgba(0,0,0,0.25); border-left: 3px solid var(--toxic); border-radius: 6px; }
.warlog.theirs { border-left-color: var(--red); }
.warlog.live { opacity: 0.75; }
.warlog .wl-t { font-size: 12px; color: #a99; font-variant-numeric: tabular-nums; }
.warlog .wl-who { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.warlog .wl-res { white-space: nowrap; }
.warlog .btn.small { padding: 2px 0; min-width: 36px; min-height: 30px; line-height: 1; }
/* телефон: имена «кто → кого» не режем многоточием — переносим, а время прячем (порядок и так сверху вниз) */
@media (max-width: 520px) {
  .warlog { grid-template-columns: 1fr auto minmax(36px, auto); gap: 6px; padding: 4px 6px; }
  .warlog .wl-t { display: none; }
  .warlog .wl-who { white-space: normal; overflow: visible; font-size: 13px; line-height: 1.25; overflow-wrap: anywhere; }
}
.taskrow { display: flex; gap: 10px; align-items: center; padding: 6px 0; border-bottom: 1px dashed rgba(255,255,255,0.1); }
.taskrow .ticon { font-size: 26px; width: 36px; text-align: center; }
.taskrow .tbody { flex: 1; }
.capbar.small { height: 18px; margin: 4px 0; }
.capbar.small span { font-size: 11px; }
.chat { display: flex; flex-direction: column; gap: 4px; max-height: 50vh; overflow: auto; font-size: 13px; }
.chatrow { display: flex; gap: 8px; padding: 4px 6px; border-radius: 6px; background: rgba(0,0,0,0.2); }
.chatrow .when { opacity: .5; font-size: 11px; min-width: 40px; }
.chatrow b { min-width: 70px; }
.chatrow.sys { opacity: .8; font-style: italic; }
.chatrow.me b { color: var(--toxic); }
/* своё сообщение в ленту убежища и готовые фразы */
.chatform { display: flex; gap: 6px; margin: 4px 0 6px; }
.chatform input { flex: 1 1 auto; min-width: 0; padding: 8px 10px; border-radius: 8px; border: 2px solid var(--wood2); background: rgba(0,0,0,0.35); color: var(--bone); font: inherit; }
.chatform .btn { flex: 0 0 auto; }
/* готовые фразы — лёгкие «пилюли», на кнопке коротко (полная фраза — в подсказке и в ленте): большими кнопками
   они в три ряда съедали пол-окна над лентой на телефоне */
.chatquick { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 4px; }
.chatquick .qchip { min-height: 30px; padding: 4px 10px; border-radius: 15px; border: 2px solid var(--wood2); background: rgba(0,0,0,0.35); color: var(--bone); font-size: 12px; font-weight: 700; white-space: nowrap; }
.chatquick .qchip:hover { border-color: var(--rust2); }
.chatquick .qchip:active { transform: translateY(1px); }
@media (max-width: 560px) { .tabs.sub.chatfil { gap: 4px; } .tabs.sub.chatfil .tab { padding: 5px 5px; } }   /* фильтр ленты — в один ряд на 400 px */
.chatrow span:last-child { overflow-wrap: anywhere; }
@media (max-width: 720px) { .wargrid { grid-template-columns: 1fr; } .herobox { flex-direction: column; align-items: center; } }

.treewrap { cursor: grab; user-select: none; touch-action: pan-x pan-y; }
.treewrap.dragging { cursor: grabbing; }
.treewrap.dragging .tnode { pointer-events: none; }

/* ===== Живые кнопки: отклик на наведение и нажатие ===== */
.bigbtn { transition: transform .12s ease, box-shadow .12s ease, filter .12s ease; }
/* Наведение НЕ двигает кнопку. Раньше она уезжала вверх на 3 px и подрастала — курсор оказывался
   за её краем, наведение слетало, кнопка возвращалась: получалось дрожание, а нажатие между
   mousedown и mouseup иногда проваливалось мимо. Теперь подсветка и тень, а движение — только при нажатии. */
.bigbtn:hover { filter: brightness(1.12); box-shadow: 0 5px 0 #2f1d0e, 0 10px 16px rgba(0,0,0,0.55); }
.bigbtn:hover .ico { animation: ico-bounce .5s ease; }
.bigbtn:active { transform: translateY(2px) scale(.97); filter: brightness(.95); box-shadow: 0 1px 0 #2f1d0e; transition-duration: .05s; }
.bigbtn .ico { display: inline-flex; align-items: center; justify-content: center; height: 30px; line-height: 1; }
/* Значок большой кнопки — только картинка ui/btn_<имя>.png. Пока её нет, span пустой:
   эмодзи вместо иконки выглядит дёшево, поэтому лучше просто подпись. */
.bigbtn .ico:empty { display: none; }
.bigbtn .bico { width: 32px; height: 32px; object-fit: contain; filter: drop-shadow(0 2px 0 rgba(0,0,0,0.5)); }
.bigbtn.attack { animation: attack-glow 2.6s ease-in-out infinite; }
.bigbtn.attack:hover { animation: none; }
@keyframes ico-bounce { 0% { transform: scale(1) rotate(0); } 30% { transform: scale(1.25) rotate(-8deg); } 60% { transform: scale(.95) rotate(6deg); } 100% { transform: scale(1) rotate(0); } }
@keyframes attack-glow { 0%, 100% { box-shadow: 0 4px 0 #2f1d0e, 0 6px 10px rgba(0,0,0,0.5); } 50% { box-shadow: 0 4px 0 #2f1d0e, 0 6px 18px rgba(217,68,47,0.75); } }
.btn { transition: transform .1s ease, filter .1s ease, box-shadow .1s ease; }
.btn:not(.dis):hover { filter: brightness(1.1); box-shadow: 0 3px 0 #2f1d0e, 0 0 10px rgba(255,220,150,0.25); }
.btn:not(.dis):active { transform: translateY(2px); box-shadow: 0 1px 0 #2f1d0e; transition-duration: .04s; }
.tab { transition: transform .1s ease, filter .1s ease; }
.tab:hover { filter: brightness(1.15); }
.ucard { transition: transform .1s ease, box-shadow .1s ease; }
.ucard:hover:not(.dis) { filter: brightness(1.12); }
.ucard:not(.dis):active { transform: scale(.97); }
.ucard:active:not(.dis) { transform: translateY(1px) scale(.97); }
.card { transition: transform .1s ease, border-color .1s ease, box-shadow .1s ease; }
.card:not(.dis):active { transform: translateY(1px) scale(.98); }
.badge { animation: badge-pop .4s ease; }
@keyframes badge-pop { 0% { transform: scale(0); } 70% { transform: scale(1.3); } 100% { transform: scale(1); } }


/* ---------- колесо разведки ----------
   Сектора — доли из WORLD.SCOUT_WHEEL, цвет — от богатства места. Крутится обычным поворотом,
   исход к этому моменту уже разыгран (World.scoutSpin): анимация ничего не решает. */
.wheelbox { position: relative; width: 160px; height: 160px; margin: 8px auto 4px; }   /* было 190: окно «Разведка» не влезало на 1280×800 (+4 %) */
.wheel { width: 100%; height: 100%; border-radius: 50%; border: 4px solid var(--wood2);
  background: conic-gradient(var(--stops)); box-shadow: 0 6px 18px rgba(0,0,0,.55), inset 0 0 22px rgba(0,0,0,.45); }
.wheel-pin { position: absolute; left: 50%; top: -6px; width: 0; height: 0; transform: translateX(-50%);
  border-left: 11px solid transparent; border-right: 11px solid transparent; border-top: 18px solid var(--gold);
  filter: drop-shadow(0 2px 2px rgba(0,0,0,.6)); }
.scout-res { text-align: center; font-size: 15px; min-height: 22px; margin-bottom: 8px; }
.wline .wdot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: var(--dc); margin-right: 6px; vertical-align: -1px; }
/* Колесо слева, шансы справа: столбиком окно на 1280×800 не влезало и после уменьшения колеса (706 из 670 px,
   отчёт 20-41). Столбиком — только на совсем узком экране. */
.scoutgrid { display: flex; gap: 12px; align-items: center; }
.scoutgrid .scoutwh { flex: 0 0 150px; min-width: 0; }
.scoutgrid .wheelbox { width: 140px; height: 140px; }
.scoutgrid .scout-res { font-size: 13px; margin-bottom: 0; }
.scoutgrid .scoutodds { flex: 1 1 auto; min-width: 0; }
@media (max-width: 360px) { .scoutgrid { flex-direction: column; align-items: stretch; } .scoutgrid .scoutwh { flex-basis: auto; } }

/* ---------- отдача от нажатия ----------
   Часть кнопок игры — не .btn, а свои элементы (вкладки, ячейки, значки на карте, крестик).
   Раньше они никак не отзывались на нажатие: непонятно, попал ты по ней или нет, особенно пальцем.
   Теперь любая нажимаемая штука на миг «вдавливается», а на телефоне не подсвечивается синим. */
.tab:active, .ptab:active, .wact:active, .wclose:active, .argbtn:active, .bigbtn .ico { -webkit-tap-highlight-color: transparent; }
.tab:active, .ptab:active { transform: translateY(1px) scale(.98); filter: brightness(1.15); }
.wact:active, .wclose:active { transform: scale(.96); filter: brightness(1.12); }
.card.savebak .btn:active { transform: translateY(2px); }
/* нажимаемое не должно выделяться как текст: двойной тап на телефоне выделял подписи кнопок */
.btn, .bigbtn, .tab, .ptab, .card, .ucard, .tnode, .wact, .close, .wclose { user-select: none; -webkit-user-select: none; touch-action: manipulation; }

@media (prefers-reduced-motion: reduce) { .bigbtn, .btn, .tab, .ucard, .card, .bigbtn .ico, .bigbtn.attack { animation: none !important; transition: none !important; } }

/* ---------- мастерская (v0.9) ---------- */
.cqueue { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.cq { display: flex; align-items: center; gap: 8px; background: rgba(0,0,0,0.3); border-radius: 10px; padding: 6px 8px; }
.cq .cqpic { width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; flex: none; }
.cq .cqpic img { width: 36px; height: 36px; object-fit: contain; }
.cq .cqbody { flex: 1; min-width: 0; font-size: 13px; }
.cq .cqbody .capbar { margin: 4px 0 0; }
.card.rcp .pic.big { display: flex; align-items: center; justify-content: center; }
.card.rcp .pic.big img { width: 54px; height: 54px; object-fit: contain; }
.card.rcp.locked { filter: grayscale(.6); }
.card .cout { font-size: 13px; font-weight: 700; color: var(--toxic); display: flex; gap: 4px; align-items: center; flex-wrap: wrap; justify-content: center; }
.argrow { display: flex; gap: 4px; flex-wrap: wrap; justify-content: center; margin: 2px 0; }
.cards.rcps { align-items: start; }
.argbtn { display: flex; flex-direction: column; align-items: center; padding: 3px 5px; min-width: 40px; }
.argbtn .pic, .argbtn img { width: 28px; height: 28px; object-fit: contain; }
.argbtn small { font-size: 10px; opacity: .8; }
/* карточка копии сохранения в окне восстановления.
   Класс НЕ .slot: так уже называются ячейки перков и зелий, и у них жёсткая ширина 104px —
   из-за совпадения имён карточка ужималась в столбик, а кнопка налезала на текст. */
.card.savebak { width: 100%; flex-direction: row; align-items: center; text-align: left; gap: 10px; padding: 10px; cursor: default; }
.card.savebak:hover { transform: none; border-color: var(--wood); }
.card.savebak .mbody { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.card.savebak .zstats { font-size: 12px; opacity: .9; }
.card.savebak .btn { flex: 0 0 auto; }
.baklist { display: flex; flex-direction: column; gap: 8px; margin: 10px 0; }
/* список «что ты должен знать до высадки»: разведки нет, орда идёт как есть, точка сгорает */
.warnlist { margin: 10px 0; padding: 0 0 0 4px; list-style: none; display: flex; flex-direction: column; gap: 8px; }
.warnlist li { display: flex; gap: 8px; align-items: flex-start; font-size: 13px; line-height: 1.35; }
/* значок слева, весь текст одной колонкой справа — иначе предупреждение про загон уезжало вбок */
.warnlist li > span.wtxt { flex: 1 1 auto; min-width: 0; }
.warnlist .bad-txt { display: block; margin-top: 3px; }
.chk { display: flex; align-items: center; gap: 8px; margin: 8px 0; font-size: 14px; cursor: pointer; }
.chk input { width: 18px; height: 18px; accent-color: var(--toxic); }

/* ---------- оживление v0.9.1 ---------- */
/* звезда в бою: коробка подпрыгивает, звёзды вспыхивают */
@keyframes starpop { 0% { transform: scale(1); } 30% { transform: scale(1.35) rotate(-4deg); } 55% { transform: scale(0.92) rotate(2deg); } 100% { transform: scale(1); } }
@keyframes starglow { 0% { text-shadow: 0 0 0 #ffe066; color: #fff; } 40% { text-shadow: 0 0 14px #ffe066, 0 0 30px #ffb300; color: #fff6c0; } 100% { text-shadow: none; } }
.bbox.pop { animation: starpop .55s cubic-bezier(.2,1.4,.4,1); }
.bbox.pop b { animation: starglow .8s ease-out; }
/* значок ресурса летит в счётчик; сам счётчик подпрыгивает */
.flyres { position: fixed; left: 0; top: 0; width: 28px; height: 28px; object-fit: contain; pointer-events: none; z-index: 60; font-size: 22px; line-height: 28px; text-align: center; filter: drop-shadow(0 2px 2px rgba(0,0,0,0.5)); will-change: transform; }
@keyframes resbump { 0% { transform: scale(1); } 35% { transform: scale(1.12); box-shadow: 0 0 14px rgba(255,230,128,0.8), 0 3px 0 rgba(0,0,0,0.4); } 100% { transform: scale(1); } }
.res.bump { animation: resbump .45s cubic-bezier(.2,1.4,.4,1); }
/* окна: влетают с лёгким пружинным увеличением, схлопываются при закрытии */
@keyframes modalin { 0% { transform: scale(.88) translateY(14px); opacity: 0; } 60% { transform: scale(1.02) translateY(-2px); opacity: 1; } 100% { transform: scale(1) translateY(0); opacity: 1; } }
@keyframes modalbg { from { opacity: 0; } to { opacity: 1; } }
@keyframes modalout { from { transform: scale(1); opacity: 1; } to { transform: scale(.92) translateY(8px); opacity: 0; } }
#modal:not(.hidden) { animation: modalbg .18s ease-out; }
.modal-box.enter { animation: modalin .26s cubic-bezier(.2,1.2,.4,1); }
#modal.closing { animation: none; pointer-events: none; }
#modal.closing .modal-box { animation: modalout .14s ease-in forwards; }
/* тост выезжает снизу с подскоком */
#toast { transition: opacity .18s, transform .28s cubic-bezier(.2,1.4,.4,1); }
/* цифры ресурсов: докручиваются (JS) и подсвечиваются при росте */
.rnum b.up { color: #d8ff9a; text-shadow: 0 0 8px rgba(127,210,58,0.6); }
.rnum b { transition: color .35s, text-shadow .35s; }
/* готовая стройка / свободный рабочий: пилюля рабочих мигает */
@keyframes pillpulse { 0%,100% { box-shadow: 0 3px 0 rgba(0,0,0,0.4); } 50% { box-shadow: 0 0 14px 3px rgba(127,210,58,0.75), 0 3px 0 rgba(0,0,0,0.4); } }
.pill.free { animation: pillpulse 1.6s ease-in-out infinite; }
/* крупный значок в карточке (рюкзак, рецепты, модули): по центру плитки */
.card .pic.big { display: flex; align-items: center; justify-content: center; }

/* ---------- боевой пропуск ---------- */
.res .rate.neg { color: #ff8a6a; }
/* убежище: уровень, вклад, журнал, цели */
.clanlevel { padding: 8px 10px; border-radius: 12px; background: rgba(0,0,0,0.2); margin-bottom: 8px; }
.lvrow { display: flex; gap: 6px; margin: 4px 0; }
.lvchip { width: 26px; height: 26px; border-radius: 50%; border: 2px solid var(--wood); display: inline-flex; align-items: center; justify-content: center; font-weight: 800; font-size: 12px; background: rgba(0,0,0,0.3); }
.lvchip.on { border-color: var(--toxic); color: var(--toxic); } .lvchip.done { border-color: var(--moss2); opacity: .8; }
.howgrid { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: 12px; margin: 4px 0; align-items: center; }
.howgrid .how { white-space: nowrap; }
.ledger { display: flex; flex-direction: column; gap: 2px; font-size: 12px; }
.ledrow { display: flex; gap: 8px; align-items: center; padding: 3px 6px; border-radius: 6px; background: rgba(0,0,0,0.18); }
.ledrow .when { opacity: .5; font-size: 11px; min-width: 40px; } .ledrow span:nth-child(2) { flex: 1; } .ledrow.give b { color: var(--toxic); } .ledrow.get b { color: var(--gold); }
.goalbox { padding: 8px 10px; border-radius: 12px; background: rgba(60,110,160,0.14); border: 1px solid rgba(127,184,255,0.35); margin-bottom: 8px; }
.goalbox .chest { white-space: nowrap; margin-right: 6px; }
.capbar.mine .fillm { position: absolute; left: 0; top: 0; bottom: 0; background: rgba(255,224,102,0.55); }
.taskrow.goal .tbody b { display: inline; }
.gold-txt { color: var(--gold); }
.reqbtns.left { justify-content: flex-start; display: flex; gap: 8px; flex-wrap: wrap; margin: 4px 0; }
.reqbtns .btn .pic { width: 22px; height: 22px; vertical-align: middle; }
.tabbadge { display: inline-block; min-width: 16px; padding: 0 4px; border-radius: 8px; background: var(--red); color: #fff; font-size: 10px; line-height: 16px; margin-left: 2px; }
.hqreq { margin: 6px 0 2px; padding: 6px 8px; border-radius: 10px; background: rgba(0,0,0,0.2); }
.reqlist { display: flex; flex-wrap: wrap; gap: 4px 8px; margin-top: 4px; font-size: 11px; }
.req.ok { color: var(--toxic); } .req.no { color: #ff9a7a; cursor: pointer; text-decoration: underline dotted; }   /* нажми — поставить */
.req.wait { color: var(--gold); cursor: pointer; }   /* уже строится — засчитается, когда достроится */
.tab.lock { opacity: .72; }   /* вкладка, где пока всё закрыто (нет здания, мал штаб) */
/* Поставки под штаб (1.60): текущий этап выделен, остальные — приглушены; под списком полоска
   завоза и кнопка. Узкий экран: кнопка на всю ширину, чтобы в неё попадали пальцем. */
.req.now { color: var(--bone); font-weight: 700; }
.req.wait { opacity: .55; }
.hqsupply .supplybar { position: relative; height: 8px; margin: 6px 0 6px; border-radius: 5px; background: rgba(0,0,0,0.35); overflow: hidden; }
.hqsupply .supplybar i { position: absolute; left: 0; top: 0; bottom: 0; background: linear-gradient(90deg, var(--toxic), #b7e07a); border-radius: 5px; }
/* бледная часть — куда завоз доедет, если нажать кнопку с текущим положением ползунка */
.hqsupply .supplybar i.plan { background: rgba(183,224,122,.32); }
/* строка «ползунок + кнопка»: на узком экране кнопка уезжает под ползунок сама */
.hqsupply .supplyrow { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.hqsupply .supplyrow .btn.mini { flex: 1 1 130px; padding: 5px 8px; font-size: 12px; }
.hqsupply .supplyslider { flex: 1 1 100%; width: 100%; height: 22px; margin: 0; -webkit-appearance: none; appearance: none; background: none; }
.hqsupply .supplyslider::-webkit-slider-runnable-track { height: 6px; border-radius: 4px; background: rgba(0,0,0,.4); border: 1px solid rgba(0,0,0,.5); }
.hqsupply .supplyslider::-moz-range-track { height: 6px; border-radius: 4px; background: rgba(0,0,0,.4); border: 1px solid rgba(0,0,0,.5); }
.hqsupply .supplyslider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 20px; height: 20px; margin-top: -8px;
  border-radius: 50%; background: radial-gradient(circle at 35% 30%, #d8f0a8, var(--toxic)); border: 2px solid #1b2609; box-shadow: 0 1px 3px rgba(0,0,0,.5); cursor: pointer; }
.hqsupply .supplyslider::-moz-range-thumb { width: 20px; height: 20px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #d8f0a8, var(--toxic)); border: 2px solid #1b2609; box-shadow: 0 1px 3px rgba(0,0,0,.5); cursor: pointer; }
.raidcard .rares { display: flex; flex-wrap: wrap; gap: 4px 8px; justify-content: center; }
.raidcard .rare { white-space: nowrap; display: inline-flex; align-items: center; gap: 2px; }
.upkeep { margin: -4px 0 6px; }
.hordeline { display: flex; gap: 6px 14px; align-items: center; flex-wrap: wrap; margin-bottom: 6px; }   /* загон + кормёжка + цена одной полосой */
.hordeline > .armyrow { margin: 0; }
.hordemeta { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1 1 200px; }   /* сжимается и встаёт рядом с карточками, а не уезжает под них */
.hordemeta .upkeep, .hordemeta .armycost, .hordemeta .queue { margin: 0; }
.hordemeta .queue .qclear { margin-left: 4px; }
#pass-info { position: relative; cursor: pointer; display: flex; align-items: center; gap: 6px; }
#pass-info .ppb { display: inline-block; width: 42px; height: 8px; border-radius: 4px; background: rgba(0,0,0,0.45); border: 1px solid var(--wood); overflow: hidden; }
#pass-info .ppb b { display: block; height: 100%; background: var(--toxic); }
#pass-info.gold { border-color: #e8b83a; box-shadow: 0 3px 0 rgba(0,0,0,0.4), 0 0 10px rgba(232,184,58,0.45); }
#pass-info.gold .ppb b { background: linear-gradient(#ffd66b, #e0a020); }
#pass-info.has-badge { padding-right: 18px; }
#pass-info .badge { position: absolute; top: -8px; right: -8px; min-width: 18px; height: 18px; border-radius: 9px; background: var(--red); border: 2px solid #2f1d0e; color: #fff; font-size: 10px; line-height: 14px; text-align: center; padding: 0 4px; }
.passhead { display: flex; gap: 12px; align-items: center; padding: 8px 10px; border-radius: 12px; background: rgba(0,0,0,0.22); margin: 8px 0; flex-wrap: wrap; }
.passhead.gold { background: linear-gradient(90deg, rgba(232,184,58,0.18), rgba(0,0,0,0.22)); }
.passhead .ptier { text-align: center; min-width: 64px; }
.passhead .pnum { font-size: 34px; font-weight: 900; line-height: 1; color: var(--toxic); text-shadow: 0 2px 0 #000; }
.passhead.gold .pnum { color: #ffd66b; }
.passhead .pbar { flex: 1; min-width: 200px; }
.passhead .pbar .capbar { margin-bottom: 4px; }
.passhead .pbuy { display: flex; flex-direction: column; gap: 10px; }
.goldbox { padding: 8px 10px; border-radius: 12px; border: 2px solid #b08a2a; background: linear-gradient(135deg, rgba(232,184,58,0.16), rgba(0,0,0,0.25)); margin: 6px 0 10px; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.goldbox.on { border-color: #ffd66b; }
.goldbox .gtitle { font-weight: 900; font-size: 15px; color: #ffd66b; }
.goldbox .small { flex: 1; min-width: 200px; }
/* Телефон: кнопка «Купить» — в строку с заголовком, описание ниже. Отдельной строкой кнопка добавляла ~50 px, и окно
   пропуска на 400 px «чуть-чуть не влезало» (автопроверка: видно 714 из 739 px, отчёт 17-25). */
@media (max-width: 700px) { .goldbox .gtitle { flex: 1 1 auto; } .goldbox .small { order: 2; flex-basis: 100%; } }
.btn.gold { background: linear-gradient(#ffd66b, #c08a1a); color: #2a1a05; text-shadow: none; }
.ptrackwrap { display: flex; gap: 6px; align-items: flex-start; }
.plabels { display: flex; flex-direction: column; gap: 6px; flex: none; }
.plabels .plab { height: 66px; display: flex; align-items: center; font-size: 11px; font-weight: 800; writing-mode: vertical-rl; transform: rotate(180deg); opacity: .8; }
.plabels .plab.gold { color: #ffd66b; }
.ptrack { display: flex; gap: 6px; overflow-x: auto; padding: 4px 2px 10px; flex: 1; scroll-snap-type: x proximity; }
.pcol { flex: none; width: 92px; display: flex; flex-direction: column; gap: 6px; scroll-snap-align: start; opacity: .85; }
.pcol.reached { opacity: 1; }
.pcol.next .pnum2 { color: var(--toxic); }
.pnum2 { text-align: center; font-weight: 900; font-size: 13px; height: 18px; line-height: 18px; }
.pcell { position: relative; height: 66px; border-radius: 10px; border: 2px solid var(--wood); background: rgba(0,0,0,0.3); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 11px; }
.pcell .pri { display: flex; align-items: center; gap: 3px; line-height: 1; }
.pcell .pri img, .pcell .pri .ck { width: 18px; height: 18px; }
.pcell.gold { border-color: #8a6a1a; background: rgba(120,90,20,0.25); }
.pcell.reached { border-color: var(--wood2); }
.pcell.can { border-color: var(--toxic); cursor: pointer; box-shadow: 0 0 8px rgba(127,210,58,0.55); animation: pillpulse 1.6s ease-in-out infinite; }
.pcell.gold.can { border-color: #ffd66b; box-shadow: 0 0 8px rgba(255,214,107,0.6); }
.pcell.claimed { opacity: .55; }
.pcell.locked { opacity: .6; }
.pcell .pmark { position: absolute; right: 3px; top: 1px; font-size: 12px; }
/* одна дорожка (только золото, 23.09): ячейки выше — наград в ячейке бывает три строки; 30-й уровень — рабочий */
.ptrackwrap.one .pcell, .ptrackwrap.one .plabels .plab { height: 84px; }
.pcell .pri.pworker { flex-direction: column; font-size: 22px; gap: 0; }
.pcell .pri.pworker small { font-size: 11px; font-weight: 800; color: #ffd66b; }
.taskrow.done { opacity: .7; }
.taskrow .tpts { font-weight: 800; white-space: nowrap; font-size: 13px; }
@media (max-width: 700px) {
  #pass-info .ppb { display: none; }
  .passhead .pnum { font-size: 26px; }
  .pcol { width: 78px; }
}

/* ===================== КАРТА ОБЛАСТИ =====================
   Свой экран поверх деревни: канвас на всю площадь, шапка сверху, карточка точки снизу.
   Карточка на телефоне прижата к низу и не выше половины экрана, чтобы саму карту было видно. */
#worldscr { position: fixed; inset: 0; z-index: 40; background: #0d100c; overflow: hidden; }   /* прилетающая карточка не должна давать полосу прокрутки */
#worldscr.hidden { display: none; }
#world-canvas { position: absolute; inset: 0; width: 100%; height: 100%; touch-action: none; cursor: pointer; }
#world-top {
  position: absolute; left: 8px; right: 8px; top: 8px; padding: 8px 10px; border-radius: 10px;
  background: rgba(16, 20, 15, 0.82); border: 1px solid #2c3427; backdrop-filter: blur(3px);
  display: flex; flex-direction: column; gap: 6px; pointer-events: auto;
}
#world-top .wrow { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
#world-top .wbtns .btn { padding: 5px 10px; font-size: 13px; }
.wlegend { display: flex; align-items: center; gap: 6px; margin-left: auto; font-size: 12px; color: #b9b8ac; }
.wlegend .wdot { width: 11px; height: 11px; border-radius: 50%; border: 2px solid var(--dc); display: inline-block; margin-left: 8px; }
#world-close { position: absolute; left: 10px; bottom: 10px; z-index: 2; }
#world-card {
  position: absolute; right: 10px; bottom: 10px; width: min(360px, calc(100% - 20px));
  max-height: 62vh; overflow: auto; padding: 10px 12px; border-radius: 12px;
  background: rgba(16, 20, 15, 0.94); border: 1px solid #38402f; box-shadow: 0 8px 24px rgba(0,0,0,0.5);
}
#world-card.hidden { display: none; }
#world-card .wtitle { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
#world-card .wicon {
  width: 38px; height: 38px; border-radius: 50%; flex: 0 0 38px; display: grid; place-items: center;
  font-size: 20px; background: #1b2018; border: 3px solid var(--dc);
}
#world-card .wclose { margin-left: auto; background: none; border: 0; font-size: 0; color: transparent; cursor: pointer; padding: 0; position: relative; width: 24px; height: 24px; }
#world-card .wclose::before, #world-card .wclose::after { content: ''; position: absolute; left: 50%; top: 50%; width: 14px; height: 2.5px; border-radius: 2px; background: #9a9a90; }
#world-card .wclose::before { transform: translate(-50%, -50%) rotate(45deg); }
#world-card .wclose::after { transform: translate(-50%, -50%) rotate(-45deg); }
#world-card .wclose:hover::before, #world-card .wclose:hover::after { background: #e8e6da; }
/* строка «подпись — значение»: в карточке точки на карте и в окне предупреждения перед высадкой */
#world-card .wline, .modal-box .wline { display: flex; justify-content: space-between; gap: 10px; padding: 3px 0; border-bottom: 1px solid #232a1f; font-size: 13px; }
#world-card .wline b, .modal-box .wline b { color: #e6e4d6; text-align: right; }
.modal-box .wline .stars { color: var(--gold); letter-spacing: 1px; margin-left: 4px; }   /* окно «Завершить бой?» */
.modal-box .endwhy { margin: -4px 0 8px; padding-right: 44px; }   /* почему кончился бой — под заголовком итогов; справа — место крестику окна */
.modal-box .muted.small + .endwhy { margin-top: 2px; }   /* в кампании — под названием миссии: с −4 px строки налезали друг на друга */
/* итоги боя: «Оживить» и «Вырастить заново» — рядом; после оживления на месте первой встаёт «Новый бой» */
.revrow { display: flex; gap: 8px; flex-wrap: wrap; margin: 6px 0 2px; }
.revrow .btn { flex: 1 1 150px; margin: 0; }
.modal-box .lstarsrow { text-align: right; margin: -2px 0 4px; }
.hordemeta .armygo { align-self: flex-start; margin-top: 2px; }
#world-card .wbtns { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
#world-card .wbtns .btn { flex: 1 1 auto; }
/* Событие в дороге: значок, название и во что обошлось */
#world-card .wroad { padding: 5px 0 5px 8px; border-left: 2px solid #3a4430; margin: 4px 0; font-size: 13px; }
#world-card .wroad .bad-txt { color: #e8676c; }
#world-card .wroad .ok-txt { color: #8fd36a; }

/* Две кнопки под картой раньше выглядели одинаково, и было не понять, что делает какая.
   Теперь у каждой свой значок, свой цвет и вторая строка «что это даёт». */
/* Кнопка разведки на карте: подпись по центру и цена читаемым размером. Была прижата влево,
   а цена написана мелким серым по тёмному — цифры не читались вовсе. */
#world-top .wbtns .btn.wact, #world-top .wact {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  text-align: center; line-height: 1.25; padding: 8px 18px; min-width: 140px; min-height: 52px;
}
#world-top .wact .wico { font-size: 18px; flex: 0 0 auto; }
#world-top .wact b { display: block; font-size: 14px; }
#world-top .wact small { display: flex; align-items: center; justify-content: center; gap: 4px;
  font-size: 13px; color: #f0ead6; font-weight: 700; }
#world-top .wact small .ricon { width: 18px; height: 18px; }
#world-top .wact:disabled { opacity: 0.5; }
#world-top .wact.full { opacity: 0.6; }   /* разведка при полной карте: открыть можно (там объяснение), отправить — нет */
body.inworld #bottombar, body.inworld #topbar, body.inworld #bpanel, body.inworld #hint { display: none; }
@media (max-width: 700px) {
  #world-card { left: 8px; right: 8px; width: auto; bottom: 56px; max-height: 52vh; }
  #world-close { right: 10px; left: 10px; }
  .wlegend { margin-left: 0; }
}

/* ===================== ДОСКА ЗАДАНИЙ =====================
   Карточка-просьба: имя жителя, его слова, шаги и награда. Взятое задание подсвечено, готовое
   к сдаче — тёплой рамкой, чтобы его было видно сразу при открытии доски. */
.cards.quests { display: flex; flex-direction: column; gap: 10px; }   /* .cards — сетка; доске нужна колонка */
/* На широком экране — две колонки: доска из пяти-шести просьб была длиной в три экрана (684 из 2066 px) */
@media (min-width: 760px) {
  .cards.quests { display: block; columns: 2; column-gap: 10px; }   /* колонки, а не сетка: короткая карточка не оставляет дыру под собой */
  .cards.quests > .card.quest { break-inside: avoid; margin-bottom: 10px; }
}
.card.quest.locked { opacity: .82; }
.card.quest.locked .cerr { margin-top: 6px; }
.card.quest { width: 100%; max-width: none; text-align: left; align-items: stretch; cursor: default; padding: 10px 12px; }
.card.quest.on { border-color: #4a6b3a; }
.card.quest.ready { border-color: #c8a13c; box-shadow: 0 0 0 1px rgba(200,161,60,0.35) inset; }
.card.quest .qhead { display: flex; align-items: baseline; gap: 8px; justify-content: space-between; }
.card.quest .qhead b { font-size: 16px; }
.card.quest:hover { transform: none; border-color: var(--wood); }
.card.quest.ready:hover { border-color: #c8a13c; }
.card.quest .qtext { font-size: 13px; color: #c9c6b6; margin: 6px 0 8px; line-height: 1.45; font-style: italic; }
.card.quest .qsteps { display: flex; flex-direction: column; gap: 3px; }
.card.quest .qstep { font-size: 13px; color: #9a998e; }
.card.quest .qstep.cur { color: #e6e4d6; }
.card.quest .qstep.done { color: #7fb45a; text-decoration: line-through; }
.card.quest .qrew { margin-top: 8px; font-size: 13px; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.card.quest .qbtns { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.card.quest .qchoice { margin-top: 10px; border-top: 1px solid #2b3226; padding-top: 8px; }
.card.quest .qask { font-size: 13px; color: #d8d5c4; margin-bottom: 8px; }
.card.quest .qopt { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%; margin-bottom: 6px; text-align: left; }
.card.quest .qopt small { color: #b9d38a; font-size: 12px; }

/* ---- доска: сцена главы, лицо жителя, печать ----
   Картинка сцены медленно наезжает (ken burns), лицо — кружок с бумажной подложкой, у готового
   задания печать «выполнено» падает с поворотом. Всё это работает и без картинок: вместо сцены
   просто нет шапки, вместо лица — инициал на бумаге. */
.card.quest .qart { position: relative; height: 76px; margin: -10px -12px 8px; overflow: hidden; border-radius: 10px 10px 0 0; }   /* было 108: доска листалась на три экрана */
.card.quest .qart .qcap { display: none; }   /* название и так стоит строкой ниже, рядом с лицом жителя */
.card.quest .qart img { width: 100%; height: 100%; object-fit: cover; display: block; animation: qkb 18s ease-in-out infinite alternate; }
.card.quest .qart .qfade { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(10,12,9,0) 40%, rgba(16,19,14,0.95) 100%); }
.card.quest .qart .qcap { position: absolute; left: 10px; bottom: 6px; font-weight: 700; font-size: 15px; color: #efe9d4; text-shadow: 0 2px 4px rgba(0,0,0,0.8); }
/* Окно сдачи задания: шапка-картинка 160 px. Правила выше привязаны к .card.quest, и здесь у рамки не было ни
   position, ни overflow: картинка вылезала на всю высоту окна под текст, окно листалось впустую (автопроверка
   «Фотоальбом: видно 446 из 580 px», отчёт 17-25). */
.qart.big { position: relative; height: 160px; margin: 0 0 10px; border-radius: 10px; overflow: hidden; }
.qart.big img { width: 100%; height: 100%; object-fit: cover; display: block; animation: qkb 24s ease-in-out infinite alternate; }
.qart.big .qfade { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(10,12,9,0) 40%, rgba(16,19,14,0.95) 100%); }
@keyframes qkb { from { transform: scale(1.02) translateY(0); } to { transform: scale(1.12) translateY(-4px); } }
.card.quest .qface { width: 38px; height: 38px; flex: 0 0 38px; border-radius: 50%; object-fit: cover; border: 2px solid var(--wood); }
.card.quest .qface.ph { display: grid; place-items: center; background: #d9cba6; color: #4a3c26; font-weight: 700; font-size: 17px; }
.card.quest .qwho { flex: 1 1 auto; min-width: 0; }
.card.quest.small { opacity: 0.97; }
.card.quest.small .qtext { font-style: normal; }
.qstamp { color: #c8a13c; border: 2px solid #c8a13c; border-radius: 6px; padding: 1px 6px; font-size: 11px; text-transform: uppercase; transform: rotate(-6deg); }
.qdone { text-align: center; }
.qdone .qseal {
  display: inline-block; margin: 4px 0 8px; padding: 4px 14px; font-size: 15px; text-transform: uppercase;
  color: #d86a3c; border: 3px solid #d86a3c; border-radius: 8px; opacity: 0; transform: rotate(-14deg) scale(2.2);
  animation: qseal .45s cubic-bezier(.2,1.4,.4,1) .15s forwards;
}
@keyframes qseal { to { opacity: 0.95; transform: rotate(-8deg) scale(1); } }

/* ---- сцены кампании ---- */
.scene { text-align: center; }
.scene .story.big { font-size: 15px; line-height: 1.55; text-align: left; margin: 10px 0 14px; }
.story.intro { font-style: italic; color: #d8d5c4; }
.story.hint { font-size: 13px; color: #a9a89c; font-style: normal; }
.story.outro { border-left: 3px solid #6b7d4a; padding-left: 10px; color: #bfd39a; font-size: 13.5px; }

/* =====================================================================
   ДВИЖЕНИЕ.
   Правила, по которым здесь всё анимируется, чтобы игра не выглядела набором кадров:
     • движение ОБЪЯСНЯЕТ, а не украшает: окно прилетает оттуда, куда его позвали; точка на карте
       появляется сверху, потому что её «привезли»; исчезает — оседает пылью;
     • длительности короткие и одинаковые по смыслу: отклик 80–120 мс, появление 180–320 мс,
       уход 160–260 мс. Ничего длиннее 400 мс, кроме дыма и переходов между экранами;
     • ускорение одно на всю игру: вылет с лёгким перелётом (cubic-bezier(.2,1.25,.4,1)),
       уход — ровно (ease-in). Разнобой кривых читается как разные игры в одной;
     • ничто не двигает то, по чему целится палец: кнопка на наведении только светлеет,
       «вдавливается» только на нажатии (историю см. в разделе «отдача от нажатия»);
     • всё это выключается при prefers-reduced-motion — правило в конце раздела.
   ===================================================================== */

/* --- переход между экранами: деревня ↔ карта ↔ бой ---
   Экраны переключаются мгновенно (иначе ломается логика), а стык прикрывает затемнение:
   в момент переключения оно уже полностью непрозрачно и за четверть секунды растворяется. */
#screenfade { position: fixed; inset: 0; background: #070906; opacity: 0; pointer-events: none; z-index: 900; }
#screenfade.run { animation: screenfade .34s ease-out forwards; }
@keyframes screenfade { 0% { opacity: .92; } 55% { opacity: .5; } 100% { opacity: 0; } }

/* Сам экран въезжает: чуть крупнее и прозрачнее — к своему размеру */
#worldscr:not(.hidden) { animation: scr-in .3s cubic-bezier(.2,1.25,.4,1) both; }
/* Ужимаем К своему размеру, а не ОТ большего: увеличенный на входе экран вылезал за края окна */
@keyframes scr-in { from { opacity: 0; transform: scale(.985); } to { opacity: 1; transform: scale(1); } }

/* --- панель здания и карточка точки: прилетают от своего края --- */
#bpanel:not(.hidden) { animation: panel-in .24s cubic-bezier(.2,1.25,.4,1) both; }
@keyframes panel-in { from { opacity: 0; transform: translateX(-14px) scale(.97); } to { opacity: 1; transform: none; } }
#world-card:not(.hidden) { animation: card-in .24s cubic-bezier(.2,1.25,.4,1) both; }
@keyframes card-in { from { opacity: 0; transform: translateX(18px) scale(.97); } to { opacity: 1; transform: none; } }
/* На телефоне карточка занимает всю ширину: сдвиг вбок вылезал бы за край — там она просто подрастает */
@media (max-width: 560px) {
  #world-card:not(.hidden) { animation-name: card-in-mob; }
  @keyframes card-in-mob { from { opacity: 0; transform: scale(.97); } to { opacity: 1; transform: none; } }
}

/* Строки характеристик проявляются каскадом — панель читается сверху вниз, а не вспыхивает целиком */
#bstats .stat, #world-card .wline { animation: row-in .2s ease-out both; }
#bstats .stat:nth-child(1), #world-card .wline:nth-child(1) { animation-delay: .02s; }
#bstats .stat:nth-child(2), #world-card .wline:nth-child(2) { animation-delay: .05s; }
#bstats .stat:nth-child(3), #world-card .wline:nth-child(3) { animation-delay: .08s; }
#bstats .stat:nth-child(4), #world-card .wline:nth-child(4) { animation-delay: .11s; }
#bstats .stat:nth-child(5), #world-card .wline:nth-child(5) { animation-delay: .14s; }
#bstats .stat:nth-child(n+6), #world-card .wline:nth-child(n+6) { animation-delay: .17s; }
@keyframes row-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

/* --- кнопки --- */
/* Наведение только светлеет (двигать нельзя — курсор соскальзывает и нажатие теряется),
   нажатие вдавливает, а от места нажатия расходится короткая волна. */
.btn { position: relative; overflow: hidden; transition: filter .12s ease, box-shadow .12s ease, transform .08s ease; }
.btn:not(.dis):hover { filter: brightness(1.12); }
.btn::after { content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(circle at center, rgba(255,255,255,0.55), rgba(255,255,255,0) 60%); opacity: 0; }
.btn:not(.dis):active::after { animation: btn-wave .34s ease-out; }
@keyframes btn-wave { 0% { opacity: .5; transform: scale(.25); } 100% { opacity: 0; transform: scale(1.6); } }
/* Главная кнопка окна тихо дышит: взгляд сразу находит, что тут делать */
.modal-box .btn.ok.big, #world-card .btn.ok.big { animation: btn-breathe 2.6s ease-in-out infinite; }
@keyframes btn-breathe { 0%, 100% { box-shadow: 0 3px 0 #2f1d0e; } 50% { box-shadow: 0 3px 0 #2f1d0e, 0 0 16px rgba(127,210,58,0.45); } }
/* Кнопка, которую только что потушили нехваткой ресурсов, коротко дрожит (UI.nope) */
.btn.nope { animation: btn-nope .3s ease-in-out; }
@keyframes btn-nope { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-4px); } 50% { transform: translateX(4px); } 75% { transform: translateX(-2px); } }

/* --- всплывающие таблички --- */
#hint:not(.hidden), #battle-hint { animation: tip-in .26s cubic-bezier(.2,1.25,.4,1) both; }
@keyframes tip-in { from { opacity: 0; transform: translate(-50%, -6px) scale(.96); } to { opacity: 1; transform: translate(-50%, 0) scale(1); } }
/* Подсказка стоит по центру (left: 50% + translateX(-50%)). Раньше её анимация заканчивалась на transform: none
   и снимала сдвиг: табличка начиналась от середины экрана, а на телефоне сжималась в правую половину —
   5 строк по 3 слова. Теперь сдвиг сохраняется, а ширина — по тексту (не шире 90 % экрана). */
#hint { width: max-content; }
#hint:not(.hidden) { animation-name: tip-in-plain; }
@keyframes tip-in-plain { from { opacity: 0; transform: translate(-50%, -6px) scale(.96); } to { opacity: 1; transform: translateX(-50%); } }

/* Движение целиком отключается, если человек просил систему не анимировать */
@media (prefers-reduced-motion: reduce) {
  #screenfade, #worldscr:not(.hidden), #bpanel:not(.hidden), #world-card:not(.hidden),
  #bstats .stat, #world-card .wline, .btn::after, .modal-box .btn.ok.big, #hint, #battle-hint { animation: none !important; }
}

/* Первая строка окна не упирается в крестик закрытия: между кнопкой строки и крестиком остаётся
   просвет, иначе они выглядят как одна слипшаяся пара и палец попадает не туда. */
/* именно padding: соседние margin схлопываются с отступом заголовка, и просвет не появлялся */
#modal-content > h2 + .row, #modal-content > .row:first-child { padding-top: 14px; }

/* --- отклик на НАВЕДЕНИЕ ---
   Кликать в игре можно не только по .btn: карточки магазина и орды, вкладки, значки очереди,
   кнопки веток, крестики. Раньше половина из них никак не отзывалась на курсор — непонятно, живая
   это картинка или просто рисунок. Теперь отзывается всё: подсветка и лёгкий подъём, а двигать
   то, по чему целится палец, по-прежнему нельзя — поэтому сдвиг крошечный и только у карточек,
   где промахнуться нечем. На тач-экранах правило не применяется (hover: hover). */
@media (hover: hover) {
  .tab:hover, .ptab:hover, .argbtn:hover, .embtn:hover, .qitem:hover, .wact:hover,
  .modal-box .close:hover, #world-card .wclose:hover { filter: brightness(1.18); }
  .card:not(.dis):hover, .ucard:not(.dis):hover, .pmcard:not(.dis):hover {
    filter: brightness(1.1); transform: translateY(-2px); box-shadow: 0 6px 12px rgba(0,0,0,0.45); }
  .card, .ucard, .pmcard { transition: transform .1s ease, filter .12s ease, box-shadow .12s ease; }
  .tab, .ptab, .argbtn, .embtn, .qitem, .wact, .modal-box .close, #world-card .wclose { transition: filter .12s ease; }
  .card.dis:hover, .ucard.dis:hover { filter: grayscale(1) brightness(.72); }
}
@media (prefers-reduced-motion: reduce) { .card, .ucard, .pmcard { transition: none !important; } }

/* Уровень зомби — табличкой НАД карточкой высадки: в бою над самой ордой ничего не пишем,
   всё, что нужно знать до нажатия, стоит над карточкой. */
/* Уровень зомби — отдельной строкой НАД карточкой. Обёртка нужна, чтобы табличка не зависела от
   толщины рамки-картинки самой карточки: absolute отсчитывался от внутреннего края рамки, и надпись
   ложилась зомби на голову. Пустая табличка (.ph) держит строй, когда уровень первый. */
.ucardwrap { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.ucardwrap .ulvl { font-style: normal; font-size: 10px; font-weight: 800; white-space: nowrap;
  background: linear-gradient(#3b4a2c, #23301b); border: 2px solid #2f1d0e; border-radius: 7px;
  padding: 0 6px; line-height: 15px; color: #ffe066; text-shadow: 0 1px 0 #000; box-shadow: 0 2px 0 rgba(0,0,0,0.45); }
.ucardwrap .ulvl.ph { visibility: hidden; }
.ucard { position: relative; }

/* Строка итогов, где перечисление длиннее одной строки: подпись сверху, находки — плиткой.
   Раньше «Вынесено» уезжало в три строки и налезало на свою же подпись. */
.resrow.col { flex-direction: column; align-items: flex-start; gap: 8px; }
.resrow.col > span { opacity: .85; }
.gotitems { display: flex; flex-wrap: wrap; gap: 10px; width: 100%; }
.gotit { display: inline-flex; align-items: center; gap: 4px; background: rgba(0,0,0,0.28);
  border: 2px solid var(--wood); border-radius: 10px; padding: 4px 8px; font-weight: 700; }
.gotit .ricon, .gotit .pic { width: 26px; height: 26px; object-fit: contain; }

/* Картинка перка не должна распирать ячейку и карточку */
.slot .pic, .card.perk .pic { object-fit: contain; }
.slot .pic { width: 40px; height: 40px; }
.card.perk .pic { width: 56px; height: 56px; }

/* Строка «Задание: …» в шапке карты: по ней видно, что на карте есть именная точка задания,
   и нажатие сразу её выделяет. Без неё игрок читал «найди дом Пахома» и не знал, где смотреть. */
#world-top .wquest { cursor: pointer; font-size: 13px; color: #ffd45e; padding: 2px 0 0; }
#world-top .wquest:hover { filter: brightness(1.15); }
/* Мутация: два вида зомби и стрелка между ними */
.queue.mut { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.queue.mut .pic { width: 44px; height: 44px; object-fit: contain; }
.queue.mut .arr { font-style: normal; font-size: 18px; color: #b9b09a; }

/* Пока окно схлопывается, оно не должно перехватывать нажатия: полсекунды «мёртвых» кликов
   читаются как «кнопка не нажалась». */
#modal.closing { pointer-events: none; }

/* ---- лента помощи убежища ----
   Одна лента вместо четырёх блоков: свои просьбы и просьбы соклановцев вперемешку, новые сверху. */
/* Ряд «Попросить»: четыре кнопки одной длины. Без этого кнопка с пояснением
   («построй бункер», «просьба уже висит») растягивалась на пол-окна, а соседняя ужималась. */
/* Звание в убежище: видно, сколько можно просить сейчас и что даст следующая ступень */
.rankbox { border: 2px solid var(--wood); border-radius: 12px; padding: 8px 10px; margin: 8px 0 10px;
  background: rgba(60,50,30,0.25); display: flex; flex-direction: column; gap: 6px; }
.rankbox .capbar { margin: 0; }
.rankbox .lvrow { display: flex; gap: 6px; flex-wrap: wrap; }
/* Окно «да / нет» (UI.ask) вместо браузерного confirm: две кнопки в ряд, на телефоне — друг под другом */
.ynrow { display: flex; gap: 10px; margin: 12px 0 4px; }
.ynrow .btn { flex: 1 1 0; }
.gatebtns { margin-top: 12px; }
.welcome-login { display: block; margin: 10px auto 2px; }   /* «У меня уже есть аккаунт» под «Понятно» — по центру, не прилипая к раме (живой прогон 25.09) */
@media (max-width: 480px) { .ynrow { flex-direction: column; } }
.askrow { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; align-items: stretch; margin: 6px 0 10px; }
.askrow > .muted { grid-column: 1 / -1; }
.askrow .btn { width: 100%; }
@media (max-width: 760px) { .askrow { grid-template-columns: repeat(2, 1fr); } }
.feed { display: flex; flex-direction: column; gap: 10px; }
.feedrow { border: 2px solid var(--wood); border-radius: 12px; padding: 8px 10px; background: rgba(0,0,0,0.25);
  display: flex; flex-direction: column; gap: 5px; }
.feedrow.mine { border-color: #6b8a4a; background: rgba(60,80,40,0.25); }
.feedrow .fwho { display: flex; align-items: baseline; gap: 8px; }
.feedrow .fwhat { font-size: 13px; }
.feedrow .fbtns { display: flex; gap: 8px; flex-wrap: wrap; }
.feedrow .capbar { margin: 0; }
/* закрытая просьба: гаснет, но пару минут висит — видно, что помощь дошла */
.feedrow.done { opacity: 0.62; border-color: #4d6b3a; }
.feedrow.done .capbar .fill { background: linear-gradient(180deg, #8fd05a, #5d9a33); }
.okmark { color: #9ede6a; }

/* ---- Полигон ---- */
.pgrow { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; margin: 6px 0 10px; }
.pgrow label { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; }
.pgrow select, .pgrow input[type=number] { background: var(--panel); color: var(--text); border: 2px solid var(--wood2); border-radius: 8px; padding: 4px 6px; font: inherit; }
.pggrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 4px 12px; margin: 4px 0 10px; }
.pgz { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 3px 0; border-bottom: 1px dashed rgba(255,255,255,0.08); }
.pgz input { width: 64px; background: var(--panel); color: var(--text); border: 2px solid var(--wood2); border-radius: 8px; padding: 3px 6px; font: inherit; text-align: right; }
.pglog { padding: 6px 0; border-bottom: 1px dashed rgba(255,255,255,0.1); font-size: 14px; }

/* ---- Мировая угроза на карте ---- */
#world-top .wrow.threat { display: block; border: 2px solid #b8402c; border-radius: 12px; padding: 8px 10px; background: rgba(60,20,14,0.55); }
#world-top .wrow.threat > div { width: 100%; }
#world-top .wrow.threat.quiet { border-color: rgba(255,255,255,0.15); background: rgba(0,0,0,0.25); display: flex; justify-content: space-between; }
#world-top .wrow.threat.won { border-color: #7fae4a; background: rgba(30,60,20,0.55); display: flex; justify-content: space-between; align-items: center; }
#world-top .wrow.threat.lost { border-color: #b8402c; display: flex; justify-content: space-between; align-items: center; }
.threat-head { display: flex; justify-content: space-between; align-items: baseline; }
.threat-desc { margin: 2px 0 6px; }
.threat-bar { position: relative; height: 18px; margin: 4px 0; border-radius: 9px; background: rgba(0,0,0,0.5); border: 1px solid rgba(255,255,255,0.15); overflow: hidden; }
.threat-bar i { position: absolute; left: 0; top: 0; bottom: 0; background: linear-gradient(90deg, #b8402c, #e8a13c); }
.threat-bar b { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 12px; text-shadow: 0 1px 0 #000; }
.threat-foot { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-top: 6px; flex-wrap: wrap; }
.threat-buff { color: #9ee07a; } .threat-debuff { color: #ff8a6a; }

/* значки механик (js/icons.js): инлайн-SVG вместо эмодзи, чтобы одинаково читались на любой системе */
img.ico { display: inline-block; vertical-align: -0.25em; width: 1.25em; height: 1.25em; margin: 0 .12em; pointer-events: none; }
.stat b img.ico, .btn img.ico, .resrow img.ico { vertical-align: -0.18em; }

/* 1.31: таблица черепов */
.lb { display: flex; flex-direction: column; gap: 4px; margin: 8px 0; }
.lbrow { display: grid; grid-template-columns: 2em 1fr auto auto; gap: 8px; align-items: center; padding: 6px 10px; background: rgba(0,0,0,0.22); border-radius: 8px; }
.lbrow.me { outline: 1px solid rgba(255,210,60,0.6); background: rgba(255,210,60,0.10); }
.lbrank { color: #cbb27a; font-weight: 700; text-align: right; }
.lbskulls { white-space: nowrap; font-weight: 700; }

/* 1.32: экономика */
.eco-now-row { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 6px 0 8px; font-size: 13px; }
.eco-now { white-space: nowrap; }
.eco-wrap { overflow-x: auto; margin: 6px 0 10px; }
.eco { width: 100%; border-collapse: collapse; font-size: 13px; }
.eco th, .eco td { padding: 4px 6px; text-align: right; white-space: nowrap; }
.eco th:first-child, .eco td.ek { text-align: left; }
.eco td.ek { max-width: 11em; overflow: hidden; text-overflow: ellipsis; }
.eco tr.sec td { text-align: left; color: #cbb27a; font-weight: 700; padding-top: 8px; border-bottom: 1px solid rgba(255,255,255,0.12); }
.eco tr.tot td { border-top: 1px solid rgba(255,255,255,0.18); font-weight: 700; }
.eco tr.bal td { font-weight: 700; }
.eco td.z { color: rgba(255,255,255,0.3); }
.ok-txt { color: #9fe25a; }

/* ---------- магазин (1.44) ---------- */
.sgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr)); gap: 14px; margin: 8px 0 14px; }
.sgrid.packs { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
/* что внутри набора — отдельными фишками: значок и число держатся вместе, строки не слипаются */
.scard .sitem { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;
  padding: 2px 7px; border-radius: 999px; background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.08); }
.scard { position: relative; overflow: hidden; border: 1px solid rgba(255,255,255,0.14); border-radius: 12px; padding: 10px 8px 8px;
  background: rgba(255,255,255,0.05); text-align: center; display: flex; flex-direction: column; gap: 4px; align-items: center; }
.scard .btn { width: 100%; margin-top: auto; padding: 9px 10px; }
.scard .sname { font-weight: 800; line-height: 1.15; }
.scard .sgot { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 6px; font-size: 13px; margin: 2px 0 4px; }
.sart { width: 84px; height: 84px; object-fit: contain; }
.sart.ph { display: flex; align-items: center; justify-content: center; font-size: 44px; line-height: 1; }
.sart.big { width: 116px; height: 116px; }
.sart.ph.big { font-size: 60px; }
.sbadge { position: absolute; top: 5px; right: 5px; background: #e0a32e; color: #241a08; font-weight: 800; font-size: 11px;
  padding: 2px 7px; border-radius: 9px; border: 1px solid #1d1611; white-space: nowrap; }
.offerbig { position: relative; overflow: hidden; display: flex; gap: 10px; align-items: center; border: 2px solid #e0a32e; border-radius: 12px;
  padding: 10px; margin: 6px 0 10px; background: rgba(224,163,46,0.10); }
.offerbig .ocol { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; text-align: left; }
.offerbig .sname { padding-right: 104px; }
#offerbox { position: absolute; left: 8px; right: 8px; bottom: 96px; z-index: 6; overflow: hidden; display: flex; gap: 8px; align-items: center;
  border: 2px solid #e0a32e; border-radius: 12px; padding: 8px 10px 8px 8px; background: rgba(28,22,16,0.94); }
#offerbox .ocol { flex: 1; min-width: 0; text-align: left; }
#offerbox.under { visibility: hidden; pointer-events: none; }   /* уступает панели здания, полосе постановки, облачку главы (UI.renderOffer) */
#offerbox .sart { width: 54px; height: 54px; }
#offerbox .sart.ph { font-size: 30px; }
#offerbox .btn { flex: 0 0 auto; }
#offerbox .oclose { position: absolute; top: 4px; right: 4px; width: 24px; height: 24px; border-radius: 50%;
  border: 1px solid #1d1611; background: #3a2f26; color: #f0e6d2; font-size: 15px; line-height: 1; cursor: pointer; padding: 0; }
@media (max-width: 520px) {
  .sart { width: 66px; height: 66px; }
  .sart.ph { font-size: 36px; }
  #offerbox { bottom: 88px; }
  #offerbox .sname { font-size: 13px; }
}

/* ---------- живость магазина и достижений (1.46) ---------- */
/* карточки влетают по очереди, а не появляются пачкой */
.sgrid .scard { animation: scardIn .34s cubic-bezier(.2,.9,.3,1.3) both; }
.sgrid .scard:nth-child(2) { animation-delay: .05s; }
.sgrid .scard:nth-child(3) { animation-delay: .1s; }
.sgrid .scard:nth-child(4) { animation-delay: .15s; }
@keyframes scardIn { from { opacity: 0; transform: translateY(14px) scale(.96); } to { opacity: 1; transform: none; } }
.scard { transition: transform .14s ease, box-shadow .14s ease, border-color .14s ease; }
.scard:hover { transform: translateY(-3px); border-color: rgba(224,163,46,.6); box-shadow: 0 6px 16px rgba(0,0,0,.35); }
.scard .btn.ok { position: relative; overflow: hidden; }
/* по кнопке цены раз в несколько секунд пробегает блик */
.scard .btn.ok::after, .offerbig .btn.ok::after {
  content: ''; position: absolute; top: 0; left: -60%; width: 40%; height: 100%; pointer-events: none;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.35), transparent);
  animation: shine 4.5s ease-in-out infinite; }
@keyframes shine { 0%, 65% { left: -60%; } 85%, 100% { left: 120%; } }
.sbadge { animation: badgePop .5s cubic-bezier(.2,.9,.3,1.5) both; }
@keyframes badgePop { from { transform: scale(0) rotate(-12deg); } to { transform: none; } }
.offerbig { animation: scardIn .4s cubic-bezier(.2,.9,.3,1.3) both; }
/* большое предложение тихо дышит рамкой, чтобы глаз его нашёл */
.offerbig { animation: scardIn .4s cubic-bezier(.2,.9,.3,1.3) both, offerGlow 2.6s ease-in-out 1s infinite; }
@keyframes offerGlow { 0%, 100% { box-shadow: 0 0 0 rgba(224,163,46,0); } 50% { box-shadow: 0 0 14px rgba(224,163,46,.45); } }
#offerbox { animation: offerUp .4s cubic-bezier(.2,.9,.3,1.25) both; }
@keyframes offerUp { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }
/* окно заказа */
.orderbox { display: flex; gap: 12px; align-items: center; border: 1px solid rgba(255,255,255,.14); border-radius: 12px;
  padding: 10px; margin: 8px 0; background: rgba(255,255,255,.05); }
.orderbox .ocol { flex: 1; min-width: 0; text-align: left; display: flex; flex-direction: column; gap: 4px; }
.orderbox .oprice { font-weight: 800; font-size: 20px; color: #e0a32e; }
/* достижения: искры от карточки и батарейка, улетающая к счётчику */
.achspark { position: fixed; z-index: 60; pointer-events: none; font-size: 16px; animation: spark .85s ease-out forwards; }
@keyframes spark { from { opacity: 1; transform: translate(0,0) scale(.6); } to { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(1.3); } }
.achfly { position: fixed; z-index: 60; pointer-events: none; font-weight: 800; color: #ffd23c; text-shadow: 0 2px 0 #1d1611;
  animation: achfly .8s cubic-bezier(.4,0,.6,1) forwards; }
@keyframes achfly { from { opacity: 1; transform: translate(0,0) scale(1); } 70% { opacity: 1; } to { opacity: 0; transform: translate(var(--tx), var(--ty)) scale(.7); } }
.res.bump { animation: bump .45s cubic-bezier(.2,.9,.3,1.6); }
@keyframes bump { 0% { transform: scale(1); } 40% { transform: scale(1.16); } 100% { transform: scale(1); } }
.acard.ready { animation: readyPulse 2.2s ease-in-out infinite; }
@keyframes readyPulse { 0%, 100% { box-shadow: 0 0 0 rgba(143,209,79,0); } 50% { box-shadow: 0 0 12px rgba(143,209,79,.5); } }
@media (prefers-reduced-motion: reduce) {
  .sgrid .scard, .offerbig, #offerbox, .sbadge { animation: none; }
  .scard .btn.ok::after, .offerbig .btn.ok::after { animation: none; }
  .acard.ready { animation: none; }
}


/* ---------- рюкзак: значок по центру карточки (1.48) ---------- */
.bagcard { text-align: center; }
.bagcard .pic { margin: 0 auto 6px; display: flex; align-items: center; justify-content: center; }
.bagcard .pic img { display: block; margin: 0 auto; }


/* ---------- шапка карты области: одна строка (1.48) ---------- */
#world-top .whead { gap: 8px 12px; }
#world-top .whead .wscout { margin-left: auto; }
#world-top .wfold { background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.18); color: #f0e6d2;
  width: 26px; height: 26px; border-radius: 8px; cursor: pointer; font-size: 13px; line-height: 1; padding: 0; flex: 0 0 auto; }
#world-top .wfold:hover { background: rgba(255,255,255,.12); }
#world-top .wlegend { margin-left: 0; }
@media (max-width: 760px) {
  #world-top .wlegend { display: none; }              /* на телефоне легенда только мешает */
  #world-top .whead .wscout { margin-left: 0; }
}

/* Строка «во дворе осталось» в отчёте об обороне: это единственный ПЛЮС в окне, где всё остальное —
   минусы, поэтому она зелёная. Иначе взгляд читает её как ещё одну потерю. */
.resrow.pile b { color: #9fd14a; }

/* ===== Глава деревни (js/chief.js) =====
   Портрет в левом нижнем углу и облачко рядом. Нажатие по всей панели — следующая реплика,
   крестик — закрыть совсем. Панель показывается только в деревне, поэтому ей не нужно уступать
   место панели здания: Chief.free() прячет её сам.
   Без файла портрета остаётся класс .noface — облачко становится обычной табличкой и не
   разваливается на пустом месте. */
#chief {
  position: absolute; left: 10px; bottom: 96px; z-index: 40;
  display: flex; align-items: flex-end; gap: 0;
  width: min(460px, calc(100vw - 20px));
  pointer-events: auto; cursor: pointer;
}
#chief .chief-por { flex: 0 0 auto; width: 124px; height: 124px; display: flex; align-items: flex-end; justify-content: center; }
/* Портрет — поясной, и внизу картинка обрывается ровной чертой с двумя острыми углами: так её
   рисует генератор (edges: touch, иначе фигура не заполняет кадр). Само по себе это выглядит как
   наклеенный прямоугольник. Гасим низ в прозрачность и слегка скругляем бока — фигура уходит в тень,
   а не обрезается ножницами. Маска работает и когда картинки нет вовсе (рисуется заглушка). */
#chief .chief-por img { width: 100%; height: 100%; object-fit: contain; object-position: bottom center; filter: drop-shadow(0 6px 10px rgba(0,0,0,0.65)); transform-origin: 50% 100%;
  border-radius: 12px 12px 0 0;
  -webkit-mask-image: linear-gradient(to bottom, #000 0 68%, rgba(0,0,0,.72) 84%, rgba(0,0,0,.28) 94%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0 68%, rgba(0,0,0,.72) 84%, rgba(0,0,0,.28) 94%, transparent 100%); }
#chief.noface .chief-por { display: none; }

#chief .chief-bub {
  position: relative; flex: 1 1 auto; min-width: 0; margin: 0 0 14px -14px;
  background: var(--panel2); border: 3px solid var(--wood2); border-radius: 14px;
  padding: 8px 26px 10px 14px; box-shadow: 0 8px 22px rgba(0,0,0,0.6);
}
#chief.noface .chief-bub { margin-left: 0; }
/* хвостик облачка — смотрит на портрет */
#chief .chief-bub::before {
  content: ''; position: absolute; left: -11px; bottom: 16px;
  border: 9px solid transparent; border-right-color: var(--wood2); border-left: 0;
}
#chief.noface .chief-bub::before { display: none; }
#chief .chief-name { font-size: 11px; font-weight: 800; letter-spacing: .04em; color: var(--gold); margin-bottom: 2px; }
#chief .chief-text { font-size: 14px; line-height: 1.42; text-shadow: 0 1px 0 rgba(0,0,0,0.6); overflow-wrap: anywhere; }
#chief .chief-more { position: absolute; right: 9px; bottom: 6px; font-size: 13px; color: var(--rust2); animation: chief-more 1.1s ease-in-out infinite; }
/* крестик цепляется за угол ОБЛАЧКА, а не всей панели: портрет выше облачка, и на широком
   экране кнопка иначе повисала в воздухе отдельно от текста */
#chief .chief-x {
  position: absolute; right: -8px; top: -10px; width: 26px; height: 26px; line-height: 1; padding: 0;
  border-radius: 50%; border: 2px solid var(--wood2); background: var(--panel); color: var(--bone);
  font-size: 16px; font-weight: 800; display: flex; align-items: center; justify-content: center;
}
#chief .chief-x:active { transform: translateY(1px); }

/* появление: портрет выезжает снизу, облачко следом */
#chief.in .chief-por img { animation: chief-rise .34s cubic-bezier(.2,1.3,.4,1) both; }
#chief.in .chief-bub { animation: chief-pop .3s cubic-bezier(.2,1.35,.4,1) .08s both; }
/* смена реплики: портрет коротко «вздыхает», текст перетекает */
#chief.flip .chief-por img { animation: chief-beat .26s ease-out both; }
#chief.flip .chief-text { animation: chief-fade .26s ease-out both; }
@keyframes chief-rise { from { opacity: 0; transform: translateY(26px) scale(.96); } to { opacity: 1; transform: none; } }
@keyframes chief-pop { from { opacity: 0; transform: translateX(-10px) scale(.94); } to { opacity: 1; transform: none; } }
@keyframes chief-beat { 0% { transform: scaleY(.94) scaleX(1.03); } 100% { transform: none; } }
@keyframes chief-fade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@keyframes chief-more { 0%, 100% { opacity: .35; transform: translateX(0); } 50% { opacity: 1; transform: translateX(2px); } }

/* Узкий экран: портрет меньше, облачко на всю ширину. Панель по-прежнему выше нижнего ряда кнопок. */
@media (max-width: 700px) {
  #chief { left: 8px; bottom: 92px; width: calc(100vw - 16px); }
  #chief .chief-por { width: 84px; height: 84px; }
  #chief .chief-bub { margin-bottom: 8px; padding: 7px 24px 8px 12px; }
  #chief .chief-name { font-size: 10px; }
  #chief .chief-text { font-size: 13px; line-height: 1.38; }
}
@media (max-width: 420px) {
  #chief .chief-por { width: 70px; height: 70px; }
  #chief .chief-text { font-size: 12px; }
}
/* полоска «облачко уйдёт само» тает за время реплики (Chief.bar) — отчёт 17-25 */
#chief .chief-tm { position: absolute; left: 14px; right: 28px; bottom: 3px; height: 2px; border-radius: 2px; background: var(--gold); opacity: .5; transform-origin: left center; pointer-events: none; }
@keyframes chief-tm { from { transform: scaleX(1); } to { transform: scaleX(0); } }
@media (prefers-reduced-motion: reduce) {
  #chief .chief-por img, #chief .chief-bub, #chief .chief-text, #chief .chief-more { animation: none !important; }
  #chief .chief-tm { display: none; }
}
/* ===== Обучение новичка (Tutor в js/chief.js, 26.09) =====
   Облачко Зои не тает само (таймера нет), у реплик без действия — кнопка «Дальше». Цель шага — мигающая рамка поверх
   (#coach .ring, над окнами и боем) и короткая подсказка рядом; сама кнопка-цель мигает (.tut-hot). */
#chief.tutor .chief-tm, #chief.tutor .chief-more { display: none; }
#chief.tutor { transition: transform .22s ease; }   /* Tutor.dodge поднимает облачко над подсказкой и плашкой стройки */
#chief.tutor .chief-bub { padding-bottom: 10px; }
#chief .chief-next { display: block; margin: 8px 0 0 auto; padding: 5px 14px; border-radius: 10px; border: 2px solid #2f1d0e;
  background: linear-gradient(#7fd23a, #4f8f1f); color: #10160c; font-weight: 900; font-size: 13px; cursor: pointer;
  box-shadow: 0 3px 0 #22380f; animation: tut-next 1.2s ease-in-out infinite; }
#chief .chief-next.hidden { display: none; }
#chief .chief-next:active { transform: translateY(2px); box-shadow: 0 1px 0 #22380f; }
@keyframes tut-next { 0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.25); } }
#coach { position: fixed; inset: 0; pointer-events: none; z-index: 55; }
#coach.hidden, #coach .hidden { display: none; }
#coach .ring { position: fixed; display: block; border: 3px solid #ffd23c; border-radius: 14px;
  box-shadow: 0 0 0 3px rgba(20,12,4,.55), 0 0 22px 6px rgba(255,210,60,.65); animation: coach-ring 1s ease-in-out infinite; }
@keyframes coach-ring { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .55; transform: scale(1.05); } }
#coach .ctip { position: fixed; display: block; max-width: min(260px, calc(100vw - 12px)); padding: 7px 11px; border-radius: 10px;
  background: #2b1a0c; border: 2px solid #ffd23c; color: #ffe9a8; font-size: 14px; font-weight: 800; line-height: 1.3;
  text-align: center; box-shadow: 0 6px 16px rgba(0,0,0,.6); animation: coach-bob 1s ease-in-out infinite; --ax: 50%; }
#coach .ctip::after { content: ''; position: absolute; left: var(--ax); width: 0; height: 0; margin-left: -8px;
  border-left: 8px solid transparent; border-right: 8px solid transparent; }
#coach .ctip.up::after { top: 100%; border-top: 9px solid #ffd23c; }
#coach .ctip.down::after { bottom: 100%; border-bottom: 9px solid #ffd23c; }
/* подсказка сбоку от цели (шаг с side): хвостик смотрит влево или вправо, по высоте — на цель (--ay) */
#coach .ctip.sr::after, #coach .ctip.sl::after { left: auto; top: var(--ay, 50%); margin: -8px 0 0; border: 8px solid transparent; }
#coach .ctip.sr::after { right: 100%; border-right: 9px solid #ffd23c; }
#coach .ctip.sl::after { left: 100%; border-left: 9px solid #ffd23c; }
@keyframes coach-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
.tut-hot { animation: tut-hot 1s ease-in-out infinite !important; }
@keyframes tut-hot { 0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.45) drop-shadow(0 0 8px #ffd23c); } }
@media (prefers-reduced-motion: reduce) { #coach .ring, #coach .ctip, .tut-hot, #chief .chief-next { animation: none !important; } }
/* экран загрузки: не доехали файлы — строка и «Повторить» (Assets.loadAll, 26.09) */
#loading .lfail { max-width: min(460px, 88vw); text-align: center; font-size: 14px; line-height: 1.45; color: #ffe9a8;
  background: rgba(20,12,4,.78); border: 2px solid var(--rust2); border-radius: 12px; padding: 10px 14px; display: flex; flex-direction: column; gap: 8px; align-items: center; }
#loading .lfail.hidden, #loading .lfail .hidden { display: none; }

/* ===== Правки под узкие экраны (замеры: tools-прогон вёрстки на 320–430 px) =====
   Три настоящих косяка, найденных замерами, а не на глаз. */

/* 1. Крестик окна налезал на последнюю вкладку. Ряд вкладок стоит вверху окна, а крестик — в том же
      углу поверх него: на узком экране палец попадал по «закрыть» вместо вкладки. Освобождаем ему угол. */
/* …но только когда вкладки — первая строка окна. Под заголовком крестик живёт в строке заголовка, и угол
   вкладкам не нужен: иначе в «Орде» на 1280 «Перки» уезжали одни во второй ряд (+15 %), а в пропуске на
   телефоне — «Достижения». */
#modal-content > .tabs:first-child { padding-right: 46px; }
/* Под заголовком: на широком экране крестик чуть длиннее строки заголовка — опускаем вкладки на 8 px (замер:
   крестик до 181, вкладки с 176 — задевал «Перки»); на телефоне вкладки всё равно в несколько рядов, и угол
   под крестик ряды не прибавляет. */
.modal-box h2 + .tabs { padding-top: 8px; }   /* padding, не margin: margin схлопнулся бы с нижним отступом заголовка */
@media (max-width: 700px) { .modal-box h2 + .tabs { padding-top: 0; padding-right: 46px; } }

/* 2. Кнопки в строках настроек сжимались и резали надпись («Регистрац…», «Войт…»). Кнопка теперь
      не ужимается, а длинное название слева переносится — оно для этого и длинное. */
.row > .btn, .row > button { flex: 0 0 auto; white-space: nowrap; }
.row > .btn.big { flex: 1 1 auto; width: auto; min-width: 0; margin-top: 0; }   /* большая кнопка в ряду не выталкивает соседнюю за край окна */
.row > span:first-child { min-width: 0; overflow-wrap: anywhere; }

/* 3. Крестик главы деревни был 25 px — мимо такого пальцем промахиваются. Сам кружок крупнее,
      плюс невидимый запас вокруг: попасть можно, не целясь. */
#chief .chief-x { width: 30px; height: 30px; }
#chief .chief-x::after { content: ''; position: absolute; inset: -9px; border-radius: 50%; }
@media (max-width: 700px) { #chief .chief-x { width: 34px; height: 34px; font-size: 18px; } }

/* Кнопки входа/регистрации в настройках стояли в ряду flex и ужимались до «Регистраци…».
   Теперь ужиматься ниже своей надписи не могут, а если не влезают — переносятся на вторую строку. */
.netform div { flex-wrap: wrap; }
.netform div > .btn { white-space: nowrap; flex: 1 1 auto; min-width: max-content; }

/* ===== Бой на телефоне: полоса зомби на всю ширину =====
   Было: полоса зомби и столбик кнопок делили одну строку, и на 360 px полосе оставалось 138 px —
   из семи карточек орды видно ОДНУ, остальные надо было выискивать прокруткой прямо во время боя.
   Стало: полоса занимает всю ширину, кнопки уходят под неё в ряд. Ровно как в мобильных стратегиях,
   и палец не промахивается мимо нужного зомби. */
@media (max-width: 700px) {
  .bbottom { flex-direction: column; align-items: stretch; gap: 6px; }
  #unitbar { flex: 1 1 auto; width: 100%; }
  .bbtns { flex-direction: row; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }
  .bbtns .btn { flex: 0 1 auto; }
  /* кнопка-гармошка на карте области была 26 px — мимо такой мажут пальцем */
  #world-top .wfold { min-width: 34px; min-height: 34px; }
}

/* Тост в бою на телефоне падал ровно на карточки зомби: полоса стала выше, а он остался на 110 px.
   Поднимаем его над всей нижней панелью боя — сообщение читается, а орда остаётся под пальцем. */
@media (max-width: 700px) {
  body.in-battle #toast { bottom: calc(190px + env(safe-area-inset-bottom, 0px)); }
}
/* Открыто окно — тост сверху экрана, а не на нижних кнопках окна (UI.toastPlace) */
body #toast.top, body.in-battle #toast.top { top: calc(6px + env(safe-area-inset-top, 0px)); bottom: auto; transform: translateX(-50%) translateY(-14px); z-index: 60; }
body #toast.top.show { transform: translateX(-50%) translateY(0); }

/* Панель подтверждения постановки: на узком экране кнопки ужимались до «Готов…» и «Отмен…».
   Теперь кнопки не сжимаются, а сама панель при нехватке места переносит их на вторую строку. */
#placebar { max-width: calc(100vw - 16px); flex-wrap: wrap; justify-content: center; }
/* по тексту, а не половиной экрана: с left: 50% плашка сжималась, и на телефоне три кнопки вставали столбиком */
#placebar { width: max-content; }
#placebar #place-info { flex: 0 0 100%; text-align: center; max-width: none; }
#placebar { max-width: min(460px, calc(100vw - 16px)); }   /* длинная строка «место занято…» переносится в этих пределах, а не растягивает плашку на экран */   /* не сжимается: при «1 1» длинное название («Пулемётное гнездо · 500») тянуло «Готово» к себе, а «Отмена» уезжала одна во вторую строку */
#placebar .btn { flex: 0 0 auto; white-space: nowrap; }

/* Резерв орды в плашке HUD: «+N» рядом с вместимостью загона — вторая орда, готовая к бою */
#army-info .res-extra { color: var(--toxic); font-weight: 800; margin-left: 2px; }

/* Граница загона на полосе орды: слева от неё то, что выйдет в бой, справа — резерв инкубатора.
   Без этой черты полоса, растянутая на загон + резерв, выглядит вечно недозаполненной. */
.capbar .penline { position: absolute; top: -2px; bottom: -2px; width: 3px; margin-left: -1px; background: var(--bone);
  box-shadow: 0 0 0 1px rgba(0,0,0,0.6); border-radius: 2px; opacity: .85; pointer-events: auto; cursor: help; }
/* подпись полосы — поверх черты загона на тёмной плашке: черта шла ровно через «Зомби:|3 / 20» (живой прогон 23.09) */
.capbar .penline ~ span { z-index: 1; pointer-events: none; }
.capbar .cblab { font-style: normal; background: rgba(20,14,8,.72); border-radius: 8px; padding: 0 8px; line-height: 1.35; }
