:root{
  --bg: #f3f1fb;
  --bg-alt: #ebe7f7;
  --surface: #ffffff;
  --border: #ddd6f0;
  --text: #1c1830;
  --text-dim: #5b5470;
  --text-faint: #8b85a8;
  --accent: #0e9c8f;
  --accent-strong: #0a7568;
  --accent-soft: #d9f5f0;
  --gold: #8a5cf0;
  --gold-soft: #ece3fd;
  --danger: #c23f3f;
  --shadow: 0 1px 2px rgba(28,24,48,0.06), 0 8px 24px -12px rgba(28,24,48,0.16);
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --bg: #12101c;
    --bg-alt: #171426;
    --surface: #1b1830;
    --border: #2a2440;
    --text: #f0eef7;
    --text-dim: #b0a9c9;
    --text-faint: #8b85a8;
    --accent: #4ce0d2;
    --accent-strong: #7ff0e5;
    --accent-soft: #16332f;
    --gold: #b388ff;
    --gold-soft: #2a2144;
    --danger: #ff6f8f;
    --shadow: 0 1px 2px rgba(0,0,0,0.4), 0 16px 40px -18px rgba(76,224,210,0.14), 0 12px 32px -14px rgba(0,0,0,0.7);
  }
}
:root[data-theme="dark"]{
  --bg: #12101c;
  --bg-alt: #171426;
  --surface: #1b1830;
  --border: #2a2440;
  --text: #f0eef7;
  --text-dim: #b0a9c9;
  --text-faint: #8b85a8;
  --accent: #4ce0d2;
  --accent-strong: #7ff0e5;
  --accent-soft: #16332f;
  --gold: #b388ff;
  --gold-soft: #2a2144;
  --danger: #ff6f8f;
  --shadow: 0 1px 2px rgba(0,0,0,0.4), 0 16px 40px -18px rgba(76,224,210,0.14), 0 12px 32px -14px rgba(0,0,0,0.7);
}
/* Фирменное радиальное свечение фона — только в тёмной теме, тот же приём,
   что и в макете аркадного направления (Этап 12). */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) body{
    background: radial-gradient(1100px 500px at 15% -10%, #241c3a 0%, #12101c 55%), var(--bg);
  }
}
:root[data-theme="dark"] body{
  background: radial-gradient(1100px 500px at 15% -10%, #241c3a 0%, #12101c 55%), var(--bg);
}

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

/* Стрелочки вверх/вниз у числовых полей — везде по приложению, не только у
   отдельных полей, которые заметили раньше (craft-tree-qty-input). Ничего не
   дают (тыкать по одной единице в поле "мин. цена лота" никто не будет), а
   на широких числах (миллионы, миллиарды) только мешают и жрут место. */
input[type="number"]{ -moz-appearance:textfield; appearance:textfield; }
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button{ -webkit-appearance:none; margin:0; }

/* Тонкий скроллбар в цветах темы вместо толстого системного (в Electron это
   всегда белая/светлая полоса от Chromium, режет глаз на тёмной теме) — везде
   сразу, не только там, где заметили (модалки, попапы дропдаунов, страница). */
*{ scrollbar-width:thin; scrollbar-color:var(--border) transparent; }
*::-webkit-scrollbar{ width:10px; height:10px; }
*::-webkit-scrollbar-track{ background:transparent; }
*::-webkit-scrollbar-thumb{
  background-color:var(--border); border-radius:8px; border:2px solid transparent; background-clip:padding-box;
}
*::-webkit-scrollbar-thumb:hover{ background-color:var(--text-faint); }
/* Настоящая причина застрявшего красного баннера (и потенциально любого
   другого элемента с атрибутом hidden): некоторые классы (.alert-banner,
   .daily-limit-bar и т.п.) сами объявляют display:flex с той же специфичностью
   (0,1,0), что и встроенное [hidden]{display:none} — и, т.к. авторский CSS
   идёт после браузерного, класс побеждает, элемент виден, даже когда JS
   выставил hidden=true. [hidden] с явным классом-селектором даёт специфичность
   (0,2,0) — выше любого одиночного класса, побеждает без !important и без
   гонки за порядком объявления в файле. Та же природа бага, что раньше ловили
   на панели фильтров (.filters-extra) — там решили сменой техники анимации,
   здесь эту же причину чинят на уровне каскада для всех элементов сразу. */
[hidden]{ display:none !important; }
body{
  background:var(--bg);
  color:var(--text);
  font-family:'Manrope',system-ui,sans-serif;
  font-size:15px;
  line-height:1.5;
}

header.top{
  position:sticky; top:0; z-index:20;
  background:var(--bg-alt);
  border-bottom:1px solid var(--border);
}
.top-inner{
  max-width:1200px; margin:0 auto;
  display:flex; align-items:center; gap:20px;
  padding:14px 24px;
}
.brand{ display:flex; align-items:center; gap:10px; font-family:'Sora',sans-serif; font-weight:600; font-size:16px; }
.brand-version{ font-family:'IBM Plex Mono',monospace; font-weight:400; font-size:11px; color:var(--text-faint); }
/* Кнопка обновлений в шапке — по умолчанию просто кружок "↻" (icon-btn),
   меняет вид по состоянию (js/app.js, initAppUpdater/applyUpdateState):
   idle -> checking (крутится) -> available/downloading/downloaded (зелёная
   неоновая "таблетка" с текстом, пульсирует) -> error (лёгкий красный тон). */
.update-badge.state-checking{ animation:update-badge-spin .9s linear infinite; }
.update-badge.state-available, .update-badge.state-downloading, .update-badge.state-downloaded{
  width:auto; padding:0 12px; height:28px; font-family:'IBM Plex Mono',monospace; font-size:11.5px; font-weight:700;
  background:var(--accent); border-color:var(--accent); color:#04120c;
  animation:update-badge-pulse 1.8s ease-in-out infinite;
}
.update-badge.state-error{ border-color:var(--danger); color:var(--danger); }
@keyframes update-badge-spin{ to{ transform:rotate(360deg); } }
@keyframes update-badge-pulse{
  0%, 100%{ box-shadow:0 0 8px 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  50%{ box-shadow:0 0 18px 4px color-mix(in srgb, var(--accent) 85%, transparent); }
}
.status{ position:relative; margin-left:auto; display:flex; align-items:center; }
/* Точка-индикатор подключения к серверу — раньше рядом был ещё и текст
   статуса/кнопка "повторить", теперь только точка. Была декоративная
   .brand-dot у логотипа — убрана как дубликат. */
.status-dot{
  width:7px; height:7px; border-radius:50%; background:var(--text-faint);
  box-shadow:0 0 0 4px color-mix(in srgb, var(--text-faint) 25%, transparent);
  cursor:default;
}
/* Своя подсказка вместо нативного title — тот моргает у браузера при каждом
   обновлении атрибута (а текст возраста данных обновляется раз в секунду,
   см. updateNextUpdateTimer() в app.js), т.к. браузер пересоздаёт тултип
   при любом изменении title, даже пока курсор уже наведён. Здесь просто
   меняется textContent у уже показанного элемента — не мигает. */
.status-tooltip{
  position:absolute; top:100%; right:0; margin-top:10px;
  background:var(--surface); border:1px solid var(--border); border-radius:8px;
  padding:6px 10px; font-family:'IBM Plex Mono',monospace; font-size:11.5px; color:var(--text-dim);
  white-space:nowrap; box-shadow:var(--shadow); z-index:50;
  opacity:0; pointer-events:none; transform:translateY(-4px);
  transition:opacity .12s ease, transform .12s ease;
}
.status:hover .status-tooltip{ opacity:1; transform:translateY(0); }
.status-dot.live{ background:var(--accent); box-shadow:0 0 0 4px var(--accent-soft); animation:status-dot-pulse 2.2s ease-in-out infinite; }
.status-dot.err{ background:var(--danger); box-shadow:0 0 0 4px color-mix(in srgb, var(--danger) 25%, transparent); }
@keyframes status-dot-pulse{
  0%, 100%{ box-shadow:0 0 0 4px var(--accent-soft); }
  50%{ box-shadow:0 0 0 6px color-mix(in srgb, var(--accent) 35%, transparent); }
}
.icon-btn{
  background:var(--surface); border:1px solid var(--border); color:var(--text-dim);
  width:32px; height:32px; border-radius:10px; cursor:pointer; font-size:14px;
}
.icon-btn:hover{ border-color:var(--accent); color:var(--accent); }

/* Тёмный аукцион — реальное игровое событие в Хабе (каждый час на 55-й
   минуте), см. js/darkAuction.js. Просто текстовый бейдж-таймер в шапке. */
/* Полоса таймеров реальных игровых событий (Тёмный аукцион и т.п.) — под
   шапкой, не в ней самой: там и так тесно от иконок/бейджей, а сюда со
   временем можно добавлять ещё таймеры в ряд, не переделывая шапку. */
.event-timers{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  max-width:1200px; margin:0 auto; padding:8px 24px 0;
}
.event-timer-badge{
  display:inline-flex; align-items:center; gap:4px;
  background:var(--surface); border:1px solid var(--border); border-radius:10px;
  padding:0 4px 0 10px; height:26px; font-family:'IBM Plex Mono',monospace; font-size:11.5px;
  color:var(--text-dim); white-space:nowrap;
}
/* Колокольчик подписки на звуковое уведомление за минуту до события —
   выключен по умолчанию (кроме Тёмного аукциона, см. DEFAULT_SETTINGS),
   тусклый/чёрно-белый, пока не включён кликом; зелёный и на полной
   непрозрачности, когда подписка активна. */
.event-bell{
  display:inline-flex; align-items:center; justify-content:center;
  width:20px; height:20px; padding:0; margin-left:2px;
  background:transparent; border:none; border-radius:6px; cursor:pointer;
  font-size:12px; opacity:.35; filter:grayscale(1); line-height:1;
}
.event-bell:hover{ opacity:.7; background:var(--bg); }
.event-bell.active{ opacity:1; filter:none; }

.wrap{ max-width:1200px; margin:0 auto; padding:24px; }

.alert-badge{
  background:var(--danger); color:#fff; font-family:'IBM Plex Mono',monospace; font-size:11px; font-weight:600;
  border-radius:100px; padding:2px 7px; min-width:18px; text-align:center;
}
.alert-banner{
  position:sticky; top:57px; z-index:19;
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  background:var(--danger); color:#fff; padding:10px 24px; font-size:14px; font-weight:600;
  animation:flashbar 1s ease-in-out 3;
}
.alert-banner .icon-btn{ background:transparent; border-color:rgba(255,255,255,.4); color:#fff; }
/* Новое совпадение сканера — хорошая новость, не тревога, поэтому зелёный акцент вместо красного */
.alert-banner.tone-good{ background:var(--accent); }
@keyframes flashbar{ 0%,100%{ opacity:1; } 50%{ opacity:.55; } }
@media (prefers-reduced-motion: reduce){ .alert-banner{ animation:none; } }

/* Дневной лимит сделок базара (15 млрд монет/сутки у Hypixel) — ручной трекер по журналу сделок */
.daily-limit-bar{
  display:flex; align-items:center; gap:12px;
  background:var(--surface); border-bottom:1px solid var(--border);
  padding:8px 24px; font-size:12px; color:var(--text-dim); font-family:'IBM Plex Mono',monospace;
}
.daily-limit-track{ flex:1; max-width:260px; height:6px; border-radius:100px; background:var(--bg-alt); overflow:hidden; }
.daily-limit-fill{ height:100%; background:var(--accent); border-radius:100px; transition:width .3s ease; }
.daily-limit-fill.near-limit{ background:var(--danger); }

.watchlist{
  border:1px solid var(--border); border-radius:18px; background:var(--surface);
  padding:16px 20px; margin-bottom:20px; box-shadow:var(--shadow);
}
.watchlist-head{ display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap; margin-bottom:12px; }
.watchlist-head h2{ font-family:'Sora',sans-serif; font-size:15px; margin:0; }
.watchlist-body{ display:flex; flex-wrap:wrap; gap:10px; }
.watch-chip{
  display:flex; align-items:center; gap:8px;
  background:var(--bg-alt); border:1px solid var(--border); border-radius:13px; padding:8px 12px; font-size:13px; cursor:pointer;
}
.watch-chip:hover{ border-color:var(--accent); }
.watch-chip .wc-name{ font-weight:600; }
.watch-chip .wc-delta{ font-family:'IBM Plex Mono',monospace; font-size:12px; }
.watch-chip .wc-delta.down{ color:var(--danger); }
.watch-chip .wc-delta.up{ color:var(--accent); }
.watch-chip .wc-remove{ background:none; border:none; color:var(--text-faint); cursor:pointer; font-size:13px; padding:0; }
.watch-chip .wc-remove:hover{ color:var(--danger); }

/* "С прошлого захода" — просто справочная информация, не функциональная
   панель уровня Watchlist/Аукцион-снайпера, поэтому визуально потише: без
   тени, без большого паддинга, приглушённый фон вместо --surface. */
#bazaarMoversDigest{
  background:var(--bg-alt); box-shadow:none; padding:10px 16px; border-radius:14px;
}
#bazaarMoversDigest .watchlist-head{ margin-bottom:8px; }
#bazaarMoversDigest .watchlist-head h2{ font-size:12px; font-weight:600; color:var(--text-faint); text-transform:uppercase; letter-spacing:.04em; }
#bazaarMoversDigest .watch-chip{ padding:5px 10px; font-size:12px; background:var(--surface); }
/* Кнопка закрытия — раньше висела на классе .wc-remove, а его стили завязаны
   на предка .watch-chip (см. выше), которого тут нет — кнопка молча падала
   на нативный вид браузера (белый квадрат с рамкой). Свой класс, тот же
   визуальный язык (без фона/рамки, тускло-серый, краснеет на ховере). */
.movers-digest-close{
  background:none; border:none; color:var(--text-faint); cursor:pointer;
  font-size:13px; font-family:inherit; padding:4px; line-height:1; border-radius:6px;
}
.movers-digest-close:hover{ color:var(--danger); background:rgba(255,255,255,.05); }
/* Тонкая полоска снизу — тает за 15с (BAZAAR_MOVERS_AUTO_HIDE_MS в app.js),
   чтобы скрытие панели не выглядело внезапным багом, а читалось как обычный
   исчезающий тост. Анимация перезапускается в renderBazaarMoversDigest(). */
.movers-digest-timer{
  height:2px; margin-top:10px; border-radius:2px; background:var(--accent);
  opacity:.5; animation:movers-digest-shrink 15s linear forwards;
  transform-origin:left;
}
@keyframes movers-digest-shrink{ from{ transform:scaleX(1); } to{ transform:scaleX(0); } }
@media (prefers-reduced-motion: reduce){ .movers-digest-timer{ animation:none; opacity:0; } }

.star-col{ width:34px; }
.star-btn-cell{
  background:none; border:none; cursor:pointer; font-size:16px; color:var(--text-faint); padding:0;
}
.star-btn-cell.on{ color:var(--gold); }
.star-btn-cell:hover{ color:var(--gold); }

.controls{
  display:flex; flex-wrap:wrap; gap:14px; align-items:end; margin-bottom:18px;
}
.controls input[type="text"]{
  flex:1; min-width:220px;
  background:var(--surface); border:1px solid var(--border); border-radius:13px;
  padding:10px 14px; color:var(--text); font-family:'Manrope',sans-serif; font-size:14px;
}
.control-group{ display:flex; flex-direction:column; gap:5px; }
.control-group label{ font-family:'IBM Plex Mono',monospace; font-size:11px; text-transform:uppercase; letter-spacing:.06em; color:var(--text-faint); }
.help-hint{
  display:inline-flex; align-items:center; justify-content:center; width:14px; height:14px;
  border-radius:50%; background:var(--bg-alt); border:1px solid var(--border); color:var(--text-faint);
  font-size:10px; font-weight:700; text-transform:none; letter-spacing:0; cursor:help; vertical-align:1px;
}
.help-hint:hover{ background:var(--accent); border-color:var(--accent); color:#fff; }
/* Раньше подсказка была доступна только по ховеру мышью — добавлен
   tabindex="0" (см. index.html), чтобы её можно было дотабаться с клавиатуры;
   :focus-visible даёт ту же подсветку, что и hover, а нативный title
   у фокусируемого элемента показывается браузером и по Tab, не только по ховеру. */
.help-hint:focus-visible{ background:var(--accent); border-color:var(--accent); color:#fff; outline:2px solid var(--accent); outline-offset:2px; }
.mc-uuid-status{ font-size:12px; color:var(--text-faint); }
.mc-uuid-status.ok{ color:var(--accent); }
.mc-uuid-status.warn{ color:var(--gold); }
.control-group input, .control-group select{
  background:var(--surface); border:1px solid var(--border); border-radius:13px;
  padding:9px 12px; color:var(--text); font-family:'IBM Plex Mono',monospace; font-size:13px; width:130px;
}
input:focus, select:focus{ outline:2px solid var(--accent); outline-offset:1px; }

#bzTradeItem{ width:240px; }

.table-note{ font-size:12.5px; color:var(--text-faint); margin:-6px 0 14px; max-width:70ch; }
.table-note code{ font-family:'IBM Plex Mono',monospace; background:var(--bg-alt); padding:1px 5px; border-radius:6px; }

/* Миньоны — боковая панель апгрейдов/маяка/топлива, по образцу outcrocalculator.com */
.minions-layout{ display:flex; gap:20px; align-items:flex-start; }
.minions-sidebar{ flex:0 0 260px; display:flex; flex-direction:column; gap:14px; position:sticky; top:16px; }
.minions-results{ flex:1; min-width:0; }
.minion-group{
  border:1px solid var(--border); border-radius:14px; background:var(--bg-alt);
  padding:14px 16px; display:flex; flex-direction:column; gap:10px;
}
.minion-group h3{
  margin:0; font-family:'IBM Plex Mono',monospace; font-size:11px; text-transform:uppercase;
  letter-spacing:.06em; color:var(--text-faint);
}
.minion-group .control-group{ gap:4px; }
.minion-group .control-group select{ width:100%; }

/* Кастомный дропдаун (топливо/маяк/кристалл/expander) — попап со списком и
   галочкой у выбранного пункта, тот же визуальный паттерн, что у
   outcrocalculator.com, просто в цветах приложения вместо их фиолетово-синих. */
.mc-select{ position:relative; }
.mc-select-btn{
  width:100%; display:flex; align-items:center; justify-content:space-between; gap:8px;
  background:var(--surface); border:1px solid var(--border); border-radius:13px;
  padding:9px 12px; color:var(--text); font-family:'IBM Plex Mono',monospace; font-size:13px;
  cursor:pointer; text-align:left;
}
.mc-select-btn:hover{ border-color:var(--accent); }
.mc-select.open .mc-select-btn{ border-color:var(--accent); outline:2px solid var(--accent); outline-offset:1px; }
.mc-select-caret{ color:var(--text-faint); font-size:11px; flex:none; }
.mc-select-menu{
  position:absolute; top:calc(100% + 6px); left:0; right:0; z-index:40;
  background:var(--surface); border:1px solid var(--border); border-radius:14px;
  box-shadow:var(--shadow); padding:6px; max-height:280px; overflow-y:auto;
}
.mc-select-item{
  width:100%; display:flex; align-items:center; justify-content:space-between; gap:10px;
  background:none; border:none; border-radius:9px; padding:8px 10px;
  color:var(--text-dim); font-family:'Manrope',sans-serif; font-size:13px; text-align:left; cursor:pointer;
}
.mc-select-item:hover{ background:var(--bg-alt); color:var(--text); }
.mc-select-item.selected{ color:var(--accent); font-weight:600; }
.mc-select-item .mc-select-check{ opacity:0; color:var(--accent); }
.mc-select-item.selected .mc-select-check{ opacity:1; }
@media (max-width: 900px){
  .minions-layout{ flex-direction:column; }
  .minions-sidebar{ flex:none; width:100%; position:static; }
}

/* Декоративная "витрина" сверху панели — силуэт миньона + колонка слотов с
   иконками текущих включённых апгрейдов (не выбор предмета, просто отражает
   уже включённые галочки/дропдауны слева, по образцу outcrocalculator.com,
   в цветах приложения). Чисто внешний вид, на расчёт не влияет. */
.minions-hero{
  position:relative; display:flex; align-items:stretch; gap:10px;
  border:1px solid var(--border); border-radius:14px; overflow:hidden;
  background:radial-gradient(120% 140% at 30% 20%, var(--bg-alt) 0%, var(--surface) 70%);
  min-height:170px; padding:10px;
}
.minions-hero-figure{
  flex:1; display:flex; align-items:center; justify-content:center; position:relative;
}
.minions-hero-figure svg{ width:76px; height:120px; }
.minions-hero-figure .mh-silhouette{ fill:var(--text-faint); opacity:.55; }
.minions-hero-figure .mh-question{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font-family:'Sora',sans-serif; font-weight:800; font-size:40px; color:var(--text);
  text-shadow:0 2px 10px rgba(0,0,0,.35);
}
.minions-hero-slots{ display:flex; flex-direction:column; gap:8px; justify-content:center; }
.minions-hero-slot{
  width:44px; height:44px; border-radius:11px; border:1px solid var(--border);
  background:var(--surface); display:flex; align-items:center; justify-content:center;
}
.minions-hero-slot.filled{ border-color:var(--accent); box-shadow:0 0 0 1px var(--accent) inset; }
.minions-hero-slot .item-icon{ width:26px; height:26px; margin:0; }

/* Пороги ROI/объёма/бюджета — раньше сворачивались за кнопкой "▾ Фильтры",
   по прямой просьбе пользователя показываются всегда, отдельной строкой под
   поиском/сортировкой/видом. Значения по-прежнему авто-сохраняются на каждый
   ввод (см. saveTopFilter()/saveBudget() в app.js) — отдельная кнопка
   "Сохранить" не нужна. */
.filters-extra{ margin-bottom:18px; }
.filters-extra-inner{
  display:flex; flex-wrap:wrap; gap:14px; align-items:end;
}

/* Строка с вкладками лидербордов + выпадающим списком "Ещё…" (Часть E) */
.leaderboard-row{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:14px; }
.leaderboard-more{
  /* margin-left:auto — визуально отделяет "Аналитика" (Данжи/Индексы —
     инструменты анализа, не заработок) от вкладок заработка слева, чтобы не
     читалось как ещё одна категория дохода наравне с ними. */
  margin-left:auto;
  background:var(--surface); border:1px solid var(--border); border-radius:13px;
  padding:9px 12px; color:var(--text-dim); font-family:'IBM Plex Mono',monospace; font-size:12.5px; cursor:pointer;
}
.leaderboard-more:hover{ border-color:var(--accent); color:var(--accent); }

.table-wrap{
  border:1px solid var(--border); border-radius:18px; overflow:hidden; background:var(--surface);
  box-shadow:var(--shadow);
}
table{ width:100%; border-collapse:collapse; }
thead th{
  text-align:left; padding:11px 16px; font-family:'IBM Plex Mono',monospace; font-size:11px;
  text-transform:uppercase; letter-spacing:.06em; color:var(--text-faint); background:var(--bg-alt);
  border-bottom:1px solid var(--border);
}
thead th.num{ text-align:right; }
tbody td{ padding:11px 16px; border-bottom:1px solid var(--border); vertical-align:middle; }
tbody tr:last-child td{ border-bottom:none; }
tbody tr:not(.loading-row):not(.empty-row){ cursor:pointer; }
tbody tr:not(.loading-row):not(.empty-row):hover{ background:var(--bg-alt); }
td.num{ text-align:right; font-family:'IBM Plex Mono',monospace; font-variant-numeric:tabular-nums; }
.item-name{ font-weight:600; display:flex; align-items:center; }
.roi-pos{ color:var(--accent); font-weight:600; }
.roi-neg{ color:var(--danger); }

/* Клик по имени предмета копирует команду (Этап 10) — рядом с кнопкой
   "Копировать", без замены текста/иконки (см. flashCopyFeedback() в app.js). */
.item-name-copy, .flip-card-name, .stat-copy{ cursor:pointer; }
.item-name-copy:hover, .flip-card-name:hover, .stat-copy:hover{ color:var(--accent); text-decoration:underline; }
.copy-flash{ color:var(--accent) !important; transition:color .15s; animation:copy-pulse .35s ease; display:inline-block; }
@keyframes copy-pulse{
  0%{ transform:scale(1); }
  45%{ transform:scale(1.1); }
  100%{ transform:scale(1); }
}

/* Иконки предметов */
.item-icon{
  display:inline-block; width:18px; height:18px; margin-right:8px; border-radius:4px;
  flex:none; vertical-align:middle;
  background:var(--bg-alt); border:1px solid var(--border);
}
/* Кроп области лица (8×8 из 64×64 листа скина) — см. подробный комментарий у
   iconHtml() в js/icons.js про то, почему нельзя просто вставить всю
   текстуру как есть (лицо занимает мизерную часть листа). Проценты вместо
   пикселей — не зависит от конкретного width/height контейнера (18px в
   таблице, 26px в детали-панели и т.д.), одно правило на все размеры. */
.item-icon-texture{
  background-repeat:no-repeat;
  background-size:800% 800%;
  background-position:14.2857% 14.2857%;
  image-rendering:pixelated;
}
.item-icon-placeholder{
  display:inline-block; background-color:var(--text-faint);
  -webkit-mask:url('assets/generic-item.svg') center/70% no-repeat;
  mask:url('assets/generic-item.svg') center/70% no-repeat;
}
/* Наши собственные обрезанные из скриншотов иконки (assets/item-icons/) —
   уже готовый кроп без фона, в отличие от .item-icon-texture (полный лист
   скина 64×64) тут просто вписываем картинку целиком. */
.item-icon-local{
  background-repeat:no-repeat;
  background-size:contain;
  background-position:center;
  image-rendering:pixelated;
  /* Некоторые предметы (блок коричневого гриба и т.п.) — сплошной кубик
     почти впритык к краям кропа, тон которого близок к рамке .item-icon в
     тёмной теме — рамка вокруг такой иконки почти не видна. Тонкий светлый
     контур внутри решает это для любого предмета, не только тёмных. */
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.1);
}
/* Зачарованная версия предмета (топливо/апгрейды миньонов чаще всего идут
   парами Coal/Enchanted Coal без разных текстур — см. js/icons.js) — свой
   значок поверх иконки/плейсхолдера, не чужая текстура. */
.item-icon-enchanted{ position:relative; }
.item-icon-enchanted::after{
  content:'✦'; position:absolute; right:-3px; bottom:-3px;
  font-size:9px; line-height:1; color:var(--accent);
  text-shadow:0 0 2px var(--bg), 0 0 2px var(--bg);
}

/* Прибыль/час — главная числовая колонка таблицы */
thead th.primary-col{ color:var(--accent-strong); }
td.profit-hour-cell{ font-size:15.5px; font-weight:700; }

/* Бейджи ликвидности / конкуренции */
.badge{
  display:inline-block; font-family:'IBM Plex Mono',monospace; font-size:10.5px; font-weight:600;
  text-transform:uppercase; letter-spacing:.03em; padding:3px 7px; border-radius:100px;
  border:1px solid transparent;
}
.badges-cell{ display:flex; flex-direction:column; gap:4px; align-items:flex-start; }
.badge-good{ background:var(--accent-soft); color:var(--accent-strong); }
.badge-mid{ background:var(--gold-soft); color:var(--gold); }
.badge-bad{ background:color-mix(in srgb, var(--danger) 16%, var(--surface)); color:var(--danger); }

/* Флаг возможной манипуляции (Этап 2) */
.flag-icon{
  color:var(--danger); margin-left:7px; font-size:13px; cursor:help; vertical-align:middle;
}
.loading-row td, .empty-row td{ text-align:center; padding:36px; color:var(--text-faint); cursor:default; }
.row-copy{
  background:transparent; border:1px solid var(--border); color:var(--text-dim);
  border-radius:9px; padding:5px 10px; font-size:11.5px; font-family:'IBM Plex Mono',monospace; cursor:pointer;
}
.row-copy:hover{ border-color:var(--accent); color:var(--accent); }

/* Detail panel — z-index поднят с 30/31 до 35/36: теперь может открываться
   поверх модалки дерева крафта (z-index 33/34, см. .craft-tree-modal) при
   клике на лист/корень дерева, оставляя саму модалку дерева открытой позади.
   top/height начинаются НЕ от самого верха экрана, а от нижнего края шапки
   (57px, тот же отступ, что уже используют .filters ниже) — иначе панель
   (z-index 35/36) визуально и функционально перекрывает шапку (header.top,
   z-index 20, включая кнопки ⌘K/Профиль/Настройки/Тема), и пока панель
   открыта, эти кнопки физически не кликаются, хотя выглядят как обычно.
   Баг найден пользователем на живом запуске: "кнопки в профиле не
   нажимаются" — на деле кнопка открытия профиля в шапке была недоступна,
   пока где-то фоном была открыта деталь предмета/настройки. */
.detail-overlay{
  position:fixed; top:57px; right:0; bottom:0; left:0; background:rgba(10,10,6,0.5); backdrop-filter:blur(2px);
  opacity:0; pointer-events:none; transition:opacity .18s; z-index:35;
}
.detail-overlay.open{ opacity:1; pointer-events:auto; }
.detail-panel{
  position:fixed; top:57px; right:0; height:calc(100% - 57px); width:min(480px, 100vw);
  background:var(--surface); border-left:1px solid var(--border);
  transform:translateX(100%); transition:transform .22s ease; z-index:36;
  overflow-y:auto;
}
.detail-panel.open{ transform:translateX(0); }
.detail-inner{ padding:26px 24px 40px; position:relative; }
.detail-close{ position:absolute; top:20px; right:20px; }
.detail-kicker{ font-family:'IBM Plex Mono',monospace; font-size:11px; text-transform:uppercase; letter-spacing:.08em; color:var(--text-faint); margin:0 0 6px; }
.detail-header h2{ font-family:'Sora',sans-serif; font-size:22px; margin:0 0 12px; padding-right:40px; text-wrap:balance; }
.detail-copyrow{ display:flex; align-items:center; gap:10px; margin-bottom:8px; }
.detail-copyrow code{ font-family:'IBM Plex Mono',monospace; font-size:12px; color:var(--text-faint); background:var(--bg-alt); padding:4px 8px; border-radius:8px; }
.copy-caveat{ font-size:12px; color:var(--text-faint); margin:0 0 16px; }
#detailExecToggle{ margin-bottom:24px; width:fit-content; }
.copy-btn{
  background:var(--accent-soft); color:var(--accent-strong); border:1px solid transparent;
  border-radius:10px; padding:7px 14px; font-size:12.5px; font-weight:700; cursor:pointer; font-family:'Manrope',sans-serif;
  box-shadow:0 1px 0 rgba(255,255,255,.04) inset; transition:transform .1s ease, box-shadow .15s ease, border-color .15s ease;
}
.copy-btn:hover{ border-color:var(--accent); transform:translateY(-1px); box-shadow:0 8px 18px -10px color-mix(in srgb, var(--accent) 45%, transparent); }
.copy-btn:active{ transform:translateY(0); }
.copy-btn.copied{ background:linear-gradient(135deg, var(--accent), var(--gold)); color:var(--bg); }

.detail-stats{ display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-bottom:28px; }
.dstat{ background:var(--bg-alt); border:1px solid var(--border); border-radius:13px; padding:12px 14px; }
.dstat-label{ font-size:11.5px; color:var(--text-faint); margin-bottom:4px; }
.dstat-val{ font-family:'IBM Plex Mono',monospace; font-size:16px; font-weight:600; font-variant-numeric:tabular-nums; }
.dstat-val.accent{ color:var(--accent); }
.dstat-val.badge{ font-size:11px; }

.detail-title-row{ display:flex; align-items:center; gap:10px; }
.detail-title-row h2{ margin:0; padding-right:0; flex:1; }
.detail-icon{ display:inline-flex; flex:none; }
.detail-icon .item-icon,
.detail-icon .item-icon-placeholder{ width:26px; height:26px; margin-right:0; }
.star-btn{
  background:none; border:1px solid var(--border); border-radius:10px; width:34px; height:34px;
  font-size:16px; cursor:pointer; color:var(--text-faint); flex:none;
}
.star-btn:hover{ border-color:var(--gold); color:var(--gold); }
.star-btn.on{ color:var(--gold); border-color:var(--gold); background:var(--gold-soft); }

.manip-warning{
  font-family:'Manrope',sans-serif; font-size:13px; font-weight:600; padding:10px 12px;
  background:color-mix(in srgb, var(--danger) 16%, var(--surface)); color:var(--danger);
  border-radius:10px; margin-bottom:20px;
}

.detail-sub{ font-family:'Sora',sans-serif; font-size:14px; margin:0 0 10px; }
.detail-sub-toggle{ display:flex; align-items:center; gap:6px; cursor:pointer; user-select:none; }
.detail-sub-toggle .toggle-arrow{ font-size:11px; color:var(--text-faint); transition:transform .15s; }
.detail-sub-toggle.open .toggle-arrow{ transform:rotate(180deg); }
.split-note{ font-size:13.5px; color:var(--text); margin:0 0 4px; }

/* Деталь-панель предмета в режиме AH (см. openAhDetail() в app.js) — те же
   DOM-узлы, что и у Bazaar-предмета (график/деталь-панель переиспользуются
   целиком), просто прячем разделы, у которых нет смысла без живого стакана
   ордеров базара (комиссия/чек-лист/ручной трейд-лог/копирование /bz), и
   показываем AH-версию блока статистики + список последних продаж вместо
   стакана. */
.detail-panel.ah-mode #detailStar,
.detail-panel.ah-mode #detailCopyrow,
.detail-panel.ah-mode #detailCopyCaveat,
.detail-panel.ah-mode #detailExecToggle,
.detail-panel.ah-mode #detailStatsBazaar,
.detail-panel.ah-mode #dPriceNote,
.detail-panel.ah-mode #dExecCompare,
.detail-panel.ah-mode #dManipWarning,
.detail-panel.ah-mode #dOrderSplitSection,
.detail-panel.ah-mode #dChecklistSection,
.detail-panel.ah-mode #dTradeLogSection,
.detail-panel.ah-mode #dOrderbooksBazaar,
.detail-panel.ah-mode #chartPriceHint{ display:none; }
.detail-panel:not(.ah-mode) #detailStatsAh,
.detail-panel:not(.ah-mode) #dAhRecentSales,
.detail-panel:not(.ah-mode) #dAhKeyNote{ display:none; }
.chart-pricebar{ display:flex; align-items:baseline; gap:8px; margin-bottom:8px; }
.chart-pricebar-now{ font-family:'IBM Plex Mono',monospace; font-size:22px; font-weight:600; color:var(--accent); font-variant-numeric:tabular-nums; }
.chart-pricebar-hint{ font-size:12px; color:var(--text-faint); }
.chart-toolbar{ display:flex; gap:6px; margin-left:auto; }
.chart-icon-btn{ width:28px; height:28px; font-size:13px; }
.chart-settings-popover{
  position:relative; margin:-2px 0 10px; padding:10px 12px; background:var(--surface);
  border:1px solid var(--border); border-radius:12px; box-shadow:var(--shadow);
}
.chart-settings-label{ font-size:12px; color:var(--text-faint); margin:0 0 8px; }
.chart-canvas-wrap{ position:relative; }
#detailChart{ width:100%; height:160px; background:var(--bg-alt); border:1px solid var(--border); border-radius:13px; margin-bottom:6px; }
#detailChartBig{ width:100%; height:440px; background:var(--bg-alt); border:1px solid var(--border); border-radius:13px; margin-bottom:6px; }
.chart-hint{ font-size:12px; color:var(--text-faint); margin:0 0 26px; }
/* Открывается ПОВЕРХ уже открытой деталь-панели (z-index:36) — базовые
   .detail-overlay/.trade-modal (35/32) этого не учитывают, без переопределения
   деталь-панель перекрывала бы развёрнутый график. */
#chartExpandOverlay{ z-index:37; }
#chartExpandModal{ z-index:38; }
.chart-expand-search{ position:absolute; top:24px; left:50%; transform:translateX(-50%); width:min(360px, 46%); }
.chart-expand-search input{
  width:100%; background:var(--bg-alt); border:1px solid var(--border); border-radius:13px;
  padding:8px 12px; color:var(--text); font-family:'Manrope',sans-serif; font-size:13px;
}
.chart-expand-search input:focus{ outline:none; border-color:var(--accent); }

.orderbooks{ display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-bottom:28px; }
.ob-title{ font-size:12px; color:var(--text-faint); margin:0 0 6px; }
.ob-table{ width:100%; border-collapse:collapse; font-family:'IBM Plex Mono',monospace; font-size:12px; }
.ob-table td{ padding:4px 0; border-bottom:1px dashed var(--border); font-variant-numeric:tabular-nums; }
.ob-table td:last-child{ text-align:right; color:var(--text-faint); }

.trade-form{ display:flex; gap:8px; margin-bottom:12px; }
.trade-form select{
  background:var(--bg-alt); border:1px solid var(--border); border-radius:10px; padding:8px 10px; color:var(--text); font-size:13px;
}
.trade-form input{
  background:var(--bg-alt); border:1px solid var(--border); border-radius:10px; padding:8px 10px; color:var(--text);
  font-family:'IBM Plex Mono',monospace; font-size:13px; width:100%; min-width:0;
}
.trade-pnl{
  font-family:'IBM Plex Mono',monospace; font-size:13px; font-weight:600; padding:9px 12px;
  background:var(--accent-soft); color:var(--accent-strong); border-radius:10px; margin-bottom:12px;
}
.trade-pnl.neg{ background:color-mix(in srgb, var(--danger) 16%, var(--surface)); color:var(--danger); }
.trade-list{ display:flex; flex-direction:column; gap:6px; margin-bottom:28px; }
.trade-row{
  display:flex; align-items:center; gap:8px; font-size:12.5px; padding:6px 10px;
  background:var(--bg-alt); border:1px solid var(--border); border-radius:10px;
}
.trade-row .tr-type{ font-weight:700; font-family:'IBM Plex Mono',monospace; }
.trade-row .tr-type.buy{ color:var(--accent); }
.trade-row .tr-type.sell{ color:var(--gold); }
.trade-row .tr-rest{ flex:1; font-family:'IBM Plex Mono',monospace; color:var(--text-dim); }
.trade-row .tr-del{ background:none; border:none; color:var(--text-faint); cursor:pointer; font-size:12px; }
.trade-row .tr-del:hover{ color:var(--danger); }

/* Чек-лист исполнения флипа (Этап 4) */
.exec-checklist{ margin:0 0 26px; padding-left:20px; font-size:13.5px; color:var(--text); display:flex; flex-direction:column; gap:6px; }
.exec-checklist li{ padding-left:2px; }
.checklist-link{ color:var(--accent); font-weight:600; text-decoration:none; }
.checklist-link:hover{ text-decoration:underline; }

@media (max-width: 720px){
  .table-wrap{ overflow-x:auto; }
  table{ min-width:860px; }
}

/* Переключатели-сегменты: вид (таблица/карточки), вкладки лидербордов (Этап 3) */
.segmented{ display:flex; gap:4px; background:var(--bg-alt); border:1px solid var(--border); border-radius:13px; padding:3px; }
.segmented-btn{
  background:none; border:none; border-radius:9px; padding:7px 12px; cursor:pointer;
  font-family:'Manrope',sans-serif; font-size:12.5px; font-weight:600; color:var(--text-dim);
}
.segmented-btn:hover{ color:var(--text); }
.segmented-btn.active{ background:var(--accent-soft); color:var(--accent-strong); box-shadow:var(--shadow); }
.leaderboard-tabs{ width:fit-content; }

/* Карточный вид (Этап 3) */
.card-grid{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(230px, 1fr)); gap:12px;
}
.flip-card{
  background:var(--surface); border:1px solid var(--border); border-radius:18px; padding:16px 18px;
  box-shadow:var(--shadow); cursor:pointer; display:flex; flex-direction:column; gap:9px;
  position:relative; overflow:hidden; isolation:isolate;
  transition:border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
/* Фирменное угловое пятно свечения (аркадный лут-дэшборд, Этап 12) — цвет
   берёт из --accent, поэтому автоматически меняется вместе с темой. */
.flip-card::before{
  content:""; position:absolute; top:-40px; right:-40px; width:110px; height:110px;
  border-radius:50%; background:var(--accent); filter:blur(28px); opacity:.16; z-index:-1;
  transition:opacity .15s ease;
}
.flip-card:hover{ border-color:var(--accent); transform:translateY(-2px); box-shadow:0 20px 40px -20px color-mix(in srgb, var(--accent) 45%, transparent), var(--shadow); }
.flip-card:hover::before{ opacity:.28; }
/* Карточки без клика по всей площади (например, Миньоны — клик по имени/
   статам копирует, но сама карточка никуда не ведёт) — курсор и hover-лифт
   обманывали, будто карточка кликабельна целиком. */
.flip-card-static{ cursor:default; }
.flip-card-static:hover{ transform:none; box-shadow:var(--shadow); border-color:var(--border); }
.flip-card-static:hover::before{ opacity:.16; }
.flip-card-head{ display:flex; align-items:center; gap:8px; }
.flip-card-name{ font-weight:700; flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.flip-card-star{ background:none; border:none; cursor:pointer; font-size:15px; color:var(--text-faint); padding:0; flex:none; }
.flip-card-star.on{ color:var(--gold); }
.flip-card-profit{ font-family:'IBM Plex Mono',monospace; font-size:21px; font-weight:700; color:var(--accent); letter-spacing:-.01em; }
.flip-card-stats{ display:flex; flex-wrap:wrap; gap:6px 14px; font-family:'IBM Plex Mono',monospace; font-size:12px; color:var(--text-dim); }
.flip-card-stats b{ color:var(--text); font-weight:600; }
.flip-card-badges{ display:flex; gap:6px; flex-wrap:wrap; }
.flip-card-actions{ display:flex; justify-content:flex-end; }

/* scanner-toggle — кнопка "▶ Запустить"/"⏸ Остановить" Аукцион-снайпера
   (Bazaar больше не использует, см. Этап 10 — активный Сканер убран).
   Основное CTA-действие страницы — даём ему заметный градиентный акцент
   вместо плоской заливки, как у второстепенных кнопок. */
.scanner-toggle{
  background:linear-gradient(135deg, var(--accent), var(--gold)); color:var(--bg); border:1px solid transparent;
  border-radius:10px; padding:7px 14px; font-size:12px; font-weight:700; cursor:pointer; font-family:'Manrope',sans-serif;
  box-shadow:0 8px 20px -8px color-mix(in srgb, var(--accent) 55%, transparent);
  transition:transform .1s ease, box-shadow .15s ease;
}
.scanner-toggle:hover{ transform:translateY(-1px); box-shadow:0 12px 26px -10px color-mix(in srgb, var(--accent) 65%, transparent); }
.scanner-toggle:active{ transform:translateY(0); }
.scanner-toggle.on{ background:linear-gradient(135deg, var(--danger), color-mix(in srgb, var(--danger) 60%, var(--gold))); color:#fff; box-shadow:0 8px 20px -8px color-mix(in srgb, var(--danger) 55%, transparent); }

.scanner-history-head{ display:flex; align-items:center; gap:10px; margin-top:14px; }
/* Раньше не задавала ни border/radius/padding/фон — рендерилась чистым
   браузерным дефолтом (плоская рамка, системный шрифт). Остальные кнопки
   в приложении (.copy-btn/.segmented-btn/...) всегда были полностью
   стилизованы, эта группа — нет, просто было не видно на светлой тёплой
   теме. На тёмной аркадной эта разница стала заметна. */
.ghost-btn{
  background:var(--surface); color:var(--text-dim); border:1px solid var(--border);
  border-radius:10px; padding:8px 16px; font-family:'Manrope',sans-serif; font-size:12.5px; font-weight:600;
  cursor:pointer; box-shadow:var(--shadow); transition:border-color .15s ease, color .15s ease, transform .08s ease;
}
.ghost-btn:hover{ color:var(--accent); border-color:var(--accent); }
.ghost-btn:active{ transform:translateY(1px); box-shadow:none; }
/* Для действий, которые НЕ второстепенные (как большинство ghost-btn), но и не
   главный CTA рядом (например "🧩 Собрать цепочку" — мощная фича, которую
   легко не заметить рядом с приглушённым обычным ghost-btn, см. пункт 21
   бэклога) — та же форма, но акцентная рамка/цвет текста, без заливки. */
.ghost-btn-accent{ color:var(--accent-strong); border-color:var(--accent); }
.ghost-btn-accent:hover{ background:var(--accent-soft); }
/* .danger-btn (Удалить выбранное) переопределяет цвет ниже под красный — это
   осознанное исключение для реально разрушительных действий, не общий случай. */
.scanner-history-list{ display:flex; flex-direction:column; gap:6px; width:100%; }
.scanner-history-row{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  background:var(--bg-alt); border:1px solid var(--border); border-radius:10px;
  padding:7px 12px; font-size:12px; font-family:'IBM Plex Mono',monospace; color:var(--text-dim);
}
.scanner-history-row b{ color:var(--text); font-family:'Manrope',sans-serif; font-weight:600; }
.scanner-feed{ margin-top:14px; }

/* Селектор диапазона графика (Этап 3) */
.chart-range{ display:flex; gap:6px; margin-bottom:10px; flex-wrap:wrap; }
.chart-range-btn{
  background:var(--bg-alt); border:1px solid var(--border); border-radius:100px; padding:5px 12px;
  font-family:'IBM Plex Mono',monospace; font-size:11.5px; color:var(--text-dim); cursor:pointer;
}
.chart-range-btn:hover{ border-color:var(--accent); color:var(--accent); }
.chart-range-btn.active{ background:var(--accent-soft); border-color:var(--accent); color:var(--accent-strong); }

/* Командная палитра — Ctrl+K (Этап 3) */
.palette-open-btn{ width:auto; padding:0 10px; font-family:'IBM Plex Mono',monospace; font-size:11px; }
.palette-overlay{ z-index:40; }
.palette{
  position:fixed; top:12%; left:50%; transform:translateX(-50%) scale(.98);
  width:min(560px, calc(100vw - 32px)); max-height:70vh; overflow:hidden;
  background:var(--surface); border:1px solid var(--border); border-radius:18px; box-shadow:var(--shadow);
  z-index:41; opacity:0; pointer-events:none; transition:opacity .15s, transform .15s;
  display:flex; flex-direction:column;
}
.palette.open{ opacity:1; pointer-events:auto; transform:translateX(-50%) scale(1); }
.palette-inner{ display:flex; flex-direction:column; min-height:0; }
.palette #paletteInput{
  border:none; border-bottom:1px solid var(--border); background:transparent; color:var(--text);
  padding:16px 18px; font-size:15px; font-family:'Manrope',sans-serif;
}
.palette #paletteInput:focus{ outline:none; }
.palette-results{ overflow-y:auto; padding:6px; }
.palette-result{
  display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:10px; cursor:pointer; font-size:13.5px;
}
.palette-result:hover, .palette-result.active{ background:var(--bg-alt); }
.palette-result-name{ flex:1; font-weight:600; }
.palette-result-id{ font-weight:400; font-size:11px; color:var(--text-faint); font-family:'IBM Plex Mono',monospace; }
.palette-result-meta{ font-family:'IBM Plex Mono',monospace; font-size:11.5px; color:var(--text-faint); }

/* Выбор предмета в форме "Мои сделки (Базар)" — тот же список строк, что и в
   ⌘K (переиспользует .palette-result*), но как выпадашка под полем, а не
   полноэкранная модалка. Выбор ОБЯЗАТЕЛЕН — журнал ведётся по реальным
   предметам bazaar, произвольный текст не сохраняется (см. js/bazaarTrades.js). */
.trade-item-picker{ position:relative; }
.trade-item-picker-results{
  position:absolute; top:calc(100% + 4px); left:0; right:0; z-index:20;
  background:var(--surface); border:1px solid var(--border); border-radius:13px;
  max-height:260px; overflow-y:auto; padding:6px; box-shadow:var(--shadow);
}
.palette-empty{ padding:16px 18px; color:var(--text-faint); font-size:13px; }
.palette-ah-results{ padding:0 6px 6px; border-top:1px solid var(--border); }
.palette-ah-status{ padding:10px; color:var(--text-faint); font-size:12.5px; }
.palette-ah-label{
  padding:10px 10px 4px; margin:0; font-family:'IBM Plex Mono',monospace; font-size:10.5px;
  text-transform:uppercase; letter-spacing:.06em; color:var(--text-faint);
}
.palette-ah-result{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:8px 10px; border-radius:10px; font-size:13px; cursor:pointer;
}
.palette-ah-result:hover{ background:var(--bg-alt); }
.palette-ah-result:hover .palette-ah-name{ color:var(--accent); }
.palette-ah-name{ font-weight:600; }
.palette-ah-meta{ font-family:'IBM Plex Mono',monospace; font-size:11px; color:var(--text-faint); white-space:nowrap; }
.palette-ah-copy{
  flex:none; background:none; border:1px solid var(--border); border-radius:7px; color:var(--text-faint);
  font-size:12px; line-height:1; padding:4px 6px; cursor:pointer;
}
.palette-ah-copy:hover{ color:var(--accent); border-color:var(--accent); }

/* Калькуляторы миньонов/данжей и рыночные индексы (Этап 5) */
.calc-panel{ margin-bottom:20px; }
.calc-panel select{
  background:var(--surface); border:1px solid var(--border); border-radius:13px;
  padding:9px 12px; color:var(--text); font-family:'IBM Plex Mono',monospace; font-size:13px; width:180px;
}
.dungeon-loot-list{ display:flex; flex-direction:column; gap:6px; }

/* История сделок — полноэкранная модалка (Этап 9) */
.trade-modal{
  position:fixed; top:6%; left:50%; transform:translateX(-50%) scale(.98);
  width:min(1180px, calc(100vw - 32px)); max-height:88vh;
  background:var(--surface); border:1px solid var(--border); border-radius:18px; box-shadow:var(--shadow);
  z-index:32; opacity:0; pointer-events:none; transition:opacity .16s, transform .16s;
  display:flex; flex-direction:column; overflow:hidden;
}
.trade-modal.open{ opacity:1; pointer-events:auto; transform:translateX(-50%) scale(1); }
#tradeHistoryOverlay{ z-index:31; }
/* Тот же .trade-modal (z-index 32), что и у "Мои сделки" — оверлей должен
   быть НИЖЕ него, иначе (класс .detail-overlay сам по себе z-index 35)
   прозрачный оверлей перехватывает клики по самой модалке раньше её
   содержимого — модалка визуально на месте, но по факту не кликабельна,
   любой клик внутри неё уходит в оверлей и закрывает её. Баг найден
   пользователем на живом запуске: клик по 3D-модели в профиле закрывал
   всю модалку целиком. */
#playerProfileOverlay{ z-index:31; }
.trade-modal-inner{ padding:24px 24px 16px; overflow-y:auto; position:relative; flex:1; min-height:0; }
.trade-modal-toolbar{ display:flex; align-items:center; gap:16px; flex-wrap:wrap; margin:14px 0 16px; }
.trade-status-check{ display:flex; align-items:center; gap:6px; font-size:13px; color:var(--text-dim); cursor:pointer; }
.trade-modal-body{ display:flex; gap:20px; align-items:flex-start; }
/* 960px раньше зажимал таблицу (8 колонок) до ~630px вместе с боковой
   диаграммой (260px) — колонка "Прибыль" и бары диаграммы обрезались по
   краю модалки. Расширил модалку и добавил overflow-x на саму таблицу как
   защиту на будущее, если колонок станет больше. */
.trade-modal-table-wrap{ flex:1; min-width:0; max-height:52vh; overflow-y:auto; overflow-x:auto; }
.trade-modal-chart{ width:280px; flex:none; }
.trade-modal-footer{ padding:14px 24px; border-top:1px solid var(--border); }
.trade-pager{ display:flex; align-items:center; justify-content:center; gap:14px; font-family:'IBM Plex Mono',monospace; font-size:12.5px; color:var(--text-dim); }
.trade-row-removed{ opacity:.45; }
.trade-row-removed td{ text-decoration:line-through; }
.trade-row-removing{ animation:trade-row-fade .2s ease forwards; }
.bz-batch-detail td{ padding:0 0 10px; border-top:none; }
.bz-batch-detail-wrap{
  margin:0 0 0 30px; padding:8px 12px; border-left:2px solid var(--border);
  display:flex; flex-direction:column; gap:4px;
}
.bz-batch-detail-row{ display:flex; align-items:center; justify-content:space-between; gap:10px; font-size:12.5px; color:var(--text-dim); }
.bz-tracked-panel{ margin:10px 0 14px; }
.bz-tracked-cards{ display:flex; flex-wrap:wrap; gap:10px; }
.bz-tracked-card{
  display:flex; flex-direction:column; gap:6px; min-width:220px; max-width:280px;
  padding:10px 12px; border-radius:12px; background:var(--bg-alt); border:1px solid var(--border);
  font-size:12.5px;
}
.bz-tracked-card-clickable{ cursor:pointer; transition:border-color .15s ease; }
.bz-tracked-card-clickable:hover{ border-color:var(--accent); }
.bz-tracked-card-head{ display:flex; align-items:center; gap:6px; }
.bz-tracked-card-head .bz-ing-copy{ flex:1; }
.bz-tracked-card-head b{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.bz-tracked-card-head button{
  border:none; background:none; color:var(--text-dim); cursor:pointer; font-size:13px;
  line-height:1; padding:2px 4px; border-radius:100px;
}
.bz-tracked-card-head button:hover{ color:var(--danger); background:color-mix(in srgb, var(--danger) 14%, transparent); }
.bz-tracked-search{
  width:100%; max-width:320px; margin:0 0 10px; box-sizing:border-box;
  background:var(--surface); border:1px solid var(--border); border-radius:10px;
  padding:7px 11px; color:var(--text); font-family:'Manrope',sans-serif; font-size:12.5px;
}
/* Несколько целей на один и тот же предмет (очередь кампаний, см.
   addOrUpdateBazaarTrackedItem в js/bazaarTrades.js) — активная карточка
   выглядит как обычно, более старые (в очереди) — заметно потемнее, чтобы
   сразу было видно, какая из них реально копит события из чата. */
.bz-tracked-card-queued{ opacity:.55; filter:saturate(.7); }
.bz-tracked-dup-badge{
  flex:none; display:inline-flex; align-items:center; justify-content:center;
  min-width:18px; height:18px; padding:0 5px; border-radius:100px;
  background:var(--border); color:var(--text-dim);
  font-family:'IBM Plex Mono',monospace; font-size:10.5px; font-weight:700;
}
.bz-tracked-dup-badge.active{
  background:color-mix(in srgb, var(--accent) 22%, transparent); color:var(--accent);
  animation:bz-tracked-dup-pulse 1.6s ease-in-out infinite;
}
@keyframes bz-tracked-dup-pulse{
  0%, 100%{ box-shadow:0 0 0 0 color-mix(in srgb, var(--accent) 45%, transparent); }
  50%{ box-shadow:0 0 0 4px color-mix(in srgb, var(--accent) 0%, transparent); }
}
.bz-tracked-progress-row{ display:flex; align-items:center; justify-content:space-between; gap:8px; color:var(--text-dim); }
.bz-tracked-bar{ height:5px; border-radius:100px; background:var(--border); overflow:hidden; }
.bz-tracked-bar > div{ height:100%; background:var(--accent); border-radius:100px; }
.bz-tracked-bar-ready > div{ background:var(--gold); }
.bz-tracked-card-actions{ display:flex; gap:6px; margin-top:2px; }
.bz-tracked-card-actions button{
  flex:1; font-size:11.5px; padding:4px 6px; border-radius:8px; border:1px solid var(--border);
  background:var(--surface); color:var(--text); cursor:pointer;
}
.bz-tracked-card-actions button:hover{ border-color:var(--accent); color:var(--accent); }
.bz-tracked-expand-btn{
  align-self:flex-start; border:none; background:none; color:var(--text-dim); cursor:pointer;
  font-size:11.5px; padding:2px 0; margin-top:2px;
}
.bz-tracked-expand-btn:hover{ color:var(--accent); }
.bz-tracked-bump-btn{
  border:none; background:color-mix(in srgb, var(--accent) 16%, transparent); color:var(--accent);
  cursor:pointer; font-size:10px; line-height:1; width:16px; height:16px; border-radius:100px;
  display:inline-flex; align-items:center; justify-content:center; padding:0;
}
.bz-tracked-bump-btn:hover{ background:color-mix(in srgb, var(--accent) 30%, transparent); }
.bz-ing-copy{ cursor:pointer; }
.bz-ing-copy:hover{ color:var(--accent); }
.bz-ing-owner-btn{
  border:none; background:none; color:var(--text-dim); cursor:pointer; font-size:12px;
  line-height:1; padding:0; margin-left:2px;
}
.bz-ing-owner-btn.active{ color:var(--accent); }
.bz-ing-owner-btn:hover{ color:var(--accent); }
@keyframes trade-row-fade{
  from{ background:color-mix(in srgb, var(--danger) 20%, transparent); opacity:1; }
  to{ background:color-mix(in srgb, var(--danger) 20%, transparent); opacity:.15; }
}
.trade-bulk-bar{
  position:absolute; bottom:14px; left:50%; transform:translateX(-50%);
  display:flex; align-items:center; gap:12px; background:var(--bg-alt); border:1px solid var(--border);
  border-radius:100px; padding:8px 16px; font-size:12.5px; box-shadow:var(--shadow);
}
.danger-btn{ border-color:var(--danger); color:var(--danger); }

/* Профиль игрока (кнопка "👤" в шапке, js/playerProfile.js) — переиспользует
   .trade-modal (тот же широкий центрированный модал, что у "Мои сделки"). */
.pprofile-coins-row{ display:flex; gap:12px; margin-bottom:20px; }
.pprofile-coin-badge, .pprofile-dungeon-badge{
  display:flex; flex-direction:column; gap:2px; padding:10px 16px; background:var(--bg-alt);
  border:1px solid var(--border); border-radius:12px;
}
.pprofile-coin-badge span, .pprofile-dungeon-badge span{ font-size:11px; color:var(--text-faint); text-transform:uppercase; letter-spacing:.04em; }
.pprofile-coin-badge b, .pprofile-dungeon-badge b{ font-family:'IBM Plex Mono',monospace; font-size:16px; }
.pprofile-skills-grid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(260px, 1fr)); gap:10px; margin-bottom:20px; }
.pprofile-skill-row{ display:flex; align-items:center; gap:8px; background:var(--bg-alt); border:1px solid var(--border); border-radius:10px; padding:8px 12px; }
.pprofile-skill-icon{ flex:none; }
.pprofile-skill-name{ flex:1; font-size:13px; }
.pprofile-skill-level{ font-family:'IBM Plex Mono',monospace; font-size:13px; font-weight:700; color:var(--accent); flex:none; }
.pprofile-skill-bar{ width:60px; height:5px; border-radius:100px; background:var(--border); overflow:hidden; flex:none; }
.pprofile-skill-bar-fill{ height:100%; background:var(--accent); }
.pprofile-dungeons-row{ display:flex; gap:12px; margin-bottom:10px; }
.pprofile-classes-row{ display:flex; gap:8px; flex-wrap:wrap; margin-bottom:20px; }
.pprofile-class-badge{
  display:flex; align-items:center; gap:6px; padding:5px 10px; border-radius:100px;
  background:var(--bg-alt); border:1px solid var(--border); font-size:12px;
}
.pprofile-class-badge b{ font-family:'IBM Plex Mono',monospace; }
.pprofile-class-badge.selected{ border-color:var(--accent); color:var(--accent-strong); }
.pprofile-armor-row{ display:flex; gap:10px; margin-bottom:20px; flex-wrap:wrap; }
.pprofile-armor-item{
  display:flex; flex-direction:column; align-items:center; gap:4px; width:90px; text-align:center;
  background:none; border:1px solid transparent; border-radius:10px; padding:6px 4px; font-family:inherit; cursor:pointer;
}
.pprofile-armor-item:hover{ border-color:var(--border); background:var(--bg-alt); }
.pprofile-armor-name{ font-size:11px; color:var(--text-dim); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%; }
.pprofile-collections-grid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(200px, 1fr)); gap:8px; margin-bottom:20px; }
.pprofile-collection-item{ display:flex; align-items:center; gap:6px; background:var(--bg-alt); border:1px solid var(--border); border-radius:10px; padding:6px 10px; }
.pprofile-collection-name{ flex:1; font-size:12px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pprofile-collection-amount{ font-family:'IBM Plex Mono',monospace; font-size:12px; color:var(--text-dim); flex:none; }
.pprofile-minions-grid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(160px, 1fr)); gap:6px; margin-bottom:20px; font-size:12.5px; }
.pprofile-minion-item{ background:var(--bg-alt); border:1px solid var(--border); border-radius:8px; padding:5px 10px; }
.pprofile-pets-list{ display:flex; flex-direction:column; gap:6px; }
.pprofile-pet-item{ display:flex; align-items:center; gap:10px; background:var(--bg-alt); border:1px solid var(--border); border-radius:10px; padding:7px 12px; font-size:13px; }
.pprofile-pet-item.active{ border-color:var(--accent); }
.pprofile-pet-tier{ font-family:'IBM Plex Mono',monospace; font-size:11px; font-weight:700; padding:1px 6px; border-radius:6px; background:var(--border); }
.pprofile-pet-name{ flex:1; }
.pprofile-pet-active-badge{ font-size:11px; color:var(--accent); font-weight:700; }
.pprofile-pet-xp{ font-family:'IBM Plex Mono',monospace; font-size:12px; color:var(--text-faint); }
.pprofile-tier-legendary{ color:var(--gold); } .pprofile-tier-mythic{ color:#e07be0; }
.pprofile-tier-epic{ color:#b06bef; } .pprofile-tier-rare{ color:#5ba8ff; }
.pprofile-known-badge{
  font-family:'IBM Plex Mono',monospace; font-size:11px; font-weight:700; padding:3px 9px; border-radius:100px;
  background:var(--accent-soft); color:var(--accent-strong); border:1px solid var(--accent); margin-left:10px;
}
.pprofile-lookup-row{ display:flex; gap:8px; align-items:center; margin-bottom:10px; flex-wrap:wrap; }
.pprofile-lookup-row input{
  flex:1; min-width:160px; background:var(--bg-alt); border:1px solid var(--border); border-radius:10px;
  padding:8px 12px; color:var(--text); font-family:'Manrope',sans-serif; font-size:13px;
}
.pprofile-favorites-row{ display:flex; gap:6px; flex-wrap:wrap; margin-bottom:14px; }
.pprofile-fav-chip{
  display:flex; align-items:center; gap:6px; background:var(--bg-alt); border:1px solid var(--border);
  border-radius:100px; padding:4px 6px 4px 12px; font-size:12px; color:var(--text); cursor:pointer;
}
.pprofile-fav-chip:hover{ border-color:var(--accent); }
.pprofile-fav-remove{ opacity:.5; padding:2px 4px; border-radius:50%; }
.pprofile-fav-remove:hover{ opacity:1; background:color-mix(in srgb, var(--danger) 20%, transparent); }
.pprofile-top-row{ display:flex; gap:20px; margin-bottom:8px; }
.pprofile-skin-canvas{ flex:none; border-radius:14px; background:var(--bg-alt); border:1px solid var(--border); }
.pprofile-top-info{ flex:1; min-width:0; }
.pprofile-tabs{ flex-wrap:wrap; width:fit-content; margin:16px 0 18px; }

/* Попап предмета по клику (лор как в игре) — поверх модалки профиля
   (.trade-modal z-index 32), см. openItemLorePopup()/closeItemLorePopup() в
   js/playerProfile.js. */
.item-lore-popup{
  position:fixed; top:50%; left:50%; transform:translate(-50%,-50%) scale(.97);
  width:min(420px, calc(100vw - 32px)); max-height:78vh; overflow-y:auto;
  background:var(--surface); border:1px solid var(--border); border-radius:16px; box-shadow:var(--shadow);
  padding:20px 20px 18px; z-index:45; opacity:0; pointer-events:none; transition:opacity .16s, transform .16s;
}
.item-lore-popup.open{ opacity:1; pointer-events:auto; transform:translate(-50%,-50%) scale(1); }
#itemLorePopupOverlay{ z-index:44; }
.item-lore-popup-head{ display:flex; align-items:center; gap:10px; margin:0 0 12px; padding-right:28px; }
.item-lore-popup-head h3{ font-family:'Sora',sans-serif; font-size:15px; margin:0; text-wrap:balance; color:var(--text); }
.item-lore-popup-body{ font-size:12.5px; line-height:1.55; }
.item-lore-popup-body .lore-line{ min-height:1.3em; }
.item-lore-popup-body .lore-ru-desc{
  background:var(--bg-alt); border:1px solid var(--border); border-left:3px solid var(--accent);
  border-radius:8px; padding:9px 11px; margin-bottom:14px; color:var(--text); font-size:12px; line-height:1.5;
  white-space:pre-line;
}
.item-lore-popup-body .lore-ru-desc-label{
  display:block; font-family:var(--mono); font-size:10px; text-transform:uppercase; letter-spacing:.06em;
  color:var(--text-faint); margin-bottom:4px;
}

/* Дерево рецепта крафта (кнопка "🌳 Дерево" на карточке) — перетаскиваемый/
   масштабируемый canvas, идея визуализации с outcrocalculator.com (Pyramid
   Viewer), но в своём стиле: карточки/цвета приложения вместо их разметки. */
.craft-tree-modal{
  z-index:34; display:flex; flex-direction:column; padding:0; overflow:hidden;
  width:min(1600px, calc(100vw - 32px)); height:min(900px, 92vh);
}
#craftTreeOverlay{ z-index:33; }
.craft-tree-header{
  display:flex; align-items:flex-start; justify-content:space-between; gap:16px;
  padding:20px 24px 14px; border-bottom:1px solid var(--border); flex:none;
}
.craft-tree-header h2{ margin:4px 0 0; }
.craft-tree-legend{ display:flex; align-items:center; gap:6px; margin:8px 0 0; font-size:12px; color:var(--text-dim); }
.craft-tree-legend-icon{ font-size:11px; flex:none; }
.craft-tree-legend-icon:not(:first-child){ margin-left:10px; }
.craft-tree-toolbar{ display:flex; align-items:center; gap:8px; flex:none; }
.craft-tree-hint{ font-size:12px; color:var(--text-faint); margin-right:6px; white-space:nowrap; }
.craft-tree-viewport{
  flex:1; min-height:0; position:relative; overflow:hidden; cursor:grab;
  background-image:radial-gradient(circle at 1px 1px, var(--border) 1px, transparent 0);
  background-size:26px 26px;
}
.craft-tree-viewport.dragging{ cursor:grabbing; }
.craft-tree-canvas{ position:absolute; top:0; left:0; transform-origin:0 0; }
.craft-tree-lines{ position:absolute; top:0; left:0; overflow:visible; pointer-events:none; }
.craft-tree-lines path{ fill:none; stroke:var(--border); stroke-width:2; }

.craft-tree-node{ position:absolute; }
/* Раньше имя делило одну строку с ценой (width:208px) и почти всегда
   обрезалось многоточием — теперь два ряда: имя сверху во всю ширину
   карточки, цены снизу. */
.craft-tree-card{
  width:260px; display:flex; flex-direction:column; gap:6px; padding:10px 12px;
  background:var(--surface); border:1px solid var(--border); border-radius:13px;
  box-shadow:var(--shadow); user-select:none;
}
.craft-tree-card.leaf{ border-color:color-mix(in srgb, var(--accent) 40%, var(--border)); }
.craft-tree-card.synth{ border-color:color-mix(in srgb, var(--gold) 40%, var(--border)); border-style:dashed; }
.craft-tree-card.root{ border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-soft), var(--shadow); }
.craft-tree-role-icon{ font-size:11px; flex:none; }
/* Лист/корень кликабельны целиком (открывают деталь-панель предмета) —
   курсор и лёгкая подсветка при наведении отличают их от synth-узлов, у
   которых своих биржевых данных нет. */
.craft-tree-card[data-detail-id]{ cursor:pointer; }
.craft-tree-card[data-detail-id]:hover{ box-shadow:0 0 0 2px var(--accent), var(--shadow); }
.craft-tree-card-head{ display:flex; align-items:center; gap:8px; }
.craft-tree-name{
  flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font-weight:500; cursor:pointer; border-radius:6px; padding:2px 4px; margin:-2px -4px;
}
.craft-tree-name:hover{ background:var(--accent-soft); color:var(--accent-strong); }
.craft-tree-meta-row{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding-left:28px; }
.craft-tree-cost{ font-family:'IBM Plex Mono',monospace; font-size:12px; color:var(--text-dim); }
.craft-tree-qty{ font-family:'IBM Plex Mono',monospace; font-size:11px; color:var(--text-faint); }
.craft-tree-qty.warn{ color:var(--danger); font-weight:700; }
.craft-large-qty-badge{ font-family:'IBM Plex Mono',monospace; font-size:11px; font-weight:700; color:var(--danger); flex:none; }
.craft-tree-badge{
  flex:none; font-size:10px; padding:1px 7px; border-radius:100px;
  background:color-mix(in srgb, var(--gold) 18%, transparent); color:var(--gold);
}
/* Поле "сколько готовых штук" на корневой карточке дерева крафта — редактируется
   прямо тут (не в боковой панели, как у "Собрать цепочку"), см. craftTreeCardHtml(). */
.craft-tree-qty-input{
  width:92px; font-family:'IBM Plex Mono',monospace; font-size:12px; padding:2px 6px;
  background:var(--bg); border:1px solid var(--border); border-radius:6px; color:var(--text);
}
.craft-tree-qty-input:focus{ outline:none; border-color:var(--accent); }
/* Переключатель Ордер/Инста на ингредиентах, где разница в цене мизерная
   (см. CRAFT_TREE_SMALL_DIFF_PCT в js/craftFlips.js) — незачем ждать
   заполнения ордера ради копеек, но можно вручную вернуть на "Ордер". */
.craft-tree-leaf-toggle{
  display:flex; border:1px solid var(--border); border-radius:8px; overflow:hidden;
}
.craft-tree-leaf-toggle button{
  font-family:'IBM Plex Mono',monospace; font-size:10px; padding:2px 8px; border:none;
  background:var(--bg); color:var(--text-faint); cursor:pointer;
}
.craft-tree-leaf-toggle button.active{ background:var(--accent-soft); color:var(--accent-strong); font-weight:700; }
.danger-btn:hover{ background:color-mix(in srgb, var(--danger) 14%, transparent); }

/* "🧩 Собрать цепочку" — редактируемая версия дерева крафта (Мои сделки,
   Базар): пользователь сам добавляет карточки покупки/крафта/продажи и
   соединяет их через выпадающий список "куда идёт" на каждой карточке
   (не перетаскиванием проводов — надёжнее и сильно проще в реализации,
   визуальный результат тот же: карточки + линии). Раскладка и стиль карточек
   переиспользуют .craft-tree-* (тот же canvas/pan/zoom, что и у обычного
   дерева крафта), поверх него — z-index выше всех остальных модалок,
   т.к. может открываться поверх уже открытой панели "Мои сделки".
*/
.bazaar-chain-modal{ z-index:44; height:min(760px, 90vh); }
#bazaarChainOverlay{ z-index:43; }
.bz-chain-toolbar{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap; flex:none;
  padding:10px 24px; border-bottom:1px solid var(--border);
}
.bz-chain-toolbar-sep{ width:1px; align-self:stretch; background:var(--border); margin:2px 4px; }
.bz-chain-preset-select, #bzChainPresetName{
  background:var(--surface); border:1px solid var(--border); border-radius:10px;
  padding:7px 10px; color:var(--text); font-family:'IBM Plex Mono',monospace; font-size:12.5px; max-width:220px;
}
.bz-chain-body{ flex:1; min-height:0; display:flex; }
.bz-chain-body .craft-tree-viewport{ flex:1; min-width:0; }
.bz-chain-side{
  width:300px; flex:none; padding:18px; border-left:1px solid var(--border);
  overflow-y:auto; display:flex; flex-direction:column; gap:14px;
}
.bz-chain-side h3{ margin:0; font-size:14px; }
.bz-chain-side .controls{ margin:0; flex-direction:column; align-items:stretch; gap:10px; }
.bz-chain-side .control-group input, .bz-chain-side .control-group select{ width:100%; }
.bz-chain-side-actions{ display:flex; gap:8px; margin-top:4px; }
.bz-chain-summary-row{ display:flex; justify-content:space-between; font-size:13px; color:var(--text-dim); }
.bz-chain-summary-row b{ color:var(--text); }
.bz-chain-summary-row.total{ padding-top:10px; border-top:1px solid var(--border); font-size:14px; }

