/* HUD. Everything here is an overlay on the canvas: pointer-events are off by
   default and switched on island by island, so a click meant for the world
   never lands on an invisible panel.

   Every size below is a multiple of `--s`, the one scale factor Hud.js derives
   from the window (see FEEL.ui). Fixed pixels were the original sin here: at
   1024x600 the bottom bar took 38% of the screen and the resource bar sat on
   top of the hint, and on a 1440p monitor the same panels shrank into a corner
   nobody looks at. One multiplier fixes both ends; a media query per panel
   fixes neither. */

#hud {
  --ink: #d8d2c4;
  --dim: #8f897c;
  --panel: rgba(12, 16, 20, 0.82);
  --edge: rgba(232, 165, 60, 0.28);
  /* Янтарь, а не зелень: весь арт нарисован по канону «янтарь по умолчанию»,
     и зелёная рамка при наведении загоралась поверх янтарных картинок.
     Оттенок не выдуман — снят с самих иконок: их яркие сигнальные пятна
     лежат между #d88838 и #c8a858, это середина, чуть осветлённая ради
     читаемости текста на тёмной панели. Бирюза жижи не тронута: это цвет
     ресурса, а не оформления. */
  --accent: #e8a53c;

  --s: 1;
  --chip-rows: 2;
  --pad: calc(9px * var(--s));
  --gap: calc(6px * var(--s));
  --r: calc(5px * var(--s));
  --chip: calc(40px * var(--s));

  /**
   * Сторона квадрата, из которого собран весь нижний бар.
   *
   * ОДНО число на три блока: миникарта слева, карточка приказов справа и
   * высота средней секции между ними. Раньше высота бара была следствием
   * содержимого — сколько кнопок в карточке, сколько рядов портретов, есть ли
   * очередь производства, — и потому менялась на каждый щелчок: выбрал
   * рабочего, и панель подпрыгнула; открыл ящик стройки, и подпрыгнула снова.
   * Интерфейс, который шевелится под курсором, заставляет целиться заново
   * после каждого действия.
   *
   * Теперь наоборот: сначала рамка, потом содержимое. Пустые места остаются
   * пустыми местами — это цена, и она дешевле прыжков.
   *
   * 228 — не круглое число из головы: в него ровно ложится карточка приказов
   * (полоса категории 30 + три ряда по 54 + четыре зазора по 6 + поля 2×9 =
   * 228), а миникарта при этом остаётся примерно той же, что была. Меняя
   * `--cell-h`, пересчитать и это.
   */
  --bar: calc(228px * var(--s));
  /* 52, а не 54: при 54 нижний ряд «Гражданских» вылезал за край квадрата на
     два-шесть пикселей и подпись клавиши срезалась. Арифметика теперь сходится
     точно — 30 (полоса категории) + 6 + 3×(52+6) = 210 = внутренняя высота
     квадрата. Меняя это число, пересчитать и `--bar`. */
  --cell-h: calc(52px * var(--s));
  /**
   * Две сетки правой панели: приказы и стройка.
   *
   * `--build-w` — ровно прежняя внутренняя ширина квадрата (228 − 2×9), то
   * есть три столбца по 66 пикселей, какими они и были. Приказам добавлено
   * своё поле в два столбца рядом; панель от этого стала шире квадрата, и это
   * осознанный размен: на снимке владельца правый квадрат был ПУСТ, а вся
   * середина экрана — чёрной. Ширину платит середина, которой там нечего
   * делать.
   */
  --build-w: calc(210px * var(--s));
  --ord-w: calc(146px * var(--s));
  --mini: calc(var(--bar) - 14px * var(--s));
  --fs: calc(12.5px * var(--s));
  --fs-sm: calc(11px * var(--s));
  --fs-xs: calc(9.5px * var(--s));

  font-family: "Segoe UI", system-ui, sans-serif;
  user-select: none;
}

#hud .panel {
  background: var(--panel);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--r);
  backdrop-filter: blur(3px);
}

#hud .icon {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: auto;
  pointer-events: none;
}

/* --- top bar ------------------------------------------------------------ */

#topbar {
  position: absolute;
  top: calc(10px * var(--s));
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: calc(20px * var(--s));
  align-items: center;
  padding: calc(6px * var(--s)) calc(16px * var(--s));
  color: var(--ink);
  font-size: calc(14px * var(--s));
  letter-spacing: 0.4px;
  max-width: calc(100vw - 20px);
  overflow: hidden;
}

#topbar .stat { display: flex; gap: calc(6px * var(--s)); align-items: baseline; }
#topbar .stat b { font-weight: 600; font-variant-numeric: tabular-nums; }
#topbar .label {
  color: var(--dim);
  font-size: calc(11px * var(--s));
  text-transform: uppercase;
  letter-spacing: calc(1.4px * var(--s));
  white-space: nowrap;
}
#topbar .warn b { color: #ffb648; }

