#newHudOverlay{
  --gold:var(--c-gold); --gold-bright:var(--c-gold-bright); --gold-dim:var(--glass-line-lit);
  --panel:var(--glass); --panel-solid:var(--glass-solid);
  --ink:var(--c-wood-900);
  position:fixed; inset:0; z-index:20;
  display:none;
  overflow:hidden;
  background:#000;
  font-family:'Cinzel',Georgia,serif;
  color:var(--gold-bright);
  user-select:none;
}
#newHudOverlay.show{ display:block; }
#newHudOverlay *{ box-sizing:border-box; }

/* Фиксированный холст: вёрстка считается один раз в постоянных пикселях
   (1400x940), а под экран игрока подгоняется целиком через transform:scale.
   Пропорции не меняются никогда — ни на 3:1, ни на планшете, ни в APK. */
#newHudBackdrop{
  position:absolute; inset:0;
  background:var(--c-wood-900) url('../img/arena_castle.jpg') center 50% / cover no-repeat;
}
#newHudBackdrop::after{
  content:''; position:absolute; inset:0;
  background:rgba(6,5,4,0.55);
  backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
}
#newHudFrame{
  position:absolute; top:50%; left:50%;
  width:1700px; height:760px;
  transform-origin:center center;
  overflow:hidden;
  border-radius:var(--r-md);
  box-shadow:0 0 60px rgba(0,0,0,0.75);
}
#newHudArena{
  position:absolute; inset:0;
  background:var(--c-wood-900) url('../img/arena_castle.jpg') 40.7% 50% / cover no-repeat;
}
#newHudArena::after{
  content:'';
  position:absolute; inset:0;
  background:
    linear-gradient(to bottom, rgba(6,5,4,0.62) 0%, rgba(6,5,4,0.15) 26%, rgba(6,5,4,0.12) 55%, rgba(6,5,4,0.82) 100%),
    linear-gradient(to right, rgba(6,5,4,0.72) 0%, rgba(6,5,4,0) 24%, rgba(6,5,4,0) 76%, rgba(6,5,4,0.72) 100%);
}

#newHudPanelStyle .nh-panel, .nh-panel{
  position:relative;
  background:var(--panel);
  border-radius:8.5px;
  backdrop-filter:blur(6px) saturate(0.9);
  -webkit-backdrop-filter:blur(6px) saturate(0.9);
  box-shadow:0 3.8px 18.8px rgba(0,0,0,0.55), inset 0 0 28.2px rgba(0,0,0,0.35);
}
/* Единая орнаментированная рамка (заменяет старый corner.png по углам).
   Пseudo-элемент абсолютно спозиционирован поверх панели вплотную к краям —
   border-image рисуется только в его собственной border-области и никак
   не меняет box-model/раскладку самой панели. */
.nh-panel::before, #newHudOverlay .control-panel::before{
  content:''; position:absolute; inset:0; pointer-events:none; z-index:2;
  border:34px solid transparent;
  border-image:url('../img/ui/frame_ornate.png') 100 fill stretch;
}

#newHud{
  position:absolute; inset:0; padding:15px;
  z-index:10;
}
#newHudLeft, #newHudRight, #newHudRightLower{ display:contents; }
#newCardYou{ position:absolute; left:15px; top:15px; width:616px; z-index:12; }
#newCardFoe{ position:absolute; right:330px; top:15px; width:616px; z-index:12; }
#newHudTopRailSlot{ position:absolute; right:15px; top:15px; width:300px; height:92.1px; z-index:12; display:flex; gap:10px; }
/* панели защиты опущены с 360 на 380 (Andy 13.09.2026): над ними три ячейки
   протокола по 64; ниже — плашка турнира, ей оставлено 9 точек */
#newHudDefSlotYou{ position:absolute; left:15px; top:372px; width:180px; z-index:12; }
#newHudDefSlotFoe{ position:absolute; right:330px; top:372px; width:180px; z-index:12; }
#newHudOverlay #newHudMovesSlot{ position:absolute; right:15px; top:125px; height:620px; width:300px !important; z-index:12; }
/* «твой ход»: панель выбора ударов вспыхивает, когда доска уходит между раундами
   (boardChooseCue, 23-board.js). Свечение — отдельным слоем: у плиты box-shadow
   с !important, анимация его не перебьёт. Всё живёт 0,95 с и убирается. */
#newHudOverlay #newHudMovesSlot .nh-cue-glow{ position:absolute; inset:-5px; border-radius:12px; pointer-events:none; z-index:5; border:2px solid rgba(255,225,140,.95); box-shadow:0 0 34px rgba(255,213,74,.95), 0 0 70px rgba(255,180,60,.55), inset 0 0 40px rgba(255,213,74,.45); animation:nhCueGlow .95s ease-out forwards; }
@keyframes nhCueGlow{ 0%{ opacity:0 } 12%{ opacity:1 } 55%{ opacity:.75 } 100%{ opacity:0 } }
#newHudOverlay #newHudMovesSlot .nh-cue-shine{ position:absolute; inset:0; overflow:hidden; border-radius:inherit; pointer-events:none; z-index:4; }
#newHudOverlay #newHudMovesSlot .nh-cue-shine::before{ content:''; position:absolute; top:-30%; bottom:-30%; left:-45%; width:32%; background:linear-gradient(105deg, rgba(255,255,255,0) 0%, rgba(255,245,200,.75) 50%, rgba(255,255,255,0) 100%); transform:skewX(-18deg); animation:nhCueShine .7s .1s ease-in-out forwards; }
@keyframes nhCueShine{ 0%{ left:-45% } 100%{ left:140% } }
#newHudOverlay #newHudMovesSlot .nh-cue-spark{ position:absolute; width:7px; height:7px; margin:-3.5px; border-radius:50%; pointer-events:none; z-index:6; background:#fff6d0; box-shadow:0 0 10px rgba(255,213,74,1), 0 0 3px #fff; opacity:0; animation-duration:.62s; animation-timing-function:ease-in-out; animation-fill-mode:forwards; }
#newHudOverlay #newHudMovesSlot .nh-cue-top{ top:0; animation-name:nhCueTop; }
#newHudOverlay #newHudMovesSlot .nh-cue-right{ right:0; animation-name:nhCueRight; }
#newHudOverlay #newHudMovesSlot .nh-cue-bottom{ bottom:0; animation-name:nhCueBottom; }
#newHudOverlay #newHudMovesSlot .nh-cue-left{ left:0; animation-name:nhCueLeft; }
@keyframes nhCueTop{ 0%{ left:0; opacity:0 } 15%{ opacity:1 } 85%{ opacity:1 } 100%{ left:100%; opacity:0 } }
@keyframes nhCueRight{ 0%{ top:0; opacity:0 } 15%{ opacity:1 } 85%{ opacity:1 } 100%{ top:100%; opacity:0 } }
@keyframes nhCueBottom{ 0%{ left:100%; opacity:0 } 15%{ opacity:1 } 85%{ opacity:1 } 100%{ left:0; opacity:0 } }
@keyframes nhCueLeft{ 0%{ top:100%; opacity:0 } 15%{ opacity:1 } 85%{ opacity:1 } 100%{ top:0; opacity:0 } }
#newHudRailSlot{ position:absolute; left:15px; bottom:10px; z-index:12; }

/* --- три кнопки, переставленные в верхний ряд справа (Menu/My Warrior/Chat) ---
   Плиту им рисует единый набор кнопок (класс .btn, 01-main.css); здесь только
   размеры и раскладка: иконка сверху, подпись шрифтом меню снизу. Цвет и фон
   тут не задавать — иначе плита не загорится при наведении. --- */
#newHudTopRailSlot #modeBackBtn, #newHudTopRailSlot #battleWarriorBtn, #newHudTopRailSlot #battleChatBtn{
  flex:1; width:auto !important; height:100% !important; margin:0 !important; min-height:0;
  display:flex !important; flex-direction:column; align-items:center; justify-content:center; gap:2px;
  padding:6px !important; text-align:center; --btn-s:0.16;
  font-family:'Pirata One','Cinzel',serif !important; font-weight:400; font-size:15px !important; letter-spacing:0.02em;
}
/* только значки: подпись на плите 300 px читалась мелко (Andy 09.09.2026); что делает
   кнопка — в подсказке title при наведении */
#newHudTopRailSlot .rail-btn-icon{ display:block !important; width:44px; height:44px; object-fit:contain; filter:drop-shadow(0 2px 3px rgba(0,0,0,0.7)); }
#newHudTopRailSlot .rail-btn-label{ display:none !important; }
#newHudTopRailSlot .rail-btn-ico{ display:block; width:40px; height:40px; margin:2px auto; }
#newHudTopRailSlot .rail-btn-ico svg{ width:100%; height:100%; display:block;
  filter:drop-shadow(0 2px 3px rgba(0,0,0,0.7)); }
#newHudTopRailSlot #battleChatBtnDot{ top:6px !important; right:6px !important; }

.nh-card{
  width:625px; min-width:210px;
  padding:12.2px 34px;
  display:flex; align-items:center; gap:12.2px;
  background:var(--glass-thin) !important;
}
#newCardFoe{ flex-direction:row-reverse; text-align:right; }

.nh-crest{
  width:52.6px; height:67.7px; flex-shrink:0; object-fit:contain;
  filter:drop-shadow(0 1.9px 3.3px rgba(0,0,0,0.75));
}
.nh-card-body{ flex:1; min-width:0; }
/* кольцо — камень у полосы здоровья (G91, 28.09.2026): оно и даёт здоровье.
   Ставит 23-board.js (boardSetRing), нет кольца — камня нет. Цвет — тир. */
.nh-ring{ position:relative; flex-shrink:0; width:50px; height:50px; border-radius:50%;
  background:radial-gradient(circle, #2b2013, #0b0805); border:2px solid var(--ring-c, #c9a227);
  box-shadow:0 0 12px var(--ring-glow, rgba(230,190,80,0.5)), inset 0 0 10px #000; }
.nh-ring img{ position:absolute; left:3px; top:3px; width:40px; height:40px; object-fit:contain; }
.nh-ring-val{ position:absolute; top:100%; left:50%; transform:translateX(-50%); margin-top:1px; white-space:nowrap;
  font-family:'Cinzel',Georgia,serif; font-size:11.5px; font-weight:700; color:var(--ring-c, #c9a227); text-shadow:0 1px 2px #000; }
.nh-ring[data-tier="1"]{ --ring-c:#b9bec4; --ring-glow:rgba(154,160,166,0.4); }
.nh-ring[data-tier="2"]{ --ring-c:#6fa9e6; --ring-glow:rgba(120,180,240,0.55); }
.nh-ring[data-tier="3"]{ --ring-c:#d9b440; --ring-glow:rgba(230,190,80,0.55); }
.nh-ring[data-tier="4"]{ --ring-c:#b58ae6; --ring-glow:rgba(190,140,250,0.6); }

/* --- реальный #p1NameBtn/#p2NameBtn переставлен сюда, снимаем прежнее
   абсолютное позиционирование прода и подгоняем размер под новый макет --- */
#newHudOverlay .fighter-name-plate{
  position:static !important; top:auto !important; left:auto !important; right:auto !important;
  z-index:auto !important; padding:0 !important; background:none !important;
  font-size:21.2px !important; font-weight:700; letter-spacing:0.04em;
  max-width:none !important; flex-wrap:nowrap !important; white-space:nowrap !important;
  margin:0 auto !important; justify-content:center;
}
#newHudOverlay .fighter-name-plate span[id$="NameLabel"]{ color:var(--gold-bright) !important; text-shadow:0 1.9px 3.8px #000; }
#newHudOverlay .fighter-name-plate span[id$="AtkLabel"]{ font-size:14.1px !important; color:rgba(243,226,189,0.75) !important; }
#newHudOverlay .fighter-name-plate span[id$="FirstBadge"]{ font-size:16.9px !important; }

/* --- реальный .hp-frame переставлен сюда --- */
#newHudOverlay .hp-frame{
  width:100% !important; margin-top:6.6px; height:24.4px; aspect-ratio:auto !important;
  background:url('../img/ui/hp_frame_gold.png') center/100% 100% no-repeat !important;
}
#newHudOverlay .hp-frame-inner{ left:10% !important; right:15.8% !important; top:18.8% !important; bottom:22.5% !important; }
#newHudOverlay .hp-frame-label{ font-size:15px !important; }

.nh-meta{ display:flex; align-items:center; gap:5.6px; margin-top:4.7px; font-size:14.1px; color:rgba(243,226,189,0.75); }

/* --- реальный #p1DefStack/#p2DefStack переставлены в свои панели --- */
.nh-def-panel{ padding:18.8px 20.7px; display:flex; flex-direction:column; gap:3.8px; min-width:150.4px; }
.nh-att-row{
  text-align:center; padding-bottom:8.5px; margin-bottom:5.6px;
  border-bottom:1px solid var(--gold-dim);
}
#newHudOverlay .nh-att-row span[id$="AtkLabel"]{
  font-size:18.8px !important; font-weight:700; color:var(--gold) !important;
  letter-spacing:0.06em; white-space:nowrap;
}
#newHudOverlay #p1DefStack, #newHudOverlay #p2DefStack{
  position:static !important; inset:auto !important; top:auto !important; bottom:auto !important;
  left:auto !important; right:auto !important;
  display:flex !important; flex-direction:column; gap:10.3px; align-items:stretch;
}
#newHudOverlay #p1DefStack > span:first-child, #newHudOverlay #p2DefStack > span:first-child{
  font-size:17.4px !important; font-weight:700; letter-spacing:0.22em; color:var(--gold);
  text-align:center; margin-bottom:2.8px;
}
#newHudOverlay .def-stat{ flex-direction:row !important; justify-content:space-between; gap:13.2px; }
#newHudOverlay #p2DefStack .def-stat{ flex-direction:row-reverse !important; }
#newHudOverlay .def-stat img{ width:50.8px !important; height:50.8px !important; }
#newHudOverlay .def-stat span{ font-size:33.8px !important; font-weight:700; }
/* 🔵 ЗНАЧКИ ЗОН СТОЯТ РОВНО (заметил Andy 21.09.2026: «у соперника три символа не
   выровнены»). Строка зоны центрируется в столбике, а её ширина складывалась из
   значка и числа — «125» шире «79» на девять точек, и значок у каждой строки уезжал
   на своё. Числу дана одна ширина на три строки: значки встали друг под другом. */
#newHudOverlay .def-stat span{ min-width:2.1em; text-align:right; }
#newHudOverlay #p2DefStack .def-stat span{ text-align:left; }
/* Точки иммунитета зоны (V122): столбик перед значком зоны, у соперника — снаружи,
   потому что его строка зеркальная (row-reverse). Цвет — стихия, как камешки перков
   в карточке; тёмное кольцо, чтобы точка не тонула на светлом кадре. */
#newHudOverlay .def-imm-dots{ display:flex; flex-direction:column; justify-content:center; gap:3px; min-width:7px; margin:0 1px; align-self:center; }
#newHudOverlay .def-imm-dots:empty{ min-width:0; margin:0; }
#newHudOverlay .def-imm-dots i{ display:block; width:7px; height:7px; border-radius:50%; background:currentColor;
  box-shadow:0 0 0 1px rgba(0,0,0,0.85), 0 0 4px currentColor; }

/* --- реальный #battleSceneBox переставлен в сцену боя, снимаем фикс px-размер --- */
#newHudStage{
  position:absolute; left:215px; right:530px; top:55px; bottom:100px;
  display:flex; align-items:center; justify-content:center;
  z-index:1;
}
#newHudOverlay #battleSceneBox{
  position:relative !important; width:100% !important; height:100% !important;
  max-width:none; left:auto !important; bottom:auto !important;
}
#newHudOverlay #battleSceneImg{ filter:drop-shadow(0 13.2px 15px rgba(0,0,0,0.75)); }
/* ===========================================================================
   ПРОТОКОЛ БОЯ (переделан 02.09.2026 по разбору с Andy).
   ---------------------------------------------------------------------------
   Было: две узкие колонки внутри сцены, прижатые к её краям, во всю высоту.
   Пока бойцы были мелкими, они там никому не мешали. После увеличения бойцы
   пришли ровно туда, и протокол оказался лежащим на груди у героя.

   Стало: плашка над панелью ATT/DEF, в одной колонке с ней и карточкой бойца.
   Сцена освобождена под бойцов целиком.

   Что в плашке (состав задан Andy):
     * номер раунда,
     * значки ударов и цифры урона,
     * мигающее слово more.

   Свёрнута — виден ТОЛЬКО последний отыгранный раунд целиком, все три удара.
   По клику на more раскрывается вниз на ту же ширину: весь матч, сверху
   последний раунд, ниже предыдущие, с прокруткой. Повторный клик сворачивает.

   Раскрытая плашка ЛОЖИТСЯ ПОВЕРХ панели ATT/DEF (z-index 14 против 12), а не
   раздвигает её. Раздвигание дёргало бы всю колонку на каждом раунде; поверх —
   это временное окно, которое игрок сам открыл и сам закроет.
   =========================================================================== */
