/* ==========================================================================
   Экран «Коллекция героев» — тёмный графит с золотом.
   Шрифты: Cinzel (заголовки/имена), Cormorant Garamond (текст/метаданные).
   Стили здесь намеренно изолированы под .collection-screen / .cg-*, чтобы
   не задевать остальные экраны на текущей фиолетовой теме (styles.css).
   ========================================================================== */

/* Переменные --cg-* переехали в :root (styles.css, Раздел 7): держать их
   на каждом экране-владельце оказалось ловушкой — модалка в document.body
   и экран отряда об это уже спотыкались. Здесь остаётся только оформление
   самих экранов. */
.collection-screen,
.squad-screen,
.combat-screen {
  font-family: "Cormorant Garamond", "Georgia", serif;
  color: var(--cg-text);
  background: radial-gradient(ellipse at top, #201c1f 0%, var(--cg-bg) 60%);
  border: 1px solid var(--cg-border);
  border-radius: 14px;
  padding: 22px 20px 28px;
}

.collection-screen *,
.squad-screen *,
.combat-screen *,
.cg-modal-overlay * {
  box-sizing: border-box;
}

/* Общие примитивы (заголовок, подзаголовок, разделитель, панель, кнопки)
   уехали в styles.css под именами .title / .subtitle / .divider / .panel /
   .btn — по одному имени на вещь. Здесь остаётся только то, что
   принадлежит конкретным экранам. */

.cg-panel__row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 24px;
  align-items: baseline;
  justify-content: space-between;
}

.cg-panel__stat {
  font-family: "Cinzel", serif;
  font-size: 15px;
  color: var(--cg-gold-bright);
}

.cg-panel__stat-label {
  font-family: "Cormorant Garamond", serif;
  font-style: italic;
  font-size: 13px;
  color: var(--cg-text-dim);
  margin-right: 6px;
}

.cg-panel__pity {
  font-family: "Cormorant Garamond", serif;
  font-size: 14px;
  color: var(--cg-text-dim);
  white-space: pre-line;
  margin-top: 8px;
}

/* Toolbar: search + element filters + sort */
.cg-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 18px;
}

.cg-search {
  flex: 1 1 220px;
  min-width: 180px;
  background: var(--cg-bg-panel);
  border: 1px solid var(--cg-border);
  border-radius: 999px;
  color: var(--cg-text);
  padding: 9px 16px;
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 14px;
}

.cg-search:focus {
  outline: none;
  border-color: var(--cg-gold-dim);
  box-shadow: 0 0 0 1px var(--cg-gold-dim);
}

.cg-search::placeholder {
  color: var(--cg-text-dim);
}

.cg-sort {
  background: var(--cg-bg-panel);
  border: 1px solid var(--cg-border);
  border-radius: 999px;
  color: var(--cg-text);
  padding: 9px 16px;
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 14px;
}

.cg-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.cg-chip {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.01em;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--cg-border);
  background: none;
  color: var(--cg-text-dim);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s, box-shadow 0.15s;
}

.cg-chip:hover {
  color: var(--cg-text);
  background: var(--cg-bg-card);
}

.cg-chip.is-active {
  color: #171217;
  border-color: var(--chip-color, var(--cg-gold));
  background: var(--chip-color, var(--cg-gold));
  box-shadow: 0 0 12px 1px var(--chip-color, var(--cg-gold));
}

/* Grid + cards */
.cg-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 20px;
}

.cg-card {
  position: relative;
  background: linear-gradient(165deg, var(--cg-bg-card), #161417 75%);
  border: 1px solid var(--cg-border);
  border-radius: 12px;
  overflow: hidden;
  cursor: pointer;
  transition: transform 0.25s ease, border-color 0.2s ease, box-shadow 0.25s ease;
  transform-style: preserve-3d;
  will-change: transform;
  --glow: var(--cg-el-nature);
}

.cg-card[data-element="fire"] { --glow: var(--cg-el-fire); }
.cg-card[data-element="water"] { --glow: var(--cg-el-water); }
.cg-card[data-element="nature"] { --glow: var(--cg-el-nature); }
.cg-card[data-element="air"] { --glow: var(--cg-el-air); }
.cg-card[data-element="metal"] { --glow: var(--cg-el-metal); }
.cg-card[data-element="light"] { --glow: var(--cg-el-light); }
.cg-card[data-element="dark"] { --glow: var(--cg-el-dark); }

/* Рамка и ореол — цвет редкости; --glow (стихия) остаётся у значка
   стихии и заглушки, чтобы обе подсказки жили одновременно. */
.cg-card {
  border-color: color-mix(in srgb, var(--rarity, var(--cg-border)) 45%, var(--cg-border));
}

.cg-card:hover {
  border-color: var(--rarity, var(--glow));
  box-shadow: 0 10px 28px -8px rgba(0, 0, 0, 0.65), 0 0 32px -4px var(--rarity, var(--glow));
}

/* Наклон карточки за курсором задаётся инлайн-стилем из JS
   (heroesCollection.js) — .cg-card:hover выше только красит рамку и
   свечение, transform ей больше не занимается, чтобы не спорить с JS. */

/* .cg-card__face — «лицевая сторона» карточки: пропорции 2:3,
   иллюстрация во весь кадр, плашка с именем поверх. С Раздела 7 её рисуют
   все три места — коллекция, каталог и призыв. Старая .cg-card__portrait
   (3:4 с текстом отдельным блоком снизу) удалена вместе с .cg-card__body
   и .cg-card__level: ими пользовался только призыв. */
.cg-card__face {
  position: relative;
  aspect-ratio: 2 / 3;
  overflow: hidden;
  background: var(--cg-bg-panel);
  border-radius: 12px;
}

.cg-card__face::before {
  content: "";
  position: absolute;
  inset: -20%;
  z-index: 0;
  background: radial-gradient(circle at 50% 35%, var(--glow) 0%, transparent 60%);
  opacity: 0.5;
  filter: blur(16px);
  animation: cg-glow-pulse 3.2s ease-in-out infinite;
  pointer-events: none;
}

.cg-card__face .cg-card__img {
  filter: brightness(0.82);
  transition: transform 0.25s ease, filter 0.25s ease;
}

.cg-card:hover .cg-card__face .cg-card__img {
  filter: brightness(1.05);
  transform: scale(1.06);
}

.cg-card__face .cg-card__placeholder {
  transition: transform 0.25s ease, filter 0.25s ease;
}

.cg-card:hover .cg-card__face .cg-card__placeholder {
  filter: brightness(1.15);
  transform: scale(1.03);
}

.cg-card__scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: linear-gradient(to top, rgba(8, 7, 9, 0.92) 0%, rgba(8, 7, 9, 0.6) 32%, transparent 62%);
  pointer-events: none;
}

.cg-card__plate {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  padding: 12px 14px 14px;
}

.cg-card__img {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: drop-shadow(0 0 10px var(--glow));
}

