/* Игра в браузере — экраны на токенах сайта (см. site/assets/css/style.css).
   Подключается ПОСЛЕ style.css, тут только то, чего там нет. */

.igra-body { min-height: 100vh; display: flex; flex-direction: column; }

/* Фон игры — было ровное фиолетовое звёздное небо (.sky/.stars из style.css),
   потом (первый заход) его сменили на то же фото-«шапку», что на других
   страницах сайта (hero-desktop.webp). С Раунда 3 (spisok.md п.3, находка
   Егора: «сверху видно старое небо/фонарщика, киберпанк-город начинается
   ниже») фото убрано совсем. Причина не в одной опечатке в CSS — у общего
   hero-фото сайта нет версии «под тему», оно ОДНО на всех 13 тем и не гасло
   мгновенно: пока JS не навесил data-theme (первая краска страницы, медленный
   канал) или пока сама фотография догружается, ровно этот бесхозный кадр и
   торчал сверху — картинка, а не токен, не может смениться раньше, чем
   догрузится. Токены темы (--gold/--surface-2/--bg — applyTheme выставляет
   их на <html> синхронно, до первой краски) такой щели не оставляют: ниже
   (правило `[data-theme=...] .sky`) у восьми сюжетных тем этот градиент всё
   равно гасится в сплошной var(--bg) под их рендером, а для пяти тем без
   сцены (4 цветовые + Терминал) это и есть финальный вид — свой акцентный
   градиент на палитре темы вместо чужого фото каменного замка, которое не
   сочеталось смыслом ни с «Лесным», ни с «Сапфировым». */
.igra-body .sky {
  background:
    radial-gradient(1100px 650px at 15% -10%, color-mix(in srgb, var(--gold) 20%, transparent), transparent 60%),
    radial-gradient(900px 620px at 92% 6%, color-mix(in srgb, var(--gold-2, var(--gold)) 14%, transparent), transparent 60%),
    linear-gradient(180deg, var(--surface-2, var(--surface)) 0%, var(--bg) 70%);
}
.btn-primary { color: var(--on-gold, #1a1206); background: linear-gradient(135deg, var(--btn-a, var(--gold-2)), var(--btn-b, var(--gold))); }
.igra-body .sky::after, .igra-body .stars { display: none; }  /* 29.09: ни шума, ни звёзд под интерфейсом игры */

/* Четыре чисто цветовые темы (Фиолетовый/Сапфировый/Лесной/Янтарный) — без
   сюжетного рендера и без своего --surface-tint, поэтому общий .sky выше
   («20%/14%») читался владельцем 29.09 как «пустой плоский фон»: у них нет
   ни карточки-акцента, ни силуэта, которые обычно отвлекают взгляд от того,
   что фон почти не виден за топбаром/картами. Усиливаем ИМЕННО у этой
   четвёрки — не трогая формулу самого .sky (её всё ещё используют crt и
   восемь сюжетных тем как основу под свой рендер/скрим): три слоя вместо
   двух (третий — тёплое пятно снизу, чтобы фон не выглядел «светильником
   в одном углу»), плюс лёгкая виньетка по краям — тень по контуру экрана,
   собранная тем же radial-gradient, а не картинкой (закон 9 — только код). */
[data-theme="dark_purple"] .igra-body .sky,
[data-theme="dark_blue"] .igra-body .sky,
[data-theme="dark_green"] .igra-body .sky,
[data-theme="dark_amber"] .igra-body .sky {
  background:
    radial-gradient(1000px 640px at 12% -8%, color-mix(in srgb, var(--gold) 32%, transparent), transparent 55%),
    radial-gradient(820px 620px at 100% 4%, color-mix(in srgb, var(--gold-2) 22%, transparent), transparent 58%),
    radial-gradient(1000px 700px at 50% 118%, color-mix(in srgb, var(--gold) 16%, transparent), transparent 65%),
    radial-gradient(140% 120% at 50% 50%, transparent 55%, color-mix(in srgb, var(--bg) 65%, black) 100%),
    linear-gradient(180deg, var(--surface-2) 0%, var(--bg) 70%);
}
[data-theme="dark_purple"] .igra-body .sky::after,
[data-theme="dark_blue"] .igra-body .sky::after,
[data-theme="dark_green"] .igra-body .sky::after,
[data-theme="dark_amber"] .igra-body .sky::after { opacity: .16; }
[data-theme="dark_purple"] .igra-body .stars,
[data-theme="dark_blue"] .igra-body .stars,
[data-theme="dark_green"] .igra-body .stars,
[data-theme="dark_amber"] .igra-body .stars { opacity: .55; }
/* position+z-index обязательны: .theme-scene-render/.theme-scrim —
   position:fixed с z-index:0 (см. igra.css ниже), а без собственного z-index
   у .igra-main эти фоновые слои по правилам стекового контекста CSS красятся
   ПОСЛЕ обычного статичного контента — то есть поверх него, а не под ним.
   Из-за этого «непрозрачные на 92%» панели (js/themes.js) на глаз всё равно
   выглядели полупрозрачными: фон и подложка ложились НА карточки сверху,
   разбавляя их обратно. Нашли на снимках сюжетных тем (28.09,
   F:\Android\otchet\temy\perenos.md) — раньше это маскировалось тем, что и
   карточки, и фон были одинаково полупрозрачными, разницу не было видно. */
/* 30.09: z-index 3, а не 1. С Раунда 4 .theme-scrim стоит на z-index 2 (над рендером
   с z-index 1) — и оказался НАД содержимым с z-index 1: вся лента, пузыри и капсула
   ввода сюжетных тем были под вуалью цвета фона на 14–32% (пергамент Летописи на
   замере 175,165,140 вместо 248,238,214). Отсюда во многом и «плоско, без глубины». */
.igra-main { position: relative; z-index: 3; flex: 1; width: 100%; padding: 24px 16px 40px; }
.igra-shell { width: min(720px, 100%); margin-inline: auto; }
.igra-shell.wide { width: min(960px, 100%); }

/* Экран входа рисуется до setTopbarVisible(true) — топбара (и его логотипа)
   на странице ещё нет вовсе, поэтому свой, отдельный от шапки. */
/* display:flex (а не inline-flex у .brand): блок на всю строку, заголовок «Вход»
   (inline-block-плашка сюжетных тем) всегда уходит строкой ниже и не наезжает
   на надпись «RPG Studio», как бы ни сузилась ширина. */
.igra-auth-brand { display: flex; width: fit-content; max-width: 100%; justify-content: center; margin: 8px 0 20px; }

.igra-topbar {
  display: flex; align-items: center; justify-content: flex-start; gap: 12px;
  padding: 12px 16px; border-bottom: 1px solid var(--border);
  background: rgba(11, 10, 18, 0.72); backdrop-filter: blur(12px);
  position: sticky; top: 0; z-index: 40;
}
.igra-topbar .brand { font-size: 1.15rem; gap: 8px; }
.igra-topbar .brand-mark { width: 30px; height: 30px; }
/* Слева направо: меню, логотип-бренд, а чернила и аватар — у правого края
   (margin-left:auto). Раньше стояло space-between на трёх детях, и логотип
   оказывался посередине шапки (владелец 29.09: «звёздочка посередине»). */
.igra-topbar-actions { display: flex; align-items: center; gap: 10px; margin-left: auto; }
/* Чернила — не рубли (владелец 28.09: «Чернил: 110 ₽» читалось как цена, хотя
   это остаток расходуемого ресурса, курс 1 чернило = 1 ₽ только на пополнении).
   Капля вместо знака ₽, ₽ тут больше нигде не показывается. */
/* Чип чернил: раньше капля+число сидели голыми на шапке — на глаз тонут
   рядом с логотипом и меню. Своя плашка того же тона, что и остальные
   акценты темы (--gold), делает цифру заметной И даёт акцентному цвету
   темы ещё одну точку на экране (владелец 29.09, второй заход: «акцент на
   счётчике чернил» — одна из пяти опор различимости темы наравне с
   карточкой/орнаментом/шапкой/кнопкой). */
.igra-ink {
  display: inline-flex; align-items: center; gap: 5px; font-size: .85rem; color: var(--text-2);
  white-space: nowrap; padding: 5px 10px 5px 8px; border-radius: 999px;
  background: color-mix(in srgb, var(--gold) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--gold) 30%, transparent);
}
.igra-ink .ink-drop { flex: none; color: var(--gold-t); }
.igra-ink b { color: var(--gold-t); font-weight: 700; }

[hidden] { display: none !important; }

/* Материал карточки — везде градиент --surface→--surface-tint (перенос
   .spill/#input-area из ui.html: там у каждой темы своя пара тонов
   материала, а не один плоский серый + цветная рамка), плюс
   backdrop-filter: blur — теперь, когда --surface стал прозрачнее (см.
   js/themes.js, второй заход 29.09: «задников не видно» — было почти
   сплошных .92/.96), сквозь карточку виден размытый задник темы вместо
   голой плашки. var(--surface-tint, var(--surface)) — фолбэк для четырёх
   цветовых тем: там своего тона материала нет (в исходнике они тоже без
   формы, см. комментарий у THEMES), фолбэк схлопывает градиент в плоский
   цвет, ничего не ломая. */
.igra-card, .igra-start-card, .igra-turn-assistant, .igra-turn-user,
.igra-chat-item, .igra-pick, .igra-lore-item {
  background: linear-gradient(165deg, var(--surface), var(--surface-tint, var(--surface)));
  backdrop-filter: blur(16px) saturate(1.05);
  -webkit-backdrop-filter: blur(16px) saturate(1.05);
}

.igra-card {
  padding: 24px; border-radius: var(--radius);
  border: 1px solid var(--border); margin-bottom: 16px;
}
.igra-field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.igra-field label { font-size: .85rem; color: var(--text-2); }

/* Тёмная тема для всех полей ввода экранов игры — раньше правило цепляло
   только инпуты, обёрнутые в .igra-field, а textarea хода и select модели
   стоят в разметке БЕЗ такой обёртки и рисовались системным белым полем.
   Селектор широкий (по .igra-shell), чтобы больше не зависеть от обёртки. */
.igra-field input, .igra-field textarea, .igra-field select,
.igra-shell input, .igra-shell textarea, .igra-shell select {
  padding: 12px 14px; border-radius: 12px; background: rgba(255,255,255,.05);
  border: 1px solid var(--border-strong); color: var(--text); font: inherit;
  width: 100%; accent-color: var(--gold);
}
.igra-field textarea { min-height: 90px; resize: vertical; }
.igra-field input:focus, .igra-field textarea:focus, .igra-field select:focus,
.igra-shell input:focus, .igra-shell textarea:focus, .igra-shell select:focus {
  outline: none; border-color: var(--gold);
}
.igra-shell select::-webkit-scrollbar { width: 10px; }
.igra-shell option { background: #17131f; color: var(--text); }

/* Обводка фокуса с клавиатуры — везде в игре, поверх обычного :focus выше */
.igra-shell :focus-visible, .igra-topbar :focus-visible {
  outline: 2px solid var(--gold); outline-offset: 2px;
}

/* Выбор модели: системная стрелка select тоже белая на белом — рисуем свою */
.igra-select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 34px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e8934c' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; background-size: 16px;
}
.igra-row { display: flex; gap: 10px; flex-wrap: wrap; }
.igra-row .btn { flex: none; }
.igra-error {
  padding: 12px 14px; border-radius: 12px; background: rgba(240,143,176,.1);
  border: 1px solid rgba(240,143,176,.35); color: var(--rose); font-size: .92rem;
  margin-bottom: 14px;
}
.igra-error[hidden] { display: none !important; }
.igra-hint { font-size: .82rem; color: var(--text-3); }

/* Список партий */
.igra-list { display: flex; flex-direction: column; gap: 10px; }
.igra-chat-item {
  display: flex; align-items: center; gap: 14px; padding: 14px 16px;
  border-radius: 14px; border: 1px solid var(--border);
  cursor: pointer; text-align: left; width: 100%;
}
.igra-chat-item:hover { background: var(--surface-2); border-color: var(--border-strong); }
.igra-chat-item .txt { flex: 1; min-width: 0; }
.igra-chat-item b { display: block; font-size: 1rem; }
.igra-chat-item span { display: block; font-size: .85rem; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.igra-chat-item .del { flex: none; }
.igra-empty { padding: 40px 20px; text-align: center; color: var(--text-3); }

/* Карточки миров/героев */
.igra-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; margin-bottom: 8px; }
.igra-pick {
  padding: 16px; border-radius: 14px; border: 1px solid var(--border);
  cursor: pointer; text-align: left;
}
.igra-pick b { display: block; margin-bottom: 6px; }
.igra-pick span { font-size: .82rem; color: var(--text-2); display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.igra-pick.is-selected { border-color: var(--gold); background: rgba(232,147,76,.1); }
.igra-pick.is-add { display: flex; align-items: center; justify-content: center; color: var(--text-3); border-style: dashed; }
.igra-cards-empty { grid-column: 1 / -1; padding: 4px 2px 10px; font-size: .85rem; color: var(--text-3); }

/* Игровой экран ---------------------------------------------------------- */
.igra-game-head { justify-content: space-between; align-items: center; margin-bottom: 10px; flex-wrap: nowrap; gap: 10px; }
/* ── Экран партии: материал и шрифты (30.09, раунд 2) ─────────────────────
   Владелец 30.09: «окна скучные, шрифты плоские, не чувствуется глубины в
   обрамлениях». Причины были буквальные: у пяти тем дисплейный шрифт вообще
   без кириллицы (Orbitron, VT323, Special Elite, Quicksand — Google отдаёт им
   только латиницу), и русский текст молча падал в Georgia/Inter/Consolas; а
   пузыри были одной плоской плашкой с одной тенью. Теперь у экрана партии свои
   переменные (--pt-*), тема их переопределяет в themes.css, раздел «Экран
   партии»: шрифт заголовка и прозы (все с кириллицей, index.html), стекло
   поверх картины (приём SillyTavern VN), трёхслойная тень + светлая кромка,
   уголки-орнамент, ярлык говорящего (Night Call / Honkai), маркер «дальше» ▼
   (Hades / HSR). Референсы: F:\Android\otchet\igra_dizajn_0930\referensy\.
   --font-display не трогаем: им пользуются остальные экраны. */
:root {
  --pt-title: var(--font-display);
  --pt-title-weight: 700;
  --pt-title-case: none;
  --pt-title-track: .005em;
  --pt-prose: 'Lora', Georgia, serif;
  --pt-prose-size: 1.07rem;
  --pt-prose-lh: 1.74;
  --pt-ui: var(--font-body);
  --pt-glow: color-mix(in srgb, var(--gold) 45%, transparent);
  --pt-bubble: linear-gradient(168deg, var(--surface), var(--surface-tint, var(--surface)));
  --pt-sheen: linear-gradient(180deg, rgba(255,255,255,.075), rgba(255,255,255,0) 42%);
  --pt-frame: color-mix(in srgb, var(--border-strong) 85%, var(--gold));
  --pt-edge: rgba(255,255,255,.13);
  --pt-shade: 0 1px 1px rgba(0,0,0,.3), 0 6px 14px -6px rgba(0,0,0,.5), 0 24px 46px -22px rgba(0,0,0,.72);
  --pt-corner: color-mix(in srgb, var(--gold) 75%, transparent);
  --pt-corners:
    linear-gradient(var(--pt-corner), var(--pt-corner)) left 7px top 7px / 12px 1.5px no-repeat,
    linear-gradient(var(--pt-corner), var(--pt-corner)) left 7px top 7px / 1.5px 12px no-repeat,
    linear-gradient(var(--pt-corner), var(--pt-corner)) right 7px top 7px / 12px 1.5px no-repeat,
    linear-gradient(var(--pt-corner), var(--pt-corner)) right 7px top 7px / 1.5px 12px no-repeat,
    linear-gradient(var(--pt-corner), var(--pt-corner)) left 7px bottom 7px / 12px 1.5px no-repeat,
    linear-gradient(var(--pt-corner), var(--pt-corner)) left 7px bottom 7px / 1.5px 12px no-repeat,
    linear-gradient(var(--pt-corner), var(--pt-corner)) right 7px bottom 7px / 12px 1.5px no-repeat,
    linear-gradient(var(--pt-corner), var(--pt-corner)) right 7px bottom 7px / 1.5px 12px no-repeat;
  --pt-radius: var(--radius);
  --pt-tag-bg: color-mix(in srgb, var(--gold) 16%, transparent);
  --pt-tag-fg: color-mix(in srgb, var(--gold-t) 60%, var(--text));   /* чистый --gold-t на подложке ярлыка давал 4.2–4.4 у dark_green/dark_amber */
  --pt-tag-bd: color-mix(in srgb, var(--gold) 50%, transparent);
  --pt-user-bg: linear-gradient(160deg, color-mix(in srgb, var(--gold) 24%, var(--surface)), color-mix(in srgb, var(--gold) 11%, var(--surface-tint, var(--surface))));
  --pt-user-bd: color-mix(in srgb, var(--gold) 62%, transparent);
  --pt-glass: color-mix(in srgb, var(--bg) 80%, transparent);
}

/* Ореол текста цвета фона темы — читаемость заголовков поверх любого задника. */
.igra-game-head, .igra-begin { --halo: 0 0 2px var(--bg), 0 0 6px var(--bg), 0 0 14px var(--bg), 0 0 28px var(--bg); }
/* Под шапкой партии — мягкое затемнение-виньетка цвета фона (не плашка): у Пустоши
   заголовок лежал на светлом небе и читался слабо (снимок 30.09). */
.igra-game-head { position: relative; isolation: isolate; }
.igra-game-head::before {
  content: ''; position: absolute; inset: -14px -18px -10px; z-index: -1; pointer-events: none;
  /* полоса-«лента» цвета фона, тает вправо и по краям сверху/снизу: заголовок на светлом
     небе (Пустошь, Летопись) держит контраст без глухой плашки */
  background: linear-gradient(90deg, color-mix(in srgb, var(--bg) 80%, transparent), color-mix(in srgb, var(--bg) 80%, transparent) 55%, transparent 95%);
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent); mask-image: linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent);
}
.igra-title-wrap { min-width: 0; flex: 1; position: relative; padding-bottom: 14px; }
/* Заголовок партии — дисплейный шрифт темы, ореол из --bg, под ним разделитель
   «линия — ромб — линия» с угасанием (Genshin / HSR). */