#newHudOverlay #logColMine, #newHudOverlay #logColTheirs{
  position:absolute !important; top:118px; width:180px !important;
  height:auto !important; z-index:14;
  display:none;                       /* до первого удара плашки нет вовсе */
  flex-direction:column; gap:5px;
  padding:7px 7px 6px; box-sizing:border-box;
  background:var(--panel) !important;
  border:1px solid var(--gold-dim);
  border-radius:8.5px;
  backdrop-filter:blur(6px) saturate(0.9);
  -webkit-backdrop-filter:blur(6px) saturate(0.9);
  box-shadow:0 3.8px 18.8px rgba(0,0,0,0.55), inset 0 0 28.2px rgba(0,0,0,0.35);
  overflow:visible;
}
#newHudOverlay #logColMine.nh-log-on, #newHudOverlay #logColTheirs.nh-log-on{ display:flex; }
/* !important: у плашки в разметке инлайновый display:flex, без него пустое
   стекло с «more» стояло бы на арене до первого удара (Andy 13.09.2026) */
#newHudOverlay #logColMine:not(.nh-log-on), #newHudOverlay #logColTheirs:not(.nh-log-on){ display:none !important; }
#newHudOverlay #logColMine{ left:15px; }
#newHudOverlay #logColTheirs{ right:330px; }

/* Подпись "your attacks" в плашке лишняя: плашка стоит в колонке своего бойца,
   прямо под его карточкой с именем — чья она, видно и без надписи. */
#newHudOverlay #logHeadMine, #newHudOverlay #logHeadTheirs{ display:none !important; }

#newHudOverlay #logMine, #newHudOverlay #logTheirs{
  display:flex; flex-direction:column; gap:5px; align-items:center;
  overflow:hidden; min-height:0;
}
/* Свёрнуто: показываем только первый блок. Первый — потому что addLogRow
   вставляет новый раунд ВВЕРХ (insertBefore), то есть первый и есть последний
   отыгранный. */
/* !important здесь обязателен: addLogRow (12-battle-ui.js) вешает на блок
   раунда инлайн-стиль display:flex, а инлайн бьёт любой селектор без него.
   Без !important плашка молча показывала все раунды сразу. */
#newHudOverlay .nh-log:not(.nh-log-open) #logMine > div:not(:first-child),
#newHudOverlay .nh-log:not(.nh-log-open) #logTheirs > div:not(:first-child){
  display:none !important;
}
/* Раскрытая плашка накрывает панель ATT/DEF ЦЕЛИКОМ, до самого её низа
   (118 + 528 = 646 = низ панели DEF). Промежуточная высота выглядела поломкой:
   плашка резала панель посередине, шапка "ATT/DEF" уходила под неё, а нули
   защиты торчали снизу сиротами. Либо не накрывать вовсе, либо накрывать
   полностью — середины тут нет. */
#newHudOverlay .nh-log.nh-log-open{ min-height:528px; }
#newHudOverlay .nh-log.nh-log-open #logMine,
#newHudOverlay .nh-log.nh-log-open #logTheirs{
  max-height:462px; overflow-y:auto; overflow-x:hidden;
}
/* more/less прижимается к низу раскрытой плашки: он там же, где был до
   раскрытия по вертикали относительно края, и его не надо искать заново. */
#newHudOverlay .nh-log.nh-log-open .nh-log-more{ margin-top:auto; }

/* Слово more. Мигает, чтобы его заметили: это единственный элемент протокола,
   на который вообще нужно нажимать. Появляется только когда раскрывать есть
   что — иначе мигало бы впустую (см. nhLogRefresh в 16-newhud.js). */
#newHudOverlay .nh-log-more{
  display:none; align-self:center; margin-top:1px;
  background:none; border:none; padding:2px 6px; cursor:pointer;
  font-family:'Cinzel',serif; font-size:11px; font-weight:700; letter-spacing:.08em;
  text-transform:lowercase; color:var(--gold-bright);
  text-shadow:0 1px 2px rgba(0,0,0,.9);
  animation:nhLogMoreBlink 1.6s ease-in-out infinite;
}
#newHudOverlay .nh-log-more.nh-log-more-on{ display:block; }
/* Раскрытая плашка своё more не мигает: игрок уже нашёл его и нажал. */
#newHudOverlay .nh-log.nh-log-open .nh-log-more{ animation:none; opacity:.85; }
@keyframes nhLogMoreBlink{
  0%,100%{ opacity:1; }
  50%{ opacity:.32; }
}
@media (prefers-reduced-motion: reduce){
  #newHudOverlay .nh-log-more{ animation:none; }
}

/* Размер значков и цифр в протоколе (выкручен по максимуму 02.09.2026).
   ---------------------------------------------------------------------------
   Бюджет ширины считался, а не подбирался на глаз: плашка 180, поля по 7 —
   внутри остаётся 166. Строка это два кружка, зазор между ними и число.
   При кружках по 54 и зазорах 2x4 на число остаётся 50 — двузначному при
   кегле 30 нужно около 33. Влезает с запасом.

   Реальный код задаёт кружку 19px инлайн-стилем, поэтому оба места (див и
   картинку внутри) перебиваем через !important.

   Прежние 38px и кегль 11 съедали меньше половины доступной ширины, а на
   телефоне превращались в нечитаемую мелочь: холст 1700 ужимается под ширину
   экрана, и на 844 точках кегль 11 становится пятью. */
#newHudOverlay #logColMine div:has(> .log-icon-img),
#newHudOverlay #logColTheirs div:has(> .log-icon-img){
  width:54px !important; height:54px !important; border-width:3px !important;
}
#newHudOverlay .log-icon-img{ width:54px !important; height:54px !important; }
#newHudOverlay #logColMine .choice-row, #newHudOverlay #logColTheirs .choice-row{ gap:4px !important; }
#newHudOverlay #logMine > div > div, #newHudOverlay #logTheirs > div > div{ gap:4px !important; }

/* Цифра урона. Кегль задан под ОБЫЧНЫЙ случай — одна-две цифры, — и ужимается
   только когда разрядов больше. Держать весь протокол мелким ради редкого
   трёхзначного урона неправильно: платит каждый бой за случай, которого почти
   не бывает. Класс len-N вешает addLogRow (12-battle-ui.js). */
#newHudOverlay .log-dmg{
  font-size:30px !important; line-height:1; white-space:nowrap;
  font-variant-numeric:tabular-nums;
}
#newHudOverlay .log-dmg.len-3{ font-size:23px !important; }
#newHudOverlay .log-dmg.len-4{ font-size:17px !important; }
/* Заголовок раунда — тоже крупнее: он подпись ко всей плашке, а был 10px. */
#newHudOverlay #logMine > div > div:first-child,
#newHudOverlay #logTheirs > div > div:first-child{ font-size:15px !important; letter-spacing:.06em; }
#newHudOverlay #turnTimerOverlay{ align-items:flex-start !important; padding-top:6px; }

/* --- реальная #battleChoicePanel (атаки/блоки) переставлена сюда, обёртка
   переиспользует настоящий класс .control-panel ради готового золотого фона --- */
.nh-moves-wrap{ width:244.4px; flex-shrink:0; }
#newHudOverlay .control-panel{
  position:relative;
  width:100%; height:100%; box-sizing:border-box;
  padding:13px 16px !important;
  display:flex !important; flex-direction:column;
  background:var(--panel) !important;
  border-radius:8.5px !important;
  backdrop-filter:blur(6px) saturate(0.9);
  -webkit-backdrop-filter:blur(6px) saturate(0.9);
  box-shadow:0 3.8px 18.8px rgba(0,0,0,0.55), inset 0 0 28.2px rgba(0,0,0,0.35) !important;
}
#newHudOverlay .atk-col > p, #newHudOverlay .blk-col > p{
  position:relative; text-align:center !important;
  margin-bottom:8.5px !important;
  display:flex !important; align-items:center; justify-content:center; gap:10px;
}
#newHudOverlay .atk-col > p::before, #newHudOverlay .atk-col > p::after,
#newHudOverlay .blk-col > p::before, #newHudOverlay .blk-col > p::after{
  content:''; display:inline-block; flex-shrink:0;
  width:30px; height:19px;
  background:url('../img/ui/flourish.png') center/contain no-repeat;
}
#newHudOverlay .atk-col > p::after, #newHudOverlay .blk-col > p::after{
  transform:scaleX(-1);
}
#newHudOverlay .choice-row button[data-zone="head"]{ background-image:url('../img/ui/zone_head_gold.png') !important; }
#newHudOverlay .choice-row button[data-zone="body"]{ background-image:url('../img/ui/zone_body_gold.png') !important; }
#newHudOverlay .choice-row button[data-zone="legs"]{ background-image:url('../img/ui/zone_legs_gold.png') !important; }
#newHudOverlay .choice-row button{
  width:69px !important; height:69px !important; border-radius:var(--r-round);
  background-color:rgba(18,13,8,0.72) !important;
  background-size:58% !important; background-position:center !important;
  border:1px solid var(--gold-dim) !important;
}
#newHudOverlay .choice-row{ margin-bottom:4px !important; }
#newHudOverlay .choice-row button.zone-btn-selected{
  background-color:rgba(60,40,14,0.85) !important;
  border-color:var(--gold) !important;
}
#newHudOverlay .ab-row{ flex-direction:column !important; gap:6px; }
#newHudOverlay .atk-col, #newHudOverlay .blk-col{ width:100%; }
#newHudOverlay #fightBtn{
  width:100% !important; margin-top:5px !important;
  padding:21px 0 !important; font-size:19px !important;
  border-radius:0 !important; letter-spacing:0.12em;
  background:
    url('../img/ui/button_frame_gold.png') center/100% 100% no-repeat,
    url('../img/ui/button_plate.png') center/100% 100% no-repeat !important;
  border:none !important; box-shadow:none !important;
}
#newHudOverlay #battleChatBtn{ width:100%; margin-top:5.6px !important; }

/* --- статус-текст + fight-обёртка --- */
#newHudFightWrap{
  position:absolute; left:692.5px; transform:translateX(-50%);
  bottom:15px; display:flex; flex-direction:column; align-items:center; gap:10px;
  width:660px; z-index:15;
}
/* Строка раунда — каменная плита (класс .plate из единого набора, без рун) в золотой
   оправе по периметру; оправу рисует ::after ниже. Отступы текста считаны под ширину
   оправы: с прежними 15 px сверху и снизу буквы упирались бы в золото. */
#newHudOverlay #statusText{
  position:relative !important; margin:0 !important; width:100%;
  font-size:25px !important; border-radius:0 !important;
  padding:24px 64px !important; line-height:1.35;
  --btn-s:0.2; --btn-stone:url('../img/ui/btn/slab_plain.webp');
  font-family:'Cinzel',serif; font-weight:700; letter-spacing:0.02em;
  text-shadow:0 1px 3px rgba(0,0,0,0.9), 0 0 12px rgba(0,0,0,0.6);
}
/* Третья редакция (Andy 10.09.2026: «обрезки какие-то сбоку; может, так же, как на
   стеклянных плашках, золото по периметру?»). Так и сделано. Почему прежнее выглядело
   огрызками: `text_swag.png` — это два завитка, растянутых по краям плиты, и на узком
   экране от них оставались обрубки. Теперь плашка носит ТУ ЖЕ золотую оправу, что
   стеклянные окна (`frame_ornate.png`, см. `.nh-panel::before` выше): рамка нарезана
   на девять кусков, углы не тянутся, поэтому на любой ширине она цельная.
   `fill` не ставим — середина должна остаться камнем. */
#newHudOverlay #statusText::after{
  content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
  border:24px solid transparent;
  border-image:url('../img/ui/frame_ornate.png') 100 stretch;
}

/* --- пост-боевая панель, переставлена как модалка внутри нового HUD --- */
/* Итоги боя — в правой колонке на месте ударов и блоков (Andy 09.09.2026: «торчит
   посреди экрана»): после боя та колонка пуста и не нужна. Панель накрывает её
   непрозрачно, кнопки столбиком. */
#newHudPostBattleSlot{
  position:absolute; inset:auto; right:15px; top:125px; width:300px; height:620px; z-index:30;
  display:flex; align-items:stretch; justify-content:center;
  pointer-events:none;
}
#newHudOverlay #postBattlePanel{
  pointer-events:auto;
  width:100%; max-width:none; height:100%; box-sizing:border-box; overflow:auto;
  margin:0 !important; padding:14px 12px 10px !important;
  background:var(--c-wood-900) !important;
  border:1px solid var(--gold-dim); border-radius:8.5px;
  display:flex; flex-direction:column; align-items:stretch; gap:8px;
}
#newHudOverlay #postBattlePanel[style*="display: block"]{ display:flex !important; }
#newHudOverlay #postBattlePanel #resultBanner{ margin-bottom:4px !important; }
#newHudOverlay #postBattlePanel #campaignRewardBanner{ max-width:100% !important; margin:0 0 6px !important; padding:10px 10px 12px !important; }
#newHudOverlay #postBattlePanel > div:last-of-type{ flex-direction:column; align-items:stretch; gap:8px !important; }
#newHudOverlay #postBattlePanel .postbattle-btn{ width:100%; margin:0 !important; }