.cg-card__placeholder {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Cinzel", serif;
  font-size: 42px;
  font-weight: 700;
  color: var(--cg-text);
  background: linear-gradient(160deg, color-mix(in srgb, var(--glow) 65%, #17151a), color-mix(in srgb, var(--glow) 25%, #17151a) 85%);
  text-shadow: 0 0 14px var(--glow);
}

.cg-card__element-tag {
  position: absolute;
  z-index: 4;
  top: 8px;
  right: 8px;
  width: 26px;
  height: 26px;
  padding: 5px;
  box-sizing: border-box;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(16, 15, 17, 0.75);
  color: var(--glow);
  border: 1px solid var(--glow);
  box-shadow: 0 0 8px var(--glow);
}

.cg-card__element-tag svg {
  display: block;
}

.cg-card__frame-corner {
  position: absolute;
  z-index: 4;
  width: 16px;
  height: 16px;
  border: 1px solid var(--cg-gold-dim);
  opacity: 0.8;
  pointer-events: none;
}

.cg-card__frame-corner--tl { top: 6px; left: 6px; border-right: none; border-bottom: none; }
.cg-card__frame-corner--br { bottom: 6px; right: 6px; border-left: none; border-top: none; }

/* Итог призыва — подпись под карточкой: новый герой, душа или эссенция. */
.cg-card__result {
  padding: 8px 10px 10px;
  border-top: 1px solid var(--cg-border-soft);
  text-align: center;
}

.cg-card__name {
  font-family: "Cinzel", serif;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--cg-gold-bright);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cg-card__stars {
  color: var(--rarity, var(--cg-gold));
  font-size: 12px;
  letter-spacing: 1px;
  margin: 2px 0 6px;
  text-shadow: 0 0 7px color-mix(in srgb, var(--rarity, var(--cg-gold)) 60%, transparent);
}

.cg-card__role {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11px;
  color: var(--cg-text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cg-bar {
  height: 7px;
  border-radius: 999px;
  background: #0d0c0e;
  border: 1px solid var(--cg-border);
  overflow: hidden;
}

.cg-bar__fill {
  height: 100%;
  border-radius: 999px;
  transition: width 0.2s;
}

.cg-bar__fill--hp-high { background: linear-gradient(90deg, #3f8f5a, #58c97a); }
.cg-bar__fill--hp-mid { background: linear-gradient(90deg, var(--cg-gold-dim), var(--cg-gold)); }
.cg-bar__fill--hp-low { background: linear-gradient(90deg, #8f3f3f, #d15656); }

.cg-status {
  display: inline-block;
  margin-top: 6px;
  font-family: "Cormorant Garamond", serif;
  font-size: 11px;
  letter-spacing: 0.03em;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--cg-border);
  color: var(--cg-text-dim);
}

.cg-status--healthy { color: #7fd99a; border-color: #3f8f5a; }
.cg-status--wounded { color: var(--cg-gold-bright); border-color: var(--cg-gold-dim); }
.cg-status--unconscious { color: #d17a7a; border-color: #8f3f3f; }

@keyframes cg-glow-pulse {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 0.75; }
}

@media (prefers-reduced-motion: reduce) {
  .cg-card__face::before {
    animation: none;
  }
}

/* ---- Detail modal ------------------------------------------------------ */
.cg-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(6, 5, 6, 0.62);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 300;
  padding: 16px;
  overflow: hidden;
}

/* Иллюстрация героя за панелью: сильное размытие + затемнение, чтобы
   читалась как атмосферный фон, а не как вторая картинка. inset:-8%
   компенсирует «съедаемые» блюром края, иначе по периметру видны
   полупрозрачные полосы. */
.cg-modal-overlay__art {
  position: absolute;
  inset: -8%;
  background-size: cover;
  background-position: center 22%;
  filter: blur(38px) saturate(1.1) brightness(0.42);
  opacity: 0.85;
  transform: scale(1.08);
  pointer-events: none;
}

.cg-modal-overlay__art::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at center, rgba(6, 5, 6, 0.35) 0%, rgba(6, 5, 6, 0.88) 78%);
}

.cg-modal {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 880px;
  max-height: 90vh;
  overflow-y: auto;
  background: linear-gradient(165deg, rgba(31, 28, 34, 0.82), rgba(12, 11, 14, 0.88));
  -webkit-backdrop-filter: blur(18px) saturate(1.15);
  backdrop-filter: blur(18px) saturate(1.15);
  border: 1px solid color-mix(in srgb, var(--rarity, var(--cg-gold)) 35%, var(--cg-border));
  border-radius: 16px;
  padding: 26px 28px 28px;
  box-shadow: 0 24px 70px -20px rgba(0, 0, 0, 0.85), 0 0 46px -14px var(--rarity, var(--cg-gold));
  font-family: "Cormorant Garamond", serif;
  color: var(--cg-text);
  animation: cg-modal-in 0.22s ease-out;
}

@keyframes cg-modal-in {
  from { opacity: 0; transform: translateY(10px) scale(0.985); }
  to { opacity: 1; transform: none; }
}

.cg-modal__close {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 2;
  background: rgba(12, 11, 14, 0.6);
  border: 1px solid var(--cg-border);
  color: var(--cg-text-dim);
  border-radius: 50%;
  width: 30px;
  height: 30px;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  transition: color 0.15s, border-color 0.15s, box-shadow 0.15s;
}

.cg-modal__close:hover {
  color: var(--cg-gold-bright);
  border-color: var(--cg-gold-dim);
  box-shadow: 0 0 12px -2px var(--cg-gold);
}

/* Слева карточка, справа данные. minmax(0,1fr) у правой колонки — иначе
   длинное описание растягивает грид и ломает пропорции. */
.cg-modal__grid {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  gap: 26px;
  align-items: start;
}

.cg-modal__left {
  position: sticky;
  top: 0;
}

/* Та же лицевая сторона, что в сетке, но без наклона за курсором —
   в модалке он только мешает читать. */
.cg-detail-card {
  position: relative;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--rarity, var(--cg-gold-dim));
  box-shadow: 0 0 34px -10px var(--rarity, var(--cg-gold));
}

.cg-detail-card .cg-card__img {
  filter: brightness(0.95);
}

.cg-modal__status-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-bottom: 10px;
}

.cg-modal__name {
  font-family: "Cinzel", serif;
  font-size: 22px;
  font-weight: 700;
  color: var(--cg-gold-bright, var(--gold-bright));
  margin: 0 0 4px;
}

.cg-modal__role {
  font-style: italic;
  color: var(--cg-text-dim, var(--muted));
  font-size: 15px;
}

.cg-modal__section-title {
  font-family: "Cinzel", serif;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--cg-gold-dim, var(--gold-dim));
  margin: 16px 0 8px;
}

.cg-modal__desc {
  font-style: italic;
  color: var(--cg-text-dim, var(--muted));
  line-height: 1.5;
  font-size: 16px;
}

.cg-xp-label {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  color: var(--cg-text-dim, var(--muted));
  margin-top: 4px;
}

/* ---- Производные боевые значения (крупные числа) ----------------------- */
.cg-derived-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
  gap: 10px;
}

.cg-derived {
  background: rgba(10, 9, 12, 0.5);
  border: 1px solid var(--cg-border);
  border-radius: 10px;
  padding: 10px 12px 9px;
  text-align: center;
}

.cg-derived__value {
  font-family: "Cinzel", serif;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.15;
  background: linear-gradient(180deg, var(--cg-gold-bright), var(--cg-gold) 70%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.cg-derived__label {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11px;
  letter-spacing: 0.02em;
  color: var(--cg-text-dim);
  margin-top: 3px;
}

/* ---- Полоски характеристик --------------------------------------------- */
.cg-statbar-group {
  display: grid;
  gap: 9px;
}

.cg-statbar__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 14px;
  margin-bottom: 3px;
}

.cg-statbar__label {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 12px;
  color: var(--cg-text-dim);
}

.cg-statbar__value {
  font-family: "Cinzel", serif;
  font-size: 14px;
  font-weight: 600;
  color: var(--cg-gold-bright);
}

.cg-statbar__track {
  height: 8px;
  border-radius: 999px;
  background: #0d0c0e;
  border: 1px solid var(--cg-border);
  overflow: hidden;
}

/* Ширину задаёт JS (heroesCollection.js): элемент вставляется нулевым и
   получает целевое значение на следующем кадре — этот переход и есть
   «наливание». transition-delay ставится там же, лесенкой по индексу. */
.cg-statbar__fill {
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--cg-gold-dim), var(--cg-gold) 55%, var(--cg-gold-bright));
  box-shadow: 0 0 10px -2px var(--cg-gold);
  transition: width 0.75s cubic-bezier(0.22, 0.68, 0.24, 1);
}

@media (prefers-reduced-motion: reduce) {
  .cg-statbar__fill {
    transition: none;
  }
}

@media (max-width: 640px) {
  .cg-grid {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 14px;
  }

  /* На телефоне панель — «шторка» снизу: прижимаем к нижнему краю,
     убираем внешние отступы и скругляем только верх. */
  .cg-modal-overlay {
    align-items: flex-end;
    padding: 0;
  }

  .cg-modal {
    max-width: none;
    max-height: 92vh;
    border-radius: 18px 18px 0 0;
    border-bottom: none;
    padding: 22px 18px calc(22px + env(safe-area-inset-bottom, 0px));
    animation: cg-sheet-up 0.26s ease-out;
  }

  .cg-modal__grid {
    grid-template-columns: 1fr;
    gap: 18px;
  }

  /* Карточка не липнет и не занимает весь экран: на узкой ширине она
     всего лишь заставка сверху, дальше сразу данные. */
  .cg-modal__left {
    position: static;
    max-width: 190px;
    margin: 0 auto;
  }

  .cg-derived-grid {
    grid-template-columns: repeat(auto-fit, minmax(92px, 1fr));
  }
}

@keyframes cg-sheet-up {
  from { transform: translateY(100%); }
  to { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .cg-modal {
    animation: none;
  }
}

/* ==========================================================================
   Экран «Отряды» (.sq-*)
   Здесь только то, что принадлежит самому экрану: доска, ячейки, схемы
   расстановок. Заголовок, кнопки, поля, пустые состояния — общие
   (.title / .btn / .field / .empty-state в styles.css).
   ========================================================================== */

.sq-section-title {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: "Cinzel", serif;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--cg-gold-dim);
  margin: 22px 0 10px;
}

.sq-name-input {
  max-width: 340px;
}

.sq-save-row {
  display: flex;
  justify-content: flex-end;
  margin-top: 6px;
}

/* ---- Список отрядов ----------------------------------------------------- */
.sq-list {
  display: grid;
  gap: 12px;
}

.sq-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  background: var(--cg-bg-panel);
  border: 1px solid var(--cg-border);
  border-radius: 12px;
  padding: 14px 16px;
  transition: border-color 0.2s, box-shadow 0.2s;
}

.sq-row:hover {
  border-color: var(--cg-gold-dim);
}

.sq-row.is-active {
  border-color: var(--cg-gold-dim);
  box-shadow: inset 3px 0 0 var(--cg-gold);
}

.sq-row__name-line {
  display: flex;
  align-items: center;
  gap: 10px;
}

.sq-row__name {
  font-family: "Cinzel", serif;
  font-size: 17px;
  font-weight: 600;
  color: var(--cg-gold-bright);
}

.sq-row__badge {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11px;
  letter-spacing: 0.03em;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--cg-gold);
  color: #171217;
  font-weight: 600;
}

.sq-row__meta {
  font-size: 14px;
  color: var(--cg-text-dim);
  margin-top: 3px;
}

.sq-row__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* ---- Карточки расстановки ----------------------------------------------- */
.sq-formations {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
}

