/* ═══════════════════════════════════════════════════════════════════════════
   МУЛЬТИВСЕСВІТ — увесь вигляд застосунку в одному файлі.

   Раніше стилів було ТРИ: fonts.css, style.css і glass.css, і кожен їхав
   окремим запитом. Через повільний тунель це коштувало двох зайвих
   рукостискань перед першим кадром — і саме тому на першому відкритті встигав
   промайнути напівзастосований вигляд: базові стилі вже приїхали, скляні ще ні.

   Друга, гірша біда була в розбіжностях. Файли перевизначали одне одного, і
   одне й те саме імʼя означало різне залежно від того, звідки читати: `--r-lg`
   був 22px у style.css і 20px у glass.css. За час роботи так накопичилось
   шість правил для `.sec` і пʼять для індикатора вкладки.

   ПОРЯДОК СКЛЕЮВАННЯ ЗНАЧУЩИЙ і саме такий:
     1) fonts.css — @font-face мусить бути оголошений до першого використання;
     2) style.css — основа: палітра, сітка, типографіка;
     3) glass.css — скляний шар, який навмисно перекриває основу.

   Правити тепер тільки цей файл. Старі три видалено, щоб не лишалось спокуси
   редагувати те, що вже нікуди не підключено.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ────────────────────────────────────────────────────────────────────────
   Далі — колишній fonts.css
   ──────────────────────────────────────────────────────────────────────── */

/* Гарнітури лежать поруч із застосунком, а не на CDN: зовнішній домен
   коштував би ще одного DNS+TLS рукостискання на першому екрані, а він і
   так їде через повільний тунель. */
@font-face {
  font-family: 'Unbounded';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/unbounded-normal-700-cyrillic-ext.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'Unbounded';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/unbounded-normal-700-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Unbounded';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/unbounded-normal-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Unbounded';
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url('/fonts/unbounded-normal-900-cyrillic-ext.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'Unbounded';
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url('/fonts/unbounded-normal-900-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Unbounded';
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url('/fonts/unbounded-normal-900-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/playfair-italic-700-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/playfair-italic-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 900;
  font-display: swap;
  src: url('/fonts/playfair-italic-900-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 900;
  font-display: swap;
  src: url('/fonts/playfair-italic-900-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/fonts/jetbrains-800-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/fonts/jetbrains-800-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


/* ────────────────────────────────────────────────────────────────────────
   Далі — колишній style.css
   ──────────────────────────────────────────────────────────────────────── */

/* Мультивсесвіт — Telegram Mini App.

   ПАЛІТРА взята з портального вихору: кислотна зелень (#b6f24a → #2d7a1c) на
   темно-зеленому ґрунті, з жовтими й білими бризками з тієї ж картинки. Неон
   маджента/ціан — з другої, «розколотої планети»: він працює як семантичний
   колір (небезпека / інформація), а не як другий акцент.

   ТИПОГРАФІКА: три ролі й один масштаб. Display — важкий, широкий, з від'ємним
   трекінгом (заголовки екранів). Body — системний ґротеск. Data — моноширинний,
   для чисел і кодів: він і читабельніший у колонках, і підтримує «портальний
   термінал» як настрій.

   НАВІГАЦІЯ: фіксована знизу, БЕЗ горизонтального скролу. У Telegram свайп від
   краю — системний жест «закрити», тож стрічка вкладок, що їздить убік, змушує
   гравця випадково виходити із застосунку.
*/

:root {
  /* ґрунт — не сірий, а зелено-чорний: нейтраль обрано, а не успадковано */
  --void:        #061109;
  --void-2:      #0a1a10;
  --panel:       #10261a;
  --panel-2:     #16321f;
  --line:        #1e4526;

  /* портал */
  --acid:        #b6f24a;
  --portal:      #8fd93f;
  --portal-mid:  #4fa32a;
  --portal-deep: #2d7a1c;
  --portal-dark: #123f16;

  /* бризки з тієї ж картинки */
  --splash:      #f5e35c;
  --foam:        #eef7e6;

  /* семантика (з «розколотої планети») — не акцент, а стан */
  --danger:      #ff4f8b;
  --info:        #35e0f5;

  --ink:         #eaffe0;
  --ink-2:       #a8c9a4;
  --ink-3:       #6e8f6d;

  /* Шкалу заокруглень визначено НИЖЧЕ, одним блоком. Тут вона колись була
     теж — і два набори тихо розходились: --r-lg існував і як 22px, і як 20px,
     а перемагав той, що нижче. Плитки одного рангу через це мали 10/12/16/20/22
     на одному екрані. */

  --scrim: .78;      /* виводиться з яскравості фото, не задається вручну */
  --bg-opacity: .30;
  --bg-image: url("/portal.svg");
  --dim: .88;   /* щільність вуалі над фоном; світле фото потребує більшої */
  --glow:     0 0 16px rgba(143, 217, 63, .45);
  --glow-max: 0 0 30px rgba(182, 242, 74, .7);

  /* типографічна шкала — одна на весь застосунок */
  /* Заголовок — головний орієнтир на екрані, тож він має читатись
     з відстані витягнутої руки, а не «поміщатись». */
  --t-display: clamp(44px, 13vw, 68px);
  --t-h1:      clamp(27px, 7.4vw, 36px);
  --t-h2:      20px;
  --t-body:    15px;
  --t-small:   13px;
  --t-label:   11px;

  --font-display: "Trebuchet MS", "Segoe UI", system-ui, sans-serif;
  --font-body:    -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
                  "Segoe UI", Roboto, system-ui, sans-serif;
  --font-data:    "JetBrains Mono", "Cascadia Mono", "Consolas", ui-monospace, monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  background: var(--void);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Портальний вихор — той самий, що на картинці: кілька зелених шарів, що
   повільно обертаються назустріч один одному. */
/* Сам портал — фоновим зображенням, приглушений і трохи розмитий, щоб текст
   лишався читабельним. Поверх нього — темна вуаль із того ж зеленого сімейства. */
body::before {
  content: ""; position: fixed; inset: -12%; z-index: 0; pointer-events: none;
  /* Спершу шукаємо ТВОЄ фото в media/bg/portal.jpg; якщо його там немає —
     браузер тихо падає на згенерований portal.svg. Тож файл можна покласти
     будь-коли, перезбирати нічого не треба. */
  background-image: var(--bg-image), url("/portal.svg");
  background-position: center; background-size: cover; background-repeat: no-repeat;
  opacity: var(--bg-opacity);
  /* Без розмиття: воно з'їдало саме зображення, заради якого фон і ставили.
     Читабельність тримають скло й тінь тексту, а не замилений фон. */
  filter: saturate(1.15) contrast(1.02);
  /* Фон статичний навмисно: рухоме тло перетягує увагу на себе
     і безперервно з'їдає кадри. Рух живе в об'єктах поверх нього. */
}
/* Вуаль розрахована на СВІТЛЕ зображення: кислотно-зелений фон інакше з'їдає
   світлий текст. Щільність керується змінною --dim, яку задає адмін у панелі —
   темному фону вистачає 0.5, світлому потрібно 0.8+. */
body::after {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(ellipse 95% 65% at 50% 38%,
      rgba(4, 12, 7, calc(var(--dim) * .78)) 0%,
      rgba(4, 12, 7, calc(var(--dim) * .96)) 58%,
      rgba(4, 12, 7, var(--dim)) 100%),
    linear-gradient(180deg,
      rgba(4, 12, 7, calc(var(--dim) * .85)) 0%,
      rgba(4, 12, 7, var(--dim)) 100%);
}
@keyframes swirl {
  from { transform: rotate(0deg)   scale(1.05); }
  50%  { transform: rotate(180deg) scale(1.16); }
  to   { transform: rotate(360deg) scale(1.05); }
}
@media (prefers-reduced-motion: reduce) {
  body::before, body::after, .portal-dot { animation: none !important; }
}

.wrap {
  position: relative; z-index: 2;
  max-width: 760px; margin: 0 auto;
  padding: 10px 14px calc(84px + env(safe-area-inset-bottom, 0px));
}

/* ── шапка ───────────────────────────────────────────────────────────────── */
.topbar {
  display: flex; align-items: center; gap: var(--s3);
  padding: 12px 16px; margin-bottom: 16px;
  background: linear-gradient(135deg, rgba(13, 32, 21, .98) 0%, rgba(7, 20, 12, .99) 100%);
  backdrop-filter: blur(8px);
  border: 1px solid var(--line); border-radius: var(--r);
  box-shadow: var(--glow);
}
.portal-dot {
  width: 38px; height: 38px; border-radius: 50%; flex: none;
  background:
    radial-gradient(circle at 42% 38%, var(--acid) 0%, var(--portal) 34%,
                    var(--portal-deep) 68%, var(--portal-dark) 100%);
  box-shadow: var(--glow-max), inset 0 0 12px rgba(0, 0, 0, .55);
  animation: pulse 3.4s ease-in-out infinite;
}
@keyframes pulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.09); } }

.brand {
  font-family: var(--font-display);
  font-size: var(--t-h1); font-weight: 800;
  letter-spacing: -.5px; line-height: 1.1;
}
.brand span { color: var(--acid); text-shadow: 0 0 14px rgba(182, 242, 74, .6); }
.who { margin-left: auto; text-align: right; font-size: var(--t-label); color: var(--ink-3); }
.who b {
  display: block; font-family: var(--font-data); font-size: var(--t-small);
  color: var(--splash); font-variant-numeric: tabular-nums;
}

/* ── заголовки ───────────────────────────────────────────────────────────── */
h1.screen {
  font-family: var(--font-display);
  font-size: var(--t-display); font-weight: 800;
  letter-spacing: -1.4px; line-height: 1.02;
  margin: 6px 0 16px; text-wrap: balance;
  text-shadow: 0 2px 18px rgba(4, 12, 7, .95), 0 0 34px rgba(143, 217, 63, .28);
}
/* Друга половина слова — моноширинним і кислотним. Одне слово, два накреслення:
   так заголовок читається як вивіска, а не як рядок тексту. */
h1.screen em {
  font-style: normal; font-family: var(--font-data); font-weight: 700;
  color: var(--acid); letter-spacing: -.5px;
  text-shadow: 0 0 22px rgba(182, 242, 74, .55);
}
h1.screen small {
  display: block; font-family: var(--font-body); font-size: var(--t-small);
  font-weight: 400; letter-spacing: 0; color: var(--ink-2); margin-top: 6px;
}
.sec {
  font-family: var(--font-data);
  font-size: var(--t-label); letter-spacing: 2.5px; text-transform: uppercase;
  color: var(--portal); font-weight: 700;
  margin: 26px 0 12px; display: flex; align-items: center; gap: var(--s3);
}
.sec::after { content: ""; flex: 1; height: 1px; background: linear-gradient(90deg, var(--line), transparent); }

/* ── картки ──────────────────────────────────────────────────────────────── */
.card {
  background: linear-gradient(165deg, rgba(13, 32, 21, .975) 0%, rgba(7, 20, 12, .985) 100%);
  backdrop-filter: blur(6px);
  border: 1px solid var(--line); border-radius: var(--r);
  overflow: hidden; margin-bottom: 14px;
  transition: border-color .2s, box-shadow .2s, transform .2s;
}
.card:hover { border-color: var(--portal-mid); box-shadow: var(--glow); }
.card .body { padding: 14px 16px; }
.card h3 {
  font-family: var(--font-display); font-size: var(--t-h2); font-weight: 700;
  margin: 0 0 6px; letter-spacing: -.2px;
}
.card p { margin: 0 0 8px; font-size: var(--t-small); color: var(--ink-2); }

/* Велике зображення — головний носій настрою світу */
.banner {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  background:
    linear-gradient(160deg, var(--portal-dark) 0%, var(--panel) 60%, var(--void-2) 100%);
  display: grid; place-items: center; cursor: pointer; overflow: hidden;
}
.banner img { width: 100%; height: 100%; object-fit: cover; display: block; }
.banner .ph { font-size: 46px; opacity: .5; filter: drop-shadow(var(--glow)); }
.banner::after {
  content: "＋ фото"; position: absolute; right: 10px; bottom: 8px;
  font-family: var(--font-data); font-size: var(--t-label); letter-spacing: 1px;
  color: var(--acid); background: rgba(6, 17, 9, .78);
  padding: 3px 9px; border-radius: 999px; border: 1px solid var(--line);
}
.banner.readonly { cursor: default; }
.banner.readonly::after { content: none; }
.banner .veil {
  position: absolute; inset: auto 0 0 0; height: 58%;
  background: linear-gradient(180deg, transparent, rgba(6, 17, 9, .92));
  pointer-events: none;
}
.banner .cap {
  position: absolute; left: 16px; right: 16px; bottom: 12px;
  font-family: var(--font-display); font-size: var(--t-h1); font-weight: 800;
  letter-spacing: -.4px; text-shadow: 0 2px 14px #000;
}
/* портрет NPC / локації — квадратне, але велике */
.portrait { aspect-ratio: 1 / 1; }
.grid2 { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: var(--s3); }

/* ── пігулки стану ───────────────────────────────────────────────────────── */
.stats { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: 10px; }
.pill {
  font-family: var(--font-data); font-size: var(--t-label); font-weight: 700;
  padding: 4px 10px; border-radius: 999px; font-variant-numeric: tabular-nums;
  background: rgba(143, 217, 63, .13); border: 1px solid rgba(143, 217, 63, .35);
  color: var(--acid);
}
.pill.warn { background: rgba(245, 227, 92, .12); border-color: rgba(245, 227, 92, .4); color: var(--splash); }
.pill.dim  { background: rgba(168, 201, 164, .08); border-color: rgba(168, 201, 164, .22); color: var(--ink-3); }
.pill.hot  { background: rgba(255, 79, 139, .13); border-color: rgba(255, 79, 139, .4); color: var(--danger); }
.pill.info { background: rgba(53, 224, 245, .1); border-color: rgba(53, 224, 245, .35); color: var(--info); }

/* ── кнопки ──────────────────────────────────────────────────────────────── */
button, .btn {
  font-family: var(--font-body); font-size: var(--t-small); font-weight: 700;
  cursor: pointer; padding: 11px 16px; border-radius: var(--r-sm);
  border: 1px solid var(--portal-deep); min-height: 42px;
  background: linear-gradient(135deg, var(--portal-deep), var(--portal));
  color: #05230a; transition: box-shadow .2s, transform .12s;
}
button:hover { box-shadow: var(--glow-max); transform: translateY(-1px); }
button:active { transform: translateY(1px); }
button:focus-visible { outline: 2px solid var(--acid); outline-offset: 2px; }
button.ghost { background: transparent; color: var(--acid); border-color: var(--line); }
button.tiny { padding: 6px 12px; min-height: 32px; font-size: var(--t-label); }
button.danger { background: transparent; color: var(--danger); border-color: rgba(255, 79, 139, .45); }
.actions { display: flex; gap: var(--s2); flex-wrap: wrap; margin-top: 12px; }

/* ── форми ───────────────────────────────────────────────────────────────── */
input[type="text"], textarea, select {
  width: 100%; background: var(--void-2); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 11px 13px; font-family: var(--font-body); font-size: var(--t-body);
}
textarea { min-height: 90px; resize: vertical; line-height: 1.5; }
input:focus, textarea:focus, select:focus { outline: none; border-color: var(--portal); box-shadow: var(--glow); }
label.field { display: block; margin-bottom: 12px; }
label.field > span {
  display: block; font-family: var(--font-data); font-size: var(--t-label);
  letter-spacing: 1.4px; text-transform: uppercase; color: var(--ink-3); margin-bottom: 6px;
}

/* ── таблиці ─────────────────────────────────────────────────────────────── */
.tablewrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: var(--t-small); }
th, td { text-align: left; padding: 9px 8px; border-bottom: 1px solid var(--line); }
td { font-variant-numeric: tabular-nums; }
th {
  font-family: var(--font-data); color: var(--portal);
  font-size: var(--t-label); text-transform: uppercase; letter-spacing: 1.4px;
}

/* ── онбординг ───────────────────────────────────────────────────────────── */
.hero {
  position: relative; overflow: hidden; border-radius: var(--r-lg);
  border: 1px solid var(--portal-mid); box-shadow: var(--glow);
  background: linear-gradient(145deg, var(--portal-dark) 0%, var(--panel) 55%, var(--void-2) 100%);
  padding: 22px 18px; margin-bottom: 18px;
}
.hero::before {
  content: ""; position: absolute; right: -70px; top: -80px;
  width: 230px; height: 230px; border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, rgba(182, 242, 74, .4) 0%, rgba(45, 122, 28, .15) 48%, transparent 72%);
  animation: swirl 18s linear infinite;
}
.hero h1 {
  position: relative; font-family: var(--font-display); font-size: var(--t-display);
  font-weight: 800; letter-spacing: -1px; line-height: 1.06; margin: 0 0 8px; text-wrap: balance;
}
.hero p { position: relative; margin: 0 0 14px; font-size: var(--t-body); color: var(--ink-2); }
.hero .actions { position: relative; }

.bar { height: 8px; border-radius: 999px; background: rgba(6, 17, 9, .75); overflow: hidden; margin: 12px 0 6px; }
.bar > i {
  display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--portal-deep), var(--acid));
  box-shadow: var(--glow); transition: width .6s cubic-bezier(.2, .8, .2, 1);
}
.bar-label { font-family: var(--font-data); font-size: var(--t-label); color: var(--ink-3); letter-spacing: .6px; }

.steps { display: flex; flex-direction: column; gap: var(--s2); }
.step {
  display: flex; gap: var(--s3); align-items: flex-start; padding: 13px 14px;
  background: var(--panel); border-radius: var(--r-sm); border-left: 3px solid var(--line);
}
.step.now { border-left-color: var(--acid); background: rgba(143, 217, 63, .09); }
.step.done { opacity: .5; }
.step .mark { font-size: 17px; flex: none; }
.step b { display: block; font-size: var(--t-body); margin-bottom: 3px; }
.step span { font-size: var(--t-small); color: var(--ink-2); }

.tips { display: flex; flex-direction: column; gap: var(--s2); }
.tip {
  font-size: var(--t-small); padding: 11px 14px; border-radius: var(--r-sm);
  background: rgba(53, 224, 245, .06); border-left: 3px solid var(--info);
}

.badge {
  display: inline-block; font-family: var(--font-data); font-weight: 700;
  font-size: 10px; letter-spacing: 1.4px; padding: 2px 8px; border-radius: var(--r-sm);
  background: var(--splash); color: #2a2400; margin-left: 8px; vertical-align: middle;
}

/* ── мапа ────────────────────────────────────────────────────────────────── */
.mapgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(165px, 1fr)); gap: var(--s3); }
.node {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 12px; font-size: var(--t-small);
}
.node.spawn { border-color: var(--splash); box-shadow: 0 0 14px rgba(245, 227, 92, .3); }
.node b { display: block; margin-bottom: 6px; font-size: var(--t-body); font-family: var(--font-display); }
.node .exits { color: var(--ink-3); font-size: var(--t-label); margin-top: 8px; line-height: 1.5; }

/* ── стани ───────────────────────────────────────────────────────────────── */
.empty { text-align: center; padding: 48px 20px; color: var(--ink-2); }
.empty .big { font-size: 52px; display: block; margin-bottom: 14px; filter: drop-shadow(var(--glow)); }
.err {
  background: rgba(255, 79, 139, .1); border: 1px solid var(--danger);
  color: #ffd9e6; padding: 13px 15px; border-radius: var(--r-sm);
  margin-bottom: 14px; font-size: var(--t-small);
}
.ok {
  background: rgba(143, 217, 63, .1); border: 1px solid var(--portal-mid);
  color: var(--ink); padding: 13px 15px; border-radius: var(--r-sm);
  margin-bottom: 14px; font-size: var(--t-small);
}
.loader { text-align: center; padding: 56px; }
.loader .portal-dot { margin: 0 auto; width: 60px; height: 60px; }