/* Andy 09.09.2026: «плашка хорошая, но очень мелко — укрупни всё». Почему мелко:
   боевой экран нарисован на холсте 1700×760 и целиком сжимается под окно браузера
   (fitNewHud), на обычном ноутбуке примерно в 0,8 — то есть 13 px разметки
   превращаются в 10 px на стекле. Поэтому размеры здесь заданы «с запасом», под
   этот коэффициент, а не по тому, как они смотрятся в разметке.
   Везде !important: размеры в самой разметке стоят инлайном (а в денежной карточке
   их рисует JS строкой), и без него класс их не перебивает.
   Ширину столбика НЕ трогаем: правее 300 px начинается панель защиты соперника
   (right:330px), и панель накрыла бы её. Место берём по высоте — её 620 px,
   а содержимого едва на треть. */
#newHudOverlay #postBattlePanel{ padding:18px 16px 14px !important; gap:10px; }
#newHudOverlay #postBattlePanel #resultText{ font-size:40px !important; }
#newHudOverlay #postBattlePanel #campaignRewardBanner{ padding:14px 14px 16px !important; }
#newHudOverlay #postBattlePanel #rankChangeLine{ font-size:21px !important; margin-top:10px !important; }
#newHudOverlay #postBattlePanel #rankQuoteLine{ font-size:17px !important; }
#newHudOverlay #postBattlePanel #slotUnlockLine{ font-size:19px !important; }
/* денежная карточка: её html собирает moneyBreakdownCardHtml (11-summary.js) с
   инлайновыми 15/14/17 px — поднимаем все три уровня сразу */
#newHudOverlay #postBattlePanel #rewardCoinsBox > div{ padding:12px 14px !important; }
#newHudOverlay #postBattlePanel #rewardCoinsBox div{ font-size:19px !important; }
#newHudOverlay #postBattlePanel #rewardCoinsBox span{ font-size:20px !important; }
#newHudOverlay #postBattlePanel .postbattle-btn{ font-size:21px !important; min-height:52px; padding:12px 18px !important; --btn-s:0.26; }
#newHudOverlay #postBattlePanel #randomOppStatus{ font-size:15px !important; }

/* позиция баннера эскалации задана ниже, в блоке про таймер хода (V28) */
#newHudOverlay #opponentGoneBox{ margin-top:7.5px !important; }

/* 🔴 ТАЙМЕР ХОДА ПРИБИТ К РАМКЕ ЭКРАНА, А НЕ К ОКНУ СЦЕНЫ (V28, 11.09.2026).
   Он живёт внутри battleSceneBox, а окно сцены — гибкий элемент ряда #newHudStage:
   стоило показаться баннеру эскалации (с 7 раунда), как он вставал СОСЕДОМ окна
   сцены и сдвигал её вправо на 44 точки, утаскивая таймер за собой прямо на
   плашку соперника. Andy 11.09.2026: «0:17» над «Freya (Bot)». Замерено на
   полигоне: без баннера таймер слева 638, с баннером 682, а плашка соперника
   начинается с 754 при ширине таймера 110.
   Лечение: элемент переезжает в #newHudFrame (так же, как значок «бьёт первым»,
   см. 16-newhud.js) и садится в зазор между карточками бойцов по координатам
   самой рамки. Карточки стоят 15..631 и 754..1370 — зазор 631..754.
   display не трогаем: его переключает существующий JS через style.display. */
#newHudFrame > #turnTimerOverlay{
  position:absolute !important; inset:auto !important; transform:none !important;
  left:631px !important; top:15px !important;
  width:123px !important; height:92px !important;
  align-items:center !important; justify-content:center !important;
  z-index:14 !important;
}
/* Баннер эскалации — ПОВЕРХ верха арены, а не соседом окна сцены в одном ряду.
   Та же причина, что у таймера: в ряду он двигал всю сцену вместе с бойцами. */
#newHudOverlay #escalationBanner{
  position:absolute !important; left:50% !important; top:58px !important; right:auto !important;
  transform:translateX(-50%) !important; margin:0 !important;
  white-space:nowrap; z-index:14 !important;
}
#newHudOverlay #turnTimerBox{ font-size:32px !important; }
/* Значок «бьёт первым» стоит НАД ГОЛОВОЙ бойца, а не между полосками здоровья.
   Координаты — те же, по которым конвейер ставит бойцов на холст 1700x760:
   герой 374, соперник 1011, темя на 115. Значок садится над теменем.
   Уровень 13 — выше слоя с бойцами (5) и его притемнения, но ниже панелей. */
#newHudFrame > .first-strike-icon{
  position:absolute !important; top:96px !important; font-size:52px !important;
  z-index:13 !important; margin:0 !important;
}
#newHudFrame > #p1FirstIcon{ left:374px !important; right:auto !important;
  transform:translateX(-50%) !important; }
#newHudFrame > #p2FirstIcon{ left:1011px !important; right:auto !important;
  transform:translateX(-50%) !important; }

/* --- нижний рельс: реальные кнопки Menu/My Warrior/Chat --- */
#newHudRailSlot{ display:flex; align-items:center; gap:9.4px; flex-wrap:wrap; }
#newHudOverlay #modeBackBtn, #newHudOverlay #battleWarriorBtn,
#newHudOverlay #battleChatBtn{
  background:var(--panel) !important; border:1px solid var(--gold-dim) !important;
  color:var(--gold-bright) !important; font-family:'Cinzel',serif !important;
  font-size:12.7px !important; font-weight:600; padding:9.4px 12.2px !important;
  border-radius:7.5px !important; backdrop-filter:blur(6px);
  -webkit-backdrop-filter:blur(6px); width:auto !important; margin:0 !important;
  white-space:nowrap;
}

/* --- компактная плашка турнира, переставленная сюда целиком из шапки страницы
   (см. setNewHudVisible) — перебиваем инлайн-стили полноширинного бара под
   размер рельса кнопок, сам текст/таймер/клик не трогаем --- */
/* плита рисуется единым набором (класс .plate), здесь только размер под рельс */
/* Andy 09.09.2026: кнопка «View Bracket» снята, нажимается вся плита — место,
   которое она занимала, ушло в размер текста. */
/* 🔴 display здесь НЕ задавать. До 10.09.2026 стояло `display:inline-flex !important`,
   и оно перебивало команду кода «спрятать»: у игрока без турнира (и вообще без
   аккаунта) плита всё равно висела в рельсе — с образцом текста из разметки вместо
   таймера. Andy принял это за «таймер не идёт». Видимостью распоряжается только
   updateTournamentBar; рельс — flex-строка, ей `display:flex` от кода годится. */
#newHudRailSlot #tournamentBar{
  position:static !important; width:auto !important;
  font-family:'Cinzel',serif !important;
  /* крупнее (Andy 13.09.2026). Слева от плашки состояния всего ~350 точек, в одну
     строку крупный текст не влезает и уходил бы под неё — поэтому в две строки */
  font-size:24px !important; font-weight:700; padding:12px 18px !important; --btn-s:0.23;
  gap:8px !important; white-space:normal; max-width:335px; line-height:1.15; text-align:center;
  align-items:center; justify-content:center; margin:0 !important;
  letter-spacing:0.02em;
}

@media (orientation:portrait){
  #newHudOverlay{ display:none !important; }
}

/* ============================================================
   Видео-набор боевых сцен (флаг ?vidfx=1, модуль 17-battlevid.js).
   Класс vidfx вешается на <html> из JS.

   Зачем всё ниже: у видео-набора фон запечён в кадр, а не вырезан
   по альфе. Из-за этого прежняя раскладка показывала ДВЕ арены сразу —
   #newHudArena во весь холст и кадр со своей ареной в прямоугольнике
   посередине. Сцена растягивается на весь холст, а затемнение краёв
   (без него золотой текст тонет в небе) переезжает поверх видео.
   ============================================================ */

/* 0. Единственная ручка настройки: на сколько кадр уезжает влево.
   Причина сдвига — асимметрия панелей. Справа их 515px (DEF 1190-1370 +
   удары 1385-1685), слева всего 195px (DEF 15-195). Свободная зона получается
   195..1190 с центром 692, а кадр центрируется по центру холста, 850.
   Пара бойцов занимает 363..1213, центр 788 — значит честный ход около 100px.
   Замерено на живой странице 23.08.2026. Крутить только это число. */
html.vidfx{ --vidfx-shift:100px; }

/* 1. Сцена на весь холст вместо прямоугольника между панелями. */
html.vidfx #newHudStage{ left:0; right:0; top:0; bottom:0; }

/* 1a. Сдвиг честный: кадр не масштабируется, просто уезжает влево. Левый край
   уходит за границу холста и обрезается его overflow:hidden, справа
   открывается полоса ровно в --vidfx-shift шириной — её гасит чернотой
   пункт 3. Вариант со сжатием кадра отвергнут: он добавлял ещё 8% обрезки
   по высоте, а там и так режутся кончик меча и ступни. */
html.vidfx #newHudOverlay #battleSceneImg{
  transform:translateX(calc(var(--vidfx-shift) * -1));
}

/* 1b. Под сценой лежала #newHudArena с той же arena_castle.jpg — вторая арена.
   Без неё в открывшейся полосе справа проступал бы замок вместо черноты.
   Видео-набору она не нужна вовсе: арена запечена в сам кадр. */
html.vidfx #newHudArena{ display:none; }
html.vidfx #newHudOverlay #battleSceneBox{ background:var(--c-ink); }

/* 2. Заполнять кадр целиком, без полей по краям.
   Кадр 16:9, холст 2.24:1 — по высоте обрезается ~20%. Veo умеет только
   16:9 и 9:16, 21:9 не существует, поэтому обрезка неизбежна. 55% по
   вертикали — компромисс: целиком влезает занесённый меч, ступни подрезаны
   минимально. Число подбирается глазами, крутить тут. */
html.vidfx #newHudOverlay #battleSceneImg{
  object-fit:cover !important;
  object-position:center 55% !important;
}

/* 3. Затемнение краёв. Нижние два градиента скопированы один в один
   с #newHudArena::after — визуально всё как было, изменился только слой:
   было под сценой, стало над ней. z-index 3: выше видео (2), ниже колонок
   протокола (8), таймера и всплывашки чата (46-49).

   Верхний градиент — новый. Он гасит правый край до ПОЛНОЙ черноты ровно
   на ширину --vidfx-shift, то есть там, где кадр обрывается после сдвига,
   и растворяет стык плавно на 260px влево. Стыка не видно, кадр просто
   уходит в темноту, а поверх неё стоит панель ударов. */
html.vidfx #newHudOverlay #battleSceneBox::after{
  content:'';
  position:absolute; inset:0;
  pointer-events:none;
  z-index:3;
  background:
    linear-gradient(to left,
      rgba(6,5,4,1) 0,
      rgba(6,5,4,1) var(--vidfx-shift),
      rgba(6,5,4,0) calc(var(--vidfx-shift) + 260px)),
    linear-gradient(to bottom, rgba(6,5,4,0.62) 0%, rgba(6,5,4,0.15) 26%, rgba(6,5,4,0.12) 55%, rgba(6,5,4,0.82) 100%),
    linear-gradient(to right, rgba(6,5,4,0.72) 0%, rgba(6,5,4,0) 24%, rgba(6,5,4,0) 76%, rgba(6,5,4,0.72) 100%);
}

/* 4. Колонки протокола лежат ВНУТРИ сцены. Сцена разъехалась на весь холст —
   без этого они уедут к краям экрана и налезут на карточки и панели DEF.
   Прибиваем к прежним экранным координатам: 215+8 слева, 530+8 справа,
   55+58 сверху. Высота была 605-66=539. */
/* Пришпиливание протокола к сцене для видеорежима убрано 02.09.2026: колонки
   больше не живут внутри сцены, они переехали в общую колонку экрана рядом с
   карточкой бойца и панелью ATT/DEF, и от растягивания сцены не зависят. */

/* ===========================================================================
   Подсветка зоны при попадании (30.08.2026).
   flashHit(who,zone) в 12-battle-ui.js всегда искал #{who}{Zone}Flash — таких
   элементов в разметке никогда не было, функция молча ничего не делала на
   каждом ударе с самого начала. Чинится не новым элементом, а тем же самым
   .def-stat, который уже стоит рядом с числом защиты той же зоны — так игрок
   видит "сюда попали" и "сколько тут защиты" в одном месте, без нового арта.
   Работает в обоих HUD (старом и #newHudOverlay), т.к. .def-stat общий класс. */
@keyframes zoneHitFlash{
  0%{ box-shadow:0 0 0 0 rgba(255,92,66,0.85); background:rgba(255,92,66,0.32); }
  55%{ box-shadow:0 0 16px 5px rgba(255,92,66,0.5); background:rgba(255,92,66,0.14); }
  100%{ box-shadow:0 0 0 0 rgba(255,92,66,0); background:transparent; }
}
.def-stat.zone-hit-flash{ animation:zoneHitFlash 550ms ease-out; border-radius:6px; }

/* ===========================================================================
   Прототип FX-слоя удара (флаг ?fxproto=1, раздел 16 docs/СТРАТЕГИЯ.md).
   Сравнение "вариант A" (только эффекты, без нового видео) — дрожание сцены
   и кольцо-иконка исхода по центру, поверх статичного кадра/idle-петли.
   Без флага html.fxproto не ставится классом (99-init.js) — ничего не грузится
   и не анимируется. */