/* Icon slots are empty until assets/ui/manifest.js exists; an empty slot must
   take no space at all, or the bar is full of gaps waiting for art. */
#topbar .ico { display: none; }
#topbar .ico.has-icon {
  display: block;
  width: calc(16px * var(--s));
  height: calc(16px * var(--s));
  align-self: center;
}

/* --- notices (transient, centred) ---------------------------------------- */

#notices {
  position: absolute;
  top: calc(56px * var(--s));
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(4px * var(--s));
}

#notices .notice {
  padding: calc(5px * var(--s)) calc(14px * var(--s));
  border-radius: calc(4px * var(--s));
  background: rgba(30, 12, 10, 0.85);
  color: #ffb0a0;
  font-size: var(--fs);
  animation: noticeFade 2.6s ease-out forwards;
}

@keyframes noticeFade {
  0% { opacity: 0; transform: translateY(-6px); }
  12% { opacity: 1; transform: none; }
  75% { opacity: 1; }
  100% { opacity: 0; }
}

/* --- event log ------------------------------------------------------------ */

/* Wider than the minimap column it sits in, on purpose: these are sentences,
   and at minimap width every one of them wrapped onto two lines. It overflows
   to the right over open ground, where there is nothing to cover. */
#log {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
  gap: calc(3px * var(--s));
  width: calc(340px * var(--s));
  max-width: calc(100vw - 24px * var(--s));
  pointer-events: none;
}

#log .line {
  display: flex;
  max-width: 100%;
  align-items: baseline;
  gap: calc(5px * var(--s));
  padding: calc(3px * var(--s)) calc(8px * var(--s));
  border-radius: calc(3px * var(--s));
  border-left: calc(2px * var(--s)) solid var(--dim);
  background: rgba(10, 13, 17, 0.72);
  color: var(--ink);
  font-size: var(--fs-sm);
  line-height: 1.35;
  animation: logIn 220ms ease-out;
}

#log .line .text { flex: 1; min-width: 0; }
#log .line .count { display: none; color: var(--dim); font-variant-numeric: tabular-nums; }
#log .line.has-count .count { display: inline; }

#log .line.good { border-left-color: var(--accent); }
#log .line.warn { border-left-color: #ffb648; color: #f0d9ad; }
#log .line.bad { border-left-color: #e2624a; color: #f3c0b4; }
#log .line.info { border-left-color: rgba(255, 255, 255, 0.22); color: var(--dim); }

@keyframes logIn {
  from { opacity: 0; transform: translateX(calc(-8px * var(--s))); }
  to { opacity: 1; transform: none; }
}

/* --- bottom bar ---------------------------------------------------------- */

#bottombar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: flex-end;
  gap: calc(10px * var(--s));
  padding: calc(10px * var(--s));
}

#left-column {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: calc(6px * var(--s));
  width: var(--bar);
  flex: 0 0 auto;
}

/* Тревога «по нашим бьют»: над миникартой, потому что метка — на ней.

   Появляется и исчезает вместе с тревогой и потому двигает то, что НАД ней
   (лог событий), а не то, что под: миникарта и панели остаются на своих
   местах, а лог и так живёт всплывающими строками. Красная и пульсирует —
   это единственное место интерфейса, которому позволено кричать. */
#alarm {
  display: none;
  width: var(--bar);
  padding: calc(5px * var(--s)) calc(8px * var(--s));
  border: 1px solid rgba(255, 74, 58, 0.8);
  border-radius: calc(4px * var(--s));
  background: rgba(120, 22, 16, 0.85);
  color: #ffd9d3;
  font-family: inherit;
  font-size: var(--fs-sm);
  text-align: left;
  cursor: pointer;
  pointer-events: auto;
  flex: 0 0 auto;
  animation: alarmPulse 900ms ease-in-out infinite;
}
#alarm.on { display: block; }
#alarm:hover { background: rgba(170, 34, 24, 0.92); }

@keyframes alarmPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 74, 58, 0.0); }
  50% { box-shadow: 0 0 calc(10px * var(--s)) 0 rgba(255, 74, 58, 0.55); }
}

/* Квадрат. Миникарта заполняет его целиком: холст рисуется в своих пикселях
   и следует за CSS-размером (Hud._resizeMinimap), так что растягивать нечего
   и мылить нечем. */
#minimap-panel {
  width: var(--bar);
  height: var(--bar);
  padding: calc(6px * var(--s));
  flex: 0 0 auto;
  pointer-events: auto;
}
#minimap {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: calc(3px * var(--s));
  cursor: crosshair;
}