.igra-title {
  margin: 0; cursor: pointer; border-radius: 8px; padding: 2px 4px; margin-left: -4px;
  font-family: var(--pt-title); font-weight: var(--pt-title-weight); text-transform: var(--pt-title-case);
  font-size: clamp(1.5rem, 1.1rem + 1.5vw, 2.2rem); line-height: 1.15; letter-spacing: var(--pt-title-track);
  color: var(--text);
  text-shadow: var(--halo), 0 0 22px var(--pt-glow);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: color .18s ease, text-shadow .18s ease;
}
.igra-title:hover, .igra-title:focus-visible { color: var(--gold-t); outline: none; }
.igra-title-wrap::before {
  content: ''; position: absolute; left: 0; right: 12%; bottom: 5px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold) 6%, color-mix(in srgb, var(--gold) 40%, transparent) 55%, transparent);
  box-shadow: 0 0 10px var(--pt-glow);
}
.igra-title-wrap::after {
  content: ''; position: absolute; left: 22px; bottom: 2px; width: 7px; height: 7px;
  background: linear-gradient(135deg, var(--gold-2), var(--gold)); transform: rotate(45deg);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--bg) 85%, transparent), 0 0 12px var(--pt-glow);
}
.igra-title-input {
  font: inherit; font-family: var(--font-display); font-size: inherit; font-weight: 600;
  color: var(--text); background: rgba(255,255,255,.05); border: 1px solid var(--gold);
  border-radius: 8px; padding: 4px 8px; margin-left: -8px; width: 100%; max-width: 420px;
}
.icon-btn-sm { flex: none; width: 34px; height: 34px; border-radius: 10px; border: 1px solid var(--border); }
.icon-btn-sm svg { width: 17px; height: 17px; }
.icon-btn-sm:disabled { opacity: .4; cursor: default; }
.icon-btn-sm:disabled:hover { background: none; color: var(--text-2); }

/* Карточка «с чего начинаем» — мастер + мир партии. Крупная, пока ход не
   сделан ни один (владелец 28.09: раньше это выглядело «сырой формой» —
   голый select и раскрывашка прямо над лентой), после первого хода
   renderStartCard() (app.js) добавляет .is-collapsed — те же самые
   modelSelect/modelHint/worldPanelBody, но в одну тонкую строку-чип, чтобы
   не отъедать место у ленты партии. */
.igra-start-card {
  padding: 16px 18px; border-radius: var(--radius);
  border: 1px solid var(--border); margin-bottom: 16px;
}
.igra-start-card .igra-field { margin-bottom: 8px; }
#modelHint { margin: 0 0 10px; }
.igra-world-panel { margin: 0; }
.igra-world-panel summary { cursor: pointer; font-size: .9rem; color: var(--text-2); padding: 6px 0; list-style-position: outside; }
.igra-world-panel .body { font-size: .9rem; color: var(--text-2); white-space: pre-wrap; padding: 8px 0 2px; }

.igra-start-card.is-collapsed {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px 16px; padding: 8px 14px;
}
.igra-start-card.is-collapsed .igra-field {
  /* Базовый .igra-field — flex-direction: column (подпись НАД полем, форма
     на всю ширину). Тут поле сжато в чип, подпись и select должны стоять
     В РЯД — без переопределения direction здесь оставался column, и label
     улетал самостоятельной строкой над select, а align-items: center по
     column-оси центрировал её по ширине — то есть вправо от узкого select
     (владелец 28.09: «Мастер» висит над и правее своего select). */
  margin-bottom: 0; display: flex; flex-direction: row; align-items: center; gap: 8px; flex: none;
}
.igra-start-card.is-collapsed .igra-field label { font-size: .78rem; white-space: nowrap; }
.igra-start-card.is-collapsed .igra-select {
  padding: 5px 26px 5px 10px; font-size: .82rem; width: auto; min-width: 0;
}
.igra-start-card.is-collapsed #modelHint { display: none; }
.igra-start-card.is-collapsed .igra-world-panel { flex: none; }
.igra-start-card.is-collapsed .igra-world-panel summary { font-size: .82rem; padding: 0; }

.igra-turns { display: flex; flex-direction: column; gap: 20px; margin-bottom: 18px; padding-top: 4px; }
/* Материал реплик. Фон — три слоя: уголки-орнамент (--pt-corners), блик сверху
   (--pt-sheen) и сама поверхность темы (--pt-bubble); тень — контактная +
   средняя + рассеянная; внутри — светлая кромка сверху и тёмная снизу (толщина
   «стекла»). Размытие задника под пузырём умеренное (8px): пузырей в партии
   много, на телефоне каждый — отдельный слой. */
.igra-turn-assistant, .igra-turn-user { position: relative; animation: pt-rise .42s cubic-bezier(.2,.8,.2,1) both; }
@keyframes pt-rise { from { opacity: 0; transform: translateY(10px) scale(.992); } }
.igra-turn-assistant {
  font-family: var(--pt-prose); font-size: var(--pt-prose-size); line-height: var(--pt-prose-lh);
  letter-spacing: .003em; white-space: pre-wrap; overflow-wrap: break-word;
  font-kerning: normal; font-variant-numeric: oldstyle-nums proportional-nums; text-wrap: pretty;
  background: var(--pt-corners), var(--pt-sheen), var(--pt-bubble);
  box-shadow: var(--pt-shade), inset 0 1px 0 var(--pt-edge), inset 0 -1px 0 rgba(0,0,0,.22);
  backdrop-filter: blur(8px) saturate(1.1); -webkit-backdrop-filter: blur(8px) saturate(1.1);
}
/* Ярлык говорящего над текстом мастера — «Мастер» капсом с разрядкой, как имя
   в диалоговом окне игры. Абсолютный: в потоке он перехватил бы ::first-letter. */
.igra-turn-assistant::before {
  content: 'Мастер'; position: absolute; top: 13px; left: 20px; pointer-events: none;
  font: 700 .66rem/1 var(--pt-ui); letter-spacing: .18em; text-transform: uppercase; white-space: nowrap;
  color: var(--pt-tag-fg); padding: 4px 9px 4px 10px; border-radius: 999px;
  background: var(--pt-tag-bg); border: 1px solid var(--pt-tag-bd);
}
/* Маркер «дальше» у последнего готового ответа — треугольник, мягко дышит (Hades / HSR). */
.igra-turns > .igra-turn-assistant:last-child:not(.igra-turn-pending)::after {
  content: ''; position: absolute; left: 50%; margin-left: -5px; bottom: 10px; width: 10px; height: 7px; pointer-events: none;
  background: var(--gold-t); clip-path: polygon(0 0, 100% 0, 50% 100%);
  filter: drop-shadow(0 0 4px var(--pt-glow)); animation: pt-next 1.6s ease-in-out infinite;
}
@keyframes pt-next { 0%, 100% { transform: translateY(0); opacity: .95; } 50% { transform: translateY(3px); opacity: .55; } }
/* Вступление — буквица на три строки: только у первой реплики мастера в партии
   (если историю начал игрок, первой стоит его реплика — буквица у первого ответа). */
.igra-turns > .igra-turn-assistant:not(.igra-turn-assistant ~ .igra-turn-assistant):not(.igra-turn-pending)::first-letter {
  float: left; font-family: var(--pt-title); font-weight: 700; font-size: 3.35em; line-height: .86;
  margin: .06em .12em -.04em 0; color: var(--gold-t);
  text-shadow: 0 2px 0 rgba(0,0,0,.25), 0 0 18px var(--pt-glow);
}
.igra-turn-user {
  /* Раньше — rgba(232,180,92,.12) и color: var(--gold-t): полупрозрачный
     янтарный вне зависимости от темы, а var(--gold-2) на светлой
     pink_kingdom и на dark_purple даёт контраст 2.6–2.7 к любому фону под
     ним (посчитано в F:\Android\otchet\temy\perenos.md) — и это не только
     из-за задника, так было бы и на плоском фоне. var(--text) вместо
     var(--gold-2) гарантирует ≥4.5:1 на всех восьми темах (та же панель,
     что у текста мастера), акцент остаётся золотой рамкой. */
  align-self: flex-end; max-width: 80%; padding: 12px 17px 13px; border-radius: 20px 20px 5px 20px;
  border: 1px solid var(--pt-user-bd); color: var(--text);
  background: var(--pt-sheen), var(--pt-user-bg);
  box-shadow: 0 1px 1px rgba(0,0,0,.28), 0 12px 26px -14px color-mix(in srgb, var(--gold) 55%, rgba(0,0,0,.6)), inset 0 1px 0 var(--pt-edge);
  backdrop-filter: blur(8px) saturate(1.1); -webkit-backdrop-filter: blur(8px) saturate(1.1);
  white-space: pre-wrap; overflow-wrap: break-word; font-family: var(--pt-ui); font-size: .98rem; line-height: 1.55;
}
.igra-caret { display: inline-block; width: 2px; height: 1em; background: var(--gold); vertical-align: -0.15em; margin-left: 2px; animation: igra-blink 1s steps(2) infinite; }
@keyframes igra-blink { 50% { opacity: 0; } }

/* «Мастер печатает» — раньше вместо этого висел ПУСТОЙ .igra-turn-assistant
   (только моргающий 2-пиксельный курсор) с первого чанка до последнего, а
   если поток обрывался ДО первого чанка (сеть/ошибка), пузырь так и
   оставался пустым навсегда — на светлых темах (pink_kingdom) это читалось
   как голая белая плашка без смысла (владелец прислал снимок 28.09, счёл
   «вёрсткой из 90-х»). Точки — понятная замена; appendStreamingBubble()
   в app.js убирает сам пузырь целиком, если ответ так и не начал приходить. */
.igra-turn-pending { min-height: 22px; display: flex; align-items: center; align-self: flex-start; min-width: 220px;
  animation: pt-rise .42s cubic-bezier(.2,.8,.2,1) both, pt-think 2.2s ease-in-out .42s infinite; }
/* «Мастер печатает»: рамка пузыря дышит светом акцента, точки — волной. Одна анимация
   на один пузырь, не на весь экран. */