/* ── НИЖНЯ НАВІГАЦІЯ ─────────────────────────────────────────────────────
   Фіксована, п'ять цілей, без горизонтального скролу: у Telegram свайп від
   краю закриває застосунок, тож стрічку вкладок, що їздить убік, чіпати не можна. */
.bottomnav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  display: grid; grid-template-columns: repeat(5, 1fr);
  background: rgba(10, 26, 16, .97);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  backdrop-filter: blur(12px);
}
.navitem {
  display: flex; flex-direction: column; align-items: center; gap: var(--s1);
  padding: 9px 4px 8px; cursor: pointer; color: var(--ink-3);
  font-size: 10px; font-weight: 600; border-top: 2px solid transparent;
  transition: color .18s, border-color .18s;
}
.navitem .ic { font-size: 19px; line-height: 1; }
.navitem.active { color: var(--acid); border-top-color: var(--acid); }
.navitem.active .ic { filter: drop-shadow(0 0 8px rgba(182, 242, 74, .8)); }

/* «Ще» — сітка розділів замість стрічки */
.menugrid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); }
.menucard {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
  padding: 18px 14px; text-align: center; cursor: pointer; transition: all .2s;
}
.menucard:hover { border-color: var(--portal); box-shadow: var(--glow); transform: translateY(-2px); }
.menucard .ic { font-size: 30px; display: block; margin-bottom: 8px; }
.menucard b { display: block; font-size: var(--t-body); font-family: var(--font-display); }
.menucard span { font-size: var(--t-label); color: var(--ink-3); }


/* ── ігровий режим: аркуш «Я» ────────────────────────────────────────────── */
.sheet { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: var(--s3); margin-top: 12px; }
.stat {
  background: rgba(6, 17, 9, .6); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 12px 8px; text-align: center;
}
.stat b {
  display: block; font-family: var(--font-data); font-size: 24px;
  color: var(--acid); font-variant-numeric: tabular-nums; line-height: 1.1;
}
.stat span {
  font-family: var(--font-data); font-size: 10px; letter-spacing: 1.6px;
  text-transform: uppercase; color: var(--ink-3);
}