/* Средняя секция: та же высота, что у боковых квадратов, и ни пикселем
   больше ни при каком содержимом. Внутри четыре полосы, три из них
   фиксированные, и только середина тянется — то есть меняется наполнение, а
   не рамка.

   ШИРИНА ОГРАНИЧЕНА, и это главная правка всей панели. Раньше здесь стояло
   `flex: 1 1 auto`, то есть секция занимала всё, что осталось между миникартой
   и карточкой приказов: на экране в две тысячи пикселей это полторы тысячи
   чёрного прямоугольника с портретом в углу и двумя строчками текста. Владелец
   прочитал это как недоделку — и правильно прочитал: карточка одного юнита не
   становится полезнее оттого, что её растянули.

   `margin: 0 auto` разводит остаток поровну на обе стороны, так что секция
   стоит по центру нижнего края, а миникарта и приказы остаются прижатыми к
   своим углам. Свободное место между ними прозрачно — там видно поле боя, и
   это лучшее, что можно сделать с местом, которому нечего показать. */
#selection-panel {
  flex: 0 1 calc(var(--bar) * 2.0);
  margin: 0 auto;
  min-width: 0;
  height: var(--bar);
  padding: calc(8px * var(--s)) calc(10px * var(--s));
  pointer-events: auto;
  display: flex;
  flex-direction: column;
  gap: calc(5px * var(--s));
  overflow: hidden;
}

/* --- верхняя полоса: боевые группы и рабочие ------------------------------ */

#utility {
  display: flex;
  align-items: center;
  gap: calc(6px * var(--s));
  height: calc(24px * var(--s));
  flex: 0 0 auto;
}

/* Группы слева и обрезаются первыми: их девять, а кнопок рабочих две, и на
   узком окне уступать должно то, чего много. */
#control-groups {
  display: flex;
  align-items: center;
  gap: calc(4px * var(--s));
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
}

.cg {
  display: flex;
  align-items: center;
  gap: calc(4px * var(--s));
  height: calc(22px * var(--s));
  padding: 0 calc(6px * var(--s));
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: calc(3px * var(--s));
  background: rgba(255, 255, 255, 0.05);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
  flex: 0 0 auto;
}
.cg:hover { border-color: var(--accent); background: rgba(232, 165, 60, 0.12); }
.cg.on { border-color: var(--accent); background: rgba(232, 165, 60, 0.22); }
.cg .num {
  color: var(--accent);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.cg .n { color: var(--dim); font-variant-numeric: tabular-nums; }

#worker-tools {
  display: flex;
  gap: calc(4px * var(--s));
  flex: 0 0 auto;
}

.wtool {
  display: flex;
  align-items: center;
  gap: calc(5px * var(--s));
  height: calc(22px * var(--s));
  padding: 0 calc(8px * var(--s));
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: calc(3px * var(--s));
  background: rgba(255, 255, 255, 0.05);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--fs-sm);
  white-space: nowrap;
  cursor: pointer;
}
.wtool:hover:not(:disabled) { border-color: var(--accent); background: rgba(232, 165, 60, 0.12); }
.wtool:disabled { opacity: 0.4; cursor: default; }
.wtool .n {
  color: var(--accent);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
/* Простаивающий рабочий — это потерянная добыча, и кнопка говорит об этом
   раньше, чем на неё нажали. Ноль простаивающих не красится ничем: норма
   не нуждается в подсветке. */
.wtool.idle.warn {
  border-color: rgba(226, 161, 58, 0.75);
  background: rgba(226, 161, 58, 0.16);
}
.wtool.idle.warn .n { color: #ffd28a; }

/* Середина — единственное, что тянется. Всё, что не влезло, обрезается
   молча: панель обещает постоянную рамку, а не постоянную полноту. */
#selection-body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: row;
  align-items: stretch;
  gap: calc(10px * var(--s));
  overflow: hidden;
}

#selection-title {
  flex: 0 0 auto;
  color: var(--dim);
  font-size: var(--fs-sm);
  line-height: calc(15px * var(--s));
  height: calc(15px * var(--s));
  text-transform: uppercase;
  letter-spacing: calc(1.4px * var(--s));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Per-type summary. Hidden entirely for a single unit or a single type — a
   row that says "Вахтовик 1" above one portrait of a вахтовик is furniture. */
#selection-groups {
  display: none;
  flex: 0 0 auto;
  align-items: center;
  flex-wrap: wrap;
  gap: calc(4px * var(--s));
  max-height: calc(22px * var(--s));
  overflow: hidden;
}
#selection-groups.on { display: flex; }

.group {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  height: calc(22px * var(--s));
  gap: calc(5px * var(--s));
  padding: 0 calc(7px * var(--s));
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: calc(10px * var(--s));
  background: rgba(255, 255, 255, 0.05);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
  white-space: nowrap;
}
.group:hover { border-color: var(--accent); background: rgba(232, 165, 60, 0.12); }
.group .n { color: var(--accent); font-variant-numeric: tabular-nums; font-weight: 600; }

/* Значок В СТРОКЕ, а не в ячейке, и размер ему надо назвать через `#hud` —
   иначе его переедет общее правило `#hud .icon { width: 100% }`, написанное
   для картинки, заполняющей квадрат. Проигранная специфичность стоила
   портрета рабочего во всю панель: кнопка тянулась по высоте строки, картинка
   бралась за сто процентов этой высоты, `object-fit: contain` держал
   пропорцию — и одна строка сводки съедала всю среднюю секцию. */