.sq-formation {
  background: var(--cg-bg-panel);
  border: 1px solid var(--cg-border);
  border-radius: 12px;
  padding: 14px 12px 12px;
  cursor: pointer;
  color: var(--cg-text);
  font-family: inherit;
  text-align: center;
  transition: border-color 0.2s, box-shadow 0.2s, transform 0.2s;
}

.sq-formation:hover {
  border-color: var(--cg-gold-dim);
  transform: translateY(-2px);
}

.sq-formation.is-active {
  border-color: var(--cg-gold);
  box-shadow: 0 0 18px -6px var(--cg-gold), inset 0 0 0 1px var(--cg-gold-dim);
}

.sq-formation__title {
  font-family: "Cinzel", serif;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--cg-gold-bright);
  margin-bottom: 10px;
}

.sq-formation__caption {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 10.5px;
  line-height: 1.35;
  color: var(--cg-text-dim);
  margin-top: 10px;
}

/* Схема из точек: три линии сверху вниз — передняя, средняя, задняя. */
.sq-diagram {
  display: grid;
  gap: 6px;
  padding: 8px 0;
}

.sq-diagram__line {
  display: grid;
  grid-template-columns: 14px 1fr;
  align-items: center;
  gap: 8px;
}

.sq-diagram__line-label {
  font-family: "Cinzel", serif;
  font-size: 10px;
  color: var(--cg-gold-dim);
}

.sq-diagram__dots {
  display: flex;
  gap: 6px;
  justify-content: center;
  min-height: 12px;
  align-items: center;
  border-bottom: 1px dashed var(--cg-border);
  padding-bottom: 5px;
}

.sq-diagram__dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--cg-text-dim);
  transition: background 0.2s, box-shadow 0.2s;
}

.sq-formation.is-active .sq-diagram__dot {
  background: var(--cg-gold);
  box-shadow: 0 0 8px var(--cg-gold);
}

/* ---- Доска отряда ------------------------------------------------------- */
.sq-counter {
  font-family: "Cinzel", serif;
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--cg-text-dim);
  border: 1px solid var(--cg-border);
  border-radius: 999px;
  padding: 2px 12px;
  text-transform: none;
}

.sq-counter.is-full {
  color: var(--cg-gold-bright);
  border-color: var(--cg-gold-dim);
}

.sq-counter.is-shaking {
  animation: sq-shake 0.36s ease;
}

@keyframes sq-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-5px); }
  45% { transform: translateX(4px); }
  70% { transform: translateX(-2px); }
}

.sq-board {
  display: grid;
  gap: 10px;
  background: rgba(10, 9, 12, 0.45);
  border: 1px solid var(--cg-border);
  border-radius: 12px;
  padding: 14px;
}

.sq-line {
  display: grid;
  grid-template-columns: 120px 1fr;
  align-items: center;
  gap: 12px;
}

.sq-line__label {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--cg-text-dim);
  text-align: right;
}

.sq-line__cells {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.sq-cell {
  position: relative;
  width: 78px;
  height: 104px;
  border-radius: 10px;
  cursor: pointer;
  padding: 0;
  overflow: hidden;
  font-family: inherit;
  transition: border-color 0.2s, box-shadow 0.2s, transform 0.2s;
}

.sq-cell--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--cg-border);
  background: rgba(255, 255, 255, 0.015);
  color: var(--cg-text-dim);
  font-size: 26px;
  line-height: 1;
}

.sq-cell--empty:hover {
  border-color: var(--cg-gold-dim);
  color: var(--cg-gold-bright);
}

.sq-cell--filled {
  border: 1px solid var(--rarity, var(--cg-gold-dim));
  background: var(--cg-bg-panel);
  box-shadow: 0 0 14px -6px var(--rarity, var(--cg-gold));
}

.sq-cell--filled:hover {
  transform: translateY(-2px);
  box-shadow: 0 0 20px -6px var(--rarity, var(--cg-gold));
}

/* Выбранная для обмена ячейка — золотом, а не цветом стихии: это
   состояние интерфейса, а не свойство героя. */
.sq-cell--filled.is-picked {
  border-color: var(--cg-gold-bright);
  box-shadow: 0 0 0 2px var(--cg-gold), 0 0 22px -4px var(--cg-gold);
  transform: translateY(-2px);
}