@keyframes fxprotoShake{
  0%,100%{ transform:translate(0,0); }
  20%{ transform:translate(-6px,2px); }
  40%{ transform:translate(5px,-3px); }
  60%{ transform:translate(-4px,-2px); }
  80%{ transform:translate(3px,3px); }
}
html.fxproto #battleSceneBox.fxproto-shake,
html.fxproto #newHudOverlay #battleSceneBox.fxproto-shake{
  animation:fxprotoShake 320ms ease-in-out;
}
@keyframes fxprotoRing{
  0%{ transform:translate(-50%,-50%) scale(0.4); opacity:0; }
  25%{ opacity:1; }
  100%{ transform:translate(-50%,-50%) scale(1.9); opacity:0; }
}
.fxproto-outcome-ring{
  position:absolute; left:50%; top:50%; width:64px; height:64px;
  border-radius:50%; border:5px solid var(--fxproto-color, #5fd068);
  pointer-events:none; z-index:45;
  animation:fxprotoRing 480ms ease-out forwards;
}
html.fxproto #battleSceneBox, html.fxproto #newHudOverlay #battleSceneBox{ overflow:visible; }

/* 🔴 ВСПЫШКА ПОЛОСЫ ЗДОРОВЬЯ ПРИ ВСТРЕЧНОМ УРОНЕ (G42, 11.09.2026).
   Riposte и Retribution снимают здоровье с того, кто бил, и никакой пометки
   на нём не было: вспышка зоны висит только на попадании по защищающемуся.
   Andy 11.09.2026 увидел, как у Брэдли «закончились очки жизни без всякого
   удара», — это был рипост. Класс вешает и снимает showCounterDamage
   (12-battle-ui.js). */
/* 🔴 ПУРПУР, А НЕ КРАСНЫЙ (Andy 20.09.2026). Вспышка полосы на сдаче сдачи
   говорит о том же событии, что печать Riposte/Retribution на доске, —
   значит и цвет у них один, семьи «ярость и сдача сдачи». Тусклый красный
   рядом с красной цифрой снятого здоровья читался как обычный урон. */
@keyframes hpCounterFlash{
  0%   { box-shadow:0 0 0 0 rgba(183,75,255,0); }
  18%  { box-shadow:0 0 12px 5px rgba(183,75,255,0.95); }
  100% { box-shadow:0 0 0 0 rgba(183,75,255,0); }
}
#newHudOverlay .hp-frame.hp-counter-flash{ animation:hpCounterFlash 0.85s ease-out 1; }

/* 🔴 НАЧАЛО РАУНДА: РЕГЕНЕРАЦИЯ И ОЖОГ — НА ПЛАШКЕ ТОГО, У КОГО СРАБОТАЛО
   (Andy 16.09.2026: «непонятно, у кого из игроков сработала»). Раньше обе
   надписи выходили крупным баннером посреди экрана — одинаково для обоих
   бойцов, и понять, кому прибавилось, было нельзя. Теперь полоса здоровья
   вспыхивает своим цветом (зелёным на лечении, красным на ожоге), а надпись
   стоит на самой плашке этого бойца. */
/* 🔴 Ч5 (Andy 26.09.2026): «регенерация считывается плохо… вся плашка здоровья
   чтобы вспыхнула зелёным, цифры побольше». Вспышка была одна, 0,9 с, по краю
   полосы — теперь два удара за 1,7 с: светится вся плашка бойца, по полосе
   бежит волна, число здоровья загорается своим цветом. Надпись под плашкой —
   крупное «+24» со словом над ним, держится почти три секунды. */
#newHudOverlay .hp-frame.hp-regen-flash{ animation:hpRegenFlash 1.7s ease-out 1; }
/* Ожог ездил на вспышке сдачи сдачи — теперь у него свой огонь, тот же, что
   у печати BURNING на доске. Один цвет на одно событие. */
#newHudOverlay .hp-frame.hp-burn-flash{ animation:hpBurnFlash 1.7s ease-out 1; }
@keyframes hpBurnFlash{
  0%   { box-shadow:0 0 0 0 rgba(255,74,26,0); }
  12%  { box-shadow:0 0 18px 8px rgba(255,74,26,0.95); }
  34%  { box-shadow:0 0 6px 2px rgba(255,74,26,0.35); }
  52%  { box-shadow:0 0 18px 8px rgba(255,74,26,0.9); }
  100% { box-shadow:0 0 0 0 rgba(255,74,26,0); }
}
@keyframes hpRegenFlash{
  0%   { box-shadow:0 0 0 0 rgba(126,217,87,0); }
  12%  { box-shadow:0 0 18px 8px rgba(126,217,87,0.95); }
  34%  { box-shadow:0 0 6px 2px rgba(126,217,87,0.35); }
  52%  { box-shadow:0 0 18px 8px rgba(126,217,87,0.9); }
  100% { box-shadow:0 0 0 0 rgba(126,217,87,0); }
}
/* Вся плашка бойца (герб, имя, полоса) — зелёным или огнём, в такт полосе. */
#newHudOverlay .nh-card.card-regen-flash{ animation:cardRegenFlash 1.7s ease-out 1; }
#newHudOverlay .nh-card.card-burn-flash{ animation:cardBurnFlash 1.7s ease-out 1; }
@keyframes cardRegenFlash{
  0%   { box-shadow:0 0 0 0 rgba(126,217,87,0), inset 0 0 0 0 rgba(126,217,87,0); }
  12%  { box-shadow:0 0 26px 6px rgba(126,217,87,0.75), inset 0 0 34px 6px rgba(126,217,87,0.45); }
  34%  { box-shadow:0 0 8px 1px rgba(126,217,87,0.25), inset 0 0 12px 2px rgba(126,217,87,0.15); }
  52%  { box-shadow:0 0 26px 6px rgba(126,217,87,0.7), inset 0 0 34px 6px rgba(126,217,87,0.4); }
  100% { box-shadow:0 0 0 0 rgba(126,217,87,0), inset 0 0 0 0 rgba(126,217,87,0); }
}
@keyframes cardBurnFlash{
  0%   { box-shadow:0 0 0 0 rgba(255,74,26,0), inset 0 0 0 0 rgba(255,74,26,0); }
  12%  { box-shadow:0 0 26px 6px rgba(255,74,26,0.7), inset 0 0 34px 6px rgba(255,74,26,0.4); }
  34%  { box-shadow:0 0 8px 1px rgba(255,74,26,0.25), inset 0 0 12px 2px rgba(255,74,26,0.15); }
  52%  { box-shadow:0 0 26px 6px rgba(255,74,26,0.65), inset 0 0 34px 6px rgba(255,74,26,0.35); }
  100% { box-shadow:0 0 0 0 rgba(255,74,26,0), inset 0 0 0 0 rgba(255,74,26,0); }
}
/* Волна по полосе здоровья: светлая полоса проходит слева направо дважды. */
#newHudOverlay .hp-frame.hp-regen-flash .hp-frame-inner::after,
#newHudOverlay .hp-frame.hp-burn-flash .hp-frame-inner::after{
  content:''; position:absolute; inset:0; pointer-events:none;
  background-repeat:no-repeat; background-size:45% 100%;
  animation:hpTickSweep 0.85s ease-in-out 2;
}
#newHudOverlay .hp-frame.hp-regen-flash .hp-frame-inner::after{
  background-image:linear-gradient(90deg, rgba(190,255,160,0) 0%, rgba(190,255,160,0.95) 50%, rgba(190,255,160,0) 100%);
}
#newHudOverlay .hp-frame.hp-burn-flash .hp-frame-inner::after{
  background-image:linear-gradient(90deg, rgba(255,170,90,0) 0%, rgba(255,170,90,0.95) 50%, rgba(255,170,90,0) 100%);
}
@keyframes hpTickSweep{
  0%   { background-position:-80% 0; }
  100% { background-position:180% 0; }
}
/* Число здоровья («318 / 500») загорается цветом события, строка чуть растёт.
   Растёт вся строка целиком, а не одно число: иначе число наезжает на «YOU». */
#newHudOverlay .hp-frame.hp-regen-flash .hp-frame-label,
#newHudOverlay .hp-frame.hp-burn-flash .hp-frame-label{ animation:hpTickNum 1.7s ease-out 1; }
#newHudOverlay .hp-frame.hp-regen-flash .hp-frame-label span[id$="hpText"]{ color:#b8ff9a; }
#newHudOverlay .hp-frame.hp-burn-flash .hp-frame-label span[id$="hpText"]{ color:#ffb27a; }
@keyframes hpTickNum{
  0%   { transform:scale(1); }
  14%  { transform:scale(1.22); }
  70%  { transform:scale(1.08); }
  100% { transform:scale(1); }
}
/* Надпись под плашкой: слово мелко, число крупно. */
#newHudOverlay .nh-card .hp-tick-tag{
  position:absolute; left:50%; top:calc(100% + 4px); transform:translateX(-50%);
  z-index:44; pointer-events:none; white-space:nowrap;
  display:flex; flex-wrap:wrap; align-items:baseline; justify-content:center; column-gap:6px;
  font-family:'Cinzel',Georgia,serif; font-weight:700; letter-spacing:.04em;
  padding:4px 16px 5px; border-radius:8px;
  background:rgba(10,8,5,0.86); border:1.5px solid rgba(217,180,92,.55);
  text-shadow:0 2px 4px #000; animation:hpTickTag 2.9s ease-out forwards;
}
#newHudOverlay .nh-card .hp-tick-tag .tick-word{
  flex:0 0 100%; text-align:center; font-size:13px; letter-spacing:.14em; text-transform:uppercase; opacity:.9;
}
#newHudOverlay .nh-card .hp-tick-tag .tick-num{ font-size:34px; line-height:1.05; }
#newHudOverlay .nh-card .hp-tick-tag .tick-hp{ font-size:17px; }
#newHudOverlay .nh-card .hp-tick-tag.tick-regen{ color:#8ef06a; border-color:rgba(126,217,87,.8); box-shadow:0 0 26px rgba(126,217,87,.5); }
#newHudOverlay .nh-card .hp-tick-tag.tick-fire{ color:#ff9a4a; border-color:rgba(255,154,74,.8); box-shadow:0 0 26px rgba(255,120,40,.5); }
@keyframes hpTickTag{
  0%{ opacity:0; transform:translate(-50%,14px) scale(.7); }
  9%{ opacity:1; transform:translate(-50%,0) scale(1.12); }
  16%{ transform:translate(-50%,0) scale(1); }
  85%{ opacity:1; transform:translate(-50%,-2px); }
  100%{ opacity:0; transform:translate(-50%,-10px); }
}

/* ===========================================================================
   ДОСКА ПОЕДИНКА (23-board.js, решение Andy 13.09.2026; вторая версия того же дня)
   ---------------------------------------------------------------------------
   Удары показывает не пара бойцов, а доска: столбик из трёх зон у каждого с
   числом защиты снаружи, меч у бьющего и щит у защищающегося (роли
   взаимоисключающие), полоса света от меча к зоне, штамп исхода, летопись
   раунда внизу, строка «кто бьёт» сверху. Материалы те же, что у панелей:
   тёмное стекло и золотая рамка (.nh-panel), значки зон из столбца выбора,
   шрифты меню. Тёплая рамка — атака, холодная — защита.
   Слой лежит в #newHudFrame на уровне 11: выше #newHud (10) с видео, ниже
   значков «бьёт первым» (13) и баннера перка (45), которые стоят на рамке.
   На время доски класс board-on на рамке прячет панели DEF и плашки протокола;
   доска тянется от левого края до столбца выбора (Andy 13.09.2026: во весь
   экран бойцы слишком далеко друг от друга), столбец выбора остаётся виден.
   Геометрия внутри доски дублируется числами в 23-board.js (центры зон,
   кончики мечей) — менять вместе.
   =========================================================================== */
#boardLayer{
  position:absolute; inset:0; z-index:11; display:none; pointer-events:none;
  opacity:0; transition:opacity .26s ease;
}
#boardLayer.board-on{ opacity:1; }
/* боковые панели уходят, пока доска на экране; между раундами возвращаются */
#newHudFrame #newHudDefSlotYou, #newHudFrame #newHudDefSlotFoe,
#newHudFrame #logColMine, #newHudFrame #logColTheirs{ transition:opacity .26s ease; }
#newHudFrame.board-on #newHudDefSlotYou, #newHudFrame.board-on #newHudDefSlotFoe,
#newHudFrame.board-on #logColMine, #newHudFrame.board-on #logColTheirs{ opacity:0 !important; pointer-events:none; }
/* пелены на весь экран нет (Andy 13.09.2026): вокруг доски всё остаётся ярким,
   петля позади темнеет только под её стеклом */
#boardLayer .board-panel{
  position:absolute; left:15px; top:122px; width:1355px; height:506px;
  background:var(--glass-solid, rgba(10,8,6,0.78));
}
#boardLayer .board-in{ position:absolute; inset:0; font-family:'Cinzel',Georgia,serif; color:var(--c-gold-bright); }

/* строка «кто бьёт» */
#boardLayer .board-head{
  position:absolute; left:0; right:0; top:14px; display:flex; align-items:baseline; justify-content:center; gap:18px;
}
#boardLayer .board-head-who{
  font-family:'Pirata One','Cinzel',serif; font-weight:400; font-size:36px; letter-spacing:0.08em;
  color:var(--c-gold-hot); text-shadow:0 0 14px rgba(255,213,74,0.45), 0 2px 6px #000; text-transform:uppercase;
}
/* номер обмена: ростом с буквы, своим цветом (Andy 13.09.2026) */
#boardLayer .board-head-no{
  font-family:'Pirata One','Cinzel',serif; font-weight:400; font-size:36px; letter-spacing:0.08em;
  color:#ff9a4a; text-shadow:0 0 14px rgba(255,154,74,0.6), 0 2px 6px #000;
}

/* дорожки между зонами: глазу видно, что ряды сопоставлены */
#boardLayer .board-lane{
  position:absolute; left:580px; right:580px; height:2px;
  background:linear-gradient(to right, rgba(217,180,92,0), rgba(217,180,92,0.26) 15%, rgba(217,180,92,0.26) 85%, rgba(217,180,92,0));
}
#boardLayer .board-l0{ top:175px; } #boardLayer .board-l1{ top:283px; } #boardLayer .board-l2{ top:391px; }

/* боец = имя, атака и три ряда «число защиты + зона» */
/* столбик поднят так, чтобы при крупных имени и ATT центры зон остались на
   176/284/392 (эти числа держат дорожки, мечи и щиты) */
#boardLayer .board-fighter{ position:absolute; top:26px; width:300px; }
#boardLayer .board-you{ left:220px; } #boardLayer .board-foe{ right:220px; }   /* на 150 ближе к центру — по краям летопись (Andy 13.09.2026) */
#boardLayer .board-name{
  font-family:'Pirata One','Cinzel',serif; font-weight:400; font-size:44px; letter-spacing:0.06em;
  color:var(--c-gold-bright); text-shadow:0 2px 6px #000; height:48px; line-height:48px; text-align:center;
  white-space:nowrap; overflow:hidden; text-transform:uppercase;
  transition:color .25s, text-shadow .25s;
}
/* ATT — как цифры защиты: тот же размер, вес и цвет (Andy 13.09.2026) */
#boardLayer .board-att{ font-size:38px; font-weight:700; letter-spacing:0.04em; height:44px; line-height:44px; text-align:center; color:var(--c-gold-bright); text-shadow:0 2px 4px #000; font-variant-numeric:tabular-nums; margin-bottom:4px; }
#boardLayer .board-row{ position:relative; height:108px; }
#boardLayer .board-zone{
  position:absolute; top:2px; z-index:2; width:104px; height:104px; border-radius:50%;
  background:radial-gradient(circle at 50% 38%, #2b2012, #0c0805 72%);
  border:2px solid rgba(217,180,92,0.45); display:flex; align-items:center; justify-content:center;
  box-shadow:inset 0 0 14px rgba(0,0,0,0.8), 0 3px 10px rgba(0,0,0,0.6);
  transition:border-color .25s, box-shadow .25s;
}
#boardLayer .board-you .board-zone{ left:150px; } #boardLayer .board-foe .board-zone{ right:150px; }
#boardLayer .board-zone img{ width:78px; height:78px; object-fit:contain; filter:drop-shadow(0 2px 2px rgba(0,0,0,0.8)); }
/* ВЕЩИ НА ДОСКЕ (G91, Andy 28.09.2026: «чтобы купленное было видно»). Зона
   и есть вещь: в кружке шлем, доспех или сапоги бойца, кайма — цвет тира, те
   же цвета, что у плиты вещи в лавке (.item-plate--t1..t4, 01-main.css).
   Тир ставится атрибутом data-tier, а не классом: className зоны
   переписывается на каждом касании (board-hit / board-blocked). Пустое гнездо —
   пунктир и тусклый значок зоны. Трещины — data-cracks, до конца боя. */