#hud .group .icon,
#hud .cg .icon {
  flex: 0 0 auto;
  width: calc(14px * var(--s));
  height: calc(14px * var(--s));
}

#selection-chips {
  display: flex;
  flex: 0 1 auto;
  align-content: flex-start;
  flex-wrap: wrap;
  gap: calc(4px * var(--s));
  max-height: calc(var(--chip) * var(--chip-rows) + 4px * var(--s) * (var(--chip-rows) - 1));
  overflow: hidden;
}

.chip {
  width: var(--chip);
  height: var(--chip);
  border-radius: calc(4px * var(--s));
  border: 1px solid rgba(255, 255, 255, 0.14);
  position: relative;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(15px * var(--s));
  font-weight: 600;
  color: rgba(0, 0, 0, 0.65);
  overflow: hidden;
  flex: 0 0 auto;
}

.chip:hover { border-color: var(--accent); }
.chip .abbr { line-height: 1; }
.chip .icon { padding: calc(3px * var(--s)); }
.chip.more {
  background: rgba(255, 255, 255, 0.06) !important;
  color: var(--dim);
  cursor: default;
  font-size: calc(13px * var(--s));
}
.chip.more:hover { border-color: rgba(255, 255, 255, 0.14); }

.chip .hp {
  position: absolute;
  left: 2px; right: 2px; bottom: 2px;
  height: calc(3px * var(--s));
  background: rgba(0, 0, 0, 0.55);
  border-radius: 2px;
  overflow: hidden;
}
.chip .hp i { display: block; height: 100%; background: #5fc24a; }
.chip.hurt .hp i { background: #e2a13a; }

/* Состав выделения и шпаргалка — вторая и третья роли той же средней полосы.
   Показывается ровно одна из трёх: карточка одного, состав группы или, когда
   не выбрано ничего, короткий список того, что делают мышь и камера. Пустой
   средняя полоса не бывает никогда — это и было условием задачи. */
#selection-side {
  display: none;
  flex: 1 1 auto;
  min-width: 0;
  flex-direction: column;
  gap: calc(4px * var(--s));
  overflow: hidden;
}
#selection-side.on { display: flex; }

#selection-empty {
  display: none;
  color: var(--dim);
  font-size: var(--fs-sm);
  line-height: 1.75;
}
#selection-empty.on { display: block; }
#selection-empty b { color: var(--ink); font-weight: 600; }

/* --- the single-selection preview ---------------------------------------- */

/* Тянется, а не жмётся к левому краю: статистика идёт в два столбца пар и
   занимает ровно ту ширину, которую панель себе оставила. */
#single { display: none; flex: 1 1 auto; min-width: 0; gap: calc(10px * var(--s)); align-items: flex-start; }
#single.on { display: flex; }

/* Портрет во всю высоту средней полосы, а не марка в углу.
   Раньше он был 64 пикселя в панели высотой 228, и три четверти карточки
   одного юнита занимало ничто. Сто четыре — это ровно то, что остаётся полосе
   после верхней строки, заголовка и очереди производства; больше не влезет,
   меньше — снова оставит дыру под собой. */
#portrait {
  position: relative;
  flex: 0 0 auto;
  width: calc(104px * var(--s));
  height: calc(104px * var(--s));
  border-radius: calc(4px * var(--s));
  border: 1px solid rgba(255, 255, 255, 0.16);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(22px * var(--s));
  font-weight: 600;
  color: rgba(0, 0, 0, 0.65);
}
/* A drawn portrait supplies its own colour; the faction fill behind it is
   there for the lettered fallback and would only muddy a picture. */
#portrait.has-icon { background: rgba(0, 0, 0, 0.35) !important; }
#portrait .icon { padding: calc(2px * var(--s)); }
#portrait .hp {
  position: absolute;
  left: calc(3px * var(--s)); right: calc(3px * var(--s)); bottom: calc(3px * var(--s));
  height: calc(4px * var(--s));
  background: rgba(0, 0, 0, 0.6);
  border-radius: 2px;
  overflow: hidden;
}
#portrait .hp i { display: block; height: 100%; width: 100%; background: #5fc24a; }
#portrait.hurt .hp i { background: #e2a13a; }

/* Пары «что — сколько», по две пары в ряд.
   Столбиком они занимали бы восемь строк высотой в сто пятьдесят пикселей —
   вдвое больше, чем средней полосе отведено, — и половина статистики
   обрезалась бы нижним краем молча. В два столбца те же восемь строк
   укладываются в четыре ряда и заодно заполняют ширину, ради которой всё
   это и затевалось. */
#single-detail {
  flex: 1 1 auto;
  min-width: 0;
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr) max-content minmax(0, 1fr);
  align-content: start;
  column-gap: calc(8px * var(--s));
  row-gap: calc(2px * var(--s));
  color: var(--ink);
  font-size: var(--fs);
  line-height: 1.45;
}
#single-detail .dim { color: var(--dim); white-space: nowrap; }
#single-detail .v { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* --- command card --------------------------------------------------------- */