.hpbar { height: 12px; border-radius: 999px; background: rgba(6, 17, 9, .8); overflow: hidden; margin: 10px 0 4px; }
.hpbar > i { display: block; height: 100%; border-radius: 999px; transition: width .5s; }
.hpbar > i.full { background: linear-gradient(90deg, var(--portal-deep), var(--acid)); }
.hpbar > i.mid  { background: linear-gradient(90deg, #b58b1c, var(--splash)); }
.hpbar > i.low  { background: linear-gradient(90deg, #a02348, var(--danger)); }

.scene { display: flex; flex-direction: column; gap: var(--s2); }
.who-row {
  display: flex; align-items: center; gap: var(--s3); padding: 10px 12px;
  background: rgba(6, 17, 9, .5); border-radius: var(--r-sm); border-left: 3px solid var(--line);
}
.who-row.player { border-left-color: var(--info); }
.who-row.npc { border-left-color: var(--portal-mid); }
.who-row .av {
  width: 42px; height: 42px; flex: none; border-radius: var(--r-sm); overflow: hidden;
  background: var(--panel-2); display: grid; place-items: center; font-size: 19px;
}
.who-row .av img { width: 100%; height: 100%; object-fit: cover; }
.who-row b { display: block; font-size: var(--t-body); }
.who-row span { font-size: var(--t-small); color: var(--ink-3); }

.exits-list { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: 10px; }
.exit {
  font-family: var(--font-data); font-size: var(--t-small);
  padding: 8px 13px; border-radius: 999px;
  background: rgba(143, 217, 63, .1); border: 1px solid var(--portal-mid); color: var(--acid);
}
.inv-list { display: flex; flex-direction: column; gap: var(--s2); margin-top: 8px; }
.inv-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 9px 12px; background: rgba(6, 17, 9, .45); border-radius: var(--r-sm); font-size: var(--t-small);
}
.inv-row .q { font-family: var(--font-data); color: var(--splash); font-variant-numeric: tabular-nums; }

/* перемикач режиму */
.modeswitch {
  display: flex; gap: var(--s2); padding: 4px; margin-bottom: 14px;
  background: rgba(6, 17, 9, .6); border: 1px solid var(--line); border-radius: 999px;
}
.modeswitch div {
  flex: 1; text-align: center; padding: 9px; border-radius: 999px; cursor: pointer;
  font-size: var(--t-small); font-weight: 700; color: var(--ink-3); transition: all .18s;
}
.modeswitch div.on { background: linear-gradient(135deg, var(--portal-deep), var(--portal)); color: #05230a; }


/* ── графіки: sparkline на CSS-сітці ─────────────────────────────────────── */
.chart {
  display: flex; align-items: flex-end; gap: var(--s1); height: 110px;
  padding: 12px 0 0; border-bottom: 1px solid var(--line);
}
.chart .col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; gap: var(--s1); }
.chart .col i {
  display: block; border-radius: 3px 3px 0 0; min-height: 2px;
  background: linear-gradient(180deg, var(--acid), var(--portal-deep));
  transition: height .4s;
}
.chart .col i.ai { background: linear-gradient(180deg, var(--info), #1a7f92); }
.chart-x {
  display: flex; gap: var(--s1); margin-top: 6px;
  font-family: var(--font-data); font-size: 9px; color: var(--ink-3);
}
.chart-x span { flex: 1; text-align: center; }
.legend { display: flex; gap: var(--s4); margin-top: 10px; font-size: var(--t-label); color: var(--ink-3); }
.legend b { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; }

/* аватар бота в шапці */
.avatar {
  width: 38px; height: 38px; border-radius: 50%; flex: none; overflow: hidden;
  border: 2px solid var(--portal-mid); box-shadow: var(--glow);
}
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* завантажувач зображень */
.uploader {
  display: grid; grid-template-columns: 88px 1fr; gap: var(--s3); align-items: center;
  padding: 12px; background: rgba(4, 12, 7, .5); border-radius: var(--r-sm); margin-bottom: 10px;
}
.uploader .prev {
  width: 88px; height: 88px; border-radius: var(--r-sm); overflow: hidden;
  background: var(--panel-2); display: grid; place-items: center; font-size: 26px;
  border: 1px solid var(--line);
}
.uploader .prev img { width: 100%; height: 100%; object-fit: cover; }

input[type="range"] { width: 100%; accent-color: var(--portal); }


/* ── скелетони: макет замість спінера ────────────────────────────────────── */
@keyframes shimmer { 0% { background-position: -420px 0; } 100% { background-position: 420px 0; } }
.skel-h, .skel-img, .skel-line {
  background: linear-gradient(90deg,
    rgba(30, 69, 38, .35) 0%, rgba(79, 163, 42, .28) 50%, rgba(30, 69, 38, .35) 100%);
  background-size: 420px 100%;
  animation: shimmer 1.25s linear infinite;
  border-radius: var(--r-sm);
}
.skel-h { height: 40px; width: 62%; margin: 6px 0 18px; border-radius: var(--r-sm); }
.skel-card {
  border: 1px solid var(--line); border-radius: var(--r);
  overflow: hidden; margin-bottom: 14px; background: rgba(7, 20, 12, .8);
}
.skel-img { height: 128px; border-radius: 0; }
.skel-body { padding: 14px 16px; display: flex; flex-direction: column; gap: var(--s2); }
.skel-line { height: 12px; }
.skel-line.w70 { width: 70%; } .skel-line.w40 { width: 40%; } .skel-line.w90 { width: 90%; }

/* Поява екрана і натиск живуть у glass.css — тут їх немає навмисно.
   Два набори анімацій в різних файлах гарантовано розійдуться. */

@media (prefers-reduced-motion: reduce) {
  #view.in > *, .skel-h, .skel-img, .skel-line { animation: none !important; }
}


/* ── Читабельність поверх довільного фото ─────────────────────────────────
   Вуаль між фото і вмістом. Її щільність приходить із заміру яскравості
   (див. applyBackdrop), тому світло-зелене фото не з'їдає текст. */
body::after {
  background: linear-gradient(
    180deg,
    rgba(6, 17, 9, calc(var(--scrim) * .96)) 0%,
    rgba(6, 17, 9, calc(var(--scrim) * .82)) 42%,
    rgba(6, 17, 9, calc(var(--scrim) * .99)) 100%
  ) !important;
}

/* Свічення допомагає на темному фоні і шкодить на світлому. */
:root[data-bg="light"] h1.screen { text-shadow: 0 2px 10px rgba(4, 12, 7, .98); }
:root[data-bg="light"] h1.screen em { text-shadow: none; color: #d8ff7a; }

/* ── Заголовок як вивіска ─────────────────────────────────────────────────
   Великий кегль сам по собі ще не читабельний: без щільного трекінгу і
   підкладки він розсипається на строкатому фоні. */
h1.screen {
  font-size: var(--t-display);
  font-weight: 900;
  letter-spacing: -2px;
  line-height: .96;
  text-transform: uppercase;
}
h1.screen em {
  /* Ключове слово іншою гарнітурою — щоб око чіплялось за суть, а не за
     початок рядка. Це той самий прийом, що й акцент у логотипі. */
  display: inline-block;
  font-size: 1.06em;
  letter-spacing: -1px;
  transform: rotate(-1.2deg);
  padding: 0 .12em;
  background: linear-gradient(180deg, transparent 62%, rgba(143, 217, 63, .22) 62%);
}
h1.screen small {
  /* Підзаголовок — речення, а не вивіска: капс тут лише сповільнює читання. */
  text-transform: none;
  font-weight: 500;
  letter-spacing: .1px;
  font-size: clamp(13px, 3.6vw, 16px);
  letter-spacing: .2px;
  opacity: .92;
  margin-top: 10px;
}
.hero h1 { font-size: var(--t-display); line-height: .95; letter-spacing: -2px; }
.sec { font-size: 12px; letter-spacing: 3px; }


/* ────────────────────────────────────────────────────────────────────────
   Далі — колишній glass.css
   ──────────────────────────────────────────────────────────────────────── */

/* ═══════════════════════════════════════════════════════════════════════════
   СКЛЯНИЙ ШАР — матеріали в дусі Apple HIG (Vibrancy & Materials) для
   Telegram Mini App.

   Головний принцип, від якого залежить усе інше: **скло не фарбується**.
   Заливка нейтральна (rgba(30,30,30,.4)), а колір приходить крізь неї з фону
   завдяки saturate(180%). Якби ми підмішали зелений у саму заливку, світло-
   зелене фото під склом дало б каламуть замість соковитого кольору.

   Швидкість: `backdrop-filter` — найдорожча операція мобільного рендеру, тож
   він живе ЛИШЕ на контейнерах (картки, панелі, хедер, навігація). Вкладені
   всередину рядки й пігулки отримують просту напівпрозору заливку: усередині
   вже розмитої поверхні власне розмиття однаково не видно, а кадри воно їсть.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Матеріали ─────────────────────────────────────────────────────────
     Дві щільності: звичайна для вмісту і густіша для панелей, що
     перекривають прокрутку (крізь хедер не має просвічувати текст). */
  --mat:          rgba(30, 30, 30, .40);
  --mat-thick:    rgba(24, 24, 24, .62);
  --mat-hover:    rgba(48, 48, 48, .48);
  --mat-light:    rgba(255, 255, 255, .15);   /* світлі елементи поверх скла */

  /* Три щільності матеріалу. Плитки заливались БІЛОЮ плівкою поверх фото:
     світле по світлому, тому текст на них і губився. Скло затемнює, а не
     освітлює — тоді білому тексту є на чому триматись. Різниця між рівнями
     означає глибину вкладеності, а не декор. */
  --mat-1: rgba(14, 18, 14, .38);   /* тиха плитка всередині панелі     */
  --mat-2: rgba(14, 18, 14, .52);   /* інтерактивна: кнопка, поле, рядок */
  --mat-3: rgba(32, 40, 32, .68);   /* наведення й фокус                */

  /* ── Відблиск на грані ─────────────────────────────────────────────────
     Верхня грань світліша за решту: так поводиться реальне скло, коли світло
     падає згори, і саме ця дрібниця відрізняє «скло» від «прозорого блоку». */
  --edge:         rgba(255, 255, 255, .20);
  --edge-top:     rgba(255, 255, 255, .30);
  --edge-soft:    rgba(255, 255, 255, .10);

  /* ── Тіні ──────────────────────────────────────────────────────────────
     Мʼякі й багатошарові: широка розмита зовнішня плюс внутрішній волосок,
     що дає товщину. Жорстких тіней немає ніде. */
  --sh:      0 8px 32px 0 rgba(0, 0, 0, .12), 0 0 1px 0 rgba(0, 0, 0, .05) inset;
  --sh-lift: 0 12px 40px 0 rgba(0, 0, 0, .18), 0 0 1px 0 rgba(255, 255, 255, .1) inset;

  --blur: blur(20px) saturate(180%);

  /* ЄДИНА шкала заокруглень. Радіус означає РІВЕНЬ ВКЛАДЕНОСТІ, а не смак:
     що глибше елемент, то менший радіус — інакше вкладена плитка виглядає
     більш «зовнішньою», ніж панель, яка її тримає.

       xl  велика панель, модалка
       lg  картка, панель
       md  плитка всередині картки
       sm  чіп, пігулка, дрібний елемент

     Сирих пікселів у решті файлу бути не повинно: саме вони й дали 10/12/16/
     20/22 на одному екрані. */
  /* ШКАЛА ВІДСТУПІВ. Крок 4px — на ньому вже стояла більшість значень, просто
     ніхто цього не записав: у файлі було 57 різних padding і 12 різних gap,
     включно з парами 10/11/12 і 13/14, які око читає як недбалість, а не як
     задум.

       s1  4px   між значком і підписом
       s2  8px   між елементами в ряду
       s3  12px  внутрішній відступ дрібного блоку
       s4  16px  внутрішній відступ картки
       s5  20px  між секціями
       s6  24px  великі поля панелі */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 20px;
  --s6: 24px;

  --r-xl: 24px;
  --r-lg: 20px;
  --r-md: 16px;
  --r-sm: 12px;
  /* Старе імʼя для --r-lg. Лишається заради місць, які ще ним користуються;
     нові правила пишуть --r-lg. */
  --r:    var(--r-lg);

  --ease: cubic-bezier(.2, .8, .2, 1);

  /* Текст поверх скла: легка тінь тримає його читабельним, коли під склом
     проходить світла ділянка фото. */
  --tsh: 0 1px 2px rgba(0, 0, 0, .35);
}

/* ── Базовий матеріал ───────────────────────────────────────────────────── */
.glass,
.card,
.menucard,
.tablewrap,
.chart,
.uploader,
.empty,
.tip,
.node,
.step,
.hero {
  background: var(--mat);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--edge);
  border-top-color: var(--edge-top);
  border-radius: var(--r-lg);
  box-shadow: var(--sh);
  transition: background .25s var(--ease), border-color .25s var(--ease),
              box-shadow .25s var(--ease), transform .14s var(--ease);
}

.hero { border-radius: var(--r-xl); }
.tip, .step, .node { border-radius: var(--r-md); }

.card:hover,
.menucard:hover {
  background: var(--mat-hover);
  border-color: rgba(255, 255, 255, .28);
  box-shadow: var(--sh-lift);
  transform: none;              /* підйом заважає на дотику */
}

/* ── Панелі, що перекривають вміст ──────────────────────────────────────── */
/* Хедер і нижня навігація стоять НАД прокруткою, тож матеріал тут густіший:
   крізь напівпрозорий хедер текст, що під ним проїжджає, читається як шум. */
.topbar,
.bottomnav,
.modeswitch {
  background: var(--mat-thick);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--edge);
  border-top-color: var(--edge-top);
  box-shadow: var(--sh);
}
.topbar     { border-radius: var(--r-lg); }
.modeswitch { border-radius: 999px; overflow: hidden; }
.bottomnav {
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  border-bottom: 0; border-left: 0; border-right: 0;
}

/* ── Вміст усередині скла: заливка без власного розмиття ────────────────── */
.stat,
.who-row,
.exit,
.inv-row,
.bar,
.hpbar,
.legend {
  background: var(--mat-2);
  border: 1px solid var(--edge-soft);
  border-radius: var(--r-md);
  backdrop-filter: none;
}

/* Згруповані списки як у iOS: одна коробка, рядки розділені волосинкою. */
.exits-list,
.inv-list {
  background: var(--mat-2);
  border: 1px solid var(--edge-soft);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.exits-list .exit,
.inv-list .inv-row {
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--edge-soft);
  border-radius: 0;
}
.exits-list .exit:last-child,
.inv-list .inv-row:last-child { border-bottom: 0; }

.pill {
  background: var(--mat-2);
  border: 1px solid var(--edge);
  text-shadow: var(--tsh);
}
.pill.warn { background: rgba(245, 227, 92, .2);  border-color: rgba(245, 227, 92, .4); }
.pill.hot  { background: rgba(255, 79, 139, .2);  border-color: rgba(255, 79, 139, .4); }
.pill.info { background: rgba(53, 224, 245, .18); border-color: rgba(53, 224, 245, .4); }
.pill.dim  { background: var(--mat-2); border-color: var(--edge-soft); }

/* ── Типографіка поверх скла ────────────────────────────────────────────── */
/* Тінь ледь помітна, але саме вона рятує текст у момент, коли під склом
   проходить світла ділянка фото. */
.card h3, .card p, .menucard b, .menucard span,
.stat b, .stat span, .who-row b, .who-row span,
.node b, .step b, .tip, .brand, .who, .navitem {
  text-shadow: var(--tsh);
}

h1.screen {
  text-shadow: 0 2px 4px rgba(0, 0, 0, .45), 0 8px 30px rgba(0, 0, 0, .3);
}
h1.screen em {
  /* Ключове слово іншим накресленням і з підсвіченою підкладкою — око
     чіпляється за суть, а не за початок рядка. */
  background: linear-gradient(180deg, transparent 60%, rgba(182, 242, 74, .28) 60%);
  text-shadow: 0 2px 4px rgba(0, 0, 0, .5), 0 0 24px rgba(182, 242, 74, .35);
}

/* ── Кнопки ─────────────────────────────────────────────────────────────── */
/* 48px — не «гарна цифра», а нижня межа, на якій палець влучає з першого разу.
   Головна кнопка світиться, щоб її було видно на склі; решта — скляні. */
button, .btn {
  min-height: 48px;
  padding: 13px 20px;
  border-radius: var(--r-md);
  font-weight: 600;
  border: 1px solid rgba(255, 255, 255, .25);
  border-top-color: rgba(255, 255, 255, .4);
  background: linear-gradient(180deg, rgba(168, 232, 74, .95) 0%, rgba(79, 163, 42, .95) 100%);
  color: #06240b;
  text-shadow: none;
  box-shadow: 0 4px 16px rgba(143, 217, 63, .3),
              0 0 1px 0 rgba(255, 255, 255, .35) inset;
  transition: background .25s var(--ease), box-shadow .25s var(--ease),
              transform .12s var(--ease);
}
button:hover {
  background: linear-gradient(180deg, rgba(184, 245, 92, 1) 0%, rgba(92, 184, 50, 1) 100%);
  box-shadow: 0 6px 22px rgba(143, 217, 63, .45),
              0 0 1px 0 rgba(255, 255, 255, .5) inset;
  transform: none;
}

button.ghost, button.tiny {
  background: var(--mat-light);
  backdrop-filter: blur(12px) saturate(180%);
  -webkit-backdrop-filter: blur(12px) saturate(180%);
  border: 1px solid var(--edge);
  border-top-color: var(--edge-top);
  color: #fff;
  text-shadow: var(--tsh);
  box-shadow: var(--sh);
}
button.ghost:hover, button.tiny:hover {
  background: var(--mat-3);
  box-shadow: var(--sh-lift);
}
button.tiny { min-height: 38px; padding: 8px 14px; border-radius: var(--r-sm); }

button.danger {
  background: rgba(255, 79, 139, .22);
  border: 1px solid rgba(255, 79, 139, .45);
  color: #ffe3ee;
  text-shadow: var(--tsh);
  box-shadow: var(--sh);
}
button.danger:hover { background: rgba(255, 79, 139, .34); box-shadow: var(--sh-lift); }

/* Натиск: стиск. Палець закриває кнопку, тож зсув на пікселі під ним не
   видно — а зміна розміру відчувається навіть наосліп. */
button:active, .btn:active,
.card:active, .menucard:active, .navitem:active,
.exit:active, .inv-row:active, .who-row:active, .node:active {
  transform: scale(.96);
  transition-duration: .08s;
}

/* ── Поля вводу ─────────────────────────────────────────────────────────── */
input[type="text"], textarea, select {
  min-height: 48px;
  background: var(--mat-2);
  backdrop-filter: blur(12px) saturate(180%);
  -webkit-backdrop-filter: blur(12px) saturate(180%);
  border: 1px solid var(--edge);
  border-top-color: var(--edge-top);
  border-radius: var(--r-md);
  color: #fff;
}
input::placeholder, textarea::placeholder { color: rgba(255, 255, 255, .45); }
input:focus, textarea:focus, select:focus {
  background: var(--mat-3);
  border-color: rgba(182, 242, 74, .6);
  outline: none;
  box-shadow: 0 0 0 4px rgba(182, 242, 74, .16);
}

/* ── Аватар бота ────────────────────────────────────────────────────────── */
/* Кругла лінза зі скляною оправою: аватар має читатись як елемент інтерфейсу,
   а не як вставлена картинка. */
/* Лише аватар: `.portal-dot` — анімований спінер, і скляна оправа на ньому
   коштувала б кадрів саме тоді, коли їх найменше. */
.avatar {
  border-radius: 50%;
  border: 1px solid var(--edge-top);
  box-shadow: 0 4px 18px rgba(0, 0, 0, .28),
              0 0 0 1px rgba(255, 255, 255, .08) inset;
  overflow: hidden;
  background: var(--mat);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
}
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.who-row .av { border-radius: 50%; border: 1px solid var(--edge); overflow: hidden; }

/* ── Повідомлення ───────────────────────────────────────────────────────── */
.err, .ok {
  background: var(--mat);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--edge);
  border-top-color: var(--edge-top);
  border-radius: var(--r-md);
  box-shadow: var(--sh);
  text-shadow: var(--tsh);
}
.err { border-color: rgba(255, 79, 139, .45); }
.ok  { border-color: rgba(143, 217, 63, .45); }

/* ── Поява екрана ───────────────────────────────────────────────────────── */
/* Каскад знизу: око встигає прочитати структуру екрана, замість того щоб
   отримати все одночасно. */
@keyframes glassUp {
  from { opacity: 0; transform: translateY(22px) scale(.985); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
#view.in > * { animation: glassUp .5s var(--ease) both; }
#view.in > *:nth-child(2)   { animation-delay: .05s; }
#view.in > *:nth-child(3)   { animation-delay: .1s; }
#view.in > *:nth-child(4)   { animation-delay: .15s; }
#view.in > *:nth-child(5)   { animation-delay: .19s; }
#view.in > *:nth-child(n+6) { animation-delay: .23s; }

/* Скелетони — того ж матеріалу, інакше момент завантаження виглядає як інший
   застосунок. */
.skel-card {
  background: var(--mat);
  backdrop-filter: var(--blur);
  -webkit-backdrop-filter: var(--blur);
  border: 1px solid var(--edge);
  border-radius: var(--r-lg);
}
.skel-h, .skel-img, .skel-line {
  background: rgba(255, 255, 255, .1);
  border-radius: var(--r-sm);
}

/* ── Межі можливостей ───────────────────────────────────────────────────── */
/* Старий WebView без backdrop-filter показав би замість скла прозорий блок, у
   якому текст лежить просто на фото. Там матеріал стає непрозорим. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass, .card, .menucard, .topbar, .bottomnav, .hero, .modeswitch,
  .tablewrap, .chart, .uploader, .empty, .tip, .node, .step,
  .err, .ok, .skel-card, button.ghost, button.tiny {
    background: rgba(18, 22, 19, .95);
  }
  input[type="text"], textarea, select { background: rgba(18, 22, 19, .9); }
}

/* Рух — не для всіх. Це вимога доступності, а не налаштування. */
@media (prefers-reduced-motion: reduce) {
  #view.in > *, .skel-h, .skel-img, .skel-line { animation: none !important; }
  button:active, .btn:active, .card:active, .menucard:active,
  .navitem:active, .exit:active, .inv-row:active,
  .who-row:active, .node:active { transform: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   ТИПОГРАФІКА — акцидентна пара

   Дві гарнітури з різних світів, і саме контраст між ними робить заголовок
   заголовком: Unbounded — широкий геометричний гротеск, який читається як
   вивіска; Playfair Display Italic — курсивна антиква з високим контрастом
   штрихів. Поставлені поруч в одному слові, вони дають те саме, що в наборі
   зветься зміною накреслення: око бачить, де головне.

   Текст, який читають (а не впізнають), лишається системним: у Mini App
   рідний шрифт телефона виграє і в швидкості, і у відчутті «свого».
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* Unbounded набагато ширший за звичайний гротеск, тож кегль для нього
     менший — інакше «МУЛЬТИВСЕСВІТ» не влазить в екран телефона. */
  --t-display: clamp(32px, 9vw, 50px);
  --font-display: "Unbounded", "Segoe UI", system-ui, sans-serif;
  --font-accent:  "Playfair Display", Georgia, "Times New Roman", serif;
}

/* ── Назва в шапці ──────────────────────────────────────────────────────── */
/* Половина слова гротеском, половина курсивною антиквою. Це та сама «одна
   назва», але око читає її як знак, а не як рядок тексту. */
.brand {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(15px, 4.4vw, 20px);
  letter-spacing: -.02em;
  line-height: 1;
  text-transform: uppercase;
  text-shadow: var(--tsh);
}
.brand span {
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 900;
  font-size: 1.16em;
  letter-spacing: 0;
  text-transform: none;
  color: var(--magenta);
  text-shadow: 0 0 18px rgba(255, 106, 213, .5), var(--tsh);
}

/* ── Заголовок екрана ───────────────────────────────────────────────────── */
h1.screen {
  font-family: var(--font-display);
  font-size: var(--t-display);
  font-weight: 900;
  letter-spacing: -.035em;
  line-height: .94;
  text-transform: uppercase;
  text-wrap: balance;
}
/* Ключове слово — курсивною антиквою в нижньому регістрі: різниця в накресленні
   ТА в регістрі, тож акцент видно навіть краєм ока. */
h1.screen em {
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 900;
  font-size: 1.2em;
  letter-spacing: -.01em;
  text-transform: none;
  color: var(--violet);
}
h1.screen small {
  font-family: var(--font-body);
  text-transform: none;
  font-weight: 500;
}

/* Рубрики — розрідженим гротеском: вони мають читатись як покажчики, а не
   змагатися із заголовком. */
.sec {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: .18em;
  text-transform: uppercase;
}

/* Назви карток і плиток — тим самим акцидентом, але дрібно. */
.card h3, .menucard b, .node b, .step b {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -.02em;
}

/* Числа лишаються моноширинними: у статистиці колонки мають шикуватись. */
.stat b, .who b, .pill { font-variant-numeric: tabular-nums; }

/* ── Сфера аватара бота ─────────────────────────────────────────────────── */
/* Порожня — світиться порталом; із фото — стає лінзою в скляній оправі.
   Обидва стани однакового розміру, щоб шапка не сіпалась при завантаженні. */
.portal-dot, .avatar {
  width: 44px; height: 44px; flex: none;
  border-radius: 50%;
}
.avatar {
  border: 1.5px solid var(--edge-top);
  box-shadow: 0 4px 18px rgba(0, 0, 0, .35),
              0 0 22px rgba(143, 217, 63, .3),
              0 0 0 1px rgba(255, 255, 255, .1) inset;
  background: var(--mat);
  overflow: hidden;
}

/* ═══════════════════════════════════════════════════════════════════════════
   КАРТКА ПЕРСОНАЖА
   Портрет ліворуч, стан праворуч — так само, як влаштований будь-який
   документ із фото: спершу обличчя, потім дані.
   ═══════════════════════════════════════════════════════════════════════════ */
.idcard {
  display: flex;
  align-items: center;
  gap: var(--s4);
  margin-bottom: 14px;
}
.idcard-meta { flex: 1; min-width: 0; }

/* Порожня рамка — це не «немає фото», а запрошення його поставити, тому вона
   клікабельна і показує це виглядом. */
.portrait-slot {
  position: relative;
  width: 92px; height: 92px; flex: none;
  border-radius: var(--r-lg);
  overflow: hidden;
  cursor: pointer;
  background: var(--mat-1);
  border: 1px solid var(--edge);
  border-top-color: var(--edge-top);
  box-shadow: var(--sh);
  display: flex; align-items: center; justify-content: center;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease), transform .12s var(--ease);
}
.portrait-slot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.portrait-slot .ph { font-size: 40px; opacity: .5; }
.portrait-slot .edit {
  position: absolute; right: 5px; bottom: 5px;
  width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px;
  background: var(--mat-thick);
  backdrop-filter: blur(12px) saturate(180%);
  -webkit-backdrop-filter: blur(12px) saturate(180%);
  border: 1px solid var(--edge-top);
}
.portrait-slot:hover { border-color: rgba(182, 242, 74, .55); box-shadow: var(--sh-lift); }
.portrait-slot:active { transform: scale(.96); }
/* Чужа анкета: дивитись можна, міняти — ні, і це має бути видно. */
.portrait-slot.ro { cursor: default; }
.portrait-slot.ro:hover { border-color: var(--edge); box-shadow: var(--sh); }
.portrait-slot.ro:active { transform: none; }

/* Рядок сусіда веде до анкети, тож у нього є стрілка — без неї
   клікабельність доводиться вгадувати. */
.who-row.player { cursor: pointer; }
.who-row .chev {
  margin-left: auto;
  font-size: 22px; line-height: 1;
  color: var(--ink-3);
  padding-left: 8px;
}
.who-row .av img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ═══════════════════════════════════════════════════════════════════════════
   ГРАФ ЛОКАЦІЙ
   Вузол — локація, ребро — перехід. Кольором і формою закодовано те, що
   справді треба знати: де вхід, куди лише в один бік, що недосяжне.
   ═══════════════════════════════════════════════════════════════════════════ */
.graphwrap {
  position: relative;
  height: 62vh; min-height: 320px; max-height: 560px;
  margin: 12px -6px 4px;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: rgba(0, 0, 0, .18);
  border: 1px solid var(--edge-soft);
  /* Тягнемо граф пальцем, тож вертикальний скрол сторінки тут вимкнено. */
  touch-action: none;
  cursor: grab;
}
.graphwrap:active { cursor: grabbing; }
.graph { width: 100%; height: 100%; display: block; }

.edge {
  stroke: rgba(255, 255, 255, .22);
  stroke-width: 2;
}
/* Односторонній перехід виділено: «увійшов і не вийшов» — це властивість
   локації, а не дрібниця оформлення. */
.edge.oneway {
  stroke: rgba(245, 227, 92, .55);
  stroke-dasharray: 7 5;
}
.arrowhead { fill: rgba(245, 227, 92, .8); }

.gnode { cursor: pointer; }
.gnode circle {
  fill: rgba(30, 30, 30, .72);
  stroke: rgba(255, 255, 255, .3);
  stroke-width: 1.5;
  transition: fill .2s var(--ease), stroke .2s var(--ease), r .2s var(--ease);
}
.gnode:active circle { stroke-width: 3; }
.gnode.spawn circle {
  fill: rgba(79, 163, 42, .8);
  stroke: var(--acid);
  stroke-width: 2.5;
}
.gnode.deadend circle { stroke: rgba(245, 227, 92, .6); stroke-dasharray: 4 3; }
.gnode.orphan  circle { stroke: rgba(255, 79, 139, .75); stroke-dasharray: 3 3; }
.gnode.sel circle { fill: rgba(143, 217, 63, .55); stroke: var(--acid); stroke-width: 3; }

.gnum {
  fill: #fff; font-size: 15px; font-weight: 700;
  text-anchor: middle; pointer-events: none;
  font-family: var(--font-data);
}
.glabel {
  fill: rgba(255, 255, 255, .92);
  font-size: 13px; font-weight: 600;
  text-anchor: middle; pointer-events: none;
  paint-order: stroke;
  stroke: rgba(0, 0, 0, .75); stroke-width: 3px; stroke-linejoin: round;
}

/* Клікабельні виходи в деталях вузла — ними ходять по графу, не гортаючи. */
.exits-list .exit { cursor: pointer; padding: 11px 14px; }

/* ═══════════════════════════════════════════════════════════════════════════
   ДАШБОРД СВІТІВ
   Два стовпчики на світ, бо це два різні питання: скільки грають і скільки
   це коштує. Одна шкала на двох злила б їх в одне безглузде число.
   ═══════════════════════════════════════════════════════════════════════════ */
.wlist { display: flex; flex-direction: column; gap: var(--s3); margin-top: 14px; }

.wrow {
  padding: 12px 14px;
  border-radius: var(--r-lg);
  background: var(--mat-2);
  border: 1px solid var(--edge-soft);
  cursor: pointer;
  transition: background .2s var(--ease), border-color .2s var(--ease), transform .12s var(--ease);
}
.wrow:hover { background: var(--mat-3); border-color: var(--edge); }
.wrow:active { transform: scale(.985); }

.wname b {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: -.02em;
  text-shadow: var(--tsh);
}
.wname span { font-size: 12px; color: var(--ink-3); }

.wbars { display: flex; flex-direction: column; gap: var(--s2); margin-top: 10px; }
.wbar {
  position: relative;
  height: 22px;
  border-radius: var(--r-sm);
  background: rgba(0, 0, 0, .28);
  overflow: hidden;
}
.wbar > i {
  position: absolute; inset: 0 auto 0 0;
  background: linear-gradient(90deg, rgba(79, 163, 42, .85), rgba(143, 217, 63, .85));
  border-radius: var(--r-sm);
}
.wbar.cost > i {
  background: linear-gradient(90deg, rgba(196, 168, 40, .8), rgba(245, 227, 92, .85));
}
/* Дорожчий за середнє — рожевим. Це не «погано», це «подивись сюди». */
.wbar.cost.hot > i {
  background: linear-gradient(90deg, rgba(196, 40, 90, .8), rgba(255, 79, 139, .9));
}
.wbar > span {
  position: relative; z-index: 1;
  display: block; padding: 3px 10px;
  font-size: 11.5px; font-weight: 700;
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .85);
}

/* Мітка живих даних: спалахує, коли екран сам перемалювався. Постійно світити
   не можна — це перетворило б корисний сигнал на шум. */
.livedot {
  width: 7px; height: 7px; flex: none;
  border-radius: 50%;
  background: var(--acid);
  opacity: 0;
  margin-left: 6px;
}
.livedot.on { animation: livePulse 1.9s var(--ease); }
@keyframes livePulse {
  0%   { opacity: 0; transform: scale(.4); box-shadow: 0 0 0 0 rgba(182, 242, 74, .6); }
  18%  { opacity: 1; transform: scale(1); box-shadow: 0 0 0 6px rgba(182, 242, 74, 0); }
  100% { opacity: 0; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) { .livedot.on { animation: none; } }

/* ═══════════════════════════════════════════════════════════════════════════
   ХАОТИЧНА ТИПОГРАФІКА — розлом між всесвітами

   Вісім варіантів літери: три гарнітури з різних світів плюс обведення, зсув
   базової лінії, розтягнення і зміна регістру. Межі підібрані так, щоб
   зламаною була ФОРМА, а не читабельність: нахил до 6°, зсув до .08em,
   масштаб .9–1.16. Далі починається не стиль, а неможливість прочитати.

   Сила ефекту задається кількістю дозволених варіантів (див. CHAOS_TARGETS):
   заголовок отримує всі вісім, підпис під цифрою — лише перші чотири.
   ═══════════════════════════════════════════════════════════════════════════ */
.chaos { display: inline; }
.chaos i { font-style: normal; display: inline-block; }

/* c0 — спокійна: перша літера кожного слова, за неї око чіпляється першим. */
.chaos i.c0 { font-family: var(--font-display); font-weight: 900; }

/* c1 — курсивна антиква, кислотним. Найпомітніший розрив у ряду. */
.chaos i.c1 {
  font-family: var(--font-accent);
  font-style: italic; font-weight: 900;
  transform: rotate(-4deg) translateY(-.03em) scale(1.1);
  /* Кольору тут немає навмисно: за колір відповідають окремі класи, і коли
     форма фарбувала сама, зелений просочувався в акценти. */
}
/* c2 — технічна моноширинна: літера з іншої, інженерної реальності. */
.chaos i.c2 {
  font-family: "JetBrains Mono", var(--font-data);
  font-weight: 800;
  transform: rotate(3deg) translateY(.04em) scale(.92);
  letter-spacing: -.04em;
}
/* c3 — розтягнення: та сама літера, але з всесвіту з іншою силою тяжіння. */
.chaos i.c3 {
  font-family: var(--font-display);
  font-weight: 700;
  transform: scaleY(1.16) scaleX(.94);
}
/* c4 — курсив у нижньому регістрі серед капсу: зміна не лише форми, а й ладу. */
.chaos i.c4 {
  font-family: var(--font-accent);
  font-style: italic; font-weight: 700;
  transform: rotate(5deg) translateY(.05em) scale(1.04);
  text-transform: lowercase;
}
/* c5 — моноширинна жовтим, збільшена. */
.chaos i.c5 {
  font-family: "JetBrains Mono", var(--font-data);
  font-weight: 800;
  transform: rotate(-2.5deg) scale(1.14);
}
/* c6 — порожня літера: лише контур, ніби її речовина лишилась у своєму світі. */
.chaos i.c6 {
  font-family: var(--font-display);
  font-weight: 900;
  color: transparent;
  -webkit-text-stroke: 1px var(--cyan);
  text-stroke: 1px var(--cyan);
  transform: translateY(-.05em) scale(1.02);
}
/* c7 — зсунута базова лінія: літера провалилась крізь рядок. */
.chaos i.c7 {
  font-family: var(--font-accent);
  font-weight: 900;
  transform: translateY(.09em) rotate(-6deg) scale(1.06);
}

/* Дрібний текст обведенням не беремо: на 11–13px контур зʼїдає саму літеру. */
.stat span .chaos i.c6,
.who-row b .chaos i.c6,
button .chaos i.c6 {
  color: inherit;
  -webkit-text-stroke: 0;
}

/* ── Глітч ────────────────────────────────────────────────────────────────
   Розшарування на канали спрацьовує рідко і коротко: постійний глітч читається
   як зламаний екран, а не як ефект. Раз на дванадцять секунд — та частота, на
   якій його помічають, але не втомлюються від нього. */
h1.screen .chaos { animation: rift 12s steps(1) infinite; }
@keyframes rift {
  0%, 92%, 100% { text-shadow: 0 2px 4px rgba(0, 0, 0, .45); }
  93% { text-shadow: -2px 0 rgba(255, 79, 139, .9), 2px 0 rgba(53, 224, 245, .9), 0 2px 4px rgba(0,0,0,.45); }
  94% { text-shadow: 3px 0 rgba(53, 224, 245, .9), -3px 0 rgba(182, 242, 74, .9), 0 2px 4px rgba(0,0,0,.45); }
  95% { text-shadow: -1px 0 rgba(255, 79, 139, .8), 0 2px 4px rgba(0, 0, 0, .45); }
}

/* Рубрики глітчать у свою фазу — щоб розломи не збігалися в один спалах. */
.sec .chaos { animation: rift 19s steps(1) 4s infinite; }

/* Назва в шапці на екрані постійно, тож тут ефект ще стриманіший. */
.brand { animation: riftBrand 17s steps(1) infinite; }
@keyframes riftBrand {
  0%, 96%, 100% { transform: none; text-shadow: var(--tsh); }
  97% { transform: translateX(-1.5px) skewX(-3deg);
        text-shadow: 2px 0 rgba(53, 224, 245, .8), -2px 0 rgba(255, 79, 139, .8); }
  98% { transform: translateX(1.5px) skewX(2deg);
        text-shadow: -2px 0 rgba(182, 242, 74, .8); }
}

/* Рубрики зсунуті з осі: підпис, що трохи «зʼїхав», читається як слід зсуву
   між шарами, а не як помилка верстки. */
.sec { transform: translateX(-2px) rotate(-.4deg); transform-origin: left center; }
.sec:nth-of-type(even) { transform: translateX(3px) rotate(.35deg); }

/* Картки теж ледь збиті з сітки — рівний стос виглядав би як таблиця, а не як
   уламки світів. Кут мікроскопічний: помітно на стосі, непомітно на одній. */
.card:nth-of-type(3n+1)  { transform: rotate(-.22deg); }
.card:nth-of-type(3n+2)  { transform: rotate(.18deg); }
.menucard:nth-child(odd) { transform: rotate(-.4deg); }
.menucard:nth-child(even){ transform: rotate(.35deg); }

@media (prefers-reduced-motion: reduce) {
  h1.screen .chaos, .sec .chaos, .brand { animation: none; }
  .chaos i { transform: none !important; }
  .card, .menucard, .sec { transform: none !important; }
}


/* ── Колір як окремий вимір розлому ───────────────────────────────────────
   Раніше колір ішов у комплекті з гарнітурою, і поєднань було рівно стільки,
   скільки варіантів. Тепер відтінок призначається окремо, тож одна й та сама
   форма може прийти з різного світу. Палітра — портальна: усі відтінки
   тримають контраст ≥ 7:1 на склі, тож це розлом, а не втрата читабельності. */
.chaos i.k1 { color: var(--cyan); }
.chaos i.k2 { color: var(--amber); }
.chaos i.k3 { color: var(--info); }
.chaos i.k4 { color: #ff9ec4; }
.chaos i.k5 { color: #a8e84a; }
.chaos i.k6 { color: #eef7e6; }

/* На головній кнопці тло світло-зелене, тож світлі відтінки там нечитабельні —
   лишаємо власний темний колір кнопки. */
button .chaos i[class*="k"] { color: inherit; }

/* ── Назва застосунку ─────────────────────────────────────────────────────
   «МУЛЬТИ» гротеском, «ВСЕСВІТ» курсивною антиквою — і кожна літера свого
   кольору й нахилу. Це не заголовок, це знак: його впізнають, а не читають,
   тож розлому тут можна більше, ніж будь-де. */
.brand { display: inline-flex; align-items: baseline; gap: .02em; }
.brand .chaos i {
  transition: transform .25s var(--ease), color .25s var(--ease);
}
.brand:hover .chaos i:nth-child(odd)  { transform: translateY(-.08em) rotate(-4deg); }
.brand:hover .chaos i:nth-child(even) { transform: translateY(.08em) rotate(4deg); }

/* ═══════════════════════════════════════════════════════════════════════════
   ЧИТАБЕЛЬНІСТЬ І ПЕРЕНОСИ
   ═══════════════════════════════════════════════════════════════════════════ */

/* Слово не рветься навпіл. Кожна літера — окремий inline-block, тож без цього
   браузер має право перенести рядок між будь-якими двома з них. */
.chaos .w { white-space: nowrap; display: inline-block; }

/* Назва застосунку мусить лишатись в один рядок і просто зменшуватись:
   перенесене навпіл імʼя виглядає як помилка, а не як стиль. */
.brand {
  white-space: nowrap;
  font-size: clamp(13px, 3.6vw, 19px);
  min-width: 0;
}
.topbar { gap: var(--s3); }
.who { flex: none; }

/* Довгі назви світів на обкладинці — теж без розривів усередині слова. */
.banner .cap { overflow-wrap: break-word; hyphens: none; }
.card h3, .menucard b, .wname b { overflow-wrap: anywhere; }

/* ── Контраст приглушеного тексту ─────────────────────────────────────────
   Ці відтінки бралися для темного тла. Під склом, крізь яке просвічує світле
   фото, вони зливаються з поверхнею — саме той текст, що «надто напівпрозорий».
   Піднімаємо світлість і додаємо тінь: тінь тут працює не як прикраса, а як
   межа між літерою і плямою фону, що проходить під склом. */
:root {
  --ink-2: #d3e8cd;
  --ink-3: #a6c2a2;
}
h1.screen small,
.card p,
.bar-label,
.who,
.legend,
.wname span,
.who-row span,
.stat span,
.step span {
  color: var(--ink-2);
  text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}
.pill.dim {
  background: var(--mat-1);
  border-color: rgba(255, 255, 255, .22);
  color: #e4f3e0;
}
.empty { color: var(--ink-2); }

/* Плитки і підписи в нижньому меню — теж світліші: вони дрібні й лежать на
   найщільнішому склі, де контраст падає найпомітніше. */
.navitem { color: #bcd6b8; }
.navitem.active { color: var(--acid); }

/* ═══════════════════════════════════════════════════════════════════════════
   АНОМАЛІЇ — рух на межі між світами

   Правило, від якого залежить, буде це стилем чи дефектом: анімації рідкі,
   короткі й НЕ синхронні. Постійний рух в інтерфейсі, яким користуються, — це
   не атмосфера, а перешкода; збіг усіх ефектів в один момент читається як збій
   рендера. Тому в кожної свій період і своя затримка, і всі періоди прості
   числа секунд — так вони майже ніколи не сходяться.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Скляні літери: прозорі, з відблиском по контуру. Ставляться зрідка — там,
   де слово має читатись як уламок, а не як текст. */
.chaos i.c8 {
  font-family: var(--font-display);
  font-weight: 900;
  color: rgba(255, 255, 255, .14);
  -webkit-text-stroke: .5px rgba(255, 255, 255, .55);
  text-stroke: .5px rgba(255, 255, 255, .55);
  text-shadow: 0 1px 0 rgba(255, 255, 255, .25), 0 -1px 0 rgba(0, 0, 0, .35);
  transform: skewX(-6deg);
}
/* На дрібному кеглі контур зʼїдає саму літеру — там скло вимикається. */
.stat span .chaos i.c8, .navitem .chaos i.c8, .who-row b .chaos i.c8 {
  color: inherit; -webkit-text-stroke: 0; text-shadow: var(--tsh);
}

/* Дрейф однієї літери: ледь помітне гойдання, ніби її тягне крізь розлом. */
@keyframes drift {
  0%, 88%, 100% { transform: translateY(0) rotate(0); }
  92% { transform: translateY(-.09em) rotate(-5deg); }
  96% { transform: translateY(.05em) rotate(3deg); }
}
.chaos i.c1 { animation: drift 23s var(--ease) infinite; }
.chaos i.c5 { animation: drift 31s var(--ease) 7s infinite; }
.chaos i.c7 { animation: drift 29s var(--ease) 13s infinite; }

/* Мерехтіння скляної літери: відблиск проходить по контуру. */
@keyframes glassSheen {
  0%, 90%, 100% { -webkit-text-stroke-color: rgba(255, 255, 255, .55); }
  95% { -webkit-text-stroke-color: rgba(255, 106, 213, .95); }
}
.chaos i.c8 { animation: glassSheen 37s steps(1) 3s infinite; }

/* Портал у порожній обкладинці дихає: картка без фото не має виглядати
   зламаною — вона має виглядати як ще не відкритий світ. */
@keyframes breathe {
  0%, 100% { transform: scale(1) rotate(0); opacity: .55; }
  50% { transform: scale(1.08) rotate(6deg); opacity: .8; }
}
.banner .ph { animation: breathe 11s ease-in-out infinite; display: inline-block; }

/* Скляний відблиск, що раз на хвилину проходить по картці — як світло іншого
   всесвіту крізь шов. Дорога операція, тож лише на картках, не на кожному рядку. */
.card::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(105deg, transparent 40%,
              rgba(255, 255, 255, .09) 48%, rgba(182, 242, 74, .07) 52%, transparent 60%);
  background-size: 260% 100%;
  background-position: 200% 0;
  animation: seam 43s linear infinite;
}
.card { position: relative; }
.card:nth-of-type(2n)::after { animation-delay: 17s; }
.card:nth-of-type(3n)::after { animation-delay: 29s; }
@keyframes seam {
  0%, 82% { background-position: 200% 0; }
  92%     { background-position: -60% 0; }
  100%    { background-position: -60% 0; }
}

/* Пігулки ледь підстрибують по черзі — маленький слід того, що світ живий. */
@keyframes nudge {
  0%, 94%, 100% { transform: translateY(0); }
  97% { transform: translateY(-2px); }
}
.pill { animation: nudge 19s var(--ease) infinite; }
.pill:nth-child(2n) { animation-delay: 5s; }
.pill:nth-child(3n) { animation-delay: 11s; }

@media (prefers-reduced-motion: reduce) {
  .chaos i, .banner .ph, .pill { animation: none !important; }
  .card::after { animation: none; opacity: 0; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   ПАЛІТРА ЗІТКНЕННЯ

   Фон зелений, тож акценти взяті НЕ зеленими: колір, який повторює тло,
   акцентом бути не може. Взято протилежний бік кола — пурпур, фуксія, блакить —
   плюс жовтий і червоний як іскри розлому. Усі відтінки перевірені на склі:
   контраст до 7:1 і вище.
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  --violet:  #b98cff;
  --magenta: #ff6ad5;
  --cyan:    #4fe3ff;
  --amber:   #ffd166;
  --ember:   #ff6b5e;
  --starlit: #fff6c9;
}

/* Кольори літер тепер із протилежного боку кола — на зеленому фоні саме вони
   читаються як розлом, а не як його продовження. */
.chaos i.k1 { color: var(--cyan); }
.chaos i.k2 { color: var(--amber); }
.chaos i.k3 { color: var(--violet); }
.chaos i.k4 { color: var(--magenta); }
.chaos i.k5 { color: var(--ember); }
.chaos i.k6 { color: var(--starlit); }

/* Акцентні елементи теж переїжджають із зеленого. Портальний зелений лишається
   лише там, де він означає «твоє»: активна вкладка й головна дія. */
.pill        { border-color: rgba(185, 140, 255, .45); }
.pill.info   { background: rgba(79, 227, 255, .16);  border-color: rgba(79, 227, 255, .45);  color: #d5f7ff; }
.pill.warn   { background: rgba(255, 209, 102, .16); border-color: rgba(255, 209, 102, .45); color: #fff0c9; }
.pill.hot    { background: rgba(255, 107, 94, .16);  border-color: rgba(255, 107, 94, .45);  color: #ffdcd8; }
.sec         { color: var(--violet); }
.card h3     { color: var(--starlit); }
.stat b      { color: var(--cyan); }
h1.screen em { color: var(--magenta); }

/* ── Зорі ─────────────────────────────────────────────────────────────────
   Розкидані по фону, різного розміру й ритму. Вони не несуть інформації, тож
   лежать під вмістом і не перехоплюють дотиків. */
.star {
  position: fixed;
  z-index: 0;
  pointer-events: none;
  border-radius: 50%;
  background: var(--starlit);
  box-shadow: 0 0 6px currentColor;
  color: var(--starlit);
  animation: twinkle var(--dur, 7s) ease-in-out var(--delay, 0s) infinite;
}
.star.c { background: var(--cyan);    color: var(--cyan); }
.star.m { background: var(--magenta); color: var(--magenta); }
.star.v { background: var(--violet);  color: var(--violet); }
@keyframes twinkle {
  0%, 100% { opacity: .18; transform: scale(.7); }
  50%      { opacity: .85; transform: scale(1.25); }
}

/* Хрестики-спалахи, як на ілюстрації розлому. */
.spark {
  position: fixed; z-index: 0; pointer-events: none;
  width: var(--s, 14px); height: var(--s, 14px);
  background:
    linear-gradient(var(--starlit), var(--starlit)) center/2px 100% no-repeat,
    linear-gradient(var(--starlit), var(--starlit)) center/100% 2px no-repeat;
  opacity: .5;
  animation: sparkPulse var(--dur, 9s) ease-in-out var(--delay, 0s) infinite;
}
@keyframes sparkPulse {
  0%, 100% { opacity: .12; transform: rotate(0) scale(.6); }
  50%      { opacity: .7;  transform: rotate(45deg) scale(1.1); }
}

/* ── Астероїди ────────────────────────────────────────────────────────────
   Пропливають екраном раз на кілька хвилин. Рідко навмисно: об'єкт, який
   постійно повзе перед очима, читається як несправність. */
.rock {
  position: fixed; z-index: 0; pointer-events: none;
  font-size: var(--s, 26px);
  opacity: .32;
  animation: floatBy var(--dur, 90s) linear var(--delay, 0s) infinite;
  filter: drop-shadow(0 0 8px rgba(185, 140, 255, .5));
}
@keyframes floatBy {
  from { transform: translate(-12vw, 0) rotate(0deg); }
  to   { transform: translate(115vw, -18vh) rotate(320deg); }
}

@media (prefers-reduced-motion: reduce) {
  .star, .spark, .rock { animation: none; opacity: .3; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   КНОПКИ — матове скло замість зеленої заливки

   Зелена кнопка на зеленому фоні втрачала межу. Матове скло з підсвіченим
   контуром видно на будь-якому тлі: воно не змагається з фоном кольором,
   а відрізняється від нього матеріалом.
   ═══════════════════════════════════════════════════════════════════════════ */
button, .btn {
  background: var(--mat-2);
  backdrop-filter: blur(18px) saturate(180%);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .3);
  border-top-color: rgba(255, 255, 255, .45);
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .55);
  box-shadow: 0 6px 20px rgba(0, 0, 0, .28),
              0 0 18px rgba(185, 140, 255, .25),
              0 0 1px 0 rgba(255, 255, 255, .5) inset;
  position: relative;
  overflow: hidden;
}
button:hover {
  background: var(--mat-3);
  border-color: rgba(255, 255, 255, .45);
  box-shadow: 0 8px 26px rgba(0, 0, 0, .34),
              0 0 26px rgba(255, 106, 213, .35),
              0 0 1px 0 rgba(255, 255, 255, .6) inset;
}

/* Головна дія відрізняється не кольором заливки, а свіченням по краю: так вона
   лишається склом і водночас читається як «саме сюди». */
button:not(.ghost):not(.tiny):not(.danger)::before {
  content: "";
  position: absolute; inset: -1px;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(120deg,
    rgba(79, 227, 255, .55), rgba(185, 140, 255, .55),
    rgba(255, 106, 213, .55), rgba(255, 209, 102, .55));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  padding: 1px;
  opacity: .85;
  animation: edgeShift 14s linear infinite;
}
@keyframes edgeShift { to { filter: hue-rotate(360deg); } }

/* ── Піксельні мешканці ───────────────────────────────────────────────────
   Кіт, прибулець, НЛО й привид — намальовані box-shadow'ами по одному пікселю.
   Жодних зовнішніх файлів: це чистий CSS, тож вони не додають запитів і
   масштабуються зміною одного числа.

   Сидять на декоративних місцях і не перекривають нічого клікабельного. */
/* Мешканці живуть у власному шарі поверх фону, але під вмістом: вони
   декорація, а не інтерфейс, тож дотиків не перехоплюють. */
@media (prefers-reduced-motion: reduce) {
  button::before { animation: none; }
}

/* Небо лежить під вмістом і не перехоплює дотиків. */
#sky { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }

/* Небо ПОВЕРХ вуалі, але під вмістом. Раніше і воно, і вуаль мали z-index 0,
   а псевдоелемент малюється пізніше за вузол — тож зорі й астероїди були
   намальовані, але сховані під затемненням. */
#sky { z-index: 1; }

/* Зум вимкнено і на рівні стилів: подвійний тап у WebKit масштабує навіть при
   user-scalable=no, якщо не заборонити жест явно. */
html { touch-action: pan-y; -webkit-text-size-adjust: 100%; }

/* Астероїди мають бути ПОМІТНІ: вони й були надто блідими, щоб їх побачити. */
.rock { opacity: .55; font-size: var(--s, 30px); }
.star { box-shadow: 0 0 8px currentColor, 0 0 16px currentColor; }
.spark { opacity: .75; }

/* ═══════════════════════════════════════════════════════════════════════════
   МЕРЕХТІННЯ ЗАГОЛОВКІВ
   Світло проходить по літерах, ніби крізь розлом. Ефект накладається на
   градієнт тексту, тож не з'їдає контраст: під ним лишається та сама заливка.
   ═══════════════════════════════════════════════════════════════════════════ */
h1.screen .chaos i.c0,
h1.screen .chaos i.c3 {
  background-image: linear-gradient(100deg,
    currentColor 0%, currentColor 38%,
    var(--starlit) 48%, var(--cyan) 52%,
    currentColor 62%, currentColor 100%);
  background-size: 300% 100%;
  background-position: 120% 0;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: sweep 9s var(--ease) infinite;
}
@keyframes sweep {
  0%, 70%, 100% { background-position: 120% 0; }
  85%           { background-position: -60% 0; }
}
/* Кожен третій заголовок ловить хвилю у свою фазу — інакше всі спалахують разом. */
h1.screen .chaos i.c0:nth-child(3n) { animation-delay: 3s; }
h1.screen .chaos i.c3:nth-child(2n) { animation-delay: 5s; }

/* Рубрики: тонка лінія світла пробігає підкресленням. */
.sec { position: relative; overflow: visible; }
.sec::before {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -3px; height: 1px;
  background: linear-gradient(90deg, transparent,
              var(--violet), var(--magenta), var(--cyan), transparent);
  background-size: 250% 100%;
  opacity: .75;
  animation: secSweep 13s linear infinite;
}
.sec:nth-of-type(2n)::before { animation-delay: 4s; }
.sec:nth-of-type(3n)::before { animation-delay: 8s; }
@keyframes secSweep {
  0%   { background-position: 200% 0; }
  100% { background-position: -100% 0; }
}

/* Пульс навколо активної вкладки — єдиний постійний рух унизу, і він
   позначає стан, а не прикрашає. */
.navitem.active .ic {
  animation: activePulse 3.4s ease-in-out infinite;
  filter: drop-shadow(0 0 6px var(--acid));
}
@keyframes activePulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.14); }
}

@media (prefers-reduced-motion: reduce) {
  h1.screen .chaos i, .sec::before, .navitem.active .ic { animation: none !important; }
  h1.screen .chaos i.c0, h1.screen .chaos i.c3 { -webkit-text-fill-color: currentColor; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   ВИДИМІСТЬ АНОМАЛІЙ

   Зорі, астероїди й мешканці лежали ПІД картками. Скло з `backdrop-filter`
   розмиває все, що позаду, тож вони були намальовані, але перетворені на
   рівний фон — а сторінка майже цілком укрита картками.

   Тепер вони поверх вмісту й не перехоплюють дотиків. Порядок такий, бо це
   аномалії: вони й мають проходити крізь інтерфейс, а не ховатись за ним.
   ═══════════════════════════════════════════════════════════════════════════ */
/* Над текстом вони приглушені, щоб не заважати читати: помітно, але не
   конкурує з вмістом. */
#sky,
.star  { opacity: .75; }
.spark { opacity: .6; }
.rock  { opacity: .42; }
/* ═══════════════════════════════════════════════════════════════════════════
   ЗАГОЛОВКИ-НАКЛЕЙКИ
   Обведення відділяє літеру від будь-якого фону, а зміщена тінь дає товщину.
   Разом вони роблять із заголовка наклейку, яку видно на чому завгодно.
   ═══════════════════════════════════════════════════════════════════════════ */
h1.screen .chaos i {
  paint-order: stroke fill;
  -webkit-text-stroke: 3px rgba(6, 14, 8, .92);
  text-stroke: 3px rgba(6, 14, 8, .92);
  text-shadow:
    2px 3px 0 rgba(6, 14, 8, .9),
    0 6px 18px rgba(0, 0, 0, .55);
}
/* Скляна літера обведення вже має власне — не подвоюємо. */
h1.screen .chaos i.c8 { -webkit-text-stroke: 1px rgba(255, 255, 255, .7); }

.banner .cap .chaos i,
.brand .chaos i {
  paint-order: stroke fill;
  -webkit-text-stroke: 2px rgba(6, 14, 8, .85);
  text-shadow: 1px 2px 0 rgba(6, 14, 8, .85), 0 4px 12px rgba(0, 0, 0, .5);
}

/* ═══════════════════════════════════════════════════════════════════════════
   МЕНШЕ ЗЕЛЕНОГО, БІЛЬШЕ ГРАДІЄНТІВ

   Зелений лишається кольором ФОНУ і стану «твоє». Літери беруть увесь інший
   спектр: суцільні відтінки плюс градієнтні переливи — так у слові майже не
   трапляється двох однакових літер.
   ═══════════════════════════════════════════════════════════════════════════ */
.chaos i.k1 { color: var(--cyan); }
.chaos i.k2 { color: var(--amber); }
.chaos i.k3 { color: var(--violet); }
.chaos i.k4 { color: var(--magenta); }
.chaos i.k5 { color: var(--ember); }
.chaos i.k6 { color: var(--starlit); }

/* Градієнтні літери. Обрізка по тексту працює лише без обведення, тож у
   заголовках-наклейках вони отримують тінь замість контуру. */
.chaos i.g1, .chaos i.g2, .chaos i.g3 {
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  -webkit-text-stroke: 0;
}
.chaos i.g1 { background-image: linear-gradient(160deg, var(--cyan), var(--violet)); }
.chaos i.g2 { background-image: linear-gradient(160deg, var(--magenta), var(--amber)); }
.chaos i.g3 { background-image: linear-gradient(160deg, var(--starlit), var(--ember)); }
h1.screen .chaos i.g1, h1.screen .chaos i.g2, h1.screen .chaos i.g3 {
  filter: drop-shadow(2px 3px 0 rgba(6, 14, 8, .9)) drop-shadow(0 5px 14px rgba(0, 0, 0, .5));
}

/* ═══════════════════════════════════════════════════════════════════════════
   ІНДИКАТОР АКТИВНОЇ ВКЛАДКИ
   Замість лінії — підсвічена комірка, що повторює форму панелі: заокруглена
   зверху, притиснута донизу. Так видно, ЯКА саме вкладка активна, а не просто
   що десь угорі є риска.
   ═══════════════════════════════════════════════════════════════════════════ */
.navitem { border-top: 0 !important; position: relative; }
/* Смужка-підпис зверху повторює заокруглення комірки. */

/* ═══════════════════════════════════════════════════════════════════════════
   ЧИТАБЕЛЬНІСТЬ ФОРМ І ТАБЛИЦЬ

   У панелі світу текст вилазив за межі полів і зливався зі склом: підписи були
   надто блідими, а довгі назви не мали куди переноситись. Форма, у якій не
   видно, що написано, — це не форма.
   ═══════════════════════════════════════════════════════════════════════════ */
label.field { min-width: 0; }
label.field > span {
  color: #e8f6e4;
  font-weight: 600;
  font-size: 13px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .7);
  opacity: 1;
}
input[type="text"], textarea, select {
  color: #fff;
  font-size: 15px;
  /* Довге значення в select обрізається трьома крапками замість того, щоб
     розсувати колонку і ламати сітку. */
  text-overflow: ellipsis;
  max-width: 100%;
}
select option { background: #101a12; color: #fff; }

/* Дві колонки на телефоні перетворювали поля на щілини. */
@media (max-width: 480px) {
  .grid2 { grid-template-columns: 1fr; }
}

/* Таблиці: довгий текст переноситься, а сама таблиця гортається вбік замість
   того, щоб розпихати сторінку. */
table { width: 100%; border-collapse: collapse; }
th, td {
  color: #eaf7e6;
  font-size: 13.5px;
  padding: 9px 10px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
  overflow-wrap: anywhere;
  vertical-align: middle;
}
th {
  color: #dceed7;
  font-weight: 700;
  font-size: 12px;
  letter-spacing: .06em;
  text-transform: uppercase;
}
tr + tr td { border-top: 1px solid var(--edge-soft); }
.tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Рядки списків: довге ім'я не має накривати число праворуч. */
.inv-row, .exit {
  display: flex; align-items: center; gap: var(--s3);
  color: #eaf7e6;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}
.inv-row > span:first-child, .exit { min-width: 0; overflow-wrap: anywhere; }
.inv-row .q { margin-left: auto; flex: none; white-space: nowrap; }
.inv-row code {
  font-family: var(--font-data);
  font-size: 12px;
  background: var(--mat-1);
  padding: 2px 6px; border-radius: var(--r-sm);
  overflow-wrap: anywhere;
}

/* Абзаци-пояснення в панелях були найблідішими з усього. */
.card p, .tip { color: #dceed7; text-shadow: 0 1px 3px rgba(0, 0, 0, .55); }
.wname span, .legend { color: #cfe4ca; }

/* ── Дрібні заголовки більші ──────────────────────────────────────────────
   Рубрики й назви карток були на межі впізнаваності: 11–15px акцидентом, який
   сам по собі широкий і через це здається дрібнішим за звичайний гротеск. */
.sec { font-size: 14px; letter-spacing: .1em; }
.card h3 { font-size: 18px; }
.menucard b { font-size: 15px; }
.stat b { font-size: 26px; }
.stat span { font-size: 12px; }
.bar-label { font-size: 13px; }
.navitem { font-size: 11px; }
.wname b { font-size: 16px; }

/* ── Аномалії помітніші й такі, що лопаються ──────────────────────────────
   Вони на найвищому шарі й перехоплюють дотик — це єдина декорація, з якою
   можна взаємодіяти, і саме тому їй дозволено трохи заважати. */
#sky, .star, .spark, .rock, .star  { opacity: .95; }
.spark { opacity: .9; }
.rock  { opacity: .8; font-size: var(--s, 42px); }
/* Лопання: спалах і розліт. Після анімації елемент прибирається з DOM. */
@keyframes pop {
  0%   { transform: scale(var(--z, 1)); opacity: 1; filter: brightness(1); }
  40%  { transform: scale(calc(var(--z, 1) * 2.4)); opacity: 1; filter: brightness(2.6); }
  100% { transform: scale(calc(var(--z, 1) * 3.6)); opacity: 0; filter: brightness(3); }
}
.popping { animation: pop .42s ease-out forwards !important; pointer-events: none; }

/* Уламки, що розлітаються від місця лопання. */
.shard {
  position: fixed; z-index: 41; pointer-events: none;
  width: 4px; height: 4px; border-radius: 1px;
  animation: shardFly .55s ease-out forwards;
}
@keyframes shardFly {
  from { transform: translate(0, 0) scale(1); opacity: 1; }
  to   { transform: translate(var(--dx), var(--dy)) scale(.2); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .popping { animation: none !important; opacity: 0 !important; }
  .shard { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   ВИПРАВЛЕННЯ ЗА ЖИВИМ ЕКРАНОМ
   ═══════════════════════════════════════════════════════════════════════════ */

/* 1. Рядки заголовка налазили один на одного. Причина складалась із трьох:
      міжрядковий .94, вертикальне розтягнення літер до 1.16 і зсуви базової
      лінії. Кожне окремо було терпимим, разом — нечитабельним. */
h1.screen {
  line-height: 1.12;
  -webkit-text-stroke: 0;      /* обведення живе на літерах, не на блоці */
}
h1.screen .chaos i {
  -webkit-text-stroke-width: 2px;
  /* Зсуви по вертикалі всередині заголовка приборкані: у великому кеглі
     0.09em — це вже цілий рядок. */
  --shift: .03em;
}
h1.screen .chaos i.c3 { transform: scaleY(1.06) scaleX(.96); }
h1.screen .chaos i.c7 { transform: translateY(.03em) rotate(-4deg) scale(1.02); }
h1.screen .chaos i.c4 { transform: rotate(3deg) translateY(.02em) scale(1.02); }
h1.screen .chaos i.c1 { transform: rotate(-3deg) scale(1.06); }

/* 2. Порожня літера ставала чорною плямою: правило наклейки перебивало її
      світлий контур темним, а заливки в неї немає за задумом. */
/* Контурній літері задаємо лише ТОВЩИНУ: колір контуру лишається за класами
   k*, інакше всі порожні літери в заголовку виходили однаково блакитними. */
h1.screen .chaos i.c6,
.banner .cap .chaos i.c6,
.brand .chaos i.c6 {
  -webkit-text-stroke-width: 2px !important;
  -webkit-text-stroke-color: var(--cyan);
  text-shadow: 0 2px 6px rgba(0, 0, 0, .8);
}
h1.screen .chaos i.c8 { -webkit-text-stroke: 1.5px var(--starlit) !important; }

/* 3. Мінімалістичний індикатор вкладки: тонка риска під іконкою замість
      залитої комірки. Позначати активність має найменша можлива позначка. */
.navitem.active .ic { animation: none; filter: none; }

/* 4. Астероїди більші й непрозорі — на екрані вони мають читатись як обʼєкти,
      а не як бліді плями. */
.rock { opacity: 1; font-size: var(--s, 54px); filter: drop-shadow(0 3px 10px rgba(0, 0, 0, .6)); }
.star { opacity: 1; }
.spark { opacity: .95; }

/* 5. Аномалії ЇДУТЬ разом зі сторінкою, а не висять перед очима.
      Постійно нерухомий обʼєкт поверх тексту заважає читати; той самий обʼєкт,
      що зникає при гортанні, лишається знахідкою. */
/* ═══════════════════════════════════════════════════════════════════════════
   ШВИДКОДІЯ
   Постійних анімацій було понад 160 — кожна змушує композитор працювати
   щокадру. Лишаємо ефект, але на порядок меншій кількості елементів: помітно
   так само, коштує вчетверо менше.
   ═══════════════════════════════════════════════════════════════════════════ */
#sky,
.chaos i.c1, .chaos i.c5, .chaos i.c7 { animation: none; }
h1.screen .chaos i.c1 { animation: drift 23s var(--ease) infinite; }
h1.screen .chaos i.c5 { animation: drift 31s var(--ease) 7s infinite; }

.pill { animation: none; }
.card::after { content: none; }        /* шов світла коштував більше, ніж додавав */
.chaos i.c8 { animation: none; }
.sec::before { animation: none; opacity: .6; }

/* Обіцяємо браузеру, що рухаються лише ці шари — тоді він виносить їх на GPU
   і не перемальовує решту сторінки. */
.star, .spark, .rock { will-change: transform, opacity; }

/* Міжрядковий із запасом на обведення: контур у 2px виступає за межі рядка
   вгору й вниз, тож 1.12 ще давав дотик між рядками у довгих назвах. */
h1.screen { line-height: 1.3; }
h1.screen .chaos i.c3 { transform: scaleY(1.03) scaleX(.97); }

/* Кольоровий клас поверх контурної літери має фарбувати САМЕ контур, а не
   заливку, якої в неї немає. */
.chaos i.c6.k1 { -webkit-text-stroke-color: var(--cyan) !important; }
.chaos i.c6.k2 { -webkit-text-stroke-color: var(--amber) !important; }
.chaos i.c6.k3 { -webkit-text-stroke-color: var(--violet) !important; }
.chaos i.c6.k4 { -webkit-text-stroke-color: var(--magenta) !important; }
.chaos i.c6.k5 { -webkit-text-stroke-color: var(--ember) !important; }
.chaos i.c6.k6 { -webkit-text-stroke-color: var(--starlit) !important; }
.chaos i.c6[class*="k"] { color: transparent !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   ЦІНА КАДРУ

   Кожна поверхня з `backdrop-filter` — окремий прохід GPU. Їх набралось 46,
   і 35 із них — кнопки та поля всередині карток, які вже розмиті. Розмиття
   всередині розмитого не видно взагалі: воно лише коштує кадрів.

   Правило, якого я тримався від початку і сам же порушив, коли робив кнопки:
   розмиття живе ЛИШЕ на контейнерах, що лежать просто на фоні.
   ═══════════════════════════════════════════════════════════════════════════ */
button, .btn,
button.ghost, button.tiny,
input[type="text"], textarea, select {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* ── Кнопка мусить виступати з картки, а не зливатися з нею ───────────────
   Головна дія була залита тим самим темним склом, що й картка під нею
   (.52 проти .62) — різниця в один відтінок, тож кнопка читалась як ділянка
   фону з текстом. Тепер у неї власна поверхня: підсвічений градієнт із
   акцентних кольорів поверх темної основи плюс світла верхня грань.

   Другорядна дія лишається темною й тихою. Різниця між ними тепер видна
   з одного погляду — це і є ієрархія, якої бракувало.                     */
button, .btn {
  background:
    linear-gradient(180deg, rgba(79, 227, 255, .20) 0%, rgba(185, 140, 255, .18) 100%),
    linear-gradient(180deg, rgba(20, 26, 22, .92), rgba(12, 16, 14, .94));
  border: 1px solid rgba(255, 255, 255, .34);
  border-top-color: rgba(255, 255, 255, .52);
  box-shadow:
    0 6px 18px rgba(0, 0, 0, .38),
    0 0 0 1px rgba(0, 0, 0, .25),
    inset 0 1px 0 rgba(255, 255, 255, .22);
}
button:hover {
  background:
    linear-gradient(180deg, rgba(79, 227, 255, .30) 0%, rgba(185, 140, 255, .26) 100%),
    linear-gradient(180deg, rgba(26, 34, 28, .94), rgba(16, 22, 18, .96));
  border-color: rgba(255, 255, 255, .5);
}
/* Другорядна: та сама форма, менше ваги. Прозорою вона не виглядає — під нею
   щільна темна основа, а не просто плівка. */
button.ghost, button.tiny {
  background: linear-gradient(180deg, rgba(28, 36, 30, .88), rgba(16, 21, 18, .92));
  border: 1px solid rgba(255, 255, 255, .24);
  border-top-color: rgba(255, 255, 255, .34);
  box-shadow: 0 4px 12px rgba(0, 0, 0, .34), inset 0 1px 0 rgba(255, 255, 255, .12);
}
button.ghost:hover, button.tiny:hover {
  background: linear-gradient(180deg, rgba(40, 50, 42, .92), rgba(24, 31, 26, .95));
  border-color: rgba(255, 255, 255, .4);
}
button.danger {
  background: linear-gradient(180deg, rgba(60, 20, 34, .92), rgba(34, 14, 22, .94));
  border-color: rgba(255, 107, 148, .55);
  color: #ffd9e4;
}
button.danger:hover {
  background: linear-gradient(180deg, rgba(84, 26, 46, .94), rgba(48, 18, 30, .96));
  border-color: rgba(255, 107, 148, .8);
}
input[type="text"], textarea, select { background: var(--mat-2); }

/* Аватар лежить у шапці, яка вже розмита. */
.avatar { backdrop-filter: none; -webkit-backdrop-filter: none; background: rgba(30, 30, 30, .6); }

/* ═══════════════════════════════════════════════════════════════════════════
   ВИПРАВЛЕННЯ ЗА ДРУГИМ ЕКРАНОМ
   ═══════════════════════════════════════════════════════════════════════════ */

/* 1. Шар аномалій розтягував сторінку. Абсолютний блок висотою 300vh усередині
      body додає ці 300vh до прокрутки — на коротких екранах виходило поле
      порожнечі під вмістом. Повертаємось до fixed, а «відліт» дає зсув при
      гортанні (див. parallaxSky), а не висота блоку. */
/* 2. Зорі прибрані: на строкатому фоні вони читались як бруд, а не як небо. */
#sky,
.star, .spark { display: none; }

/* 3. Обведення на літерах заголовка прибрано — воно давало чорні плями замість
      контуру. Замість нього під заголовком лежить темна підкладка: вона
      відділяє текст від фону цілим блоком, а не обмальовує кожну літеру. */
h1.screen .chaos i,
.banner .cap .chaos i,
.brand .chaos i {
  -webkit-text-stroke: 0 !important;
  text-stroke: 0 !important;
  text-shadow: 0 2px 6px rgba(0, 0, 0, .95), 0 0 22px rgba(0, 0, 0, .8);
}
h1.screen .chaos i.c6 {
  /* Контурній літері контур потрібен за задумом — лишаємо, але тонкий. */
  -webkit-text-stroke: 1.5px currentColor !important;
  color: transparent;
}
h1.screen {
  position: relative;
  isolation: isolate;
  padding: 10px 14px 12px;
  margin-left: -14px; margin-right: -14px;
  -webkit-text-stroke: 0;
}
h1.screen::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, rgba(8, 16, 10, .82), rgba(8, 16, 10, .62));
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  border: 1px solid var(--edge-soft);
}
/* Те саме для назви на обкладинці — там фон найстрокатіший. */
.banner .cap {
  background: linear-gradient(180deg, transparent, rgba(6, 14, 8, .75));
  padding: 18px 14px 10px;
  left: 0; right: 0; bottom: 0;
}

/* 4. Індикатор вкладки: під ПІДПИСОМ, а не під іконкою, і власним кольором —
      блакить видно на зеленому фоні краще за зелений на зеленому. */
.navitem { padding-bottom: 12px; }
.navitem.active { color: var(--cyan); }

/* ═══════════════════════════════════════════════════════════════════════════
   АНОМАЛІЇ ГОРТАЮТЬСЯ РАЗОМ ЗІ СТОРІНКОЮ

   Були `fixed` і зсувались скриптом — через це висіли на місці, поки скрипт
   не спрацював, і взагалі не рухались там, де подія прокрутки не долітала.
   Тепер вони абсолютні ВСЕРЕДИНІ контейнера вмісту: він уже має потрібну
   висоту, тож обʼєкти їдуть самі, без жодного рядка коду.
   ═══════════════════════════════════════════════════════════════════════════ */
#sky { position: absolute; inset: 0; height: 100%; }
.rock { position: absolute; }

/* Астероїд пропливає по своїй смузі, а не через увесь екран: усередині
   контейнера «115vw» вело б його далеко за межі вмісту. */
@keyframes floatBy {
  from { transform: translateX(-8%) rotate(0deg); }
  to   { transform: translateX(108%) rotate(300deg); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   ЧИТАБЕЛЬНІСТЬ ЗАГОЛОВКІВ БЕЗ ОБВЕДЕННЯ

   Обведення кожної літери на строкатому фоні збиралось у чорні згустки й
   псувало саме те, заради чого його ставили. Замість нього — багатошарова
   тінь: вона повторює форму літери, темніє під нею і не торкається самого
   контуру. Плюс підкладка під блоком заголовка.
   ═══════════════════════════════════════════════════════════════════════════ */
h1.screen .chaos i,
.banner .cap .chaos i,
.brand .chaos i,
.card h3 .chaos i,
.sec .chaos i,
.menucard b .chaos i,
.wname b .chaos i {
  -webkit-text-stroke: 0 !important;
  text-stroke: 0 !important;
  text-shadow:
    0 1px 0 rgba(4, 10, 6, .9),
    0 2px 3px rgba(4, 10, 6, .85),
    0 4px 12px rgba(0, 0, 0, .75),
    0 0 26px rgba(0, 0, 0, .55);
}
/* Порожня і скляна літери без контуру зникли б — їм контур і є формою. */
h1.screen .chaos i.c6 { -webkit-text-stroke: 1.5px currentColor !important; color: transparent; }
h1.screen .chaos i.c8 { -webkit-text-stroke: 1px var(--starlit) !important; }

/* ── Підкладки під усі заголовки, а не лише під головний ─────────────────── */
.sec {
  display: inline-flex;
  padding: 5px 12px;
  border-radius: var(--r-sm);
  background: rgba(8, 16, 10, .62);
  border: 1px solid var(--edge-soft);
  backdrop-filter: none;
}
.sec::after { display: none; }
.card h3, .wname b, .menucard b { text-shadow: 0 2px 4px rgba(4, 10, 6, .9); }

/* ── Основний текст: тінь скрізь, де він лягає на скло ──────────────────── */
.card p, .tip, .inv-row, .exit, td, th, .stat span, .stat b,
.bar-label, .who-row b, .who-row span, .legend, .empty, .step b, .step span {
  text-shadow: 0 1px 3px rgba(4, 10, 6, .85), 0 2px 8px rgba(0, 0, 0, .5);
}

/* Картки трохи щільніші: на строкатому фоні матеріал .40 пропускав забагато
   візуального шуму саме туди, де лежить текст. */
:root { --mat: rgba(22, 26, 22, .62); --mat-thick: rgba(16, 20, 16, .8); }

/* ═══════════════════════════════════════════════════════════════════════════
   ВИПРАВЛЕННЯ ЗА ТРЕТІМ ЕКРАНОМ
   ═══════════════════════════════════════════════════════════════════════════ */

/* 1. Літери зникали цілком («АД  І» замість «АДМІН»).
      Причина: у порожньої літери заливка прозора за задумом, а контур я задав
      як `currentColor` — тобто теж прозорий. Літера ставала невидимою. Контур
      мусить мати ВЛАСНИЙ колір, ніколи не похідний від заливки. */
.chaos i.c6,
h1.screen .chaos i.c6,
.banner .cap .chaos i.c6,
.brand .chaos i.c6 {
  color: transparent !important;
  -webkit-text-stroke: 1.6px var(--cyan) !important;
  text-stroke: 1.6px var(--cyan) !important;
}
.chaos i.c6.k1 { -webkit-text-stroke-color: var(--cyan) !important; }
.chaos i.c6.k2 { -webkit-text-stroke-color: var(--amber) !important; }
.chaos i.c6.k3 { -webkit-text-stroke-color: var(--violet) !important; }
.chaos i.c6.k4 { -webkit-text-stroke-color: var(--magenta) !important; }
.chaos i.c6.k5 { -webkit-text-stroke-color: var(--ember) !important; }
.chaos i.c6.k6 { -webkit-text-stroke-color: var(--starlit) !important; }

.chaos i.c8,
h1.screen .chaos i.c8 {
  color: rgba(255, 255, 255, .16) !important;
  -webkit-text-stroke: 1.2px var(--starlit) !important;
  text-stroke: 1.2px var(--starlit) !important;
}

/* 2. Мешканці накривали текст. Вони декорація, тож ідуть ЗА картки: у зазорах
      і на полях їх видно, а прочитати вони не заважають. Читабельність важить
      більше за помітність декору — це не компроміс, а порядок пріоритетів. */
/* 2. Мешканці прибрані з гри; тут лишається лише шар неба.

   ЦЕ МІСЦЕ ВЖЕ ЛАМАЛОСЬ: прибираючи створіння регуляркою, я зʼїв закриваючу
   дужку і лишив обірваний селектор `:not(`. Розбір CSS від цього рядка й до
   кінця файлу помирає мовчки — сторінка просто втрачає половину стилів, і
   виглядає це як «дизайн поламався», а не як синтаксична помилка. */
#sky { z-index: 30; }
.wrap > *:not(#sky) { position: relative; z-index: 1; }

/* 3. Індикатор вкладки лежав ПОВЕРХ підпису: у відступ знизу вже закладено
      безпечну зону, а я додав її вдруге — і риска піднялась на 34px угору,
      просто на текст. */
.navitem { padding-bottom: 14px; }
.bottomnav { padding-bottom: env(safe-area-inset-bottom, 0px); }

/* 4. Підпис під графіком розповзався на три колонки: жирні шматки всередині
      флексу ставали окремими елементами. Це суцільний рядок тексту. */
.legend {
  display: block;
  line-height: 1.5;
  font-size: 12.5px;
  padding: 10px 12px;
  border-radius: var(--r-sm);
}
.legend b { display: inline; font-weight: 700; color: var(--starlit); }

/* 5. Рубрика мала і підкладку, і залишок підкреслення — лишаємо тільки
      підкладку, бо разом вони давали зайву риску під блоком. */
.sec::before { display: none; }

/* ═══════════════════════════════════════════════════════════════════════════
   ЗАГОЛОВОК НЕ ЗАЛЕЖИТЬ ВІД ГРАДІЄНТА

   Мерехтіння працювало через обрізку фону по тексту: заливка літери робилась
   прозорою, а видимість давав градієнт. Достатньо одному пізнішому правилу
   перебити фон — і літера зникає повністю. Саме так і сталося з «АДМІН», де
   зникли дві літери з пʼяти.

   Ефект не вартий того, щоб від нього залежала видимість головного тексту.
   Літери фарбуються звичайним кольором; мерехтіння лишається на підкладці
   заголовка, де його зникнення нікому не шкодить.
   ═══════════════════════════════════════════════════════════════════════════ */
h1.screen .chaos i,
h1.screen .chaos i.c0,
h1.screen .chaos i.c3,
.chaos i.g1, .chaos i.g2, .chaos i.g3 {
  background-image: none !important;
  -webkit-text-fill-color: currentColor !important;
  /* `animation: none` тут БУЛО і глушило танець літер. Мерехтіння через
     градієнт прибрано разом із фоном вище, тож глушити більше нічого. */
}
/* Порожня і скляна літери — виняток: у них заливки немає за задумом. */
.chaos i.c6 { -webkit-text-fill-color: transparent !important; }
.chaos i.c8 { -webkit-text-fill-color: rgba(255, 255, 255, .16) !important; }

/* Мерехтіння переїхало на підкладку: світло проходить під заголовком, а не
   крізь самі літери. */
h1.screen::before {
  background:
    linear-gradient(100deg, transparent 35%, rgba(79, 227, 255, .1) 48%,
                    rgba(185, 140, 255, .12) 55%, transparent 68%),
    linear-gradient(180deg, rgba(8, 16, 10, .84), rgba(8, 16, 10, .66));
  background-size: 260% 100%, 100% 100%;
  background-position: 200% 0, 0 0;
  animation: plateSweep 11s var(--ease) infinite;
}
@keyframes plateSweep {
  0%, 72%, 100% { background-position: 200% 0, 0 0; }
  88%           { background-position: -60% 0, 0 0; }
}
@media (prefers-reduced-motion: reduce) { h1.screen::before { animation: none; } }

/* ═══════════════════════════════════════════════════════════════════════════
   ЛІТЕРИ БЕЗ ЗАЛИВКИ ПРИБРАНІ

   Порожня і скляна літери тримались на самому контурі. Це виявилось джерелом
   одного й того самого дефекту тричі поспіль: досить одному правилу зачепити
   колір контуру — і літера зникає повністю, як зникли «О» і «Л» у «Моралес».

   Варіант, у якому видимість тримається на одній властивості, крихкий за
   будовою. Замінюємо їх на заливні: ефект «іншого світу» дають гарнітура,
   нахил і колір, а не відсутність тіла.
   ═══════════════════════════════════════════════════════════════════════════ */
.chaos i.c6 {
  color: var(--cyan) !important;
  -webkit-text-fill-color: var(--cyan) !important;
  -webkit-text-stroke: 0 !important;
  font-family: var(--font-data);
  font-weight: 800;
  transform: skewX(-8deg) scale(1.04);
}
.chaos i.c8 {
  color: var(--starlit) !important;
  -webkit-text-fill-color: var(--starlit) !important;
  -webkit-text-stroke: 0 !important;
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 900;
  transform: rotate(4deg) scale(1.06);
}
.chaos i.c6[class*="k"], .chaos i.c8[class*="k"] {
  color: inherit;
  -webkit-text-fill-color: currentColor !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   ТІНЬ БЕЗ ЧОРНОГО ДВІЙНИКА

   Різка тінь зі зсувом на піксель малювала темну копію літери. Літери
   нахилені й налазять на сусідні, тож ця копія лягала ПОВЕРХ сусідки — звідси
   «чорні літери поверх нормальних». Лишаємо тільки мʼяке затемнення довкола:
   воно відділяє текст від фону, не малюючи нічого поверх.
   ═══════════════════════════════════════════════════════════════════════════ */
h1.screen .chaos i,
.banner .cap .chaos i,
.brand .chaos i,
.card h3 .chaos i,
.sec .chaos i,
.menucard b .chaos i,
.wname b .chaos i {
  text-shadow: 0 0 8px rgba(4, 10, 6, .95), 0 0 20px rgba(0, 0, 0, .7) !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   ЗАГОЛОВОК ПОМІЩАЄТЬСЯ В СВОЮ ПІДКЛАДКУ
   Літери нахилені й збільшені, тож займають більше, ніж каже кегль. Даємо
   запас з боків і дозволяємо їм виступати за рядок, не обрізаючись.
   ═══════════════════════════════════════════════════════════════════════════ */
:root { --t-display: clamp(26px, 7.4vw, 42px); }
h1.screen {
  padding: 14px 18px 16px;
  overflow: visible;
  letter-spacing: -.02em;
}
h1.screen .chaos { overflow: visible; }
h1.screen .chaos i { padding: 0 .01em; }

/* Заголовки другого й третього порядку були надто дрібними для акциденту. */
.sec { font-size: 16px; padding: 6px 14px; }
.card h3 { font-size: 20px; }
.menucard b { font-size: 16px; }
.wname b { font-size: 17px; }
.banner .cap { font-size: clamp(19px, 5.4vw, 26px); }
.stat span { font-size: 13px; }

/* ═══════════════════════════════════════════════════════════════════════════
   ЛІТЕРИ ТАНЦЮЮТЬ
   Постійний, дуже малий рух: кожна літера гойдається у свою фазу. Амплітуда
   навмисно мікроскопічна — заголовок має жити, а не стрибати.
   ═══════════════════════════════════════════════════════════════════════════ */
@keyframes dance {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  25%      { transform: translateY(-.05em) rotate(-2.5deg); }
  50%      { transform: translateY(.02em) rotate(1.5deg); }
  75%      { transform: translateY(-.03em) rotate(2deg); }
}
h1.screen .chaos i {
  animation: dance 4.5s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * .12s);
}
/* Варіанти зі своїм нахилом танцюють від нього, а не від нуля. */
h1.screen .chaos i.c1, h1.screen .chaos i.c4,
h1.screen .chaos i.c7, h1.screen .chaos i.c8 { animation-name: danceTilt; }
@keyframes danceTilt {
  0%, 100% { transform: rotate(-3deg) translateY(0) scale(1.04); }
  30%      { transform: rotate(1deg) translateY(-.06em) scale(1.07); }
  60%      { transform: rotate(-5deg) translateY(.03em) scale(1.02); }
}

/* Індикатор вкладки під підписом: даємо панелі реальну висоту, інакше риска
   не має де стати і лягає на текст. */
.bottomnav { padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }
.navitem { padding: 9px 4px 6px; }

@media (prefers-reduced-motion: reduce) {
  h1.screen .chaos i { animation: none !important; }
}

/* Танець вмикається останнім правилом, щоб його не перебило нічим раніше. */
h1.screen .chaos i { animation: dance 4.5s ease-in-out infinite !important; }
h1.screen .chaos i.c1, h1.screen .chaos i.c4,
h1.screen .chaos i.c7, h1.screen .chaos i.c8 {
  animation: danceTilt 5.5s ease-in-out infinite !important;
}
@media (prefers-reduced-motion: reduce) {
  h1.screen .chaos i { animation: none !important; }
}

/* Затримку задаємо ОКРЕМИМ правилом: скорочений запис `animation` скидає
   animation-delay у нуль, і всі літери починали гойдатись в такт — виходив
   не танець, а спільний стрибок. */
h1.screen .chaos i { animation-delay: calc(var(--i, 0) * .11s) !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   ЧОРНА ЗАЛИВКА ПОВЕРХ ЛІТЕР — ДОБИВАЄМО ПРИЧИНУ

   Правил, що ставили тінь чи обведення на літери заголовка, накопичилось
   кілька в різних місцях файлу, і пізніші не завжди перебивали ранні. Тут
   ОДНЕ фінальне правило на всі акцентні написи: жодного контуру, жодного
   зсуву — лише мʼяке затемнення довкола.
   ═══════════════════════════════════════════════════════════════════════════ */
.chaos i {
  -webkit-text-stroke: 0 !important;
  text-stroke: 0 !important;
  text-shadow: 0 0 7px rgba(3, 8, 5, .98), 0 0 18px rgba(0, 0, 0, .72) !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   ШАПКА: НАЗВА ГОЛОВНІША ЗА ВСЕ ІНШЕ

   Раніше назва була дрібнішою за заголовок екрана — ієрархія стояла на голові.
   Тепер вона найбільша в шапці, з власним мерехтінням і бліками на склі.
   ═══════════════════════════════════════════════════════════════════════════ */
.topbar {
  position: relative;
  overflow: hidden;
  padding: 14px 16px;
}
/* Блік: смуга світла раз на 9 секунд проходить по всій плашці. */
.topbar::after {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  background: linear-gradient(105deg,
    transparent 38%, rgba(255, 255, 255, .16) 46%,
    rgba(79, 227, 255, .2) 50%, rgba(255, 106, 213, .16) 54%,
    transparent 62%);
  background-size: 240% 100%;
  background-position: 200% 0;
  animation: topSheen 9s var(--ease) infinite;
}
@keyframes topSheen {
  0%, 66%, 100% { background-position: 200% 0; }
  86%           { background-position: -70% 0; }
}

.brand {
  letter-spacing: -.03em;
  z-index: 1;
}
/* «МУЛЬТИ» холодним, «ВСЕСВІТ» теплим — дві частини читаються як два світи,
   що зіткнулись, а не як одне слово з випадковими кольорами. */
.brand > .chaos i:nth-child(odd)  { color: var(--cyan); }
.brand > .chaos i:nth-child(even) { color: var(--violet); }
.brand span .chaos i:nth-child(odd)  { color: var(--amber); }
.brand span .chaos i:nth-child(even) { color: var(--magenta); }
.brand span { font-size: 1.1em; }

/* Баланс у шапці не має сперечатися з назвою за увагу. */
.who b { font-size: 13px; }
.who { font-size: 10px; }

/* ═══════════════════════════════════════════════════════════════════════════
   ПЛАВАЮЧІ ОБʼЄКТИ: ОДНАКОВІ ПРАВИЛА НА ВСІХ СТОРІНКАХ

   Були то над вмістом, то під ним, і лопались не всюди. Причина: шар сіявся
   один раз при завантаженні, а при переході між вкладками вміст перемальовував
   контейнер — шар лишався в старому місці стопки або взагалі губився.
   ═══════════════════════════════════════════════════════════════════════════ */
/* Самі обʼєкти дотик перехоплюють — інакше лопнути їх неможливо. */
#sky > * { pointer-events: auto; cursor: crosshair; }

/* ═══════════════════════════════════════════════════════════════════════════
   ІЄРАРХІЯ: ЛОГОТИП, ЗАГОЛОВОК, РУБРИКА

   Три різні речі, які досі виглядали однаково — той самий розлом літер, той
   самий блиск, схожі кеглі. Через це око не могло сказати, що головніше.

   Розводимо їх по РІЗНИХ ознаках, а не лише по кеглю:
   • логотип — постійний, малий, спокійний, з власним холодним світінням;
   • заголовок екрана — найбільший і єдиний, хто танцює;
   • рубрика — дрібна, розріджена, без жодного руху.
   ═══════════════════════════════════════════════════════════════════════════ */
/* ── Шапка: назва більше нічого не перекриває ──────────────────────────── */
.topbar {
  display: flex;
  align-items: center;
  gap: var(--s3);
  flex-wrap: nowrap;
}
.portal-dot, .avatar { flex: 0 0 auto; }
.brand {
  flex: 1 1 auto;
  min-width: 0;
  /* Назва тепер стискається сама і не наїжджає на баланс: раніше вона мала
     фіксовану ширину й лізла на число зверху. */
  overflow: hidden;
  text-overflow: clip;
}
.who {
  flex: 0 0 auto;
  margin-left: 0;
  text-align: right;
  white-space: nowrap;
}
.livedot { flex: 0 0 auto; }

/* Логотип не танцює і не глітчить — він точка спокою, до якої око
   повертається. Рух у постійному елементі втомлює. */
.brand, .brand .chaos i {
  animation: none !important;
}
.brand .chaos i {
  /* Холодне світіння замість танцю: помітно, але нерухомо. */
  text-shadow: 0 0 6px rgba(3, 8, 5, .95), 0 0 14px rgba(79, 227, 255, .45) !important;
}

/* ── Заголовок екрана — єдиний головний ────────────────────────────────── */
:root { --t-display: clamp(30px, 8.6vw, 46px); }
h1.screen { font-size: var(--t-display); }

/* ── Рубрика: дрібна й тиха ────────────────────────────────────────────── */
.sec {
  font-size: 13px;
  letter-spacing: .16em;
  padding: 5px 11px;
  opacity: .96;
}
.sec .chaos i {
  /* Рубрики не ламаємо кольором: строкатий підзаголовок сперечається із
     заголовком за увагу, а має вести до нього. */
  color: #dceed7 !important;
  -webkit-text-fill-color: #dceed7 !important;
  font-family: var(--font-display) !important;
  transform: none !important;
  animation: none !important;
}

/* Назви карток — між заголовком і рубрикою, теж без руху. */
.card h3 { font-size: 19px; }
.card h3 .chaos i, .menucard b .chaos i, .wname b .chaos i {
  animation: none !important;
}

/* Блиск лишається ЛИШЕ на плашці шапки й під заголовком екрана. Скрізь інде
   він перетворював сторінку на суцільне мерехтіння. */
.card::after, .pill { animation: none !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   ПАНЕЛЬ СВІТУ: З КАТАЛОГУ В РОБОЧИЙ ІНСТРУМЕНТ

   Вона показувала NPC і локації тими самими великими обкладинками, що й
   вітрину світів. Але вітрину РОЗДИВЛЯЮТЬСЯ, а панель — ГОРТАЮТЬ у пошуках
   потрібного: 42 NPC по半-екрана кожен це не каталог, а стрічка.

   Тому тут фото стають мініатюрами, картки — рядками, а між змістовими
   блоками зʼявляється повітря, якого бракувало.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Мініатюра замість обкладинки на весь екран. */
#ownerBody .banner {
  aspect-ratio: auto;
  height: 92px;
  border-radius: var(--r-md) var(--r-md) 0 0;
}
#ownerBody .banner.portrait { height: 92px; }
#ownerBody .banner .ph { font-size: 30px; }
#ownerBody .banner .cap {
  font-size: 14px;
  padding: 10px 10px 7px;
}

/* Сітка щільніша: на екрані має вміщатись більше одиниць, а не більше пікселів
   однієї. */
#ownerBody .grid2 {
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: var(--s3);
}
#ownerBody .grid2 .card { margin-bottom: 0; }
#ownerBody .grid2 .card .body { padding: 10px 11px; }
#ownerBody .grid2 .card h3 { font-size: 14px; margin-bottom: 4px; }
#ownerBody .grid2 .card p {
  font-size: 12px;
  /* Опис NPC скорочуємо до двох рядків: у списку потрібно впізнати, а не
     прочитати цілком. Повний текст — у редагуванні. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── Повітря між блоками ────────────────────────────────────────────────── */
#ownerBody > .sec,
#ownerBody .sec { margin: 26px 0 12px; }
#ownerBody > article.card { margin-bottom: 18px; }
#ownerBody .card .body { padding: 16px; }
#ownerBody .card .body > * + * { margin-top: 12px; }
#ownerBody label.field { display: block; margin-bottom: 12px; }
#ownerBody label.field > span { display: block; margin-bottom: 6px; }
#ownerBody .actions { margin-top: 16px; gap: var(--s3); }
#ownerBody p { line-height: 1.55; margin-bottom: 10px; }
#ownerBody table td, #ownerBody table th { padding: 10px 12px; }

/* Довгі списки прокручуються всередині свого блоку, а не розтягують сторінку
   на кілометр: 42 NPC підряд робили панель непридатною для роботи. */
#ownerBody .grid2.long {
  max-height: 62vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding-right: 4px;
}
#ownerBody .inv-list { max-height: 46vh; overflow-y: auto; }

/* Заголовок розділу показує кількість — щоб було видно масштаб до гортання. */
#ownerBody .sec { justify-content: space-between; }

/* Дрібні кнопки все одно натискають пальцем: 37px — це промах через раз.
   44px — межа, нижче якої влучання стає лотереєю. */
button.tiny { min-height: 44px; padding: 10px 16px; }

/* ═══════════════════════════════════════════════════════════════════════════
   СПИСКИ NPC І ЛОКАЦІЙ: БЕЗ ВКЛАДЕНОЇ ПРОКРУТКИ

   Обмеження висоти з внутрішнім скролом різало картки по межі контейнера —
   кнопка «Змінити» зникала на півслові. Плюс вкладена прокрутка на телефоні
   краде жести: палець не знає, що він гортає.

   Замість цього список показує перші кілька одиниць, а решта розгортається
   кнопкою. Так екран лишається коротким, а нічого не обрізається.
   ═══════════════════════════════════════════════════════════════════════════ */
#ownerBody .grid2.long {
  max-height: none;
  overflow: visible;
  padding-right: 0;
}
#ownerBody .inv-list { max-height: none; overflow: visible; }

/* Приховані одиниці згорнутого списку. */
#ownerBody .grid2.long.collapsed > .card:nth-child(n+7) { display: none; }

/* Картка в списку має СТАЛУ будову: обкладинка, назва, підпис, дія знизу.
   Різна висота карток у сітці — головна причина, чому список виглядає
   зламаним: кнопки опиняються на різних рівнях. */
#ownerBody .grid2 > .card {
  display: flex;
  flex-direction: column;
  min-height: 208px;
}
#ownerBody .grid2 > .card .body {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--s2);
}
/* Дія притискається донизу — тоді всі кнопки в ряд стоять на одній лінії. */
#ownerBody .grid2 > .card .actions {
  margin-top: auto;
  padding-top: 8px;
}
#ownerBody .grid2 > .card p { margin: 0; }

/* Кнопка розгортання — на всю ширину під списком. */
.more-btn {
  width: 100%;
  margin-top: 10px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   АСТЕРОЇДИ: ЧОМУ ВОНИ СТОЯЛИ І ЧОМУ НЕ ЛОПАЛИСЬ

   Дві окремі причини, обидві мої.

   1. Не летіли. Я переписав анімацію на `translateX(108%)`, а відсоток у
      translate рахується від РОЗМІРУ САМОГО ЕЛЕМЕНТА, не контейнера. Для
      емодзі в 50px це 54 пікселі замість екрана — рух був, але непомітний.

   2. Не лопались. Шар лежав під вмістом (z-index 0), а картки скла над ним:
      дотик діставався картки, а не астероїда. І видно їх майже не було з тієї
      самої причини.

   Ставимо шар НАД вмістом. Так, вони інколи перетнуть текст — але це рідкий
   рухомий об'єкт, а не постійна перешкода, і саме цього ефекту й хотіли.
   ═══════════════════════════════════════════════════════════════════════════ */
/* Політ через увесь екран: відлік у vw, а не у відсотках від самої емодзі:
   відсоток там рахується від розміру САМОЇ емодзі, тобто 54 пікселі. */
.rock {
  left: -70px;
  animation-name: flyAcross;
}
@keyframes flyAcross {
  from { transform: translate(0, 0) rotate(0deg); }
  to   { transform: translate(calc(100vw + 140px), -14vh) rotate(300deg); }
}

/* Мешканці лишаються на місці, але тепер їх видно й вони натискаються. */
/* ═══════════════════════════════════════════════════════════════════════════
   СІТКА СТАТИСТИКИ: ТРИ КОЛОНКИ НЕ ЗАВЖДИ ПОМІЩАЮТЬСЯ

   `.sheet` була прибита до трьох колонок. На екрані 375px це працювало, поки
   підписи були короткі («Сила», «Розум»), і зламалось на нових блоках, де вони
   довші: «Ходів лишилось», «Почали грати». Вміст вилазив на 84 пікселі й
   обрізався — саме це й було видно як «контент обривається».

   Колонки тепер підлаштовуються: три, коли влазить, дві або одна, коли ні.
   ═══════════════════════════════════════════════════════════════════════════ */
.sheet {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(92px, 1fr));
  gap: var(--s2);
}
.stat {
  min-width: 0;
  padding: 12px 6px;
  overflow: hidden;
}
.stat b {
  display: block;
  /* Число підлаштовується під ширину комірки: $0.0043 і 334 не мають
     однакової довжини, а місце в них одне. */
  font-size: clamp(17px, 5.6vw, 26px);
  line-height: 1.1;
  overflow-wrap: anywhere;
}
.stat span {
  display: block;
  font-size: 11.5px;
  line-height: 1.25;
  overflow-wrap: anywhere;
  hyphens: auto;
}

/* Поля форм не мають вилазити за картку. */
label.field, label.field > input, label.field > select, label.field > textarea {
  max-width: 100%;
  box-sizing: border-box;
}
input[type="range"] { width: 100%; }

/* Прев'ю зображення в брендингу не має схлопуватись у смужку. */
.uploader .prev { min-height: 64px; overflow: hidden; }

/* Підписи під цифрами переносяться вільно: у комірці 85px довге слово мусить
   ламатись, інакше воно просто вилазить. */
.stat span, .bar-label {
  overflow-wrap: anywhere;
  word-break: break-word;
  white-space: normal;
}
.stat span .w, .bar-label .w { white-space: normal; }

/* Повзунок затемнення разом із підписом не має вилазити за картку. */
label.field { box-sizing: border-box; padding-right: 2px; }

/* ═══════════════════════════════════════════════════════════════════════════
   СМУЖКА ГЕРОЇВ

   Обличчя й імена, нічого більше. Її завдання не розповісти про персонажа, а
   дати до нього дійти одним тапом — подробиці нижче, в аркуші обраного.
   Горизонтальна прокрутка тут доречна: список короткий і однорідний, а місця
   вертикально шкода.
   ═══════════════════════════════════════════════════════════════════════════ */
.roster {
  display: flex;
  gap: var(--s3);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding: 4px 2px 10px;
  margin: 0 -2px 6px;
  scrollbar-width: none;
}
.roster::-webkit-scrollbar { display: none; }

.rost {
  flex: 0 0 auto;
  width: 76px;
  text-align: center;
  cursor: pointer;
  /* Неактивні герої притлумлені, але ЧИТАБЕЛЬНІ. Було .62 — на світлому фоні
     обкладинки світу імена зливались, і смужка виглядала як ряд вимкнених
     кнопок. Активного тепер видно не тим, що решта бліда, а кільцем довкола
     обличчя й повною яскравістю. */
  opacity: .82;
  transition: opacity .2s var(--ease), transform .12s var(--ease);
}
.rost:hover { opacity: .95; }
.rost:active { transform: scale(.95); }
/* Активний персонаж не тьмяний — саме за цим його й знаходять поглядом. */
.rost.on { opacity: 1; cursor: default; }

.rost-face {
  width: 58px; height: 58px;
  margin: 0 auto 6px;
  border-radius: 50%;
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  font-size: 26px;
  background: var(--mat-1);
  border: 1px solid var(--edge-soft);
}
.rost.on .rost-face {
  border: 2px solid var(--cyan);
  box-shadow: 0 0 14px rgba(79, 227, 255, .55);
}
.rost-face img { width: 100%; height: 100%; object-fit: cover; }

.rost b {
  display: block;
  font-size: 12px;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .8);
}
.rost span {
  display: block;
  font-size: 10px;
  color: var(--ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ═══════════════════════════════════════════════════════════════════════════
   СПОКІЙНА ТИПОГРАФІКА ТАМ, ДЕ ЧИТАЮТЬ І НАТИСКАЮТЬ

   Кнопка, рубрика, назва картки — це не місце для розлому. Їх читають на
   ходу, і кожна зайва варіація коштує частки секунди впізнавання. Розлом
   лишається заголовкам; решта набрана однією гарнітурою й одним кольором.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Кнопки: звичайний білий текст, без різнобою. */
button, .btn {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: 0;
  color: #fff;
  text-transform: none;
}
button.tiny { font-size: 13.5px; }

/* Рубрики: білі, більші, розріджені. Фіолетовий на склі втрачав контраст
   саме на дрібному кеглі — там, де його найважче читати. */
.sec {
  color: #f2fbef;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: .1em;
  padding: 7px 14px;
  background: var(--mat-1);
  border: 1px solid var(--edge);
  text-shadow: 0 1px 3px rgba(0, 0, 0, .8);
  transform: none;
}
.sec:nth-of-type(even) { transform: none; }

/* Назви карток і плиток — акцидент, але одним кольором. */
.card h3, .menucard b, .wname b, .node b, .step b {
  color: #f4fbf2;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -.01em;
}

/* Нижнє меню й рядки списків — системним шрифтом: їх читають боковим зором. */
.navitem, .exit, .inv-row, .who-row b, .who-row span {
  font-family: var(--font-body);
  letter-spacing: 0;
}

/* Числа статистики — моноширинні й білі: вони для порівняння, а не для краси. */
.stat b { color: #fff; font-family: var(--font-data); }
.stat span { color: #cfe4ca; letter-spacing: .04em; }

/* ── Рубрики: остаточно ───────────────────────────────────────────────────
   Правил для `.sec` за час роботи накопичилось шість у різних місцях файлу, і
   вони перебивали одне одного непередбачувано. Це останнє і навмисно
   безумовне: фіолетовий на дрібному кеглі втрачав контраст саме там, де його
   найважче читати.

   Шість правил на один селектор — сама по собі ознака, що файл час
   упорядкувати; поки що фіксуємо результат. */
#view .sec,
#ownerBody .sec,
.sec {
  color: #f4fbf2 !important;
  font-size: 15px !important;
  font-weight: 700 !important;
  letter-spacing: .09em !important;
  background: var(--mat-1) !important;
  border: 1px solid rgba(255, 255, 255, .2) !important;
  padding: 7px 14px !important;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .85) !important;
  transform: none !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   ІНДИКАТОР ВІДКРИТОЇ ВКЛАДКИ — одне правило

   Їх було пʼять у різних місцях файлу: залита комірка, риска зверху, дві з
   подвійним урахуванням безпечної зони і остання з відʼємним відступом. Кожна
   писалась як виправлення попередньої, але жодна не прибирала її, тож вигравала
   просто найнижча — і смужка опинилась НИЖЧЕ вкладки, у порожньому відступі
   панелі, відірвана від підпису.

   Тут вона одна. Прив'язка до низу САМОЇ вкладки, а не до панелі: безпечна
   зона вже врахована відступом .bottomnav, і додавати її вдруге означає
   виштовхнути смужку за межі того, що вона позначає.
   ═══════════════════════════════════════════════════════════════════════════ */
.navitem.active::after {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 1px;
  width: 24px;
  height: 3px;
  border-radius: 3px;
  background: var(--cyan);
  box-shadow: 0 0 10px rgba(79, 227, 255, .9);
}
/* ═══════════════════════════════════════════════════════════════════════════
   НАЗВА ЗʼЯВЛЯЄТЬСЯ ВЖЕ ЗЛАМАНОЮ

   Назва — єдиний хаотичний напис у статичному HTML: решту екрана малює скрипт,
   і до того часу гарнітури вже на місці. Тому показуємо її аж тоді, коли по
   ній пройшовся applyChaos — інакше видно проміжний стан, у якому вона ще
   звичайна.

   Розкриття продубльоване анімацією із затримкою: якщо скрипт з якоїсь причини
   не виконався, назва все одно зʼявиться за 1.2 с. Ховати текст назавжди
   заради усунення мерехтіння — гірше за саме мерехтіння.
   ═══════════════════════════════════════════════════════════════════════════ */
.brand { animation: brandReveal .18s ease 1.2s both; }
.brand[data-chaos] { animation: none; opacity: 1; }
@keyframes brandReveal { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .brand { animation-duration: .01s; }
}
/* ═══════════════════════════════════════════════════════════════════════════
   ІКОНКИ

   Контурний набір лежить у самому документі (див. index.html). Розмір задаємо
   тут, а колір успадковується від тексту — тож іконка завжди в тон підпису
   поруч, і не треба тримати окремі варіанти під кожен стан.
   ═══════════════════════════════════════════════════════════════════════════ */
.ic {
  width: 22px; height: 22px;
  flex: none;
  display: inline-block;
  vertical-align: -.28em;
  /* Тонкий контур на строкатому фоні губиться, тож під ним лежить та сама
     мʼяка тінь, що й під текстом поруч. */
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .75));
}
.ic.big { width: 30px; height: 30px; }
.navitem .ic { width: 23px; height: 23px; vertical-align: 0; }
.navitem.active .ic { filter: drop-shadow(0 0 7px rgba(79, 227, 255, .85)); }
.menucard .ic { display: block; margin: 0 auto 10px; }
.modeswitch .ic { width: 18px; height: 18px; vertical-align: -.24em; margin-right: 4px; }
.banner .ph .ic, .portrait-slot .ph .ic { width: 38px; height: 38px; opacity: .75; }
.portrait-slot .edit .ic { width: 15px; height: 15px; }

/* ═══════════════════════════════════════════════════════════════════════════
   НАЗВА В ШАПЦІ — ГОЛОВНИЙ ЗНАК, А НЕ ПІДПИС

   Заголовок екрана виглядав цікавіше за саму назву застосунку: у нього 46px і
   темна підкладка, у назви — 19px і нічого. Вийшло, що назва програє власному
   вмісту. Даємо їй ту саму підкладку й більший кегль: вона має бути першим,
   що впізнають, а не дрібним написом над контентом.
   ═══════════════════════════════════════════════════════════════════════════ */
.brand {
  font-size: clamp(19px, 6vw, 28px) !important;
  letter-spacing: -.035em;
  padding: 4px 2px;
}
.brand .chaos i {
  /* Літери назви більші за сусідні елементи шапки, тож і розкид між ними
     помітніший — саме за це око чіпляється як за знак. */
  font-size: 1.02em;
}
.topbar {
  /* Місця під більшу назву: баланс і аватар тиснуться, назва отримує решту. */
  gap: var(--s2);
  padding: 12px 14px;
}
.who b { font-size: 12px; }
.who { font-size: 9.5px; opacity: .8; }
/* ═══════════════════════════════════════════════════════════════════════════
   ЗАГОЛОВОК НЕ ВИЛАЗИТЬ ЗА КРАЙ

   Підкладка була розтягнута негативними полями до самого краю екрана, а літери
   в ній нахилені й трохи збільшені — тобто малюються ЗА межами свого рядка.
   Разом це давало обрізану останню літеру: місця для виступу просто не
   лишалось. Тепер плашка стоїть у колонці вмісту, як і решта панелей, і запас
   на виступ бере з її ж відступів.
   ═══════════════════════════════════════════════════════════════════════════ */
h1.screen {
  margin-left: 0;
  margin-right: 0;
  border-radius: var(--r-lg);
}
/* ═══════════════════════════════════════════════════════════════════════════
   ДІАГРАМИ АДМІНКИ

   Кільце — не прикраса: воно показує ЧАСТКУ, а частку око читає з кута краще,
   ніж із числа в таблиці. Тому в центрі стоїть сума, а поруч у легенді —
   обидва відсотки одразу (ходів і витрат): уся суть саме в їхній розбіжності.
   ═══════════════════════════════════════════════════════════════════════════ */
.donut-wrap { display: flex; gap: var(--s4); align-items: center; flex-wrap: wrap; }
.donut {
  width: 132px; height: 132px; flex: none;
  border-radius: 50%;
  position: relative;
  box-shadow: 0 6px 22px rgba(0, 0, 0, .45);
}
.donut-hole {
  position: absolute; inset: 26px;
  border-radius: 50%;
  background: rgba(10, 14, 11, .94);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
}
.donut-hole b {
  font-family: var(--font-data); font-size: 19px; color: #fff; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.donut-hole span { font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }

.legend-list { flex: 1; min-width: 168px; display: flex; flex-direction: column; gap: var(--s2); }
.lg-row {
  display: grid;
  grid-template-columns: 12px 1fr auto;
  grid-template-areas: "dot name cost" ". turns cost";
  gap: 2px 8px;
  align-items: center;
  font-size: 12.5px;
}
.lg-row b { grid-area: dot; width: 11px; height: 11px; border-radius: 3px; }
.lg-row span { grid-area: name; color: #eaf7e6; font-weight: 600; overflow-wrap: anywhere; }
.lg-row i { grid-area: turns; font-style: normal; font-size: 11px; color: var(--ink-3); }
.lg-row u {
  grid-area: cost; text-decoration: none;
  font-family: var(--font-data); font-variant-numeric: tabular-nums;
  font-size: 13px; font-weight: 700; color: var(--amber);
}

/* Доба: 24 стовпчики, пік підсвічений. Решта тиха — інакше графік читається як
   гірлянда, а не як розподіл. */
.chart.hours { gap: var(--s1); height: 96px; }
.chart.hours .col i { background: linear-gradient(180deg, rgba(79, 227, 255, .75), rgba(79, 227, 255, .2)); }
.chart.hours .col i.peak { background: linear-gradient(180deg, var(--amber), rgba(255, 209, 102, .3)); }

/* Воронка: довжина смуги — частка від першого кроку, тож видно саме падіння. */
.funnel { display: flex; flex-direction: column; gap: var(--s2); }
.fn-row { display: flex; align-items: center; gap: var(--s3); }
.fn-bar {
  height: 34px;
  border-radius: var(--r-sm);
  background: linear-gradient(90deg, rgba(79, 227, 255, .38), rgba(185, 140, 255, .3));
  border: 1px solid rgba(255, 255, 255, .18);
  display: flex; align-items: center;
  padding: 0 10px;
  min-width: 0;
}
.fn-bar span {
  font-size: 12.5px; font-weight: 600; color: #fff; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .85);
}
.fn-num {
  flex: none; text-align: right;
  font-family: var(--font-data); font-variant-numeric: tabular-nums;
  font-size: 15px; font-weight: 700; color: #fff; line-height: 1.05;
}
.fn-num i { display: block; font-style: normal; font-size: 10.5px; color: var(--ink-3); }
.fn-drop {
  flex: none;
  font-family: var(--font-data); font-size: 12px; font-weight: 700;
  color: #ff9ab4;
}

/* ═══════════════════════════════════════════════════════════════════════════
   НАЗВА — ЛОГОТИП У ДВА РЯДКИ

   Учора я збільшив її до 28px, не перевіривши, що в шапці стільки місця немає:
   поруч стоять аватар і баланс. Рядок не переносився, тож `overflow: hidden`
   просто зрізав хвіст — на екрані лишалось «МУЛЬТИВСЕ».

   Замість гри з кеглем робимо те, що робить будь-який знак у такій ситуації:
   ставимо дві частини одна під одною. «МУЛЬТИ» і «ВСЕСВІТ» — і так дві різні
   гарнітури, тож розділення читається як задум, а не як перенос. Кожна частина
   вдвічі коротша, отже вміщається із запасом і може бути більшою.
   ═══════════════════════════════════════════════════════════════════════════ */
.brand {
  display: flex;
  align-items: baseline;
  justify-content: flex-start;
  /* Назву не переносимо й не розриваємо НІКОЛИ: розділене навпіл імʼя читається
     як помилка верстки, а не як знак. Замість цього кегль підганяється під
     наявне місце (див. fitBrand у app.js) — тоді вона завжди ціла і завжди
     настільки велика, наскільки дозволяє шапка. */
  white-space: nowrap;
  /* Ховаємо переповнення як страхувальну сітку: якщо підбір кегля з якоїсь
     причини не спрацював, назва радше обріжеться, ніж наїде на баланс. У
     нормі до цього не доходить. */
  overflow: hidden;
  line-height: 1.05;
  font-size: 22px;
  gap: 0;
  transform-origin: left center;
}
.brand > span { display: inline; }
/* Друга частина трохи більша й зі зсувом — так пара читається як лігатура
   логотипа, а не як два незалежні слова. */
.brand span .chaos { margin-left: .06em; }

.topbar { align-items: center; padding: 10px 14px; }

/* ═══════════════════════════════════════════════════════════════════════════
   РУБРИКИ: ПЛАШКА МУСИТЬ ТРИМАТИ ТЕКСТ

   Матеріал .38 задумувався для плиток ВСЕРЕДИНІ карток, де під ним уже лежить
   темне скло. Рубрика ж стоїть просто на фотографії, і там та сама щільність
   пропускає весь малюнок — світлі ділянки фону проходять крізь неї й
   зʼїдають літери.

   Тому в рубрики власна, найщільніша підкладка. Це не виняток із системи
   матеріалів, а її третій випадок: «поверх фону, без картки під собою».
   ═══════════════════════════════════════════════════════════════════════════ */
#view .sec,
#ownerBody .sec,
.sec {
  background: rgba(9, 13, 10, .82) !important;
  border: 1px solid rgba(255, 255, 255, .22) !important;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .4);
  backdrop-filter: blur(10px) saturate(150%);
  -webkit-backdrop-filter: blur(10px) saturate(150%);
}

/* ═══════════════════════════════════════════════════════════════════════════
   ЛЕГЕНДА ГРАФІКА: КОЛЬОРОВІ ПОЗНАЧКИ ПОВЕРНУЛИСЬ

   Селектор `.legend b` означав дві різні речі одночасно: квадратик кольору під
   графіком динаміки і просто жирне слово в підписі під дашбордом світів.
   Пізніше правило зробило його `display: inline` — і квадратики зникли, бо
   ширина й висота на рядковому елементі не діють. Підпис лишився цілим,
   а легенда перетворилась на «AI-ходи безкоштовні» без жодної позначки.

   Розводимо за ознакою, яка вже є в розмітці: у квадратика власний колір
   у style, у жирного слова — ні.
   ═══════════════════════════════════════════════════════════════════════════ */
.legend b[style] {
  display: inline-block;
  width: 11px; height: 11px;
  border-radius: 3px;
  margin-right: 6px;
  vertical-align: -1px;
  border: 1px solid rgba(255, 255, 255, .25);
}
/* Пункти легенди йдуть у рядок і не злипаються. */
.legend span { display: inline-block; margin-right: 16px; white-space: nowrap; }

/* ═══════════════════════════════════════════════════════════════════════════
   СМУЖКА ГЕРОЇВ: ІКОНКА ЗАМІСТЬ ЕМОДЗІ
   ═══════════════════════════════════════════════════════════════════════════ */
.rost-face .ic { width: 26px; height: 26px; opacity: .55; }
.rost.on .rost-face .ic { opacity: .9; }

/* Підпис під обличчям не має обриватись на півслові там, де є місце. */
.rost { width: 82px; }
.rost b { font-size: 11.5px; }

/* Іконка в пігулці й у порожньому стані. Пігулка дрібна, тож іконка в ній
   помітно менша за навігаційну — інакше вона перебиває саме число.       */
.pill .ic { width: 14px; height: 14px; vertical-align: -.2em; margin-right: 2px; }
.empty .big .ic { width: 52px; height: 52px; opacity: .6; }
.card p .ic { width: 16px; height: 16px; vertical-align: -.24em; margin-right: 4px; }
.tip .ic { width: 16px; height: 16px; vertical-align: -.24em; margin-right: 4px; }
.card h3 .ic { width: 19px; height: 19px; vertical-align: -.2em; margin-right: 5px; }
.bar-label .ic { width: 15px; height: 15px; vertical-align: -.22em; margin-right: 3px; }

/* Правила білінгу приходять готовою розміткою з того самого сервісу, що й
   у чаті. Тут лише даємо їй дихати: суцільна стіна тексту в картці
   нечитабельна, а це саме той текст, який мусять дочитати.            */
.policy { line-height: 1.6; font-size: 14px; }
.policy b { color: #f4fbf2; }
.policy code { font-family: var(--font-data); font-size: 12.5px; background: var(--mat-1);
  padding: 2px 6px; border-radius: var(--r-sm); }

/* Підписи осі не переносяться: «08-03» у два рядки читається як два числа. */
.chart-x span { white-space: nowrap; font-size: 9.5px; letter-spacing: -.02em; }

/* ── Світ-передпокій ──────────────────────────────────────────────────────
   Виглядає інакше НАВМИСНО: приглушений, без акценту, з поясненням замість
   лічильників. Якби він виглядав як звичайна картка, різницю довелося б
   вгадувати з того, чого на ній НЕМАЄ, — а відсутність помічають найгірше. */
.card.hub { opacity: .92; border-style: dashed; }
.card.hub .banner { filter: grayscale(.55) brightness(.85); }
.hub-note {
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-2);
  border-left: 2px solid rgba(255, 255, 255, .22);
  padding-left: 10px;
  margin: 10px 0;
}

/* На найвужчих екранах (SE, складані) місця не вистачає обом. Прибираємо
   баланс, а не назву: баланс видно ще у двох місцях — на вкладці «Ходи» і в
   блоці «Ходи й тариф», — а назва в застосунку одна. */
@media (max-width: 359px) {
  .who { display: none; }
}
/* ═══════════════════════════════════════════════════════════════════════════
   ВІКНО ВВЕДЕННЯ

   Замінює браузерний prompt(). Стоїть по центру, затемнює все під собою і
   тримає фокус: поки воно відкрите, іншої дії в застосунку немає — саме тому
   в нього можна класти незворотні дії, які раніше йшли через системне вікно.
   ═══════════════════════════════════════════════════════════════════════════ */
.modal-wrap {
  position: fixed; inset: 0; z-index: 90;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  background: rgba(4, 8, 5, .72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: modalIn .16s var(--ease) both;
}
@keyframes modalIn { from { opacity: 0; } to { opacity: 1; } }
.modal {
  width: 100%; max-width: 420px;
  background: linear-gradient(180deg, rgba(24, 30, 25, .98), rgba(14, 19, 15, .99));
  border: 1px solid rgba(255, 255, 255, .22);
  border-top-color: rgba(255, 255, 255, .34);
  border-radius: var(--r-lg);
  box-shadow: 0 20px 60px rgba(0, 0, 0, .6);
  padding: 18px;
  animation: modalUp .2s var(--ease) both;
}
@keyframes modalUp { from { transform: translateY(14px) scale(.98); } to { transform: none; } }
.modal h3 {
  margin: 0 0 8px;
  font-family: var(--font-display); font-weight: 700; font-size: 18px;
  color: #f4fbf2;
}
.modal-hint { font-size: 13px; line-height: 1.55; color: var(--ink-2); margin: 0 0 12px; }
.modal input, .modal textarea { width: 100%; }
.modal textarea { min-height: 88px; }
.modal .actions { margin-top: 14px; }
.modal .actions button { flex: 1; }
.modal-err { color: #ff9ab4; font-size: 12.5px; min-height: 16px; margin-top: 6px; }

@media (prefers-reduced-motion: reduce) {
  .modal-wrap, .modal { animation: none; }
}
/* ═══════════════════════════════════════════════════════════════════════════
   БОНУСИ

   Список, а не картки: три-чотири рядки з однаковою будовою читаються швидше
   за стос коробок. Отриманий бонус приглушений, але НЕ прихований — питання
   «звідки в мене ці ходи» так само важливе, як «що я ще не забрав».
   ═══════════════════════════════════════════════════════════════════════════ */
.bon-list { display: flex; flex-direction: column; gap: var(--s1); }
.bon-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: 12px 2px;
  border-bottom: 1px solid var(--edge-soft);
}
.bon-row:last-child { border-bottom: 0; }
.bon-row.done { opacity: .62; }
.bon-main { flex: 1; min-width: 0; }
.bon-main b { display: block; font-size: 14.5px; color: #f4fbf2; }
.bon-main span { display: block; font-size: 12px; line-height: 1.45; color: var(--ink-3); margin-top: 2px; }
.bon-side { flex: none; display: flex; align-items: center; gap: var(--s2); }
.bon-side i {
  font-style: normal;
  font-family: var(--font-data); font-variant-numeric: tabular-nums;
  font-size: 16px; font-weight: 700; color: var(--amber);
}
.bon-row.done .bon-side i { color: var(--ink-2); }
/* ═══════════════════════════════════════════════════════════════════════════
   НАСТУПНИЙ КРОК

   Головний елемент першого екрана. Новачок має побачити ОДНУ дію, а не список
   із шести — список читається як домашнє завдання, крок виконується.
   ═══════════════════════════════════════════════════════════════════════════ */
.card.nowstep {
  border-color: rgba(79, 227, 255, .45);
  box-shadow: 0 8px 30px rgba(0, 0, 0, .4), 0 0 24px rgba(79, 227, 255, .16);
}
.nowstep-head { display: flex; align-items: center; gap: var(--s3); margin-bottom: 10px; }
.nowstep-num {
  flex: none;
  font-family: var(--font-data);
  font-size: 22px; font-weight: 700; color: var(--cyan);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.nowstep-num i { font-style: normal; font-size: 12px; color: var(--ink-3); }
.nowstep-head b {
  font-family: var(--font-display); font-weight: 700; font-size: 19px;
  color: #f4fbf2; letter-spacing: -.01em;
}
/* Сама дія — найбільший текст у картці: її читають і виконують. */
.nowstep-do { font-size: 15.5px; line-height: 1.5; color: #fff; margin: 0 0 8px; }
.nowstep-why { font-size: 13px; line-height: 1.5; color: var(--ink-2); margin: 0; }
.card.nowstep .actions button { width: 100%; }
/* ═══════════════════════════════════════════════════════════════════════════
   ЕКСКУРСІЯ КАБІНЕТОМ

   Затемнення робить не окремий шар, а САМА рамка — велетенською тінню назовні.
   Чотири прямокутники довкола цілі давали б щілини на стиках і розʼїжджались
   при прокрутці; тут отвір завжди рівно там, де ціль.
   ═══════════════════════════════════════════════════════════════════════════ */
.tour-veil { position: fixed; inset: 0; z-index: 100; pointer-events: auto; background: transparent; }
/* Затемнення зазвичай дає САМА рамка (`box-shadow` на 9999px довкола цілі).
   На кроці без цілі рамки немає — темніє вуаль, тим самим кольором, щоб перехід
   між кроками не зчитувався як спалах. */
.tour-veil.solid { background: rgba(3, 8, 5, .82); transition: background .22s var(--ease); }

.tour-ring {
  position: fixed;
  z-index: 101;
  border-radius: var(--r-md);
  border: 2px solid var(--cyan);
  box-shadow: 0 0 0 9999px rgba(3, 8, 5, .82), 0 0 22px rgba(79, 227, 255, .75);
  pointer-events: none;
  transition: top .22s var(--ease), left .22s var(--ease),
              width .22s var(--ease), height .22s var(--ease);
  animation: tourPulse 1.8s ease-in-out infinite;
}
@keyframes tourPulse {
  0%, 100% { box-shadow: 0 0 0 9999px rgba(3, 8, 5, .82), 0 0 18px rgba(79, 227, 255, .6); }
  50%      { box-shadow: 0 0 0 9999px rgba(3, 8, 5, .82), 0 0 30px rgba(79, 227, 255, .95); }
}

.tour-tip {
  position: fixed;
  z-index: 102;
  left: 14px; right: 14px;
  max-width: 460px;
  margin: 0 auto;
  padding: 16px;
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, rgba(24, 30, 25, .99), rgba(14, 19, 15, 1));
  border: 1px solid rgba(255, 255, 255, .24);
  border-top-color: rgba(255, 255, 255, .36);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .6);
  animation: modalUp .2s var(--ease) both;
}
.tour-count {
  font-family: var(--font-data);
  font-size: 11px; letter-spacing: .12em;
  color: var(--cyan);
  margin-bottom: 6px;
}
.tour-tip b {
  display: block;
  font-family: var(--font-display); font-weight: 700; font-size: 18px;
  color: #f4fbf2; margin-bottom: 6px;
}
.tour-tip p { margin: 0; font-size: 14px; line-height: 1.55; color: var(--ink-2); }
.tour-tip .actions { margin-top: 14px; }
.tour-tip .actions button { flex: 1; }
/* Картка без цілі: ставити її «під» або «над» нічим, тож ставимо посеред
   екрана. Верх і низ задаємо обидва — так вона лишається в межах екрана й на
   низькому пристрої, де інакше поїхала б за край. */
.tour-tip.mid {
  top: 50%; bottom: auto;
  max-height: calc(100vh - 32px);
  overflow-y: auto;
  /* Власна поява, а не спільний modalUp: той закінчується на `transform: none`
     і, лишаючись на елементі (`fill-mode: both`), стирав би зсув на пів висоти.
     Картка тоді провисала б нижче середини — саме тим «сіпанням», яке видно
     на око. Центрування мусить жити ВСЕРЕДИНІ анімації. */
  animation: tourMid .2s var(--ease) both;
}
@keyframes tourMid {
  from { transform: translateY(calc(-50% + 14px)) scale(.98); }
  to   { transform: translateY(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .tour-ring { animation: none; transition: none; }
  .tour-tip { animation: none; }
  /* Без анімації зсув нема кому задати — повертаємо його простим правилом. */
  .tour-tip.mid { animation: none; transform: translateY(-50%); }
  .tour-veil.solid { transition: none; }
}

/* ── Рекомендований світ ──────────────────────────────────────────────────
   Одна позначка на весь каталог. Дві вже не підказка, а шум: якщо виділено
   все, не виділено нічого. */
.card.pick {
  border-color: rgba(79, 227, 255, .5);
  box-shadow: 0 10px 34px rgba(0, 0, 0, .42), 0 0 26px rgba(79, 227, 255, .2);
}
.pick-tag {
  display: inline-block;
  font-family: var(--font-data);
  font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase;
  color: #062028;
  background: linear-gradient(135deg, var(--cyan), #8ef0ff);
  padding: 4px 10px;
  border-radius: 999px;
  margin-bottom: 10px;
}
/* ── Смужка кроку ─────────────────────────────────────────────────────────
   Один рядок замість цілого екрана-орієнтира. Стоїть над списком, зникає
   разом із виконаним кроком і нічого не вимагає натискати — просто каже, що
   тут робити далі. */
.stepstrip {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  padding: 11px 14px;
  margin: 0 0 14px;
  border-radius: var(--r-md);
  background: linear-gradient(90deg, rgba(79, 227, 255, .16), rgba(185, 140, 255, .1));
  border: 1px solid rgba(79, 227, 255, .32);
  font-size: 14px;
  line-height: 1.45;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .8);
}
.stepstrip-num {
  flex: none;
  font-family: var(--font-data);
  font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--cyan);
}
/* ── Екскурсія: вихід має бути очевидним ──────────────────────────────────
   Шар, що накриває екран і ловить дотики, ЗОБОВʼЯЗАНИЙ мати помітний вихід.
   Інакше людина, яка не влучила в кнопку, вважає застосунок зламаним — і має
   рацію, бо для неї він саме такий. */
.tour-veil { cursor: pointer; }
.tour-tip { position: fixed; cursor: default; }
.tour-x {
  position: absolute;
  top: 8px; right: 8px;
  width: 32px; height: 32px;
  min-height: 32px;
  padding: 0;
  border-radius: 50%;
  font-size: 20px; line-height: 1;
  background: rgba(255, 255, 255, .1);
  border: 1px solid rgba(255, 255, 255, .2);
  color: #fff;
  box-shadow: none;
}
.tour-x:hover { background: rgba(255, 255, 255, .2); }
.tour-tip .tour-count { padding-right: 40px; }
.tour-hint {
  margin-top: 10px;
  text-align: center;
  font-size: 11.5px;
  color: var(--ink-3);
}

/* ── Правила білінгу: текст приходить рядками, а не абзацами ──────────────
   Сервіс віддає готовий текст із переносами `\n` — у чаті Telegram вони
   працюють, у HTML схлопуються в один суцільний абзац. Через це блок правил
   виглядав як стіна тексту. Зберігаємо переноси, не дублюючи розмітку. */
.policy { white-space: pre-line; }
/* ── Досьє персонажа ───────────────────────────────────────────────────────
   Вкладки, а не довгий сувій: «що про мене памʼятають» і «хто мене любить» —
   різні питання, і змішані в одному потоці вони заважають одне одному. */
.modal.wide { max-width: 560px; width: calc(100vw - 28px); }

.dossier-tabs {
  display: flex; gap: var(--s2);
  margin: 4px 0 14px;
  overflow-x: auto;
  /* Смужка вкладок гортається вбік, але сама сторінка — ні: інакше на вузькому
     екрані від дотику їде весь застосунок. */
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.dossier-tabs::-webkit-scrollbar { display: none; }

.dossier-tab {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: 8px 13px;
  border-radius: 999px;
  font-family: var(--font-data);
  font-size: 13px;
  color: var(--ink-2);
  background: var(--mat-1);
  border: 1px solid var(--edge-soft);
  cursor: pointer;
  white-space: nowrap;
  transition: background .16s var(--ease), color .16s var(--ease), border-color .16s var(--ease);
}
.dossier-tab .ic { width: 16px; height: 16px; }
.dossier-tab.on {
  color: #061109;
  background: var(--acid);
  border-color: var(--acid);
  font-weight: 700;
}

.dossier-body {
  max-height: min(62vh, 520px);
  overflow-y: auto;
  /* Місце під смугу прокрутки, щоб вміст не стрибав при її появі. */
  padding-right: 4px;
}
.dossier-body .sec:first-child { margin-top: 0; }
.dossier-body .who-row { margin-bottom: 8px; }
.dossier-body .who-row span { display: block; margin-top: 3px; }
.dossier-body .pill { margin-right: 5px; }

/* ── Донат: ID гравця важливіший за посилання ─────────────────────────────
   Без ID у коментарі платіж анонімний, і адмін не знає, кому нараховувати
   ходи. Тому число велике, моноширинне й копіюється в один тап. */
.idbox {
  margin: var(--s4) 0 var(--s3);
  padding: var(--s3) var(--s4);
  border-radius: var(--r-md);
  background: rgba(143, 217, 63, .10);
  border: 1px dashed var(--portal-mid);
  cursor: pointer;
  text-align: center;
  transition: background .16s var(--ease);
}
.idbox:hover { background: rgba(143, 217, 63, .16); }
.idbox:active { transform: scale(.99); }
.idbox span {
  display: block;
  font-size: var(--t-small);
  color: var(--ink-3);
}
.idbox b {
  display: block;
  margin: var(--s1) 0;
  font-family: var(--font-data);
  font-size: 26px;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--acid);
  font-variant-numeric: tabular-nums;
}
.idbox i {
  font-size: 11.5px;
  color: var(--ink-3);
  font-style: normal;
}
.warnline {
  margin: 0 0 var(--s3);
  padding: var(--s2) var(--s3);
  border-radius: var(--r-sm);
  border-left: 3px solid var(--warn, #e0a355);
  background: rgba(224, 163, 85, .10);
  font-size: var(--t-small);
  color: var(--ink-2);
}

/* ── Ціна: гривня головна, долар довідковий ───────────────────────────────
   Гравець платить у гривні через банку, тож саме вона має читатись першою.
   Долар лишається, бо ціни в пакетах задані в ньому й так їх легше звіряти. */
.pricerow {
  display: flex; align-items: baseline; gap: var(--s2);
  margin: 0 0 var(--s1);
}
.pricerow b {
  font-family: var(--font-display);
  font-size: 24px; font-weight: 800;
  color: var(--acid);
  font-variant-numeric: tabular-nums;
}
.pricerow span { font-size: var(--t-small); color: var(--ink-3); }
.pricenote {
  margin: 0 0 var(--s2);
  font-size: var(--t-small);
  color: var(--ink-3);
}
.pricenote b { color: var(--acid); }