#boardLayer .board-zone[data-tier="1"]{ border:3px solid #9aa0a6; box-shadow:inset 0 0 14px rgba(0,0,0,0.8), 0 3px 10px rgba(0,0,0,0.6), 0 0 16px rgba(154,160,166,0.45); }
#boardLayer .board-zone[data-tier="2"]{ border:3px solid #4a90d9; box-shadow:inset 0 0 14px rgba(0,0,0,0.8), 0 3px 10px rgba(0,0,0,0.6), 0 0 18px rgba(120,180,240,0.6); }
#boardLayer .board-zone[data-tier="3"]{ border:3px solid #c9a227; box-shadow:inset 0 0 14px rgba(0,0,0,0.8), 0 3px 10px rgba(0,0,0,0.6), 0 0 18px rgba(230,190,80,0.6); }
#boardLayer .board-zone[data-tier="4"]{ border:3px solid #9b6bd1; box-shadow:inset 0 0 14px rgba(0,0,0,0.8), 0 3px 10px rgba(0,0,0,0.6), 0 0 20px rgba(190,140,250,0.65); }
#boardLayer .board-zone[data-tier="none"]{ border:2px dashed rgba(201,183,149,0.4); }
#boardLayer .board-zone[data-tier="none"] .board-zone-ico{ opacity:.28; filter:grayscale(1); }
#boardLayer .board-zone:not([data-tier="none"]) .board-zone-ico{ width:92px; height:92px; }
#boardLayer .board-tier{
  position:absolute; left:50%; bottom:-3px; transform:translateX(-50%); z-index:3; white-space:nowrap;
  font-family:'Cinzel',Georgia,serif; font-size:12px; font-weight:900; letter-spacing:0.1em; line-height:15px;
  padding:1px 8px 0; border-radius:8px; color:#120c05; box-shadow:0 1px 3px #000;
}
#boardLayer .board-zone[data-tier="1"] .board-tier{ background:#9aa0a6; }
#boardLayer .board-zone[data-tier="2"] .board-tier{ background:#6fa9e6; }
#boardLayer .board-zone[data-tier="3"] .board-tier{ background:#d9b440; }
#boardLayer .board-zone[data-tier="4"] .board-tier{ background:#b58ae6; }
#boardLayer .board-zone[data-tier="none"] .board-tier{ background:rgba(40,30,20,0.92); color:var(--c-gold-dim); }
#boardLayer .board-crack{ position:absolute; inset:0; width:100%; height:100%; z-index:2; pointer-events:none; overflow:visible; }
#boardLayer .board-crack path{
  fill:none; stroke:#fff6d8; stroke-width:2.4; stroke-linecap:round; stroke-linejoin:round;
  stroke-dasharray:120; stroke-dashoffset:120; opacity:0;
  transition:stroke-dashoffset .28s ease-out, opacity .08s;
  filter:drop-shadow(0 0 3px rgba(255,180,70,0.9)) drop-shadow(0 0 1px #000);
}
#boardLayer .board-zone[data-cracks="1"] .board-crack-1,
#boardLayer .board-zone[data-cracks="2"] .board-crack-1, #boardLayer .board-zone[data-cracks="2"] .board-crack-2,
#boardLayer .board-zone[data-cracks="3"] .board-crack-1, #boardLayer .board-zone[data-cracks="3"] .board-crack-2,
#boardLayer .board-zone[data-cracks="3"] .board-crack-3{ stroke-dashoffset:0; opacity:1; }
#boardLayer .board-def{
  position:absolute; top:2px; width:96px; height:104px; line-height:104px; font-size:38px; font-weight:700;
  color:var(--c-gold-bright); text-shadow:0 2px 4px #000; font-variant-numeric:tabular-nums;
}
#boardLayer .board-you .board-def{ left:36px; text-align:right; } #boardLayer .board-foe .board-def{ right:36px; text-align:left; }
/* роли: тёплая рамка у бьющего, холодная у защищающегося */
/* роли: цвет живёт в имени и в ярком предмете (меч тёплый, щит холодный), рамки
   зон не перебрасываются; у бьющего зоны и цифры защиты приглушены — по ним
   сейчас никто не бьёт, «цель» — половина защищающегося */
#boardLayer .board-zone, #boardLayer .board-def{ transition:opacity .3s, border-color .25s, box-shadow .25s; }
#boardLayer .board-role-att .board-zone, #boardLayer .board-role-att .board-def{ opacity:.4; }
/* 🔴 ИМЕНА НЕ МЕНЯЮТ ЦВЕТ ПО РОЛИ (Andy 20.09.2026: «не очень хорошо, что цвета
   у имён бойцов меняются в зависимости от того, кто бьёт. Пусть остаются
   статичного цвета, у нас и так мелькания много… пусть у того, кто бьёт, имя
   немного увеличивается, или как-то иначе незаметнее, элегантнее»).
   Было: имя бьющего оранжевое, защищающегося голубое — два перекраса на каждый
   удар, шесть за раунд. Стало: оба имени всегда пергаментные, а кто бьёт —
   сказано РАЗМЕРОМ: имя бьющего чуть крупнее и ярче, защищающегося чуть тише.
   Переход плавный, поэтому смены роли не мелькают, а перетекают.
   Масштаб берётся transform'ом, а не размером шрифта: размер шрифта на имени
   уже занят подгонкой длинного имени под ширину столбика (boardSetNames). */
#boardLayer .board-name{
  transform:scale(1); transform-origin:50% 50%; opacity:.86;
  transition:transform .28s ease, opacity .28s ease, color .2s ease;
}
#boardLayer .board-role-att .board-name{ transform:scale(1.07); opacity:1; text-shadow:0 0 12px rgba(243,226,189,0.35), 0 2px 6px #000; }
#boardLayer .board-role-def .board-name{ transform:scale(1); opacity:.78; }
/* 🔴 ПОПАДАНИЕ — ЗЕЛЁНОЕ, А НЕ КРАСНОЕ (решение Andy 16.09.2026).
   Красным на доске остаётся только цифра снятого здоровья. Причина: красный
   читается как «плохо, ошибка», а дошедший удар — это событие, которое
   состоялось; красный кружок поверх зоны выглядел как запрет. Зелёный тут
   значит «удар засчитан», у обеих сторон одинаково: кто бьёт — написано
   словами сверху. */
#boardLayer .board-zone.board-hit{
  border-color:#4ade80 !important; box-shadow:0 0 34px rgba(74,222,128,0.85), inset 0 0 22px rgba(74,222,128,0.5) !important;
  animation:boardShake .42s ease;
}
#boardLayer .board-zone.board-blocked{ border-color:var(--c-gold-hot) !important; box-shadow:0 0 30px rgba(255,213,74,0.7), inset 0 0 18px rgba(0,0,0,0.8) !important; }
@keyframes boardShake{ 0%,100%{transform:translateX(0)} 20%{transform:translateX(-7px)} 40%{transform:translateX(6px)} 60%{transform:translateX(-4px)} 80%{transform:translateX(3px)} }

/* меч и щит — знаки, не актёры; видны только у своей роли */
/* меч и щит есть у обоих всегда (Andy 13.09.2026); роль — яркостью. В покое меч
   поднят вертикально у своего столбика, замах — поворот на зону (boardSwordAim
   ставит transform на месте), возврат — снова в поднятое положение */
#boardLayer .board-sword{ position:absolute; width:200px; height:54px; top:257px; opacity:.32; transition:opacity .3s, transform .35s ease, filter .3s; filter:drop-shadow(0 2px 3px #000); }
#boardLayer .board-sword.board-on{ opacity:1; filter:drop-shadow(0 0 12px rgba(255,154,74,0.85)) drop-shadow(0 2px 3px #000); }
/* меч бойца картинкой (G91): есть меч — картинка, нет — прежний знак */
#boardLayer .board-sword{ overflow:visible; }
#boardLayer .board-sword .board-blade{ display:none; }
#boardLayer .board-sword[data-blade="on"] .board-blade{ display:inline; }
#boardLayer .board-sword[data-blade="on"] .board-sword-plain{ display:none; }
#boardLayer #boardSwordyou{ left:540px; top:236px; } #boardLayer #boardSwordfoe{ right:540px; top:278px; transform:scaleX(-1); }   /* горизонтально, чуть разведены по высоте */
/* замах: меч наклоняется туда, куда пойдёт удар (Andy 13.09.2026). У соперника
   меч отражён по горизонтали, поворот тем же знаком — верх остаётся верхом. */
/* замах: угол и подача меча считаются в 23-board.js (boardSwordAim) и ставятся
   стилем на месте — полоса выходит из острия под тем же углом; классы
   board-aim-* остались как отметка зоны */
#boardLayer .board-shield{
  position:absolute; width:112px; height:130px; top:219px; opacity:.55; z-index:3;   /* в покое — естественно, у средней зоны, заметный (Andy: «щита нет»; «внизу, у ног» — нет, вернуть в середину) */
  transition:top .3s cubic-bezier(.3,.9,.4,1.1), left .3s cubic-bezier(.3,.9,.4,1.1), right .3s cubic-bezier(.3,.9,.4,1.1), opacity .25s, filter .2s;
  filter:drop-shadow(0 3px 4px #000);
}
#boardLayer #boardShieldyou{ left:425px; } #boardLayer #boardShieldfoe{ right:425px; }   /* покой: перед корпусом, вплотную к рукояти лежащего меча (меч с 540), не под ним */
#boardLayer .board-shield.board-on{ opacity:1; filter:drop-shadow(0 0 12px rgba(188,216,255,0.8)) drop-shadow(0 3px 4px #000); }
#boardLayer .board-shield.board-z0{ top:111px; } #boardLayer .board-shield.board-z1{ top:219px; } #boardLayer .board-shield.board-z2{ top:327px; }
#boardLayer #boardShieldyou.board-up{ left:436px; } #boardLayer #boardShieldfoe.board-up{ right:436px; }
#boardLayer .board-shield.board-shield-flash{ filter:drop-shadow(0 0 18px rgba(255,213,74,0.95)) drop-shadow(0 3px 4px #000); }   /* своя метка, не .board-flash сцены (14.09.2026) */

/* удар: полоса света от меча к зоне */
/* выпад меча к зоне (Andy 14.09.2026: полоса «будто стреляет» снята): бросок
   за 90 мс, отход за 220 мс; засечка от клинка на зоне при попадании */
#boardLayer .board-sword.board-thrust{ transition:transform .09s cubic-bezier(.2,.9,.3,1), opacity .3s, filter .3s; }
#boardLayer .board-sword.board-recoil{ transition:transform .22s cubic-bezier(.3,.6,.4,1), opacity .3s, filter .3s; }
#boardLayer .board-slash{
  position:absolute; width:104px; height:9px; border-radius:5px; opacity:0; z-index:6; pointer-events:none;
  background:linear-gradient(90deg, rgba(255,120,90,0) 0%, #fff 30%, #fff 70%, rgba(255,120,90,0) 100%);
  box-shadow:0 0 14px rgba(255,90,60,.95), 0 0 30px rgba(255,60,40,.6);
}
#boardLayer .board-slash.board-slash-on{ animation:boardSlash .32s cubic-bezier(.1,.9,.3,1) forwards; }
@keyframes boardSlash{ 0%{ opacity:0; filter:brightness(3) blur(3px); } 20%{ opacity:1; filter:brightness(2) blur(0); } 100%{ opacity:.95; filter:brightness(1); } }

/* исход рядом с зоной */
#boardLayer .board-stamp{
  position:absolute; z-index:6; font-family:'Pirata One','Cinzel',serif; font-weight:400; opacity:0; pointer-events:none; white-space:nowrap;
  text-shadow:0 2px 0 #000, 0 3px 12px rgba(0,0,0,0.9);
}
#boardLayer .board-stamp-dmg{ font-size:66px; color:#ff8a75; }
#boardLayer .board-stamp-blk{ font-size:44px; color:var(--c-gold-hot); letter-spacing:0.06em; }
/* штамп появляется рывком и стоит до самого следующего удара (Andy 13.09.2026:
   «удлинить момент попадания»); гаснет по снятию board-show */
#boardLayer .board-stamp{ transition:opacity .25s; }
#boardLayer .board-stamp-dmg.board-show{ opacity:1; animation:boardRise .6s ease forwards; }
#boardLayer .board-stamp-blk.board-show{ opacity:1; animation:boardPop .6s ease forwards; }
@keyframes boardRise{ 0%{transform:translate(-50%,0) scale(0.7); opacity:0} 25%{transform:translate(-50%,-14px) scale(1.15); opacity:1} 100%{transform:translate(-50%,-30px) scale(1); opacity:1} }
@keyframes boardPop{ 0%{transform:translate(-50%,0) scale(0.6); opacity:0} 25%{transform:translate(-50%,0) scale(1.1); opacity:1} 100%{transform:translate(-50%,-6px) scale(1); opacity:1} }
/* ---------------------------------------------------------------------------
   ПЕЧАТЬ ПЕРКА (Andy 20.09.2026). Одна на удар: старший перк крупно, второй
   строкой под ним. Цвет ставится на месте из таблицы BOARD_PERK_FX
   (23-board.js) — семь цветов по смыслу, здесь их нет нарочно, чтобы цвет
   перка жил в ОДНОМ месте и не разъезжался между кодом и стилями.
   Движение по просьбе Andy: «надпись за секунду растёт из средней в большую и
   тает в воздухе». Поэтому одна анимация на секунду: первые 0,2 с рост,
   дальше подъём и растворение. Печать не держится до следующего удара, в
   отличие от штампа урона: перк — это событие, а не исход.
   --------------------------------------------------------------------------- */
#boardLayer .board-perk{
  position:absolute; z-index:7; text-align:center; white-space:nowrap;
  opacity:0; pointer-events:none; transform:translate(-50%,-50%) scale(0.72);
}
#boardLayer .board-perk-main{
  font-family:'Pirata One','Cinzel',serif; font-weight:400; font-size:40px; letter-spacing:0.06em; line-height:1.05;
}
#boardLayer .board-perk-sub{
  font-family:'Cinzel',Georgia,serif; font-size:19px; letter-spacing:0.16em; line-height:1.2; margin-top:2px;
}
#boardLayer .board-perk.board-show{ animation:boardPerkRise 1s cubic-bezier(.2,.8,.3,1) forwards; }
/* Отскок (Andy 20.09.2026): печать вспыхивает там, где перк сработал, и
   улетает на сторону бьющего — туда, откуда убыло здоровье. Сдвиги --dx/--dy
   кладёт 23-board.js: считаются они из геометрии доски, а она живёт там. */
#boardLayer .board-perk.board-fly{ animation:boardPerkFly 1.25s cubic-bezier(.25,.6,.25,1) forwards; }
@keyframes boardPerkFly{
  0%   { opacity:0;  transform:translate(-50%,-50%) scale(0.70); }
  16%  { opacity:1;  transform:translate(-50%,-50%) scale(1.14); }
  30%  { opacity:1;  transform:translate(-50%,-50%) scale(1.00); }
  72%  { opacity:1;  transform:translate(calc(-50% + var(--dx,0px)), calc(-50% + var(--dy,0px))) scale(1.00); }
  86%  { opacity:.95;transform:translate(calc(-50% + var(--dx,0px)), calc(-50% + var(--dy,0px))) scale(1.10); }
  100% { opacity:0;  transform:translate(calc(-50% + var(--dx,0px)), calc(-50% + var(--dy,0px) - 22px)) scale(1.04); }
}
@keyframes boardPerkRise{
  0%   { opacity:0;  transform:translate(-50%,-50%) scale(0.72); }
  20%  { opacity:1;  transform:translate(-50%,-54%) scale(1.10); }
  34%  { opacity:1;  transform:translate(-50%,-56%) scale(1.00); }
  68%  { opacity:.9; transform:translate(-50%,-84%) scale(1.02); }
  100% { opacity:0;  transform:translate(-50%,-116%) scale(1.06); }
}
/* Имя бойца в цвете перка, пока состояние держится (Andy 20.09.2026: «его имя
   само тоже должно краситься в цвет перка, пока действует»). Полоска под
   именем — absolute, чтобы не сдвинуть ни на точку геометрию столбиков: их
   центры держат дорожки, мечи и щиты. */