/* The command card and, floating above it, whatever the unit is shouting.
   The plate is positioned rather than stacked so that its arrival never
   resizes the column — a panel that jumps sideways when a unit gets sarcastic
   is a panel the player learns to distrust. */
#right-column {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-end;
  flex: 0 0 auto;
}

#bark {
  position: absolute;
  right: 0;
  bottom: calc(100% + 6px * var(--s));
  display: none;
  width: calc(330px * var(--s));
  max-width: calc(100vw - 24px * var(--s));
  padding: calc(6px * var(--s)) calc(10px * var(--s));
  border-radius: calc(4px * var(--s));
  border-left: calc(2px * var(--s)) solid var(--accent);
  background: rgba(10, 13, 17, 0.88);
  pointer-events: none;
  animation: barkIn 180ms ease-out;
}
#bark.on { display: block; }
#bark .who {
  display: block;
  color: var(--accent);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: calc(1.2px * var(--s));
}
#bark .line { display: block; color: var(--ink); font-size: var(--fs); line-height: 1.4; }

@keyframes barkIn {
  from { opacity: 0; transform: translateY(calc(4px * var(--s))); }
  to { opacity: 1; transform: none; }
}

/* Второй квадрат бара, той же стороны, что и миникарта. Кнопок в нём бывает
   от двух до восьми, и раньше карточка от этого росла и опускалась — то есть
   кнопка «снести» оказывалась то там, то тут. Теперь сетка стоит на месте, а
   пустые ряды остаются пустыми. */
/* Две сетки в одной панели: слева стройка и производство, справа приказы.

   ПРИКАЗЫ СПРАВА, у самого края экрана, и это не вкус. Половина со стройкой
   появляется и исчезает вместе с выделением — у разведчика строить нечего, —
   а приказы есть всегда, пока выбрано хоть что-то своё. Стой они слева от
   исчезающей половины, вся сетка приказов ездила бы по экрану на каждый
   щелчок: кнопка «Стоп» оказывалась бы то там, то тут. Прижатые к краю, они
   не двигаются вовсе, а появляется и пропадает только стройка.

   Высота — прежний квадрат: раскрытая категория ложится в него ровно, и
   трогать эту арифметику нельзя (см. `#card-buttons`). Ширина теперь по
   содержимому. */
#command-card {
  flex: 0 0 auto;
  height: var(--bar);
  padding: var(--pad);
  pointer-events: auto;
  display: flex;
  flex-direction: row;
  align-items: stretch;
  justify-content: flex-end;
  gap: var(--gap);
}

#card-side { display: none; flex: 0 0 var(--build-w); min-width: 0; }
#card-side.on { display: block; }

#order-grid {
  display: none;
  flex: 0 0 var(--ord-w);
  box-sizing: content-box;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: min-content;
  gap: var(--gap);
  align-content: start;
  min-width: 0;
}
#order-grid.on { display: grid; }
/* Разделитель появляется только когда делить есть что. */
#card-side.on + #order-grid.on {
  border-left: 1px solid rgba(255, 255, 255, 0.10);
  padding-left: var(--gap);
}

/* Нечего показать — так и скажем. Пустая панель читается как поломка, панель
   с одной строчкой — как ожидание. */
#card-empty {
  display: none;
  width: calc(190px * var(--s));
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--dim);
  font-size: var(--fs-sm);
  line-height: 1.5;
}
#card-empty.on { display: flex; }

#card-buttons {
  display: grid;
  /* `1fr` is `minmax(auto, 1fr)`, so a button holding the word "Карбоновый"
     forces its column wider than a third and the whole card overflows its own
     panel. `minmax(0, 1fr)` is the only version that means three equal thirds. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  /* Высоту ряда задаёт кнопка, а не сетка: `.cmd` — ровно `--cell-h`,
     `.cmd.nav` — тонкая полоса категории. Строка `grid-auto-rows: var(--cell-h)`
     здесь была бы соблазнительно ровнее и неверна: она отвела бы полосе
     категории целый ряд в 54 пикселя вместо тридцати, и «Гражданские» с их
     семью зданиями перестали бы помещаться в квадрат — третий ряд обрезался
     по нижнему краю. Считать надо по тому, что реально стоит в ряду:
     30 + 6 + (54 + 6) × 3 = 210 = внутренняя высота квадрата. */
  grid-auto-rows: min-content;
  gap: var(--gap);
  align-content: start;
  height: 100%;
  min-height: 0;
  /* Категория с десятью зданиями обрежется, а не растянет бар. Сегодня
     максимум — семь, и это ровно три ряда. */
  overflow: hidden;
}

.cmd {
  display: flex;
  flex-direction: column;
  height: var(--cell-h);
  border-radius: calc(4px * var(--s));
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.05);
  color: var(--ink);
  font-family: inherit;
  cursor: pointer;
  padding: calc(3px * var(--s));
  overflow: hidden;
  min-width: 0;
}