/* Карточки цепочки — тот же .craft-tree-card, плюс роль-специфичная рамка и
   кнопка "🔗 Соединить" прямо на карточке (не только в боковой панели), чтобы
   соединять цепочку не открывая форму редактирования каждый раз. */
.bz-chain-card.buy{ border-color:color-mix(in srgb, var(--accent) 40%, var(--border)); }
.bz-chain-card.craft{ border-color:color-mix(in srgb, var(--gold) 40%, var(--border)); border-style:dashed; }
.bz-chain-card.sell{ border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-soft), var(--shadow); }
.bz-chain-card{ cursor:grab; transition:box-shadow .15s, opacity .15s; }
.bz-chain-card:active{ cursor:grabbing; }
.bz-chain-card:hover{ box-shadow:0 0 0 2px var(--accent), var(--shadow); }
.bz-chain-card.selected{ box-shadow:0 0 0 2px var(--accent), var(--shadow); }
.bz-chain-card-incomplete{ color:var(--text-faint); font-size:11px; font-style:italic; padding-left:28px; }
.bz-chain-delete-btn{ position:absolute; top:-8px; right:-8px; background:var(--surface); border:1px solid var(--border); border-radius:50%; width:20px; height:20px; font-size:11px; line-height:1; cursor:pointer; color:var(--text-faint); }
.bz-chain-delete-btn:hover{ color:var(--danger); border-color:var(--danger); }