#boardLayer .board-name{ position:relative; }
/* Держащееся состояние — единственный случай, когда имя вообще меняет цвет
   (Andy 20.09.2026). Поэтому оно светит в полную силу, не приглушаясь ролью. */
#boardLayer .board-name.board-name-hold{ opacity:1; }
#boardLayer .board-name-bar{
  position:absolute; left:18%; right:18%; bottom:2px; height:2px; border-radius:1px;
}
/* точка перка в ячейке летописи */
.duel-cell .board-cell-dot{
  display:inline-block; width:9px; height:9px; border-radius:50%; margin-left:5px; vertical-align:middle;
}
#boardLayer .board-ring{
  position:absolute; z-index:5; width:40px; height:40px; border-radius:50%; border:4px solid var(--c-gold-hot);
  transform:translate(-50%,-50%) scale(0.3); opacity:0; pointer-events:none;
}
#boardLayer .board-ring-hit{ border-color:#4ade80; box-shadow:0 0 18px rgba(74,222,128,0.55); }
/* кольцо удара разлетается и остаётся стоять вокруг зоны до следующего удара */
#boardLayer .board-ring{ transition:opacity .25s; }
#boardLayer .board-ring.board-go{ animation:boardRing .55s ease-out forwards; }
@keyframes boardRing{ 0%{transform:translate(-50%,-50%) scale(0.3); opacity:1} 70%{transform:translate(-50%,-50%) scale(3.4); opacity:.75} 100%{transform:translate(-50%,-50%) scale(3.2); opacity:.6} }

/* летопись раунда: у каждого бойца три ячейки рядом с его зонами (по обменам);
   ячейка .duel-cell — общая с плашками протокола арены (12-battle-ui.js) */
#boardLayer .board-chron{ position:absolute; top:144px; width:200px; display:flex; flex-direction:column; gap:44px; }   /* 64 + 44 = шаг рядов 108 */
#boardLayer .board-chron-you{ left:18px; } #boardLayer .board-chron-foe{ right:18px; }
/* Andy 13.09.2026: значки в протоколе арены очень маленькие — ячейка 64 со
   значками 40 и там, и на доске */