.cmd:hover:not(:disabled) { border-color: var(--accent); background: rgba(232, 165, 60, 0.12); }
.cmd:disabled { opacity: 0.42; cursor: default; }

/* Приказы холоднее стройки. Различать их надо не читая: слева — во что
   вложить ресурсы, справа — что сделать прямо сейчас, и путать эти два дела
   в горячке боя обходится дороже всего. Клавиша на лице кнопки той же
   янтарной, что и везде: это способ ВЫУЧИТЬ управление, а не украшение. */
.cmd.ord {
  border-color: rgba(150, 190, 220, 0.22);
  background: rgba(150, 190, 220, 0.07);
}
.cmd.ord:hover:not(:disabled) {
  border-color: rgba(170, 210, 240, 0.75);
  background: rgba(150, 190, 220, 0.18);
}
.cmd.ord .name { font-size: var(--fs-sm); }

/* Категории стройки и выход из них — навигация, а не приказ, и выглядят они
   иначе: полоса во всю ширину карточки, подпись слева, клавиша справа.

   Ширина здесь не украшение, а необходимость. Ячейка приказа — 68 пикселей,
   и слово «Гражданские» в неё не влезает: перенос рвал его как придётся
   («Гражданск / ие»), потому что русских правил переноса у браузера нет и
   `hyphens: auto` для него пустой звук. Иконки ящикам никто не рисует —
   значит подпись обязана помещаться целиком, а поместиться она может только
   в строке. Заодно две широкие полосы над сеткой зданий сразу читаются как
   другой уровень меню, а не как два здания, которых почему-то два. */
.cmd.nav {
  grid-column: 1 / -1;
  flex-direction: row;
  align-items: center;
  gap: calc(8px * var(--s));
  height: calc(30px * var(--s));
  padding: 0 calc(9px * var(--s));
  border-color: rgba(232, 165, 60, 0.38);
  background: rgba(232, 165, 60, 0.09);
}
.cmd.nav:hover:not(:disabled) { background: rgba(232, 165, 60, 0.20); }
.cmd.nav .face { flex: 1 1 auto; justify-content: flex-start; }
.cmd.nav .foot { flex: 0 0 auto; }
.cmd.nav .foot .cost { display: none; }
.cmd.nav .name {
  font-size: var(--fs-sm);
  font-weight: 600;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The face holds either the icon or the name; the foot holds the price and
   the key. They are stacked rather than layered, because the old card put the
   badges on top of the label and long Russian names ran underneath them. */
.cmd .face {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.cmd .name {
  font-size: var(--fs-xs);
  line-height: 1.1;
  text-align: center;
  hyphens: auto;
  overflow-wrap: anywhere;
}

.cmd .foot {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: calc(3px * var(--s));
  font-size: var(--fs-xs);
  line-height: 1;
}
.cmd .foot .cost { color: var(--dim); white-space: nowrap; overflow: hidden; }
.cmd .foot .key { color: var(--accent); letter-spacing: 0.5px; }

/* --- production queue ----------------------------------------------------- */

/* Очередь производства переехала из карточки приказов в среднюю секцию — и
   не ради красоты. В карточке она добавлялась к кнопкам снизу, то есть
   поднимала весь блок ровно тогда, когда игрок ставил юнита в очередь: панель
   уезжала из-под курсора в момент самого частого действия в игре.
   Здесь у неё своя полоса постоянной высоты: пустая, пока никто ничего не
   производит, и той же самой, когда производит. */
#queue {
  flex: 0 0 auto;
  height: calc(34px * var(--s));
  overflow: hidden;
}

#queue .qhead {
  color: var(--dim);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: calc(1.2px * var(--s));
  margin-bottom: calc(3px * var(--s));
}

#queue .qrow { display: flex; gap: calc(3px * var(--s)); }

#queue .qslot {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  height: calc(20px * var(--s));
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(3px * var(--s));
  background: rgba(255, 255, 255, 0.10);
  border-radius: calc(3px * var(--s));
  overflow: hidden;
  font-size: var(--fs-xs);
  color: var(--ink);
}
#queue .qslot.advance { background: rgba(232, 165, 60, 0.14); }
/* Хвост очереди — то, что снимет правая кнопка. Подсвечен, чтобы обещание
   кнопки было видно до нажатия, а не после возврата денег. */
#queue .qslot { pointer-events: auto; cursor: context-menu; }
#queue .qslot.last { outline: 1px solid rgba(255, 255, 255, 0.22); outline-offset: -1px; }
#queue .qslot.last:hover { outline-color: rgba(255, 120, 100, 0.9); }
#queue .qslot .fill {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 0;
  background: var(--accent);
  opacity: 0.35;
}
#queue .qslot .abbr,
#queue .qslot .left,
#queue .qslot .icon { position: relative; }
#queue .qslot .icon { width: calc(14px * var(--s)); height: calc(14px * var(--s)); }
#queue .qslot .left { color: var(--accent); font-variant-numeric: tabular-nums; }