/* Соединение "кликни на один, потом на другой" (см. bazaarChainConnectingFrom
   в js/bazaarChain.js) — вместо перетаскивания провода за курсором (отдельный
   большой кусок инженерии — hit-testing по пикселям, resize при зуме и т.д.),
   но с тем же осязаемым результатом: жмёшь на кнопку, карточки-кандидаты
   светятся, кликаешь по одной — линия сама отрисовывается с анимацией. */
.bz-chain-connection-row{ padding-left:28px; margin-top:2px; }
.bz-chain-connect-port{
  background:none; border:1px dashed var(--border); border-radius:8px; color:var(--text-faint);
  font-size:11px; padding:3px 8px; cursor:pointer; font-family:'IBM Plex Mono',monospace;
}
.bz-chain-connect-port:hover{ color:var(--accent); border-color:var(--accent); }
.bz-chain-expand-btn{
  background:none; border:1px dashed var(--border); border-radius:8px; color:var(--text-faint);
  font-size:11px; padding:3px 8px; cursor:pointer; font-family:'IBM Plex Mono',monospace; width:100%; margin-top:4px;
}
.bz-chain-expand-btn:hover{ color:var(--accent); border-color:var(--accent); }
.bz-chain-connected-to{ font-size:11px; color:var(--text-dim); font-family:'IBM Plex Mono',monospace; }