.sq-cell__img,
.sq-cell__placeholder {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.sq-cell__placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Cinzel", serif;
  font-size: 26px;
  font-weight: 700;
  color: var(--cg-text);
  background: linear-gradient(160deg, color-mix(in srgb, var(--glow) 60%, #17151a), color-mix(in srgb, var(--glow) 20%, #17151a) 85%);
}

.sq-cell__index {
  position: absolute;
  top: 4px;
  left: 4px;
  min-width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--cg-gold);
  color: #171217;
  font-family: "Cinzel", serif;
  font-size: 11px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.sq-cell__name {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 12px 5px 4px;
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 10px;
  color: var(--cg-text);
  background: linear-gradient(to top, rgba(8, 7, 9, 0.95), transparent);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- Сетка выбора героев ------------------------------------------------ */
.sq-picker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 14px;
  border-radius: 12px;
  transition: box-shadow 0.3s;
}

/* Короткая подсветка сетки, когда её позвали кнопкой «+» с доски. */
.sq-picker-grid.is-calling {
  box-shadow: 0 0 0 2px var(--cg-gold-dim), 0 0 26px -8px var(--cg-gold);
}

.sq-pick {
  position: relative;
}

.sq-pick.is-selected {
  border-color: var(--cg-gold);
  box-shadow: 0 0 0 2px var(--cg-gold), 0 0 24px -6px var(--cg-gold);
}

.sq-pick__index {
  position: absolute;
  z-index: 5;
  top: 6px;
  left: 6px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: linear-gradient(180deg, var(--cg-gold-bright), var(--cg-gold) 70%);
  color: #171217;
  font-family: "Cinzel", serif;
  font-size: 13px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 12px -2px var(--cg-gold);
}

@media (prefers-reduced-motion: reduce) {
  .sq-counter.is-shaking {
    animation: none;
  }

  .sq-formation,
  .sq-cell {
    transition: none;
  }
}

@media (max-width: 640px) {
  .sq-line {
    grid-template-columns: 1fr;
    gap: 5px;
  }

  .sq-line__label {
    text-align: left;
  }

  .sq-picker-grid {
    grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
    gap: 10px;
  }

  .sq-row__actions {
    width: 100%;
  }
}

/* ==========================================================================
   Призыв: экран (.sm-screen …) и сцена анимации (.sm-overlay …)
   Цвет уровня события приходит из JS переменной --tier, цвет стихии
   героя — --glow, цвет редкости конкретной карточки — --rarity.
   ========================================================================== */

.sm-panel {
  display: grid;
  gap: 20px;
  justify-items: center;
  padding: 8px 0 4px;
}

.sm-crystals {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.sm-crystals__value {
  font-family: "Cinzel", serif;
  font-size: 40px;
  font-weight: 700;
  background: linear-gradient(180deg, var(--gold-bright), var(--gold) 70%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.sm-crystals__label {
  font-family: "Cormorant Garamond", serif;
  font-style: italic;
  font-size: 15px;
  color: var(--cg-text-dim);
}

.sm-pity {
  width: 100%;
  max-width: 420px;
}

.sm-pity__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 12px;
  color: var(--cg-text-dim);
  margin-bottom: 5px;
}

.sm-pity__count {
  color: var(--cg-gold-bright);
}

/* Мягкий гарант уже включился — полоса перестаёт быть просто счётчиком. */
.bar__fill.is-soft {
  background: linear-gradient(90deg, var(--gold), var(--gold-bright));
  box-shadow: 0 0 12px -2px var(--gold);
}

.sm-pull-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  width: 100%;
  max-width: 560px;
}

.sm-pull {
  display: grid;
  gap: 3px;
  justify-items: center;
  padding: 16px 14px;
  border-radius: 12px;
  border: 1px solid var(--cg-gold-dim);
  background: linear-gradient(165deg, var(--cg-bg-card), #161417 78%);
  color: var(--cg-text);
  font-family: inherit;
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s;
}

.sm-pull:hover:not(:disabled) {
  border-color: var(--cg-gold);
  box-shadow: 0 0 20px -6px var(--cg-gold);
  transform: translateY(-2px);
}

.sm-pull--hero {
  border-color: var(--cg-gold);
  box-shadow: inset 0 0 24px -14px var(--cg-gold);
}

.sm-pull:disabled {
  opacity: 0.42;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
  border-color: var(--cg-border);
}

.sm-pull__label {
  font-family: "Cinzel", serif;
  font-size: 17px;
  font-weight: 600;
  color: var(--cg-gold-bright);
}

.sm-pull__cost {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 12px;
  color: var(--cg-text);
}

.sm-pull__note {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11px;
  color: var(--cg-text-dim);
  text-align: center;
}

/* ВРЕМЕННО (Раздел 6): панель предпросмотра анимации. Удаляется вместе с
   devSummonPreview.js. */
.sm-devtools {
  margin-top: 22px;
  padding: 12px 14px;
  border: 1px dashed var(--cg-border);
  border-radius: 10px;
  width: 100%;
  max-width: 560px;
}

.sm-devtools__title {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11px;
  color: var(--cg-text-dim);
  margin-bottom: 8px;
}

.sm-devtools__row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.sm-devtools__row .btn {
  padding: 6px 12px;
  font-size: 12px;
  border-color: var(--cg-border);
}

/* ==========================================================================
   Магазин (.shop-*) — инструмент разработки, а не игровая механика.
   Пометка о тестовом режиме сделана нарочито заметной: через месяц никто
   не должен принять эти цены за настоящую экономику.
   ========================================================================== */

.shop-notice {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
  padding: 12px 16px;
  border: 1px solid var(--cg-gold);
  border-left-width: 4px;
  border-radius: 10px;
  background: linear-gradient(90deg, rgba(201, 163, 92, 0.16), rgba(201, 163, 92, 0.05));
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 13px;
  color: var(--cg-gold-bright);
  letter-spacing: 0.01em;
}

.shop-notice__mark {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid var(--cg-gold);
  font-family: "Cinzel", serif;
  font-weight: 700;
}

.shop-wallet {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 12px;
  margin-bottom: 20px;
}

.shop-wallet__item {
  display: grid;
  justify-items: center;
  gap: 2px;
  padding: 12px 10px;
  border: 1px solid var(--cg-border);
  border-radius: 10px;
  background: var(--cg-bg-panel);
}

.shop-wallet__value {
  font-family: "Cinzel", serif;
  font-size: 24px;
  font-weight: 700;
  background: linear-gradient(180deg, var(--cg-gold-bright), var(--cg-gold) 70%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.shop-wallet__label {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11px;
  color: var(--cg-text-dim);
}

.shop-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 14px;
}

.shop-card {
  display: grid;
  gap: 8px;
  justify-items: center;
  padding: 18px 16px;
  border: 1px solid var(--cg-gold-dim);
  border-radius: 12px;
  background: linear-gradient(165deg, var(--cg-bg-card), #161417 78%);
  text-align: center;
}

.shop-card.is-blocked {
  border-color: var(--cg-border);
  opacity: 0.7;
}

.shop-card__title {
  font-family: "Cinzel", serif;
  font-size: 18px;
  font-weight: 600;
  color: var(--cg-gold-bright);
}

.shop-card__note {
  font-family: "Cormorant Garamond", serif;
  font-style: italic;
  font-size: 15px;
  color: var(--cg-text-dim);
  min-height: 22px;
}

.shop-card__buy {
  margin-top: 4px;
  width: 100%;
}

@media (max-width: 640px) {
  .shop-grid {
    grid-template-columns: 1fr;
  }

  .shop-notice {
    font-size: 12px;
    padding: 10px 12px;
  }
}

/* ---- Сцена -------------------------------------------------------------- */

.sm-overlay {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  padding: 20px 16px;
  background: rgba(4, 4, 6, 0);
  transition: background 0.4s ease;
  overflow-y: auto;
}

.sm-overlay.is-dark {
  background: rgba(4, 4, 6, 0.93);
}

/* В финале кнопки «Пропустить» уже нет, поэтому верхний отступ под неё не
   нужен — он же и выталкивал сетку за экран. */
.sm-overlay.is-final {
  background: rgba(4, 4, 6, 0.96);
  justify-content: center;
  padding-top: 16px;
  gap: 12px;
}

.sm-overlay.is-final .sm-stage {
  gap: 10px;
}

.sm-canvas {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* Вспышка — отдельный слой поверх частиц, чтобы гаснуть независимо.
   Длительность приходит из JS переменной --flash-ms: у перламутра она
   заметно дольше, и держать её в двух местах значило бы рассинхрон. */
.sm-flash {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  --flash-ms: 340ms;
  background: radial-gradient(circle at center, #fff 0%, var(--tier) 28%, transparent 72%);
}

.sm-flash.is-firing {
  animation: sm-flash var(--flash-ms) ease-out;
}

/* Расходящиеся лучи — только для 5★. Конический градиент с
   прозрачными секторами даёт лучи без единой картинки. */
.sm-flash.is-rays::after {
  content: "";
  position: absolute;
  inset: -40%;
  background: conic-gradient(
    from 0deg,
    transparent 0deg 8deg,
    rgba(255, 255, 255, 0.55) 9deg 11deg,
    transparent 12deg 30deg,
    rgba(240, 209, 144, 0.5) 31deg 33deg,
    transparent 34deg 60deg,
    rgba(217, 212, 242, 0.45) 61deg 63deg,
    transparent 64deg 90deg
  );
  animation: sm-rays var(--flash-ms) ease-out;
  mix-blend-mode: screen;
}

@keyframes sm-flash {
  0% { opacity: 0; transform: scale(0.6); }
  22% { opacity: 1; transform: scale(1.05); }
  100% { opacity: 0; transform: scale(1.25); }
}

@keyframes sm-rays {
  0% { opacity: 0; transform: rotate(0deg) scale(0.5); }
  30% { opacity: 0.9; }
  100% { opacity: 0; transform: rotate(34deg) scale(1.5); }
}

/* Ударная волна кульминации: расходящееся кольцо поверх всей сцены. */
.sm-overlay.is-shockwave::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 40px;
  height: 40px;
  margin: -20px 0 0 -20px;
  border-radius: 50%;
  border: 2px solid rgba(255, 248, 240, 0.85);
  box-shadow: 0 0 40px 10px rgba(240, 209, 144, 0.35);
  pointer-events: none;
  animation: sm-shockwave 0.9s cubic-bezier(0.16, 0.75, 0.3, 1);
}

@keyframes sm-shockwave {
  0% { transform: scale(0.2); opacity: 0; border-width: 3px; }
  15% { opacity: 1; }
  100% { transform: scale(34); opacity: 0; border-width: 0.5px; }
}

.sm-stage {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 900px;
}

.sm-controls {
  position: relative;
  z-index: 3;
  display: flex;
  gap: 10px;
}

/* «Пропустить» видна с первого кадра — сотый призыв не должен смотреть
   всю сцену целиком. */
.sm-skip {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 5;
}

/* ---- Карточка в сцене --------------------------------------------------- */

/* width:100% обязателен. Сетка — flex-элемент в колонке .sm-stage с
   align-items:center, из-за чего её ширина схлопывается до содержимого;
   при неопределённой ширине repeat(auto-fit, …) сваливается в одну
   колонку — именно так десятка и выкладывалась столбиком. */
.sm-grid {
  display: grid;
  gap: 14px;
  width: 100%;
  justify-content: center;
}

/* Одиночный призыв — одна крупная карточка. Селектор с :not обязателен:
   у .sm-grid и .sm-grid--many одинаковая специфичность, и правило для
   одной карточки, оказавшись ниже по файлу, перебивало число колонок у
   десятки — из-за этого сетка на телефоне и схлопывалась в столбик. */
.sm-grid:not(.sm-grid--many) {
  grid-template-columns: minmax(0, 210px);
}

/* Десятка должна помещаться в экран целиком, поэтому размер карточки
   ограничен не шириной колонки, а высотой окна: строки карточек 2:3 плюс
   подписи обязаны уложиться в один экран. Число колонок задаётся точками
   останова ниже, число строк считается от него.
   clamp снизу не даёт карточкам превратиться в марки на низких экранах —
   тогда лучше короткая прокрутка, чем нечитаемая сетка. */
.sm-grid--many {
  --sm-cols: 5;
  --sm-rows: 2;
  --sm-gap: 10px;
  --sm-labels: 62px; /* имя + звёзды + плашка под карточкой */
  --sm-chrome: 150px; /* отступы оверлея, итоговая строка, «Продолжить» */
  --sm-vh: 100vh;
  --sm-card: clamp(
    64px,
    calc((var(--sm-vh) - var(--sm-chrome) - var(--sm-rows) * var(--sm-labels)) / var(--sm-rows) / 1.5),
    132px
  );
  gap: var(--sm-gap);
  grid-template-columns: repeat(var(--sm-cols), minmax(0, 1fr));
  max-width: calc(var(--sm-cols) * var(--sm-card) + (var(--sm-cols) - 1) * var(--sm-gap));
}

/* dvh учитывает свёрнутую адресную строку на телефоне; vh выше остаётся
   запасным вариантом для старых браузеров. */
@supports (height: 100dvh) {
  .sm-grid--many {
    --sm-vh: 100dvh;
  }
}

/* Компактные подписи: на мелкой карточке остаются имя, звёзды и короткая
   плашка, стихия с ролью уходят в подсказку при наведении (title). */
.sm-grid--many .sm-card__name {
  font-size: 12px;
  margin-top: 4px;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sm-grid--many .sm-card__stars {
  font-size: 11px;
  letter-spacing: 1px;
}

.sm-grid--many .sm-card__meta {
  display: none;
}

.sm-grid--many .sm-plaque {
  font-size: 10px;
  padding: 2px 7px;
  margin-top: 2px;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sm-plaque__short {
  display: none;
}

@media (max-width: 899px) {
  .sm-grid--many {
    --sm-cols: 4;
    --sm-rows: 3;
  }
}

@media (max-width: 599px) {
  .sm-grid--many {
    --sm-cols: 3;
    --sm-rows: 4;
  }
}

.sm-card {
  display: grid;
  gap: 4px;
  justify-items: center;
  opacity: 0;
  transform: scale(0.72);
}

.sm-card.is-revealed {
  animation: sm-card-in 0.8s cubic-bezier(0.18, 0.9, 0.28, 1.08) forwards;
}

@keyframes sm-card-in {
  0% { opacity: 0; transform: scale(0.72) rotate(-4deg); }
  55% { opacity: 1; transform: scale(1.06) rotate(2deg); }
  78% { transform: scale(0.98) rotate(-1deg); }
  100% { opacity: 1; transform: scale(1) rotate(0deg); }
}

/* Иллюстрация — главное, эффект — обрамление. Поверх арта не лежит
   ничего: свечение ушло во внешнюю тень, inset-подсветку убрал, рамка
   тонкая по краю. */
.sm-card__frame {
  position: relative;
  width: 100%;
  aspect-ratio: 2 / 3;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--rarity, var(--glow));
  box-shadow: 0 0 34px -8px var(--rarity, var(--glow));
}

.sm-card__img,
.sm-card__placeholder {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.sm-card__placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Cinzel", serif;
  font-size: 40px;
  font-weight: 700;
  color: var(--cg-text);
  background: linear-gradient(160deg, color-mix(in srgb, var(--glow) 60%, #17151a), #14121a 85%);
}

.sm-card__name {
  font-family: "Cinzel", serif;
  font-size: 15px;
  font-weight: 600;
  color: var(--cg-gold-bright);
  margin-top: 6px;
  text-align: center;
}

.sm-card__stars {
  color: var(--rarity);
  font-size: 13px;
  letter-spacing: 2px;
  text-shadow: 0 0 9px color-mix(in srgb, var(--rarity) 65%, transparent);
}

.sm-card__meta {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11px;
  color: var(--cg-text-dim);
  text-align: center;
}

.sm-plaque {
  margin-top: 4px;
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11px;
  padding: 4px 11px;
  border-radius: 999px;
  border: 1px solid var(--cg-border);
  color: var(--cg-text-dim);
  text-align: center;
}

.sm-plaque--new {
  color: #7fd99a;
  border-color: #3f8f5a;
  box-shadow: 0 0 14px -6px #3f8f5a;
}

.sm-plaque--soul {
  color: var(--cg-gold-bright);
  border-color: var(--cg-gold-dim);
}

.sm-summary {
  font-family: "Cormorant Garamond", serif;
  font-style: italic;
  font-size: 17px;
  color: var(--cg-text);
  text-align: center;
  padding-top: 6px;
}

/* Искры для 4★ и 5★ — вокруг карточки, но не поверх иллюстрации:
   слой лежит ниже рамки (z-index: -1) и виден только за её пределами.
   Прежняя версия рисовала точки прямо по арту. */
.sm-overlay.is-sparkling .sm-card {
  position: relative;
  isolation: isolate;
}

.sm-overlay.is-sparkling .sm-card::before {
  content: "";
  position: absolute;
  inset: -14% -18%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(circle at 8% 22%, var(--rarity, var(--tier)) 0 1.5px, transparent 2px),
    radial-gradient(circle at 94% 34%, var(--rarity, var(--tier)) 0 1.2px, transparent 2px),
    radial-gradient(circle at 4% 74%, var(--rarity, var(--tier)) 0 1.6px, transparent 2px),
    radial-gradient(circle at 97% 68%, var(--rarity, var(--tier)) 0 1.1px, transparent 2px),
    radial-gradient(circle at 50% 104%, var(--rarity, var(--tier)) 0 1.4px, transparent 2px);
  animation: sm-sparks 2.6s linear infinite;
}

@keyframes sm-sparks {
  from { transform: translateY(-8%); opacity: 0.9; }
  to { transform: translateY(12%); opacity: 0; }
}

/* Единственное, что допустимо поверх арта: едва заметный стеклянный
   блик, скользящий при наведении. */
.sm-card__frame::after,
.cg-card__face::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(104deg, transparent 38%, rgba(255, 255, 255, 0.14) 48%, transparent 58%);
  transform: translateX(-40%);
  transition: opacity 0.25s ease, transform 0.5s ease;
}

.sm-card:hover .sm-card__frame::after,
.cg-card:hover .cg-card__face::after {
  opacity: 1;
  transform: translateX(40%);
}

@media (prefers-reduced-motion: reduce) {
  .sm-overlay,
  .sm-flash,
  .sm-flash.is-firing,
  .sm-flash.is-rays::after,
  .sm-overlay.is-shockwave::after,
  .sm-card__frame::after,
  .cg-card__face::after,
  .sm-card.is-revealed {
    transition: none;
    animation: none;
  }

  .sm-card {
    opacity: 1;
    transform: none;
  }

  .sm-overlay.is-sparkling .sm-card__frame::after {
    animation: none;
    opacity: 0.5;
  }
}

/* Узкий экран (~380px): Mini App открывают в основном с телефона. */
@media (max-width: 480px) {
  .sm-crystals__value {
    font-size: 34px;
  }

  .sm-pull-row {
    grid-template-columns: 1fr;
    gap: 10px;
  }

  .sm-pull {
    padding: 13px 12px;
  }

  .sm-overlay {
    padding: 14px 10px;
    justify-content: flex-start;
    padding-top: 62px;
  }

  .sm-grid:not(.sm-grid--many) {
    grid-template-columns: minmax(0, 178px);
  }

  /* Телефон: три в ряд. Подгонка размера под высоту окна здесь снята
     (max-width: none) — пять или четыре строки в экран всё равно не
     помещаются, а расчёт по высоте ужимал карточки до 64 px и оставлял
     широкие пустые поля по бокам. Ширина теперь делится между колонками
     целиком: на 380 px карточка выходит около 113 px.

     Почему три, а не две: десять карточек в два столбца — это пять строк
     против четырёх, то есть заметно больше прокрутки, а жалоба была
     именно на неё. Если 113 px окажется мелко — поменяйте --sm-cols на 2
     в этом блоке, остальное подстроится само. */
  .sm-grid--many {
    --sm-cols: 3;
    --sm-gap: 8px;
    max-width: none;
  }

  /* Совсем узкие экраны (320–339 px): три колонки дали бы меньше 95 px,
     здесь читаемость важнее длины прокрутки. */
  @media (max-width: 339px) {
    .sm-grid--many {
      --sm-cols: 2;
    }
  }

  .sm-grid--many .sm-card__name {
    font-size: 11px;
    margin-top: 3px;
  }

  .sm-grid--many .sm-card__stars {
    font-size: 10px;
    letter-spacing: 0.5px;
  }

  .sm-grid--many .sm-plaque {
    font-size: 9px;
    padding: 2px 6px;
    border-radius: 6px;
  }

  .sm-grid--many .sm-plaque__full {
    display: none;
  }

  .sm-grid--many .sm-plaque__short {
    display: inline;
  }

  .sm-card__name { font-size: 12px; }
  .sm-card__meta { font-size: 10px; }
  .sm-plaque { font-size: 10px; padding: 3px 8px; }
  .sm-summary { font-size: 15px; }
}

/* ==========================================================================
   Боевой экран (.cb-*)
   Противники сверху, отряд снизу, между ними — сцена для эффектов.
   Старые .combat-* из styles.css удалены: ими пользовался только этот
   экран.
   ========================================================================== */

.cb-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--cg-border-soft);
}

/* «Отступить» переехало сюда из нижней панели: низ экрана отдан
   действиям целиком, чтобы ход делался одним касанием под большим
   пальцем. */
.cb-retreat {
  margin-left: auto;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--cg-border);
  background: none;
  color: var(--cg-text-dim);
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 12px;
  cursor: pointer;
}

.cb-retreat:hover:not(:disabled) {
  color: #d17a7a;
  border-color: var(--combat-red-dim);
}

.cb-topbar__floor {
  font-family: "Cinzel", serif;
  font-size: 18px;
  font-weight: 700;
  color: var(--cg-gold-bright);
  letter-spacing: 0.04em;
}

.cb-topbar__wave {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 13px;
  color: var(--cg-text-dim);
}

.cb-side {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: center;
  padding: 16px 0;
}

.cb-side--enemy {
  align-items: flex-start;
}

.cb-side--player {
  align-items: flex-end;
}

/* Сцена между рядами. Всплывающие числа к ней не привязаны — они
   вылетают из самих портретов, — поэтому в бою она сжата почти в ноль и
   разворачивается только под итог. Прежние 54px постоянного воздуха на
   телефоне стоили дороже, чем давали. */
.cb-stage {
  position: relative;
  min-height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(ellipse at center, rgba(201, 163, 92, 0.09) 0%, transparent 70%);
  border-top: 1px solid var(--cg-border-soft);
  border-bottom: 1px solid var(--cg-border-soft);
}

.cb-stage.is-open {
  min-height: 54px;
}

/* ---- Плитка бойца ------------------------------------------------------- */
/* Коробки вокруг бойца нет: фигура стоит прямо на сцене. Рамка и фон
   переехали на .cb-unit__portrait — то есть достаются только заглушке,
   иначе буква висела бы в пустоте. Ширину плитки делят между собой:
   трое врагов получают больше места, четверо героев — меньше, и никто
   не уезжает на второй ряд. */
.cb-unit {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  max-width: 120px;
  border-radius: 12px;
  padding: 4px 2px 8px;
  text-align: center;
  transition: opacity 0.3s, filter 0.3s, transform 0.2s;
}

.cb-unit__portrait {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: 8px;
  overflow: hidden;
  background: #131116;
  border: 1px solid var(--cg-border);
}

/* ---- Чибик ---------------------------------------------------------------
   Спрайт с прозрачностью стоит на поле, а не лежит в обрезанном окошке:
   у плитки с чибиком нет ни рамки кадра, ни фона. Файл подхватывается по
   имени героя (assets/hero_chibi/<hero_id>.png), поэтому добавление
   следующего героя — это положить файл, а не править код.
   -------------------------------------------------------------------------- */

.cb-unit__stage {
  position: relative;
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  --ring: transparent;
}

/* Подсветка — светящийся овал под ногами вместо прямоугольной рамки.
   Лежит под фигурой, поэтому читается как свет на полу, а не как обводка. */
.cb-unit__stage::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 3%;
  width: 88%;
  height: 20%;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(ellipse at center, var(--ring) 0%, transparent 72%);
  opacity: 0;
  transition: opacity 0.25s ease;
  pointer-events: none;
}

.cb-unit--chibi.is-active .cb-unit__stage {
  --ring: var(--cg-gold);
}

.cb-unit--chibi.is-target .cb-unit__stage {
  --ring: var(--combat-red);
}

.cb-unit--chibi.is-active .cb-unit__stage::before,
.cb-unit--chibi.is-target .cb-unit__stage::before {
  opacity: 0.95;
}

.cb-unit__chibi {
  position: relative;
  z-index: 1; /* поверх овала подсветки */
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Ноги к нижнему краю: так фигуры разного роста встают на одну линию. */
  object-position: bottom center;
  display: block;
  transform-origin: 50% 100%;
  filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.55));
  transition: filter 0.3s ease;
}

/* Свечение по силуэту, а не по прямоугольнику: drop-shadow идёт по
   контуру прозрачного PNG. */
.cb-unit--chibi.is-active .cb-unit__chibi {
  filter: drop-shadow(0 0 7px var(--cg-gold)) drop-shadow(0 4px 6px rgba(0, 0, 0, 0.55));
}

.cb-unit--chibi.is-target .cb-unit__chibi {
  filter: drop-shadow(0 0 7px var(--combat-red)) drop-shadow(0 4px 6px rgba(0, 0, 0, 0.55));
}

/* Покой — еле заметное покачивание. Разная задержка по стихии развела бы
   бойцов по фазе; пока хватает того, что анимация стартует с загрузкой. */
.cb-unit--chibi .cb-unit__chibi {
  animation: cb-chibi-idle 3.2s ease-in-out infinite;
}

@keyframes cb-chibi-idle {
  0%, 100% { transform: translateY(0) rotate(0deg) scaleY(1); }
  50% { transform: translateY(-2px) rotate(0.7deg) scaleY(1.012); }
}

/* Атака — рывок вперёд и возврат. Направление берётся из data-side:
   отряд бьёт вверх, к врагам, враги — вниз. */
.cb-unit--chibi[data-side="player"].is-acting .cb-unit__chibi {
  animation: cb-chibi-lunge-up 0.5s cubic-bezier(0.2, 0.9, 0.3, 1);
}

.cb-unit--chibi[data-side="enemy"].is-acting .cb-unit__chibi {
  animation: cb-chibi-lunge-down 0.5s cubic-bezier(0.2, 0.9, 0.3, 1);
}

@keyframes cb-chibi-lunge-up {
  0% { transform: translateY(0) scale(1); }
  28% { transform: translateY(-14px) scale(1.06); }
  55% { transform: translateY(-4px) scale(1.02); }
  100% { transform: translateY(0) scale(1); }
}

@keyframes cb-chibi-lunge-down {
  0% { transform: translateY(0) scale(1); }
  28% { transform: translateY(14px) scale(1.06); }
  55% { transform: translateY(4px) scale(1.02); }
  100% { transform: translateY(0) scale(1); }
}

/* Получен урон — вздрагивание со вспышкой. Вспышка сделана свечением, а
   не осветлением: brightness выбелил бы весь спрайт и потерял силуэт. */
.cb-unit--chibi.is-hit .cb-unit__chibi {
  animation: cb-chibi-hurt 0.42s ease-out;
}

@keyframes cb-chibi-hurt {
  0% {
    transform: translateX(0);
    filter: drop-shadow(0 0 0 #fff) drop-shadow(0 4px 6px rgba(0, 0, 0, 0.55));
  }
  15% {
    transform: translateX(-5px) rotate(-2deg);
    filter: drop-shadow(0 0 10px #fff) drop-shadow(0 0 18px var(--combat-red)) brightness(1.5);
  }
  40% { transform: translateX(4px) rotate(1.5deg); }
  65% { transform: translateX(-2px) rotate(-0.8deg); }
  100% {
    transform: translateX(0);
    filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.55));
  }
}

/* Поражение — наклон и затемнение. Анимация покоя здесь обязана
   выключиться, иначе павший продолжит покачиваться. */
.cb-unit--chibi.is-dead .cb-unit__chibi {
  animation: none;
  transform: rotate(-14deg) translateY(6px);
  filter: grayscale(1) brightness(0.4) drop-shadow(0 2px 4px rgba(0, 0, 0, 0.6));
  transition: transform 0.5s ease, filter 0.5s ease;
}

/* Указатель цели. Одной красной рамки на мелком портрете мало —
   треугольник над плиткой виден боковым зрением, не всматриваясь. */
.cb-unit__marker {
  position: absolute;
  top: -9px;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 7px solid transparent;
  border-right: 7px solid transparent;
  border-top: 9px solid var(--combat-red);
  filter: drop-shadow(0 0 6px var(--combat-red));
  animation: cb-marker 1.4s ease-in-out infinite;
}

@keyframes cb-marker {
  0%, 100% { transform: translate(-50%, 0); }
  50% { transform: translate(-50%, 3px); }
}

.cb-unit__img,
.cb-unit__placeholder {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* У противников нет иллюстраций (tower_config.py), поэтому заглушка
   должна выглядеть намеренной, а не «картинка не загрузилась». */
.cb-unit__placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Cinzel", serif;
  font-size: 34px;
  font-weight: 700;
  color: var(--cg-text-dim);
  background:
    radial-gradient(circle at 50% 38%, color-mix(in srgb, var(--glow) 35%, #17151a), #121016 72%);
}

.cb-unit__name {
  font-family: "Cinzel", serif;
  font-size: 13px;
  font-weight: 600;
  color: var(--cg-gold-bright);
  margin-top: 7px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cb-unit__level {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 10.5px;
  color: var(--cg-text-dim);
  margin-bottom: 6px;
}

/* Полоса HP лежит поверх нижнего края портрета, а не отдельной строкой
   под ним: так каждый ряд бойцов ниже примерно на 20px. */
.cb-unit__hp {
  position: absolute;
  left: 4px;
  right: 4px;
  bottom: 4px;
  height: 6px;
  border-radius: 999px;
  background: rgba(6, 5, 8, 0.85);
  border: 1px solid rgba(0, 0, 0, 0.6);
  overflow: hidden;
  z-index: 2;
}

.cb-unit__hp-fill {
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, #3f8f5a, #58c97a);
  transition: width 0.35s ease, background 0.35s ease;
}

/* Боевые сигналы держатся на --combat-red — приглушённом кирпичном.
   Алый редкости (--rarity-5) заметно ярче и насыщеннее, чтобы низкое HP
   и подсветка цели не читались как «выпала пятёрка». */
.cb-unit__hp-fill.is-low {
  background: linear-gradient(90deg, var(--combat-red-dim), var(--combat-red));
}

.cb-unit__hp-text {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 10px;
  color: var(--cg-text-dim);
  margin-top: 3px;
}

.cb-unit__energy {
  display: flex;
  gap: 4px;
  justify-content: center;
  margin-top: 6px;
}

/* ---------------------------------------------------------------------
   Чибик на месте карточки
   --------------------------------------------------------------------- */

/* Чибик квадратный, а место под карточку вертикальное. Растягивать его
   нельзя, обрезать — тоже, поэтому он вписывается целиком и прижимается
   к низу: так фигура стоит, а не парит посередине кадра.
   Фон — тот же градиент по стихии, что был под буквой, иначе прозрачный
   спрайт повис бы в пустоте.
   Правило одно на все экраны, размеры и форма — за рамкой конкретного
   места. */
.hero-chibi {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  overflow: hidden;
  background: linear-gradient(
    160deg,
    color-mix(in srgb, var(--glow) 60%, #17151a),
    color-mix(in srgb, var(--glow) 20%, #17151a) 85%
  );
}

.hero-chibi__img {
  /* Отступы в процентах, а не в пикселях: одна и та же доля кадра на
     плитке коллекции, в ячейке отряда и на карточке призыва. */
  max-width: 82%;
  max-height: 88%;
  margin-bottom: 4%;
  object-fit: contain;
  display: block;
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.55));
}

/* Ячейка отряда заметно мельче остальных мест, и те же 82% там уже
   нечитаемы — фигуре отдаётся почти весь кадр. Правило вписывания при
   этом прежнее: пропорции сохраняются, обрезки нет. */
.sq-cell__chibi .hero-chibi__img {
  max-width: 94%;
  max-height: 94%;
  margin-bottom: 2%;
}

/* ---------------------------------------------------------------------
   Боевая мощь (CP)
   --------------------------------------------------------------------- */

.cg-cp {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin-top: 6px;
}

.cg-cp__label {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--cg-text-dim);
}

.cg-cp__value {
  font-family: "Cinzel", serif;
  font-size: 24px;
  font-weight: 700;
  color: var(--cg-gold-bright);
}

/* Число в углу плитки: сравнивается взглядом, поэтому мелкое и не
   спорит с портретом. */
.cg-card__cp {
  position: absolute;
  right: 6px;
  bottom: 6px;
  z-index: 3;
  padding: 2px 6px;
  border-radius: 999px;
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 10px;
  color: var(--cg-gold-bright);
  background: rgba(6, 5, 8, 0.72);
  border: 1px solid var(--cg-border);
}

/* Подпись линии в редакторе отряда. Бонусы и доля атак стоят под
   названием, чтобы выбор схемы был осознанным, а не наугад. */
.sq-line__bonus,
.sq-line__share {
  display: block;
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 10.5px;
  line-height: 1.35;
  color: var(--cg-text-dim);
}

.sq-line__bonus {
  color: var(--cg-gold);
}

.cg-line-note {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11.5px;
  color: var(--cg-text-dim);
  margin-top: 8px;
}

/* Сумма CP над доской отряда: состав решается здесь, поэтому число
   стоит крупно и рядом с местом, где его меняют. */
.sq-total-cp {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
  margin: 2px 0 10px;
}

.sq-total-cp__label {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--cg-text-dim);
}

.sq-total-cp__value {
  font-family: "Cinzel", serif;
  font-size: 26px;
  font-weight: 700;
  color: var(--cg-gold-bright);
}

.sq-cell__cp {
  display: block;
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 10px;
  color: var(--cg-gold);
}

.sq-row__cp {
  margin-left: auto;
  font-family: "Cinzel", serif;
  font-size: 14px;
  font-weight: 700;
  color: var(--cg-gold-bright);
}

.cp-compare {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 10px;
  border-radius: 8px;
  background: rgba(10, 9, 12, 0.5);
  border: 1px solid var(--cg-border);
}

.cp-compare__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.cp-compare__value {
  font-family: "Cinzel", serif;
  font-size: 16px;
  font-weight: 700;
  color: var(--cg-gold-bright);
}

/* Только существующая палитра: золото акцентов, обычный светлый текст
   и алый пятизвёздной редкости. Новых цветов не заводим. */
.cp--ready { color: var(--cg-gold-bright); }
.cp--risky { color: var(--cg-text); }
.cp--danger { color: var(--rarity-5); }

/* ---------------------------------------------------------------------
   Экипировка
   --------------------------------------------------------------------- */

/* Прибавка от экипировки — золотом, цветом акцентов интерфейса.
   Основное значение остаётся обычным, иначе на глаз не отличить, где
   собственная сила героя, а где чужая. */
.cg-bonus {
  color: var(--cg-gold-bright);
  font-weight: 600;
}

.eq-cells {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
  gap: 8px;
  margin-top: 8px;
}

.eq-cells__loading,
.eq-cells__note {
  grid-column: 1 / -1;
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 12px;
  color: var(--cg-text-dim);
}

/* Плитка предмета. Рамка и свечение несут редкость, поэтому иконка одна
   на тип оружия или направление брони — восемь вместо шестнадцати. */
.eq-item {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  width: 100%;
  padding: 9px 10px;
  text-align: left;
  border-radius: 8px;
  cursor: pointer;
  color: inherit;
  background: rgba(14, 12, 16, 0.72);
  border: 1px solid var(--cg-border);
  transition: border-color 0.2s, box-shadow 0.2s, transform 0.12s;
}

.eq-item:hover {
  transform: translateY(-1px);
}

.eq-item--r3 {
  border-color: var(--rarity-3);
  box-shadow: 0 0 14px -6px var(--rarity-3);
}

.eq-item--r4 {
  border-color: var(--rarity-4);
  box-shadow: 0 0 14px -6px var(--rarity-4);
}

.eq-item--r5 {
  border-color: var(--rarity-5);
  box-shadow: 0 0 16px -5px var(--rarity-5);
}

.eq-item--empty {
  border-style: dashed;
  opacity: 0.75;
}

/* Заглушка вместо арта: иконки рисуются отдельно, и до их появления
   плитка обязана оставаться читаемой, а не пустой. */
.eq-item__icon {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  font-size: 16px;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid var(--cg-border);
}

/* Настоящая иконка вместо символа: фон убран, поэтому подложка ей не
   нужна — рамка редкости у самой плитки. */
.eq-item__icon--art {
  object-fit: contain;
  background: none;
  border-color: transparent;
}

.eq-item__body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.eq-item__name {
  font-family: "Cinzel", serif;
  font-size: 12.5px;
  color: var(--cg-gold-bright);
}

.eq-item__meta,
.eq-item__note,
.eq-item__bonus {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11px;
  color: var(--cg-text-dim);
}

.eq-item__bonus {
  color: var(--cg-gold);
}

.eq-picker__list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 60vh;
  overflow-y: auto;
}

.eq-picker__lines {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 8px 0 12px;
}

.eq-picker__actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* Метки эффектов. Цвет холодный и приглушённый: это не боевой сигнал
   вроде низкого HP, а состояние бойца, и спорить за внимание с полосой
   здоровья ему не нужно. */
.cb-unit__effects {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  justify-content: center;
  margin-top: 5px;
}

.cb-effect {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 9.5px;
  line-height: 1;
  padding: 3px 5px;
  border-radius: 4px;
  color: #a9c4d6;
  background: rgba(46, 70, 88, 0.5);
  border: 1px solid rgba(120, 160, 190, 0.35);
  white-space: nowrap;
}

.cb-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 1px solid var(--cg-border);
  background: #0d0c0e;
  transition: background 0.25s, box-shadow 0.25s, border-color 0.25s;
}

.cb-dot.is-on {
  background: linear-gradient(180deg, var(--cg-gold-bright), var(--cg-gold));
  border-color: var(--cg-gold-dim);
  box-shadow: 0 0 7px -1px var(--cg-gold);
}

/* Чей сейчас ход. Прямоугольная подсветка осталась только у заглушки —
   у чибика её заменяет овал под ногами и свечение по силуэту. */
.cb-unit:not(.cb-unit--chibi).is-active .cb-unit__portrait {
  border-color: var(--cg-gold);
  box-shadow: 0 0 0 1px var(--cg-gold), 0 0 26px -6px var(--cg-gold);
}

/* Короткий импульс в момент, когда этот боец бьёт. У чибика вместо этого
   рывок самой фигуры (cb-chibi-lunge-*), поэтому плитку не трогаем —
   иначе вернулся бы прямоугольник, который мы только что убрали. */
.cb-unit:not(.cb-unit--chibi).is-acting .cb-unit__portrait {
  box-shadow: 0 0 0 1px var(--cg-gold-bright), 0 0 30px -4px var(--cg-gold);
}

.cb-unit:not(.cb-unit--chibi).is-acting {
  transform: translateY(-4px);
}

.cb-unit.is-dead {
  opacity: 0.42;
  filter: grayscale(1);
}

.cb-unit.is-selectable {
  cursor: pointer;
}

.cb-unit.is-selectable:hover {
  transform: translateY(-2px);
}

/* Текущая цель. Подсвечена всегда, а не только после выбора действия:
   ход уходит по ней одним касанием кнопки внизу. */
.cb-unit:not(.cb-unit--chibi).is-target .cb-unit__portrait {
  border-color: var(--combat-red);
  box-shadow: 0 0 0 1px var(--combat-red), 0 0 24px -6px var(--combat-red);
}

/* У чибика вздрагивание и вспышка живут на самой фигуре
   (cb-chibi-hurt) — прямоугольная вспышка нужна только заглушке. */
.cb-unit:not(.cb-unit--chibi).is-hit .cb-unit__portrait {
  animation: cb-hit 0.42s ease;
}

@keyframes cb-hit {
  0% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
  18% { box-shadow: 0 0 0 3px rgba(255, 236, 210, 0.9), 0 0 34px -2px var(--combat-red); }
  100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
}

/* ---- Всплывающие числа -------------------------------------------------- */
.cb-unit__fx {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: visible;
}

.cb-pop {
  position: absolute;
  left: 50%;
  top: 42%;
  transform: translateX(-50%);
  display: flex;
  align-items: baseline;
  gap: 5px;
  font-family: "Cinzel", serif;
  font-size: 26px;
  font-weight: 700;
  color: #ffd9c8;
  text-shadow: 0 0 10px rgba(209, 86, 86, 0.9), 0 2px 4px rgba(0, 0, 0, 0.8);
  animation: cb-pop-up 1.05s ease-out forwards;
  white-space: nowrap;
}

.cb-pop--miss {
  font-size: 17px;
  color: var(--cg-text-dim);
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.85);
}

/* Крит: пометка алым, число крупнее, взлёт резче и дольше.
   Алый — тот же --rarity-5, что и у пятизвёздочной редкости; новый
   цвет не заводится. */
.cb-pop--crit {
  font-size: 36px;
  animation: cb-pop-up-crit 1.4s cubic-bezier(0.16, 0.9, 0.28, 1) forwards;
  text-shadow: 0 0 14px color-mix(in srgb, var(--rarity-5) 80%, transparent),
    0 2px 5px rgba(0, 0, 0, 0.85);
}

.cb-pop__mark {
  font-size: 15px;
  letter-spacing: 0.08em;
  color: var(--rarity-5);
  text-shadow: 0 0 10px color-mix(in srgb, var(--rarity-5) 70%, transparent),
    0 1px 3px rgba(0, 0, 0, 0.9);
}

@keyframes cb-pop-up {
  0% { opacity: 0; transform: translate(-50%, 8px) scale(0.85); }
  18% { opacity: 1; transform: translate(-50%, 0) scale(1.1); }
  35% { transform: translate(-50%, -4px) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -46px) scale(1); }
}

