*{margin:0;padding:0;box-sizing:border-box}

/* html получает тот же фон, что и body — на iOS Safari эффект "резинки" при овер-скролле
   в начале/конце страницы на долю секунды показывает то, что находится ЗА body (обычно
   белую или чёрную дефолтную заливку браузера), а не сам фон сайта. Одинаковый фон на
   обоих уровнях убирает этот визуальный провал независимо от текущей темы. */
html{background-color:var(--bg-page, #0F1115)}

/* ===== Система тем и акцентных цветов =====
   Два независимых переключателя, оба через атрибуты на <html>:
   - data-theme: "dark" (по умолчанию) | "light" | "oled" — определяет фон/текст/границы.
   - data-accent: "purple" (по умолчанию) | "orange" | "red" | "green" | "blue" — определяет
     единственный акцентный цвет, который раньше был захардкожен как #8B5CF6 по всему файлу.
   Все компоненты ниже используют var(--accent) и var(--bg-*)/var(--text-*)/var(--border-*)
   вместо конкретных hex-значений, поэтому переключение — это просто смена атрибута в JS
   (см. APP.THEME в core.js), без пересчёта DOM. --accent-rgb хранится отдельным триплетом
   "R,G,B" (не hex) специально для использования внутри rgba(var(--accent-rgb),.2) — так
   прозрачные варианты акцента (свечения, полупрозрачные фоны) тоже следуют за темой. */
:root{
  --accent:#8B5CF6;
  --accent-rgb:139,92,246;
  --accent-light:#a78bfa;
  /* --holo-1..--holo-5 — пять цветов-остановок для linear-gradient() голо-акцентов,
     переопределяются в html[data-accent="holo-*"] ниже. У обычных (не-holo) акцентов
     все 5 равны var(--accent) — если override-блок ниже случайно попытается собрать
     градиент для обычной темы, получится просто сплошная заливка тем же цветом, что
     и раньше, без визуальной разницы. Анимация — плавный линейный перелив слева направо
     через background-position (см. @keyframes holoSweep ниже), а не вращение угла через
     @property/conic-gradient: тот подход давал эффект вращающегося CD-диска, что было
     решено сменить на более сдержанный и премиальный "бегущий свет", как у перламутра
     или карбона на солнце. */
  --holo-1:var(--accent);--holo-2:var(--accent);--holo-3:var(--accent);--holo-4:var(--accent);--holo-5:var(--accent);
  --holo-anim-duration:6s;

  --bg-page:#0F1115;
  --bg-card:#1A1D24;
  --bg-card-alt:#171b22;
  --bg-sidebar:#16191f;
  --bg-input:#171b22;
  --bg-row-border:#22262f;

  --border:#525C70;
  --border-soft:#68738A;

  --text-primary:#fff;
  --text-secondary:#9CA3AF;
  --text-muted:#6B7280;
  --text-footer:#777;

  --danger:#EF4444;
  --success:#22C55E;
}

html[data-accent="orange"]{--accent:#F97316;--accent-rgb:249,115,22;--accent-light:#fb923c;}
html[data-accent="red"]{--accent:#EF4444;--accent-rgb:239,68,68;--accent-light:#f87171;}
html[data-accent="green"]{--accent:#22C55E;--accent-rgb:34,197,94;--accent-light:#4ade80;}
html[data-accent="blue"]{--accent:#3B82F6;--accent-rgb:59,130,246;--accent-light:#60a5fa;}

/* ===== Голографические акценты =====
   Второй ряд тех же 5 цветов, но с переливающимся градиентом вместо плоской заливки —
   --accent/--accent-rgb/--accent-light остаются одним цветом (тем же базовым тоном)
   для мест, где градиент физически не работает (border-color, обычный text color,
   rgba() для теней/свечений); --holo-1..--holo-5 хранят отдельные цвета-остановки
   градиента для мест, которые физически МОГУТ быть градиентом.
   Анимация — background-position плавно едет от 0% к -200% (см. @keyframes holoSweep
   ниже), что даёт эффект бегущей слева направо волны света поверх background-size:300%
   растянутого linear-gradient — как перелив на карбоне/перламутре под углом, а не
   вращение (более ранняя версия через conic-gradient + @property давала эффект
   вращающегося CD-диска, который выглядел дёшево, а не премиально).
   Голограмма — это ОДИН цвет, который переливается по яркости/насыщенности при смене
   угла обзора, не радуга из разных цветов. Поэтому каждая палитра ниже — это один и
   тот же hue (тот же тон, что у обычного акцента) с небольшим сдвигом ±12° и вариациями
   светлоты/насыщенности, вплоть до почти-белого
   блика в одной точке — а не смесь фиолетового+розового+синего+циана. */
html[data-accent="holo-purple"]{
  --accent:#A78BFA;--accent-rgb:167,139,250;--accent-light:#C4B5FD;
  --holo-1:#2F16FE;--holo-2:#7953FF;--holo-3:#C9B3FB;--holo-4:#9653FF;--holo-5:#962BFF;
}
html[data-accent="holo-orange"]{
  --accent:#FB923C;--accent-rgb:251,146,60;--accent-light:#FDBA74;
  --holo-1:#D22C00;--holo-2:#FF5E10;--holo-3:#FBA96F;--holo-4:#FF8610;--holo-5:#E68C00;
}
html[data-accent="holo-red"]{
  --accent:#F87171;--accent-rgb:248,113,113;--accent-light:#FCA5A5;
  --holo-1:#EF0735;--holo-2:#FE3546;--holo-3:#F69999;--holo-4:#FE4635;--holo-5:#F84012;
}
html[data-accent="holo-green"]{
  --accent:#4ADE80;--accent-rgb:74,222,128;--accent-light:#86EFAC;
  --holo-1:#119927;--holo-2:#11D649;--holo-3:#5FE390;--holo-4:#11D66A;--holo-5:#12AC6A;
}
html[data-accent="holo-blue"]{
  --accent:#60A5FA;--accent-rgb:96,165,250;--accent-light:#93C5FD;
  --holo-1:#008DF4;--holo-2:#3291FF;--holo-3:#93BAFA;--holo-4:#326FFF;--holo-5:#0935FF;
}

/* Анимация линейного перелива слева направо через background-position. ВАЖНО про знак:
   при background-size > 100% формула CSS для процентной позиции — offset = (container_size
   - image_size) * (percent/100) — даёт ОТРИЦАТЕЛЬНУЮ разницу (container меньше image), значит
   чтобы реально сдвинуть картинку ВЛЕВО (offset отрицательный), процент должен быть
   ПОЛОЖИТЕЛЬНЫМ, а не отрицательным, как может показаться интуитивно. Первая версия этой
   анимации использовала отрицательные проценты (0% → -60%) в паре с background-repeat:
   no-repeat — из-за перепутанного знака картинка на самом деле уезжала ВПРАВО и полностью
   выезжала за пределы элемента, оставляя пустоту (баг, из-за которого голо-свотчи и активные
   кнопки выглядели наполовину чёрными/прозрачными). Правильное направление — 0% → 100%. */
@keyframes holoSweep{
  from{background-position:0% 0%;}
  to{background-position:100% 0%;}
}
/* ===== Применение голо-градиента к существующим акцентным поверхностям =====
   Вместо нового класса на каждом элементе (пришлось бы редактировать разметку во всех
   модулях-калькуляторах) — один override-блок по уже существующим селекторам, который
   активируется только когда выбран голо-акцент (родительский [data-accent^="holo-"]).
   Каждый селектор здесь — точная копия того места в файле, где обычно стоит
   background:var(--accent), плюс линейный градиент поверх и анимация сдвига позиции.
   Для обычных (не-holo) акцентов это правило вообще не применяется, так что
   производительность/вид плоских тем не меняется ни на бит. */
[data-accent^="holo-"] .badge,
[data-accent^="holo-"] .sidebtn:hover,
[data-accent^="holo-"] .sidebtn.active,
[data-accent^="holo-"] .toolbar .toolbtn.active,
[data-accent^="holo-"] .toolbtn.active,
[data-accent^="holo-"] .recycle-tab-btn.active,
[data-accent^="holo-"] .toast-undo-btn:hover,
[data-accent^="holo-"] .segment-thumb,
[data-accent^="holo-"] .upgrade-mat-chip.active,
[data-accent^="holo-"] .fab-expand{
  background-image:linear-gradient(100deg,var(--holo-1),var(--holo-2),var(--holo-3),var(--holo-4),var(--holo-5),var(--holo-1),var(--holo-2),var(--holo-3),var(--holo-4),var(--holo-5),var(--holo-1),var(--holo-2));
  background-size:200% 100%;
  background-repeat:no-repeat;
  animation:holoSweep var(--holo-anim-duration) ease-in-out infinite alternate;
}
/* .card.active и .settings-trigger используют border/box-shadow для акцента, а не
   background — вращающийся градиент по 2px рамке был бы визуально незаметен и избыточно
   сложен технически (border-image + анимация), поэтому вместо этого просто усиливаем
   свечение под голо-акцентом заметнее, чем у обычного плоского цвета. */
[data-accent^="holo-"] .card.active{
  box-shadow:0 0 30px rgba(var(--accent-rgb),.35);
}
[data-accent^="holo-"] .settings-trigger.settings-open{
  box-shadow:0 0 16px rgba(var(--accent-rgb),.5);
}

/* Светлая тема — светлый фон, тёмный текст, те же карточки/паттерны переструктурированы
   под инверсию яркости. Акцентный цвет остаётся тем же (var(--accent) не переопределяется
   здесь), т.к. цвет акцента и тема — два независимых выбора пользователя. Фон страницы
   заметно темнее карточек (#E4E7EC против белого) — иначе карточки визуально сливаются
   с фоном и тонкая граница #E5E7EB её одной не спасает, особенно на телефонных экранах
   при дневном свете. Плюс лёгкая тень на карточках (см. .card ниже) — она держит
   разделение даже там, где граница на глаз незаметна. */
html[data-theme="light"]{
  --bg-page:#E4E7EC;
  --bg-card:#FFFFFF;
  --bg-card-alt:#F3F4F6;
  --bg-sidebar:#FFFFFF;
  --bg-input:#F3F4F6;
  --bg-row-border:#E5E7EB;

  --border:#9AA3B2;
  --border-soft:#828C9E;

  --text-primary:#111827;
  --text-secondary:#4B5563;
  --text-muted:#6B7280;
  --text-footer:#9CA3AF;
}

/* Сверхтёмная (OLED) — чистый чёрный фон вместо тёмно-серого #0F1115, карточки почти
   сливаются с фоном (минимальная разница яркости), акцент становится единственным
   ярким пятном на экране — экономит батарею на OLED-экранах и даёт максимальный контраст. */
html[data-theme="oled"]{
  --bg-page:#000000;
  --bg-card:#0A0A0A;
  --bg-card-alt:#000000;
  --bg-sidebar:#000000;
  --bg-input:#0A0A0A;
  --bg-row-border:#1A1A1A;

  --border:#4A4A4A;
  --border-soft:#5E5E5E;

  --text-primary:#fff;
  --text-secondary:#A0A0A0;
  --text-muted:#707070;
  --text-footer:#666;
}

/* ===== Фоновая текстура =====
   Едва заметный hex-grid (шестигранная сетка) поверх фона страницы — намёк на металл/
   чертёж/индустриальную тему Rust, не отвлекает от плотного интерфейса калькуляторов.
   Цвет узора следует за выбранным акцентом (см. html[data-accent=...] body ниже) —
   CSS-переменные не работают внутри data:image/svg+xml URL, поэтому вместо одного
   правила с var(--accent) даём 5 готовых SVG, по одному на каждый акцент, с тем же
   путём и разным stroke. background-attachment:fixed — паттерн не скроллится вместе
   с контентом, остаётся статичным "фоном мира", как в играх с параллаксом. */
body{
  font-family:'Manrope',sans-serif;
  color:var(--text-primary);
  min-height:100vh;
  background-color:var(--bg-page);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='100' viewBox='0 0 56 100'%3E%3Cpath d='M28 0L56 16V50L28 66L0 50V16Z' fill='none' stroke='%238B5CF6' stroke-opacity='0.12' stroke-width='1.5'/%3E%3Cpath d='M28 34L56 50V84L28 100L0 84V50Z' fill='none' stroke='%238B5CF6' stroke-opacity='0.12' stroke-width='1.5'/%3E%3C/svg%3E");
  background-attachment:fixed;
  background-repeat:repeat;
}
html[data-accent="orange"] body{background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='100' viewBox='0 0 56 100'%3E%3Cpath d='M28 0L56 16V50L28 66L0 50V16Z' fill='none' stroke='%23F97316' stroke-opacity='0.12' stroke-width='1.5'/%3E%3Cpath d='M28 34L56 50V84L28 100L0 84V50Z' fill='none' stroke='%23F97316' stroke-opacity='0.12' stroke-width='1.5'/%3E%3C/svg%3E");}
html[data-accent="red"] body{background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='100' viewBox='0 0 56 100'%3E%3Cpath d='M28 0L56 16V50L28 66L0 50V16Z' fill='none' stroke='%23EF4444' stroke-opacity='0.12' stroke-width='1.5'/%3E%3Cpath d='M28 34L56 50V84L28 100L0 84V50Z' fill='none' stroke='%23EF4444' stroke-opacity='0.12' stroke-width='1.5'/%3E%3C/svg%3E");}
html[data-accent="green"] body{background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='100' viewBox='0 0 56 100'%3E%3Cpath d='M28 0L56 16V50L28 66L0 50V16Z' fill='none' stroke='%2322C55E' stroke-opacity='0.12' stroke-width='1.5'/%3E%3Cpath d='M28 34L56 50V84L28 100L0 84V50Z' fill='none' stroke='%2322C55E' stroke-opacity='0.12' stroke-width='1.5'/%3E%3C/svg%3E");}
html[data-accent="blue"] body{background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='100' viewBox='0 0 56 100'%3E%3Cpath d='M28 0L56 16V50L28 66L0 50V16Z' fill='none' stroke='%233B82F6' stroke-opacity='0.12' stroke-width='1.5'/%3E%3Cpath d='M28 34L56 50V84L28 100L0 84V50Z' fill='none' stroke='%233B82F6' stroke-opacity='0.12' stroke-width='1.5'/%3E%3C/svg%3E");}

/* Голографические варианты узора — та же hex-сетка, но оба path одного повторяющегося
   тайла окрашены в БЛИЗКИЕ оттенки одного тона (не в разные цвета), плюс поверх добавлен
   медленно плывущий слева направо linear-gradient слой на 6% непрозрачности из той же
   однотонной палитры, что и у кнопок/бейджей. Сама SVG-сетка не может быть анимированным
   градиентом (data-URI статичен), но overlay сверху даёт эффект лёгкой волны света,
   бегущей по всей странице, независимо от статичной геометрии сетки под ним; вторая
   линия сетки чуть темнее/светлее первой — намёк на глубину, а не смену цвета.
   background-size/position указаны для ОБОИХ слоёв (первое значение — для градиента,
   второе — auto для SVG, который должен просто повторяться на месте без сдвига). */
html[data-accent="holo-purple"] body{background-image:
    linear-gradient(100deg, rgba(47,22,254,.07), rgba(150,42,255,.07), rgba(201,179,251,.07), rgba(47,22,254,.07), rgba(150,42,255,.07), rgba(47,22,254,.07), rgba(150,42,255,.07), rgba(201,179,251,.07), rgba(47,22,254,.07), rgba(150,42,255,.07)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='100' viewBox='0 0 56 100'%3E%3Cpath d='M28 0L56 16V50L28 66L0 50V16Z' fill='none' stroke='%238B5CF6' stroke-opacity='0.13' stroke-width='1.5'/%3E%3Cpath d='M28 34L56 50V84L28 100L0 84V50Z' fill='none' stroke='%23C9B3FB' stroke-opacity='0.11' stroke-width='1.5'/%3E%3C/svg%3E");
  background-size:200% 100%, auto;
  animation:holoSweep 22s ease-in-out infinite alternate;
  background-repeat:no-repeat,repeat;
  background-attachment:fixed,fixed;
}
html[data-accent="holo-orange"] body{background-image:
    linear-gradient(100deg, rgba(210,44,0,.07), rgba(255,94,16,.07), rgba(251,169,111,.07), rgba(210,44,0,.07), rgba(255,94,16,.07), rgba(210,44,0,.07), rgba(255,94,16,.07), rgba(251,169,111,.07), rgba(210,44,0,.07), rgba(255,94,16,.07)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='100' viewBox='0 0 56 100'%3E%3Cpath d='M28 0L56 16V50L28 66L0 50V16Z' fill='none' stroke='%23F97316' stroke-opacity='0.13' stroke-width='1.5'/%3E%3Cpath d='M28 34L56 50V84L28 100L0 84V50Z' fill='none' stroke='%23FBA96F' stroke-opacity='0.11' stroke-width='1.5'/%3E%3C/svg%3E");
  background-size:200% 100%, auto;
  animation:holoSweep 22s ease-in-out infinite alternate;
  background-repeat:no-repeat,repeat;
  background-attachment:fixed,fixed;
}
html[data-accent="holo-red"] body{background-image:
    linear-gradient(100deg, rgba(239,7,53,.07), rgba(254,53,70,.07), rgba(246,153,153,.07), rgba(239,7,53,.07), rgba(254,53,70,.07), rgba(239,7,53,.07), rgba(254,53,70,.07), rgba(246,153,153,.07), rgba(239,7,53,.07), rgba(254,53,70,.07)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='100' viewBox='0 0 56 100'%3E%3Cpath d='M28 0L56 16V50L28 66L0 50V16Z' fill='none' stroke='%23EF4444' stroke-opacity='0.13' stroke-width='1.5'/%3E%3Cpath d='M28 34L56 50V84L28 100L0 84V50Z' fill='none' stroke='%23F69999' stroke-opacity='0.11' stroke-width='1.5'/%3E%3C/svg%3E");
  background-size:200% 100%, auto;
  animation:holoSweep 22s ease-in-out infinite alternate;
  background-repeat:no-repeat,repeat;
  background-attachment:fixed,fixed;
}
html[data-accent="holo-green"] body{background-image:
    linear-gradient(100deg, rgba(17,153,39,.07), rgba(17,214,73,.07), rgba(95,227,144,.07), rgba(17,153,39,.07), rgba(17,214,73,.07), rgba(17,153,39,.07), rgba(17,214,73,.07), rgba(95,227,144,.07), rgba(17,153,39,.07), rgba(17,214,73,.07)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='100' viewBox='0 0 56 100'%3E%3Cpath d='M28 0L56 16V50L28 66L0 50V16Z' fill='none' stroke='%2322C55E' stroke-opacity='0.13' stroke-width='1.5'/%3E%3Cpath d='M28 34L56 50V84L28 100L0 84V50Z' fill='none' stroke='%235FE390' stroke-opacity='0.11' stroke-width='1.5'/%3E%3C/svg%3E");
  background-size:200% 100%, auto;
  animation:holoSweep 22s ease-in-out infinite alternate;
  background-repeat:no-repeat,repeat;
  background-attachment:fixed,fixed;
}
html[data-accent="holo-blue"] body{background-image:
    linear-gradient(100deg, rgba(0,141,244,.07), rgba(50,145,255,.07), rgba(147,186,250,.07), rgba(0,141,244,.07), rgba(50,145,255,.07), rgba(0,141,244,.07), rgba(50,145,255,.07), rgba(147,186,250,.07), rgba(0,141,244,.07), rgba(50,145,255,.07)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='100' viewBox='0 0 56 100'%3E%3Cpath d='M28 0L56 16V50L28 66L0 50V16Z' fill='none' stroke='%233B82F6' stroke-opacity='0.13' stroke-width='1.5'/%3E%3Cpath d='M28 34L56 50V84L28 100L0 84V50Z' fill='none' stroke='%2393BAFA' stroke-opacity='0.11' stroke-width='1.5'/%3E%3C/svg%3E");
  background-size:200% 100%, auto;
  animation:holoSweep 22s ease-in-out infinite alternate;
  background-repeat:no-repeat,repeat;
  background-attachment:fixed,fixed;
}

/* ===== Единая гарнитура сайта: Manrope =====
   Раньше здесь стоял Oswald для заголовков + Inter для текста — по фидбэку от
   пользователей это читалось как "газетный" стиль (узкое сжатое начертание, характерное
   для печатных заголовков), а не как современный игровой интерфейс. Manrope — открытый
   геометрический гротеск с полной поддержкой кириллицы (в отличие от части модных
   узких/техно-шрифтов вроде Space Grotesk, у которых кириллицы просто нет в природе —
   проверено перед заменой) — используется одной гарнитурой и для заголовков, и для
   тела текста, вместо пары из двух разных шрифтов. Собственный трекинг не нужен —
   у Manrope, в отличие от узкого Oswald, буквы не "слипаются" на крупных размерах. */
h1,h2,h3,.title,.nav-title h2{
  font-weight:700;
}
.container{width:min(1800px,94%);margin:auto;padding:40px 0}
header{margin-bottom:40px}
header h1{font-size:42px;font-weight:800}
header p{margin-top:10px;color:var(--text-secondary);font-size:18px}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:22px}
.card{background:var(--bg-card);border:2px solid var(--border);border-radius:18px;padding:24px;cursor:pointer;transition:.25s}
/* На светлой теме тонкая граница ещё менее заметна на маленьком экране при ярком свете —
   добавляем мягкую тень, дублирующую эффект границы за счёт разницы в глубине, а не
   только в цвете. На тёмных темах увеличенного контраста --border (см. :root выше)
   уже достаточно, тень там не нужна. */
html[data-theme="light"] .card{box-shadow:0 1px 3px rgba(17,24,39,.06), 0 1px 2px rgba(17,24,39,.04)}
html[data-theme="light"] .card:hover{box-shadow:0 8px 20px rgba(17,24,39,.08)}
.card:hover{transform:translateY(-6px);border-color:var(--accent);box-shadow:0 0 25px rgba(var(--accent-rgb),.2)}
/* ===== Кастомные SVG-иконки модулей (замена emoji) =====
   Единый набор из 8 иконок хранится как <symbol> в index.html (см. комментарий там) —
   .icon/.sidebtn получают конкретные размеры под каждый контекст, а сама заливка идёт
   через currentColor, поэтому .icon (карточки) наследует var(--accent) неявно через цвет
   родителя (см. .icon ниже), а .sidebtn — свой цвет по активному/неактивному состоянию.
   width/height на самом <svg>, а не только на symbol/viewBox — на карточках Safari иначе
   иногда рендерит их в размере по умолчанию 300x150 на долю секунды до применения CSS. */
.icon{width:46px;height:46px;margin-bottom:18px;color:var(--accent)}
.icon svg,.nav-icon{width:100%;height:100%;display:block}
.title{font-size:22px;font-weight:700}
.description{margin-top:10px;color:var(--text-secondary);line-height:1.6}
footer{margin-top:50px;text-align:center;color:var(--text-footer)}
.badge{display:inline-block;margin-top:15px;padding:6px 12px;background:var(--accent);border-radius:50px;font-size:13px;font-weight:700}

/* Приветственная подсказка для новых посетителей (см. #onboardingBanner в index.html) —
   растягивается на всю ширину сетки карточек (grid-column:1/-1), а не сжимается в одну
   ячейку той же ширины, что и карточки калькуляторов. Показывается один раз через JS-флаг
   в localStorage — не должна навязчиво возвращаться после того, как человек её закрыл.
   Текст переводится через data-i18n атрибуты, как и остальная статичная разметка. */
.onboarding-banner{
grid-column:1/-1;
display:flex;
align-items:flex-start;
gap:16px;
background:rgba(var(--accent-rgb),.08);
border:1px solid rgba(var(--accent-rgb),.3);
border-radius:18px;
padding:20px 24px;
}
.onboarding-banner-icon{font-size:28px;flex-shrink:0}
.onboarding-banner-text{flex:1}
.onboarding-banner-text b{font-size:16px}
.onboarding-banner-text p{margin-top:6px;color:var(--text-secondary);line-height:1.6;font-size:14px}
@media(max-width:640px){
.onboarding-banner{flex-direction:column}
}

/* Компактная сворачиваемая подсказка внутри модуля-калькулятора (см. APP.UI.moduleHint
   в core.js) — тот же принцип, что у onboarding-banner на Главной (показать один раз,
   запомнить закрытие), но меньше и без отдельного заголовка: подсказка внутри модуля
   поясняет одну конкретную вещь ("как это работает"), а не весь сайт целиком, поэтому
   не нуждается в том же объёме текста и визуального веса. */
.module-hint{
display:flex;
align-items:flex-start;
gap:10px;
background:rgba(var(--accent-rgb),.07);
border:1px solid rgba(var(--accent-rgb),.25);
border-radius:12px;
padding:12px 14px;
margin-bottom:16px;
}
.module-hint-icon{font-size:16px;flex-shrink:0;line-height:1.5}
.module-hint-text{flex:1;font-size:13px;color:var(--text-secondary);line-height:1.5}
.module-hint-close{
background:none;border:none;color:var(--text-muted);cursor:pointer;
font-size:14px;line-height:1;padding:2px;flex-shrink:0;
-webkit-tap-highlight-color:transparent;
}
.module-hint-close:hover{color:var(--text-primary)}

header{
display:flex;
justify-content:space-between;
align-items:center;
gap:20px;
flex-wrap:wrap;
}
.top-actions{
display:flex;
gap:12px;
align-items:center;
}
.search{
background:var(--bg-card);
border:1px solid var(--border);
color:var(--text-primary);
padding:12px 16px;
border-radius:12px;
min-width:260px;
outline:none;
}
/* Выпадающий список результатов глобального поиска (см. #globalSearchResults в index.html) —
   появляется под полем поиска на Главной, когда запрос находит совпадения не только среди
   8 карточек модулей, но и внутри баз данных калькуляторов (предметы крафта/рейда/переработки).
   Работает на обоих языках — названия результатов и подписи модулей переводятся в core.js. */
.global-search-results{
position:absolute;
top:calc(100% + 8px);
left:0;
right:0;
max-height:360px;
overflow-y:auto;
background:var(--bg-card);
border:1px solid var(--border);
border-radius:12px;
box-shadow:0 12px 32px rgba(0,0,0,.4);
z-index:60;
}
.global-search-result-item{
display:flex;
justify-content:space-between;
align-items:center;
gap:10px;
padding:12px 16px;
cursor:pointer;
border-bottom:1px solid var(--border);
transition:.15s;
}
.global-search-result-item:last-child{border-bottom:none}
.global-search-result-item:hover,
.global-search-result-item.kbd-active{
background:rgba(var(--accent-rgb),.12);
}
.global-search-result-name{
font-size:14px;
color:var(--text-primary);
}
.global-search-result-module{
font-size:12px;
color:var(--accent);
white-space:nowrap;
}
.global-search-no-results{
padding:16px;
text-align:center;
color:var(--text-muted);
font-size:13px;
}
.sidebar{
position:fixed;
left:0;top:0;bottom:0;
width:88px;
background:var(--bg-sidebar);
border-right:1px solid var(--border);
display:flex;
flex-direction:column;
align-items:center;
padding:24px 0;
gap:14px;
overflow-y:auto;
}
/* Обёртка нужна, чтобы полоска-индикатор (см. .sidebtn-wrap::before) позиционировалась
   относительно слота кнопки, а не самой кнопки — так её можно расположить чуть левее
   от иконки, вплотную к краю сайдбара, как в Discord, без искажения формы самой иконки. */
.sidebtn-wrap{position:relative;display:flex;align-items:center;flex-shrink:0}
.sidebtn-wrap::before{
  content:'';
  position:absolute;left:-14px;top:50%;
  width:4px;height:0;
  border-radius:0 4px 4px 0;
  background:var(--text-primary);
  transform:translateY(-50%);
  transition:height .2s cubic-bezier(.4,0,.2,1), opacity .2s;
  opacity:0;
}
.sidebtn-wrap:hover::before{height:20px;opacity:.5}
.sidebtn-wrap:has(.sidebtn.active)::before{height:32px;opacity:1}
.sidebtn{
width:54px;height:54px;border-radius:16px;
display:flex;align-items:center;justify-content:center;
background:var(--bg-card);border:1px solid var(--border);
color:var(--text-secondary);
transition:background .2s, border-color .2s, border-radius .25s cubic-bezier(.4,0,.2,1), transform .2s, color .2s;
flex-shrink:0;
}
/* Сама SVG-иконка (см. symbol-спрайт в index.html) — currentColor подхватывает .sidebtn
   color выше: приглушённый text-secondary в покое, белый на hover/active (см. ниже),
   вместо эмодзи, у которого не было единого управления цветом через CSS вообще. */
.sidebtn .nav-icon{width:30px;height:30px}
/* border-radius растёт при hover/active (16px → 22px/26px) — тот же "квадрат размякает
   в скруглённый квадрат" эффект, что у иконок серверов в Discord, вместо простого
   изменения цвета/масштаба. Масштаб оставлен, но чуть мягче прежнего (1.08 → 1.05),
   чтобы не спорить с новым эффектом формы за внимание. */
.sidebtn:hover{background:var(--accent);border-radius:22px;transform:scale(1.05);color:#fff}
.sidebtn.active{background:var(--accent);border-color:var(--accent);border-radius:26px;color:#fff}
/* Кнопка "Главная" использует растровый логотип сайта вместо эмодзи (см. index.html) —
   белая монохромная версия специально, а не оригинальные серый+оранжевый цвета логотипа:
   фон кнопки на hover/active равен var(--accent), который пользователь может сменить на
   любой из 10 акцентов в настройках (включая голографические) — оригинальные цвета лого
   теряют контраст на части этих акцентов (особенно orange/red), а сплошной белый силуэт
   остаётся одинаково читаемым на любом фоне без привязки к конкретному акценту. */
.sidebtn-logo-img{width:26px;height:26px;object-fit:contain;pointer-events:none}
/* .sidebtn фон совпадает с .card (белый) и сидит на белом .sidebar — на тёмных темах
   разница цветов сама разделяет их, на светлой нужна тень, как и у .card выше. */
html[data-theme="light"] .sidebtn{box-shadow:0 1px 3px rgba(17,24,39,.08)}
.container{margin-left:120px}
@media(max-width:768px){
.sidebar{display:none}
.container{margin-left:auto}
.search{min-width:100%}
/* background-attachment:fixed известен как источник лагов при скролле на части мобильных
   браузеров (особенно старый iOS Safari) — на узких экранах переключаем на scroll,
   визуальная разница почти незаметна, а плавность скролла важнее. */
body{background-attachment:scroll}
}


.content-panel{
margin-top:34px;
background:var(--bg-card-alt);
border:2px solid var(--border);
border-radius:18px;
padding:28px;
animation:fade .35s cubic-bezier(.22,1,.36,1);
/* Слабое постоянное акцентное свечение — отличает открытую панель калькулятора от
   рядового статичного блока, читается как "активное окно" не только по border,
   но и по лёгкому ореолу. Заметно слабее hover-свечения карточек (.15 против .2
   alpha у .card:hover), т.к. это состояние держится постоянно, а не на секунду. */
box-shadow:0 0 40px rgba(var(--accent-rgb),.08);
}
.content-panel h2{font-size:28px;margin-bottom:10px}
.content-panel p{color:var(--text-secondary);line-height:1.7}
.card.active{
border-color:var(--accent);
box-shadow:0 0 25px rgba(var(--accent-rgb),.25);
}
/* ===== Toast-уведомления =====
   Стек карточек сверху по центру (не пересекается с FAB-кнопками, которые всегда
   снизу справа). Каждый toast имеет тип (success/error/info) со своей иконкой и
   цветным акцентом слева, плюс тающую полоску снизу — видно, сколько времени
   осталось до автоматического закрытия. */
.toast-stack{
  position:fixed;
  top:20px;left:50%;
  transform:translateX(-50%);
  z-index:1200;
  display:flex;
  flex-direction:column;
  gap:10px;
  align-items:center;
  pointer-events:none;
  width:min(420px,calc(100vw - 32px));
}
.toast-item{
  pointer-events:auto;
  position:relative;
  display:flex;
  align-items:flex-start;
  gap:10px;
  width:100%;
  background:var(--bg-card);
  border:1px solid var(--border);
  border-left:3px solid var(--accent);
  padding:13px 16px 15px;
  border-radius:12px;
  box-shadow:0 8px 24px rgba(0,0,0,.35);
  overflow:hidden;
  opacity:0;
  transform:translateY(-16px) scale(.96);
  transition:opacity .25s cubic-bezier(.34,1.56,.64,1), transform .25s cubic-bezier(.34,1.56,.64,1);
}
.toast-item.show{opacity:1;transform:translateY(0) scale(1)}
.toast-item.hide{opacity:0;transform:translateY(-10px) scale(.96)}
.toast-item.type-success{border-left-color:var(--success)}
.toast-item.type-error{border-left-color:var(--danger)}
.toast-item.type-info{border-left-color:var(--accent)}
.toast-icon{font-size:18px;line-height:1;flex-shrink:0;margin-top:1px}
.toast-text{font-size:14px;line-height:1.4;flex:1}
.toast-close{
  background:none;border:none;color:var(--text-muted);cursor:pointer;
  font-size:16px;line-height:1;padding:2px;flex-shrink:0;
  -webkit-tap-highlight-color:transparent;
}
.toast-close:hover{color:var(--text-primary)}
.toast-close:focus,.toast-close:focus-visible{outline:none}
.toast-undo-btn{
  background:none;border:1px solid var(--accent);color:var(--accent);
  cursor:pointer;font-size:12px;font-weight:700;
  padding:4px 10px;border-radius:7px;flex-shrink:0;
  -webkit-tap-highlight-color:transparent;
  transition:.15s;
}
.toast-undo-btn:hover{background:var(--accent);color:#fff}
.toast-progress{
  position:absolute;left:0;bottom:0;height:2px;
  background:currentColor;opacity:.5;
  animation:toastShrink linear forwards;
}
.toast-item.type-success .toast-progress{color:var(--success)}
.toast-item.type-error .toast-progress{color:var(--danger)}
.toast-item.type-info .toast-progress{color:var(--accent)}
@keyframes toastShrink{
  from{width:100%}
  to{width:0%}
}
@media (max-width:640px){
  .toast-stack{top:12px}
}
@keyframes fade{
from{opacity:0;transform:translateY(12px)}
to{opacity:1;transform:none}
}

.page{display:none;animation:fade .35s cubic-bezier(.22,1,.36,1)}
.page.active{display:block}
.nav-title{display:flex;justify-content:space-between;align-items:center;margin-bottom:18px}
.back-btn{
background:var(--accent);border:none;color:#fff;padding:10px 16px;
border-radius:10px;cursor:pointer;font-weight:600;display:none}
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:16px;margin-top:24px}
.stat{
background:var(--bg-card);border:1px solid var(--border);border-radius:14px;padding:18px}
.stat h3{font-size:14px;color:var(--text-secondary);margin-bottom:8px}
.stat b{font-size:24px}

.toolbar{display:flex;gap:12px;margin:20px 0;flex-wrap:wrap}
.toolbtn{
background:var(--bg-card);border:1px solid var(--border);color:var(--text-primary);
padding:10px 16px;border-radius:10px;cursor:pointer;transition:.2s}
.toolbtn:hover{border-color:var(--accent)}
.toolbar .toolbtn.active{background:var(--accent);border-color:var(--accent);color:#fff}
.toolbtn.active{background:var(--accent);border-color:var(--accent);color:#fff}
.searchmark{outline:2px solid var(--accent)}


/* Desktop two-column layout */
@media (min-width:1100px){
  html,body{
    height:100%;
    overflow:hidden;
  }
  .container{
    display:grid;
    grid-template-columns:420px 1fr;
    grid-template-rows:auto 1fr auto;
    grid-template-areas:
      "header header"
      "grid   panel"
      "footer footer";
    gap:18px;
    height:100vh;
    padding-top:14px;
    padding-bottom:14px;
  }
  header{margin-bottom:0}
  header h1{font-size:32px}
  header p{font-size:15px}
  footer{margin-top:0;font-size:13px}
  header{grid-area:header}
  footer{grid-area:footer}
  .grid{
    grid-area:grid;
    width:auto;
    grid-template-columns:repeat(2,1fr);
    min-height:0;
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
  }
  .content-panel{
    grid-area:panel;
    margin-top:0;
    min-width:0;
    min-height:0;
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
  }
  /* Скроллбары в теме сайта: серая дорожка, оранжевый ползунок */
  .grid,.content-panel{
    scrollbar-width:thin;
    scrollbar-color:var(--accent) var(--bg-card);
  }
  .grid::-webkit-scrollbar,
  .content-panel::-webkit-scrollbar{
    width:8px;
  }
  .grid::-webkit-scrollbar-track,
  .content-panel::-webkit-scrollbar-track{
    background:var(--bg-card);
    border-radius:8px;
  }
  .grid::-webkit-scrollbar-thumb,
  .content-panel::-webkit-scrollbar-thumb{
    background:var(--accent);
    border-radius:8px;
  }
  .grid::-webkit-scrollbar-thumb:hover,
  .content-panel::-webkit-scrollbar-thumb:hover{
    background:var(--accent-light);
  }
  .back-btn{
    display:none !important;
  }
}


/* Craft desktop split */
@media (min-width:1100px){
.craft-layout{display:grid;grid-template-columns:minmax(380px,1fr) 380px;gap:24px;align-items:start}
.craft-left{min-width:0}
.craft-right{position:sticky;top:30px}
}

/* Ещё шире экраны — даём панели больше воздуха вместо пустоты по бокам */
@media (min-width:1500px){
  .container{
    grid-template-columns:460px 1fr;
  }
  .craft-layout{grid-template-columns:minmax(420px,1fr) 420px}
}

/* Мобильный полноэкранный режим калькулятора: когда открыт любой модуль (не "Главная"),
   панель разворачивается на весь экран поверх карточек — не нужно листать вниз мимо списка. */
@media (max-width:1099px){
  .content-panel.fullscreen-mobile{
    position:fixed;
    inset:0;
    z-index:1000;
    margin:0;
    border-radius:0;
    border:none;
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
    padding:0 20px 40px;
  }
  .content-panel.fullscreen-mobile .nav-title{
    position:sticky;
    top:0;
    z-index:5;
    background:var(--bg-card-alt);
    padding:16px 0;
    margin-bottom:8px;
    border-bottom:1px solid var(--border);
  }
  .content-panel.fullscreen-mobile .back-btn{
    display:inline-block !important;
  }
}


/* ===== Переработчик (Recycler) ===== */

.recycle-wrap{display:flex;flex-direction:column;gap:16px}

/* Сетка карточек предметов: 1 колонка на мобиле, авто-заполнение плитками на широких экранах */
.recycle-grid{
  display:grid;
  grid-template-columns:1fr;
  gap:10px;
}
@media (min-width:700px){
  .recycle-grid{grid-template-columns:repeat(2,1fr)}
}
@media (min-width:1500px){
  .recycle-grid{grid-template-columns:repeat(2,1fr)}
}

.recycle-card{
  background:var(--bg-card);
  border:1px solid var(--border);
  border-radius:14px;
  padding:14px;
  display:flex;
  flex-direction:column;
  gap:10px;
  transition:border-color .2s, transform .15s;
  animation:cardIn .25s ease;
}
.recycle-card:hover{border-color:var(--border-soft)}
.recycle-card.has-qty{border-color:var(--accent);box-shadow:0 0 0 1px rgba(var(--accent-rgb),.15)}

@keyframes cardIn{
  from{opacity:0;transform:translateY(6px)}
  to{opacity:1;transform:none}
}
@keyframes qtyPop{
  0%{transform:scale(1)}
  40%{transform:scale(1.25)}
  100%{transform:scale(1)}
}
.qty-pop{animation:qtyPop .25s ease}

.recycle-card-head{display:flex;justify-content:space-between;align-items:flex-start;gap:10px}
.recycle-card-title{font-weight:600;font-size:15px;line-height:1.3}
.recycle-card-cat{font-size:11px;color:var(--text-muted);margin-top:2px}

.recycle-chips{display:flex;flex-wrap:wrap;gap:6px}
.recycle-chip{
  display:inline-flex;align-items:center;gap:5px;
  background:var(--bg-card-alt);border:1px solid var(--border);
  border-radius:20px;padding:4px 10px;font-size:12px;white-space:nowrap;
}
.recycle-chip.guaranteed{border-color:rgba(34,197,94,.35);color:#86efac}
.recycle-chip.chance{border-color:rgba(234,179,8,.35);color:#fde68a}
.recycle-chip .chip-amt{font-weight:700;color:#fff}

.recycle-shredder-tag{
  display:inline-flex;align-items:center;gap:4px;
  font-size:11px;color:var(--accent);background:rgba(var(--accent-rgb),.1);
  border:1px solid rgba(var(--accent-rgb),.3);border-radius:20px;padding:3px 9px;
  align-self:flex-start;
}

.recycle-counter-row{display:flex;justify-content:flex-end;align-items:center;gap:10px;margin-top:auto}
.recycle-counter{display:flex;align-items:center;gap:8px}
.recycle-counter button{
  width:34px;height:34px;border-radius:10px;
  background:var(--bg-card-alt);border:1px solid var(--border);color:var(--text-primary);
  font-size:18px;line-height:1;cursor:pointer;transition:.2s;
  display:flex;align-items:center;justify-content:center;
}
.recycle-counter button:hover{border-color:var(--accent);background:rgba(var(--accent-rgb),.08)}
.recycle-counter b{min-width:28px;text-align:center;font-size:16px}

/* Переключатель режима переработчика — крупные плитки */
/* Результат: карточка ресурса с иконкой */
.result-resource-row{
  display:flex;justify-content:space-between;align-items:center;
  padding:9px 0;border-bottom:1px solid var(--bg-row-border);
}
.result-resource-row:last-child{border-bottom:none}
.result-resource-name{display:flex;align-items:center;gap:8px;font-size:14px}
.result-resource-val{font-weight:700;font-size:15px}

/* Результат переработки теперь открывается в модальном оверлее (recycleResultOverlay,
   см. recycle.js) — тот же паттерн, что "План рейда"/upgrade.js. Панель .recycle-pane-items
   всегда видна как обычный блок, отдельная переключаемая панель результата не нужна. */
.recycle-tab-badge{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:18px;height:18px;padding:0 5px;margin-left:6px;
  background:rgba(255,255,255,.25);border-radius:20px;font-size:11px;
}

/* ===== Универсальное пустое состояние =====
   Используется везде, где список/результат пуст: нет избранного, нет совпадений
   поиска, ничего не выбрано и т.д. Иконка мягко покачивается — не механическая
   заглушка, а живой элемент интерфейса, который сразу считывается взглядом. */
.empty-state{
  padding:34px 20px;
  text-align:center;
  color:var(--text-muted);
  animation:emptyStateIn .3s ease;
}
.empty-state .empty-icon{
  font-size:38px;
  margin-bottom:12px;
  display:block;
  animation:emptyIconFloat 2.6s ease-in-out infinite;
}
.empty-state .empty-title{
  font-size:15px;
  font-weight:700;
  color:var(--text-secondary);
  margin-bottom:4px;
}
.empty-state .empty-desc{
  font-size:13px;
  line-height:1.5;
  max-width:320px;
  margin:0 auto;
}
@keyframes emptyStateIn{
  from{opacity:0;transform:translateY(6px)}
  to{opacity:1;transform:none}
}
@keyframes emptyIconFloat{
  0%,100%{transform:translateY(0)}
  50%{transform:translateY(-5px)}
}
/* Совместимость со старой разметкой (.recycle-empty), которая ещё встречается в
   нескольких местах кода — работает идентично .empty-state. */
.recycle-empty{padding:30px 16px;text-align:center;color:var(--text-muted);animation:emptyStateIn .3s ease}
.recycle-empty .empty-icon{font-size:34px;margin-bottom:10px;display:block;animation:emptyIconFloat 2.6s ease-in-out infinite}

/* Звёздочка избранного на карточке */
.recycle-fav-btn{
  position:relative;
  background:none;border:none;cursor:pointer;
  padding:2px;flex-shrink:0;
  -webkit-tap-highlight-color:transparent;
}
.recycle-fav-btn:focus,.recycle-fav-btn:focus-visible{outline:none}
.fav-star{
  display:inline-block;
  font-size:19px;line-height:1;
  color:var(--text-muted);transition:transform .15s;
}
.recycle-fav-btn:hover .fav-star{transform:scale(1.15)}
.recycle-fav-btn.is-fav .fav-star{color:var(--accent)}

/* Анимация "взрыва" при добавлении в избранное — звезда резко вырастает, чуть
   поворачивается и возвращается на место (пружинистый эффект), плюс вокруг неё
   разлетаются короткоживущие искры-частицы (см. .fav-spark, генерируются в JS).
   Применяется ТОЛЬКО к .fav-star (сама звезда), не к кнопке-контейнеру — иначе
   вместе со звездой скачет вся квадратная область вокруг неё, что выглядит грубо. */
@keyframes favPop{
  0%{transform:scale(1) rotate(0deg)}
  35%{transform:scale(1.5) rotate(-12deg)}
  60%{transform:scale(.85) rotate(6deg)}
  100%{transform:scale(1) rotate(0deg)}
}
.fav-pop{animation:favPop .45s cubic-bezier(.34,1.56,.64,1)}

.fav-spark-wrap{
  position:absolute;inset:0;pointer-events:none;
  overflow:visible;
}
.fav-spark{
  position:absolute;top:50%;left:50%;
  width:5px;height:5px;border-radius:50%;
  background:var(--accent);
  transform:translate(-50%,-50%);
  animation:favSpark .55s ease-out forwards;
}
@keyframes favSpark{
  0%{opacity:1;transform:translate(-50%,-50%) translate(0,0) scale(1)}
  100%{opacity:0;transform:translate(-50%,-50%) translate(var(--sx),var(--sy)) scale(.3)}
}

/* ===== Универсальный сегментированный переключатель (2-4 состояния) =====
   Используется везде, где нужно выбрать один режим из нескольких:
   Переработчик (Все/Частые/Избранное, Монумент/Safe Zone),
   Калькулятор крафта и Калькулятор ресурсов (режим пороха), и т.д.
   Плавающий индикатор .segment-thumb физически едет между кнопками (transform),
   создавая эффект "переливания", а не просто мгновенно меняет фон. */
.segment-switch{
  position:relative;
  display:flex;gap:3px;padding:4px;margin-bottom:16px;
  background:var(--bg-page);border:1px solid var(--border);border-radius:12px;
}
.segment-thumb{
  position:absolute;top:4px;bottom:4px;left:4px;
  border-radius:9px;
  background:linear-gradient(135deg,var(--accent),var(--accent-light));
  box-shadow:0 2px 10px rgba(var(--accent-rgb),.4);
  transition:
    transform .38s cubic-bezier(.34,1.56,.64,1),
    width .38s cubic-bezier(.34,1.56,.64,1),
    height .38s cubic-bezier(.34,1.56,.64,1);
  transform-origin:center;
  z-index:0;
  will-change:transform;
}
/* "Желейный" squash&stretch на время движения: сжимаемся по одной оси, растягиваемся
   по другой — короткий, живой эффект, а не просто механическое скольжение блока. */
.segment-switch:not(.column-mode) .segment-thumb.thumb-moving{
  transform:var(--thumb-transform) scaleX(1.08) scaleY(.9);
}
.segment-switch.column-mode .segment-thumb.thumb-moving{
  transform:var(--thumb-transform) scaleY(1.08) scaleX(.96);
}
.segment-btn{
  position:relative;z-index:1;
  flex:1;padding:9px 10px;border:none;border-radius:9px;
  background:transparent;color:var(--text-secondary);font-size:13px;font-weight:600;
  cursor:pointer;transition:color .2s;
  white-space:nowrap;
  text-align:center;
}
.segment-btn:hover{color:#fff}
.segment-btn.active{color:#fff}

/* На узких экранах подписи в 3+ кнопках физически не влезают в один горизонтальный ряд —
   вместо скролла (который прятал часть текста и путал пользователя) переключатель
   становится вертикальным столбцом: каждая кнопка на всю ширину, свободный перенос текста.
   Thumb в этом режиме едет по вертикали (translateY) и занимает всю ширину контейнера. */
@media (max-width:640px){
  .segment-switch{flex-direction:column}
  .segment-btn{
    white-space:normal;
    text-align:left;
    padding:12px 14px;
  }
}

.recycle-subheading{
  font-size:11px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--text-muted);margin-bottom:8px;
}

/* Крупный вариант сегмента (иконка+подпись+процент в столбик) — для Монумент/Safe Zone */
.segment-switch.segment-lg .segment-btn{
  display:flex;flex-direction:column;align-items:center;gap:4px;
  padding:12px 8px;
}
.segment-switch.segment-lg .segment-btn .mode-icon{font-size:22px}
.segment-switch.segment-lg .segment-btn .mode-pct{font-size:12px;opacity:.75}

/* Список выбранных предметов в панели результата */
.recycle-selected-row{
  display:flex;justify-content:space-between;align-items:center;gap:10px;
  padding:8px 0;border-bottom:1px solid var(--bg-row-border);
}
.recycle-selected-row:last-child{border-bottom:none}

/* ===== Универсальная строка списка с разделителем (Discord-style) =====
   Тонкая линия между элементами списка вместо оборачивания каждой строки в отдельную
   карточку с рамкой — более лёгкий, "плоский" паттерн для плотных списков (предметов,
   логов, настроек), где рамка на каждой строке была бы избыточной. Последняя строка
   без границы снизу, чтобы список не заканчивался повисшей линией перед следующим
   блоком. Используется как базовый класс — можно комбинировать с flex/grid внутри. */
.list-row{
  padding:10px 0;
  border-bottom:1px solid var(--bg-row-border);
}
.list-row:last-child{border-bottom:none}
.list-row:hover{background:rgba(var(--accent-rgb),.04)}
.recycle-selected-name{font-size:13px;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.recycle-selected-row .recycle-counter button{width:26px;height:26px;font-size:15px;border-radius:8px}
.recycle-selected-row .recycle-counter b{font-size:13px;min-width:18px}
.recycle-remove-btn{
  background:none;border:none;color:var(--text-muted);cursor:pointer;
  font-size:15px;padding:4px;transition:color .15s;
}
.recycle-remove-btn:hover{color:var(--danger)}

/* ===== Прогресс-бар "есть / нужно" (режим "У меня есть" в калькуляторе крафта) =====
   Тонкая полоска под каждым полем ввода — заполняется от 0 до 100% по соотношению
   введённого количества к тому, что реально требуется. Цвет плавно переходит от красного
   (сильный дефицит) через жёлтый к зелёному (хватает) — это даёт мгновенное визуальное
   считывание без необходимости вчитываться в цифры, дополняя текстовый статус-бейдж снизу. */
.have-progress-track{
  height:4px;
  border-radius:2px;
  background:var(--bg-page);
  margin-top:6px;
  overflow:hidden;
}
.have-progress-fill{
  height:100%;
  width:0%;
  border-radius:2px;
  background:var(--danger);
  transition:width .35s cubic-bezier(.4,0,.2,1), background-color .35s ease;
}

/* ===== Skeleton loading (плейсхолдеры на время тяжёлого рендера) =====
   Бегущий градиент-блик создаёт иллюзию "загрузки контента", а не мёртвой заглушки.
   Форма карточки повторяет .recycle-card, чтобы переход к реальному контенту не дёргал
   раскладку — высота и отступы примерно совпадают. */
.skeleton-card{
  background:var(--bg-card);
  border:1px solid var(--border);
  border-radius:14px;
  padding:14px;
  display:flex;
  flex-direction:column;
  gap:10px;
  min-height:118px;
}
.skeleton-line{
  height:14px;
  border-radius:6px;
  background:linear-gradient(90deg,var(--bg-row-border) 25%,#2e3340 50%,var(--bg-row-border) 75%);
  background-size:200% 100%;
  animation:skeletonShimmer 1.4s ease-in-out infinite;
}
.skeleton-title{width:70%;height:16px}
.skeleton-chip{width:85%}
@keyframes skeletonShimmer{
  0%{background-position:200% 0}
  100%{background-position:-200% 0}
}

/* ===== Калькулятор апгрейда: выбор материалов "Из / В" ===== */
.upgrade-material-grid{
  display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:24px;
}
@media (max-width:600px){
  .upgrade-material-grid{grid-template-columns:1fr}
}
.upgrade-material-col{
  background:var(--bg-card);border:1px solid var(--border);border-radius:14px;padding:16px;
}
.upgrade-chip-list{display:flex;flex-wrap:wrap;gap:8px}
.upgrade-mat-chip{
  display:flex;align-items:center;gap:7px;
  padding:10px 14px;border-radius:11px;
  background:var(--bg-card-alt);border:1px solid var(--border);color:var(--text-secondary);
  font-size:14px;font-weight:600;cursor:pointer;
  transition:border-color .2s, background .2s, transform .12s, color .2s;
}
.upgrade-mat-chip .mat-icon{font-size:17px}
.upgrade-mat-chip:hover{border-color:var(--accent);color:#fff}
.upgrade-mat-chip.active{
  background:linear-gradient(135deg,var(--accent),var(--accent-light));
  border-color:var(--accent);color:#fff;
  box-shadow:0 3px 12px rgba(var(--accent-rgb),.35);
  transform:translateY(-1px);
}

/* ===== Плавающая круглая кнопка (FAB), которая раскрывается с подписью при наведении =====
   Используется для "План рейда" и подобных вспомогательных панелей. Позиционирование
   через безопасные отступы (env safe-area) и min(), чтобы никогда не вылезать за экран
   даже на самых узких телефонах или с вырезом/чёлкой снизу. */
.fab-expand{
  position:fixed;
  right:max(20px, env(safe-area-inset-right, 20px));
  bottom:max(20px, env(safe-area-inset-bottom, 20px));
  height:56px;min-width:56px;max-width:calc(100vw - 40px);
  border-radius:28px;
  background:linear-gradient(135deg,var(--accent),var(--accent-light));
  border:none;color:#fff;
  cursor:pointer;z-index:900;
  display:inline-flex;align-items:center;
  padding:0;
  box-shadow:0 6px 20px rgba(var(--accent-rgb),.4);
  transition:min-width .3s cubic-bezier(.4,0,.2,1), box-shadow .2s, transform .15s;
  white-space:nowrap;
}
.fab-expand:hover,.fab-expand:focus-visible{
  min-width:180px;
  box-shadow:0 8px 26px rgba(var(--accent-rgb),.55);
}
.fab-expand:active{transform:scale(.96)}
.fab-expand .fab-icon{
  flex-shrink:0;width:56px;height:56px;
  display:flex;align-items:center;justify-content:center;
  font-size:24px;
}
/* SVG-иконка внутри FAB (см. #icon-checklist в index.html) — заменила emoji 📋/🧾,
   используется одинаково во всех FAB-кнопках результата сайта (Raid/Upgrade/Recycle)
   для единообразия, см. решение в чате. */
.fab-expand .fab-icon .nav-icon{width:28px;height:28px}
.fab-expand .fab-label{
  max-width:0;opacity:0;overflow:hidden;
  font-size:14px;font-weight:700;
  transition:max-width .3s cubic-bezier(.4,0,.2,1), opacity .2s .05s;
  padding-right:0;
  white-space:nowrap;
}
.fab-expand:hover .fab-label,.fab-expand:focus-visible .fab-label{
  max-width:220px;opacity:1;padding-right:20px;
}
.fab-expand.fab-touch-open{min-width:fit-content}
.fab-expand.fab-touch-open .fab-label{max-width:220px;opacity:1;padding-right:20px}

/* Поле ручного ввода количества (печи, крафт-счётчики) — выглядит как число, а не как обычный текстовый инпут */
.smelt-count-input{
  font-size:24px;font-weight:700;text-align:center;
  width:70px;background:var(--bg-card-alt);border:1px solid var(--border);color:var(--text-primary);
  border-radius:10px;padding:8px 4px;
}
.smelt-count-input:focus{outline:none;border-color:var(--accent)}

/* Плавающая круглая кнопка (FAB) — резервируем место снизу страницы, чтобы она не перекрывала
   последний элемент контента (например, кнопку "Скопировать" в апгрейде или итог в рейде) */
body:has(.fab-expand) .content-panel{padding-bottom:90px}

/* Поле ввода количества в счётчике крафта — заменяет прежний <b>, теперь редактируемое */
.craft-count{
  width:52px;text-align:center;font-weight:700;font-size:15px;
  background:var(--bg-card-alt);border:1px solid var(--border);color:var(--text-primary);
  border-radius:8px;padding:6px 2px;
}
.craft-count:focus{outline:none;border-color:var(--accent)}
.fab-badge{
  position:absolute;top:-4px;right:-4px;
  min-width:24px;height:24px;padding:0 6px;
  border-radius:12px;background:#fff;color:var(--accent);
  font-size:12px;font-weight:800;
  display:flex;align-items:center;justify-content:center;
  border:2px solid var(--bg-card-alt);
  z-index:2;
  box-shadow:0 2px 6px rgba(0,0,0,.3);
}
@media (max-width:1099px){
  /* На мобиле подпись по hover не сработает (нет курсора) — раскрываем по долгому нажатию
     через JS (см. raid.js), здесь просто не даём подписи мешать при обычных тапах. */
  .fab-expand .fab-label{transition:max-width .3s cubic-bezier(.4,0,.2,1), opacity .15s}
}/* ===== "Вау-момент" карточки результата расчёта =====
   Применяется к главному числовому результату калькулятора (сейчас — блок "Самый
   дешёвый способ" в Рейде, см. openItem() в raid.js) в момент его появления. Три части
   эффекта работают вместе, но каждая с отдельной ролью, а не просто "анимировать всё":
   1) сама карточка появляется через scale+fade вместо мгновенного показа (result-hero-in) —
      мягкий, но заметный жест "вот твой ответ", а не резкий скачок текста;
   2) holo-градиентная обводка держится не постоянно, а всего один цикл при появлении
      (resultHoloRing, ровно один запуск holoSweep через animation-iteration-count:1) —
      если оставить бесконечной, она станет фоновым шумом и перестанет читаться как
      "момент", поэтому обводка проигрывает один проход и гаснет в статичный var(--accent);
   3) цифра считается вверх от 0 до итога через requestAnimationFrame в JS
      (см. animateNumber() в core.js) — здесь только сопутствующий CSS-класс.
   Работает при ЛЮБОМ выбранном акценте, не только holo: --holo-1..--holo-5 для плоских
   тем равны var(--accent) (см. :root), поэтому обводка получается однотонной пульсацией
   вместо перелива — эффект деградирует красиво, а не ломается. */
.result-hero{
  position:relative;
  animation:resultHeroIn .5s cubic-bezier(.22,1.4,.36,1);
}
@keyframes resultHeroIn{
  from{opacity:0;transform:scale(.92) translateY(8px)}
  to{opacity:1;transform:none}
}
.result-hero::before{
  content:'';
  position:absolute;
  inset:-2px;
  border-radius:inherit;
  padding:2px;
  background-image:linear-gradient(100deg,var(--holo-1),var(--holo-2),var(--holo-3),var(--holo-4),var(--holo-5),var(--holo-1),var(--holo-2),var(--holo-3),var(--holo-4),var(--holo-5),var(--holo-1),var(--holo-2));
  background-size:200% 100%;
  background-repeat:no-repeat;
  -webkit-mask:linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite:xor;
  mask-composite:exclude;
  animation:holoSweep .9s ease-out 1, resultRingFade 1.8s ease-out forwards;
  pointer-events:none;
}
@keyframes resultRingFade{
  0%,55%{opacity:1}
  100%{opacity:0}
}
/* Сама цифра — для animateNumber() в core.js, чуть плотнее трекинг на крупном размере,
   чтобы отсчитывающиеся большие числа не "дрожали" по ширине на каждый кадр из-за
   разной ширины цифр в некоторых шрифтах. */
.result-hero-number{
  font-variant-numeric:tabular-nums;
}



/* ===== Панель настроек (кнопка-шестерёнка в шапке) =====
   Заменяет прежние отдельно стоящие .badge (версия) и .lang-switch — теперь оба живут
   внутри одной панели вместе с выбором акцентного цвета и темы. Кнопка-шестерёнка —
   единственный видимый элемент в шапке, всё остальное открывается по клику в drawer
   справа (тот же паттерн подъезжающей панели, что уже используется в toast-stack/FAB,
   не вводим новый визуальный язык). На мобиле drawer растягивается на всю ширину. */
.settings-trigger{
  width:44px;height:44px;border-radius:12px;
  background:var(--bg-card);border:1px solid var(--border);
  color:var(--text-secondary);font-size:19px;
  display:flex;align-items:center;justify-content:center;
  cursor:pointer;transition:.2s;flex-shrink:0;
}
.settings-trigger:hover{border-color:var(--accent);color:var(--text-primary)}
.settings-trigger:active{transform:scale(.92)}
/* Поворот шестерёнки происходит осознанно — когда панель настроек реально открыта
   (класс settings-open навешивается на trigger в JS вместе с открытием drawer),
   а не на каждый hover, который выглядел как случайное дёрганье при наведении. */
.settings-trigger.settings-open{border-color:var(--accent);color:var(--accent);transform:rotate(90deg)}

/* ===== Подсказка про голографические акценты =====
   Всплывает один раз при первом визите под кнопкой-шестерёнкой (см. initHoloHint
   в core.js) — намекает на holo-раздел в настройках, не трогая ничего в остальном
   интерфейсе и не подменяя выбор темы автоматически (см. обсуждение в чате: holo
   остаётся опцией, которую человек выбирает сам, подсказка только показывает, что
   она существует). Обводка и текст используют --holo-1..--holo-5 текущего акцента
   как живой, уже переливающийся пример эффекта — если сейчас выбран плоский акцент
   (--holo-* тогда все равны var(--accent), см. :root), обводка/текст останутся
   однотонными и анимация выше просто не даст видимой разницы: ничего не сломается,
   подсказка просто менее "вкусная" на вид, пока человек не попробует holo сам. */
.holo-hint{
  position:absolute;
  top:calc(100% + 10px);
  left:0;
  z-index:120;
  display:flex;align-items:center;gap:8px;
  background:var(--bg-card);
  border:1px solid var(--border);
  border-radius:12px;
  padding:9px 10px 9px 14px;
  box-shadow:0 10px 28px rgba(0,0,0,.4);
  white-space:nowrap;
  animation:holoHintIn .4s cubic-bezier(.34,1.56,.64,1);
}
/* Стрелка-указатель вверх, направленная точно на кнопку-шестерёнку слева от неё. */
.holo-hint::before{
  content:'';
  position:absolute;
  top:-6px;left:16px;
  width:11px;height:11px;
  background:var(--bg-card);
  border-left:1px solid var(--border);
  border-top:1px solid var(--border);
  transform:rotate(45deg);
}
.holo-hint-text{
  font-size:13px;font-weight:600;
  background-image:linear-gradient(100deg,var(--holo-1),var(--holo-2),var(--holo-3),var(--holo-4),var(--holo-5),var(--holo-1),var(--holo-2),var(--holo-3),var(--holo-4),var(--holo-5),var(--holo-1),var(--holo-2));
  background-size:200% 100%;
  background-repeat:no-repeat;
  -webkit-background-clip:text;
  background-clip:text;
  -webkit-text-fill-color:transparent;
  color:var(--accent);
  animation:holoSweep var(--holo-anim-duration) ease-in-out infinite alternate;
}
.holo-hint-close{
  background:none;border:none;color:var(--text-muted);cursor:pointer;
  font-size:13px;line-height:1;padding:2px;flex-shrink:0;
  -webkit-tap-highlight-color:transparent;
}
.holo-hint-close:hover{color:var(--text-primary)}
@keyframes holoHintIn{
  from{opacity:0;transform:translateY(-6px) scale(.95)}
  to{opacity:1;transform:none}
}
@media(max-width:640px){
  /* На мобильном header-badges — это просто обёртка по ширине самой кнопки (44px),
     поэтому right:0 здесь означало бы "0 от правого края этих 44px", а не от края
     экрана — из-за этого подсказка раньше улетала за левую границу вьюпорта вместе
     со своим nowrap-текстом. Правильная точка отсчёта — левый край кнопки (left:0,
     как на десктопе), а не правый; ширина ограничена и подсказке разрешено переносить
     текст на две строки, если она всё равно не помещается на очень узких экранах. */
  .holo-hint{
    left:0;right:auto;
    max-width:calc(100vw - 40px);
    white-space:normal;
  }
  .holo-hint::before{left:16px;right:auto}
}

.settings-overlay{
  position:fixed;inset:0;
  background:rgba(0,0,0,.55);
  z-index:1300;
  opacity:0;pointer-events:none;
  transition:opacity .25s ease;
}
.settings-overlay.open{opacity:1;pointer-events:auto}

.settings-drawer{
  position:fixed;top:0;right:0;bottom:0;
  width:min(380px,100vw);
  background:var(--bg-card);
  border-left:1px solid var(--border);
  z-index:1301;
  display:flex;flex-direction:column;
  transform:translateX(100%);
  transition:transform .3s cubic-bezier(.4,0,.2,1);
  overflow-y:auto;
}
.settings-drawer.open{transform:translateX(0)}

.settings-header{
  display:flex;align-items:center;justify-content:space-between;
  padding:22px 24px;border-bottom:1px solid var(--border);
  flex-shrink:0;
}
.settings-header h3{font-size:19px}
.settings-close{
  width:36px;height:36px;border-radius:10px;border:1px solid var(--border);
  background:var(--bg-card-alt);color:var(--text-secondary);
  font-size:16px;cursor:pointer;transition:.2s;
  display:flex;align-items:center;justify-content:center;
}
.settings-close:hover{border-color:var(--accent);color:var(--text-primary)}

.settings-body{padding:22px 24px;display:flex;flex-direction:column;gap:28px}
.settings-section-label{
  font-size:12px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--text-muted);margin-bottom:12px;font-weight:700;
}

/* Кружки выбора акцентного цвета — сам кружок залит соответствующим цветом (не через
   var(--accent), т.к. все 5 должны быть видны одновременно вне зависимости от того,
   какой сейчас активен), с кольцом-обводкой и галочкой на активном варианте. */
.accent-swatches{display:flex;gap:14px;flex-wrap:wrap}
.accent-swatch{
  width:42px;height:42px;border-radius:50%;
  cursor:pointer;border:2px solid transparent;
  display:flex;align-items:center;justify-content:center;
  transition:transform .15s, border-color .15s;
  position:relative;
}
.accent-swatch:hover{transform:scale(1.1)}
.accent-swatch.active{border-color:var(--text-primary)}
.accent-swatch.active::after{
  content:'✓';color:#fff;font-size:16px;font-weight:800;
  text-shadow:0 1px 3px rgba(0,0,0,.5);
}
.accent-swatch[data-accent-value="purple"]{background:#8B5CF6}
.accent-swatch[data-accent-value="orange"]{background:#F97316}
.accent-swatch[data-accent-value="red"]{background:#EF4444}
.accent-swatch[data-accent-value="green"]{background:#22C55E}
.accent-swatch[data-accent-value="blue"]{background:#3B82F6}

/* Подпись "Голографические" — чуть отступлена сверху от предыдущего ряда обычных
   свотчей, тот же визуальный вес что и у settings-section-label выше по разметке. */
.holo-label{margin-top:18px}

/* Кратковременная подсветка раздела голо-акцентов, когда человек попадает сюда по клику
   на подсказку (см. holoHint в core.js/index.html) — глаз сразу цепляется за нужное
   место среди остальных разделов панели настроек, вместо того чтобы искать самому. */
@keyframes holoFocusPulse{
  0%,100%{box-shadow:none}
  30%{box-shadow:0 0 0 3px rgba(var(--accent-rgb),.35)}
}
.holo-focus-pulse{
  border-radius:14px;
  animation:holoFocusPulse 1.6s ease;
}

/* Голо-свотчи в самой панели настроек — тот же плывущий слева направо linear-gradient,
   что и в остальном интерфейсе (см. holoSweep выше). Свотчи — витрина эффекта: если
   здесь заливка статична, человек не видит переливания до того, как уже выбрал акцент,
   и решение "нравится/не нравится" принимается вслепую. Каждый свотч анимируется тем же
   @keyframes holoSweep, но с собственным animation-delay (см. :nth-child ниже) — так
   все 5 плывут не синхронно в такт, а слегка вразнобой, что выглядит как живой перелив,
   а не как один узор, механически повторённый 5 раз. background-size:300% растягивает
   градиент в 3 раза шире круглого свотча — на маленькой площади (42px) без растяжки волна
   пробегала бы слишком быстро и резко, как мигание, а не плавный перелив. */
.accent-swatch-holo{
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.25);
  background-size:200% 100%;
  background-repeat:no-repeat;
  animation:holoSweep 4s ease-in-out infinite alternate;
}
.accent-swatch-holo:nth-child(2){animation-delay:-.8s}
.accent-swatch-holo:nth-child(3){animation-delay:-1.6s}
.accent-swatch-holo:nth-child(4){animation-delay:-2.4s}
.accent-swatch-holo:nth-child(5){animation-delay:-3.2s}
.accent-swatch[data-accent-value="holo-purple"]{background-image:linear-gradient(100deg,#2F16FE,#7953FF,#C9B3FB,#9653FF,#962BFF,#2F16FE,#7953FF,#C9B3FB,#9653FF,#962BFF)}
.accent-swatch[data-accent-value="holo-orange"]{background-image:linear-gradient(100deg,#D22C00,#FF5E10,#FBA96F,#FF8610,#E68C00,#D22C00,#FF5E10,#FBA96F,#FF8610,#E68C00)}
.accent-swatch[data-accent-value="holo-red"]{background-image:linear-gradient(100deg,#EF0735,#FE3546,#F69999,#FE4635,#F84012,#EF0735,#FE3546,#F69999,#FE4635,#F84012)}
.accent-swatch[data-accent-value="holo-green"]{background-image:linear-gradient(100deg,#119927,#11D649,#5FE390,#11D66A,#12AC6A,#119927,#11D649,#5FE390,#11D66A,#12AC6A)}
.accent-swatch[data-accent-value="holo-blue"]{background-image:linear-gradient(100deg,#008DF4,#3291FF,#93BAFA,#326FFF,#0935FF,#008DF4,#3291FF,#93BAFA,#326FFF,#0935FF)}

/* Карточки выбора темы — мини-превью (тёмный/светлый/чёрный квадратик) вместо голого
   текста, чтобы пользователь визуально понимал разницу до клика, не только по названию. */
.theme-options{display:flex;flex-direction:column;gap:10px}
.theme-option{
  display:flex;align-items:center;gap:14px;
  padding:12px 14px;border-radius:12px;
  background:var(--bg-card-alt);border:1px solid var(--border);
  cursor:pointer;transition:.2s;
}
.theme-option:hover{border-color:var(--accent)}
.theme-option.active{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent)}
.theme-preview{
  width:38px;height:38px;border-radius:10px;flex-shrink:0;
  border:1px solid rgba(255,255,255,.08);
}
.theme-preview.preview-dark{background:linear-gradient(135deg,#1A1D24,#0F1115)}
.theme-preview.preview-light{background:linear-gradient(135deg,#FFFFFF,#E5E7EB)}
.theme-preview.preview-oled{background:linear-gradient(135deg,#0A0A0A,#000000)}
.theme-option-text b{font-size:14px;display:block}
.theme-option-text span{font-size:12px;color:var(--text-secondary)}

/* Переключатель языка внутри панели — тот же .lang-switch стиль что и раньше, теперь
   просто живёт в новом месте, плюс версия сайта под ним как обычная строка метаданных. */
.settings-lang-row{
  display:flex;align-items:center;justify-content:space-between;
  padding:12px 14px;border-radius:12px;
  background:var(--bg-card-alt);border:1px solid var(--border);
}
.settings-lang-row span{font-size:14px;color:var(--text-secondary)}
.lang-switch{
  background:var(--bg-card);border:1px solid var(--border);color:var(--text-primary);
  padding:8px 14px;border-radius:9px;font-size:13px;font-weight:600;
  cursor:pointer;transition:.2s;
}
.lang-switch:hover{border-color:var(--accent)}
.settings-version-row{
  font-size:13px;color:var(--text-muted);
  display:flex;align-items:center;justify-content:space-between;
  padding-top:4px;
}
/* Пульсирующая точка-статус рядом с версией сайта — дешёвая, но узнаваемая деталь
   в духе "онлайн"-индикаторов Discord/Slack. Чисто декоративная (сайт статичный,
   не проверяет реальный статус сервера), сигнализирует "всё работает" на уровне
   ощущения, не факта — если в будущем появится реальная проверка статуса (аптайм
   API и т.п.), эту же точку можно запитать от неё без изменения разметки. */
.status-dot{
  width:8px;height:8px;border-radius:50%;
  background:var(--success);
  flex-shrink:0;
  position:relative;
}
.status-dot::after{
  content:'';
  position:absolute;inset:0;
  border-radius:50%;
  background:var(--success);
  animation:statusPulse 2s ease-out infinite;
}
@keyframes statusPulse{
  0%{transform:scale(1);opacity:.7}
  100%{transform:scale(2.4);opacity:0}
}