/* Инлайн-цена (order/instant) и количество прямо на карточке цепочки — цена
   тянется из уже загруженного снимка базара, клик применяет её сразу, без
   похода в боковую панель (см. bzChainInlinePriceRowHtml/bzChainQtyInputRowHtml
   в js/bazaarChain.js). */
.bz-chain-price-row{
  display:flex; gap:4px; padding-left:28px; margin-top:2px;
}
.bz-chain-price-row button{
  flex:1; min-width:0; font-family:'IBM Plex Mono',monospace; font-size:10.5px; padding:3px 6px;
  border:1px solid var(--border); border-radius:7px; background:var(--bg); color:var(--text-faint);
  cursor:pointer; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.bz-chain-price-row button.active{ background:var(--accent-soft); color:var(--accent-strong); border-color:var(--accent); font-weight:700; }
.bz-chain-qty-row{
  display:flex; align-items:center; gap:6px; padding-left:28px; margin-top:4px;
}
.bz-chain-qty-label{ font-size:10px; color:var(--text-faint); text-transform:uppercase; letter-spacing:.03em; flex:none; }
.bz-chain-qty-input{
  width:80px; font-family:'IBM Plex Mono',monospace; font-size:12px; padding:2px 6px;
  background:var(--bg); border:1px solid var(--border); border-radius:6px; color:var(--text);
}
.bz-chain-qty-input:focus{ outline:none; border-color:var(--accent); }
.bz-chain-card-summary{ margin-top:4px; }
.bz-chain-disconnect-btn{
  background:none; border:none; color:var(--text-faint); font-size:10px; cursor:pointer; margin-left:6px; padding:0;
}
.bz-chain-disconnect-btn:hover{ color:var(--danger); }
.bz-chain-card.bz-chain-connecting-source{ box-shadow:0 0 0 2px var(--gold), var(--shadow); }
.bz-chain-card.bz-chain-connect-eligible{
  cursor:pointer; box-shadow:0 0 0 2px var(--accent), var(--shadow);
  animation:bz-chain-eligible-pulse 1.1s ease-in-out infinite;
}
.bz-chain-card.bz-chain-connect-ineligible{ opacity:.35; }
@keyframes bz-chain-eligible-pulse{
  0%, 100%{ box-shadow:0 0 0 2px var(--accent), var(--shadow); }
  50%{ box-shadow:0 0 0 5px color-mix(in srgb, var(--accent) 35%, transparent), var(--shadow); }
}
.bz-chain-card.bz-chain-pulse{ animation:bz-chain-connected-pulse .5s ease; }
@keyframes bz-chain-connected-pulse{
  0%{ box-shadow:0 0 0 2px var(--accent), var(--shadow); }
  50%{ box-shadow:0 0 0 8px color-mix(in srgb, var(--accent) 45%, transparent), var(--shadow); }
  100%{ box-shadow:0 0 0 2px var(--accent), var(--shadow); }
}
/* pathLength="1" на самом path — длина дуги нормализована к 1, поэтому один и
   тот же dasharray/dashoffset "рисует" линию за одинаковое время независимо
   от того, короткая она или длинная (соседние карточки или через весь холст). */
.craft-tree-lines path.bz-chain-new-edge{
  stroke-dasharray:1; stroke-dashoffset:1; animation:bz-chain-draw-line .4s ease forwards;
}
@keyframes bz-chain-draw-line{ to{ stroke-dashoffset:0; } }
.th-name-copy{ cursor:pointer; }
.th-name-copy:hover{ text-decoration:underline; color:var(--accent); }
/* Приветственная модалка первого запуска (Этап 11) — тот же центрированный
   паттерн, что и .palette, просто меньше и без списка результатов. */
.onboarding-modal{
  position:fixed; top:50%; left:50%; transform:translate(-50%,-50%) scale(.98);
  width:min(420px, calc(100vw - 32px));
  background:var(--surface); border:1px solid var(--border); border-radius:18px; box-shadow:var(--shadow);
  z-index:42; opacity:0; pointer-events:none; transition:opacity .16s, transform .16s;
}
.onboarding-modal.open{ opacity:1; pointer-events:auto; transform:translate(-50%,-50%) scale(1); }
.onboarding-inner{ padding:22px; }
.onboarding-inner input{
  background:var(--bg-alt); border:1px solid var(--border); border-radius:13px;
  padding:9px 12px; color:var(--text); font-family:'Manrope',sans-serif; font-size:14px;
}
.onboarding-actions{ display:flex; justify-content:flex-end; gap:8px; }
#onboardingOverlay{ z-index:41; }

/* Экран логина (Этап 12) — блокирует ВЕСЬ интерфейс до входа, поэтому
   z-index выше всего остального в приложении (item-lore-popup в профиле —
   45 — самый высокий из существующих) и своя полноэкранная непрозрачная
   подложка, а не .detail-overlay (у той top:57px — оставляет виден хедер). */
.auth-gate{
  position:fixed; inset:0; z-index:60; display:flex; align-items:center; justify-content:center;
  background:var(--bg);
}
.auth-card{
  width:min(380px, calc(100vw - 32px)); background:var(--surface); border:1px solid var(--border);
  border-radius:18px; padding:28px 26px; box-shadow:var(--shadow); position:relative;
}
.auth-lang-switch{ position:absolute; top:14px; right:14px; }
.auth-lang-switch .icon-btn{ background:none; border:none; cursor:pointer; font-size:18px; padding:4px; border-radius:8px; }
.auth-lang-switch .icon-btn:hover{ background:var(--bg-alt); }
.auth-lang-menu{
  position:absolute; top:calc(100% + 4px); right:0; background:var(--surface); border:1px solid var(--border);
  border-radius:10px; box-shadow:var(--shadow); overflow:hidden; z-index:1; min-width:120px;
}
.auth-lang-menu button{
  display:block; width:100%; text-align:left; background:none; border:none; cursor:pointer;
  padding:8px 12px; font-size:13px; color:var(--text); font-family:'Manrope',sans-serif; margin:0;
}
.auth-lang-menu button:hover{ background:var(--bg-alt); }
.auth-lang-menu button.active{ color:var(--accent); font-weight:700; }
.auth-card h2{ font-family:'Sora',sans-serif; font-size:1.3rem; margin:0 0 8px; }
.auth-card form label{
  display:block; font-size:11px; color:var(--text-faint); margin:14px 0 6px;
  text-transform:uppercase; letter-spacing:.06em; font-family:'IBM Plex Mono',monospace;
}
.auth-card form input{
  width:100%; background:var(--bg-alt); border:1px solid var(--border); border-radius:10px;
  padding:9px 12px; color:var(--text); font-family:'Manrope',sans-serif; font-size:14px;
}
.auth-card form input:focus{ outline:none; border-color:var(--accent); }
/* ID-селектор, не общий "button" внутри .auth-card — иначе перебивал бы
   кнопки языкового меню (#authLangMenu), которое тоже внутри .auth-card. */
#authSubmit{
  width:100%; margin-top:18px; font-weight:700; padding:10px 16px; border-radius:12px; border:none;
  cursor:pointer; background:var(--accent); color:#08221f; font-family:'Manrope',sans-serif; font-size:14px;
}
#authSubmit:disabled{ opacity:.6; cursor:default; }
#authStatus{ margin:12px 0 0; font-size:13px; min-height:1.2em; }
#authStatus.error{ color:var(--danger); }