.duel-cell{
  position:relative; min-width:0; height:64px; box-sizing:border-box; overflow:hidden; display:flex; align-items:center; justify-content:center; gap:4px; padding-top:12px;
  border:1px solid rgba(217,180,92,0.22); border-radius:6px; background:rgba(0,0,0,0.35);
  font-family:'Cinzel',Georgia,serif; font-size:28px; font-weight:700; color:rgba(243,226,189,0.35); font-variant-numeric:tabular-nums;
  transition:border-color .2s, background .2s;
}
.duel-cell .board-cell-no{
  position:absolute; left:8px; top:1px; font-family:'EB Garamond',serif; font-size:14px; font-weight:600;
  color:var(--c-gold-dim); opacity:0.8; letter-spacing:0.06em; text-transform:uppercase; white-space:nowrap;
}
.duel-cell > img{ width:40px; height:40px; object-fit:contain; }
.duel-cell .board-cell-arrow{ font-family:'EB Garamond',serif; font-size:26px; line-height:1; color:var(--c-gold-dim); margin:0 2px; }
.duel-cell .board-cell-shl{ position:relative; display:inline-flex; align-items:center; justify-content:center; width:40px; height:46px; }
.duel-cell .board-cell-shl svg{ width:38px; height:44px; }
.duel-cell .board-cell-shl img{ position:absolute; left:8px; top:7px; width:23px; height:23px; }
.duel-cell .board-cell-res{ margin-left:4px; }
.duel-cell.board-cell-hit .board-cell-res{ color:#ff6a52; text-shadow:0 0 8px rgba(255,60,40,0.55); font-weight:700; }   /* красным — ТОЛЬКО снятые пункты (Andy 16.09.2026) */
.duel-cell.board-cell-blk .board-cell-res{ color:var(--c-gold-hot); font-family:'Pirata One','Cinzel',serif; font-weight:400; font-size:24px; letter-spacing:0.04em; }
.duel-cell.board-cell-done{ color:var(--c-gold-bright); border-color:rgba(217,180,92,0.5); }
/* Исход цветом (Andy 14.09.2026: «удачные и неудачные удары должны отличаться
   цветом»): удар дошёл — кровь, тёплая красная подложка и рамка; отбит — сталь,
   холодная синяя. Одно правило для доски и для плашек арены. */
.duel-cell.board-cell-done.board-cell-hit{ background:linear-gradient(90deg, rgba(22,84,48,0.6), rgba(12,50,30,0.5)); border-color:rgba(74,222,128,0.7); box-shadow:inset 0 0 14px rgba(40,160,90,0.35); }   /* дошёл — зелёная (Andy 16.09.2026) */
.duel-cell.board-cell-done.board-cell-blk{ background:linear-gradient(90deg, rgba(18,42,80,0.55), rgba(10,26,52,0.45)); border-color:rgba(120,170,255,0.65); box-shadow:inset 0 0 14px rgba(60,110,200,0.35); }
.duel-cell.board-cell-done.board-cell-hit .board-cell-no{ color:rgba(150,240,185,0.85); }
.duel-cell.board-cell-done.board-cell-blk .board-cell-no{ color:rgba(170,200,255,0.8); }
.duel-cell.board-cell-done.board-cell-blk .board-cell-res{ color:#cfe2ff; text-shadow:0 0 8px rgba(120,170,255,0.6); }
.duel-cell.board-cell-cur{ border-color:var(--c-gold-hot); background:rgba(255,213,74,0.08); box-shadow:0 0 12px rgba(255,213,74,0.25); }
.duel-cell.board-cell-you{ border-left:3px solid rgba(255,154,74,0.75); }
.duel-cell.board-cell-foe{ border-right:3px solid rgba(255,154,74,0.75); }
/* плашки протокола арены: ячейка во всю ширину плашки, плашка чуть шире под неё */
#newHudOverlay #logColMine, #newHudOverlay #logColTheirs{ width:214px !important; }
#newHudOverlay #logMine > div, #newHudOverlay #logTheirs > div{ width:100%; }
#newHudOverlay .nh-log .duel-cell{ width:100%; }
@media (prefers-reduced-motion:reduce){ #boardLayer .board-zone.board-hit{ animation:none; } }

/* тёмная секунда после ролика добивания (battleBlackout в 17-battlevid.js):
   быстро в черноту, из черноты — медленнее, под проявление заставки */
#newHudFrame #battleBlackout{ position:absolute; inset:0; z-index:60; background:#000; opacity:0; pointer-events:none; transition:opacity .7s ease; }
#newHudFrame #battleBlackout.on{ opacity:1; transition:opacity .2s ease; }

/* ---- СБОРКА ДОСКИ В НАЧАЛЕ РАУНДА (boardAssemble в 23-board.js) ----
   Сцена: арена темнеет (board-storm на <html>), имена бойцов слетаются в титул
   «ANDY vs. BRADLEY» и сшибаются (board-title-*), плита падает с высоты и
   врезается (boardSlam, тряска board-shake-*), кузнечные удары впечатывают
   элементы — вещь зависает над плитой и вбивается (boardForge + вспышка
   board-flash + искры на холсте board-fx), дорожки льются золотом, ячейки
   поднимаются камнем, по доске идёт огненная волна языками (board-flame),
   рамка раскаляется (boardFrameGlow), строка горит (board-burn), колокол —
   EN GARDE посреди экрана (board-engarde-*). Пока на слое класс
   board-building, невбитые части невидимы. */
#boardLayer .board-fx{ position:absolute; left:0; top:0; width:1700px; height:760px; z-index:12; pointer-events:none; }
#newHudOverlay #battleSceneBox, #newHudArena{ transition:filter .6s ease; }
html.board-storm #newHudOverlay #battleSceneBox, html.board-storm #newHudArena{ filter:brightness(.28); }

/* плита: с высоты, размытая движением, двойной отскок */
#boardLayer.board-building .board-panel{ transform:scale(1.8) translateY(-420px); opacity:0; filter:blur(8px); }
#boardLayer.board-building.board-l-panel .board-panel{ animation:boardSlam .5s cubic-bezier(.6,0,1,.5) forwards; }
@keyframes boardSlam{ 0%{transform:scale(1.8) translateY(-420px); opacity:0; filter:blur(8px)} 12%{opacity:1} 78%{transform:none; filter:blur(0)} 86%{transform:translateY(-9px)} 100%{transform:none; opacity:1; filter:none} }

/* ковка: вещь зависает над плитой (замах), потом вбивается — касание на 60% (BOARD_BLOW_LAG) */
#boardLayer.board-building .board-name, #boardLayer.board-building .board-att,
#boardLayer.board-building .board-row, #boardLayer.board-building .board-head{ opacity:0; }
#boardLayer.board-building .board-forged{ opacity:1; animation:boardForge .3s cubic-bezier(.3,.7,.3,1) forwards; }
@keyframes boardForge{
  0%{transform:scale(1.9) translateY(-14px); opacity:.2; filter:brightness(2.6) blur(2px)}
  45%{transform:scale(1.7) translateY(-10px); opacity:.6; filter:brightness(2.4) blur(1px)}
  60%{transform:scale(.88); opacity:1; filter:brightness(2) blur(0)}
  78%{transform:scale(1.05); filter:brightness(1.3)}
  100%{transform:scale(1); opacity:1; filter:brightness(1)}
}
#boardLayer .board-flash{
  position:absolute; z-index:7; width:280px; height:280px; margin:-140px 0 0 -140px; border-radius:50%; pointer-events:none;
  background:radial-gradient(circle, rgba(255,255,240,.98) 0%, rgba(255,225,140,.7) 26%, rgba(255,150,50,.25) 55%, rgba(255,140,40,0) 72%);
  animation:boardFlash .34s ease-out forwards;
}
#boardLayer .board-flash.board-flash-big{ width:520px; height:520px; margin:-260px 0 0 -260px; animation-duration:.5s; }
@keyframes boardFlash{ 0%{transform:scale(.25); opacity:1} 100%{transform:scale(1.4); opacity:0} }

#boardLayer.board-building .board-lane{ transform:scaleX(0); box-shadow:0 0 12px rgba(255,200,90,.7), 0 0 3px rgba(255,240,200,.9); transition:transform .45s cubic-bezier(.3,.6,.4,1); }
#boardLayer.board-building.board-l-lanes .board-lane{ transform:scaleX(1); }
#boardLayer .duel-cell{ transition:transform .26s cubic-bezier(.2,.9,.3,1.25), opacity .2s, border-color .2s, background .2s; }
#boardLayer.board-building .duel-cell:not(.board-cell-in){ transform:translateY(90px); opacity:0; }
/* короткая сцена (board-whole): плита падает уже со всем содержимым, ковки нет */
#boardLayer.board-building.board-whole .board-name, #boardLayer.board-building.board-whole .board-att,
#boardLayer.board-building.board-whole .board-row, #boardLayer.board-building.board-whole .board-head{ opacity:1; }
#boardLayer.board-building.board-whole .board-lane{ transform:none; box-shadow:none; }
#boardLayer.board-building.board-whole .duel-cell:not(.board-cell-in){ transform:none; opacity:1; }

/* огонь: волна и языки поверх неё */
#boardLayer .board-flame{ position:absolute; inset:0; overflow:hidden; pointer-events:none; border-radius:8.5px; z-index:8; opacity:0; }
#boardLayer .board-flame::before{
  content:''; position:absolute; top:-12%; bottom:-12%; left:0; width:55%;
  background:linear-gradient(90deg, rgba(255,120,30,0) 0%, rgba(255,120,30,.35) 25%, rgba(255,210,110,.9) 48%, rgba(255,240,190,.95) 52%, rgba(255,140,40,.45) 72%, rgba(255,120,30,0) 100%);
  filter:blur(6px); transform:skewX(-16deg) translateX(-130%);
}
#boardLayer .board-flame::after{
  content:''; position:absolute; top:-20%; bottom:-20%; left:0; width:60%;
  background:
    radial-gradient(ellipse 60px 150px at 18% 30%, rgba(255,200,90,.95), rgba(255,120,30,0) 70%),
    radial-gradient(ellipse 50px 190px at 42% 72%, rgba(255,232,160,.95), rgba(255,120,30,0) 70%),
    radial-gradient(ellipse 72px 130px at 63% 18%, rgba(255,160,60,.9), rgba(255,120,30,0) 70%),
    radial-gradient(ellipse 46px 170px at 80% 56%, rgba(255,240,190,.9), rgba(255,120,30,0) 70%),
    radial-gradient(ellipse 58px 140px at 32% 92%, rgba(255,140,40,.85), rgba(255,120,30,0) 70%),
    radial-gradient(ellipse 40px 120px at 92% 84%, rgba(255,210,120,.85), rgba(255,120,30,0) 70%);
  filter:blur(3px); mix-blend-mode:screen; transform:translateX(-130%);
}
#boardLayer.board-l-flame .board-flame{ opacity:1; }
#boardLayer.board-l-flame .board-flame::before{ animation:boardFlameRun .7s cubic-bezier(.35,.1,.45,1) forwards; }
#boardLayer.board-l-flame .board-flame::after{ animation:boardFlameTongues .7s cubic-bezier(.35,.1,.45,1) forwards; }
/* раскалённая рамка — на внутреннем слое, чтобы не сбивать анимацию падения плиты */
#boardLayer.board-l-flame .board-in{ animation:boardFrameGlow 1.7s ease-out forwards; border-radius:inherit; }
#boardLayer .board-head-who.board-burn{ animation:boardBurn 1.7s ease-out; }
@keyframes boardFlameRun{ 0%{transform:skewX(-16deg) translateX(-130%)} 100%{transform:skewX(-16deg) translateX(300%)} }
@keyframes boardFlameTongues{ 0%{transform:translateX(-130%) scaleY(.8)} 50%{transform:translateX(60%) scaleY(1.18)} 100%{transform:translateX(280%) scaleY(.9)} }
@keyframes boardFrameGlow{
  0%{box-shadow:none}
  35%{box-shadow:0 0 70px rgba(255,160,50,0.9), 0 0 24px rgba(255,220,140,0.8), inset 0 0 40px rgba(255,140,40,0.45)}
  100%{box-shadow:none}
}
@keyframes boardBurn{ 0%{text-shadow:0 0 14px rgba(255,213,74,0.45), 0 2px 6px #000} 30%{text-shadow:0 0 34px rgba(255,180,60,1), 0 0 12px rgba(255,240,200,1), 0 2px 6px #000} 100%{text-shadow:0 0 14px rgba(255,213,74,0.45), 0 2px 6px #000} }

/* титул «ANDY vs. BRADLEY»: имена слетаются с двух сторон, сшибаются, рассыпаются */
#boardLayer .board-title{
  position:absolute; left:15px; width:1355px; top:312px; display:none; align-items:center; justify-content:center; gap:34px;
  z-index:9; pointer-events:none; font-family:'Pirata One','Cinzel',serif; font-size:120px; line-height:1;
}
#boardLayer .board-title.board-title-on{ display:flex; }
#boardLayer .board-title.board-title-measure{ display:flex; visibility:hidden; }
#boardLayer .board-title-name{
  font-size:1em; letter-spacing:.04em; white-space:nowrap;
  background:linear-gradient(180deg,#fff4d0 0%,#ffd75a 32%,#b07a1e 52%,#ffe6a3 70%,#8a5a16 100%); background-size:100% 200%;
  -webkit-background-clip:text; background-clip:text; color:transparent;
  filter:drop-shadow(0 4px 0 #2a1a05) drop-shadow(0 8px 18px rgba(0,0,0,.85));
  transition:transform .3s cubic-bezier(.15,.75,.25,1);
}
#boardLayer .board-title-you{ transform:translateX(-1300px); }
#boardLayer .board-title-foe{ transform:translateX(1300px); }
#boardLayer .board-title.board-title-in .board-title-name{ transform:none; }
#boardLayer .board-title-vs{
  font-family:'EB Garamond',serif; font-style:italic; font-size:.55em; color:var(--c-gold-dim); opacity:0; transform:scale(.4);
  transition:opacity .2s, transform .25s cubic-bezier(.2,.9,.3,1.4); text-shadow:0 2px 6px #000;
}
#boardLayer .board-title.board-title-slam .board-title-vs{ opacity:1; transform:none; }
#boardLayer .board-title.board-title-slam .board-title-name{ animation:boardTitleSlam .38s ease-out both, boardTitleSheen 1s .15s ease-in-out; }
@keyframes boardTitleSlam{
  0%{transform:scale(1.28); filter:brightness(3) drop-shadow(0 0 40px rgba(255,220,120,1))}
  30%{transform:scale(.96)}
  100%{transform:scale(1); filter:drop-shadow(0 4px 0 #2a1a05) drop-shadow(0 8px 18px rgba(0,0,0,.85))}
}
@keyframes boardTitleSheen{ 0%{background-position:0 0} 100%{background-position:0 100%} }
#boardLayer .board-title.board-title-out{ animation:boardTitleOut .42s ease-in forwards; }
@keyframes boardTitleOut{ 0%{opacity:1; filter:blur(0)} 100%{opacity:0; filter:blur(14px); transform:translateY(-36px) scale(1.06)} }

/* колокол: EN GARDE посреди экрана */
#boardLayer .board-engarde{
  position:absolute; left:15px; width:1355px; top:305px; text-align:center; z-index:13; pointer-events:none; opacity:0;
  font-family:'Pirata One','Cinzel',serif; font-size:150px; line-height:1; letter-spacing:.08em; color:var(--c-gold-hot);
  text-shadow:0 0 30px rgba(255,200,80,.9), 0 0 90px rgba(255,150,40,.6), 0 6px 0 #2a1a05, 0 12px 24px rgba(0,0,0,.9);
}
#boardLayer .board-engarde.board-engarde-in{ animation:boardEngardeIn .5s cubic-bezier(.2,.9,.3,1.2) forwards; }
@keyframes boardEngardeIn{ 0%{opacity:0; transform:scale(2.2); filter:blur(10px) brightness(3)} 60%{opacity:1; transform:scale(.96); filter:blur(0) brightness(1.8)} 100%{opacity:1; transform:scale(1); filter:none} }
#boardLayer .board-engarde.board-engarde-out{ animation:boardEngardeOut .4s ease-in forwards; }
@keyframes boardEngardeOut{ 0%{opacity:1; transform:scale(1)} 100%{opacity:0; transform:scale(1.15); filter:blur(8px)} }

.board-shake-huge{ animation:boardShakeHuge 2.6s cubic-bezier(.15,.6,.3,1); }   /* вдвое к прежним 1,3 с (Andy 16.09.2026) */
.board-shake-big{ animation:boardShakeBig .48s ease-out; }
.board-shake-mid{ animation:boardShakeMid .3s ease-out; }
@keyframes boardShakeHuge{ 0%,100%{transform:translate(0,0) rotate(0)} 5%{transform:translate(-52px,34px) rotate(-1.4deg)} 12%{transform:translate(48px,-38px) rotate(1.2deg)} 20%{transform:translate(-38px,26px) rotate(-.9deg)} 30%{transform:translate(30px,-21px) rotate(.7deg)} 42%{transform:translate(-22px,15px) rotate(-.5deg)} 56%{transform:translate(15px,-10px) rotate(.3deg)} 70%{transform:translate(-9px,6px)} 85%{transform:translate(4px,-3px)} }   /* размашистее вдвое — Andy 16.09.2026 «долбануло так долбануло» */
.board-shake-small{ animation:boardShakeSmall .16s ease-out; }
@keyframes boardShakeBig{ 0%{transform:translate(0,0)} 10%{transform:translate(-16px,10px)} 22%{transform:translate(14px,-12px)} 34%{transform:translate(-10px,7px)} 48%{transform:translate(8px,-5px)} 64%{transform:translate(-5px,3px)} 82%{transform:translate(2px,-2px)} 100%{transform:translate(0,0)} }
@keyframes boardShakeMid{ 0%{transform:translate(0,0)} 20%{transform:translate(-9px,5px)} 45%{transform:translate(7px,-6px)} 70%{transform:translate(-4px,3px)} 100%{transform:translate(0,0)} }
@keyframes boardShakeSmall{ 0%{transform:translate(0,0)} 30%{transform:translate(-4px,3px)} 65%{transform:translate(3px,-2px)} 100%{transform:translate(0,0)} }
@media (prefers-reduced-motion:reduce){ #boardLayer .board-flame::before, #boardLayer .board-flame::after, .board-shake-huge, .board-shake-big, .board-shake-mid, .board-shake-small{ animation:none !important; } }

/* ---- ПОЛОСЫ ЗДОРОВЬЯ: наливаются со сборкой доски (boardHpFillStart) и
   вспыхивают, налившись; плита проигравшего раскалывается на решающем ударе
   (plateShatter в 17-battlevid.js) ---- */
#newHudOverlay .hp-frame-fill.hp-filling{ transition:width 2.3s cubic-bezier(.2,.6,.3,1); }
#newHudOverlay .nh-card.hp-full-flash{ animation:hpFullFlash 1s ease-out; }
@keyframes hpFullFlash{
  0%{ box-shadow:0 0 0 rgba(255,213,74,0); filter:brightness(1); }
  25%{ box-shadow:0 0 42px rgba(255,213,74,0.95), 0 0 14px rgba(255,240,200,0.9); filter:brightness(1.8); }
  100%{ box-shadow:0 0 0 rgba(255,213,74,0); filter:brightness(1); }
}
#newHudOverlay .nh-card{ transition:filter .4s, opacity .4s; }
/* ---- РАЗЛОМ ПЛАШКИ ПРОИГРАВШЕГО, вторая версия (Andy 14.09.2026: «в пять раз
   эпичнее, звук в такт»). Треск 0,42 с: плита дрожит, четыре ветвистые трещины с
   раскалённой кромкой; взрыв: вспышка, ударная волна через весь экран, встряска
   huge, 18 кусков во все стороны с вращением в глубину, каменная крошка, угли,
   пыль; остаток тлеет; плашка победителя — золото с бликом. ---- */
#newHudOverlay .nh-card.plate-crack{ animation:plateQuake .42s linear; }
@keyframes plateQuake{ 0%{transform:translate(0,0)} 15%{transform:translate(-2px,1px)} 30%{transform:translate(3px,-2px)} 45%{transform:translate(-3px,2px)} 60%{transform:translate(4px,-1px)} 75%{transform:translate(-4px,3px)} 90%{transform:translate(3px,-3px)} 100%{transform:translate(0,0)} }
#newHudOverlay .plate-crack-svg{ position:absolute; inset:0; width:100%; height:100%; pointer-events:none; z-index:5; overflow:visible; }
#newHudOverlay .plate-crack-svg polyline{ fill:none; stroke-linejoin:round; stroke-linecap:round; transition:stroke-dashoffset .3s ease-out; }
#newHudOverlay .plate-crack-svg .plate-crack-glow{ filter:drop-shadow(0 0 6px rgba(255,120,30,.95)) drop-shadow(0 0 14px rgba(255,80,10,.7)); }
#newHudOverlay .nh-card.plate-broken{ filter:brightness(.36) saturate(.35); animation:plateEmber 2.2s ease-out forwards; }
#newHudOverlay .nh-card.plate-broken .hp-frame, #newHudOverlay .nh-card.plate-broken .nh-crest{ opacity:0; }
@keyframes plateEmber{ 0%{ box-shadow:inset 0 0 60px rgba(255,110,30,.95), 0 0 40px rgba(255,90,20,.7); } 35%{ box-shadow:inset 0 0 40px rgba(255,80,20,.6), 0 0 18px rgba(255,80,20,.35); } 100%{ box-shadow:inset 0 0 0 rgba(255,80,20,0), 0 0 0 rgba(255,80,20,0); } }
#newHudOverlay .plate-flash{ position:absolute; pointer-events:none; z-index:45; border-radius:14px; background:radial-gradient(ellipse at center, #fff 0%, rgba(255,240,200,.95) 30%, rgba(255,190,110,.5) 60%, rgba(255,150,60,0) 100%); animation:plateFlash .55s ease-out forwards; }
@keyframes plateFlash{ 0%{ opacity:1; transform:scale(.8) } 40%{ opacity:.9; transform:scale(1.35) } 100%{ opacity:0; transform:scale(1.9) } }
#newHudFrame .plate-flash-frame{ position:absolute; inset:0; pointer-events:none; z-index:44; background:radial-gradient(circle at var(--cx) var(--cy), rgba(255,244,220,1) 0%, rgba(255,210,140,.55) 26%, rgba(255,160,60,0) 62%); animation:plateFlashFrame .7s ease-out forwards; }
@keyframes plateFlashFrame{ 0%{ opacity:0 } 12%{ opacity:1 } 100%{ opacity:0 } }
/* миг темноты перед вспышкой — глазу нужен контраст */
#newHudFrame .plate-dark{ position:absolute; inset:0; pointer-events:none; z-index:43; background:#000; animation:plateDark .5s ease-out forwards; }
@keyframes plateDark{ 0%{ opacity:.55 } 18%{ opacity:.55 } 100%{ opacity:0 } }
#newHudOverlay .plate-fire{ position:absolute; pointer-events:none; z-index:38; width:420px; height:300px; margin:-150px 0 0 -210px; border-radius:50%; background:radial-gradient(ellipse at center, rgba(255,250,220,1) 0%, rgba(255,190,80,.95) 18%, rgba(255,100,20,.8) 42%, rgba(120,30,5,.35) 68%, rgba(60,10,0,0) 100%); filter:blur(4px); animation:plateFire 2s ease-out forwards; }
@keyframes plateFire{ 0%{ transform:scale(.2); opacity:1 } 45%{ transform:scale(1.15); opacity:.95 } 100%{ transform:scale(1.6) translateY(-30px); opacity:0 } }
#newHudOverlay .plate-smoke{ position:absolute; pointer-events:none; z-index:37; width:320px; height:320px; margin:-160px 0 0 -160px; border-radius:50%; background:radial-gradient(circle, rgba(40,30,22,.85) 0%, rgba(60,45,32,.55) 40%, rgba(60,45,32,0) 70%); filter:blur(6px); animation:plateSmoke 6s ease-out forwards; }
@keyframes plateSmoke{ 0%{ transform:scale(.3); opacity:0 } 15%{ opacity:.9 } 100%{ transform:scale(2.4) translateY(-120px); opacity:0 } }
/* волна — размером, а не scale: у растянутого кольца кайма толстеет вместе с ним */
#newHudFrame .plate-wave{ position:absolute; pointer-events:none; z-index:46; transform:translate(-50%,-50%); border-radius:50%; border:6px solid rgba(255,230,170,.95); box-shadow:0 0 36px rgba(255,200,100,.9), inset 0 0 36px rgba(255,200,100,.6); animation:plateWave 1.8s cubic-bezier(.25,.6,.35,1) forwards; }
#newHudFrame .plate-wave.plate-wave-2{ animation-delay:.14s; border-width:3px; }
@keyframes plateWave{ 0%{ width:60px; height:60px; opacity:1 } 100%{ width:3200px; height:3200px; opacity:0 } }
#newHudOverlay .plate-shard{
  position:absolute; pointer-events:none; z-index:40; margin:0 !important; box-sizing:border-box;
  animation:plateShardFly 6s forwards;          /* куски летят вдвое дольше (Andy 16.09.2026) */
  filter:brightness(1.15) drop-shadow(0 6px 8px rgba(0,0,0,.85));
}
@keyframes plateShardFly{
  0%{ transform:perspective(900px) translate(0,0) rotateX(0) rotateY(0) rotateZ(0); opacity:1; filter:brightness(2.2); animation-timing-function:cubic-bezier(.2,.7,.5,1); }
  28%{ transform:perspective(900px) translate(calc(var(--dx) * .42), var(--dy1)) rotateX(calc(var(--rx) * .3)) rotateY(calc(var(--ry) * .3)) rotateZ(calc(var(--rz) * .3)); opacity:1; filter:brightness(1.1); animation-timing-function:cubic-bezier(.5,0,.85,.5); }
  100%{ transform:perspective(900px) translate(var(--dx), var(--dy2)) rotateX(var(--rx)) rotateY(var(--ry)) rotateZ(var(--rz)); opacity:0; filter:brightness(.6); }
}
#newHudOverlay .plate-chip{ position:absolute; pointer-events:none; z-index:41; background:linear-gradient(135deg, #7a6040, #2a1d10); border:1px solid rgba(217,180,92,.7); box-shadow:0 3px 5px rgba(0,0,0,.7); animation:plateShardFly 5.4s forwards; }
#newHudOverlay .plate-dust{
  position:absolute; pointer-events:none; z-index:39; width:260px; height:260px; margin:-130px 0 0 -130px; border-radius:50%;
  background:radial-gradient(circle, rgba(200,180,150,.8) 0%, rgba(160,140,110,.45) 40%, rgba(140,120,95,0) 70%);
  animation:plateDust 5s ease-out forwards;
}
@keyframes plateDust{ 0%{ transform:scale(.25); opacity:1 } 100%{ transform:scale(3.2) translateY(-40px); opacity:0 } }
#newHudOverlay .plate-spark{
  position:absolute; pointer-events:none; z-index:42; width:6px; height:6px; border-radius:50%;
  background:#fff6d0; box-shadow:0 0 10px rgba(255,200,90,1), 0 0 4px #fff;
  animation:plateShardFly 4s forwards;
}
#newHudOverlay .nh-card.plate-victor{ animation:plateVictor 2.2s ease-out; }
@keyframes plateVictor{
  0%{ box-shadow:0 0 0 rgba(255,213,74,0); filter:brightness(1); }
  12%{ box-shadow:0 0 70px rgba(255,213,74,1), 0 0 24px rgba(255,245,210,1); filter:brightness(2.1); }
  40%{ box-shadow:0 0 30px rgba(255,213,74,.7); filter:brightness(1.35); }
  60%{ box-shadow:0 0 50px rgba(255,213,74,.9); filter:brightness(1.6); }
  100%{ box-shadow:0 0 0 rgba(255,213,74,0); filter:brightness(1); }
}
#newHudOverlay .plate-shine{ position:absolute; inset:0; overflow:hidden; pointer-events:none; z-index:6; border-radius:inherit; }
#newHudOverlay .plate-shine::before{ content:''; position:absolute; top:-30%; bottom:-30%; left:-40%; width:26%; background:linear-gradient(105deg, rgba(255,255,255,0) 0%, rgba(255,250,220,.85) 50%, rgba(255,255,255,0) 100%); transform:skewX(-20deg); animation:plateShine .75s .25s ease-in-out forwards; }
@keyframes plateShine{ 0%{ left:-40% } 100%{ left:130% } }