@keyframes pt-think { 50% { border-color: var(--gold); } }
.igra-typing { display: inline-flex; align-items: center; gap: 6px; }
.igra-typing i {
  width: 7px; height: 7px; border-radius: 50%; background: var(--gold-t); display: block;
  box-shadow: 0 0 8px var(--pt-glow);
  animation: igra-typing-bounce 1.2s ease-in-out infinite;
}
.igra-typing i:nth-child(2) { animation-delay: .16s; }
.igra-typing i:nth-child(3) { animation-delay: .32s; }
.igra-typing::after { content: 'подбирает слова'; margin-left: 8px; font: italic .86rem/1 var(--pt-prose); color: var(--text-2); }
@keyframes igra-typing-bounce { 0%, 60%, 100% { transform: translateY(0); opacity: .4; } 30% { transform: translateY(-5px); opacity: 1; } }

/* #screen-game — единственный экран, где секция должна доставать до низа
   вьюпорта: .igra-main — flex-item на всю высоту .igra-body (flex:1), но сам
   он не flex-контейнер, а секции внутри — обычные блоки высотой по контенту.
   При короткой партии (пара ходов) #screen-game заканчивался сразу под
   последним сообщением, а .igra-input-bar (position: sticky; bottom: 0)
   стикуется только в границах своего родителя — если у родителя нет запаса
   высоты вниз, стикать некуда, и полоса ввода вставала не у низа экрана,
   а сразу после сообщений, с фоном темы голой плашкой под ней до самого низа
   страницы (владелец 28.09: «полоса ввода после сообщений, плашка фона под
   ней»). min-height гарантирует запас, чтобы sticky всегда мог дотянуть
   полосу до низа вьюпорта — на 100dvh (учитывает адресную строку/панели
   браузера), с запасным 100vh для браузеров без dvh. */
#screen-game.igra-shell {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
#screen-game.igra-shell .igra-turns { flex: 1 0 auto; }
/* 30.09: пустая партия прокручивалась на 105 px (телефон) / 123 px (ПК): min-height секции = 100dvh,
   а над ней ещё шапка (57-59 px) и верхний отступ .igra-main, а под ней нижний отступ .igra-main —
   страница выходила выше окна, при прокрутке заголовок уходил под шапку, а под капсулой показывалась
   тёмная плашка градиента .igra-input-bar. Теперь, пока открыта партия, .igra-main сам тянется на
   остаток окна под шапкой, секция заполняет его целиком (без собственных 100dvh) и нижнего отступа нет:
   капсула стоит у низа окна, страница ровно в окно. Длинная партия прокручивается как раньше. */
.igra-body:has(#screen-game:not([hidden])) { min-height: 100vh; min-height: 100dvh; }
.igra-main:has(#screen-game:not([hidden])) { display: flex; flex-direction: column; padding-bottom: 0; }
.igra-main:has(#screen-game:not([hidden])) > #screen-game { flex: 1 0 auto; min-height: 0; }

/* Поле ввода хода: прибито к низу, растёт по высоте само (app.js трогает
   height напрямую), круглая кнопка отправки — вместо прежней текстовой
   «Ход»/«Заново» пары. Подсказка про Enter/Shift+Enter раньше жила прямо в
   placeholder и лезла на телефоне в три строки текста вместо одной короткой
   («что вы делаете?») — теперь это отдельная строка, и показывается только
   там, где есть мышь/трекпад (hover:hover) И точный указатель (pointer:fine):
   у тач-телефона в норме нет ни того, ни другого, клавиши Shift на
   экранной клавиатуре тоже нет — подсказка там была не подсказкой, а шумом.

   env(safe-area-inset-bottom) — отступ снизу на телефонах с домашним
   индикатором (iPhone): без него кнопка отправки утыкается прямо в
   системную полосу жестов. interactive-widget=resizes-content в <meta
   viewport> (index.html) — чтобы при открытии клавиатуры браузер уменьшал
   layout-вьюпорт вместе с visual-вьюпортом: без этого sticky продолжает
   считать «низ» от старой, большей высоты, и полоса ввода утекает под
   клавиатуру вместо того, чтобы всплыть над ней. */
.igra-input-bar {
  position: sticky; bottom: 0; z-index: 2;
  padding: 10px 0 max(14px, env(safe-area-inset-bottom));
  background: linear-gradient(0deg, var(--bg) 55%, transparent);
}

/* Капсула ввода — один скруглённый контур на весь блок (textarea сверху,
   тулбар снизу), а не текстовое поле и круглая кнопка порознь рядом друг с
   другом, как было раньше («уровень школьника», слово владельца 29.09).
   Материал — тот же градиент surface→surface-tint, что у карточек
   (см. правило выше в файле), поэтому капсула не плоская голая рамка, а
   стекло того же тона, что и остальной интерфейс темы. */
.igra-composer {
  position: relative; display: flex; flex-direction: column; gap: 4px;
  border-radius: 26px; border: 1px solid var(--pt-frame);
  /* Капсула сама и есть поле (без «поля в поле»): тёмное стекло поверх картины,
     блик сверху, толщина кромками, подъём трёхслойной тенью. */
  background: var(--pt-sheen), linear-gradient(170deg, color-mix(in srgb, var(--surface) 70%, var(--pt-glass)), var(--pt-glass));
  backdrop-filter: blur(18px) saturate(1.15);
  -webkit-backdrop-filter: blur(18px) saturate(1.15);
  padding: 8px 8px 8px 16px;
  box-shadow: var(--pt-shade), inset 0 1px 0 var(--pt-edge), inset 0 -1px 0 rgba(0,0,0,.25);
  transition: border-color .18s ease, box-shadow .22s ease;
}
.igra-composer:focus-within {
  border-color: var(--gold);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 26%, transparent), 0 0 28px -4px var(--pt-glow),
              var(--pt-shade), inset 0 1px 0 var(--pt-edge);
}
.igra-turn-input {
  display: block; width: 100%; resize: none; overflow-y: auto;
  min-height: 24px; max-height: 160px; line-height: 1.45;
  /* Своя textarea без рамки/фона общего правила `.igra-shell textarea` —
     капсула уже несёт и то, и другое, второй контур внутри выглядел бы
     полем в поле. */
  background: none; border: 0; border-radius: 0; padding: 6px 2px 4px;
}
html .igra-shell .igra-composer #turnInput.igra-turn-input {
  padding: 10px 4px 6px; min-height: 42px; font-size: 1rem; color: var(--text);
  background: transparent; border: 0; border-radius: 0; box-shadow: none;
}
html .igra-shell .igra-composer #turnInput.igra-turn-input:focus { outline: none; box-shadow: none; border: 0; }
.igra-composer-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding-top: 6px;
  border-top: 1px solid color-mix(in srgb, var(--border-strong) 45%, transparent); }

/* Таблетка «Мастер · мир» — заменяет отдельную карточку #startCard над
   лентой (владелец 29.09: «сырая форма» — голый select и раскрывашка прямо
   над сообщениями). Открывает #masterPopover, те же modelSelect/modelHint/
   worldPanelBody, что были в карточке — просто в другом месте разметки.
   30.09: чип с рамкой акцента (NovelAI), значок в кружке-медальоне. */