/* Плавающая иконка, тот же приём, что у .hero-icon на сайте (server/site/style.css) */
@keyframes auth-float{ 0%,100%{ transform:translateY(0) } 50%{ transform:translateY(-8px) } }
@keyframes auth-fade-in{ from{ opacity:0; transform:translateY(10px) scale(.96) } to{ opacity:1; transform:translateY(0) scale(1) } }
.auth-icon{
  display:block; width:64px; height:64px; margin:0 auto 16px; border-radius:16px;
  box-shadow:var(--shadow); animation:auth-float 5s ease-in-out infinite, auth-fade-in .5s ease-out;
}
.auth-card-center{ text-align:center; }
.auth-card-center h2{ margin-bottom:0; }

.auth-remember-row{
  display:flex !important; align-items:center; gap:7px; margin:14px 0 0 !important;
  font-size:13px; text-transform:none !important; letter-spacing:normal !important; font-family:'Manrope',sans-serif !important;
  color:var(--text-dim); cursor:pointer;
}
.auth-remember-row input{ width:auto; margin:0; }

.auth-device-mismatch{ margin-top:14px; text-align:center; }
.auth-device-mismatch .icon-btn{ font-size:22px; background:none; border:none; cursor:pointer; }
.auth-device-mismatch p{ margin:8px 0 0; }