/* --- tooltip -------------------------------------------------------------- */

#tooltip {
  position: absolute;
  display: none;
  max-width: calc(240px * var(--s));
  padding: calc(6px * var(--s)) calc(9px * var(--s));
  border-radius: calc(4px * var(--s));
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(8, 11, 15, 0.95);
  color: var(--ink);
  font-size: var(--fs);
  line-height: 1.45;
  pointer-events: none;
  z-index: 5;
}
#tooltip.on { display: block; }
#tooltip b { display: block; font-weight: 600; }
#tooltip span { display: block; font-size: var(--fs-sm); }
#tooltip .cost { color: var(--dim); }
#tooltip .key { color: var(--accent); }
/* `.why` is why you *cannot*, and is meant to read as a problem. A plain
   explanation gets `.note`, or the tooltip alarms the player over nothing. */
#tooltip .why { color: #ffb0a0; }
#tooltip .note { color: var(--dim); }

/* --- drag box ------------------------------------------------------------ */

#dragbox {
  position: absolute;
  border: 1px solid var(--accent);
  background: rgba(232, 165, 60, 0.12);
  display: none;
  pointer-events: none;
}

/* --- outcome ------------------------------------------------------------- */

/* Экран исхода. Картинка ставится фоном из кода, когда она есть; затемнение
   лежит поверх неё отдельным слоем, а не примешано к цвету фона — иначе с
   появлением картинки текст оказался бы на светлом и пропал. */
#outcome {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 10px;
  /* Полупрозрачная вуаль, а не заслонка: поле боя под ней обязано просвечивать,
     иначе «продолжить смотреть» нечего и предлагать. */
  background-color: rgba(4, 6, 10, 0.55);
  color: var(--ink);
}
#outcome.on { display: flex; }

/* Карточка, а не занавес: под ней должно быть видно поле боя, ради которого
   человек и остаётся смотреть. Фон исхода сместился на неё же — картинка
   художника теперь рамка объявления, а не заслонка на весь экран. */
#outcome .card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(10px * var(--s));
  padding: calc(26px * var(--s)) calc(40px * var(--s));
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: calc(var(--r) * 2);
  background: rgba(6, 9, 14, 0.92);
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.6);
  pointer-events: auto;
}
#outcome h1 { font-size: calc(34px * var(--s)); font-weight: 200; letter-spacing: calc(8px * var(--s)); }
#outcome p { color: var(--dim); font-size: var(--fs-sm); letter-spacing: 2px; }
#outcome .acts { display: flex; gap: calc(10px * var(--s)); margin-top: calc(8px * var(--s)); }
#outcome .obtn {
  padding: calc(9px * var(--s)) calc(18px * var(--s));
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: var(--r);
  background: var(--panel);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--fs-sm);
  letter-spacing: 1px;
  cursor: pointer;
}
#outcome .obtn:hover { border-color: var(--accent); }
#outcome .obtn.primary { border-color: var(--accent); color: var(--accent); }

/* --- системные кнопки и отладочные тумблеры ------------------------------- */

/* Правый верхний угол — единственный, где ничего нет: ресурсы по центру,
   подсказка слева, панели внизу. Тумблеры отладки видны всегда, потому что
   сейчас время отладки; уйдут вместе с ним, одним куском разметки и одним
   методом Hud. Ряд системных кнопок (звук, настройки) — над ними и своим
   рядом, потому что переживёт их. */
#cheats {
  position: absolute;
  top: calc(10px * var(--s));
  right: calc(10px * var(--s));
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: calc(5px * var(--s));
  pointer-events: auto;
}

/* Звук и шестерёнка — в одну строку: обе короткие, обе нужны часто, и в
   столбик они съедали бы высоту у того, что под ними. */
.sysrow {
  display: flex;
  gap: calc(5px * var(--s));
}

.sysbtn {
  display: flex;
  align-items: center;
  gap: calc(5px * var(--s));
  padding: calc(5px * var(--s)) calc(10px * var(--s));
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--r);
  background: var(--panel);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--fs-sm);
  letter-spacing: 0.3px;
  white-space: nowrap;
  cursor: pointer;
}
.sysbtn:hover { border-color: var(--accent); }
.sysbtn.gear { font-size: calc(13px * var(--s)); line-height: 1; padding-inline: calc(9px * var(--s)); }

/* Полный экран включён — состояние спокойное, поэтому и знак спокойный:
   подсветка рамкой, без тревожного цвета. Это не «что-то не так», это
   «сейчас так». */
.sysbtn.full.on { border-color: var(--accent); color: var(--accent); }

/* Тишина — состояние тревожное и должна выглядеть тревожно: игрок, который
   не понимает, почему игра молчит, ищет причину в игре, а не в своей кнопке.
   Красный, значок и подпись — три независимых знака одного и того же. */
