/* ---------- Страж сада, тролли и охота за сверчками ----------
   Тот же язык, что у деревьев/алтаря (styles.css): контакт-тень в два
   слоя под ногами, приглушение цвета под ночную сцену (saturate/
   brightness/hue-rotate/drop-shadow), проценты вместо px для позиций —
   чтобы новые спрайты читались частью той же картины, а не наклейкой
   поверх неё. */

/* ---------- Страж ---------- */
.guardian-prop {
  position: absolute;
  transform: translate(-50%, 0);
  width: 38vw;
  height: 38vw;
  max-width: 172px;
  max-height: 172px;
  z-index: 6;
  pointer-events: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
/* Настоящая ходьба к цели — покадровый спрайт (31 кадр, вырезан из того
   же видео, что и атака: 1.6–4.1с ролика, чёткий переступ ногами), кадр
   листает JS в том же rAF/setTimeout-цикле, что двигает left/top (см.
   walkGuardianTo в guardian.js) — тот же принцип, что и бег тролля. */
.guardian-walk-sprite {
  position: absolute;
  left: 50%; bottom: 4%;
  /* тот же масштаб, что у атаки/стоячей картинки — раньше 65px давал
     "скачок размера" при переключении со стоячей позы */
  width: 132px; height: 150px; /* 229×260 кадр, пропорционально увеличен */
  transform: translate(-50%, 0) scaleX(var(--face, 1));
  transform-origin: 50% 100%;
  background-image: url("../assets/guardian/guardian-walk-strip-v2.png?v=6");
  background-repeat: no-repeat;
  background-size: 3360px 150px; /* 24 ячейки по 140px = кадр 132 + прозрачные поля по 4px */
  filter:
    drop-shadow(0 6px 8px rgba(0,0,0,.45))
    saturate(.88) brightness(.86) hue-rotate(-3deg) contrast(1.05);
  /* Переключение состояний теперь через opacity, а не display:none —
     display не умеет переходов, поэтому раньше смена "идёт"→"стоит"
     была резким щелчком кадра ("анимация обрывается"). Кроссфейд слоёв
     друг на друге (все три — img/walk/attack — сидят в одной точке) даёт
     мягкий переход вместо склейки встык.
     Стоячая поза и первый кадр ходьбы — из РАЗНОГО видео (руки в разных
     положениях), поэтому при долгом кроссфейде (было .22s) полсекунды
     видно двойной силуэт — плечи и ноги читаются полупрозрачными. Держим
     переход коротким: смена всё ещё мягкая, но окно двойной экспозиции
     слишком короткое, чтобы глаз успел его считать. */
  opacity: 0;
  pointer-events: none;
  transition: opacity .08s ease;
}
/* Ходьба со спины и лицом к камере — отдельные ракурсы из своих роликов
   (период шага 60 кадров, петля бесшовная). Раньше вертикальный подход
   отыгрывался боковым спрайтом, и Страж «шагал вбок, а ехал вверх». Рост и
   линия ног подогнаны под боковой спрайт один в один, поэтому смена ракурса
   не даёт скачка размера. Зеркалить эти ракурсы нельзя — они симметричны,
   поэтому scaleX к ним не применяется. */
.guardian-walk-up-sprite,
.guardian-walk-down-sprite {
  position: absolute;
  left: 50%; bottom: 4%;
  width: 109px; height: 150px;
  transform: translate(-50%, 0);
  transform-origin: 50% 100%;
  background-repeat: no-repeat;
  background-size: 3510px 150px; /* 30 ячеек по 117px = кадр 109 + поля по 4px */
  filter:
    drop-shadow(0 6px 8px rgba(0,0,0,.45))
    saturate(.88) brightness(.86) hue-rotate(-3deg) contrast(1.05);
  opacity: 0;
  pointer-events: none;
  transition: opacity .08s ease;
}
.guardian-walk-up-sprite   { background-image: url("../assets/guardian/guardian-walk-up.png?v=1"); }
.guardian-walk-down-sprite { background-image: url("../assets/guardian/guardian-walk-down.png?v=1"); }

/* какой ракурс показываем — решает JS, выставляя класс на .guardian-prop */
.guardian-prop.walking.dir-side .guardian-walk-sprite { opacity: 1; }
.guardian-prop.walking.dir-up   .guardian-walk-up-sprite { opacity: 1; }
.guardian-prop.walking.dir-down .guardian-walk-down-sprite { opacity: 1; }
.guardian-prop.walking.dir-up   .guardian-walk-sprite,
.guardian-prop.walking.dir-down .guardian-walk-sprite { opacity: 0; }
.guardian-prop.attacking .guardian-walk-up-sprite,
.guardian-prop.attacking .guardian-walk-down-sprite { opacity: 0; }

.guardian-prop.walking .guardian-img,
.guardian-prop.walking .guardian-attack-sprite { opacity: 0; }

.guardian-contact-shadow {
  position: absolute;
  left: 50%; bottom: 0%;
  width: 92%; height: 24%;
  transform: translate(-50%, 0);
  border-radius: 50%;
  background:
    radial-gradient(ellipse 34% 46% at 50% 60%, rgba(2,7,2,.75), rgba(2,7,2,0) 100%),
    radial-gradient(ellipse 62% 55% at 50% 52%, rgba(4,12,5,.42), rgba(4,12,5,0) 100%);
  filter: blur(3.5px);
}
.guardian-img {
  /* Стоячая поза — это КАДР ИЗ ТОГО ЖЕ ВИДЕО, что ходьба и удар
     (guardian-stand.png = последний кадр атаки, возврат в стойку), а не
     отдельная рисованная картинка. Раньше здесь был другой арт: другой
     ракурс, свет и пропорции, поэтому каждый переход "стоит↔бьёт" был
     кроссфейдом между двумя РАЗНЫМИ фигурами — это и читалось как обрыв
     анимации и отсутствие единой картинки. Теперь кадр, геометрия
     (245x150) и точка привязки совпадают с attack-спрайтом один в один,
     так что переход незаметен. */
  position: absolute;
  left: 50%; bottom: 4%;
  height: 150px;
  width: auto;
  max-width: none;
  transform: translate(-50%, 0) scaleX(var(--face, 1)) scale(1);
  transform-origin: 50% 100%;
  image-rendering: -webkit-optimize-contrast;
  /* та же тональная подгонка под ночь, что у деревьев/алтаря, но чуть
     мягче — у Стража своё голубое свечение, топить его в темноте не надо */
  filter:
    drop-shadow(0 6px 8px rgba(0,0,0,.45))
    saturate(.88) brightness(.86) hue-rotate(-3deg) contrast(1.05);
  animation: guardianBreathe 4.2s ease-in-out infinite;
  opacity: 1;
  /* transform (без учёта дыхания — оно отдельным keyframe) тоже плавно
     довозится, чтобы разворот при смене направления не был мгновенным
     щелчком, когда Страж останавливается лицом в другую сторону, чем шёл */
  transition: filter 1.1s ease, opacity .08s ease, transform .18s ease;
}
@keyframes guardianBreathe {
  0%, 100% { transform: translate(-50%, 0) scaleX(var(--face, 1)) scale(1); }
  50%      { transform: translate(-50%, 0) scaleX(var(--face, 1)) scale(1.018); }
}
/* устал — тускнеет, чуть оседает, дыхание почти останавливается */
.guardian-prop.tired .guardian-img {
  animation-duration: 7.5s;
  filter:
    drop-shadow(0 5px 6px rgba(0,0,0,.4))
    saturate(.38) brightness(.58) hue-rotate(6deg) contrast(1.0);
}
@keyframes guardianBreatheTired {
  0%, 100% { transform: translate(-50%, 2%) scaleX(var(--face, 1)) scale(.975); }
  50%      { transform: translate(-50%, 1.4%) scaleX(var(--face, 1)) scale(.98); }
}
.guardian-prop.tired .guardian-img { animation-name: guardianBreatheTired; }
/* Атака — настоящий покадровый бросок-и-удар (41 кадр, вырезан из
   присланного видео: замах → рывок с рассекающей энергией → удар оземь с
   разлётом искр → пыль оседает → возврат в стойку), тот же принцип, что и
   бег тролля — кадр листает JS в guardian.js (см. playGuardianAttack),
   не CSS steps(), по той же причине (в этом окружении steps() давал
   плавную интерполяцию вместо чётких кадров). */
.guardian-attack-sprite {
  position: absolute;
  left: 50%; bottom: 4%;
  /* высота подогнана под guardian-img (height:96% от контейнера ~137-165px
     в мобильном диапазоне) — раньше тут было жёстко 65px, вдвое-втрое
     мельче стоячей картинки, и переключение между ними давало заметный
     "скачок размера" ("размеры разные у них"). */
  width: 245px; height: 150px; /* 425×260 кадр, пропорционально увеличен */
  transform: translate(-50%, 0) scaleX(var(--face, 1));
  transform-origin: 50% 100%;
  background-image: url("../assets/guardian/guardian-attack-strip-v2.png?v=6");
  background-repeat: no-repeat;
  background-size: 13156px 150px; /* 52 ячейки по 253px = кадр 245 + поля по 4px */
  filter:
    drop-shadow(0 6px 8px rgba(0,0,0,.45))
    saturate(.88) brightness(.86) hue-rotate(-3deg) contrast(1.05);
  opacity: 0;
  pointer-events: none;
  transition: opacity .22s ease;
}
.guardian-prop.attacking .guardian-img,
.guardian-prop.attacking .guardian-walk-sprite { opacity: 0; }
.guardian-prop.attacking .guardian-attack-sprite { opacity: 1; }

/* кольцо стамины над головой — тот же принцип, что ritual-ring у алтаря.
   Временно спрятано (см. просьбу убрать) — вернуть можно, сняв display:none. */
.guardian-stamina-ring {
  display: none;
  position: absolute;
  left: 50%; top: 6%;
  width: 38%; height: 38%;
  transform: translate(-50%, 0);
  pointer-events: none;
  z-index: 2;
  opacity: .95;
}
.guardian-stamina-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); display: block; }
.stamina-bg { fill: none; stroke: rgba(8, 16, 11, .5); stroke-width: 5.5; }
.stamina-fill {
  fill: none; stroke: #7FE8FF; stroke-width: 5.5; stroke-linecap: round;
  stroke-dasharray: 175.9;
  stroke-dashoffset: 175.9;
  filter: drop-shadow(0 0 4px rgba(120,225,255,.7));
  transition: stroke-dashoffset .9s linear, stroke .6s ease;
}
.guardian-prop.tired .stamina-fill { stroke: #A9B7AC; filter: none; }

@media (prefers-reduced-motion: reduce) {
  .guardian-img { animation: none !important; }
}

/* ---------- Точка появления троллей — арка в стене руин ---------- */
.troll-spawn {
  position: absolute;
  transform: translate(-50%, 0);
  width: 19vw;
  height: 19vw;
  max-width: 92px;
  max-height: 92px;
  z-index: 3;
  cursor: pointer;
  transition: transform .15s ease;
}
.troll-spawn:active {
  transform: translate(-50%, 0) scale(.93);
}
.troll-spawn img {
  width: 100%; height: auto; display: block;
  filter:
    drop-shadow(0 4px 5px rgba(0,0,0,.5))
    saturate(.78) brightness(.7) hue-rotate(-6deg) contrast(1.05);
}
/* дыхание тьмы в проёме — намекает, что оттуда вот-вот кто-то вылезет */
.troll-spawn::after {
  content: "";
  position: absolute;
  left: 50%; top: 40%;
  width: 28%; height: 24%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(ellipse, rgba(170, 220, 100, .32), rgba(170,220,100,0) 72%);
  animation: spawnPulse 3.4s ease-in-out infinite;
  mix-blend-mode: screen;
}
@keyframes spawnPulse {
  0%, 100% { opacity: .3; }
  50%      { opacity: .7; }
}
@media (prefers-reduced-motion: reduce) {
  .troll-spawn::after { animation: none !important; opacity: .5; }
}

/* ---------- Тролли ---------- */
.trolls-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* z-index НЕ задаём намеренно. Раньше здесь стояло 5 — слой становился
     собственным стекинговым контекстом, и какой бы z-index ни выставлял JS
     самому троллю, весь слой целиком лежал ниже грядок (у тех z-index 40+).
     Из-за этого тролль ФИЗИЧЕСКИ не мог оказаться перед деревом — отсюда и
     «проходит сквозь текстуру». Без своего контекста z-index каждого тролля
     сравнивается напрямую с деревьями и Стражем, и сортировка по глубине
     (см. depthZ в render.js) наконец работает. */
}
.troll {
  position: absolute;
  width: 14vw;
  height: 14vw;
  max-width: 70px;
  max-height: 70px;
  transform: translate(-50%, 0) scale(.15);
  transform-origin: 50% 100%;
  opacity: 0;
  cursor: pointer;
  /* left/top больше не твинятся CSS-транзишном — позицию во время бега
     гонит JS покадрово (см. runTrollTo в guardian.js), с прыжком/приседом,
     иначе перемещение читается как "картинку тащат", а не бег. Тут
     остаётся только transition на появление/исчезание. */
  transition: opacity .3s ease, transform .3s cubic-bezier(.2,1.7,.35,1);
  will-change: left, top;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
.troll-contact-shadow {
  position: absolute;
  left: 50%; bottom: 2%;
  width: 88%; height: 20%;
  transform: translate(-50%, 0) scale(1, 1);
  transform-origin: 50% 50%;
  border-radius: 50%;
  background: radial-gradient(ellipse 42% 52% at 50% 60%, rgba(2,7,2,.68), rgba(2,7,2,0) 100%);
  filter: blur(2.5px);
  transition: transform .1s linear, opacity .1s linear;
}
.troll img {
  /* та же логика, что у .guardian-img — канва шире содержимого */
  position: absolute;
  left: 50%; bottom: 6%;
  height: 98%;
  width: auto;
  max-width: none;
  transform: translate(-50%, 0) scaleX(var(--face, 1));
  transform-origin: 50% 100%;
  image-rendering: -webkit-optimize-contrast;
  filter:
    drop-shadow(0 4px 5px rgba(0,0,0,.5))
    saturate(.72) brightness(.8) hue-rotate(2deg) contrast(1.06);
  animation: trollJitter .5s ease-in-out infinite;
}
.troll.running img { animation: none; }

/* Ходьба к дереву — настоящий покадровый шаг (17 кадров, вырезаны из того
   же видео, где тролль подходит к дереву), а не подпрыгивающая статичная
   картинка. Кадр листает JS (см. runTrollTo в guardian.js) — тем же
   способом, что у Стража, и по той же причине: CSS steps() тут давал
   плавную интерполяцию вместо чётких кадров.
   Ходьба и удар отмасштабированы от одной высоты тела и стоят на одной
   «земле» (bottom), поэтому переход между ними не даёт скачка размера. */
.troll-walk-sprite {
  display: none;
  position: absolute;
  left: 50%; bottom: 6%;
  width: 59px; height: 70px;
  transform: translate(-50%, 0) scaleX(var(--face, 1));
  transform-origin: 50% 100%;
  /* разворот на смене направления — плавно, а не мгновенным щелчком */
  transition: transform .16s ease;
  /* Новый ролик ходьбы: 34 кадра, ЧЕСТНАЯ петля (стык силуэтов 0.779 против
     0.797 у соседних кадров — 98% нормы, шва не видно). Прежний спрайт цикла
     не имел вовсе (стык 0.35), из-за чего анимация зримо начиналась заново
     после каждого шага. */
  background-image: url("../assets/guardian/troll-walk-side.png?v=2");
  background-repeat: no-repeat;
  background-size: 2278px 70px; /* 34 ячейки по 67px = кадр 59 + поля по 4px */
  filter:
    drop-shadow(0 4px 5px rgba(0,0,0,.5))
    saturate(.72) brightness(.8) hue-rotate(2deg) contrast(1.06);
}
.troll.running.dir-side .troll-walk-sprite { display: block; }
.troll.running img { display: none; }
.perf-lite .troll-walk-sprite,
.perf-lite .troll-walk-up-sprite,
.perf-lite .troll-walk-down-sprite { display: none !important; }
.perf-lite .troll.running img { display: block !important; }

/* Ходьба анфас (в глубину двора, к дальним/ближним грядкам) — кадры того же
   ролика заряда тролля (troll-charge-greenscreen.mp4), где он и так бежит
   анфас на камеру: обрезали полупрозрачный наезд камеры в начале и
   привели каждый кадр к одной высоте (силуэт в исходнике растёт почти в
   4 раза — камера приближается, а не тролль топчется на месте), иначе он
   на глазах раздувался бы посреди двора. «Вниз» (к камере) — кадры как
   есть, «вверх» (от камеры) — та же плёнка задом наперёд: для второго
   ракурса отдельного отснятого материала нет, а попятный бег в объезд не
   так заметен, зато не оставляет тролля с одним боковым видом на весь
   двор. Не зеркалим — анфас, разворачивать нечего. */
.troll-walk-up-sprite,
.troll-walk-down-sprite {
  display: none;
  position: absolute;
  left: 50%; bottom: 6%;
  width: 59px; height: 70px;
  transform: translate(-50%, 0);
  transform-origin: 50% 100%;
  background-repeat: no-repeat;
  background-size: 2546px 70px; /* 38 ячеек по 67px = кадр 59 + поля по 4px */
  filter:
    drop-shadow(0 4px 5px rgba(0,0,0,.5))
    saturate(.72) brightness(.8) hue-rotate(2deg) contrast(1.06);
}
.troll-walk-down-sprite { background-image: url("../assets/guardian/troll-walk-down.png?v=1"); }
.troll-walk-up-sprite   { background-image: url("../assets/guardian/troll-walk-up.png?v=1"); }
.troll.running.dir-down .troll-walk-down-sprite { display: block; }
.troll.running.dir-up   .troll-walk-up-sprite { display: block; }

/* Атака дерева — тролль дошёл и реально бьёт по стволу (43 кадра,
   зациклено JS в startTrollAttacking), а не просто стоит рядом. */
.troll-attack-sprite {
  display: none;
  position: absolute;
  left: 50%; bottom: 6%;
  width: 87px; height: 70px;
  transform: translate(-50%, 0) scaleX(var(--face, 1));
  transform-origin: 50% 100%;
  transition: transform .16s ease;
  background-image: url("../assets/guardian/troll-attack-strip-v2.png?v=6");
  background-repeat: no-repeat;
  background-size: 4085px 70px; /* 43 ячейки по 95px = кадр 87 + поля по 4px */
  filter:
    drop-shadow(0 4px 5px rgba(0,0,0,.5))
    saturate(.72) brightness(.8) hue-rotate(2deg) contrast(1.06);
}
.troll.attacking .troll-attack-sprite { display: block; }
.troll.attacking img,
.troll.attacking .troll-walk-sprite,
.troll.attacking .troll-walk-up-sprite,
.troll.attacking .troll-walk-down-sprite { display: none; }
.perf-lite .troll-attack-sprite { display: none !important; }
.perf-lite .troll.attacking img { display: block !important; animation: trollJitter .35s ease-in-out infinite; }

/* Дерево трясётся, пока его бьёт тролль — целится в .tree-img-wrap самой
   грядки (см. render.js), не в спрайт тролля. Класс тролль сам вешает на
   нужный .plot и сам же снимает (startTrollAttacking/stopTrollAttacking
   в guardian.js), когда его убили или он ушёл. */
.plot.tree-under-attack .tree-img-wrap {
  animation: treeUnderAttackShake .22s ease-in-out infinite;
}
/* Кадр контакта дубины: короткая вспышка по стволу — удар должен читаться
   как попадание, а не просто тряска рядом стоящего тролля. */
.plot.tree-hit .tree-img-wrap img {
  filter: brightness(1.5) saturate(1.2) drop-shadow(0 0 6px rgba(255, 220, 150, .55));
  transition: filter .06s ease-out;
}
@keyframes treeUnderAttackShake {
  0%, 100% { transform: translate(-50%, 0) rotate(-2.4deg); }
  50%      { transform: translate(-50%, 0) rotate(2.4deg); }
}
@media (prefers-reduced-motion: reduce) {
  .plot.tree-under-attack .tree-img-wrap { animation: none; }
}
@keyframes trollJitter {
  0%, 100% { transform: translate(-50%, 0) scaleX(var(--face, 1)) rotate(-1.6deg); }
  50%      { transform: translate(-50%, 0) scaleX(var(--face, 1)) rotate(1.6deg); }
}
.troll.spawning { opacity: 1; transform: translate(-50%, 0) scale(1); }
.troll.spawn-in { animation: trollPop .4s cubic-bezier(.2,1.7,.35,1); }
@keyframes trollPop {
  0%   { transform: translate(-50%, 0) scale(.1); opacity: 0; }
  60%  { transform: translate(-50%, 0) scale(1.12); opacity: 1; }
  100% { transform: translate(-50%, 0) scale(1); }
}
.troll:active img { transform: translate(-50%, 0) scaleX(var(--face, 1)) scale(.9); }
/* тап-убийство: короткий удар, потом растворяется на месте */
/* Смерть от удара Стража: без задержки и быстро — тролля придавливает
   рукой, и он тут же схлопывается. Раньше тут была задержка .06s и .3s
   на анимацию, из-за чего он ещё заметно «доживал» после придавливания. */
.troll.dying {
  pointer-events: none;
  transition: opacity .14s ease, transform .14s cubic-bezier(.4,0,.6,1);
  opacity: 0;
  transform: translate(-50%, 0) scale(.28, .16);
}
.troll.dying img { animation: trollHit .2s ease-out; }
@keyframes trollHit {
  0%   { transform: translate(-50%, 0) scaleX(var(--face, 1)) scale(1); }
  40%  { transform: translate(-50%, 0) scaleX(var(--face, 1)) scale(1.25, .78); }
  100% { transform: translate(-50%, 0) scaleX(var(--face, 1)) scale(.8); }
}
/* не поймали вовремя — растворяется в тени на месте, не пятясь бегом
   назад (бежать вперёд-спрайтом в обратную сторону выглядело так, будто
   тролль идёт задом наперёд — см. правку) */
.troll.retreating {
  pointer-events: none;
  transition: opacity .6s ease, transform .6s ease;
  opacity: 0;
  transform: translate(-50%, -14px) scale(.55);
}
@media (prefers-reduced-motion: reduce) {
  .troll img { animation: none !important; }
}

/* ---------- VFX смерти тролля ---------- */
.troll-vfx {
  position: absolute;
  width: 20vw;
  max-width: 100px;
  transform: translate(-50%, -55%) scale(.6);
  opacity: 0;
  pointer-events: none;
  /* поверх всех персонажей и деревьев: слой троллей больше не создаёт свой
     стекинговый контекст, поэтому эффектам нужен свой высокий z-index */
  z-index: 2000;
  mix-blend-mode: screen;
}
.troll-vfx.play { animation: vfxBurst .5s ease-out forwards; }
@keyframes vfxBurst {
  0%   { opacity: 0; transform: translate(-50%, -55%) scale(.35) rotate(-6deg); }
  22%  { opacity: 1; transform: translate(-50%, -55%) scale(1) rotate(0deg); }
  100% { opacity: 0; transform: translate(-50%, -55%) scale(1.3) rotate(4deg); }
}

/* всплывающий "+N" сверчков на месте убийства */
.cricket-pop {
  position: absolute;
  transform: translate(-50%, 0);
  font-family: var(--font-round);
  font-weight: 800;
  font-size: 13px;
  color: #E9F7A1;
  text-shadow: 0 1px 3px rgba(0,0,0,.85), 0 0 8px rgba(190, 230, 90, .5);
  pointer-events: none;
  z-index: 2001;
  opacity: 0;
  animation: cricketPopFloat 1s ease-out forwards;
}
@keyframes cricketPopFloat {
  0%   { opacity: 0; transform: translate(-50%, 0) scale(.7); }
  15%  { opacity: 1; transform: translate(-50%, -6px) scale(1); }
  75%  { opacity: 1; transform: translate(-50%, -34px) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -42px) scale(.95); }
}