.auth-tabs{ width:100%; margin:0 0 18px; }
.auth-tabs .segmented-btn{ flex:1; text-align:center; }

/* Ник Minecraft на регистрации — необязательное поле, оформлено заметно
   тише остальных (полупрозрачная тонкая рамка) по просьбе пользователя —
   видно, что оно есть, но не тянет внимание на себя как обязательные поля. */
.auth-optional-label{ opacity:.6; }
.auth-input-subtle{ border-color:color-mix(in srgb, var(--border) 50%, transparent) !important; opacity:.75; }
.auth-input-subtle:focus{ opacity:1; }

#authSignupSubmit, #authCodeSubmit{
  width:100%; margin-top:18px; font-weight:700; padding:10px 16px; border-radius:12px; border:none;
  cursor:pointer; background:var(--accent); color:#08221f; font-family:'Manrope',sans-serif; font-size:14px;
}
#authSignupSubmit:disabled, #authCodeSubmit:disabled{ opacity:.6; cursor:default; }
#authSignupStatus, #authCodeStatus{ margin:12px 0 0; font-size:13px; min-height:1.2em; }
#authSignupStatus.error, #authCodeStatus.error{ color:var(--danger); }
#authSignupStatus.ok, #authCodeStatus.ok{ color:var(--accent-strong); }