/* Тот же взлёт, но с большим замахом и заметной паузой на пике —
   крит должен успеть прочитаться. */
@keyframes cb-pop-up-crit {
  0% { opacity: 0; transform: translate(-50%, 10px) scale(0.6); }
  14% { opacity: 1; transform: translate(-50%, -2px) scale(1.32); }
  26% { transform: translate(-50%, -6px) scale(0.98); }
  38% { transform: translate(-50%, -8px) scale(1.06); }
  60% { opacity: 1; transform: translate(-50%, -18px) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -62px) scale(1); }
}

/* ---- Кнопки действий ---------------------------------------------------- */
/* Панель действий прибита к низу окна.
   sticky, а не fixed: липкий элемент остаётся в потоке, поэтому не надо
   вручную подбирать нижний отступ экрана под его высоту — и он не
   перекроет журнал, если контент всё же окажется длиннее экрана. */
.cb-actions {
  position: sticky;
  bottom: 0;
  z-index: 6;
  display: grid;
  gap: 10px;
  justify-items: center;
  padding: 12px 0 calc(10px + env(safe-area-inset-bottom, 0px));
  margin-top: 10px;
  background: linear-gradient(to top, var(--cg-bg) 62%, rgba(10, 10, 14, 0.85));
  border-top: 1px solid var(--cg-border-soft);
}