/* ---------- Чип сверчков в HUD — симметрично wallet-chip, у левого тумблера ---------- */
.cricket-chip {
  position: absolute;
  left: 10px; top: 54px;
  z-index: 6;
  display: flex; align-items: center; gap: 6px;
  padding: 4px 13px 4px 5px;
  border: none; border-radius: 99px;
  background: rgba(10, 20, 14, 0.22);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  font-family: var(--font-round);
  font-size: 12.5px; font-weight: 800; letter-spacing: .01em;
  color: rgba(240, 235, 210, 0.95);
  text-shadow: 0 1px 3px rgba(0,0,0,.8);
  cursor: pointer;
  transition: transform .12s, background .12s;
}
.cricket-chip:active { transform: scale(.95); background: rgba(12, 24, 16, 0.55); }
.cricket-chip img { width: 24px; height: 24px; border-radius: 50%; flex: none; }
.cricket-chip .cc-pulse { animation: ccPulse .32s ease; display: inline-block; }
@keyframes ccPulse { 0% { transform: scale(1.3); } 100% { transform: scale(1); } }

/* ---------- Панель Стража: статы + прокачка ---------- */
.guardian-overlay {
  position: fixed; inset: 0;
  background: rgba(4, 9, 5, 0.82);
  display: flex; align-items: center; justify-content: center;
  z-index: 32;
  padding: 24px 16px;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .28s ease, visibility 0s linear .28s;
}
.guardian-overlay.open {
  opacity: 1; visibility: visible; pointer-events: auto;
  transition: opacity .28s ease, visibility 0s linear 0s;
}
.guardian-modal {
  position: relative;
  width: min(340px, 92vw);
  border-radius: 22px;
  padding: 22px 20px 20px;
  background: linear-gradient(180deg, #14251a, #0c1710);
  border: 1px solid rgba(140, 210, 190, 0.16);
  box-shadow: 0 20px 60px rgba(0,0,0,.55);
  text-align: center;
  color: #F0EBD2;
}
.guardian-modal-close {
  position: absolute; right: 12px; top: 12px;
  width: 30px; height: 30px;
  border: none; border-radius: 50%;
  background: rgba(255,255,255,.08);
  color: #F0EBD2;
  font-size: 15px;
  cursor: pointer;
}
.guardian-modal-thumb {
  width: 128px; height: 128px;
  margin: 4px auto 4px;
  display: grid; place-items: center;
}
.guardian-modal-thumb img {
  max-width: 100%; max-height: 100%;
  filter: drop-shadow(0 8px 14px rgba(0,0,0,.5)) saturate(.94) brightness(.96);
  transition: filter .6s ease;
}
.guardian-modal.state-tired .guardian-modal-thumb img {
  filter: drop-shadow(0 8px 14px rgba(0,0,0,.5)) saturate(.42) brightness(.66);
}
.guardian-modal-name {
  font-family: 'Yeseva One', serif;
  font-size: 20px;
  margin: 2px 0 2px;
}
.guardian-modal-state {
  font-size: 12.5px;
  font-weight: 700;
  color: #9CE6C9;
  margin: 0 0 14px;
}
.guardian-modal.state-tired .guardian-modal-state { color: #C8B48A; }

.guardian-stat-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 9px 2px;
  border-bottom: 1px solid rgba(255,255,255,.08);
  font-size: 12.5px;
}
.guardian-stat-row span:first-child { color: rgba(240,235,210,.68); }
.guardian-stat-row span:last-child { font-weight: 700; }

.guardian-upgrade-btn {
  width: 100%;
  margin-top: 16px;
  padding: 13px;
  border: none; border-radius: 14px;
  background: linear-gradient(180deg, #7ED9FF, #4CB4E8);
  box-shadow: 0 6px 0 #2E86B8, 0 10px 18px rgba(0,0,0,.35);
  color: #0B2430;
  font-family: var(--font-round);
  font-size: 14.5px; font-weight: 800;
  cursor: pointer;
  transition: transform .1s, box-shadow .1s;
}
.guardian-upgrade-btn:active {
  transform: translateY(3px);
  box-shadow: 0 3px 0 #2E86B8, 0 6px 12px rgba(0,0,0,.3);
}
.guardian-upgrade-btn:disabled {
  opacity: .5;
  box-shadow: 0 6px 0 rgba(0,0,0,.2), 0 10px 18px rgba(0,0,0,.2);
  cursor: default;
}
.guardian-upgrade-btn:disabled:active { transform: none; }
.guardian-max-level {
  margin-top: 16px;
  font-size: 12.5px;
  color: #9CE6C9;
  font-weight: 700;
}