.sysbtn.muted {
  border-color: rgba(200, 70, 60, 0.85);
  background: rgba(200, 70, 60, 0.22);
  color: #ffb3ab;
}

.cheat {
  display: flex;
  align-items: center;
  gap: calc(6px * var(--s));
  padding: calc(5px * var(--s)) calc(11px * var(--s));
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--r);
  background: var(--panel);
  color: var(--dim);
  font-family: inherit;
  font-size: var(--fs-sm);
  letter-spacing: 0.3px;
  white-space: nowrap;
  cursor: pointer;
}
.cheat:hover:not(:disabled) { border-color: var(--accent); color: var(--ink); }
.cheat:disabled { opacity: 0.4; cursor: default; }

/* Состояние — не только цветом: лампа слева видна и на снимке, и тому, кто
   не различает янтарь на сером. */
.cheat::before {
  content: '';
  flex: 0 0 auto;
  width: calc(7px * var(--s));
  height: calc(7px * var(--s));
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  border: 1px solid rgba(255, 255, 255, 0.22);
}
.cheat.on {
  border-color: var(--accent);
  background: rgba(232, 165, 60, 0.20);
  color: #ffdca4;
}
.cheat.on::before {
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 0 calc(6px * var(--s)) rgba(232, 165, 60, 0.9);
}

/* --- флажки цели ---------------------------------------------------------- */

/* Метка стоит там, куда идёт выделенное, ровно пока приказ жив. Кольцо
   приказа отвечает на щелчок и гаснет за полсекунды; этот флажок отвечает на
   вопрос «а куда они, собственно, идут», и потому живёт столько же, сколько
   сам приказ.

   Слой сквозной: щелчок по флажку должен попадать в землю под ним, иначе
   метка о приказе начнёт мешать отдавать приказы. */
#order-flags {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}

.oflag {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  display: none;
  will-change: transform;
}
/* Древко от точки вверх, полотнище на верхушке. Нижний конец древка — и есть
   отмеченное место, поэтому вся конструкция растёт ВВЕРХ от начала координат
   элемента: так метка не съезжает с точки при смене размера. */
.oflag .pole {
  position: absolute;
  left: -1px;
  bottom: 0;
  width: calc(2px * var(--s));
  height: calc(18px * var(--s));
  background: var(--flag, #7ce87c);
  box-shadow: 0 0 calc(3px * var(--s)) rgba(0, 0, 0, 0.6);
}
.oflag .cloth {
  position: absolute;
  left: calc(1px * var(--s));
  bottom: calc(11px * var(--s));
  width: 0;
  height: 0;
  border-left: calc(11px * var(--s)) solid var(--flag, #7ce87c);
  border-top: calc(3.5px * var(--s)) solid transparent;
  border-bottom: calc(3.5px * var(--s)) solid transparent;
  filter: drop-shadow(0 0 calc(2px * var(--s)) rgba(0, 0, 0, 0.55));
}

/* --- hints --------------------------------------------------------------- */

/* Below the resource bar, not beside it. Centred at the top and pinned to the
   left, the two used to overlap the moment the window got narrow — which is
   exactly the window where a player most needs to read the controls. */
#hint {
  position: absolute;
  left: calc(12px * var(--s));
  top: calc(56px * var(--s));
  max-width: calc(300px * var(--s));
  padding: calc(8px * var(--s)) calc(12px * var(--s));
  color: var(--dim);
  font-size: var(--fs-sm);
  line-height: 1.6;
}
#hint b { color: var(--ink); font-weight: 600; }
#hint.armed { color: var(--accent); }

/* Шпаргалка отсюда УШЛА — в панель выделения, где ей и место (см. CHEAT_SHEET
   в Hud.js). Плашка теперь появляется только со взведённым курсором и в
   остальное время не занимает поле боя вовсе. */
#hint.off { display: none; }

/* Сообщение о недокачанном. Красное и крупное намеренно: его задача — быть
   замеченным, а не вписаться. Заглушка, которая выглядит как результат, стоила
   владельцу получаса; надпись о ней имеет право выглядеть как поломка. */
.bl-trouble {
  position: relative;
  max-width: 520px;
  margin-top: 18px;
  padding: 16px 20px;
  border: 1px solid rgba(210, 80, 70, 0.8);
  border-radius: 6px;
  background: rgba(40, 12, 10, 0.9);
  color: #ffd7d2;
  font-size: 12px;
  line-height: 1.5;
  text-align: center;
}
.bl-trouble-head { font-size: 13px; letter-spacing: 3px; color: #ff9c92; margin-bottom: 8px; }
.bl-trouble-list { color: #c9a09a; font-size: 11px; }
.bl-trouble-go {
  margin-top: 12px;
  padding: 7px 16px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 4px;
  background: transparent;
  color: #ffd7d2;
  font-family: inherit;
  font-size: 12px;
  cursor: pointer;
}
.bl-trouble-go:hover { border-color: #ff9c92; }