/* ============================================================
   ТЕМП ПОКАЗА: та же кнопка хода становится «2×», потом «SKIP»
   (задача Andy 17.09.2026, модуль 25-speed.js).

   Нарочно НЕ меняем ни место, ни размер кнопки: палец уже знает,
   где она. Меняется только подпись и цвет каймы — холодный,
   чтобы «2×» не путали с «FIGHT» и не жали вслепую перед ходом.
   ============================================================ */
#newHudOverlay #fightBtn.fight-btn--speed{
  color:#bfe3ff !important;
  text-shadow:0 1px 3px rgba(0,0,0,0.9), 0 0 14px rgba(120,190,255,0.45);
  letter-spacing:0.18em;
}
#newHudOverlay #fightBtn.fight-btn--speed:disabled{ opacity:0.6; }

/* ===========================================================================
   СМЕРТЕЛЬНЫЙ УДАР (26-deathblow.js, V97 — задача Andy 20.09.2026)
   Сцена забирает экран целиком: доска на z-index 11, значки и баннеры на 13+,
   поэтому здесь 30. Координаты — в холсте 1700×760, как у доски.
   Весь эффект держится на паузах и на том, что экран ТЕМНЕЕТ, а не мигает.
   =========================================================================== */
#dbLayer{
  position:absolute; inset:0; z-index:30; display:none;
  font-family:'Cinzel',Georgia,serif; color:var(--c-gold-bright);
}
/* пелена не чёрная, а густая багровая: чёрный читается как «экран погас»,
   багровый — как «сейчас будет кровь» */
/* 🔴 ПЕЛЕНА, А НЕ ГЛУХАЯ ТЕМНОТА (Andy 20.09.2026: «пелена была лучше, чем
   полное затемнение»). Сквозь неё видно арену и бойцов — бой не исчез, он
   замер. Мельтешение, из-за которого темноту и загущали, убрано иначе:
   класс db-on гасит панели, полосы и строку раунда, а картина боя остаётся. */
#dbLayer .db-dim{
  position:absolute; inset:0; opacity:0;
  transition:opacity .5s ease;
  background:
    radial-gradient(120% 90% at 50% 46%, rgba(46,6,6,0.66) 0%, rgba(14,4,4,0.86) 55%, rgba(6,2,2,0.92) 100%);
}
/* интерфейс боя гаснет на время сцены: панель ходов, строка раунда, полосы,
   протокол. Арена остаётся тенью — бой никуда не делся, он просто замер. */
#newHudFrame.db-on #newHudMovesSlot, #newHudFrame.db-on #newHudFightWrap,
#newHudFrame.db-on #newHudDefSlotYou, #newHudFrame.db-on #newHudDefSlotFoe,
#newHudFrame.db-on #logColMine, #newHudFrame.db-on #logColTheirs,
#newHudFrame.db-on #newHudLeft, #newHudFrame.db-on #newHudRight,
#newHudFrame.db-on #newHudNameSlotYou, #newHudFrame.db-on #newHudNameSlotFoe,
#newHudFrame.db-on #newHudHpSlotYou, #newHudFrame.db-on #newHudHpSlotFoe{
  opacity:0 !important; pointer-events:none;
  transition:opacity .45s ease;
}
#dbLayer.db-dim-on .db-dim{ opacity:1; }
#dbLayer.db-low .db-dim{ transition:opacity .12s ease; }

/* --- надпись. Не выскакивает, а ПРОСТУПАЕТ: размытие и разрядка сходятся
   к нулю за девять десятых секунды — как клеймо на остывающем железе. */
/* 🔴 Заголовок крупнее по просьбе Andy (20.09.2026) и уже не одно слово, а целая
   фраза — «YOUR CHANCE AT A DEATH BLOW», его формулировка. Поэтому разрядка
   меньше прежней, а строка может переноситься: с прежними 0.46em она упёрлась
   бы в края холста. */
#dbLayer .db-title{
  position:absolute; left:70px; right:70px; top:56px; text-align:center;
  font-family:'Pirata One','Cinzel',serif; font-weight:400; font-size:86px; line-height:1.04;
  text-transform:uppercase;
  letter-spacing:0.3em; text-indent:0.3em;
  color:#ffd54a;
  text-shadow:0 0 44px rgba(255,90,40,0.55), 0 0 12px rgba(255,213,74,0.5), 0 4px 10px #000;
  opacity:0; filter:blur(16px);
  transition:opacity .9s ease, filter .9s ease, letter-spacing .9s ease, text-indent .9s ease;
}
#dbLayer.db-title-on .db-title{ opacity:1; filter:blur(0); letter-spacing:0.04em; text-indent:0.04em; }
#dbLayer.db-low .db-title{ transition:opacity .15s ease; filter:none; letter-spacing:0.12em; text-indent:0.12em; }

#dbLayer .db-sub{
  position:absolute; left:0; right:0; top:188px; text-align:center;
  font-family:'EB Garamond',Georgia,serif; font-size:30px; letter-spacing:0.04em;
  color:rgba(243,226,189,0.72); text-shadow:0 2px 6px #000;
  opacity:0; transition:opacity .7s ease .18s;
}
#dbLayer.db-title-on .db-sub{ opacity:1; }
#dbLayer.db-low .db-sub{ transition:opacity .12s ease; }

/* --- три зоны. Крупные плиты во весь экран, а НЕ кнопки боя: это другой
   разговор, и глаз должен это понять раньше, чем прочтёт надпись. */
/* 🔴 ЗОНЫ — КРУГИ (Andy 20.09.2026: «зоны везде у нас в кругах, а тут вдруг
   квадраты»). Тот же вид, что у кнопок зон в панели ходов, только во весь
   экран: круглая плашка со значком, подпись снаружи под кругом. */
#dbLayer .db-zones{
  position:absolute; left:0; right:0; top:248px;
  display:flex; justify-content:center; align-items:flex-start; gap:56px;
  pointer-events:none;
}
#dbLayer.db-zones-on .db-zones{ pointer-events:auto; }
#dbLayer .db-zone{
  position:relative; padding:0; cursor:pointer; background:none; border:none;
  display:flex; flex-direction:column; align-items:center; gap:14px;
  opacity:0; transform:translateY(46px) scale(0.94);
  transition:opacity .55s ease, transform .55s cubic-bezier(.2,.8,.3,1), filter .3s ease;
}
#dbLayer .db-zone-disc{
  position:relative; width:252px; height:252px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:radial-gradient(circle at 50% 38%, rgba(38,27,18,0.95), rgba(10,7,5,0.97));
  border:3px solid rgba(217,180,92,0.55);
  box-shadow:inset 0 0 44px rgba(0,0,0,0.8), 0 8px 26px rgba(0,0,0,0.6);
  transition:border-color .25s ease, box-shadow .25s ease;
}
#dbLayer .db-zone img{ width:146px; height:146px; filter:drop-shadow(0 3px 8px rgba(0,0,0,0.9)); }
#dbLayer .db-zone-name{
  font-family:'Pirata One','Cinzel',serif; font-size:40px; letter-spacing:0.14em;
  color:var(--c-gold-bright); text-shadow:0 2px 6px #000;
}
#dbLayer .db-zone-mark{
  position:absolute; top:6px; right:24px; font-size:44px; line-height:1;
  color:#ffd54a; text-shadow:0 0 14px rgba(255,213,74,0.8), 0 2px 6px #000;
}
#dbLayer.db-zones-on .db-zone{ opacity:1; transform:none; }
/* 🔴 Медленный пульс, пока идёт выбор (просьба Andy): круг дышит целиком —
   и размером, и светом, — а не мигает рамкой. Три круга бьются вразнобой,
   со сдвигом, иначе экран пульсирует одним куском. */
#dbLayer.db-zones-on .db-zone-disc{ animation:db-pulse 2.4s ease-in-out infinite; }
#dbLayer.db-zones-on .db-zone:nth-child(2) .db-zone-disc{ animation-delay:.3s; }
#dbLayer.db-zones-on .db-zone:nth-child(3) .db-zone-disc{ animation-delay:.6s; }
@keyframes db-pulse{
  0%,100%{ transform:scale(1);
    border-color:rgba(217,180,92,0.45);
    box-shadow:inset 0 0 44px rgba(0,0,0,0.8), 0 8px 26px rgba(0,0,0,0.6); }
  50%    { transform:scale(1.045);
    border-color:rgba(255,213,74,0.9);
    box-shadow:inset 0 0 44px rgba(0,0,0,0.62), 0 0 40px rgba(255,150,60,0.38), 0 8px 26px rgba(0,0,0,0.6); }
}
#dbLayer .db-zone:hover{ filter:brightness(1.18); }
#dbLayer.db-low .db-zone{ transition:opacity .12s ease; }
#dbLayer.db-low .db-zone-disc{ animation:none; }

/* выбранная мной / погашенные / ход соперника */
#dbLayer .db-zone-mine .db-zone-disc{ animation:none !important; border-color:#ffd54a !important;
  box-shadow:inset 0 0 44px rgba(0,0,0,0.5), 0 0 40px rgba(255,180,70,0.55) !important; }
#dbLayer .db-zone-off{ opacity:0.16 !important; filter:grayscale(1); }
#dbLayer .db-zone-off .db-zone-disc{ animation:none !important; }
#dbLayer .db-zone-atk{ opacity:1 !important; }
#dbLayer .db-zone-atk .db-zone-disc{ animation:none !important; border-color:#ff5a3c !important;
  box-shadow:inset 0 0 44px rgba(60,0,0,0.7), 0 0 46px rgba(255,70,40,0.65) !important; }
#dbLayer .db-zone-def{ opacity:1 !important; }
#dbLayer .db-zone-def .db-zone-disc{ animation:none !important; border-color:#7ec8ff !important;
  box-shadow:inset 0 0 44px rgba(0,20,40,0.7), 0 0 46px rgba(120,190,255,0.55) !important; }
#dbLayer .db-zone-clash{ opacity:1 !important; }
#dbLayer .db-zone-clash .db-zone-disc{ animation:none !important; border-color:#ffd54a !important;
  box-shadow:inset 0 0 44px rgba(40,30,0,0.7), 0 0 56px rgba(255,213,74,0.8) !important; }

#dbLayer .db-call{
  position:absolute; left:0; right:0; top:594px; text-align:center;
  font-family:'Cinzel',serif; font-weight:700; font-size:30px; letter-spacing:0.22em;
  color:#ffd54a; text-shadow:0 0 16px rgba(255,154,74,0.5), 0 2px 6px #000;
  opacity:0; transition:opacity .5s ease;
}
#dbLayer.db-zones-on .db-call{ opacity:1; }

/* --- фитиль: срок на выбор — догорающий огонь, а не цифра.
   Цифра давит арифметикой, огонь тревожит. */
#dbLayer .db-fuse{
  position:absolute; left:50%; transform:translateX(-50%); top:650px;
  width:860px; height:7px; border-radius:4px;
  background:rgba(255,255,255,0.07); overflow:hidden; opacity:0; transition:opacity .4s ease;
}
#dbLayer .db-fuse-on{ opacity:1; }
#dbLayer .db-fuse i{
  display:block; height:100%; width:100%;
  background:linear-gradient(90deg, rgba(255,90,20,0.35), #ff9a4a 55%, #ffd54a 100%);
  box-shadow:0 0 18px rgba(255,140,50,0.85);
}

/* --- исход */
/* На исходе сцена перестраивается: заголовок уходит (он уже сказал своё),
   зоны отступают вверх и мельчают — на них видно, КТО куда пошёл, но спорить
   с приговором они больше не должны. Слово исхода встаёт на освободившееся
   место. Без этой перестановки «HELD» ложилось прямо на плиту зоны. */
#dbLayer.db-hit .db-title, #dbLayer.db-held .db-title,
#dbLayer.db-hit .db-sub, #dbLayer.db-held .db-sub{ opacity:0; transition:opacity .3s ease; }
#dbLayer.db-hit .db-zones, #dbLayer.db-held .db-zones{
  transform:translateY(-104px) scale(0.58); transform-origin:50% 0;
  transition:transform .4s cubic-bezier(.2,.8,.3,1);
}
#dbLayer .db-outcome{
  position:absolute; left:0; right:0; top:352px; text-align:center;
  opacity:0; transform:scale(0.86);
  transition:opacity .35s ease, transform .35s cubic-bezier(.2,.9,.3,1);
  pointer-events:none;
}
#dbLayer .db-outcome-on{ opacity:1; transform:none; }
#dbLayer .db-outcome-word{
  font-family:'Pirata One','Cinzel',serif; font-size:148px; line-height:1; letter-spacing:0.14em;
  text-indent:0.14em; text-transform:uppercase;
}
#dbLayer .db-outcome-sub{
  margin-top:14px; font-family:'EB Garamond',Georgia,serif; font-size:30px;
  color:rgba(243,226,189,0.8); text-shadow:0 2px 6px #000;
}
#dbLayer.db-hit .db-outcome-word{ color:#ff5b3a;
  text-shadow:0 0 70px rgba(255,60,25,0.95), 0 0 24px rgba(255,120,80,0.5), 0 4px 12px #000; }
#dbLayer.db-held .db-outcome-word{ color:#bfe3ff; text-shadow:0 0 54px rgba(120,190,255,0.7), 0 4px 12px #000; }
/* попадание заливает экран багровым сверху вниз; выстоял — экран светлеет */
/* Попадание НЕ заливает экран ровным красным — это читается как «ошибка
   системы», а не как смерть. Свет идёт снизу от места удара и гаснет к краям:
   тёмная сцена с багровым подсветом, где слово DEATH остаётся самым ярким. */
#dbLayer.db-hit .db-dim{
  background:
    radial-gradient(90% 75% at 50% 62%, rgba(150,14,8,0.42) 0%, rgba(48,3,3,0.82) 44%, rgba(9,0,0,0.93) 100%);
}
#dbLayer.db-held .db-dim{ opacity:0.7; }

/* один белый кадр на касании — не вспышка-мигалка, а именно кадр */
#dbLayer .db-flash{
  position:absolute; inset:0; background:#fff; opacity:0; pointer-events:none;
}
#dbLayer .db-flash-on{ animation:db-frame .42s ease-out 1; }
@keyframes db-frame{ 0%{ opacity:0.92; } 12%{ opacity:0.5; } 100%{ opacity:0; } }

/* Телефон в альбомной: холст масштабируется целиком (#newHudFrame), поэтому
   отдельных размеров здесь не нужно — правится только то, что задано в px
   вне холста. Проверка — tools/deathblow_test.js, ширина 844×390. */