.auth-spam-hint{ margin-top:-18px; font-size:11px; opacity:.75; }

.auth-code-row{ display:flex; gap:8px; justify-content:center; margin-top:16px; }
.auth-code-box{
  width:42px !important; height:52px; text-align:center; font-size:22px; font-weight:700;
  font-family:'IBM Plex Mono',monospace !important; text-transform:uppercase; padding:0 !important;
}

#updateRequiredGate .auth-card, #updatingOverlay .auth-card{ text-align:center; }
#updateRequiredBtn{
  width:100%; margin-top:18px; font-weight:700; padding:10px 16px; border-radius:12px; border:none;
  cursor:pointer; background:var(--accent); color:#08221f; font-family:'Manrope',sans-serif; font-size:14px;
}

.chart-tooltip{
  position:absolute; top:0; pointer-events:none; background:var(--surface); border:1px solid var(--border);
  border-radius:10px; padding:6px 10px; font-family:'IBM Plex Mono',monospace; font-size:12px; white-space:nowrap; z-index:5;
}

/* Пока не пришёл первый снимок Bazaar от сервера (см. #bazaarLoadingState в
   index.html, updateServerBadge()/afterBazaarChanged() в app.js) — раньше на
   этом месте была просто пустота (карточки скрыты по умолчанию до первых
   данных), выглядело как будто приложение сломано, а не грузится. */