.igra-master-pill {
  display: inline-flex; align-items: center; gap: 7px; max-width: 58%;
  padding: 5px 12px 5px 5px; border-radius: 999px; border: 1px solid color-mix(in srgb, var(--gold) 45%, var(--border-strong));
  background: var(--pt-sheen), color-mix(in srgb, var(--gold) 10%, var(--surface-2)); color: var(--text); font-family: var(--pt-ui); font-size: .82rem; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer;
  box-shadow: 0 1px 2px rgba(0,0,0,.3), 0 6px 14px -8px rgba(0,0,0,.6), inset 0 1px 0 var(--pt-edge);
  transition: background .15s ease, color .15s ease, border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.igra-master-pill::after {
  content: ''; flex: none; width: 6px; height: 6px; margin: -3px 1px 0 2px;
  border-right: 1.6px solid var(--gold-t); border-bottom: 1.6px solid var(--gold-t); transform: rotate(45deg);
  transition: transform .2s ease;
}
.igra-master-pill[aria-expanded="true"]::after { transform: rotate(225deg); margin-top: 3px; }
.igra-master-pill:hover, .igra-master-pill:focus-visible { color: var(--text); border-color: var(--gold); transform: translateY(-1px);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 18%, transparent), 0 8px 18px -8px var(--pt-glow), inset 0 1px 0 var(--pt-edge); outline: none; }
.igra-master-pill:active { transform: translateY(0); }
.igra-master-pill svg {
  flex: none; box-sizing: content-box; padding: 5px; border-radius: 50%; color: var(--on-gold, #1a1206);
  background: linear-gradient(135deg, var(--gold-2), var(--gold)); box-shadow: inset 0 1px 0 rgba(255,255,255,.4), 0 0 10px -2px var(--pt-glow);
}
.igra-master-pill span { overflow: hidden; text-overflow: ellipsis; }

.igra-input-hint { display: none; flex: 1; text-align: center; margin: 0; font-size: .74rem; color: var(--text-2); letter-spacing: .01em; }
.igra-input-hint kbd, .igra-input-hint b { font: inherit; }
/* Только мышь и не узкое окно: в окне ПК шириной с телефон подсказка
   сжималась в три строки рядом с «таблеткой» мастера (снимки 29.09) */
@media (hover: hover) and (pointer: fine) and (min-width: 600px) {
  .igra-input-hint { display: block; }
}
/* Кнопка хода: литой кружок акцента — блик сверху, тень внутри снизу, кольцо и
   свечение; нажатие вдавливает. */
.igra-send-btn {
  position: relative; flex: none; width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center;
  color: var(--on-gold, #1a1206); border: 1px solid color-mix(in srgb, var(--gold-2) 70%, #fff); cursor: pointer;
  background: radial-gradient(120% 90% at 50% 0%, rgba(255,255,255,.38), rgba(255,255,255,0) 55%), linear-gradient(160deg, var(--gold-2), var(--gold));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 16%, transparent), 0 10px 22px -8px var(--pt-glow), 0 2px 3px rgba(0,0,0,.35),
              inset 0 -3px 6px rgba(0,0,0,.22);
  transition: transform .15s ease, box-shadow .15s ease, background .15s ease, opacity .15s ease, filter .15s ease;
}
.igra-send-btn:hover { transform: translateY(-1px); filter: brightness(1.08); box-shadow: 0 0 0 4px color-mix(in srgb, var(--gold) 24%, transparent), 0 12px 26px -8px var(--pt-glow), 0 2px 3px rgba(0,0,0,.35), inset 0 -3px 6px rgba(0,0,0,.22); }
.igra-send-btn:active { transform: translateY(1px) scale(.97); box-shadow: 0 0 0 2px color-mix(in srgb, var(--gold) 20%, transparent), inset 0 3px 6px rgba(0,0,0,.35); }
.igra-send-btn:focus-visible { outline: 2px solid var(--gold-t); outline-offset: 3px; }
/* Пусто в поле — кнопка пригашена и не кликается, как в образце (Claude):
   раньше кружок был всегда ярким, даже когда отправлять нечего. 30.09: не
   прозрачная, а «выключенная» — утопленный кружок с видимой стрелкой. */
.igra-send-btn:disabled {
  cursor: default; transform: none; filter: none; color: var(--text-2);
  background: color-mix(in srgb, var(--surface-2) 80%, transparent); border-color: var(--border-strong);
  box-shadow: inset 0 2px 5px rgba(0,0,0,.3);
}
.igra-send-btn[data-state="stop"] {
  color: var(--text); background: var(--surface-2); border-color: var(--border-strong);
  box-shadow: inset 0 1px 0 var(--pt-edge);
}
.igra-send-btn[data-state="stop"] svg { width: 15px; height: 15px; }

/* Окно «Модель» (+ «Мир партии»). Лежит в <body>, а не в экране игры: слой
   .igra-main (z-index 1) оказывался под шапкой (40), и окно наезжало на
   заголовок «Новая партия» (снимок владельца 29.09). Выше меню (60).
   Телефон — панель снизу на всю ширину, ПК — окно у кнопки (left/bottom
   ставит app.js, placeMasterPopover). Фон непрозрачный: --bg под градиентом,
   иначе текст читался бы поверх ленты. */
.igra-master-popover-backdrop { position: fixed; inset: 0; z-index: 70; background: radial-gradient(120% 90% at 50% 100%, rgba(6,5,10,.66), rgba(6,5,10,.4)); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
.igra-master-popover-backdrop[hidden] { display: none; }
.igra-master-popover {
  position: fixed; z-index: 71; left: 12px; bottom: 80px;
  width: 700px; max-width: calc(100vw - 24px); max-height: min(70vh, 600px);
  display: flex; flex-direction: column; overflow: hidden;
  padding: 18px 18px 0; border-radius: calc(var(--radius) + 4px); border: 1px solid var(--pt-frame);
  color: var(--text);
  /* Непрозрачное «стекло»: --bg под поверхностью, блик и уголки сверху — окно
     лежит над лентой, текст под ним просвечивать не должен. */
  background-color: var(--bg);
  background-image: var(--pt-corners), var(--pt-sheen), radial-gradient(90% 60% at 15% 0%, color-mix(in srgb, var(--gold) 12%, transparent), transparent 70%), linear-gradient(165deg, var(--surface), var(--surface-tint, var(--surface)));
  box-shadow: 0 2px 6px rgba(0,0,0,.35), 0 30px 80px -20px rgba(0,0,0,.8), 0 0 40px -12px var(--pt-glow), inset 0 1px 0 var(--pt-edge), inset 0 0 0 1px rgba(255,255,255,.03);
  animation: pt-pop .24s cubic-bezier(.2,.8,.2,1) both;
}
@keyframes pt-pop { from { opacity: 0; transform: translateY(12px) scale(.985); } }
/* Затухание снизу: если под последней строкой окна есть ещё содержимое (класс ставит app.js). */
.igra-master-popover::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 44px; pointer-events: none; opacity: 0;
  background: linear-gradient(180deg, transparent, var(--bg) 92%); transition: opacity .2s ease;
}
.igra-master-popover.has-more::after { opacity: 1; }
.igra-master-popover[hidden] { display: none; }
.igra-sheet-body { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; padding: 2px 2px 16px; }
.igra-sheet-head {
  flex: none; display: flex; align-items: center; gap: 10px; margin-bottom: 14px; padding-bottom: 13px; position: relative;
  border-bottom: 1px solid transparent;
  border-image: linear-gradient(90deg, transparent, var(--gold) 4%, color-mix(in srgb, var(--gold) 30%, transparent) 60%, transparent) 1;
}
/* ромб на разделителе под заголовком окна — тот же знак, что под заголовком партии */
.igra-sheet-head::after {
  content: ''; position: absolute; left: 18px; bottom: -4px; width: 7px; height: 7px; transform: rotate(45deg);
  background: linear-gradient(135deg, var(--gold-2), var(--gold)); box-shadow: 0 0 10px var(--pt-glow);
}
.igra-sheet-title { margin: 0; flex: 1; min-width: 0; font-family: var(--pt-title); font-weight: var(--pt-title-weight); text-transform: var(--pt-title-case); letter-spacing: var(--pt-title-track); font-size: 1.4rem; color: var(--text); line-height: 1.1; text-shadow: 0 0 18px var(--pt-glow); }
.igra-sheet-count {
  flex: none; font-family: var(--pt-ui); font-size: .76rem; font-weight: 700; letter-spacing: .04em; color: var(--text); padding: 4px 11px; border-radius: 999px;
  background: color-mix(in srgb, var(--gold) 18%, var(--surface-2, transparent)); border: 1px solid color-mix(in srgb, var(--gold) 55%, transparent);
  box-shadow: inset 0 1px 0 var(--pt-edge);
}
.igra-sheet-close {
  width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; cursor: pointer;
  color: var(--text); background: var(--pt-sheen), var(--surface-2, transparent); border: 1px solid var(--border-strong);
  box-shadow: 0 2px 6px -2px rgba(0,0,0,.5), inset 0 1px 0 var(--pt-edge);
  transition: border-color .15s ease, transform .2s ease, box-shadow .15s ease;
}
.igra-sheet-close:hover, .igra-sheet-close:focus-visible { border-color: var(--gold); transform: rotate(90deg); box-shadow: 0 0 14px -2px var(--pt-glow), inset 0 1px 0 var(--pt-edge); outline: none; }
/* Список моделей: на ПК две колонки, на телефоне одна плотная. Все 7 видны сразу. */
.igra-model-list { list-style: none; margin: 0 0 14px; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.igra-model-list > li { display: flex; }
.igra-model-item {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; cursor: pointer; position: relative;
  padding: 9px 12px; border-radius: max(8px, calc(var(--pt-radius) - 4px)); border: 1px solid color-mix(in srgb, var(--border-strong) 80%, transparent);
  background: var(--pt-sheen), color-mix(in srgb, var(--surface-2) 70%, var(--bg)); color: var(--text); font: inherit; font-family: var(--pt-ui);
  box-shadow: 0 1px 2px rgba(0,0,0,.3), inset 0 1px 0 var(--pt-edge);
  transition: border-color .15s ease, background .15s ease, transform .15s ease, box-shadow .15s ease;
}
.igra-model-item:hover, .igra-model-item:focus-visible { border-color: var(--gold); transform: translateY(-1px); outline: none;
  box-shadow: 0 10px 20px -12px rgba(0,0,0,.8), 0 0 0 3px color-mix(in srgb, var(--gold) 14%, transparent), inset 0 1px 0 var(--pt-edge); }
.igra-model-item:active { transform: translateY(0) scale(.99); }
.igra-model-item[aria-checked="true"] {
  border-color: var(--gold);
  background: var(--pt-sheen), linear-gradient(160deg, color-mix(in srgb, var(--gold) 26%, var(--surface-2)), color-mix(in srgb, var(--gold) 9%, var(--bg)));
  box-shadow: 0 0 0 1px var(--gold), 0 12px 26px -12px var(--pt-glow), inset 0 1px 0 var(--pt-edge);
}
.igra-model-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.igra-model-name { font-size: .96rem; font-weight: 700; color: var(--text); overflow-wrap: anywhere; line-height: 1.2; }
.igra-model-note { font-size: .76rem; line-height: 1.3; color: var(--text-2); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.igra-model-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.igra-model-price { flex: none; font-size: .74rem; color: var(--text-2); white-space: nowrap; }
.igra-model-tick {
  flex: none; width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; line-height: 1;
  border: 1.5px solid var(--border-strong); font-weight: 800; font-size: .8rem; color: var(--on-gold, #1a1206);
  box-shadow: inset 0 2px 4px rgba(0,0,0,.3);
}
.igra-model-item[aria-checked="true"] .igra-model-tick { background: radial-gradient(100% 80% at 50% 0%, rgba(255,255,255,.4), transparent 60%), linear-gradient(135deg, var(--gold-2), var(--gold)); border-color: var(--gold-t); box-shadow: 0 0 12px var(--pt-glow); }
.igra-world-panel-title { margin: 0 0 6px; font-size: .82rem; color: var(--text-2); font-weight: 700; }
.igra-world-panel { border-top: 1px solid var(--border); padding-top: 12px; }
.igra-world-panel .body { font-size: .88rem; color: var(--text-2); }
.igra-world-rows { margin: 0; display: grid; grid-template-columns: max-content 1fr; gap: 6px 12px; }
.igra-world-rows dt { font-weight: 700; color: var(--text); }
.igra-world-rows dd { margin: 0; color: var(--text-2); overflow-wrap: anywhere; }
@media (max-width: 700px) {
  .igra-master-popover {
    left: 0 !important; right: 0; bottom: 0 !important; width: 100%; max-width: 100%;
    max-height: 88vh; max-height: 88dvh; border-radius: 22px 22px 0 0; border-bottom: 0;
    padding: 12px 12px env(safe-area-inset-bottom);
  }
  .igra-sheet-head { margin-bottom: 8px; padding-bottom: 8px; }
  .igra-model-list { grid-template-columns: 1fr; gap: 6px; margin-bottom: 10px; }
  .igra-model-item { padding: 7px 11px; }
  .igra-model-note { -webkit-line-clamp: 1; font-size: .72rem; }
}
@media (max-width: 700px) and (max-height: 700px) {
  .igra-model-item { padding: 6px 10px; }
  .igra-model-name { font-size: .9rem; }
}

/* Выбор «кто начинает» — две карточки над пустой лентой новой партии. */
.igra-begin { margin: 8px 0 18px; animation: pt-rise .45s cubic-bezier(.2,.8,.2,1) both; }
/* Заголовок блока — дисплейный шрифт темы с ромбами по бокам (Genshin). */
.igra-begin-title {
  display: flex; align-items: center; gap: 12px; margin: 0 0 14px; position: relative; isolation: isolate;
  font-family: var(--pt-title); font-weight: var(--pt-title-weight); text-transform: var(--pt-title-case); letter-spacing: var(--pt-title-track);
  font-size: 1.28rem; color: var(--text); text-shadow: var(--halo), 0 0 20px var(--pt-glow);
}
.igra-begin-title::before {
  content: ''; position: absolute; inset: -10px -16px; z-index: -1; pointer-events: none;
  background: linear-gradient(90deg, color-mix(in srgb, var(--bg) 80%, transparent), color-mix(in srgb, var(--bg) 80%, transparent) 60%, transparent 96%);
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 25%, #000 75%, transparent); mask-image: linear-gradient(180deg, transparent, #000 25%, #000 75%, transparent);
}
.igra-begin-title::after {
  content: ''; flex: 1; height: 1px; min-width: 24px;
  background: linear-gradient(90deg, var(--gold), transparent); box-shadow: 0 0 8px var(--pt-glow);
}
.igra-begin-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
/* Карточки выбора: стекло поверх картины, свет из верхнего угла (Friends & Fables),
   уголки-орнамент, стрелка «вперёд» выезжает при наведении. */
.igra-begin-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px; text-align: left; cursor: pointer; position: relative;
  padding: 18px 18px 20px; border-radius: var(--pt-radius); border: 1px solid var(--pt-frame); color: var(--text); font: inherit; font-family: var(--pt-ui);
  background: var(--pt-corners), radial-gradient(80% 70% at 0% 0%, color-mix(in srgb, var(--gold) 16%, transparent), transparent 70%), var(--pt-sheen), var(--pt-bubble);
  backdrop-filter: blur(14px) saturate(1.1); -webkit-backdrop-filter: blur(14px) saturate(1.1);
  box-shadow: var(--pt-shade), inset 0 1px 0 var(--pt-edge), inset 0 -1px 0 rgba(0,0,0,.22);
  transition: border-color .18s ease, transform .2s cubic-bezier(.2,.8,.2,1), box-shadow .2s ease;
}
.igra-begin-card::after {
  content: '→'; position: absolute; right: 16px; top: 50%; transform: translate(-6px, -50%); opacity: 0;
  font: 700 1.2rem/1 var(--pt-ui); color: var(--gold-t); transition: opacity .2s ease, transform .2s ease;
}
.igra-begin-card:hover, .igra-begin-card:focus-visible {
  border-color: var(--gold); transform: translateY(-3px); outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 16%, transparent), 0 22px 40px -16px var(--pt-glow), var(--pt-shade), inset 0 1px 0 var(--pt-edge);
}
.igra-begin-card:hover::after, .igra-begin-card:focus-visible::after { opacity: 1; transform: translate(0, -50%); }
.igra-begin-card:active { transform: translateY(0) scale(.99); }
.igra-begin-ico {
  width: 46px; height: 46px; border-radius: 50%; display: grid; place-items: center; color: var(--on-gold, #1a1206); margin-bottom: 6px;
  background: radial-gradient(100% 80% at 50% 0%, rgba(255,255,255,.42), transparent 58%), linear-gradient(145deg, var(--gold-2), var(--gold));
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--gold) 16%, transparent), 0 10px 20px -8px var(--pt-glow), inset 0 -3px 5px rgba(0,0,0,.2);
}
.igra-begin-ico.alt { color: var(--gold-t); background: radial-gradient(100% 80% at 50% 0%, rgba(255,255,255,.12), transparent 60%), color-mix(in srgb, var(--gold) 14%, var(--surface-2)); border: 1px solid color-mix(in srgb, var(--gold) 55%, transparent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--gold) 8%, transparent), inset 0 1px 0 var(--pt-edge); }
/* подпись карточки — столбцом: имя над пояснением (на ПК спаны текли одной строкой) */
.igra-begin-txt { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.igra-begin-name { font-family: var(--pt-title); font-weight: var(--pt-title-weight); font-size: 1.12rem; line-height: 1.25; padding-right: 18px; }
.igra-begin-sub { font-size: .85rem; line-height: 1.45; color: var(--text-2); }
@media (max-width: 600px) {
  .igra-begin-grid { grid-template-columns: 1fr; gap: 10px; }
  .igra-begin-card { flex-direction: row; align-items: center; gap: 14px; padding: 14px 16px; }
  .igra-begin-ico { margin: 0; flex: none; width: 42px; height: 42px; }
  .igra-begin-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
  .igra-begin-card::after { display: none; }
}

/* Навигация игры: бургер + выдвижная панель (истинная боковая — от 1024px) */
.igra-nav-toggle { padding: 8px 10px; }
.igra-nav-backdrop {
  position: fixed; inset: 0; background: rgba(6,5,10,.6); z-index: 55;
  opacity: 0; pointer-events: none; transition: opacity .2s ease;
}
.igra-nav-backdrop.is-open { opacity: 1; pointer-events: auto; }
.igra-nav {
  position: fixed; top: 0; left: 0; height: 100vh; width: 272px; max-width: 84vw;
  /* var(--surface) задумана для панелей поверх фона страницы, а не поверх
     остального содержимого (после 28.09 она уже почти непрозрачная — см.
     js/themes.js, — но выдвижное меню всё равно лежит НАД текстом хода и
     карточками, z-index выше, и должно быть однозначно непрозрачным, а не
     «почти»). Свой непрозрачный градиент, как у бокового меню сайта
     (.drawer в assets/css/style.css), решает то же самое надёжнее. */
  background: linear-gradient(180deg, #14111f, #0e0c18); border-right: 1px solid var(--border-strong);
  z-index: 60; transform: translateX(-100%); transition: transform .2s ease;
  overflow-y: auto; padding-bottom: 16px; display: flex; flex-direction: column;
}
.igra-nav.is-open { transform: translateX(0); }
.igra-nav-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; border-bottom: 1px solid var(--border); margin-bottom: 8px;
}
.igra-nav-head .brand { font-size: 1.05rem; gap: 8px; }
.igra-nav-close { display: inline-flex; }
/* Пункты бокового меню. Всё на токенах темы (--gold/--gold-2/--text*/--border*/--radius-sm):
   подложка и полоса активного пункта берут акцент темы, форму задают переменные
   --nav-r/--nav-tile-r, которые themes.css переопределяет по темам. position не ставим
   ни на .igra-nav, ни на .igra-topbar (ломало макет, spisok п.25) — полоса делается
   inset-тенью, украшения — псевдоэлементами внутри пункта. */