.cb-actions--empty {
  min-height: 40px;
}

.cb-hint {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-family: "Cormorant Garamond", serif;
  font-size: 16px;
  color: var(--cg-text-dim);
}

.cb-hint__actor {
  font-family: "Cinzel", serif;
  color: var(--cg-gold-bright);
}

.cb-hint__arrow {
  color: var(--cg-text-dim);
}

.cb-hint__target {
  font-family: "Cinzel", serif;
  color: #e08a8a;
}

.cb-action-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 10px;
  width: 100%;
}

.cb-action {
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: flex-start;
  text-align: left;
  padding: 13px 16px;
  border-radius: 10px;
  border: 1px solid var(--cg-gold-dim);
  background: linear-gradient(165deg, var(--cg-bg-card), #161417 78%);
  color: var(--cg-text);
  cursor: pointer;
  font-family: inherit;
  transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s;
}

.cb-action:hover:not(.is-disabled) {
  border-color: var(--cg-gold);
  box-shadow: 0 0 18px -6px var(--cg-gold);
  transform: translateY(-2px);
}

.cb-action__name {
  font-family: "Cinzel", serif;
  font-size: 15px;
  font-weight: 600;
  color: var(--cg-gold-bright);
}

.cb-action__hint {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 11px;
  color: var(--cg-text-dim);
}

.cb-action.is-disabled {
  opacity: 0.38;
  cursor: not-allowed;
  border-color: var(--cg-border);
  box-shadow: none;
  transform: none;
}

/* ---- Исход боя ---------------------------------------------------------- */
.cb-outcome {
  display: grid;
  gap: 10px;
  justify-items: center;
  padding: 18px 0;
}

.cb-banner {
  font-family: "Cinzel Decorative", "Cinzel", serif;
  font-size: clamp(30px, 7vw, 52px);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: cb-banner-in 0.5s ease-out;
}

.cb-banner--victory {
  background: linear-gradient(180deg, #ffe9a8, var(--cg-gold) 55%, #8a713f);
  filter: drop-shadow(0 0 18px rgba(212, 175, 55, 0.45));
}

.cb-banner--defeat {
  background: linear-gradient(180deg, #f0a0a0, #b03636 55%, #5e1f1f);
  filter: drop-shadow(0 0 18px rgba(176, 54, 54, 0.4));
}

.cb-banner--retreated {
  background: linear-gradient(180deg, #cfc6d4, var(--cg-text-dim) 60%, #5a545f);
}

@keyframes cb-banner-in {
  from { opacity: 0; transform: scale(0.9); }
  to { opacity: 1; transform: none; }
}

.cb-banner__note {
  font-family: "Cormorant Garamond", serif;
  font-style: italic;
  color: var(--cg-text-dim);
  margin: 0;
}

/* ---- Журнал ------------------------------------------------------------- */
/* Журнал свёрнут до одной последней строки и разворачивается по тапу.
   Развёрнутый занимал около 160px — четверть экрана телефона ради того,
   что игрок только что видел анимацией. */
.cb-log {
  margin-top: 12px;
  border: 1px solid var(--cg-border);
  border-radius: 10px;
  background: rgba(10, 9, 12, 0.45);
  overflow: hidden;
}

.cb-log__toggle {
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 12px;
  background: none;
  border: none;
  cursor: pointer;
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 12px;
  line-height: 1.35;
  color: var(--cg-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cb-log__toggle:hover {
  color: var(--cg-gold-bright);
}

.cb-log__lines {
  display: none;
  max-height: 132px;
  overflow-y: auto;
  padding: 4px 12px 10px;
  flex-direction: column;
  gap: 4px;
  border-top: 1px solid var(--cg-border);
}

.cb-log.is-open .cb-log__lines {
  display: flex;
}

.cb-log__line {
  font-family: "Work Sans", system-ui, sans-serif;
  font-size: 12px;
  line-height: 1.4;
  color: var(--cg-text-dim);
}

.cb-log__line:last-child {
  color: var(--cg-text);
}

/* Пометка крита в журнале — тем же алым, что и всплывающее число. */
.cb-log__crit {
  color: var(--rarity-5);
  font-weight: 600;
  letter-spacing: 0.06em;
  margin-right: 6px;
}

.cb-log__line--crit {
  color: var(--cg-text);
}

@media (prefers-reduced-motion: reduce) {
  .cb-pop {
    animation-duration: 0.5s;
  }

  /* Крит остаётся заметным пометкой и размером, но без резкого замаха
     и долгого зависания — движение здесь и просили убавить. */
  .cb-pop--crit {
    animation: cb-pop-up 0.6s ease-out forwards;
  }

  .cb-unit,
  .cb-unit__hp-fill {
    transition: none;
  }

  .cb-unit:not(.cb-unit--chibi).is-hit .cb-unit__portrait,
  .cb-unit__marker,
  .cb-banner {
    animation: none;
  }

  /* Покачивание в покое отключается целиком. Рывок при атаке и
     вздрагивание при уроне оставлены: это не фон, а обратная связь на
     действие — без них непонятно, кто ударил и кому прилетело. */
  .cb-unit--chibi .cb-unit__chibi {
    animation: none;
  }
}

/* Телефон: весь цикл хода обязан помещаться в экран без прокрутки.
   Бюджет на 380×640 — верхняя строка 28, ряд врагов ~140, сцена 22,
   ряд отряда ~140, свёрнутый журнал 32, панель действий ~128.
   Около 490 из 640, запас на вырез экрана и четвёртого героя. */
@media (max-width: 640px) {
  .combat-screen {
    padding: 12px 10px 0;
  }

  /* Ширина не задаётся: плитки делят ряд поровну (flex: 1 1 0 выше).
     Трое врагов получают по ~104px, четверо героев — по ~88px, и никто
     не уезжает на второй ряд, который стоил бы ещё 140px высоты. */
  .cb-unit {
    padding: 2px 1px 6px;
    max-width: 108px;
  }

  .cb-side {
    gap: 6px;
    padding: 6px 0;
  }

  /* Уровень отдельной строкой убран — он в подсказке по удержанию.
     Экономит по 14px на каждом ряду. */
  .cb-unit__level {
    display: none;
  }

  .cb-unit__name {
    font-size: 11px;
    margin-top: 5px;
  }

  .cb-unit__hp-text {
    font-size: 9px;
    margin-top: 2px;
  }

  .cb-unit__energy {
    gap: 3px;
    margin-top: 4px;
  }

  .cb-dot {
    width: 6px;
    height: 6px;
  }

  /* Высота боевого экрана на телефоне посчитана впритык — метка эффекта
     не должна её увеличивать, иначе вернётся прокрутка в бою. */
  .cb-unit__effects {
    margin-top: 3px;
    gap: 2px;
  }

  .cb-effect {
    font-size: 8.5px;
    padding: 2px 4px;
  }

  .cb-unit__marker {
    top: -7px;
    border-left-width: 6px;
    border-right-width: 6px;
    border-top-width: 8px;
  }

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

  .cb-action-row {
    grid-template-columns: 1fr 1fr;
    gap: 8px;
  }

  .cb-action {
    padding: 10px 12px;
  }

  .cb-action__name {
    font-size: 14px;
  }

  .cb-action__hint {
    font-size: 10px;
  }

  .cb-hint {
    font-size: 14px;
  }

  .cb-log {
    margin-top: 8px;
  }

  .cb-log__lines {
    max-height: 40vh;
  }
}
