/*
 * ТЕХНОМАГИЯ — оболочка.
 *
 * Игра занимает весь экран, интерфейс лежит поверх холста. Всё, что
 * можно, сделано на CSS: свечение не должно стоить кадров, их и так мало
 * на телефоне.
 *
 * Палитра — ночной кибер-парк: холодная зелень земли, мятный и голубой
 * свет фонарей, янтарь на предупреждениях. Прежняя кассетная лиловая
 * гамма ушла вместе с плёночными слоями: она принадлежала другой игре, и
 * две игры одного автора не должны выглядеть одной.
 */

:root {
  --ink: #050b0c;
  --acid: #3dffb4;
  --violet: #7df3ff;
  --pink: #ff5d8f;
  --amber: #ffc95a;
  --paper: #e8fbf6;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--mono);
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
}

#screen {
  position: fixed;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;
  cursor: crosshair;
}


/*
 * Кнопка возврата. На сайте такая же лежит в общем /game-menu.css, но
 * игра живёт отдельным репозиторием и обязана открываться сама по себе —
 * из папки, с флешки, откуда угодно. Двадцать строк дешевле зависимости.
 */
/*
 * Область нажатия не меньше 44 точек по обеим сторонам — это не вкус, а
 * порог, ниже которого палец промахивается. Было 54x19: девятнадцать
 * точек это меньше трёх миллиметров, и попасть в такое на ходу нельзя.
 *
 * Размер задаётся самому элементу, а не невидимой подложкой: подложку не
 * видно ни в замере, ни глазом, и «кнопка выглядит крошечной, но нажать
 * можно» — это всё равно плохая кнопка.
 */
.game-home-menu {
  position: fixed;
  top: max(10px, env(safe-area-inset-top));
  right: max(10px, env(safe-area-inset-right));
  z-index: 1000;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid var(--acid);
  background: #0b1010f2;
  color: var(--paper);
  font: 700 10px var(--mono);
  letter-spacing: .08em;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: 0 0 14px #76ff9f20;
}

.game-home-menu:hover,
.game-home-menu:focus-visible {
  background: #153725;
  color: #fff;
  outline: 2px solid var(--violet);
  outline-offset: 3px;
}

@media (max-height: 600px) and (orientation: landscape) {
  .game-home-menu { padding: 8px 10px; }   /* min-height 44 держится сверху */
}


/* =========================================================
   HUD
   ========================================================= */

.hud {
  position: fixed;
  top: max(10px, env(safe-area-inset-top));
  left: max(10px, env(safe-area-inset-left));
  /* Справа сверху живёт кнопка «НА САЙТ» — HUD в неё не заезжает. */
  right: max(112px, env(safe-area-inset-right));
  z-index: 10;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: flex-start;
  pointer-events: none;
}

/* Атрибут hidden обязан побеждать раскладку: иначе спрятанный блок
   исправно занимает место, а игрок читает пустую строку как поломку. */
.hud-slot[hidden] { display: none; }

.hud-slot {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 8px 11px;
  border: 1px solid #ffffff1c;
  background: #0b0713cc;
  backdrop-filter: blur(3px);
}

.hud-slot b {
  font: 800 13px/1 var(--mono);
  letter-spacing: .1em;
  color: var(--acid);
}

.hud-label {
  font: 700 8px/1 var(--mono);
  letter-spacing: .16em;
  color: #8a7c99;
}

.hud-score {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}

.hud-score b { color: var(--paper); }

.ammo {
  display: flex;
  gap: 3px;
  min-height: 7px;
}

.ammo i {
  width: 3px;
  height: 9px;
  background: var(--amber);
  box-shadow: 0 0 6px #ffe06b60;
}