.igra-nav-group { display: flex; flex-direction: column; gap: 3px; padding: 0 12px; margin-top: 12px; }
.igra-nav-label {
  display: flex; align-items: center; gap: 8px; margin: 0 4px 5px;
  font-size: .68rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--text-3);
}
.igra-nav-label::after { content: ''; flex: 1; height: 1px; background: var(--border-strong); }
.igra-nav-foot { margin-top: auto; padding-top: 12px; border-top: 1px solid var(--border-strong); }
.igra-nav-item {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 46px;
  text-align: left; padding: 5px 10px 5px 6px; color: var(--text); background: transparent;
  border: 1px solid transparent; border-radius: var(--nav-r, var(--radius-sm));
  font: inherit; font-size: .95rem; font-weight: 500; cursor: pointer; text-decoration: none;
  transition: background .16s ease, color .16s ease, border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.nav-ic {
  flex: none; width: 34px; height: 34px; display: grid; place-items: center;
  border-radius: var(--nav-tile-r, 10px); color: var(--text-2);
  background: color-mix(in srgb, var(--text) 6%, transparent); border: 1px solid var(--border-strong);
  transition: background .16s ease, color .16s ease, border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.igra-nav-item .ic { width: 20px; height: 20px; display: block; }
.nav-t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.igra-nav-item:hover {
  background: color-mix(in srgb, var(--gold) 12%, transparent); color: var(--text);
  transform: translateX(2px);
}
.igra-nav-item:hover .nav-ic {
  color: var(--gold-t); border-color: color-mix(in srgb, var(--gold-2) 55%, transparent);
  background: color-mix(in srgb, var(--gold) 16%, transparent);
}
.igra-nav-item:focus-visible, .igra-nav-account:focus-visible { outline: 2px solid var(--gold-2); outline-offset: 1px; }
.igra-nav-item.is-active, .igra-nav-item.is-active:hover {
  color: var(--text); font-weight: 600; transform: none;
  background: linear-gradient(90deg, color-mix(in srgb, var(--gold) 30%, transparent), color-mix(in srgb, var(--gold) 7%, transparent));
  border-color: color-mix(in srgb, var(--gold-2) 50%, transparent);
  box-shadow: inset 3px 0 0 var(--gold-2), 0 0 22px -8px var(--gold-2);
}
.igra-nav-item.is-active .nav-ic {
  color: #fff; border-color: transparent;
  background: linear-gradient(135deg, var(--gold-2), var(--gold));
  box-shadow: 0 0 14px -2px var(--gold-2);
}
.igra-nav-item.is-disabled, .igra-nav-item.is-disabled:hover {
  color: var(--text-3); cursor: default; background: transparent; transform: none; box-shadow: none;
}
.igra-nav-item.is-disabled .nav-ic { color: var(--text-3); background: transparent; border-style: dashed; border-color: var(--border-strong); }
.igra-nav-item .tag {
  flex: none; margin-left: auto; font-size: .6rem; letter-spacing: 0; padding: 1px 7px;
  border: 1px solid var(--border-strong); border-radius: 999px; color: var(--text-3); white-space: nowrap;
}
#navLogout { color: color-mix(in srgb, var(--rose) 30%, var(--text)); }
#navLogout .nav-ic { color: var(--rose); border-color: color-mix(in srgb, var(--rose) 35%, transparent); }
#navLogout:hover { background: color-mix(in srgb, var(--rose) 14%, transparent); }
#navLogout:hover .nav-ic { color: var(--rose); border-color: var(--rose); background: color-mix(in srgb, var(--rose) 16%, transparent); }
@media (prefers-reduced-motion: reduce) { .igra-nav-item, .nav-ic { transition: none; } .igra-nav-item:hover { transform: none; } }

/* Аватарка: картинка на месте, пока не пришла (или у игрока её нет) —
   буква имени в кружке того же размера, тот же вид, что у людей привычен
   по почте/мессенджерам */
.avatar-circle {
  flex: none; border-radius: 50%; overflow: hidden; background: var(--surface-2);
  border: 1px solid var(--border); display: grid; place-items: center;
  color: var(--text-2); font-weight: 700; font-family: var(--font-body, Inter, system-ui, sans-serif);
  line-height: 1; padding: 0; text-indent: 0; text-align: center;
  text-transform: uppercase; user-select: none;
}
.avatar-circle img { width: 100%; height: 100%; object-fit: cover; display: block; }
.igra-topbar-avatar { width: 32px; height: 32px; font-size: 14.4px; cursor: pointer; padding: 0; border: 1px solid var(--border); }
.igra-nav-account {
  display: flex; align-items: center; gap: 12px; align-self: stretch; margin: 4px 12px 2px; padding: 12px;
  border-radius: var(--nav-r, var(--radius-sm)); cursor: pointer; text-align: left; font: inherit; color: var(--text);
  border: 1px solid var(--border-strong);
  background: linear-gradient(135deg, color-mix(in srgb, var(--gold) 22%, transparent), color-mix(in srgb, var(--gold) 4%, transparent));
  transition: border-color .16s ease, box-shadow .16s ease;
}
.igra-nav-account:hover { border-color: var(--gold-2); box-shadow: 0 0 20px -8px var(--gold-2); }
.igra-nav-account:hover .nav-chev { color: var(--gold-t); transform: translateX(2px); }
.igra-nav-account .avatar-circle {
  width: 42px; height: 42px; font-size: 18.9px; border: 2px solid var(--gold-2);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 22%, transparent);
}
.nav-who { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.nav-who small { font-size: .66rem; letter-spacing: .12em; text-transform: uppercase; color: var(--text-3); font-weight: 700; }
.nav-who b { font-size: .9rem; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-chev { flex: none; width: 18px; height: 18px; color: var(--text-3); transition: color .16s ease, transform .16s ease; }
.cabinet-avatar-row { display: flex; align-items: center; gap: 16px; margin-bottom: 14px; }
.cabinet-avatar-row .avatar-circle { width: 72px; height: 72px; font-size: 32.4px; }
.cabinet-avatar-actions { display: flex; flex-direction: column; gap: 8px; flex: 1 1 0; min-width: 0; align-items: flex-start; }
/* 30.09: на 360 в «Экшене» (моноширинный капс) кнопки шире карточки: разрешаем перенос строки и сжатие до колонки */
.cabinet-avatar-actions .btn { max-width: 100%; white-space: normal; text-align: center; overflow-wrap: anywhere; line-height: 1.25; }

@media (min-width: 1024px) {
  .igra-nav-toggle, .igra-nav-close, .igra-nav-backdrop { display: none; }
  .igra-nav { transform: none; box-shadow: none; }
  /* .igra-nav — position:fixed (вне потока), поэтому margin-left сам по себе
     только СДВИГАЕТ topbar/main, а их width:100% по-прежнему считается от
     ширины body — без вычитания ширины бокового меню оба вылезают вправо на
     272px за край экрана (у .igra-shell.wide, 960px, это давало ~112px
     обрезанного правого края — Герои и Миры несли ту же поломку ДО раздела
     Таверна/Магазин, просто на них так широко ничего не смотрели).

     Отступ нужен, только пока меню вообще показано. app.js прячет и топбар,
     и .igra-nav разом атрибутом hidden (setTopbarVisible) — на экране входа
     до setTopbarVisible(true) меню нет вовсе, а этот отступ раньше всё равно
     сдвигал .igra-main, и экран входа оказывался смещён вправо примерно на
     половину отступа (центрирование считало центр от чужой, урезанной
     ширины). Держим #topbar:not([hidden]) как метку «меню сейчас показано»
     — самого топбара это не касается, у него и так display:none, пока он
     hidden. */
  #topbar:not([hidden]) { margin-left: 272px; width: calc(100% - 272px); }
  #topbar:not([hidden]) ~ .igra-main { margin-left: 272px; width: calc(100% - 272px); }
  /* На ПК боковое меню всегда на экране (строка выше) и уже несёт свою
     надпись «Игра» с логотипом (.igra-nav-head .brand) — та же надпись в
     верхней шапке была бы вторая подряд перед глазами. На телефоне меню
     скрыто за бургером, поэтому там марка в шапке остаётся единственной и
     этот блок её не трогает (media начинается с 1024px). */
  .igra-topbar .brand { display: none; }
}

/* Панель партий внутри игры (задание 29.09: «большая пустая область слева»
   на экране хода). Тот же материал и приём, что у .igra-nav (выезжающая
   панель, непрозрачный градиент, задвижка translateX) — но отдельный
   компонент, а не часть .igra-nav: тот общий для всех экранов и уже несёт
   свою мобильную логику (бургер сайта), плести туда ещё и партии значило бы
   путать два независимых выезжающих меню в одном narrow-контейнере. На ПК
   компонент просто встаёт правым соседом .igra-nav (left:272px) — на глаз
   это одна колонка «меню сверху, партии снизу», а по разметке — два места
   с одинаковым покроем. */
/* На телефоне это была ВТОРАЯ кнопка меню рядом с бургером ☰ в шапке
   (владелец 29.09: «два значка списка на одном экране») — обе открывали
   разные списки почти одного и того же (партии). Оставляем один вход:
   бургер шапки → пункт «Партии» (тот же renderChatList, что видит и эта
   панель). На ПК кнопка и так скрыта ниже (панель там — постоянная колонка). */
.igra-games-panel-toggle { display: none; }

.igra-games-panel-backdrop {
  position: fixed; inset: 0; background: rgba(6,5,10,.6); z-index: 55;
  opacity: 0; pointer-events: none; transition: opacity .2s ease;
}
.igra-games-panel-backdrop.is-open { opacity: 1; pointer-events: auto; }

.igra-games-panel {
  position: fixed; top: 0; left: 0; height: 100vh; width: 300px; max-width: 88vw;
  background: linear-gradient(180deg, #14111f, #0e0c18); border-right: 1px solid var(--border-strong);
  z-index: 58; transform: translateX(-100%); transition: transform .2s ease;
  overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 12px;
}
.igra-games-panel.is-open { transform: translateX(0); }
.igra-games-panel-head { display: flex; align-items: center; justify-content: space-between; }
.igra-games-panel-head h2 { margin: 0; }
.igra-games-panel-new { width: 100%; }

.igra-games-panel-list { display: flex; flex-direction: column; gap: 8px; overflow-y: auto; flex: 1; }
.igra-game-item {
  display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px; border-radius: 14px;
  border: 1px solid var(--border); cursor: pointer; text-align: left; width: 100%; background: none;
  color: var(--text); font: inherit;
}
.igra-game-item:hover { background: var(--surface-2); border-color: var(--border-strong); }
.igra-game-item.is-current { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 12%, transparent); }
.igra-game-item .txt { flex: 1; min-width: 0; }
.igra-game-item b { display: block; font-size: .95rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.igra-game-item span { display: block; font-size: .8rem; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 2px; }
.igra-game-item time { display: block; font-size: .72rem; color: var(--text-3); margin-top: 4px; }
.igra-game-item .del { flex: none; }

@media (min-width: 1024px) {
  .igra-games-panel-backdrop { display: none; }
  .igra-games-panel-close { display: none; }
  /* body.has-games-panel — выставляет app.js, пока открыт #screen-game.
     Без class-гейта панель сидела бы в разметке (position:fixed, вне потока)
     и была бы видна поверх остальных экранов (Кабинет, Миры…), хотя там ей
     не место — там «партии» уже есть отдельным пунктом меню. */
  body.has-games-panel .igra-games-panel {
    left: 272px; transform: none; box-shadow: none;
  }
  body.has-games-panel #topbar:not([hidden]) { margin-left: 572px; width: calc(100% - 572px); }
  body.has-games-panel #topbar:not([hidden]) ~ .igra-main { margin-left: 572px; width: calc(100% - 572px); }
  /* На ПК внутри партии рядом с .igra-nav встаёт вторая колонка — сам список
     партий (см. комментарий у .igra-games-panel выше). Пункт «Партии» в
     .igra-nav ведёт туда же (screen-list, тот же renderChatList) — пока
     колонка на экране, это дубль одного и того же списка (владелец 29.09:
     «Партии» дважды на экране). Вне игры (Герои/Миры/Кабинет) колонки нет,
     и пункт меню остаётся единственным путём к списку партий. */
  body.has-games-panel #navPartii { display: none; }
}

/* Список записей лора (общий список-стиль с «Партиями») */
.igra-lore-item {
  display: flex; align-items: center; gap: 14px; padding: 14px 16px;
  border-radius: 14px; border: 1px solid var(--border);
  cursor: pointer; text-align: left; width: 100%;
}
.igra-lore-item:hover { background: var(--surface-2); border-color: var(--border-strong); }
.igra-lore-item .txt { flex: 1; min-width: 0; }
.igra-lore-item b { display: block; font-size: 1rem; }
.igra-lore-item span { display: block; font-size: .85rem; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.igra-lore-item .del { flex: none; }

/* Карточки-«манагеры» (Герои/Миры) — те же .igra-pick, плюс кнопка удаления сверху */
.igra-manage-card { position: relative; }
.igra-manage-card .del {
  position: absolute; top: 6px; right: 6px; width: 28px; height: 28px; padding: 0;
  display: flex; align-items: center; justify-content: center; border-radius: 8px;
}

@media (max-width: 600px) {
  .igra-main { padding: 16px 16px 32px; }
  .igra-topbar { padding: 10px 12px; flex-wrap: wrap; row-gap: 8px; }
  .igra-topbar .brand span:last-child { display: none; }
  .igra-topbar-actions { gap: 6px; }
  .igra-ink { font-size: .78rem; }
  .igra-topbar-actions .btn-sm { padding: 8px 10px; font-size: .82rem; }
  .igra-title { font-size: 1.5rem; }
  .igra-turn-user { max-width: 90%; }
}

@media (prefers-reduced-motion: reduce) {
  .igra-caret { animation: none; }
  .igra-typing i { animation: none; opacity: .8; }
  .igra-turn-assistant, .igra-turn-user, .igra-turn-pending, .igra-begin, .igra-master-popover { animation: none; }
  .igra-turns > .igra-turn-assistant:last-child::after { animation: none; }
}

/* ── Темы оформления (js/themes.js) ──────────────────────────────────────
   Восемь сюжетных тем кладут растровый рендер (#theme-scene-render,
   <picture> с ПК/мобильным webp) поверх .sky. Раунд 3 (spisok.md п.4,
   находка Егора: «Розовое королевство» — плоский рисунок вместо 3D-замка)
   дал рендеру z-index:1 против z-index:0 у тогдашнего SVG-плейсхолдера —
   починило порядок относительно .sky, но не саму жалобу: SVG (fantasy.svg/
   cyberpunk.svg/pink_kingdom.svg) как был отдельным непрозрачным (opacity
   .5) на весь экран слоем НАД .sky, так и остался — просто теперь НИЖЕ
   рендера, а не выше. На 1280, где рендер уже загружен, его object-fit:cover
   не гарантирует, что каждый пиксель экрана закрашен непрозрачной частью
   картинки (кадр у webp меньше/иначе скадрирован, чем у SVG) — по краям
   сквозь рендер была видна часть SVG-силуэта. На 412 те же два слоя, вместе
   с decoding=async/loading=lazy у рендера, иногда давали окно, где снимок
   стенда успевал случиться ДО onload картинки — виден только SVG, и это и
   есть «плоский замок вместо 3D» из жалобы (a). Раунд 4 убрал SVG совсем
   (см. THEME_SCENES/mountScene в js/themes.js): пока webp не загрузился (js
   добавляет класс .is-loaded только из onload с реальным naturalWidth>0),
   под .theme-scrim/.sky виден сплошной var(--bg) той же темы — ни силуэта,
   ни постороннего рисунка, никогда одновременно с рендером. */
.theme-scene-render {
  position: fixed; inset: 0; width: 100%; height: 100%;
  display: block; pointer-events: none; z-index: 1;
}
.theme-scene-render img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center 30%;
  opacity: 0;
}
@media (prefers-reduced-motion: no-preference) { .theme-scene-render img { transition: opacity .35s ease; } }
.theme-scene-render.is-loaded img { opacity: 1; }
@media (max-width: 600px) {
  .theme-scene-render img { object-position: center 20%; }
}
/* Затемняющая/высветляющая подложка над задником сюжетной темы, под шапкой
   и содержимым. Красится в var(--bg) самой темы, а не в чёрный, — на тёмных
   темах затемняет, на светлой pink_kingdom (bg почти белый) высветляет, и
   в обоих случаях тянет задник к тому же тону, на который уже рассчитан
   контраст текста и панелей. Без неё сюжетные фоны (особенно webp-рендеры)
   спорили с текстом на экране входа и текстом хода мастера (см. итог
   проверки читаемости, F:\Android\otchet\temy\perenos.md). z-index:2 —
   заведомо выше рендера (см. комментарий выше), а не «следующий элемент в
   разметке». Непрозрачность — var(--scrim-opacity), своя у каждой сюжетной
   темы (js/themes.js): единое число «на глаз» (было .45) держалось на
   тёмных фонах, а на светлом pink_kingdom клало плотную вуаль поверх
   готового рендера — Раунд 4, жалоба владельца на «выцветший» замок. */
.theme-scrim {
  position: fixed; inset: 0; z-index: 2; pointer-events: none;
  background: var(--bg); opacity: var(--scrim-opacity, .45);
}
@media (prefers-reduced-motion: no-preference) { .theme-scrim { transition: background-color .2s ease, opacity .2s ease; } }

/* Источник «наслоения тем», которое поймал владелец на 412px (28.09, вторая
   переделка, и снова Раунд 3, spisok.md п.3): .igra-body .sky — это
   ОБЩЕСАЙТОВЫЙ статичный задник (строка ~11 выше — до Раунда 3 фото
   hero-desktop(.webp), теперь токены темы), вообще не знающий о теме игры.
   У сюжетных тем он не заменялся, а ложился ПОД их SVG/webp-сцену и
   .theme-scrim — сквозь полупрозрачные слои были видны одновременно ДВЕ
   картинки, и это выглядело как «осталась прошлая тема» (или, после Раунда 3
   без фото, — как задник, не закрывающий экран целиком, пока сцена
   догружается). Правка: где у темы есть собственная сцена (`THEME_SCENES` в
   js/themes.js — восемь тем с рендером из тринадцати), `.sky` гасится в
   сплошной var(--bg), дальше решает сама тема; у цветовых тем и у `crt`
   (Терминал — задника нет нарочно, см. THEME_SCENES) `.sky` остаётся
   единственным задником, поведение не меняется. */
[data-theme="fantasy"] .igra-body .sky,
[data-theme="cyberpunk"] .igra-body .sky,
[data-theme="pink_kingdom"] .igra-body .sky,
[data-theme="neo_action"] .igra-body .sky,
[data-theme="wasteland"] .igra-body .sky,
[data-theme="horror"] .igra-body .sky,
[data-theme="noir"] .igra-body .sky,
[data-theme="abyss"] .igra-body .sky {
  /* Не background-image: none — .sky это ОДНО правило `background:` с двумя
     слоями (градиент + фото), image:none снял бы и градиент, обнажив то,
     что за .sky (без объявленного фона). var(--bg) — тот же тон, что кладёт
     .theme-scrim поверх сцены темы, поэтому смена бесшовная. */
  background: var(--bg);
}

/* Текст мастера — самый долгочитаемый экран игры, поэтому у него своя
   непрозрачная подложка (var(--surface), см. js/themes.js — с 28.09 это уже
   ≥92% непрозрачности), а не голый текст поверх задника/подложки: даже с
   .theme-scrim пёстрый webp-рендер даёт локальные яркие/тёмные пятна, на
   которых фиксированный контраст не гарантирован. У пользовательской
   реплики (.igra-turn-user) такая же панель была и раньше. */
.igra-turn-assistant {
  border: 1px solid var(--pt-frame);
  border-radius: var(--pt-radius); padding: 42px 24px 24px; color: var(--text);
}
@media (max-width: 600px) { .igra-turn-assistant { padding: 40px 18px 22px; } }
/* ПК: колонка 720px — строка прозы выходила под 85 знаков; крупнее кегль и шире поля → ~70. */
@media (min-width: 1024px) { .igra-turn-assistant { font-size: calc(var(--pt-prose-size) * 1.07); padding: 44px 34px 28px; } }
[data-theme="pink_kingdom"] .igra-field input, [data-theme="pink_kingdom"] .igra-field textarea,
[data-theme="pink_kingdom"] .igra-field select, [data-theme="pink_kingdom"] .igra-shell input,
[data-theme="pink_kingdom"] .igra-shell textarea, [data-theme="pink_kingdom"] .igra-shell select {
  background: rgba(240,72,154,.06); color: var(--text);
}

/* ── Полный перекрас интерфейса по темам (перенос из F:\rpg_studio_tablet\ui.html) ──
   Раньше тема меняла только фон-задник и палитру CSS-переменных (--bg/--gold/…),
   а карточки мастера, пузыри игрока, кнопка отправки, поле ввода и шапка/меню
   везде рисовались одинаково. Настольная версия красит под тему ещё и форму:
   шрифт заголовков/хода мастера (там --acc/--t0 плюс код на data-theme=X режет
   форму кнопок и рамки — ui.html:785-980), у некоторых тем — обводку карточки
   (fantasy: ::before/::after у #entity-card, ui.html:492-500). Здесь то же самое
   через существующие --font-display/var(--radius) и точечные правила по
   [data-theme] — без WebGL и без переснятых картинок, только CSS. Четыре
   цветовые темы (dark_purple/blue/green/amber) в исходнике тоже без формы —
   только палитра, это не пропуск, а то же самое отличие «сюжетная/цветовая»,
   что в ui.html (родные THEMES там тоже не размечают data-theme для них). */

/* «Летопись» (fantasy) — тёмное дерево, пергамент, золото: сдвоенная рамка
   карточек (ui.html:492-500 рисует ::before/::after у карточки такой же
   парой линий), ход мастера — засечками с воздухом, как разворот книги. */
[data-theme="fantasy"] { --font-display: 'Playfair Display', 'Cormorant Garamond', 'Georgia', serif; }
[data-theme="fantasy"] .igra-card, [data-theme="fantasy"] .igra-start-card {
  border: 2px solid var(--border-strong);
  box-shadow: inset 0 0 0 2px #241a0c, inset 0 0 0 3px rgba(224,173,63,.35), 0 6px 18px rgba(0,0,0,.3);
}
/* пузыри партии этой темы — themes.css, раздел «Экран партии» (30.09) */
[data-theme="fantasy"] .igra-send-btn {
  border-radius: 50%; box-shadow: 0 0 0 3px rgba(201,150,46,.18), 0 8px 22px rgba(0,0,0,.35);
}
/* Шапка/меню — золотая линия-рамка снизу/справа (border-image, перенос
   ui.html:945-948: там та же лента "прозрачный→золото→прозрачный") —
   вместо плоской тёмной плашки, которую легко спутать с нуаром/тишиной. */
[data-theme="fantasy"] .igra-topbar {
  background: linear-gradient(180deg, #221a0e, #1a140c);
  border-bottom: 1px solid transparent;
  border-image: linear-gradient(90deg, transparent, #8a621c 20%, #e0ad3f 50%, #8a621c 80%, transparent) 1;
}
[data-theme="fantasy"] .igra-nav, [data-theme="fantasy"] .igra-games-panel { background: linear-gradient(180deg, #191309, #150f08); border-right-color: #4a3c24; }
[data-theme="fantasy"] .igra-nav-item:hover, [data-theme="fantasy"] .igra-game-item:hover { background: #241c10; }

/* «Киберпанк» (cyberpunk) — холодная ночь, циан + всплеск мадженты:
   неоновое свечение на кнопке/рамках (ui.html:851-908 — box-shadow с тем же
   циановым тоном), заголовок/ход мастера — геометрический дисплейный шрифт. */
[data-theme="cyberpunk"] { --font-display: 'Orbitron', 'Inter', sans-serif; }
[data-theme="cyberpunk"] .igra-card, [data-theme="cyberpunk"] .igra-start-card {
  box-shadow: 0 0 0 1px rgba(0,200,240,.22), 0 0 18px rgba(0,200,240,.08);
}
[data-theme="cyberpunk"] .igra-field input, [data-theme="cyberpunk"] .igra-field textarea,
[data-theme="cyberpunk"] .igra-field select, [data-theme="cyberpunk"] .igra-shell input,
[data-theme="cyberpunk"] .igra-shell textarea, [data-theme="cyberpunk"] .igra-shell select,
[data-theme="cyberpunk"] .igra-turn-input {
  background: rgba(0,200,240,.05); border-color: rgba(0,200,240,.35);
}
[data-theme="cyberpunk"] .igra-field input:focus, [data-theme="cyberpunk"] .igra-field textarea:focus,
[data-theme="cyberpunk"] .igra-turn-input:focus {
  border-color: var(--gold); box-shadow: 0 0 0 2px rgba(0,200,240,.25);
}
[data-theme="cyberpunk"] .igra-send-btn { box-shadow: 0 0 18px rgba(0,200,240,.55), inset 0 1px 0 rgba(255,255,255,.35); }
[data-theme="cyberpunk"] .igra-topbar {
  background: rgba(6,10,18,.92);
  border-bottom: 1px solid transparent;
  border-image: linear-gradient(90deg, rgba(63,224,255,.7), rgba(63,224,255,.08) 40%, rgba(63,224,255,.08) 60%, rgba(63,224,255,.7)) 1;
}
[data-theme="cyberpunk"] .igra-nav, [data-theme="cyberpunk"] .igra-games-panel { background: #060a12; }
/* Срезанный угол (перенос ui.html:1000+ clip-path у #chat-empty h2) —
   у сюжетной карточки самой, не только у пустого экрана: узнаваемый
   «чип» без круглых углов, которых в теме нет нигде. */
[data-theme="cyberpunk"] .igra-card, [data-theme="cyberpunk"] .igra-start-card {
  clip-path: polygon(14px 0, 100% 0, 100% 100%, 0 100%, 0 14px);
}

/* «Розовое королевство» (pink_kingdom) — светлая, зефирная: мягче скругления
   (уже даёт var(--radius) выше), пастельный градиент карточек, лёгкий
   шрифт-заголовок вместо тяжёлой антиквы (ui.html:796-845 — форма кнопок и
   рамки на розовом фоне мягче обычных, никаких острых углов вовсе). */
[data-theme="pink_kingdom"] { --font-display: 'Quicksand', 'Inter', sans-serif; }
[data-theme="pink_kingdom"] .igra-card, [data-theme="pink_kingdom"] .igra-start-card {
  background: linear-gradient(180deg, #ffffff, #ffeaf3);
}
/* пузыри партии этой темы — themes.css, раздел «Экран партии» (30.09) */
[data-theme="pink_kingdom"] .igra-send-btn { box-shadow: 0 8px 20px rgba(240,72,154,.35), inset 0 1px 0 rgba(255,255,255,.5); }
[data-theme="pink_kingdom"] .igra-topbar { background: rgba(255,245,249,.86); }
[data-theme="pink_kingdom"] .igra-nav, [data-theme="pink_kingdom"] .igra-games-panel { background: linear-gradient(180deg,#fff5f9,#ffeaf3); border-right-color: var(--border); }
[data-theme="pink_kingdom"] .igra-nav-item:hover, [data-theme="pink_kingdom"] .igra-chat-item:hover, [data-theme="pink_kingdom"] .igra-game-item:hover { background: #ffeaf3; }

/* «Экшен» (neo_action) — графит и электрический след: срезанные углы вместо
   скруглений (ui.html держит --r-lg маленьким у этой темы и рубит форму
   кнопок), шрифт заголовков — плотный гротеск в духе консольного HUD. */
[data-theme="neo_action"] { --font-display: 'Oswald', 'Inter', sans-serif; }
[data-theme="neo_action"] .igra-card, [data-theme="neo_action"] .igra-start-card {
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%);
}
/* пузыри партии этой темы — themes.css, раздел «Экран партии» (30.09) */
/* Уголки-скобки на кнопке отправки — перенос ui.html:965-984 (::before/
   ::after у #sendbtn, тот же HUD-приём: не рамка целиком, а засечки по
   двум углам, как прицел). */
[data-theme="neo_action"] .igra-send-btn {
  border-radius: 8px; box-shadow: 0 0 14px rgba(0,217,110,.45); position: relative; overflow: visible;
}
[data-theme="neo_action"] .igra-send-btn::before, [data-theme="neo_action"] .igra-send-btn::after {
  content: ''; position: absolute; width: 10px; height: 10px; pointer-events: none;
}
[data-theme="neo_action"] .igra-send-btn::before {
  top: -4px; left: -4px; border-top: 2px solid #3dff9c; border-left: 2px solid #3dff9c;
}
[data-theme="neo_action"] .igra-send-btn::after {
  bottom: -4px; right: -4px; border-bottom: 2px solid #3dff9c; border-right: 2px solid #3dff9c;
}
[data-theme="neo_action"] .igra-topbar {
  background: #080a0c; border-bottom: 1px solid transparent;
  border-image: linear-gradient(90deg, rgba(0,217,110,.7), rgba(0,217,110,.08) 40%, rgba(0,217,110,.08) 60%, rgba(0,217,110,.7)) 1;
}
[data-theme="neo_action"] .igra-nav, [data-theme="neo_action"] .igra-games-panel { background: #070910; border-right-color: rgba(0,217,110,.3); }

/* «Пустошь» (wasteland) — ржавое железо, пыль: рубленые края (radius уже
   мал в палитре), пунктирная «сварная» рамка карточек, машинописный шрифт
   заголовка — как обрывок радиолога, а не книжная антиква. */
[data-theme="wasteland"] { --font-display: 'Special Elite', 'Georgia', serif; }
[data-theme="wasteland"] .igra-card, [data-theme="wasteland"] .igra-start-card {
  border: 2px dashed var(--border-strong);
}
/* пузыри партии этой темы — themes.css, раздел «Экран партии» (30.09) */
[data-theme="wasteland"] .igra-send-btn { border-radius: 4px; box-shadow: 0 0 0 2px rgba(194,112,58,.3); }
/* Ржавые потёки на стыке шапки (перенос ui.html:10541-10567: неровные
   диагональные полосы через repeating-linear-gradient — тема просит
   фактуры, "ровный градиент читался бы просто как цвет", их же слова). */
[data-theme="wasteland"] .igra-topbar {
  background: #1c160c; border-bottom: 3px solid transparent;
}
[data-theme="wasteland"] .igra-topbar::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -3px; height: 3px; pointer-events: none;
  background: rgba(150,72,26,.55);
}
[data-theme="wasteland"] .igra-nav, [data-theme="wasteland"] .igra-games-panel { background: #17130b; border-right-color: #3d3324; }

/* «Тишина» (horror) — холод, обесцвеченность, клинические углы: острые
   прямые края (radius уже 3-4px в палитре), разрядка/капитель у названий —
   клинический протокол, а не тёплая книжная надпись. */
[data-theme="horror"] .igra-title, [data-theme="horror"] .igra-nav-item,
[data-theme="horror"] .igra-topbar .brand span:last-child {
  letter-spacing: .04em;
}
/* Ничего тёплого и ничего скруглённого: ни свечения, ни градиента на
   рамке (в отличие от fantasy/wasteland/abyss) — «клинический протокол»
   держится на голом контрасте, это и есть его отличие от соседей по
   тёмной палитре. filter: grayscale чуть гасит цвет самого текста/рамок,
   не трогая фон/задник — картинка коридора/палаты остаётся цветной. */
[data-theme="horror"] .igra-card, [data-theme="horror"] .igra-start-card {
  border-width: 1px; border-radius: 2px; box-shadow: none; filter: saturate(.7);
}
/* пузыри партии этой темы — themes.css, раздел «Экран партии» (30.09) */
[data-theme="horror"] .igra-send-btn { border-radius: 2px; box-shadow: none; }
[data-theme="horror"] .igra-topbar {
  background: #0c1211; border-bottom: 1px solid var(--border-strong);
}
[data-theme="horror"] .igra-nav, [data-theme="horror"] .igra-games-panel { background: #0a0e0d; border-right: 1px solid var(--border-strong); }
[data-theme="horror"] .igra-nav-item:hover, [data-theme="horror"] .igra-chat-item:hover, [data-theme="horror"] .igra-game-item:hover { background: #10201d; }

/* «Нуар» (noir) — монохром и один тёплый фонарь: узкие жалюзи-полосы в
   подложке шапки/меню (ui.html держит нуар почти без формы — три правила —
   тон и один акцент важнее декора), тёплое свечение только на кнопке
   отправки — «фонарь» в чёрно-белом кадре. */
[data-theme="noir"] .igra-topbar, [data-theme="noir"] .igra-nav, [data-theme="noir"] .igra-games-panel {
  background: #0b0b0c;
}
[data-theme="noir"] .igra-send-btn { box-shadow: 0 0 16px rgba(217,164,65,.5), inset 0 1px 0 rgba(255,255,255,.35); }
/* пузыри партии этой темы — themes.css, раздел «Экран партии» (30.09) */
/* «Один тёплый фонарь»: единственный цветной штрих в монохромной теме —
   тёплая полоска слева на реплике мастера, как край света от лампы под
   абажуром, остальная рамка нейтрально-серая. */
[data-theme="noir"] .igra-card, [data-theme="noir"] .igra-start-card {
  border-width: 1px 1px 1px 3px; border-left-color: var(--gold);
}

/* «Бездна» (abyss) — глубокая вода, свет живых существ: мягкое голубое
   свечение карточек (как биолюминесценция), плавные скругления (radius уже
   выше среднего), спокойная пульсация выключена при prefers-reduced-motion. */
[data-theme="abyss"] .igra-card, [data-theme="abyss"] .igra-start-card {
  border-width: 1px; border-color: rgba(43,179,200,.4);
  box-shadow: 0 0 26px rgba(43,179,200,.22), inset 0 0 0 1px rgba(79,216,232,.18);
  animation: abyss-glow 4.5s ease-in-out infinite;
}
@keyframes abyss-glow {
  0%, 100% { box-shadow: 0 0 26px rgba(43,179,200,.22), inset 0 0 0 1px rgba(79,216,232,.18); }
  50% { box-shadow: 0 0 34px rgba(43,179,200,.36), inset 0 0 0 1px rgba(79,216,232,.3); }
}
@media (prefers-reduced-motion: reduce) {
  [data-theme="abyss"] .igra-card, [data-theme="abyss"] .igra-start-card { animation: none; }
}
[data-theme="abyss"] .igra-send-btn { box-shadow: 0 0 20px rgba(43,179,200,.55); }
[data-theme="abyss"] .igra-topbar { background: rgba(4,8,15,.9); border-bottom-color: rgba(43,179,200,.3); }
[data-theme="abyss"] .igra-nav, [data-theme="abyss"] .igra-games-panel { background: #04080f; border-right-color: rgba(43,179,200,.25); }

/* «Терминал» (crt) — экран ЭЛТ вплотную: единственная тема без задника
   вовсе (js/themes.js THEME_SCENES) — вся тема в фактуре, а не в картинке.
   Развёртка — CSS-повтор поверх .igra-main (не картинка, не WebGL, чистый
   градиент), весь текст на люминофорном моноширинном шрифте, острые края
   (radius уже 2-3px в палитре). Развёртка выключена при
   prefers-reduced-motion — мерцающий узор поверх текста хода мешает читать
   тем, кто просил меньше движения. */
[data-theme="crt"] { --font-display: 'VT323', 'Consolas', monospace; --font-body: 'VT323', 'Consolas', monospace; }
[data-theme="crt"] .igra-nav-item, [data-theme="crt"] .igra-game-item, [data-theme="crt"] button,
[data-theme="crt"] .igra-field input, [data-theme="crt"] .igra-field textarea, [data-theme="crt"] .igra-field select {
  font-family: 'VT323', 'Consolas', monospace; letter-spacing: .02em;
}
[data-theme="crt"] .igra-card, [data-theme="crt"] .igra-start-card {
  border-radius: 2px; box-shadow: inset 0 0 0 1px rgba(34,224,92,.25);
}
[data-theme="crt"] .igra-main {
  position: relative;
}
[data-theme="crt"] .igra-main::before {
  content: ''; position: fixed; inset: 0; z-index: 1; pointer-events: none;
  background: repeating-linear-gradient(180deg, rgba(0,0,0,0) 0px, rgba(0,0,0,0) 2px, rgba(0,0,0,.12) 3px);
  mix-blend-mode: multiply;
}
@media (prefers-reduced-motion: reduce) {
  [data-theme="crt"] .igra-main::before { display: none; }
}
[data-theme="crt"] .igra-send-btn { border-radius: 2px; box-shadow: 0 0 12px rgba(34,224,92,.6); }
[data-theme="crt"] .igra-topbar, [data-theme="crt"] .igra-nav, [data-theme="crt"] .igra-games-panel { background: #020604; }

/* Переключатель темы (кабинет /igra/): сетка превью-карточек */
.theme-picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 10px; }
.theme-swatch {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  padding: 12px; border-radius: 14px; border: 1px solid var(--border);
  background: var(--surface); cursor: pointer; text-align: left; font: inherit; color: var(--text);
}
.theme-swatch:hover { border-color: var(--border-strong); }
.theme-swatch.is-selected { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold); }
.theme-swatch .dot { width: 100%; height: 34px; border-radius: 10px; }
.theme-swatch .name { font-size: .88rem; }
.theme-sound-row { display: flex; align-items: center; gap: 10px; margin-top: 14px; font-size: .9rem; color: var(--text-2); }

@media (prefers-reduced-motion: reduce) {
  .theme-scene-render img { transition: none; }
  .theme-scrim { transition: none; }
}

/* ===================================================================
   ПУСТЫЕ СОСТОЯНИЯ (правки 29.09, пачка 2). Только общие токены темы —
   --bg / --text / --text-2 / --gold / --border-strong. Нет ни одного
   [data-theme=...] правила: цвета сами подстраиваются под все темы.
   Подложка непрозрачная (смесь фона темы и золота), чтобы текст не
   сливался с рисунком экрана (было: розовая тема, замок под текстом).
   =================================================================== */
.igra-empty-card, .igra-shell .tv-notice {
  grid-column: 1 / -1; display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center;
  padding: clamp(28px, 5vw, 48px) 20px; border-radius: var(--radius, 18px);
  border: 2px dashed color-mix(in srgb, var(--gold) 65%, var(--bg));
  background: color-mix(in srgb, var(--bg) 88%, var(--gold) 12%);
  color: var(--text);
}
.igra-empty-ic {
  display: grid; place-items: center; width: 60px; height: 60px; border-radius: 50%;
  color: var(--gold-t); background: color-mix(in srgb, var(--bg) 78%, var(--gold) 22%);
  border: 1px solid color-mix(in srgb, var(--gold) 55%, var(--bg));
}
.igra-empty-title, .igra-shell .tv-notice-title { margin: 0; font-family: var(--font-display); font-size: 1.3rem; font-weight: 700; color: var(--text); }
.igra-empty-text, .igra-shell .tv-notice-text { margin: 0; max-width: 46ch; color: var(--text); font-size: .95rem; line-height: 1.5; }
.igra-empty-card .btn { margin-top: 6px; }
#magazinBalance:empty { display: none; }
/* Вход: «Войти по паролю» — заметная второстепенная кнопка */
.igra-alt-link {
  display: inline-flex; align-items: center; justify-content: center; min-height: 46px; padding: 10px 22px;
  font-size: 1rem; font-weight: 700; color: var(--gold-t); border: 2px solid var(--gold); background: color-mix(in srgb, var(--bg) 92%, var(--gold) 8%);
  border-radius: 12px; text-decoration: none;
}
.igra-alt-link:hover { background: color-mix(in srgb, var(--bg) 82%, var(--gold) 18%); }
/* Вход: «Отправить код ещё раз» с отсчётом (resend.js) */
.igra-resend-note { margin: 0 0 12px; color: var(--text-2); overflow-wrap: anywhere; }
.igra-resend-note b { color: var(--text); font-weight: 700; }
.igra-resend-row { margin: 14px 0 0; }
.igra-resend {
  min-height: 44px; padding: 8px 4px; border: 0; background: transparent; font: inherit; font-size: .95rem; font-weight: 700;
  color: var(--gold-t); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; text-align: left; max-width: 100%;
}
.igra-resend:disabled { color: var(--text-2); text-decoration: none; cursor: default; opacity: 1; }
.igra-resend:not(:disabled):hover { text-decoration-thickness: 2px; }

/* ===================================================================
   ГЕРОИ И NPC (29.09). Экран «Герои» — два параллельных столбца на ПК
   (≥1024), две вкладки на телефоне. Только токены темы, без [data-theme].
   Столбцы делят ширину .igra-shell.wide; справа от неё на ≥1181 лежит
   колонка сцены (padding-right у .igra-main), поэтому сами столбцы
   узкие и карточки в них — по одной в ряд.
   =================================================================== */
.igra-count {
  display: inline-block; min-width: 1.6em; padding: 1px 8px; margin-left: 6px; border-radius: 999px;
  font-size: .78rem; font-weight: 700; line-height: 1.5; text-align: center; vertical-align: middle;
  color: var(--text); background: color-mix(in srgb, var(--bg) 80%, var(--gold) 20%);
  border: 1px solid color-mix(in srgb, var(--gold) 45%, var(--bg));
}
.igra-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; align-items: start; }
.igra-col { min-width: 0; }
.igra-col-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; min-height: 40px; }
.igra-col-title { margin: 0; font-family: var(--font-display); font-size: 1.2rem; font-weight: 700; color: var(--text); }
.igra-col-cards { grid-template-columns: minmax(0, 1fr); }
.igra-chartabs { display: none; }

.igra-typebadge {
  display: inline-flex; align-items: center; gap: 5px; margin-bottom: 8px; padding: 2px 9px 2px 7px;
  border-radius: 999px; font-style: normal; font-size: .72rem; font-weight: 700; letter-spacing: .3px;
  color: var(--text); border: 1px solid color-mix(in srgb, var(--gold) 50%, var(--bg));
  background: color-mix(in srgb, var(--bg) 82%, var(--gold) 18%);
}
.igra-pick.is-npc .igra-typebadge {
  border-color: color-mix(in srgb, var(--text-2) 55%, var(--bg));
  background: color-mix(in srgb, var(--bg) 84%, var(--text-2) 16%);
}
.igra-pick.is-hero { border-left: 3px solid color-mix(in srgb, var(--gold) 80%, var(--bg)); }
.igra-pick.is-npc { border-left: 3px dashed color-mix(in srgb, var(--text-2) 70%, var(--bg)); }
.igra-manage-card .igra-typebadge { display: inline-flex; }
.igra-pick[aria-pressed="true"]::after { content: "\2713"; float: right; color: var(--gold-t); font-weight: 700; }

@media (max-width: 1023px) {
  .igra-chartabs { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 16px; padding: 4px; border-radius: 14px;
    border: 1px solid var(--border-strong); background: color-mix(in srgb, var(--bg) 88%, var(--text) 12%); }
  .igra-chartab { min-height: 44px; padding: 8px 12px; border: 0; border-radius: 10px; cursor: pointer;
    font: inherit; font-weight: 700; color: var(--text-2); background: transparent; }
  .igra-chartab.is-active { color: var(--text); background: color-mix(in srgb, var(--bg) 70%, var(--gold) 30%);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--gold) 60%, var(--bg)); }
  .igra-cols { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .igra-cols[data-active="heroes"] #colNpcs, .igra-cols[data-active="npcs"] #colHeroes { display: none; }
  .igra-col-head { justify-content: flex-end; }
  .igra-col-title { display: none; }
}

/* Форма героя / NPC: обложка-квадрат слева, имя и тип справа (образец — ui.html настольной версии) */
.igra-charform-top { display: flex; gap: 20px; align-items: flex-start; margin-bottom: 4px; }
.igra-charform-main { flex: 1; min-width: 0; }
.igra-charform-cover {
  flex: none; width: 132px; height: 132px; border-radius: 18px; display: grid; place-items: center;
  font-family: var(--font-display); font-size: 3rem; font-weight: 700; line-height: 1; color: var(--gold-t);
  background: color-mix(in srgb, var(--bg) 84%, var(--gold) 16%);
  border: 2px dashed color-mix(in srgb, var(--gold) 55%, var(--bg));
}
.igra-charform-cover[data-type="npcs"] { color: var(--text-2); border-color: color-mix(in srgb, var(--text-2) 55%, var(--bg)); background: color-mix(in srgb, var(--bg) 88%, var(--text-2) 12%); }
.igra-charform-cover[data-type="worlds"] { border-radius: 14px; }
/* Обложка: квадрат стал кнопкой (выбор файла), картинка ложится поверх буквы */
button.igra-charform-cover { position: relative; overflow: hidden; padding: 0; margin: 0; cursor: pointer; appearance: none; -webkit-appearance: none; }
button.igra-charform-cover:hover, button.igra-charform-cover:focus-visible { border-color: var(--gold); }
button.igra-charform-cover:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
button.igra-charform-cover.has-image { border-style: solid; }
.igra-charform-cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.igra-charform-cover img[hidden], .igra-charform-cover span[hidden] { display: none; }
.igra-charform-coverbox { flex: none; width: 132px; display: flex; flex-direction: column; gap: 8px; }
.igra-cover-actions { display: flex; flex-direction: column; gap: 6px; }
.igra-cover-actions .btn { width: 100%; justify-content: center; white-space: normal; text-align: center; }
.igra-backlink { margin: 0 0 12px; }
/* Миниатюра обложки в карточке списка */
.igra-manage-card.has-cover { padding-left: 84px; min-height: 84px; }
.igra-manage-card .igra-cover-thumb {
  position: absolute; left: 14px; top: 14px; width: 56px; height: 56px; border-radius: 12px; object-fit: cover;
  border: 1px solid var(--border-strong);
}
.igra-typeswitch { display: flex; gap: 8px; flex-wrap: wrap; }
.igra-typeopt {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 8px 16px; border-radius: 999px; cursor: pointer;
  font: inherit; font-weight: 600; color: var(--text-2); background: transparent; border: 1px solid var(--border-strong);
}
.igra-typeopt:hover { color: var(--text); border-color: var(--gold); }
.igra-typeopt.is-active { color: var(--text); background: color-mix(in srgb, var(--bg) 70%, var(--gold) 30%); border-color: var(--gold); }
@media (max-width: 520px) {
  .igra-charform-top { flex-direction: column; }
  .igra-charform-cover { width: 96px; height: 96px; font-size: 2.2rem; }
  .igra-charform-coverbox { width: 100%; flex-direction: row; align-items: center; gap: 14px; }
  .igra-cover-actions { flex: 1; min-width: 0; }
}

/* ── Формы: флажки, радиокнопки и тумблеры (29.09) ──────────────────────────
   Общее правило `.igra-shell input` (ширина 100%, поля, фон) годится для текстовых полей и
   ломало флажки: квадратик прижимался влево, подпись съезжала в узкую колонку. */
.igra-shell input[type="checkbox"], .igra-shell input[type="radio"] {
  width: auto; padding: 0; background: transparent; border-radius: 4px; flex: none;
}
.theme-sound-row { display: block; margin-top: 16px; }
.igra-switch { display: flex; align-items: center; gap: 12px; cursor: pointer; text-align: left; color: var(--text); font-size: .92rem; line-height: 1.35; }
.igra-switch input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.igra-switch-track {
  position: relative; flex: none; width: 46px; height: 26px; border-radius: 999px;
  background: color-mix(in srgb, var(--text) 14%, var(--bg)); border: 1px solid var(--border-strong);
  transition: background .16s ease, border-color .16s ease;
}
.igra-switch-track::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; border-radius: 50%;
  background: var(--text-2); transition: transform .16s ease, background .16s ease;
}
.igra-switch input:checked + .igra-switch-track { background: color-mix(in srgb, var(--gold) 55%, var(--bg)); border-color: var(--gold-2); }
.igra-switch input:checked + .igra-switch-track::after { transform: translateX(20px); background: #fff; }
.igra-switch input:focus-visible + .igra-switch-track { outline: 2px solid var(--gold-2); outline-offset: 2px; }
.igra-switch-text { flex: 1; min-width: 0; }
@media (prefers-reduced-motion: reduce) { .igra-switch-track, .igra-switch-track::after { transition: none; } }

/* Пункты меню «Картинки» (в разработке) и «Выйти» — читаемые, не блёклые */
.igra-nav-item.is-disabled { color: var(--text-2); }
.igra-nav-item.is-disabled .nav-ic { color: var(--text-2); border-color: var(--text-3); }
.igra-nav-item .tag { color: var(--text-2); border-color: var(--text-3); }
#navLogout { color: var(--text); }
#navLogout .nav-ic { color: color-mix(in srgb, var(--rose) 60%, var(--text)); border-color: color-mix(in srgb, var(--rose) 60%, transparent); }
.igra-hint { color: var(--text-2); }

/* 29.09: подсказки в полях — читаемые (браузерный серый давал 3:1 на тёмных подложках) */
.igra-shell input::placeholder, .igra-shell textarea::placeholder { color: var(--text-2); opacity: 1; }
.igra-shell .tv-subnav { background: color-mix(in srgb, var(--bg) 82%, var(--text) 18%); }
/* 30.09: вкладки Таверны читаются во всех 13 темах (замер по пикселям: было 2,1-4,5, стало не ниже 4,5).
   Подпись — основным цветом темы, активная — не сплошной заливкой (белёсый текст на розовом давал 2,1:1),
   а тонированной таблеткой с рамкой цвета кнопки темы. Только внутри игры: /taverna/ не затронута. */
.igra-shell .tv-subnav a { color: var(--text); font-weight: 600; }
.igra-shell .tv-subnav a.is-active { color: var(--text); font-weight: 700; background: color-mix(in srgb, var(--btn-b, var(--gold)) 24%, var(--bg)); box-shadow: inset 0 0 0 1.5px var(--btn-b, var(--gold)); }

/* Шаблоны миров («быстрый старт»): обложка жанра с главной, затемнение снизу,
   название, жанр, завязка и заметная кнопка. Текст поверх картинки всегда светлый
   на тёмной подложке — не зависит от темы, поэтому читается во всех 13 (затемнение только под текстом, верх картинки в полной яркости; читаемость
   держат подложка .8-.9 и тень текста). */
.igra-shab-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); gap: 14px; }
.igra-shab {
  position: relative; display: flex; align-items: flex-end; min-height: 360px;
  border-radius: 14px; overflow: hidden; border: 1px solid var(--border);
  background: #0b0a12; isolation: isolate; 
}
.igra-shab-art, .igra-shab-art img { position: absolute; inset: 0; width: 100%; height: 100%; }
.igra-shab-art img { object-fit: cover; transition: transform .8s ease; filter: brightness(calc(1 / (1 - var(--scrim-opacity, 0)))); }  /* .igra-main (z1) лежит под .theme-scrim (z2, фон темы с --scrim-opacity): без поправки вуаль притушала обложку на 25-30% */
.igra-shab:hover .igra-shab-art img { transform: scale(1.05); }
.igra-shab-body {
  position: relative; z-index: 1; width: 100%; display: flex; flex-direction: column; align-items: flex-start;
  padding: 40px 16px 16px; color: #f4efe6;
  background: linear-gradient(180deg, rgba(8,7,14,0) 0, rgba(8,7,14,.88) 44px, rgba(8,7,14,.95) 100%);
}
.igra-shab-kicker { text-shadow: 0 1px 3px rgba(0,0,0,.9); font-size: .74rem; letter-spacing: .08em; text-transform: uppercase; font-weight: 700; color: #f2c98a; }
.igra-shab-name { text-shadow: 0 1px 4px rgba(0,0,0,.9); margin: 4px 0 6px; font-family: var(--font-display); font-size: 1.35rem; line-height: 1.2; font-weight: 700; color: #fff; }
.igra-shab-hook {
  margin: 0 0 14px; font-size: .9rem; line-height: 1.4; color: #f1edf6; text-shadow: 0 1px 3px rgba(0,0,0,.9);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.igra-shab-take { align-self: flex-end; min-width: 132px; }
.igra-shab-take:disabled { opacity: .85; cursor: default; filter: saturate(.6); }
/* CRT: у общей кнопки тёмно-зелёный конец градиента даёт 3.5:1 — здесь светлее, чтобы текст держал 4.5:1 */
html[data-theme="crt"] .igra-shab .igra-shab-take { background: linear-gradient(135deg, #4cf27e, #22e05c); }
/* Измерено по пикселям под текстом кнопки: у pink_kingdom было 3.21, у abyss 4.15 — здесь фон подправлен до 4.5+ */
html[data-theme="pink_kingdom"] .igra-shab .igra-shab-take { background: linear-gradient(180deg, #a3155b, #870f4a); }
html[data-theme="pink_kingdom"] .igra-shab .igra-shab-take::before { opacity: .35; }
html[data-theme="abyss"] .igra-shab .igra-shab-take { background: linear-gradient(135deg, #a8f1f8, #ddd6ff) !important; }

/* ── Список выбора на «Новой партии» (picker.js) ───────────────────────────
   Свёрнутое поле — одна строка высотой с обычный input; открытый список
   лежит в <body> (fixed) и на ≤700px выезжает панелью снизу. */
.igra-pickcard { margin-bottom: 16px; }
.igra-pickcard .igra-pick-h { margin: 0 0 8px; }
.igra-pickcard .igra-pick-h:not(:first-child) { margin-top: 20px; }
.igra-pickcard .igra-pick-hint { margin: 0 0 8px; font-size: .82rem; line-height: 1.4; color: var(--text-2); }
.igra-pick-none { margin: 0 0 8px; color: var(--text-2); }
.cb { position: relative; }
.cb-field {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 48px; text-align: left;
  padding: 8px 12px 8px 14px; border-radius: 12px; cursor: pointer; font: inherit;
  background: color-mix(in srgb, var(--bg) 70%, var(--surface));
  border: 1px solid var(--border-strong); color: var(--text);
}
.cb-field:hover, .cb-field[aria-expanded="true"] { border-color: var(--gold); }
.cb-val { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.cb-val b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cb-val b.cb-empty { font-weight: 500; color: var(--text-2); }
.cb-val small { font-size: .78rem; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cb-arrow { flex: none; display: flex; color: var(--text-2); transition: transform .15s; }
.cb-field[aria-expanded="true"] .cb-arrow { transform: rotate(180deg); }
.cb-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.cb-chip {
  display: inline-flex; align-items: center; gap: 2px; max-width: 100%; padding: 2px 2px 2px 10px;
  border-radius: 999px; font-size: .84rem; color: var(--text);
  background: color-mix(in srgb, var(--bg) 70%, var(--surface)); border: 1px solid var(--gold);
}
.cb-chip > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 60vw; }
.cb-chip button {
  flex: none; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 50%; cursor: pointer;
  background: transparent; color: var(--text); font-size: 1.1rem; line-height: 1;
}
.cb-chip button:hover { background: color-mix(in srgb, var(--gold) 30%, transparent); }
.cb-backdrop { position: fixed; inset: 0; z-index: 1190; background: rgba(0,0,0,.5); }
.cb-pop {
  position: fixed; z-index: 1200; display: flex; flex-direction: column; box-sizing: border-box;
  padding: 8px; border-radius: 12px; border: 1px solid var(--border-strong); color: var(--text);
  background-color: var(--bg);
  background-image: linear-gradient(165deg, var(--surface), var(--surface-tint, var(--surface)));
  box-shadow: 0 14px 40px rgba(0,0,0,.45);
}
.cb-grip { display: none; }
.cb-pop .cb-search {
  flex: none; width: 100%; box-sizing: border-box; margin-bottom: 6px; padding: 10px 12px; border-radius: 10px;
  font: inherit; color: var(--text); background: color-mix(in srgb, var(--bg) 70%, var(--surface));
  border: 1px solid var(--border-strong);
}
.cb-pop .cb-search:focus { outline: none; border-color: var(--gold); }
.cb-list { list-style: none; margin: 0; padding: 0; overflow-y: auto; overscroll-behavior: contain; flex: 1; min-height: 0; }
.cb-opt {
  display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: 8px; cursor: pointer;
  min-height: 44px; box-sizing: border-box;
}
.cb-opt.is-active { background: color-mix(in srgb, var(--gold) 22%, transparent); }
.cb-opt.is-selected { background: color-mix(in srgb, var(--gold) 14%, transparent); }
.cb-opt.is-selected.is-active { background: color-mix(in srgb, var(--gold) 28%, transparent); }
.cb-mark {
  flex: none; width: 18px; height: 18px; border-radius: 5px; border: 1.5px solid var(--text-2);
  display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700; color: var(--text);
}
.cb-opt.is-selected .cb-mark { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 35%, transparent); }
.cb-opt.is-selected .cb-mark::after { content: ""; width: 5px; height: 9px; border: solid currentColor; border-width: 0 2px 2px 0; transform: rotate(45deg) translate(-1px, -1px); }
.cb-pop:not(.cb-multi) .cb-mark { border-radius: 50%; }
.cb-txt { min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.cb-txt b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cb-txt small { font-size: .78rem; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cb-create .cb-txt b { color: var(--gold-t, var(--text)); }
.cb-none { padding: 10px; font-size: .84rem; color: var(--text-2); }
@media (max-width: 700px) {
  .cb-pop {
    left: 0; right: 0; bottom: 0; top: auto; width: auto; max-height: 72dvh; height: auto;
    border-radius: 16px 16px 0 0; padding: 6px 12px calc(12px + env(safe-area-inset-bottom));
  }
  .cb-grip { display: block; flex: none; width: 40px; height: 4px; margin: 2px auto 10px; border-radius: 2px; background: var(--text-2); opacity: .6; }
}

/* 360–400px: «Модель мастера» и «С чего начнём историю?» дисплейными шрифтами тем
   (капитель Тишины, Pixelify Терминала, Russo One Киберпанка) переносились на две строки. */
@media (max-width: 400px) {
  .igra-sheet-title { font-size: 1.12rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .igra-begin-title { font-size: 1.08rem; }
  html[data-theme="horror"] .igra-sheet-title, html[data-theme="horror"] .igra-begin-title { letter-spacing: .02em; font-size: .98rem; }
}