.bazaar-loading{
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:16px;
  padding:80px 20px; color:var(--text-dim); text-align:center;
}
.bazaar-loading-spinner{
  width:34px; height:34px; border-radius:50%;
  border:3px solid var(--border); border-top-color:var(--accent);
  animation:update-badge-spin .9s linear infinite;
}
.bazaar-loading p{ margin:0; font-size:14px; }

/* Демо-версия сайта (server/site/demo/): аккуратное всплывающее сообщение
   «эта функция только в приложении» вместо системного alert() (см.
   showDemoNotice() в app.js). */
.demo-toast{
  position:fixed; left:50%; bottom:28px; transform:translate(-50%, 16px);
  max-width:min(440px, calc(100vw - 32px)); z-index:9999;
  background:var(--surface); color:var(--text); border:1px solid var(--accent);
  border-left:3px solid var(--accent);
  border-radius:12px; padding:14px 18px; font-size:14px; line-height:1.45;
  box-shadow:0 12px 40px rgba(0,0,0,.28);
  opacity:0; pointer-events:none; transition:opacity .22s ease, transform .22s ease;
}
.demo-toast.show{ opacity:1; transform:translate(-50%, 0); }

/* Функции только для установленного приложения (трей, автообновление,
   уведомления событий, экспорт/импорт профиля, ключ API) — в браузерной
   демке физически не работают, поэтому там скрыты. Атрибут data-demo ставит
   demoShim.js; в настоящем приложении его нет и всё показывается как обычно. */
html[data-demo] .app-only{ display:none !important; }