.ammo[data-empty="1"] i { background: #5b4b2a; }

.hud-points {
  position: relative;
  flex-direction: row;
  align-items: center;
  gap: 8px;
}

.hud-points b { color: var(--amber); }

/*
 * Цепочка убийств. Полоска — не украшение: по ней видно, сколько осталось
 * до обнуления множителя, а это и есть весь риск в счёте.
 */
.combo {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 34px;
  padding: 3px 6px;
  border: 1px solid var(--pink);
  background: #2a0a1b;
  animation: comboPop .18s ease-out;
}

/*
 * Съёмка витрины. Из кадра убирается всё, что не игра: показания, кнопки,
 * подсказки, ссылка на сайт. Три секунды чистого кадра — иначе на карточке
 * половину места занимает интерфейс, а не то, ради чего её снимали.
 *
 * Перечислено поимённо намеренно. Общее правило вида «спрятать всё, кроме
 * холста» переживёт ровно до первого нового блока в разметке, и тот молча
 * окажется в кадре.
 */
body.is-shooting .hud,
body.is-shooting .daemons,
body.is-shooting .pad,
body.is-shooting .toast,
body.is-shooting .found,
body.is-shooting .ghost,
body.is-shooting .mute,
body.is-shooting .game-home-menu,
body.is-shooting .veil,
body.is-shooting .tome {
  display: none !important;
}

/*
 * Ячейка, в которую только что легла стихия. Вспышка короткая и резкая:
 * она отмечает событие, а не рисует состояние, и к следующему нажатию
 * должна успеть погаснуть — иначе три вспышки сольются в одно свечение
 * и разница между «набираю» и «набрал» снова пропадёт.
 */
.stack .is-landed {
  animation: stack-land .22s ease-out;
}

@keyframes stack-land {
  0% { transform: scale(1.9); filter: brightness(2.4); }
  60% { transform: scale(.92); filter: brightness(1.4); }
  100% { transform: scale(1); filter: brightness(1); }
}

.combo[hidden] { display: none; }

.combo b {
  color: var(--pink);
  font: 900 13px/1 var(--mono);
}

.combo i {
  display: block;
  height: 2px;
  background: var(--pink);
  transform-origin: left center;
}

@keyframes comboPop {
  from { transform: scale(1.25); }
  to { transform: scale(1); }
}

.hud-target b { color: var(--violet); }

/* Время вышло за чужой результат — цель уже не побить, и это видно сразу. */
.hud-target[data-late="1"] b { color: var(--pink); }

.hud-stack {
  flex-direction: row;
  align-items: center;
  gap: 7px;
}

.stack {
  display: flex;
  gap: 4px;
}

.stack i {
  width: 15px;
  height: 15px;
  border: 1px solid #ffffff2a;
  background: transparent;
}

/* Набираемая стихия мигает, пока не легла в очередь: это и есть та секунда,
   которую игрок стоит замедленным. */
.stack i.is-charging {
  border-width: 2px;
  animation: chargePulse .26s linear infinite;
}

@keyframes chargePulse {
  from { opacity: .35; }
  to { opacity: 1; }
}

.form {
  color: var(--paper);
  font: 900 13px var(--mono) !important;
  letter-spacing: .1em;
  white-space: nowrap;
}

.form[hidden] { display: none; }

/* =========================================================
   ПЯТЬ КЛАВИШ
   =========================================================
   Панель висит всегда. Состав — весь язык игры, и держать
   его в памяти игрок не обязан: пока клавиши на экране,
   заклинание собирается глазами, а не по памяти.
   ========================================================= */

.daemons {
  position: fixed;
  left: 50%;
  bottom: max(14px, env(safe-area-inset-bottom));
  z-index: 9;
  display: flex;
  gap: 8px;
  transform: translateX(-50%);
}

.daemon-key {
  display: grid;
  justify-items: center;
  gap: 2px;
  width: 62px;
  min-height: 44px;
  padding: 7px 4px 6px;
  border: 1px solid currentColor;
  border-radius: 3px;
  background: #0a0f10e6;
  cursor: pointer;
  touch-action: none;
  transition: transform .08s, background .12s;
}

.daemon-key b {
  font: 900 17px/1 var(--mono);
  color: inherit;
}

.daemon-key i {
  font: 700 8px/1 var(--mono);
  font-style: normal;
  letter-spacing: .1em;
  color: #8fa39b;
}

.daemon-key:hover { background: #10201ce6; }
.daemon-key.is-held,
.daemon-key[data-active="1"] {
  transform: translateY(2px);
  background: currentColor;
}
.daemon-key[data-active="1"] b { color: #050b0c; }
.daemon-key[data-active="1"] i { color: #050b0c; }

/* Недоступное на этаже не прячется, а тушится: так видно, что стихий пять
   и какие ещё впереди. Обещания при этом нет — по такой кнопке видно, что
   она закрыта. */
.daemon-key[data-locked="1"] {
  opacity: .3;
  filter: grayscale(1);
  cursor: default;
}

.daemon-key[data-element="fire"] { border-color: #ff5a1f; color: #ff5a1f; }
.daemon-key[data-element="water"] { border-color: #4de1ff; color: #4de1ff; }
.daemon-key[data-element="wind"] { border-color: #76ff9f; color: #76ff9f; }
.daemon-key[data-element="earth"] { border-color: #d08a3e; color: #d08a3e; }
.daemon-key[data-element="bolt"] { border-color: #ffe14d; color: #ffe14d; }

.mute {
  position: fixed;
  top: calc(max(10px, env(safe-area-inset-top)) + 44px);
  right: max(10px, env(safe-area-inset-right));
  z-index: 1000;
  min-height: 44px;
  padding: 8px 10px;
  border: 1px solid #ffffff22;
  background: #0b0713e6;
  color: #a596b3;
  font: 700 9px var(--mono);
  letter-spacing: .1em;
  cursor: pointer;
}

.mute[data-off="1"] { color: var(--pink); border-color: #ff2d9555; }

/* Вторая кнопка того же ряда: книга стоит под звуком, а не в углу карты. */
.mute-second { top: calc(max(10px, env(safe-area-inset-top)) + 74px); }

.toast {
  position: fixed;
  left: 50%;
  bottom: max(22vh, 140px);
  z-index: 10;
  padding: 9px 14px;
  border-left: 3px solid var(--acid);
  background: #0b0713e6;
  color: var(--paper);
  font: 800 11px var(--mono);
  letter-spacing: .14em;
  white-space: nowrap;
  transform: translateX(-50%);
  pointer-events: none;
}

.operation-hud {
  position: fixed;
  left: 50%;
  top: max(76px, calc(env(safe-area-inset-top) + 70px));
  z-index: 8;
  display: grid;
  gap: 3px;
  width: min(560px, calc(100vw - 160px));
  padding: 8px 12px;
  border: 1px solid #7ffcff55;
  background: #061013d9;
  color: #d9ffff;
  font: 700 10px var(--mono);
  letter-spacing: .1em;
  text-align: center;
  transform: translateX(-50%);
  pointer-events: none;
}

.operation-hud[hidden], .operation-hud span[hidden] { display: none; }
.operation-hud b { color: #7ffcff; font-size: 12px; }
#operationOptional { color: #ffd27f; }
#operationLesson { color: #ffffffaa; }

.physical-observation {
  position: fixed;
  left: 50%;
  top: max(152px, calc(env(safe-area-inset-top) + 146px));
  z-index: 8;
  width: min(520px, calc(100vw - 180px));
  padding: 7px 11px;
  border-left: 2px solid #7ffcff;
  background: #050b0cdd;
  color: #d9ffff;
  font: 700 10px/1.35 var(--mono);
  letter-spacing: .08em;
  text-align: center;
  transform: translateX(-50%);
  pointer-events: none;
}

.physical-observation[hidden] { display: none; }

@media (max-width: 700px) {
  .operation-hud {
    top: max(68px, calc(env(safe-area-inset-top) + 62px));
    width: calc(100vw - 118px);
    font-size: 8px;
    letter-spacing: .06em;
  }

  .physical-observation {
    top: max(137px, calc(env(safe-area-inset-top) + 131px));
    width: calc(100vw - 132px);
    font-size: 8px;
    letter-spacing: .04em;
  }
}


/* =========================================================
   ПАЛЬЦЫ
   ========================================================= */

.ghost {
  position: fixed;
  z-index: 8;
  width: 0;
  height: 0;
  pointer-events: none;
}

.ghost::before {
  content: '';
  position: absolute;
  left: -46px;
  top: -46px;
  width: 92px;
  height: 92px;
  border: 1px solid #ffffff20;
  border-radius: 50%;
}

.ghost i {
  position: absolute;
  left: -17px;
  top: -17px;
  width: 34px;
  height: 34px;
  border: 1px solid var(--acid);
  border-radius: 50%;
  background: #76ff9f1f;
}

/*
 * Кнопки стоят столбиком у правой кромки, а не в углу. Угол занят: там
 * лежит большой палец, который целится плавающим стиком, и кнопка в том
 * же месте отбирает у него прицел.
 */
.pad {
  position: fixed;
  right: max(10px, env(safe-area-inset-right));
  /* Внизу, а не по центру правого края: посередине она легла прямо на
     поле и перехватывала клики по тому, во что игрок целился. */
  bottom: max(14px, env(safe-area-inset-bottom));
  z-index: 9;
  /* Кнопка видна и на мыши. Играть одной мышью должно быть можно целиком:
     стихии набираются кликом по нижнему ряду, а выпускать было нечем —
     пробел оставался единственным выходом, и это уже не «одной мышью». */
  display: grid;
  opacity: .82;
  grid-auto-flow: row;
  gap: 9px;
  justify-items: end;
}

/* На мыши она скромнее: там есть пробел и клик, и кнопка — запасной путь. */
.pad-big { width: 86px; height: 86px; border-radius: 50%; font: 900 13px var(--mono); }

.pad-key {
  border: 1px solid var(--acid);
  background: #0b1010cc;
  color: var(--paper);
  font: 800 9px var(--mono);
  letter-spacing: .08em;
  border-radius: 50%;
  touch-action: none;
}

.pad-small {
  width: 62px;
  height: 62px;
}

.pad-big {
  order: -1;
  width: 76px;
  height: 76px;
  border-width: 2px;
  border-color: var(--pink);
  color: var(--pink);
  font-size: 11px;
  box-shadow: 0 0 24px #ff2d9525;
}

.pad-key.is-held {
  background: #76ff9f28;
  transform: scale(.94);
}

/* =========================================================
   ТЕЛЕФОН
   =========================================================
   Порядок важности задан игрой, а не вкусом: поле, кнопки
   магии, книга, всё остальное. Поэтому поле забирает почти
   весь экран, магия лежит сразу под ним, книга остаётся
   различимой кнопкой, а звук и часы ужимаются до строчки.
   ========================================================= */

@media (pointer: coarse) and (orientation: portrait),
       (max-width: 700px) and (orientation: portrait) {
  /* Нижние игровые кнопки остаются поверх книги. Запас не даёт им закрыть
     последние наблюдения: карточку можно прокрутить так, чтобы текст целиком
     оказался выше управления. */
  .tome-card::after {
    content: "";
    display: block;
    height: calc(112px + env(safe-area-inset-bottom));
  }

  #screen {
    inset: 0 0 auto 0;
    height: 74%;
  }

  /* Стихии — сразу под полем, во всю ширину и первыми под пальцем. */
  .daemons {
    bottom: auto;
    top: calc(74% + 8px);
    gap: 5px;
  }

  /* Палец — не курсор: клетка ниже сорока четырёх точек промахивается. */
  .daemon-key {
    width: 68px;
    min-height: 46px;
    padding: 6px 3px;
    display: grid;
    align-content: center;
  }

  .daemon-key b { display: none; }
  .daemon-key i { font-size: 10px; }

  /* Выпуск — под правым большим пальцем. По нему бьют не глядя. */
  .pad {
    top: auto;
    right: max(12px, env(safe-area-inset-right));
    bottom: max(12px, env(safe-area-inset-bottom));
    display: grid;
    transform: none;
  }

  .pad-big {
    width: 116px;
    height: 116px;
    border-radius: 50%;
    font: 900 17px var(--mono);
  }

  /* Книга — третья по важности, значит остаётся кнопкой, а не строчкой. */
  .mute-second {
    top: auto;
    left: max(12px, env(safe-area-inset-left));
    right: auto;
    bottom: calc(max(12px, env(safe-area-inset-bottom)) + 46px);
    padding: 11px 18px;
    font: 800 12px var(--mono);
    border-color: var(--violet);
    color: var(--paper);
  }

  /* Часы, счёт, звук и ссылка — последние. Строчкой, мелко. */
  .hud {
    top: auto;
    bottom: max(12px, env(safe-area-inset-bottom));
    left: max(12px, env(safe-area-inset-left));
    right: auto;
    justify-content: flex-start;
    max-width: 58vw;
    gap: 4px;
  }

  .hud-slot { padding: 3px 6px; }
  .hud-slot b { font-size: 10px; }
  .hud-label { font-size: 7px; }
  .hud-stack { display: none; }

  /* Кнопка книги тоже .mute, поэтому здесь она исключена явно: иначе это
     правило садит её ровно на кнопку звука. */
  .mute:not(.mute-second),
  .game-home-menu {
    top: auto;
    right: auto;
    left: max(12px, env(safe-area-inset-left));
    bottom: calc(max(12px, env(safe-area-inset-bottom)) + 94px);
    padding: 4px 10px;
    font: 700 8px var(--mono);
  }

  .game-home-menu { left: calc(max(12px, env(safe-area-inset-left)) + 82px); }

  .toast { bottom: calc(26% + 12px); }
  .found { top: 32%; }
}

/*
 * Телефон боком. Полосы снизу тут быть не может: высоты и так мало, и
 * любая полка съедает половину поля. Всё лежит поверх, по углам, и всё
 * прозрачное — под кнопками должно быть видно, что происходит.
 */
@media (pointer: coarse) and (orientation: landscape) {
  .pad {
    top: auto;
    right: max(12px, env(safe-area-inset-right));
    bottom: max(12px, env(safe-area-inset-bottom));
    display: grid;
    transform: none;
  }

  .pad-big {
    width: 96px;
    height: 96px;
    border-radius: 50%;
    font: 900 14px var(--mono);
  }

  /* Стихии — рядом вдоль нижней кромки, левее кнопки выпуска. */
  .daemons {
    left: max(12px, env(safe-area-inset-left));
    bottom: max(12px, env(safe-area-inset-bottom));
    transform: none;
    gap: 4px;
  }

  .daemon-key {
    width: 60px;
    min-height: 44px;
    padding: 5px 3px;
    display: grid;
    align-content: center;
    background: #050b0cd0;
  }

  .daemon-key b { display: none; }
  .daemon-key i { font-size: 9px; }

  /* Книга — заметной кнопкой в правом верхнем углу, подальше от пальцев. */
  .mute-second {
    top: max(10px, env(safe-area-inset-top));
    right: max(12px, env(safe-area-inset-right));
    left: auto;
    bottom: auto;
    padding: 9px 14px;
    font: 800 11px var(--mono);
    border-color: var(--violet);
    color: var(--paper);
    background: #050b0cd0;
  }

  /* Часы и счёт — мелкой строкой сверху слева, на своём месте. */
  .hud {
    top: max(8px, env(safe-area-inset-top));
    bottom: auto;
    gap: 4px;
  }

  .hud-slot { padding: 3px 6px; background: #050b0cd0; }
  .hud-slot b { font-size: 10px; }
  .hud-label { font-size: 7px; }
  .hud-stack { display: none; }

  .mute:not(.mute-second),
  .game-home-menu {
    top: calc(max(10px, env(safe-area-inset-top)) + 40px);
    right: max(12px, env(safe-area-inset-right));
    left: auto;
    bottom: auto;
    padding: 4px 10px;
    font: 700 8px var(--mono);
    background: #050b0cd0;
  }

  .game-home-menu { top: calc(max(10px, env(safe-area-inset-top)) + 68px); }

  .toast { bottom: calc(max(12px, env(safe-area-inset-bottom)) + 118px); }
  .found { top: 34%; }
}

/* =========================================================
   ЭКРАНЫ МЕЖДУ ПОПЫТКАМИ
   ========================================================= */

.veil {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: grid;
  place-items: center;
  padding: 18px;
  background: #05040ad9;
  backdrop-filter: blur(6px);
}

.veil[hidden] { display: none; }

.veil-card {
  width: min(430px, 100%);
  max-height: 92vh;
  overflow: auto;
  padding: 24px 22px 20px;
  border: 2px solid var(--acid);
  background: linear-gradient(150deg, #1a0b28, #0a1512);
  box-shadow: 10px 10px 0 #05040a, 0 0 44px #76ff9f22;
}

.veil[data-tone="dead"] .veil-card { border-color: var(--pink); box-shadow: 10px 10px 0 #05040a, 0 0 44px #ff2d9530; }
.veil[data-tone="clear"] .veil-card { border-color: var(--amber); box-shadow: 10px 10px 0 #05040a, 0 0 44px #ffe06b30; }
.veil[data-tone="pause"] .veil-card { border-color: var(--violet); box-shadow: 10px 10px 0 #05040a, 0 0 44px #bc70ff30; }

.veil-kicker {
  display: block;
  margin-bottom: 8px;
  color: var(--violet);
  font: 800 9px var(--mono);
  letter-spacing: .22em;
}

.veil h1 {
  margin: 0 0 12px;
  font: 900 30px/1 system-ui, -apple-system, sans-serif;
  letter-spacing: .01em;
  color: var(--acid);
  text-transform: uppercase;
}

.veil[data-tone="dead"] h1 { color: var(--pink); }
.veil[data-tone="clear"] h1 { color: var(--amber); }
.veil[data-tone="pause"] h1 { color: var(--violet); }

.veil p {
  margin: 0 0 16px;
  color: #cbbbd6;
  font-size: 12px;
  line-height: 1.55;
}

.veil-stats span[data-warn="1"] {
  color: var(--pink);
}

.veil-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin-bottom: 18px;
  color: #8a7c99;
  font: 700 9px var(--mono);
  letter-spacing: .14em;
  line-height: 1.5;
}

.veil-score {
  margin: 0 0 18px;
  padding: 14px;
  border: 1px solid #ffffff1c;
  background: #06040c;
}

.veil-score[hidden] { display: none; }

.veil-score .rank {
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin-bottom: 12px;
}

.veil-score .rank b {
  font: 900 46px/1 system-ui, -apple-system, sans-serif;
  color: var(--amber);
  text-shadow: 3px 3px 0 #05040a;
}

.veil-score .rank span {
  color: #6f6280;
  font: 800 9px var(--mono);
  letter-spacing: .2em;
}

.veil-score[data-rank="S"] .rank b { color: var(--pink); }
.veil-score[data-rank="A"] .rank b { color: var(--acid); }
.veil-score[data-rank="D"] .rank b { color: #8a7c99; }

.veil-score ul {
  display: grid;
  gap: 5px;
  margin: 0 0 11px;
  padding: 0;
  list-style: none;
}

.veil-score li {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  color: #a596b3;
  font: 700 10px var(--mono);
  letter-spacing: .08em;
}

.veil-score li b { color: var(--paper); font-weight: 800; }

.score-total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding-top: 9px;
  border-top: 1px solid #ffffff1c;
  color: #6f6280;
  font: 800 9px var(--mono);
  letter-spacing: .18em;
}

.score-total b {
  color: var(--amber);
  font: 900 22px/1 var(--mono);
}

.score-best {
  margin: 9px 0 0;
  color: #6f6280;
  font: 700 9px var(--mono);
  letter-spacing: .12em;
}

.score-best[data-record="1"] { color: var(--acid); }

.veil-action, .veil-second {
  width: 100%;
  min-height: 48px;
  border: 2px solid var(--acid);
  background: #16412c;
  color: #fff;
  font: 800 12px var(--mono);
  letter-spacing: .12em;
  cursor: pointer;
  box-shadow: 4px 4px 0 #05040a;
}

.veil-second {
  margin-top: 9px;
  border-color: #ffffff28;
  background: transparent;
  color: #a596b3;
  box-shadow: none;
}

.veil-action:hover, .veil-second:hover { background: #1e5c3d; color: #fff; }

.veil-code {
  margin: 0 0 16px;
  padding: 12px;
  border: 1px dashed #ffffff22;
  background: #06040c;
}

.veil-code label {
  display: block;
  margin-bottom: 6px;
  color: var(--violet);
  font: 800 8px var(--mono);
  letter-spacing: .18em;
}

.code-row { display: flex; gap: 6px; }

.code-row #nickBox {
  flex: 0 0 120px;
  color: var(--acid);
  text-transform: uppercase;
}

.code-row input {
  flex: 1;
  min-width: 0;
  height: 38px;
  padding: 0 9px;
  border: 1px solid #ffffff22;
  background: #0d0817;
  color: var(--amber);
  font: 600 11px var(--mono);
  outline: none;
}

.code-row button {
  padding: 0 12px;
  border: 1px solid var(--violet);
  background: #23113a;
  color: var(--paper);
  font: 800 9px var(--mono);
  letter-spacing: .1em;
  cursor: pointer;
}

.veil-code small {
  display: block;
  margin-top: 7px;
  color: #6f6280;
  font-size: 9px;
  line-height: 1.5;
}

/* Низкий экран: карточка ужимается, иначе кнопка уезжает за кромку. */
@media (max-height: 520px) {
  .veil-card { padding: 16px; }
  .veil h1 { font-size: 22px; }
  .veil p { margin-bottom: 10px; }
}

/* =========================================================
   КНИГА ЗАКЛИНАНИЙ
   =========================================================
   Сетка из клеток, а не список: двадцать пять веществ должны
   читаться одним взглядом как заполненная наполовину доска —
   именно вид пустых клеток и заставляет их закрывать.
   ========================================================= */

.tome {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: grid;
  place-items: center;
  padding: 18px;
  background: #05040ae6;
  backdrop-filter: blur(6px);
}

.tome[hidden] { display: none; }

.tome-card {
  width: min(560px, 100%);
  max-height: 92vh;
  overflow: auto;
  padding: 20px 20px 18px;
  border: 2px solid var(--violet);
  background: linear-gradient(150deg, #170c26, #0a1018);
  box-shadow: 10px 10px 0 #05040a, 0 0 44px #bc70ff2e;
}

.tome-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 10px;
}

.tome-head .veil-kicker { margin: 0; }
.tome-head b { color: var(--amber); font: 800 12px var(--mono); }

.tome-close {
  margin-left: auto;
  padding: 5px 10px;
  border: 1px solid var(--violet);
  background: none;
  color: var(--paper);
  font: 700 9px var(--mono);
  letter-spacing: .14em;
  cursor: pointer;
}

.tome-close:hover { background: #bc70ff22; }

.tome-hint {
  margin: 0 0 14px;
  color: #9a8fae;
  font: 600 10px/1.5 var(--mono);
}

.tome-title {
  margin: 18px 0 8px;
  color: var(--violet);
  font: 800 9px var(--mono);
  letter-spacing: .22em;
}

.tome-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 6px;
}

.tome-cell {
  padding: 7px 8px;
  border: 1px solid #ffffff18;
  background: #ffffff08;
  min-height: 52px;
}

/* Неоткрытая клетка показывает форму пустоты — сколько стихий в составе.
   Пустая клетка не зовёт, «состав из трёх» зовёт. */
/*
 * Значок заклинания. Он крупнее подписи намеренно: клетка читается
 * картинкой, а имя дочитывают уже после того, как узнали вещь. Файл
 * может не приехать — набор рисуется частями, — и тогда картинка
 * убирает себя сама, а клетка остаётся прежней.
 */
.tome-icon {
  display: block;
  width: 34px;
  height: 34px;
  margin: 2px 0 3px;
  image-rendering: auto;
}

.tome-list .tome-icon {
  float: left;
  width: 28px;
  height: 28px;
  margin: 0 7px 0 0;
}

.tome-cell[data-known="0"] { opacity: .42; }
.tome-cell[data-known="0"] .tome-name { color: #6b6280; }

.tome-marks {
  display: flex;
  gap: 3px;
  margin-bottom: 4px;
}

.tome-marks i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
}

.tome-name {
  display: block;
  font: 800 11px/1.2 var(--mono);
  letter-spacing: .04em;
}

.tome-note {
  display: block;
  margin-top: 3px;
  color: #9a8fae;
  font: 600 8px/1.35 var(--mono);
}

.tome-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 5px;
}

.tome-list li {
  padding: 7px 9px;
  border-left: 3px solid #ffffff20;
  background: #ffffff08;
}

.tome-list li[data-known="0"] { opacity: .5; }

.tome-sign {
  font: 800 11px var(--mono);
  letter-spacing: .05em;
}

.tome-recipe {
  color: #9a8fae;
  font: 600 9px var(--mono);
}


/* =========================================================
   НАХОДКА
   =========================================================
   Новое вещество или именное заклинание — единственное
   событие, ради которого стоит отвлечь игрока от боя. Всё
   остальное он прочитает потом в книге; это надо заметить
   сейчас, поэтому крупно и по центру.
   ========================================================= */

.found {
  position: fixed;
  left: 50%;
  top: 34%;
  z-index: 12;
  display: grid;
  justify-items: center;
  gap: 6px;
  padding: 34px 62px;
  text-align: center;
  pointer-events: none;
  transform: translate(-50%, -50%);
  animation: found-in .5s cubic-bezier(.2, 1.4, .4, 1);

  /* Подложка размытым пятном, а не панелью: объявление всплывает поверх
     боя, и рамка посреди экрана читалась бы как окно, которое надо
     закрыть. Пятно гасит фон ровно там, где стоят буквы. */
  background: radial-gradient(
    ellipse at center,
    rgba(5, 11, 12, .92) 0%,
    rgba(5, 11, 12, .74) 48%,
    rgba(5, 11, 12, 0) 76%
  );
}

.found[hidden] { display: none; }

.found-kicker {
  font: 800 10px var(--mono);
  letter-spacing: .34em;
  color: #8fa39b;
}

.found b {
  font: 900 clamp(30px, 7vw, 58px)/1 system-ui, -apple-system, sans-serif;
  letter-spacing: .02em;
  text-transform: uppercase;
  text-shadow: 0 0 26px currentColor;
}

.found i {
  max-width: 24ch;
  font: 600 11px/1.4 var(--mono);
  font-style: normal;
  color: #b9cdc5;
}

@keyframes found-in {
  from { opacity: 0; transform: translate(-50%, -50%) scale(.86); }
  to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

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