/* Без @property браузер считает кастомные CSS-переменные непрозрачными
   токенами и не умеет их плавно интерполировать при смене темы — даже если
   на итоговое свойство (background-color и т.п.) навешан transition, смена
   переменной применяется скачком. Регистрируем их как <color>, чтобы
   переключение Xbox <-> Steam красилось плавно, а не дёргано. */
@property --bg { syntax: "<color>"; inherits: true; initial-value: #0b1710; }
@property --bg-panel { syntax: "<color>"; inherits: true; initial-value: #0f2015; }
@property --green { syntax: "<color>"; inherits: true; initial-value: #6bbf1a; }
@property --green-bright { syntax: "<color>"; inherits: true; initial-value: #9be51a; }
@property --green-dark { syntax: "<color>"; inherits: true; initial-value: #1c3a12; }
@property --text { syntax: "<color>"; inherits: true; initial-value: #e8f2e0; }
@property --text-dim { syntax: "<color>"; inherits: true; initial-value: #9fb08f; }
@property --row-bg { syntax: "<color>"; inherits: true; initial-value: #12241a; }
@property --row-bg-alt { syntax: "<color>"; inherits: true; initial-value: #0f1e16; }
@property --row-hover { syntax: "<color>"; inherits: true; initial-value: #1a3322; }
@property --unlocked { syntax: "<color>"; inherits: true; initial-value: #b7ff3b; }
@property --locked { syntax: "<color>"; inherits: true; initial-value: #5a6a56; }
@property --rare-gold { syntax: "<color>"; inherits: true; initial-value: #e8c34a; }
@property --border { syntax: "<color>"; inherits: true; initial-value: #223a28; }
@property --bg-radial { syntax: "<color>"; inherits: true; initial-value: #16301f; }
@property --topbar-grad-1 { syntax: "<color>"; inherits: true; initial-value: #14281a; }
@property --topbar-grad-2 { syntax: "<color>"; inherits: true; initial-value: #0c1810; }
@property --accent-shade { syntax: "<color>"; inherits: true; initial-value: #3f7a10; }

:root {
  --bg: #0b1710;
  --bg-panel: #0f2015;
  --green: #6bbf1a;
  --green-bright: #9be51a;
  --green-dark: #1c3a12;
  --text: #e8f2e0;
  --text-dim: #9fb08f;
  --row-bg: #12241a;
  --row-bg-alt: #0f1e16;
  --row-hover: #1a3322;
  --unlocked: #b7ff3b;
  --locked: #5a6a56;
  --rare-gold: #e8c34a;
  --border: #223a28;
  --bg-radial: #16301f;
  --topbar-grad-1: #14281a;
  --topbar-grad-2: #0c1810;
  --accent-shade: #3f7a10;
  font-family: "Segoe UI", Tahoma, Arial, sans-serif;
}

/* Steam-тема — активируется атрибутом data-platform="steam" на <html> при
   переключении платформы. Значения тех же переменных подменяются на палитру
   Steam (тёмно-синий фон, голубой акцент вместо зелёного), поэтому вся
   остальная разметка перекрашивается автоматически без доп. правил. */
/* Switch 2 — временная нейтральная тёмно-серая тема с красным акцентом
   (плейсхолдер, пока не готов свой логотип/палитра — см. reference про Switch 2). */
html[data-platform="switch2"] {
  --bg: #17181a;
  --bg-panel: #1e2023;
  --green: #e6383f;
  --green-bright: #ff5a60;
  --green-dark: #4a1618;
  --text: #f2f2f2;
  --text-dim: #9a9a9e;
  --row-bg: #1e2023;
  --row-bg-alt: #191a1c;
  --row-hover: #2a2c2f;
  --unlocked: #ff5a60;
  --locked: #5c5c60;
  --rare-gold: #e8c34a;
  --border: #3a3c40;
  --bg-radial: #202224;
  --topbar-grad-1: #1e2023;
  --topbar-grad-2: #101112;
  --accent-shade: #7a1f22;
}

/* 3DS/DS/PSP/PS1/PS2 — те же ручные retro-библиотеки, что и Switch 2 (см.
   RETRO_PLATFORM_META в app.js), временные нейтральные палитры-плейсхолдеры,
   каждая со своим акцентом, пока нет своих логотипов/цветов от пользователя. */
html[data-platform="3ds"] {
  --bg: #14191f;
  --bg-panel: #1a212a;
  --green: #3ab6ff;
  --green-bright: #7ad2ff;
  --green-dark: #143a52;
  --text: #eaf4fb;
  --text-dim: #8fa3b3;
  --row-bg: #1a212a;
  --row-bg-alt: #151b22;
  --row-hover: #223142;
  --unlocked: #7ad2ff;
  --locked: #5a6a75;
  --rare-gold: #e8c34a;
  --border: #2a3d4d;
  --bg-radial: #1c2733;
  --topbar-grad-1: #1a212a;
  --topbar-grad-2: #0e1319;
  --accent-shade: #1c5a80;
}

html[data-platform="ds"] {
  --bg: #17151f;
  --bg-panel: #1e1b29;
  --green: #a06bff;
  --green-bright: #c39bff;
  --green-dark: #3a1f5c;
  --text: #f0ecf9;
  --text-dim: #9a90ab;
  --row-bg: #1e1b29;
  --row-bg-alt: #191623;
  --row-hover: #2b2540;
  --unlocked: #c39bff;
  --locked: #5c5568;
  --rare-gold: #e8c34a;
  --border: #362c4d;
  --bg-radial: #221d30;
  --topbar-grad-1: #1e1b29;
  --topbar-grad-2: #110f18;
  --accent-shade: #522f80;
}

/* GBA — тот же лиловый регистр, что у самой консоли (indigo), но темнее и
   холоднее DS, чтобы платформы не путались между собой в свитчере. */
html[data-platform="gba"] {
  --bg: #171420;
  --bg-panel: #1e1a2c;
  --green: #7c5cff;
  --green-bright: #a48bff;
  --green-dark: #35215c;
  --text: #ece9f7;
  --text-dim: #948aab;
  --row-bg: #1e1a2c;
  --row-bg-alt: #191525;
  --row-hover: #2a2340;
  --unlocked: #a48bff;
  --locked: #59526b;
  --rare-gold: #e8c34a;
  --border: #332b4d;
  --bg-radial: #201a2f;
  --topbar-grad-1: #1e1a2c;
  --topbar-grad-2: #100e17;
  --accent-shade: #4630a0;
}

/* PS3 — синий регистр PlayStation, темнее и холоднее PSP/PS2, чтобы три
   PlayStation-платформы не сливались друг с другом в свитчере. */
html[data-platform="ps3"] {
  --bg: #0f1420;
  --bg-panel: #161d2c;
  --green: #3b82f6;
  --green-bright: #7db1ff;
  --green-dark: #17356b;
  --text: #eaf0fb;
  --text-dim: #8b9ab0;
  --row-bg: #161d2c;
  --row-bg-alt: #121826;
  --row-hover: #1f2a40;
  --unlocked: #7db1ff;
  --locked: #566277;
  --rare-gold: #e8c34a;
  --border: #29354d;
  --bg-radial: #131a28;
  --topbar-grad-1: #161d2c;
  --topbar-grad-2: #0a0e16;
  --accent-shade: #1e4f9c;
}

/* PS4 — тот же синий регистр PlayStation, что у PS3, но заметно светлее/ярче,
   чтобы платформы не путались в свитчере. */
html[data-platform="ps4"] {
  --bg: #0c1626;
  --bg-panel: #142236;
  --green: #2f8fff;
  --green-bright: #7fc0ff;
  --green-dark: #12376b;
  --text: #e9f2fc;
  --text-dim: #86a0bd;
  --row-bg: #142236;
  --row-bg-alt: #101c2c;
  --row-hover: #1c2f47;
  --unlocked: #7fc0ff;
  --locked: #536578;
  --rare-gold: #e8c34a;
  --border: #223752;
  --bg-radial: #101d30;
  --topbar-grad-1: #142236;
  --topbar-grad-2: #080f1a;
  --accent-shade: #1a5aa0;
}

/* PS5 — светлая холодная гамма (белый корпус консоли), в противовес тёмно-синим
   PS3/PS4 — самый заметный контраст в свитчере среди трёх PlayStation-платформ. */
html[data-platform="ps5"] {
  --bg: #12151c;
  --bg-panel: #1a1e28;
  --green: #6ec3ff;
  --green-bright: #cfeaff;
  --green-dark: #23425e;
  --text: #f2f6fb;
  --text-dim: #93a0b3;
  --row-bg: #1a1e28;
  --row-bg-alt: #151821;
  --row-hover: #232a37;
  --unlocked: #cfeaff;
  --locked: #5c6675;
  --rare-gold: #e8c34a;
  --border: #2b3242;
  --bg-radial: #171b24;
  --topbar-grad-1: #1a1e28;
  --topbar-grad-2: #0a0c11;
  --accent-shade: #3a6f95;
}

/* PS Vita — фиолетовый/сиреневый, вместо синего регистра PS3/4/5: платформа
   не консольная, а портативная, и в свитчере не должна сливаться с ними. */
html[data-platform="vita"] {
  --bg: #17121f;
  --bg-panel: #201a2c;
  --green: #a855f7;
  --green-bright: #d1a3ff;
  --green-dark: #4c1d7a;
  --text: #f3eefc;
  --text-dim: #9d8fb0;
  --row-bg: #201a2c;
  --row-bg-alt: #191424;
  --row-hover: #2c2440;
  --unlocked: #d1a3ff;
  --locked: #5f5570;
  --rare-gold: #e8c34a;
  --border: #362a4a;
  --bg-radial: #1c1628;
  --topbar-grad-1: #201a2c;
  --topbar-grad-2: #0e0b14;
  --accent-shade: #6b2fa8;
}

html[data-platform="psp"] {
  --bg: #14181a;
  --bg-panel: #1a2124;
  --green: #4ecdc4;
  --green-bright: #7de5dc;
  --green-dark: #164a44;
  --text: #eaf6f4;
  --text-dim: #8fa8a4;
  --row-bg: #1a2124;
  --row-bg-alt: #151b1d;
  --row-hover: #223330;
  --unlocked: #7de5dc;
  --locked: #576b67;
  --rare-gold: #e8c34a;
  --border: #2a4442;
  --bg-radial: #1c2726;
  --topbar-grad-1: #1a2124;
  --topbar-grad-2: #0e1314;
  --accent-shade: #1c6c62;
}

html[data-platform="ps1"] {
  --bg: #19181a;
  --bg-panel: #211f21;
  --green: #b8b2a8;
  --green-bright: #ded8cc;
  --green-dark: #4a453e;
  --text: #f2f0ec;
  --text-dim: #a39d92;
  --row-bg: #211f21;
  --row-bg-alt: #1a181a;
  --row-hover: #302d2c;
  --unlocked: #ded8cc;
  --locked: #605c56;
  --rare-gold: #e8c34a;
  --border: #423d38;
  --bg-radial: #24211f;
  --topbar-grad-1: #211f21;
  --topbar-grad-2: #131213;
  --accent-shade: #55503f;
}

html[data-platform="ps2"] {
  --bg: #0f1320;
  --bg-panel: #151a2c;
  --green: #4a6bdb;
  --green-bright: #7d97ec;
  --green-dark: #1c2c5c;
  --text: #eaeefa;
  --text-dim: #8b93b0;
  --row-bg: #151a2c;
  --row-bg-alt: #101425;
  --row-hover: #202a48;
  --unlocked: #7d97ec;
  --locked: #565e78;
  --rare-gold: #e8c34a;
  --border: #2a3358;
  --bg-radial: #171d33;
  --topbar-grad-1: #151a2c;
  --topbar-grad-2: #0a0d18;
  --accent-shade: #253a75;
}

/* Xbox Original (2001) — тоже без ачивментов (система появилась только с
   Xbox 360), тот же ручной retro-принцип. Янтарный акцент, чтобы явно
   отличаться от ярко-зелёной темы обычной вкладки Xbox (360/One/Series). */
html[data-platform="xbox_og"] {
  --bg: #191510;
  --bg-panel: #211b14;
  --green: #e8952e;
  --green-bright: #ffb75c;
  --green-dark: #5c3c14;
  --text: #f7f0e6;
  --text-dim: #ad9d86;
  --row-bg: #211b14;
  --row-bg-alt: #1a1610;
  --row-hover: #332818;
  --unlocked: #ffb75c;
  --locked: #6b6053;
  --rare-gold: #e8c34a;
  --border: #4a3c26;
  --bg-radial: #251f16;
  --topbar-grad-1: #211b14;
  --topbar-grad-2: #120e0a;
  --accent-shade: #7a4f18;
}

/* У большей части retro-платформ (Switch 2, 3DS, Xbox Original) нет системы
   ачивментов — прячем панель ачивментов (тулбар поиска/сортировки, группы).
   PS1/PS2/PSP/DS — исключение: у них есть реальные ачивменты с
   retroachievements.org (класс .retro-ra-platform, тоже ставится в
   applyPlatformTheme() в app.js), поэтому для них эта панель остаётся видимой. */
html.retro-platform:not(.retro-ra-platform) #tracker .toolbar,
html.retro-platform:not(.retro-ra-platform) #tracker .group {
  display: none;
}
/* Кнопки Xbox-специфичных источников (OpenXBL-ресинк, иконки/год со
   stratege.ru) не имеют смысла ни у одной retro-платформы, включая RA. */
html.retro-platform #sync-game-btn,
html.retro-platform #stratege-icons-btn,
html.retro-platform #year-resolve-btn {
  display: none;
}
/* stratege.ru/год-резолв — только для Xbox-игр, не для Steam (там свой
   автоматический источник года — официальный Store API, см. resolveMissingSteamYears). */
html[data-platform="steam"] #stratege-icons-btn,
html[data-platform="steam"] #year-resolve-btn {
  display: none;
}
/* Описания скрытых ачивментов со stratege.ru — наоборот, только для Steam
   (у Xbox своя логика locked_description прямо из OpenXBL, спойлерить нечего). */
html:not([data-platform="steam"]) #stratege-desc-btn {
  display: none;
}

html[data-platform="steam"] {
  --bg: #171a21;
  --bg-panel: #1b2838;
  --green: #66c0f4;
  --green-bright: #8ed1ff;
  --green-dark: #1b3a52;
  --text: #e9f3fb;
  --text-dim: #8f98a0;
  --row-bg: #1b2838;
  --row-bg-alt: #16202d;
  --row-hover: #2a475e;
  --unlocked: #a4d007;
  --locked: #5a6672;
  --rare-gold: #e8c34a;
  --border: #2a3f5a;
  --bg-radial: #1b2838;
  --topbar-grad-1: #1b2838;
  --topbar-grad-2: #0f1621;
  --accent-shade: #1a4a68;
}

/* Плавная перекраска темы при переключении платформы вместо резкой смены. */
body,
.topbar,
.icon-btn,
.secondary-btn,
button[type="submit"],
.sidebar,
.sidebar-item,
.sidebar-item.active,
.sidebar-cover,
.cover-tile,
.ach-row,
.ach-icon,
.filter-btn,
.filter-btn.active,
.modal,
.platform-menu,
.platform-menu-item,
#api-key-input, #steam-api-key-input, #steam-id-input, #picker-search, #search, #game-select, #sort-select, .library-sort, .library-search,
.picker-item,
.group-title,
.covers-group-title,
.status {
  transition: background-color 0.4s ease, background-image 0.4s ease, border-color 0.4s ease,
    color 0.4s ease, box-shadow 0.4s ease;
}

* { box-sizing: border-box; scrollbar-width: thin; scrollbar-color: var(--green-dark) var(--bg); }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-track { background: var(--bg); }
*::-webkit-scrollbar-thumb { background: var(--green-dark); border-radius: 5px; border: 2px solid var(--bg); background-clip: padding-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--green); }

body {
  margin: 0;
  background: radial-gradient(ellipse at top, var(--bg-radial) 0%, var(--bg) 60%);
  color: var(--text);
  min-height: 100vh;
  transition: background-color 0.4s ease, background-image 0.4s ease, color 0.4s ease;
}

.hidden { display: none !important; }

.topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  background: linear-gradient(180deg, var(--topbar-grad-1) 0%, var(--topbar-grad-2) 100%);
  border-bottom: 2px solid var(--green-dark);
  position: sticky;
  top: 0;
  z-index: 10;
}

.brand {
  display: flex; align-items: center; gap: 10px; font-size: 14px;
  background: none; border: none; padding: 4px 6px; margin: -4px -6px; border-radius: 4px;
  cursor: pointer;
}
.brand:hover { background: rgba(255,255,255,0.06); }
/* object-fit: contain — логотипы платформ (особенно пользовательские, см.
   static/img/*-orb.png) не всегда квадратные по факту, без contain они бы
   растягивались/сплющивались в квадратную рамку. */
.brand-orb { width: 26px; height: 26px; object-fit: contain; filter: drop-shadow(0 0 5px rgba(155,229,26,0.55)); transition: filter 0.4s ease; }
/* steamalikeicon.png — чёрный глиф на прозрачном фоне, на тёмной шапке
   сливался бы с фоном и был виден только размытый ореол — инвертируем
   в белый, чтобы сам значок читался, а свечение осталось акцентным. */
html[data-platform="steam"] .brand-orb { filter: invert(1) drop-shadow(0 0 5px rgba(102,192,244,0.7)); }
/* Все retro-платформы (Switch 2/3DS/DS/PSP/PS1/PS2/Xbox Original) используют
   свой уже определённый --green-bright из палитры платформы (см. блоки
   html[data-platform="..."] выше) — не нужно дублировать rgba под каждую. */
html.retro-platform .brand-orb { filter: drop-shadow(0 0 5px var(--green-bright)); }
.brand-text {
  font-family: "Eurostile", "Century Gothic", "Segoe UI", Tahoma, sans-serif;
  font-weight: 700;
  letter-spacing: 5px;
  font-size: 15px;
  color: #eafce0;
  text-shadow: 0 0 10px rgba(155, 229, 26, 0.45), 0 0 1px rgba(255,255,255,0.6);
  transition: color 0.4s ease, text-shadow 0.4s ease;
}
html[data-platform="steam"] .brand-text {
  font-family: "Motiva Sans", "Arial Black", "Arial", sans-serif;
  font-weight: 900;
  letter-spacing: 1px;
  color: #e9f3fb;
  text-shadow: 0 0 10px rgba(102, 192, 244, 0.45), 0 0 1px rgba(255,255,255,0.6);
}
html.retro-platform .brand-text {
  font-family: "Segoe UI", "Arial", sans-serif;
  font-weight: 800;
  letter-spacing: 2px;
  color: var(--text);
  text-shadow: 0 0 10px var(--green-bright), 0 0 1px rgba(255,255,255,0.6);
}
.brand-caret { font-size: 10px; color: var(--text-dim); margin-left: -2px; }

.profile { display: flex; align-items: center; gap: 8px; margin-left: auto; font-size: 13px; color: var(--text-dim); }
.gamerpic { width: 26px; height: 26px; border-radius: 3px; background: var(--green-dark) center/cover no-repeat; display: inline-block; }
.gamertag { color: var(--text); font-weight: 600; }
.gamerscore::before { content: "⚡"; margin-right: 3px; color: var(--green-bright); }

.icon-btn {
  background: var(--row-bg);
  border: 1px solid var(--border);
  color: var(--text);
  width: 32px; height: 32px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
  display: flex; align-items: center; justify-content: center;
}
.icon-btn:hover { background: var(--row-hover); }
.icon-btn img { width: 18px; height: 18px; display: block; opacity: 0.9; }
.icon-btn:hover img { opacity: 1; }

main { max-width: 1100px; margin: 0 auto; padding: 16px; }

.panel h2 { font-size: 16px; margin: 4px 0 10px; }
.panel p { color: var(--text-dim); font-size: 13px; line-height: 1.6; }
.panel a { color: var(--green-bright); }

.platform-icons-list { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.platform-icon-row {
  display: flex; align-items: center; gap: 10px;
  background: var(--row-bg); border: 1px solid var(--border); border-radius: 4px;
  padding: 6px 10px;
}
.platform-icon-preview { width: 26px; height: 26px; border-radius: 3px; object-fit: cover; flex: none; }
.platform-icon-label { flex: 1; font-size: 13px; }
.platform-icon-row .file-btn, .platform-icon-reset-btn { flex: none; }

.link-btn {
  background: none; border: none; padding: 0; margin: 0;
  color: var(--green-bright); text-decoration: underline; cursor: pointer;
  font-size: inherit; font-family: inherit;
}
.link-btn:hover { color: var(--green); }

#settings-form, #steam-settings-form { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
#api-key-input, #steam-api-key-input, #steam-id-input, #picker-search, #search, #game-select, #sort-select, #sgdb-search-name, #cover-editor-name-input {
  background: var(--row-bg);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 8px 10px;
  border-radius: 4px;
  font-size: 13px;
}
#api-key-input, #steam-api-key-input { flex: 1 1 220px; }
#steam-id-input { flex: 1 1 160px; }
button[type="submit"], .secondary-btn {
  background: var(--green);
  border: none;
  color: #0b1710;
  font-weight: 700;
  padding: 8px 14px;
  border-radius: 4px;
  cursor: pointer;
}
button[type="submit"]:hover, .secondary-btn:hover { background: var(--green-bright); }
.secondary-btn { background: var(--row-bg); color: var(--text); border: 1px solid var(--border); font-weight: 600; }
.secondary-btn:hover { background: var(--row-hover); }

.status { font-size: 13px; margin-top: 8px; }
.status.error { color: #ff6b6b; }
.status.ok { color: var(--green-bright); }

.picker-list { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; max-height: 60vh; overflow-y: auto; }
.picker-item {
  display: flex; align-items: center; gap: 10px;
  background: var(--row-bg); border: 1px solid var(--border);
  border-radius: 4px; padding: 8px 10px; cursor: pointer;
}
.picker-item:hover { background: var(--row-hover); border-color: var(--green); }
.picker-item img { width: 40px; height: 40px; border-radius: 3px; object-fit: cover; background: var(--green-dark); }
.picker-item .meta { display: flex; flex-direction: column; }
.picker-item .meta .name { font-weight: 600; font-size: 13px; }
.picker-item .meta .sub { font-size: 11px; color: var(--text-dim); }

.tracker-layout { display: flex; gap: 16px; align-items: flex-start; }
.tracker-main { flex: 1; min-width: 0; }

.sidebar {
  width: var(--sidebar-width, 180px); flex-shrink: 0;
  background: var(--row-bg); border: 1px solid var(--border); border-radius: 6px;
  display: flex; flex-direction: column;
  max-height: calc(100vh - 90px);
  position: sticky; top: 70px;
}
.sidebar-resizer {
  flex-shrink: 0; align-self: stretch; width: 10px; margin: 0 -5px;
  cursor: col-resize; position: relative; z-index: 1;
}
.sidebar-resizer::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 50%;
  width: 2px; transform: translateX(-50%); border-radius: 2px;
  background: transparent; transition: background 0.15s;
}
.sidebar-resizer:hover::after, .sidebar-resizer.dragging::after { background: var(--green); }
.sidebar-resizer.dragging { cursor: col-resize; }
.sidebar-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 10px 8px; font-size: 11px; letter-spacing: 1px; text-transform: uppercase;
  color: var(--text-dim); border-bottom: 1px solid var(--border);
}
.sidebar-header-actions { display: flex; gap: 6px; }
.sidebar-header .icon-btn { width: 24px; height: 24px; font-size: 13px; }
.library-search {
  margin: 8px 8px 0; padding: 6px 8px; font-size: 11px;
  background: var(--row-bg); border: 1px solid var(--border); color: var(--text); border-radius: 4px;
  width: calc(100% - 16px);
}
.library-sort {
  margin: 6px 8px 0; padding: 6px 8px; font-size: 11px;
  background: var(--row-bg); border: 1px solid var(--border); color: var(--text-dim); border-radius: 4px;
}
.sidebar-list { overflow-y: auto; padding: 6px; display: flex; flex-direction: column; gap: 4px; }

.sidebar-item {
  display: flex; align-items: center; gap: 8px; position: relative;
  padding: 6px; border-radius: 4px; cursor: pointer;
}
.sidebar-item:hover { background: var(--row-hover); }
.sidebar-item.active { background: var(--green-dark); box-shadow: inset 0 0 0 1px var(--green); }
.sidebar-cover {
  width: 36px; height: 36px; border-radius: 3px; object-fit: cover; flex-shrink: 0;
  background: linear-gradient(145deg, var(--green) 0%, var(--accent-shade) 100%);
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 13px; color: #0b1710;
}
.sidebar-meta { flex: 1; min-width: 0; }
/* Длинное название переносится на вторую строку, а не режется многоточием:
   места в строке списка хватает, а обрезанное имя ("DEATH STRANDING 2: ON
   THE ...") ничего не говорит. Двумя строками и ограничиваемся, иначе
   какой-нибудь сборник с DLC в названии распухнет на пол-экрана. */
.sidebar-name {
  font-size: 12px; font-weight: 600; line-height: 1.25;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; overflow-wrap: anywhere;
}
.game-year { font-weight: 400; opacity: 0.6; font-size: 0.9em; }
.sidebar-progress { display: block; font-size: 10px; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Колонка года/значка издания — отдельный flex-item на уровне .sidebar-item
   (сосед .sidebar-meta), а не часть текста внутри него: название игры может
   перенестись на 1 или 2 строки, и если бейджи сидят в потоке под названием,
   их вертикальная позиция от этого гуляет по всему списку. Вынесенные в
   свою колонку и выровненные по центру строки, они остаются на одной
   линии/столбце независимо от длины названия. */
.sidebar-side {
  flex-shrink: 0; display: flex; flex-direction: column; align-items: flex-end; gap: 4px;
  /* Фиксированная ширина, а не auto по содержимому — иначе строка без
     значка физического издания (уже её просто нет) была бы у́же и год
     съезжал бы левее относительно строк, где значок есть. */
  min-width: 40px;
}
.sidebar-badges { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.sidebar-year-badge {
  flex-shrink: 0; font-size: 9px; line-height: 1.5; padding: 0 5px;
  border-radius: 3px; background: var(--row-hover); border: 1px solid var(--border);
  color: var(--text-dim);
}
.physical-edition-badge { flex-shrink: 0; font-size: 11px; line-height: 1; }
.physical-edition-badge.placeholder { visibility: hidden; }
.sidebar-item.hidden-flagged .sidebar-name { color: var(--locked); }
.sidebar-hide-btn {
  background: none; border: none; color: var(--text-dim); cursor: pointer; font-size: 13px;
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 20px;
  opacity: 0;
  transition: opacity 0.15s, background 0.15s;
}
.sidebar-item:hover .sidebar-hide-btn { background: var(--row-hover); border-radius: 3px; }
.sidebar-hide-btn:hover { opacity: 1; color: var(--text); }

/* Только для игр, заведённых вручную (RetroGame/SwitchGame — все, Game —
   is_manual). Слева от sidebar-hide-btn, тот же принцип невидимости. */
.sidebar-delete-btn {
  background: none; border: none; color: var(--text-dim); cursor: pointer; font-size: 13px;
  position: absolute; right: 28px; top: 50%; transform: translateY(-50%);
  width: 20px;
  opacity: 0;
  transition: opacity 0.15s, background 0.15s;
}
.sidebar-item:hover .sidebar-delete-btn { background: var(--row-hover); border-radius: 3px; }
.sidebar-delete-btn:hover { opacity: 1; color: #ff6b6b; }
.sidebar-empty { padding: 12px; font-size: 12px; color: var(--text-dim); }

.sidebar-footer { display: flex; gap: 6px; padding: 8px; border-top: 1px solid var(--border); }
.secondary-btn.small { padding: 6px 8px; font-size: 11px; flex: 1; }

.sync-progress { padding: 8px 10px; border-top: 1px solid var(--border); }
.sync-progress-label { font-size: 11px; color: var(--text-dim); margin-bottom: 6px; }
.sync-progress-bar { height: 6px; border-radius: 3px; background: var(--bg); overflow: hidden; margin-bottom: 6px; }
.sync-progress-fill { height: 100%; background: var(--green-bright); width: 0%; transition: width 0.3s; }

#game-select { display: none; width: 100%; margin-bottom: 10px; }

.covers-group { margin-bottom: 22px; }
.covers-group-title {
  font-size: 12px; letter-spacing: 1px; text-transform: uppercase;
  color: var(--text-dim); border-bottom: 1px solid var(--border);
  padding-bottom: 4px; margin: 0 0 10px;
}
.covers-group-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 14px;
  /* без этого Grid растягивает все карточки в ряду по высоте самой высокой
     (X360/XboxOne с шапкой над обложкой) — карточкам без такой шапки внизу
     оставался пустой зазор цвета фона */
  align-items: start;
}
.cover-tile {
  cursor: pointer;
  border-radius: 6px;
  overflow: hidden;
  position: relative;
  background: linear-gradient(145deg, var(--green) 0%, var(--accent-shade) 100%);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.1);
}
.cover-tile:hover { box-shadow: inset 0 0 0 2px var(--green-bright); }

/* X360/XboxOne шапки без альфа-канала — идут отдельным блоком НАД обложкой */
.cover-header-static { display: block; width: 100%; height: auto; cursor: pointer; }
.cover-header-static:hover { filter: brightness(1.1); }

.cover-art-wrap { position: relative; aspect-ratio: 2 / 3; overflow: hidden; }
/* DS/3DS — картриджи этих платформ квадратные (в отличие от портретных
   Xbox/Steam/PS2-обложек), под них меняем форму плитки в сетке. */
html[data-platform="ds"] .cover-art-wrap,
html[data-platform="3ds"] .cover-art-wrap {
  aspect-ratio: 1 / 1;
}
.cover-art-wrap .cover-art {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* многие старые обложки — квадратные Store-тайлы со служебной полосой у левого
     края (лого/название платформы); смещаем кроп вправо, чтобы её прятать */
  object-position: 75% center;
}

/* PS1/PS2/Xbox Original: обложка — 3D-рендер коробки на прозрачном фоне (см.
   app/boxart.py), а не прямоугольная картинка. Поэтому у плитки нет ни своих
   пропорций, ни подложки: любая рамка вокруг такого рендера читается как
   серый прямоугольник позади коробки. Высоту задаёт сама картинка, фон/
   обводка плитки убраны, обратная связь на наведение — подсветка самой
   коробки. */
html[data-platform="ps1"] .cover-tile,
html[data-platform="ps2"] .cover-tile,
html[data-platform="xbox_og"] .cover-tile,
html[data-platform="gba"] .cover-tile,
html[data-platform="ps3"] .cover-tile {
  background: none;
  box-shadow: none;
  border-radius: 0;
  overflow: visible;
}
html[data-platform="ps1"] .cover-tile:hover,
html[data-platform="ps2"] .cover-tile:hover,
html[data-platform="xbox_og"] .cover-tile:hover,
html[data-platform="gba"] .cover-tile:hover,
html[data-platform="ps3"] .cover-tile:hover { box-shadow: none; }
html[data-platform="ps1"] .cover-art-wrap,
html[data-platform="ps2"] .cover-art-wrap,
html[data-platform="xbox_og"] .cover-art-wrap,
html[data-platform="gba"] .cover-art-wrap,
html[data-platform="ps3"] .cover-art-wrap { aspect-ratio: auto; overflow: visible; }
html[data-platform="ps1"] .cover-art-wrap .cover-art,
html[data-platform="ps2"] .cover-art-wrap .cover-art,
html[data-platform="xbox_og"] .cover-art-wrap .cover-art,
html[data-platform="gba"] .cover-art-wrap .cover-art,
html[data-platform="ps3"] .cover-art-wrap .cover-art {
  height: auto;
  object-fit: contain;
  object-position: center;
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.55));
}
html[data-platform="ps1"] .cover-tile:hover .cover-art,
html[data-platform="ps2"] .cover-tile:hover .cover-art,
html[data-platform="xbox_og"] .cover-tile:hover .cover-art,
html[data-platform="gba"] .cover-tile:hover .cover-art,
html[data-platform="ps3"] .cover-tile:hover .cover-art { filter: drop-shadow(0 4px 10px rgba(0,0,0,0.7)) brightness(1.12); }
/* Игра без найденной коробки — единственный случай, когда у такой плитки всё
   же есть прямоугольник: буква-заглушка должна на чём-то лежать. */
html[data-platform="ps1"] .cover-tile .cover-fallback,
html[data-platform="ps2"] .cover-tile .cover-fallback,
html[data-platform="xbox_og"] .cover-tile .cover-fallback,
html[data-platform="gba"] .cover-tile .cover-fallback,
html[data-platform="ps3"] .cover-tile .cover-fallback {
  height: auto; aspect-ratio: 2 / 3; border-radius: 6px;
  background: linear-gradient(145deg, var(--green) 0%, var(--accent-shade) 100%);
}
/* В сайдбаре 36px-иконка тоже коробка целиком: object-fit: cover срезал бы ей
   бока, а подложка под прозрачным PNG выглядела бы плашкой. */
html[data-platform="ps1"] img.sidebar-cover,
html[data-platform="ps2"] img.sidebar-cover,
html[data-platform="xbox_og"] img.sidebar-cover,
html[data-platform="gba"] img.sidebar-cover,
html[data-platform="ps3"] img.sidebar-cover { object-fit: contain; background: none; }
.cover-tile .cover-fallback {
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 32px; color: #0b1710;
}
.cover-tile.hidden-flagged { opacity: 0.4; }

.cover-edit-btn {
  position: absolute; right: 6px; bottom: 6px; z-index: 2;
  width: 24px; height: 24px; border-radius: 4px;
  background: rgba(11,23,16,0.75); border: 1px solid rgba(255,255,255,0.2); color: #fff;
  font-size: 12px; cursor: pointer;
  opacity: 0; transition: opacity 0.15s;
  display: flex; align-items: center; justify-content: center;
}
.cover-edit-btn span { display: inline-block; transform: scaleX(-1); }
.cover-edit-btn:hover { opacity: 1; background: var(--green-dark); border-color: var(--green); }

.cover-hide-btn {
  position: absolute; right: 34px; bottom: 6px; z-index: 2;
  width: 24px; height: 24px; border-radius: 4px;
  background: rgba(11,23,16,0.75); border: 1px solid rgba(255,255,255,0.2); color: #fff;
  font-size: 12px; cursor: pointer;
  opacity: 0; transition: opacity 0.15s;
  display: flex; align-items: center; justify-content: center;
}
.cover-hide-btn:hover { opacity: 1; background: var(--green-dark); border-color: var(--green); }

/* Только для вручную добавленных игр — левее cover-hide-btn. */
.cover-delete-btn {
  position: absolute; right: 62px; bottom: 6px; z-index: 2;
  width: 24px; height: 24px; border-radius: 4px;
  background: rgba(11,23,16,0.75); border: 1px solid rgba(255,255,255,0.2); color: #fff;
  font-size: 12px; cursor: pointer;
  opacity: 0; transition: opacity 0.15s;
  display: flex; align-items: center; justify-content: center;
}
.cover-delete-btn:hover { opacity: 1; background: #4a1414; border-color: #ff6b6b; color: #ff6b6b; }

.platform-menu {
  position: fixed; z-index: 150;
  background: var(--row-bg); border: 1px solid var(--border); border-radius: 6px;
  padding: 6px; display: flex; flex-direction: column; gap: 4px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.55);
  width: 200px;
}
.platform-menu-item {
  background: var(--bg); border: 1px solid transparent; border-radius: 4px;
  padding: 4px; cursor: pointer; display: block; width: 100%;
}
.platform-menu-item:hover { border-color: var(--green); }
.platform-menu-item.active { border-color: var(--green-bright); box-shadow: inset 0 0 0 1px var(--green-bright); }
.platform-menu-item img { width: 100%; height: auto; display: block; }
.platform-menu-label { display: block; font-size: 12px; color: var(--text); padding: 6px 4px; text-align: left; }

.platform-switcher-menu { width: 190px; max-height: 80vh; overflow-y: auto; }
.platform-switcher-item {
  display: flex !important; align-items: center; gap: 10px; padding: 7px !important;
}
/* Логотипы — свои картинки пользователя произвольного вида (тёмные/прозрачные
   логотипы на тёмном фоне меню сливались бы независимо от размера) — светлая
   карточка-подложка под иконкой даёт контраст любому логотипу, plus contain
   не обрезает широкие/нестандартных пропорций картинки. */
.platform-switcher-item img {
  width: 32px !important; height: 32px !important; object-fit: contain;
  background: #f2f2f0; border-radius: 6px; padding: 3px; flex-shrink: 0;
}
/* Раньше инвертировался чёрный глиф под тёмный фон меню — на светлой
   карточке-подложке чёрный глиф и так читается, инверсия сделала бы его
   белым-на-белом. */
.platform-switcher-item img.steam-icon { filter: none; }
.platform-switcher-item .platform-menu-label { padding: 0; font-weight: 600; font-size: 13px; }

/* Series X шапка — с альфа-каналом, накладывается прямо на арт */
.cover-header-zone {
  position: absolute; top: 0; left: 0; width: 100%; min-height: 16px;
  cursor: pointer; z-index: 1;
}
.cover-header-zone:hover { background: rgba(255,255,255,0.08); }
.cover-header {
  width: 100%; height: auto; display: block;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,0.6));
}
.cover-tile-info {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 22px 8px 7px;
  background: linear-gradient(0deg, rgba(0,0,0,0.92) 0%, rgba(0,0,0,0.55) 55%, rgba(0,0,0,0) 100%);
  opacity: 0;
  transition: opacity 0.15s;
}
.cover-tile:hover .cover-tile-info { opacity: 1; }
.cover-tile-name { font-size: 12px; font-weight: 700; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,0.8); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cover-tile-progress { font-size: 10px; color: var(--green-bright); text-shadow: 0 1px 2px rgba(0,0,0,0.8); }

.toolbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 12px; }
#search { flex: 1; min-width: 140px; }
.filters { display: flex; gap: 4px; }
.filter-btn {
  background: var(--row-bg); border: 1px solid var(--border); color: var(--text-dim);
  padding: 7px 10px; border-radius: 4px; font-size: 12px; cursor: pointer;
}
.filter-btn.active { background: var(--green-dark); color: var(--green-bright); border-color: var(--green); }

.game-summary {
  font-size: 12px; color: var(--text-dim); margin: 4px 0 14px;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.game-summary .secondary-btn.small { flex: 0 0 auto; }
.game-summary b { color: var(--green-bright); }

.group-title {
  font-size: 12px; letter-spacing: 1px; text-transform: uppercase;
  color: var(--text-dim); border-bottom: 1px solid var(--border);
  padding-bottom: 4px; margin: 18px 0 6px;
}
.group-title.rare-title { color: var(--rare-gold); border-color: #4a3f1e; }
.group-title.platinum-title { color: #cfe0f0; border-color: #445a70; }
#list-platinum-group { margin-bottom: 22px; padding-bottom: 4px; border-bottom: 1px solid var(--border); }
#list-platinum-group .ach-row { background: rgba(207, 224, 240, 0.06); }
#list-platinum-group .ach-row:nth-child(odd), #list-platinum-group .ach-row:nth-child(even) { background: rgba(207, 224, 240, 0.06); }

.ach-list { display: flex; flex-direction: column; }

/* Заполняет пустующую у retro-платформ панель ачивментов справкой из
   Википедии и гайдом из локального архива GameFAQs (см. loadRetroInfoPanel
   в app.js). Видимость переключается там же классом .hidden, а не через
   .retro-platform в CSS, чтобы Switch 2 (retro, но без архива) её не видел. */
.retro-info-panel { display: flex; flex-direction: column; gap: 18px; margin-top: 6px; }
.retro-block-title {
  font-size: 12px; letter-spacing: 1px; text-transform: uppercase;
  color: var(--text-dim); border-bottom: 1px solid var(--border);
  padding-bottom: 4px; margin: 0 0 8px;
}
.retro-wiki-text { font-size: 13px; line-height: 1.6; color: var(--text); margin: 0 0 8px; }
.retro-wiki-link { font-size: 12px; color: var(--green-bright); text-decoration: none; }
.retro-wiki-link:hover { text-decoration: underline; }

.retro-block-title { display: flex; align-items: center; gap: 8px; }
.wiki-refind-btn { width: 20px; height: 20px; font-size: 11px; opacity: 0.7; text-transform: none; letter-spacing: normal; border-bottom: none; }
.wiki-refind-btn:hover { opacity: 1; }

/* Панель метаданных IGDB — общая для всех платформ (в отличие от блока выше,
   который живёт только у ретро-полки), поэтому переиспользует его типографику
   вместо собственной: визуально это тот же блок «Об игре». */
.igdb-panel { margin-top: 18px; }

.retro-ra-panel { display: flex; align-items: center; gap: 8px; margin-top: 14px; }
.retro-ra-panel .hint { flex: 1; margin: 0; }
.retro-stratege-link {
  flex: 0 0 auto;
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  background: var(--row-bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 14px;
  text-decoration: none;
  opacity: 0.85;
}
.retro-stratege-link:hover { background: var(--row-hover); opacity: 1; }
.igdb-body { display: flex; gap: 12px; align-items: flex-start; }
.igdb-cover { width: 68px; flex: 0 0 auto; border-radius: 3px; border: 1px solid var(--border); }
.igdb-text { min-width: 0; }
.igdb-facts { font-size: 12px; color: var(--text-dim); line-height: 1.7; margin: 0 0 8px; }
.igdb-facts b { color: var(--text); font-weight: 600; }

.retro-guide-buttons { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.retro-guide-row { display: flex; align-items: stretch; gap: 4px; }
.retro-guide-btn { flex: 1; min-width: 0; text-align: left; white-space: normal; }
.retro-guide-hide-btn { flex: 0 0 auto; width: 28px; opacity: 0.55; font-size: 12px; }
.retro-guide-hide-btn:hover { opacity: 1; color: #e06060; }
.retro-guide-refind { align-self: flex-start; opacity: 0.75; }

/* Полноэкранное чтение гайда (не миниатюрное окошко в панели) — ASCII-гайды
   GameFAQs рассчитаны на моноширинный шрифт и бывают по 500КБ+, читать их
   в узкой колонке неудобно. Секция переключается через show() как
   статистика/бэклог. Текст рисуется построчно (не единым <pre>), чтобы у
   каждой строки был номер-гутер для закладок (см. app.js: renderGuideLines). */
/* Гайды бывают длинными — без sticky кнопка "назад" уезжала за пределы
   экрана вместе со шкалой прокрутки, и вернуться к игре можно было только
   проскроллив обратно наверх. */
/* top: 0 здесь коллидирует с .topbar — та тоже sticky top:0 (54px высотой,
   см. .topbar) и лежит выше по z-index, так что при top:0 эта плашка не
   "плыла бы поверх текста", а безобидно пряталась ЗА топбаром сразу после
   первого пикселя скролла — выглядело как "кнопка назад вообще не липнет". */
#guide-reader .backlog-header {
  position: sticky; top: 54px; z-index: 5;
  background: var(--bg); padding: 12px 0; margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
}

.guide-reader-body { display: flex; align-items: flex-start; gap: 20px; margin-top: 16px; }
#guide-reader-text {
  flex: 1; min-width: 0; margin: 0 auto; padding: 20px 24px; max-width: 900px;
  background: var(--row-bg); border: 1px solid var(--border); border-radius: 8px;
  font-family: "Consolas", "Courier New", monospace; font-size: 14px; line-height: 1.6;
  color: var(--text); overflow-x: auto;
}
.guide-line { display: flex; align-items: flex-start; border-radius: 3px; }
.guide-line-num {
  flex: 0 0 auto; width: 44px; margin-right: 12px; padding-right: 6px;
  text-align: right; border-right: 1px solid var(--border);
  color: var(--text-dim); opacity: 0.55; font-size: 12px; user-select: none; cursor: pointer;
}
.guide-line-num:hover { opacity: 1; color: var(--green-bright); }
.guide-line-text { flex: 1; min-width: 0; white-space: pre-wrap; word-break: break-word; }
.guide-line.bookmarked { background: var(--green-dark); }
.guide-line.bookmarked .guide-line-num { opacity: 1; color: var(--rare-gold); font-weight: bold; }
.guide-line.flash { animation: guide-line-flash 1.4s ease; }
@keyframes guide-line-flash { 0%, 100% { background: transparent; } 25% { background: var(--row-hover); } }

/* top — под topbar (54px) И под самим sticky-заголовком гайда (у него
   own top:54px + собственная высота ~57px, см. #guide-reader .backlog-header
   выше), иначе закладки на скролле заезжали бы под заголовок. */
.guide-bookmarks-panel { flex: 0 0 240px; position: sticky; top: 116px; align-self: flex-start; }
.guide-bookmarks-list { display: flex; flex-direction: column; gap: 6px; max-height: 70vh; overflow-y: auto; margin-bottom: 8px; }
.guide-bookmark-item {
  display: flex; align-items: center; gap: 6px; cursor: pointer;
  background: var(--row-bg); border: 1px solid var(--border); border-radius: 4px;
  padding: 6px 8px; font-size: 12px;
}
.guide-bookmark-item:hover { border-color: var(--green); background: var(--row-hover); }
.guide-bookmark-line-no { flex: 0 0 auto; color: var(--rare-gold); font-weight: bold; }
.guide-bookmark-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-dim); }
.guide-bookmark-remove { flex: 0 0 auto; opacity: 0.5; }
.guide-bookmark-remove:hover { opacity: 1; color: #e06060; }

@media (max-width: 900px) {
  .guide-reader-body { flex-direction: column; }
  .guide-bookmarks-panel { position: static; width: 100%; }
}

.guide-search-all-label { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-dim); margin-top: 8px; cursor: pointer; }
.guide-search-results { display: flex; flex-direction: column; gap: 4px; max-height: 360px; overflow-y: auto; margin-top: 10px; }
.guide-search-result-item {
  text-align: left; padding: 8px 10px; border-radius: 4px; border: 1px solid transparent;
  background: var(--row-bg); color: var(--text); cursor: pointer; font-size: 13px;
  text-transform: capitalize;
}
.guide-search-result-item:hover { border-color: var(--green); background: var(--row-hover); }

.ach-row {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 8px; border-radius: 3px; cursor: pointer;
  border-bottom: 1px solid rgba(255,255,255,0.03);
}
.ach-row:nth-child(odd) { background: var(--row-bg); }
.ach-row:nth-child(even) { background: var(--row-bg-alt); }
.ach-row:hover { background: var(--row-hover); }
.ach-row.hidden-item { display: none; }

.ach-icon {
  width: 34px; height: 34px; border-radius: 3px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(145deg, var(--green) 0%, var(--accent-shade) 100%);
  color: #0b1710; font-weight: 800; font-size: 14px;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.15);
  overflow: hidden;
}
.ach-icon img { width: 100%; height: 100%; object-fit: cover; }
.ach-row.locked .ach-icon {
  background: linear-gradient(145deg, #2a3a2c 0%, #17231a 100%);
  color: var(--locked);
}
.ach-row.locked .ach-icon img { filter: grayscale(1) brightness(0.55); }

.ach-main { flex: 1; min-width: 0; }
.ach-name { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ach-row.locked .ach-name { color: var(--locked); }
.ach-desc { font-size: 11px; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ach-row.expanded .ach-name, .ach-row.expanded .ach-desc { white-space: normal; }
.ach-secret-badge { font-size: 10px; margin-right: 4px; opacity: 0.75; }
.ach-desc-spoiler { cursor: pointer; font-style: italic; text-decoration: underline dotted; text-underline-offset: 2px; }
.ach-desc-spoiler:hover { color: var(--text); }

.ach-score { font-size: 12px; color: var(--green-bright); font-weight: 700; width: 44px; text-align: right; flex-shrink: 0; }
.ach-row.locked .ach-score { color: var(--locked); }

.ach-rarity { font-size: 10px; width: 54px; text-align: right; color: var(--text-dim); flex-shrink: 0; }
.ach-rarity.rare { color: var(--rare-gold); }

.ach-date { font-size: 10px; color: var(--text-dim); width: 78px; text-align: right; flex-shrink: 0; }

/* Вставить ачивмент в запись журнала — та же логика hover-reveal, что и у
   sidebar-hide-btn/backlog-entry-remove по всему приложению. */
.ach-journal-insert-btn {
  background: none; border: 1px solid var(--border); border-radius: 4px; color: var(--text-dim);
  cursor: pointer; font-size: 13px; width: 26px; height: 26px; flex-shrink: 0;
  opacity: 0; transition: opacity 0.15s, color 0.15s, border-color 0.15s;
}
.ach-row:hover .ach-journal-insert-btn { opacity: 1; }
.ach-journal-insert-btn:hover { color: var(--green-bright); border-color: var(--green-bright); }

.modal-overlay {
  position: fixed; inset: 0; background: rgba(0,0,0,0.7);
  display: flex; align-items: center; justify-content: center; z-index: 100;
}
.modal {
  background: var(--bg-panel); border: 1px solid var(--border); border-radius: 8px;
  padding: 18px; width: 320px; max-width: calc(100vw - 32px);
}
.modal h2 { margin: 0 0 12px; font-size: 15px; }
.modal.modal-wide { width: 640px; }

.sgdb-search-form { display: flex; gap: 8px; margin-top: 4px; }
.sgdb-search-form input { flex: 1; }

.cover-editor-name-form { display: flex; gap: 8px; margin: 4px 0 10px; }
.cover-editor-name-form input { flex: 1; }

.sgdb-search-results {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 8px; max-height: 60vh; overflow-y: auto; margin: 10px 0;
}
.sgdb-search-result {
  aspect-ratio: 2 / 3; border-radius: 6px; overflow: hidden; cursor: pointer;
  border: 2px solid transparent; background: var(--row-bg); position: relative;
}
/* PS1/DS/3DS — квадратные коробки/картриджи, см. .cover-art-wrap выше. */
.sgdb-search-results.square-cover .sgdb-search-result { aspect-ratio: 1 / 1; }
.sgdb-search-result:hover { border-color: var(--green); }
.sgdb-search-result img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sgdb-search-result.selecting::after {
  content: "..."; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: rgba(11,23,16,0.75); color: var(--green-bright); font-size: 20px; font-weight: 800;
}
.sgdb-search-result.selected { border-color: var(--green-bright); }
.sgdb-search-result.selected::before {
  content: "✓"; position: absolute; top: 4px; right: 4px; z-index: 2;
  background: var(--green-bright); color: #06120a; width: 18px; height: 18px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 800;
}
/* Выбор коробки из локального архива 3D-рендеров — те же прозрачные рендеры,
   что и в сетке: кроп резал бы их по бокам, а подложка плитки читалась бы как
   серый прямоугольник позади коробки (см. html[data-platform="ps1"]
   .cover-tile выше). */
#boxart-search-results .sgdb-search-result { background: none; }
#boxart-search-results .sgdb-search-result img { object-fit: contain; }
/* Тот же архив коробок, но результаты показаны в окне добавления игры
   (см. runRetroAddSearch в app.js) — та же причина: cover не подходит
   прозрачным рендерам произвольного соотношения сторон. */
#retro-add-results.boxart-source .sgdb-search-result { background: none; }
#retro-add-results.boxart-source .sgdb-search-result img { object-fit: contain; }

.cover-editor-frame {
  position: relative; width: 100%; aspect-ratio: 2 / 3;
  overflow: hidden; border-radius: 6px; background: var(--row-bg);
  cursor: grab; touch-action: none; user-select: none;
}
.cover-editor-frame.square-cover { aspect-ratio: 1 / 1; }
.cover-editor-frame.dragging { cursor: grabbing; }
.cover-editor-frame img {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%;
  object-fit: cover; pointer-events: none;
}
/* Превью в редакторе должно показывать ровно то, что окажется в сетке, а там
   у PS1 коробка целиком без подложки. */
html[data-platform="ps1"] .cover-editor-frame,
html[data-platform="gba"] .cover-editor-frame,
html[data-platform="ps3"] .cover-editor-frame { background: none; }
html[data-platform="ps1"] .cover-editor-frame img,
html[data-platform="gba"] .cover-editor-frame img,
html[data-platform="ps3"] .cover-editor-frame img { object-fit: contain; }
#cover-editor-zoom { width: 100%; margin: 10px 0; }
.modal-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.modal-actions .secondary-btn.small { flex: 1 1 auto; text-align: center; }
.file-btn { display: flex; align-items: center; justify-content: center; }

/* ---------- Глобальный поиск — командная палитра: широкая чистая строка ввода
   без заголовков/кнопок, результаты выезжают под ней. Прижата к верху экрана
   (не по центру), как Spotlight/командные палитры в IDE. ---------- */
.search-overlay { align-items: flex-start; padding-top: 12vh; backdrop-filter: blur(2px); }
.search-modal {
  width: 640px; max-width: calc(100vw - 32px);
  background: var(--bg-panel); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
  overflow: hidden;
}
.search-modal-input {
  width: 100%; border: none; border-radius: 0; background: transparent;
  color: var(--text); padding: 18px 20px; font-size: 17px; outline: none;
}
.search-modal-input::placeholder { color: var(--text-dim); }
.global-search-results:not(:empty) { border-top: 1px solid var(--border); padding: 8px; max-height: 60vh; overflow-y: auto; }
.search-result-group + .search-result-group { margin-top: 14px; }
.search-result-group-title {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-dim); margin: 8px 0 6px; padding: 0 6px;
}
.search-result-group:first-child .search-result-group-title { margin-top: 4px; }
.search-result-item {
  display: flex; align-items: center; gap: 10px; padding: 9px 10px;
  border-radius: 8px; cursor: pointer; border: 1px solid transparent;
}
.search-result-item:hover, .search-result-item.active { background: var(--row-bg); border-color: var(--border); }
.search-result-platform-icon { width: 20px; height: 20px; border-radius: 4px; object-fit: cover; flex: none; }
.search-result-main { min-width: 0; flex: 1; }
.search-result-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-result-title mark, .search-result-sub mark {
  background: var(--green-dark); color: var(--green-bright); border-radius: 2px;
}
.search-result-sub {
  font-size: 12px; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; margin-top: 2px;
}
.search-result-item.dimmed { opacity: 0.55; }
.search-result-hidden-tag { font-size: 10px; color: var(--text-dim); border: 1px solid var(--border); border-radius: 3px; padding: 1px 4px; flex: none; }
.search-result-empty { padding: 10px 8px; color: var(--text-dim); font-size: 13px; }
/* Буквенный фоллбэк для ачивмента без иконки (легаси Xbox 360, см. память проекта) */
.search-result-icon-fallback {
  width: 20px; height: 20px; border-radius: 4px; flex: none;
  background: var(--row-bg-alt); color: var(--text-dim);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
}
/* Микрообложка игры в результате поиска (и в игровом, и в журнальном) —
   портретные пропорции (в отличие от квадратных .search-result-platform-icon
   у ачивментов). Размер — как у карточки сессии в ленте статистики
   (.feed-session-cover), для единого визуального языка по всему приложению. */
.search-result-cover-thumb { width: 38px; height: 51px; border-radius: 4px; object-fit: cover; flex: none; }
.search-result-cover-letter {
  background: var(--row-bg-alt); color: var(--text-dim);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
}

/* Обложка + микро-бейдж платформы + (если есть двойник на другой платформе,
   см. dedupe_games в app/search.py) кнопка смены платформы по наведению. */
.search-result-cover-wrap { position: relative; flex: none; }
.search-result-platform-badge {
  position: absolute; right: -2px; bottom: -2px; width: 13px; height: 13px;
  border-radius: 50%; background: var(--bg); padding: 0; box-shadow: 0 0 0 1px var(--bg);
  object-fit: cover; pointer-events: none;
}
/* Steam-иконка — чёрный круг с белым лого прямо в самой картинке (не залитый
   квадрат) — на тёмном фоне приложения белые линии лого сливаются с фоном.
   Белая подложка только под этим конкретным значком, у остальных платформ
   фон остаётся как обычно (см. .search-result-platform-badge выше). padding
   у базового класса — 0 (не 1px): сама картинка уже нарисована кругом край
   в край, лишний внутренний отступ только увеличивал видимую белую/фоновую
   кайму вокруг значка, не добавляя ничего к самой иконке. */
.search-result-platform-badge-white-bg { background: #fff; box-shadow: 0 0 0 1px #fff; }
/* Текстовый бейдж платформы после названия+года в строке результата —
   основной способ считать платформу на глаз (см. .search-result-platform-tag
   ниже); значок на обложке остаётся маленьким и вторичным, чтобы не закрывать
   собой саму обложку. */
.search-result-platform-tag {
  /* display:inline-block + свои height/line-height — бейдж сам себе задаёт
     высоту, а не наследует line-height окружающего текста. Родитель
     (.search-result-title) обрезает переполнение (overflow:hidden для
     многоточия у длинных названий), и без своей высоты нижняя граница
     бейджа частично попадала под обрезку. */
  display: inline-block; box-sizing: border-box;
  font-size: 9px; font-weight: 600; letter-spacing: 0.2px; text-transform: uppercase;
  color: var(--text-dim); border: 1px solid var(--border); border-radius: 3px;
  padding: 0 4px; height: 14px; line-height: 12px; margin-left: 6px; flex: none; vertical-align: middle;
}
.search-result-swap-btn {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.6); color: var(--text); border: none; border-radius: 3px;
  font-size: 11px; line-height: 1; cursor: pointer; padding: 0;
  opacity: 0; transition: opacity 0.12s;
}
.search-result-cover-wrap:hover .search-result-swap-btn { opacity: 1; }

.cover-playtime-badge {
  position: absolute; left: 6px; top: 6px; z-index: 2;
  background: rgba(11,23,16,0.75); border: 1px solid rgba(255,255,255,0.2); color: #fff;
  font-size: 10px; padding: 2px 6px; border-radius: 4px;
}
.cover-playtime-badge-small {
  font-size: 8px; padding: 1px 4px; border-radius: 3px;
}
.cover-physical-badge {
  position: absolute; right: 6px; top: 6px; z-index: 2;
  font-size: 10px;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.8));
}

#physical-toggle-btn.active { background: var(--green-dark); color: var(--green-bright); border-color: var(--green); }

/* ---------- Backlog ---------- */

/* Единая высота/скругление для всех кнопок-переключателей внутри бэклога
   (шапка, вкладки категорий, тулбар над списком) — раньше высота "плавала"
   между 28/30/32px с разным border-radius, из-за чего ряд кнопок выглядел
   вразнобой. Здесь всё сведено к одной сетке: 32px высота, radius 6px. */
#backlog .icon-btn { width: 32px; height: 32px; border-radius: 6px; font-size: 15px; }
#backlog .secondary-btn.small {
  height: 32px; display: inline-flex; align-items: center; justify-content: center;
  padding: 0 12px; border-radius: 6px; font-size: 12px;
}

.backlog-header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.backlog-header h2 { margin: 0 auto 0 4px; }
.backlog-header .secondary-btn.small { flex: none; }

.backlog-categories { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.backlog-category-tab {
  background: var(--row-bg); border: 1px solid var(--border); color: var(--text-dim);
  height: 32px; padding: 0 14px; border-radius: 16px; font-size: 12px; font-weight: 600; cursor: pointer;
}
.backlog-category-tab:hover { border-color: var(--green); color: var(--text); }
.backlog-category-tab.active { background: var(--green-dark); color: var(--green-bright); border-color: var(--green); }

.backlog-category-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--border);
}
.backlog-category-toolbar span { font-size: 14px; font-weight: 700; }
.backlog-category-toolbar-actions { display: flex; gap: 6px; align-items: center; }

.backlog-entries { display: flex; flex-direction: column; gap: 8px; }
.backlog-entry-row {
  display: flex; align-items: center; gap: 12px;
  background: var(--row-bg); border: 1px solid var(--border); border-radius: 6px;
  padding: 8px 10px; cursor: pointer;
}
.backlog-entry-row:hover { background: var(--row-hover); border-color: var(--green); }
.backlog-entry-row.dragging { opacity: 0.4; }
.backlog-entry-drag-handle {
  flex-shrink: 0; cursor: grab; color: var(--text-dim); font-size: 16px;
  padding: 4px 2px; user-select: none; align-self: stretch; display: flex; align-items: center;
}
.backlog-entry-drag-handle:hover { color: var(--green-bright); }
.backlog-entry-drag-handle:active { cursor: grabbing; }
.backlog-entry-cover {
  width: 96px; height: 144px; border-radius: 4px; object-fit: cover; flex-shrink: 0;
  background: linear-gradient(145deg, var(--green) 0%, var(--accent-shade) 100%);
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 28px; color: #0b1710;
}
/* PS1/DS/3DS в бэклоге могут стоять рядом с портретными обложками других
   платформ — поэтому квадрат тут переключается per-entry классом
   (isSquareCoverPlatform в app.js), а не через data-platform на <html>. */
.backlog-entry-cover-wrap.square-cover .backlog-entry-cover { height: 96px; }
/* PS1/PS2/Xbox Original — обложка тут тоже 3D-рендер коробки на прозрачном
   фоне (см. BOXART_PLATFORMS/html[data-platform=...] .cover-tile в основной
   сетке выше), а не прямоугольная картинка. Тот же зелёный градиент-подложка
   позади прозрачного PNG читался бы как плашка вокруг коробки, поэтому для
   такого элемента строки бэклога фон убираем и не обрезаем картинку. */
.backlog-entry-cover-wrap.boxart-cover .backlog-entry-cover {
  background: none;
  object-fit: contain;
  filter: drop-shadow(0 3px 6px rgba(0,0,0,0.55));
}
.backlog-entry-info { flex: 0 0 240px; min-width: 0; }
.backlog-entry-name { font-size: 14px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.backlog-entry-sub { font-size: 11px; color: var(--text-dim); margin: 2px 0 6px; }
.backlog-entry-recent {
  flex: 1 1 auto; min-width: 0; align-self: stretch;
  display: flex; align-items: center; align-content: center; gap: 4px; flex-wrap: wrap;
  border-left: 1px solid var(--border); padding-left: 14px;
}
.backlog-entry-recent:empty, .backlog-entry-recent:has(.backlog-recent-empty:only-child) { border-left: none; }
.backlog-recent-icon {
  width: 26px; height: 26px; border-radius: 3px; overflow: hidden; flex-shrink: 0;
  background: linear-gradient(145deg, var(--green) 0%, var(--accent-shade) 100%);
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 11px; color: #0b1710;
}
.backlog-recent-icon img { width: 100%; height: 100%; object-fit: cover; }
.backlog-recent-icon.locked {
  background: linear-gradient(145deg, #2a3a2c 0%, #17231a 100%); color: var(--locked);
}
.backlog-recent-icon.locked img { filter: grayscale(1) brightness(0.55); }
.backlog-recent-overflow { background: var(--bg); color: var(--text-dim); font-size: 10px; font-weight: 700; }
.backlog-recent-empty { font-size: 11px; color: var(--text-dim); }
.backlog-entry-journal-col {
  flex: 0 0 260px; min-width: 0; align-self: stretch;
  display: flex; flex-direction: column; justify-content: center; gap: 3px;
  border-left: 1px solid var(--border); padding-left: 14px;
}
.backlog-entry-journal-col:empty { display: none; }
.backlog-entry-journal-title {
  font-size: 10px; letter-spacing: 1px; text-transform: uppercase; color: var(--text-dim); margin-bottom: 2px;
}
.backlog-entry-journal-col .backlog-entry-note { margin: 0; cursor: default; }

.backlog-entry-remove {
  background: none; border: none; color: var(--text-dim); cursor: pointer; font-size: 14px; flex-shrink: 0;
  opacity: 0; transition: opacity 0.15s; width: 24px; height: 24px;
}
.backlog-entry-row:hover .backlog-entry-remove { opacity: 1; }
.backlog-entry-remove:hover { color: #ff6b6b; }

.backlog-detail-header { display: flex; gap: 16px; margin: 12px 0 16px; }
.backlog-detail-cover {
  width: 140px; height: 187px; border-radius: 6px; flex-shrink: 0;
  background: linear-gradient(145deg, var(--green) 0%, var(--accent-shade) 100%);
  overflow: hidden;
}
.backlog-detail-cover.square-cover { height: 140px; }
/* См. .backlog-entry-cover-wrap.boxart-cover выше — тот же прозрачный
   3D-рендер коробки, та же причина убрать подложку и кроп. */
.backlog-detail-cover.boxart-cover { background: none; }
.backlog-detail-cover.boxart-cover .backlog-detail-cover-img {
  object-fit: contain;
  filter: drop-shadow(0 3px 6px rgba(0,0,0,0.55));
}
.backlog-detail-cover-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.backlog-detail-cover-letter {
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
  font-size: 48px; font-weight: 700; color: rgba(255, 255, 255, 0.85);
}
.backlog-detail-meta { display: flex; flex-direction: column; justify-content: center; gap: 6px; }
.backlog-detail-meta h2 { margin: 0; font-size: 20px; }
.backlog-detail-progress { font-size: 13px; color: var(--green-bright); }
.hltb-link { font-size: 12px; color: var(--green-bright); text-decoration: none; }
.hltb-link:hover { text-decoration: underline; }

.backlog-move-category-label {
  display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--text-dim);
}
.backlog-move-category-select {
  background: var(--row-bg); border: 1px solid var(--border); color: var(--text);
  padding: 5px 8px; border-radius: 6px; font-size: 12px; font-weight: 600; cursor: pointer;
}
.backlog-move-category-select:hover { border-color: var(--green); }

/* PDF-гайд — небольшая, но заметная золотистая плашка (выделяется на фоне
   обычных серых secondary-btn, чтобы бросаться в глаза среди прочих кнопок). */
.backlog-guide-pdf { display: flex; align-items: center; gap: 6px; }
.guide-pdf-btn {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600;
  padding: 6px 10px; border-radius: 5px; cursor: pointer; border: 1px solid var(--rare-gold);
  color: var(--rare-gold); background: rgba(232, 195, 74, 0.1); transition: background 0.15s;
  white-space: nowrap;
}
.guide-pdf-btn:hover { background: rgba(232, 195, 74, 0.2); }
.guide-pdf-remove {
  width: 22px; height: 22px; flex-shrink: 0; border-radius: 4px; border: 1px solid var(--border);
  background: none; color: var(--text-dim); cursor: pointer; font-size: 12px;
}
.guide-pdf-remove:hover { color: #ff6b6b; border-color: #ff6b6b; }

.backlog-detail-fields { display: flex; gap: 16px; margin-bottom: 14px; flex-wrap: wrap; }
.backlog-detail-fields label {
  display: flex; flex-direction: column; gap: 4px; font-size: 11px; color: var(--text-dim);
}
.backlog-detail-fields input {
  background: var(--row-bg); border: 1px solid var(--border); color: var(--text);
  padding: 7px 9px; border-radius: 4px; font-size: 13px; width: 120px;
}

.backlog-notes-label { display: flex; flex-direction: column; gap: 4px; font-size: 11px; color: var(--text-dim); margin-bottom: 16px; }
.backlog-notes-label textarea {
  background: var(--row-bg); border: 1px solid var(--border); color: var(--text);
  padding: 8px 10px; border-radius: 4px; font-size: 13px; font-family: inherit; resize: vertical;
}

.backlog-journal { margin-bottom: 20px; }
.backlog-journal h3, .backlog-detail-view h3 {
  font-size: 12px; letter-spacing: 1px; text-transform: uppercase;
  color: var(--text-dim); border-bottom: 1px solid var(--border);
  padding-bottom: 4px; margin: 0 0 10px;
}
.backlog-journal-form { margin-bottom: 14px; }
.backlog-journal-form-row { display: flex; gap: 8px; margin-bottom: 8px; align-items: flex-start; }
#backlog-journal-date { background: var(--row-bg); border: 1px solid var(--border); color: var(--text); padding: 7px 9px; border-radius: 4px; font-size: 13px; flex-shrink: 0; }

/* Редактор записи — contenteditable вместо textarea: пишешь и сразу видишь
   итоговый результат (жирный/курсив/подчёркнутый текст, ссылки, чипы
   ачивментов) без отдельного блока превью под полем. */
.journal-editor-wrap { flex: 1; min-width: 0; }
.journal-editor-toolbar { display: flex; gap: 4px; margin-bottom: 6px; }
.journal-editor-btn {
  background: var(--row-bg); border: 1px solid var(--border); color: var(--text);
  width: 28px; height: 28px; border-radius: 4px; cursor: pointer; font-size: 13px;
}
.journal-editor-btn:hover { background: var(--row-hover); border-color: var(--green); }
#backlog-journal-editor {
  background: var(--row-bg); border: 1px solid var(--border); color: var(--text);
  padding: 7px 9px; border-radius: 4px; font-size: 13px; font-family: inherit;
  min-height: 120px; max-height: 320px; overflow-y: auto; line-height: 1.5;
}
#backlog-journal-editor:focus { outline: none; border-color: var(--green); }
#backlog-journal-editor:empty::before { content: attr(data-placeholder); color: var(--text-dim); }
#backlog-journal-editor .journal-ach-chip { cursor: default; }
.backlog-journal-form-actions { display: flex; justify-content: flex-end; gap: 8px; }
.backlog-journal-list { display: flex; flex-direction: column; gap: 6px; }
.backlog-journal-item {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  background: var(--row-bg); border: 1px solid var(--border); border-radius: 4px; padding: 8px 10px;
}
.backlog-journal-date { font-size: 11px; color: var(--text-dim); flex-shrink: 0; }
.backlog-journal-text { flex: 1; font-size: 13px; white-space: pre-wrap; }
.backlog-journal-actions { display: flex; gap: 6px; margin-left: auto; opacity: 0; transition: opacity 0.15s; }
.backlog-journal-item:hover .backlog-journal-actions { opacity: 1; }
.backlog-journal-edit, .backlog-journal-remove { background: none; border: none; color: var(--text-dim); cursor: pointer; font-size: 12px; }
.backlog-journal-edit:hover { color: var(--green-bright); }
.backlog-journal-remove:hover { color: #ff6b6b; }

/* Скриншоты — превью перед отправкой формы и уже прикреплённые к записи. */
.journal-screenshot-preview { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.journal-screenshot-preview:empty { margin-bottom: 0; }
.journal-screenshot-preview-tile { position: relative; width: 64px; height: 64px; border-radius: 4px; overflow: hidden; }
.journal-screenshot-preview-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.journal-screenshot-preview-tile button {
  position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 3px;
  background: rgba(0,0,0,0.7); border: none; color: #fff; cursor: pointer; font-size: 11px; line-height: 1;
}
.journal-screenshot-preview-tile button:hover { background: #ff6b6b; }
.journal-screenshots { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 4px; }
.journal-screenshot-item { position: relative; width: 72px; height: 72px; }
.journal-screenshot-item[draggable="true"] { cursor: grab; }
.journal-screenshot-item[draggable="true"]:active { cursor: grabbing; }
.journal-screenshot-item.dragging { opacity: 0.4; }
.journal-screenshot-thumb {
  width: 72px; height: 72px; object-fit: cover; border-radius: 4px; cursor: pointer;
  border: 1px solid var(--border); transition: border-color 0.15s;
}
.journal-screenshot-thumb:hover { border-color: var(--green-bright); }
.journal-screenshot-remove {
  position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 3px;
  background: rgba(0,0,0,0.7); border: none; color: #fff; cursor: pointer; font-size: 11px; line-height: 1;
  opacity: 0; transition: opacity 0.15s;
}
.journal-screenshot-item:hover .journal-screenshot-remove { opacity: 1; }
.journal-screenshot-remove:hover { background: #ff6b6b; }

/* Ачивмент, вставленный в текст записи журнала (маркер [[ach:...]]) —
   инлайн-чип с иконкой прямо посреди текста. */
.journal-ach-chip {
  display: inline-flex; align-items: center; gap: 4px; vertical-align: middle;
  background: var(--green-dark); border: 1px solid var(--green); border-radius: 12px;
  padding: 1px 8px 1px 1px; font-size: 12px; font-weight: 600; color: var(--green-bright);
  margin: 0 1px;
}
.journal-ach-chip img { width: 18px; height: 18px; border-radius: 50%; object-fit: cover; }
/* Чип знает адрес своего ачивмента (см. journalAchPayloadEncoded) — курсор
   отмечает, что по нему можно перейти в библиотеку (см. navigateToAchievementFromChip). */
.journal-ach-chip-nav { cursor: pointer; }
.journal-ach-chip-nav:hover { filter: brightness(1.2); }
#backlog-journal-editor .journal-ach-chip-nav { cursor: default; filter: none; }

/* Компактная версия того же маркера — только текст, без картинки/рамки/паддинга.
   Используется там, где строка обрезается через text-overflow: ellipsis
   (мини-превью журнала в списке бэклога): inline-flex-чип с картинкой внутри
   такой строки ломает расчёт ellipsis — вместо аккуратной обрезки браузер
   схлопывает всю строку в одно "…". Тултип с полными данными — тот же самый
   (см. wireJournalAchChips). */
.journal-ach-mention { color: var(--green-bright); font-weight: 700; cursor: default; }

.cursor-tooltip-screenshot { width: 100%; max-width: 220px; border-radius: 4px; display: block; margin-bottom: 6px; }

.screenshot-lightbox-modal { width: auto; max-width: min(96vw, 1600px); padding: 12px; }
.screenshot-lightbox-modal img { display: block; max-width: 100%; max-height: 92vh; border-radius: 4px; margin: 0 auto; }

/* ---------- Лента активности журнала ---------- */
.backlog-feed-filters { display: flex; gap: 8px; margin-left: auto; }
.backlog-feed-filters select {
  background: var(--row-bg); border: 1px solid var(--border); color: var(--text);
  padding: 6px 8px; border-radius: 4px; font-size: 12px;
}
.backlog-feed-list { display: flex; flex-direction: column; gap: 4px; max-width: 640px; margin: 0 auto; }
.backlog-feed-date-header {
  font-size: 12px; font-weight: 700; letter-spacing: 0.3px; text-transform: capitalize;
  color: var(--green-bright); margin: 18px 0 8px; padding-bottom: 4px; border-bottom: 1px solid var(--border);
}
.backlog-feed-date-header:first-child { margin-top: 4px; }
.backlog-feed-day-group { display: flex; flex-direction: column; gap: 8px; }
.backlog-feed-card {
  display: flex; gap: 10px; background: var(--row-bg); border: 1px solid var(--border);
  border-radius: 6px; padding: 10px;
}
.backlog-feed-card-cover { width: 46px; height: 46px; border-radius: 4px; object-fit: cover; flex-shrink: 0; }
.backlog-feed-card-cover-letter {
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(145deg, var(--green) 0%, var(--accent-shade) 100%);
  font-weight: 800; font-size: 16px; color: #0b1710;
}
.backlog-feed-card-body { flex: 1; min-width: 0; }
.backlog-feed-card-game { font-size: 11px; font-weight: 700; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.3px; margin-bottom: 2px; }
.backlog-feed-card-text { font-size: 13px; white-space: pre-wrap; }

.backlog-entry-cover-wrap { position: relative; flex-shrink: 0; }
.backlog-platform-badge {
  position: absolute; right: -4px; bottom: -4px; width: 18px; height: 18px;
  border-radius: 50%; background: var(--bg); padding: 2px; box-shadow: 0 0 0 1px var(--border);
  object-fit: contain;
}
/* Тот же приём, что и золотистая кнопка гайда в детальной карточке — только
   компактный бэдж-кружок поверх обложки, чтобы не раздувать строку списка. */
.backlog-entry-guide-badge {
  position: absolute; left: -4px; top: -4px; width: 20px; height: 20px; z-index: 2;
  border-radius: 50%; background: var(--rare-gold); box-shadow: 0 0 0 2px var(--bg);
  border: none; color: #1a1400; cursor: pointer; font-size: 10px; line-height: 1;
  display: flex; align-items: center; justify-content: center; padding: 0;
}
.backlog-entry-guide-badge:hover { filter: brightness(1.15); }

.backlog-entry-name-row { display: flex; align-items: center; gap: 8px; }
.backlog-entry-name-row .backlog-entry-name { flex: 1; }
.backlog-hltb-icon-btn {
  width: 20px; height: 20px; flex-shrink: 0; color: var(--text-dim);
  display: flex; align-items: center; justify-content: center;
  opacity: 0; transition: opacity 0.15s, color 0.15s;
}
.backlog-hltb-icon-btn svg { width: 100%; height: 100%; }
.backlog-entry-row:hover .backlog-hltb-icon-btn { opacity: 1; }
.backlog-hltb-icon-btn:hover { color: var(--green-bright); }

.backlog-progress-wrap { display: flex; align-items: center; gap: 8px; margin: 4px 0; }
.backlog-progress-bar { flex: 1; max-width: 220px; height: 5px; border-radius: 3px; background: var(--bg); overflow: hidden; }
.backlog-progress-fill { height: 100%; background: var(--green-bright); transition: width 0.3s; }
.backlog-progress-fill.manual { background: var(--rare-gold); }
.backlog-progress-label { font-size: 10px; color: var(--text-dim); flex-shrink: 0; width: 32px; }

.backlog-entry-note {
  font-size: 11px; color: var(--text-dim); margin: 2px 0 6px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}
.backlog-entry-note-date { color: var(--green-bright); margin-right: 4px; }
.backlog-entry-note-text { color: var(--text); }

/* Динамика по количеству влезших записей (см. journalCol.dataset.count в
   app.js) — чем их меньше, тем больше места достаётся каждой под текст,
   вместо обрезки в одну строку с многоточием. */
.backlog-entry-journal-col[data-count="1"] .backlog-entry-note {
  white-space: normal; display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical; overflow: hidden;
}
.backlog-entry-journal-col[data-count="2"] .backlog-entry-note {
  white-space: normal; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.backlog-entry-journal-col[data-count="3"] .backlog-entry-note {
  white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

.cursor-tooltip {
  position: fixed; z-index: 300; pointer-events: none;
  background: var(--bg-panel); border: 1px solid var(--border); border-radius: 6px;
  padding: 10px; width: 240px; box-shadow: 0 8px 24px rgba(0,0,0,0.55);
}
.cursor-tooltip.hidden { display: none; }
.cursor-tooltip-header { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.cursor-tooltip-icon { width: 32px; height: 32px; border-radius: 3px; object-fit: cover; flex-shrink: 0; }
.cursor-tooltip-name { font-size: 13px; font-weight: 700; color: var(--text); }
.cursor-tooltip-desc { font-size: 11px; color: var(--text-dim); margin-bottom: 6px; line-height: 1.4; overflow-wrap: break-word; word-break: break-word; }
.cursor-tooltip-meta { display: flex; justify-content: space-between; font-size: 10px; color: var(--green-bright); }

/* HLTB display styles */
.backlog-detail-hltb-section { 
  margin: 12px 0; 
  padding: 10px;
  background: var(--row-bg);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.hltb-display { display: flex; flex-direction: column; gap: 10px; }
.hltb-times-header {
  font-size: 11px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-dim);
  font-weight: 600;
  margin-bottom: 4px;
}
.hltb-times { 
  display: flex; 
  gap: 20px; 
  flex-wrap: wrap; 
  padding: 8px 12px;
  background: var(--bg);
  border-radius: 4px;
}
.hltb-time { 
  font-size: 13px; 
  color: var(--text-dim); 
  display: flex;
  align-items: center;
  gap: 6px;
}
.hltb-time strong { 
  color: var(--green-bright); 
  font-weight: 700;
  font-size: 12px;
}
.hltb-time span { 
  color: var(--text);
  font-weight: 600;
  font-size: 14px;
}
.hltb-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.hltb-category-select {
  background: var(--row-bg); border: 1px solid var(--border); color: var(--text);
  padding: 6px 10px; border-radius: 4px; font-size: 12px;
  cursor: pointer;
}
.hltb-category-select:hover { border-color: var(--green); }
.hltb-empty { margin: 8px 0; }

/* HLTB search modal */
.hltb-search-results { max-height: 400px; overflow-y: auto; margin: 12px 0; }
.hltb-search-result {
  display: flex; align-items: center; gap: 12px; padding: 10px;
  background: var(--row-bg); border: 1px solid var(--border); border-radius: 6px;
  margin-bottom: 8px; transition: background 0.15s;
}
.hltb-search-result:hover { background: var(--row-hover); border-color: var(--green); }
.hltb-result-img {
  width: 60px; height: 80px; object-fit: cover; border-radius: 4px;
  background: var(--bg); flex-shrink: 0;
}
.hltb-result-info { flex: 1; min-width: 0; }
.hltb-result-name { font-size: 14px; font-weight: 600; margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hltb-result-meta { font-size: 11px; color: var(--text-dim); margin-bottom: 4px; }
.hltb-result-meta span { margin-right: 12px; }
.hltb-result-times { font-size: 11px; color: var(--green-bright); }
.hltb-result-times span { margin-right: 10px; }

/* HLTB badge in backlog list */
.backlog-entry-hltb-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  background: var(--green-dark);
  border: 1px solid var(--green);
  border-radius: 12px;
  font-size: 10px;
  color: var(--green-bright);
  font-weight: 600;
  margin-top: 4px;
}
.backlog-entry-hltb-badge svg {
  width: 12px;
  height: 12px;
}
.backlog-hltb-toggle { display: inline-flex; gap: 2px; margin-left: 4px; }
.hltb-cat-btn {
  border: 1px solid var(--green); background: transparent; color: var(--green-bright);
  border-radius: 8px; font-size: 9px; font-weight: 700; padding: 1px 5px; cursor: pointer; line-height: 1.4;
}
.hltb-cat-btn.active { background: var(--green-bright); color: var(--bg); }
.hltb-cat-btn:hover:not(.active) { background: var(--green-dark); }

@media (max-width: 640px) {
  main { padding: 10px; }
  /* Кнопок в шапке стало больше (библиотека, статистика, бэклог, настройки),
     и на узком экране они выдавливали её в горизонтальную прокрутку. */
  .topbar { gap: 6px; padding: 8px 10px; }
  .brand-text { display: none; }
  .profile { min-width: 0; gap: 5px; }
  .gamertag { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 90px; }
  .sidebar { display: none; }
  #game-select { display: block; }
  .ach-date, .ach-rarity { display: none; }
  .toolbar { flex-direction: column; align-items: stretch; }
  .backlog-detail-header { flex-direction: column; }
  .backlog-entry-row { flex-wrap: wrap; }
  .backlog-entry-journal-col {
    flex-basis: 100%; border-left: none; padding-left: 0;
    border-top: 1px solid var(--border); padding-top: 8px; margin-top: 6px;
  }
}

/* ---------- Резервная копия (блок в настройках) ---------- */
.backup-block {
  margin-top: 28px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}
.backup-actions {
  display: flex;
  gap: 8px;
  margin-top: 10px;
  flex-wrap: wrap;
}
/* Экспорт — обычная ссылка на эндпоинт (браузер сам качает файл), но выглядеть
   должна кнопкой, как остальные действия рядом. */
.backup-actions .secondary-btn.small {
  flex: 0 0 auto;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

/* ---------- Экран статистики ---------- */
.stats-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 10px;
  margin-bottom: 22px;
}
.stat-card {
  background: var(--row-bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 12px 14px;
  text-align: center;
  /* Карточки в одном ряду грида растягиваются на высоту самой высокой (см.
     "Ачивментов выбито" с её строками разбивки) — у коротких карточек
     (Gamerscore, Игры на 100%) без этого контент повисал у верхнего края. */
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.stat-value { font-size: 22px; font-weight: 800; color: var(--unlocked); line-height: 1.15; }
.stat-label { font-size: 12px; color: var(--text); margin-top: 4px; }
.stat-sub { font-size: 10px; color: var(--text-dim); margin-top: 2px; }

/* Разбивка по платформам внутри карточки (см. statPlatformBreakdownHtml/
   statPlatinumBreakdownHtml) — чипы "бейдж + число", а не отдельная строка
   текста на платформу. flex-wrap переносит лишние чипы на следующую строку
   сам, поэтому карточка не может "поехать" вширь и сломать сетку
   .stats-cards, даже если платформ окажется много. */
.stat-platform-breakdown { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 10px; margin-top: 8px; }
.stat-platform-chip {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 11px; font-weight: 600; color: var(--text-dim); font-variant-numeric: tabular-nums;
}
.stat-platform-chip-badge { width: 13px; height: 13px; border-radius: 50%; object-fit: contain; opacity: 0.9; flex-shrink: 0; }
/* Иконка платины (platinumtrophy.png) — рядом с бейджем платформы в чипе
   (см. statPlatinumBreakdownHtml/platinumTrophyIconHtml). */
.stat-trophy-icon { width: 13px; height: 13px; object-fit: contain; flex-shrink: 0; }

/* Чипы с кастомным cursor-tooltip (см. wireStatCardTooltips) — курсор-
   подсказка, что тут есть что навести, помимо самого содержимого. */
.stat-platinum-chip, .stat-playtime-chip, .stat-completed-chip { cursor: help; }
/* "Игры на 100%" — единственная карточка, где чип не одна из нескольких
   разбивок, а всё содержимое карточки, поэтому крупнее остальных чипов. */
.stat-completed-chip { font-size: 32px; font-weight: 800; color: var(--unlocked); gap: 8px; }
.stat-completed-chip .stat-platform-chip-badge { width: 26px; height: 26px; }

/* Разбивка "Ачивментов выбито" по платформам вместо одной суммы Xbox+Steam
   (см. achievementsCardHtml) — своя строка на платформу: бейдж, дробь,
   процент, прижатый к правому краю. */
.stat-ach-breakdown { display: flex; flex-direction: column; gap: 5px; margin-top: 6px; }
.stat-ach-row { display: flex; align-items: center; gap: 6px; }
.stat-ach-row-count { font-size: 17px; font-weight: 800; color: var(--unlocked); font-variant-numeric: tabular-nums; }
.stat-ach-row-pct { font-size: 11px; color: var(--text-dim); margin-left: auto; }

/* Мини-иконка игры внутри строки тултипа (платина/100%-пройденные, см.
   statTooltipGameRowHtml) — та же квадратная иконка, что и в сайдбаре
   библиотеки, просто мельче. recent-tooltip-row остаётся ровно с двумя
   прямыми детьми (имя-блок + дата) для justify-content: space-between —
   иконка и подпись игры сгруппированы внутри recent-tooltip-name. */
.recent-tooltip-name { display: flex; align-items: center; gap: 6px; min-width: 0; }
.recent-tooltip-icon { width: 20px; height: 20px; border-radius: 3px; object-fit: cover; flex-shrink: 0; }

.stats-section { margin-bottom: 26px; }
.stats-section h3 {
  font-size: 13px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--green-bright); margin: 0 0 10px;
}
.stats-section-header { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; }
.stats-section-header h3 { margin: 0; }
.stats-section-header .library-sort { width: auto; margin: 0; }

/* Заголовок секции, ведущий на её развёрнутую версию: выглядит как остальные
   заголовки, но подсвечивается и подчёркивается, чтобы было видно, что он
   кликабельный. */
.stats-section-link {
  padding: 0; border: 0; background: none; cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--green-bright);
}
.stats-section-link:hover { color: var(--text); text-decoration: underline; }

/* Тепловая карта: столбец — неделя, строка — день недели. На узком экране
   уезжает в горизонтальную прокрутку, а не ломает сетку. */
.heatmap-wrap { overflow-x: auto; padding-bottom: 4px; --heat-cell: 11px; --heat-gap: 2px; }
@media (max-width: 1180px) { .heatmap-wrap { --heat-cell: 12px; --heat-gap: 3px; } }
/* Каждый месяц — свой блок, и весь год по возможности укладывается в одну
   строку: так он читается как календарь, а не как две несвязанные половины.
   Ради этого клетка мельче (11px) и промежутки между месяцами узкие — год
   целиком занимает ~1050px. На экранах, где столько нет, сетка честно
   сворачивается в 6 / 4 / 3 колонки, а не уезжает в горизонтальную прокрутку.
   Число колонок фиксированное, а не flex-wrap "сколько влезет": при переносе
   по месту год разваливался на 11 + 1, и декабрь висел один во второй строке. */
.heatmap { display: grid; grid-template-columns: repeat(12, max-content); gap: 14px 12px; justify-content: center; }
@media (max-width: 1180px) { .heatmap { grid-template-columns: repeat(6, max-content); gap: 16px 20px; } }
@media (max-width: 820px)  { .heatmap { grid-template-columns: repeat(4, max-content); } }
@media (max-width: 620px)  { .heatmap { grid-template-columns: repeat(3, max-content); } }
@media (max-width: 460px)  { .heatmap { grid-template-columns: repeat(2, max-content); } }
/* Все блоки одной ширины (6 недель), даже если месяц укладывается в 5 —
   иначе колонки календаря съезжают друг относительно друга. */
.heatmap-month-block { flex: 0 0 auto; width: calc(6 * var(--heat-cell) + 5 * var(--heat-gap)); }
.heatmap-month-title {
  font-size: 10px; color: var(--text-dim); margin-bottom: 5px;
  text-transform: uppercase; letter-spacing: 0.06em;
}
.heatmap-grid { display: flex; gap: var(--heat-gap); }
.heatmap-col { display: flex; flex-direction: column; gap: var(--heat-gap); }
.heatmap-cell {
  width: var(--heat-cell); height: var(--heat-cell); border-radius: 2px; display: block;
  background: var(--row-bg); border: 1px solid var(--border);
}
.heatmap-cell.empty { background: transparent; border-color: transparent; }
.heatmap-cell[data-day] { cursor: pointer; }
/* День без ачивментов и без наигранного времени открывать нечем — курсор об
   этом и сообщает. has-playtime переопределяет это ниже: там кликать есть смысл. */
.heatmap-cell[data-count="0"] { cursor: default; }
.heatmap-cell[data-day]:hover { outline: 1px solid var(--green-bright); outline-offset: 1px; }
.heatmap-cell.level-1 { background: var(--green-dark); border-color: var(--green-dark); }
.heatmap-cell.level-2 { background: var(--accent-shade); border-color: var(--accent-shade); }
.heatmap-cell.level-3 { background: var(--green); border-color: var(--green); }
.heatmap-cell.level-4 { background: var(--unlocked); border-color: var(--unlocked); }
/* Играл в этот день, но ничего не выбил — точка янтарного цвета в углу
   пустой клетки (тот же акцент, что у карточки сессии в ленте), сама шкала
   заливки уровней остаётся только про ачивменты. */
.heatmap-cell.has-playtime {
  cursor: pointer;
  background: radial-gradient(circle at 65% 65%, var(--rare-gold) 0 22%, transparent 24%) var(--row-bg);
}
.heatmap-legend {
  display: flex; justify-content: flex-end; align-items: center;
  gap: 12px; margin-top: 8px; flex-wrap: wrap;
}
.heatmap-legend-scale { display: flex; align-items: center; gap: 3px; font-size: 10px; color: var(--text-dim); }

/* Список ачивментов за день внутри подсказки — она узкая по умолчанию,
   под перечень нужна пошире, а длинный день не должен уезжать за экран. */
.cursor-tooltip:has(.day-tooltip-list) { width: 320px; }
.day-tooltip-list { display: flex; flex-direction: column; gap: 8px; }

/* ---------- Календарь релизов ---------- */
/* Переключатель "Библиотека / Ожидаемые релизы" — тот же визуальный язык,
   что у .calendar-picker-month-btn, но горизонтальный ряд из двух вкладок. */
.calendar-mode-toolbar { display: flex; gap: 6px; margin-bottom: 12px; }
.calendar-mode-btn {
  flex: 1; background: var(--row-bg); border: 1px solid var(--border); border-radius: 6px;
  color: var(--text-dim); font-size: 12px; font-weight: 600; padding: 7px 10px; cursor: pointer;
  transition: border-color 0.12s, color 0.12s, background-color 0.12s;
}
.calendar-mode-btn:hover { border-color: var(--green); color: var(--text); }
.calendar-mode-btn.active { border-color: var(--green-bright); background: var(--row-hover); color: var(--text); }

.calendar-toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.calendar-month-label {
  flex: 1; text-align: center; background: none; border: none; color: var(--text);
  font-size: 15px; font-weight: 700; cursor: pointer; padding: 6px; border-radius: 4px;
}
.calendar-month-label:hover { background: var(--row-hover); }
.calendar-weekdays {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px;
  font-size: 11px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.04em;
  text-align: center; margin-bottom: 6px;
}
.calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.calendar-day {
  min-height: 98px; background: var(--row-bg); border: 1px solid var(--border);
  border-radius: 6px; padding: 5px; display: flex; flex-direction: column; gap: 5px;
}
.calendar-day.empty { background: transparent; border-color: transparent; }
.calendar-day.is-today { border-color: var(--green-bright); box-shadow: inset 0 0 0 1px var(--green-bright); }
.calendar-day-num { font-size: 11px; color: var(--text-dim); }
.calendar-day.is-today .calendar-day-num { color: var(--green-bright); font-weight: 700; }
/* Размер плиток — --tile-w/--tile-h (см. calendarTileDims в app.js), выставляются
   в JS на конкретную ячейку в зависимости от числа релизов в этот день. */
.calendar-day-games { display: flex; flex-wrap: wrap; gap: 4px; --tile-w: 84px; --tile-h: 112px; }
.calendar-game-tile {
  position: relative;
  width: var(--tile-w); height: var(--tile-h); border-radius: 4px; overflow: hidden; cursor: pointer;
  background: var(--row-bg-alt); flex: none;
}
.calendar-game-tile:hover { outline: 2px solid var(--green-bright); outline-offset: 1px; }
.calendar-game-tile.dimmed { opacity: 0.5; }
/* Игра на двух платформах сразу (см. item.twin) — маленькая кнопка смены
   версии в углу плитки, а не на весь её размер (плитки календаря мельче
   обложек результатов поиска, полный оверлей перекрывал бы половину дня). */
.calendar-tile-swap-btn {
  position: absolute; right: 2px; bottom: 2px; width: 16px; height: 16px; z-index: 1;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.7); color: #fff; border: none; border-radius: 50%;
  font-size: 10px; line-height: 1; cursor: pointer; padding: 0;
  opacity: 0; transition: opacity 0.12s;
}
.calendar-game-tile:hover .calendar-tile-swap-btn { opacity: 1; }
/* PS1/PS2/Xbox Original/... — та же логика, что у .backlog-entry-cover-wrap.
   boxart-cover: 3D-рендер коробки на прозрачном фоне, подложка плитки под ним
   читалась бы серой плашкой позади коробки. */
.calendar-game-tile.boxart-cover { background: none; border-radius: 0; }
.calendar-game-tile.boxart-cover img {
  object-fit: contain;
  filter: drop-shadow(0 3px 6px rgba(0,0,0,0.55));
}
.calendar-game-tile.boxart-cover:hover { outline: none; }
.calendar-game-tile.boxart-cover:hover img { filter: drop-shadow(0 3px 8px rgba(0,0,0,0.7)) brightness(1.1); }
/* 1-2 релиза в день — показываем обложку целиком (contain), а не обрезанным
   квадратом: места достаточно, плитка сама портретной формы под пропорции
   коробки. Много релизов — плитки маленькие квадраты, там contain оставил бы
   тонкую полоску от обложки, cover честнее показывает миниатюру. */
.calendar-game-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.calendar-game-tile.contain img { object-fit: contain; }
.calendar-game-fallback {
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; color: var(--text-dim); background: var(--row-bg-alt);
}
@media (max-width: 620px) {
  .calendar-day { min-height: 70px; }
  .calendar-day-games { --tile-w: 46px; --tile-h: 46px; }
}

/* Свой попап выбора месяца/года (см. openCalendarPicker в app.js) — тот же
   визуальный язык, что у .platform-menu (переключатель платформы в шапке). */
.calendar-picker-menu { width: 200px; padding: 10px; gap: 10px; }
.calendar-picker-year-row { display: flex; align-items: center; justify-content: space-between; }
/* <button>, а не <span> (кликабельна — открывает сетку годов), поэтому явно
   сбрасываем браузерный вид кнопки — иначе она заливается системным белым. */
.calendar-picker-year {
  background: none; border: 1px solid transparent; border-radius: 4px; color: var(--text);
  font-size: 14px; font-weight: 700; padding: 4px 10px; cursor: pointer;
  transition: background-color 0.12s, border-color 0.12s, transform 0.05s;
}
.calendar-picker-year:hover { background: var(--row-hover); border-color: var(--green); }
.calendar-picker-year:active { transform: scale(0.95); }
.calendar-picker-months { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.calendar-picker-month-btn {
  background: var(--bg); border: 1px solid transparent; border-radius: 4px; color: var(--text);
  font-size: 12px; padding: 8px 4px; cursor: pointer; transition: border-color 0.12s, transform 0.05s;
}
.calendar-picker-month-btn:hover { border-color: var(--green); }
.calendar-picker-month-btn:active { transform: scale(0.94); }
.calendar-picker-month-btn.active { border-color: var(--green-bright); background: var(--row-hover); font-weight: 700; }

/* ---------- Ожидаемые релизы (вкладка внутри календаря) ---------- */
.calendar-upcoming-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.calendar-upcoming-list { display: flex; flex-direction: column; gap: 8px; }
/* Разделитель месяца — липнет под топбаром (см. .topbar, top: 0, z-index: 10)
   при прокрутке ленты, тот же приём, что и у #guide-reader .backlog-header:
   иначе плашка либо перекрывала бы текст, либо пряталась за топбаром. */
.calendar-upcoming-month-header {
  position: sticky; top: 54px; z-index: 5;
  background: var(--bg); padding: 10px 2px 6px;
  font-size: 12px; font-weight: 700; color: var(--green-bright);
  text-transform: uppercase; letter-spacing: 0.05em;
  border-bottom: 1px solid var(--border);
}
.calendar-upcoming-month-header:first-child { padding-top: 0; }
.calendar-upcoming-item {
  display: flex; align-items: center; gap: 12px; background: var(--row-bg);
  border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px;
}
.calendar-upcoming-item.clickable { cursor: pointer; }
.calendar-upcoming-item.clickable:hover { border-color: var(--green-bright); background: var(--row-hover); }
.calendar-upcoming-cover {
  flex: none; width: 52px; height: 70px; border-radius: 4px; overflow: hidden; background: var(--row-bg-alt);
}
.calendar-upcoming-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.calendar-upcoming-info { min-width: 0; flex: 1; }
.calendar-upcoming-title-row { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.calendar-upcoming-title { font-size: 14px; font-weight: 700; color: var(--text); }
.calendar-upcoming-date { font-size: 12px; color: var(--green-bright); margin-top: 2px; }
.calendar-upcoming-meta { font-size: 12px; color: var(--text-dim); margin-top: 2px; }

/* Бейджи платформ — те же орбы, что и везде в приложении (см.
   platformBadgeHtml), просто крупнее и рядом с названием, а не мелким
   довеском к строке статистики. */
.calendar-upcoming-platform-badge { width: 18px; height: 18px; object-fit: contain; border-radius: 50%; flex: none; vertical-align: middle; }
/* Эксклюзив одной экосистемы (см. upcomingPlatformBadgesHtml) — золотое
   пульсирующее свечение, тот же приём и та же анимация, что у редкого
   ачивмента (.ach-icon.rare/rare-pulse в разделе "Редкие ачивменты"), просто
   в размере бейджа платформы, а не иконки ачивмента. */
.calendar-upcoming-platform-badge.exclusive {
  animation: rare-pulse 2.4s ease-in-out infinite;
  outline: 1px solid rgba(232,195,74,0.45);
  outline-offset: 1px;
}

/* Звёздочка "слежу" (см. UpcomingRelease.starred) — пустая по умолчанию,
   заливается и желтеет по клику/если уже отмечена. */
.calendar-upcoming-star-btn {
  flex: none; background: none; border: none; font-size: 20px; line-height: 1; cursor: pointer;
  color: var(--text-dim); padding: 4px; transition: color 0.12s, transform 0.05s;
}
.calendar-upcoming-star-btn:hover { color: #e8c34a; }
.calendar-upcoming-star-btn:active { transform: scale(0.9); }
.calendar-upcoming-star-btn.active { color: #e8c34a; text-shadow: 0 0 6px rgba(232,195,74,0.6); }

.calendar-upcoming-starred-toggle-btn.active { border-color: #e8c34a; color: #e8c34a; background: var(--row-hover); }

/* ---------- "Годовщина" на экране статистики ---------- */
/* Один блок без собственной плашки — вся статистика вокруг уже лежит на
   общем фоне панели, отдельная рамка тут была бы лишней подложкой поверх
   подложки. Одна игра (fallback-режим) — крупная обложка на всю высоту
   строки; несколько сразу (сегодня годовщина у пары игр) — плитки мельче и
   в ряд, gap держит их компактно без рамок между собой. */
.stats-anniversary { margin-bottom: 20px; }
.stats-anniversary.hidden { display: none; }
.stats-anniversary-title { font-size: 13px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.05em; margin: 0 0 10px; }
.stats-anniversary-cards { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 22px; }
.anniversary-card { display: flex; align-items: center; gap: 10px; }
.stats-anniversary-cards.compact .anniversary-card { gap: 8px; }
/* Плитка обложки переиспользует .calendar-game-tile (см. app.js), тут только
   размер и золотое свечение — тот же приём, что у редкого ачивмента
   (.ach-icon.rare/rare-pulse), просто заметнее под размер большой обложки. */
.anniversary-cover {
  --tile-w: 84px; --tile-h: 112px;
  flex: none; cursor: pointer;
  animation: rare-pulse-lg 2.6s ease-in-out infinite;
  outline: 1px solid rgba(232,195,74,0.5);
  outline-offset: 0;
}
.anniversary-cover.compact { --tile-w: 46px; --tile-h: 61px; animation: rare-pulse 2.4s ease-in-out infinite; }
.anniversary-cover.boxart-cover { outline: none; }
.anniversary-cover.boxart-cover img { filter: drop-shadow(0 0 10px rgba(232,195,74,0.65)) drop-shadow(0 3px 6px rgba(0,0,0,0.55)); }
.anniversary-cover.compact.boxart-cover img { filter: drop-shadow(0 0 6px rgba(232,195,74,0.6)) drop-shadow(0 2px 4px rgba(0,0,0,0.5)); }
@keyframes rare-pulse-lg {
  0%, 100% {
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.15),
                0 0 6px 1px rgba(232,195,74,0.5), 0 0 14px 2px rgba(232,195,74,0.22);
  }
  50% {
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.15),
                0 0 12px 2px rgba(232,195,74,0.85), 0 0 26px 7px rgba(232,195,74,0.4);
  }
}
.anniversary-text { font-size: 13px; line-height: 1.5; color: var(--text); }
.anniversary-text b { color: var(--rare-gold); }
@media (prefers-reduced-motion: reduce) {
  .anniversary-cover { animation: none; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.15), 0 0 10px 2px rgba(232,195,74,0.7); }
}

.day-tooltip-row { display: flex; align-items: flex-start; gap: 7px; }
.day-tooltip-name { font-size: 11px; font-weight: 600; color: var(--text); line-height: 1.25; overflow-wrap: break-word; word-break: break-word; }
/* Описание в подсказке ограничиваем двумя строками: она висит у курсора и не
   прокручивается, длинный текст просто выпихнул бы её за край экрана.
   Полный текст всегда виден в ленте разблокировок ниже. */
.day-tooltip-desc {
  font-size: 10px; color: var(--text-dim); line-height: 1.3; margin: 1px 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  overflow-wrap: break-word; word-break: break-word;
}
.day-tooltip-game { font-size: 9px; color: var(--green); }
.tooltip-title { font-size: 11px; font-weight: 700; color: var(--green-bright); margin-bottom: 6px; }
.ach-icon.small { width: 24px; height: 24px; font-size: 11px; }

.stats-rarest { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 8px; }
.stats-rarest { align-items: stretch; }
.rarest-item {
  display: flex; align-items: center; gap: 10px;
  background: var(--row-bg); border: 1px solid var(--border); border-radius: 5px; padding: 8px 10px;
}
.rarest-item .ach-icon { align-self: flex-start; }
.rarest-meta { flex: 1; min-width: 0; }
.rarest-name { font-size: 12px; color: var(--text); font-weight: 600; }
/* Описание показываем целиком: оно и объясняет, за что ачивмент выдан. */
.rarest-desc { font-size: 10px; color: var(--text-dim); line-height: 1.35; margin: 2px 0 3px; }
.rarest-game { font-size: 10px; color: var(--green); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rarest-pct { font-size: 13px; font-weight: 800; color: var(--rare-gold); }

/* ---------- «Последние запущенные игры» ---------- */
/* Максимум 12 карточек, но реально показываем только то, что помещается в
   одну строку без скролла (см. renderRecentGames в app.js — считает по
   ширине контейнера и обрезает список, а не сжимает обложки). Ширина/отступ
   карточки здесь (100 + 10) захардкожены и там же в JS (RECENT_CARD_WIDTH/
   RECENT_CARD_GAP) — держать в паре. */
.stats-recent { display: flex; justify-content: center; gap: 10px; }
.recent-card {
  flex-shrink: 0; width: 100px; cursor: pointer;
  display: flex; flex-direction: column; gap: 4px;
  padding: 4px; border-radius: 5px;
}
.recent-card:hover { background: var(--row-hover); }
.recent-cover { width: 100px; height: 150px; border-radius: 4px; object-fit: cover; flex-shrink: 0; }
.recent-cover-letter {
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(145deg, var(--green) 0%, var(--accent-shade) 100%);
  color: #0b1710; font-weight: 800; font-size: 24px;
}
/* boxart-платформы (см. isBoxartPlatform/recentCoverMarkup) — 3D-рендер
   коробки на прозрачном фоне, не портретная обложка: обрезать под 100×150
   как остальные обложки означало бы срезать саму коробку и оставить кусок
   белого фона. object-fit: contain показывает её целиком, по центру
   зарезервированного места (та же высота 150px, что у портретных обложек —
   карточки в ряду не скачут). */
.recent-cover.boxart-cover {
  object-fit: contain; background: none;
  filter: drop-shadow(0 3px 6px rgba(0,0,0,0.55));
}
/* Название убрано с самой карточки (есть в тултипе по наведению на обложку)
   — вместо него строка с платформой/часами/датой, той же высоты, что раньше
   занимала одна строка названия. */
.recent-meta-row { display: flex; align-items: center; gap: 4px; font-size: 10px; color: var(--text-dim); }
.recent-platform-badge { width: 12px; height: 12px; border-radius: 50%; object-fit: contain; flex-shrink: 0; }
.recent-hours { white-space: nowrap; }
.recent-date { margin-left: auto; white-space: nowrap; }

.recent-tooltip-list { display: flex; flex-direction: column; gap: 3px; }
.recent-tooltip-row { display: flex; justify-content: space-between; gap: 10px; font-size: 10px; }
.recent-tooltip-label { color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.recent-tooltip-value { color: var(--text); text-align: right; flex-shrink: 0; }
/* Списки с мини-иконками игр (платина/100%-пройденные) — пошире дефолтных
   240px, иконка+имя+дата в одну строку иначе теснятся (см. .cursor-tooltip). */
.cursor-tooltip:has(.recent-tooltip-icon) { width: 300px; }

/* ---------- «Что добить» ---------- */
.stats-pickups { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 8px; }
.pickup-card {
  display: flex; gap: 10px;
  background: var(--row-bg); border: 1px solid var(--border); border-radius: 5px; padding: 8px 10px;
}
.pickup-card:hover { background: var(--row-hover); }
.pickup-cover { width: 46px; height: 69px; border-radius: 3px; object-fit: cover; flex-shrink: 0; }
.pickup-cover-letter {
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(145deg, var(--green) 0%, var(--accent-shade) 100%);
  color: #0b1710; font-weight: 800; font-size: 18px;
}
.pickup-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
/* Длинное название переносится, а не режется: по обрезку не понять, какая
   это часть серии — та же причина, что и в списке библиотеки. */
.pickup-name { font-size: 12px; font-weight: 600; color: var(--text); line-height: 1.25; }
.pickup-rank {
  display: inline-block; margin-right: 5px; padding: 0 4px; border-radius: 3px;
  background: var(--green-dark); color: var(--green-bright);
  font-size: 10px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.pickup-bar { height: 4px; border-radius: 2px; background: var(--border); overflow: hidden; }
.pickup-bar i { display: block; height: 100%; background: var(--unlocked); }
.pickup-facts { display: flex; align-items: center; gap: 8px; font-size: 10px; color: var(--text-dim); }
.pickup-percent { color: var(--unlocked); font-weight: 700; font-size: 11px; }
/* Бейдж платформы + кнопка разбора оценки — одной группой у правого края
   строки фактов: не своя строка (карточка не растёт), не поверх обложки. */
.pickup-right-group { margin-left: auto; display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.pickup-platform-badge { width: 14px; height: 14px; border-radius: 50%; object-fit: contain; flex-shrink: 0; opacity: 0.85; }
.pickup-why {
  flex-shrink: 0;
  width: 16px; height: 16px; line-height: 14px; padding: 0;
  border-radius: 50%; border: 1px solid var(--border);
  background: transparent; color: var(--text-dim); font-size: 10px; cursor: help;
}
.pickup-why:hover { border-color: var(--green); color: var(--green-bright); }
.pickup-next { display: flex; flex-wrap: wrap; gap: 4px; }

.stats-ach-icon { cursor: pointer; }
/* Оставшиеся ачивменты приглушены так же, как заблокированные строки в
   списке самой игры — иначе непонятно, что они ещё не получены. */
.stats-ach-icon.locked {
  background: linear-gradient(145deg, #2a3a2c 0%, #17231a 100%);
  color: var(--locked);
}
.stats-ach-icon.locked img { filter: grayscale(1) brightness(0.55); }

.cursor-tooltip:has(.pickup-why-list) { width: 300px; }
.cursor-tooltip:has(.calendar-tooltip-summary) { width: 280px; }
.pickup-why-list { display: flex; flex-direction: column; gap: 3px; }
.pickup-why-row { display: flex; align-items: baseline; gap: 6px; font-size: 10px; }
.pickup-why-label { color: var(--text-dim); flex-shrink: 0; }
.pickup-why-value { color: var(--text); flex: 1; min-width: 0; text-align: right; }
.pickup-why-factor { color: var(--green-bright); font-variant-numeric: tabular-nums; min-width: 26px; text-align: right; }
.pickup-why-note { font-size: 9px; color: var(--text-dim); margin-top: 6px; line-height: 1.35; }

.stats-feed { display: flex; flex-direction: column; gap: 3px; }
.feed-day {
  font-size: 11px; color: var(--green-bright); text-transform: uppercase; letter-spacing: 0.06em;
  margin: 12px 0 4px; border-bottom: 1px solid var(--border); padding-bottom: 3px;
}
.feed-day:first-child { margin-top: 0; }
.feed-row {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--row-bg); border-radius: 4px; padding: 7px 8px;
}
.feed-row:hover { background: var(--row-hover); }
.feed-main { flex: 1; min-width: 0; }
.feed-name { font-size: 12px; color: var(--text); font-weight: 600; }
/* Описание — целиком, с переносом: обрезать его многоточием бессмысленно,
   именно оно объясняет, за что ачивмент. */
.feed-desc { font-size: 11px; color: var(--text-dim); line-height: 1.35; margin: 1px 0 2px; }
.feed-game { font-size: 10px; color: var(--green); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.feed-meta { display: flex; align-items: center; gap: 10px; font-size: 10px; color: var(--text-dim); flex-shrink: 0; padding-top: 2px; }
/* Время показывается только при наведении, но место под него держится всегда
   (visibility, а не display) — иначе строка дёргалась бы под курсором. */
.feed-time { font-variant-numeric: tabular-nums; visibility: hidden; }
.feed-row:hover .feed-time { visibility: visible; }
/* В списке за день время — основная координата (дата и так в заголовке),
   поэтому там оно видно всегда. */
.feed-time.always { visibility: visible; }
.feed-score { color: var(--unlocked); font-weight: 700; }
.feed-rarity.rare { color: var(--rare-gold); font-weight: 700; }

/* Схлопнутый заход в игру: пять и больше ачивментов одной игры за один день.
   Полоска слева отличает группу от обычной строки, не утяжеляя её рамкой. */
.feed-group {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--row-bg); border-radius: 4px; padding: 7px 8px;
  border-left: 2px solid var(--green);
}
.feed-group:hover { background: var(--row-hover); }
/* Обложка игры (см. feedSessionCoverHtml) идёт первым элементом в строке,
   как и у карточек сессий/одиночных разблокировок — остальное содержимое
   группы (шапка/иконки/имена) уходит в отдельную колонку рядом. */
.feed-group-body { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
.feed-group-head { display: flex; align-items: baseline; gap: 10px; }
.feed-group-game {
  flex: 1; min-width: 0; font-size: 12px; font-weight: 600; color: var(--green);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.feed-group-meta { flex-shrink: 0; font-size: 10px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.feed-group-icons { display: flex; flex-wrap: wrap; gap: 4px; }
/* Перечисление названий — чтобы группу можно было прочитать, не наводя мышь
   на каждую иконку по очереди. */
.feed-group-names { font-size: 10px; color: var(--text-dim); line-height: 1.4; }

/* Карточка игровой сессии (наиграно время без ачивментов, см. PlaySession) —
   обложка вместо иконки-ачивмента и янтарный акцент вместо зелёного, чтобы
   не путать с разблокировкой на беглый взгляд по ленте. */
.feed-session {
  display: flex; align-items: center; gap: 10px;
  background: var(--row-bg); border-radius: 4px; padding: 7px 8px;
  border-left: 2px solid var(--rare-gold);
}
.feed-session:hover { background: var(--row-hover); }
.feed-session-cover { width: 28px; height: 38px; border-radius: 3px; object-fit: cover; flex: none; }
.feed-session-cover-letter {
  background: var(--row-bg-alt); color: var(--text-dim);
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700;
}
.feed-session-body { flex: 1; min-width: 0; }
.feed-session-game {
  font-size: 12px; color: var(--text); font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.feed-session-duration { font-size: 11px; color: var(--rare-gold); margin-top: 1px; }
/* Только у ручных сессий (ретро/Switch 2, см. sessionDeleteBtnHtml) — дата
   там всегда "момент сохранения", ошибиться и захотеть убрать легко. Скрыта
   до наведения — тот же принцип, что у rarest-exclude-btn. */
.session-delete-btn {
  flex: none; width: 18px; height: 18px; line-height: 16px; padding: 0;
  border-radius: 3px; border: 1px solid var(--border);
  background: var(--row-bg); color: var(--text-dim);
  font-size: 11px; cursor: pointer; opacity: 0; transition: opacity 0.12s;
}
.feed-session:hover .session-delete-btn { opacity: 1; }
.session-delete-btn:hover { background: rgba(255,80,80,0.18); border-color: #ff6b6b; color: #ff6b6b; }

/* Запись журнала бэклога внутри общей ленты активности (см.
   statsJournalCardHtml, app/main.py::journal_activity_items) — фиолетовый
   акцент отличает её от зелёных разблокировок и янтарных сессий с первого
   взгляда. Показывается целиком (текст + скриншоты + чипы ачивментов), а не
   обрезанным превью — клик по самой карточке уводит в бэклог к этой записи. */
.stats-journal-card {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--row-bg); border-radius: 4px; padding: 7px 8px;
  border-left: 2px solid #a58aef; cursor: pointer;
}
.stats-journal-card:hover { background: var(--row-hover); }
/* display: contents — обёртка нужна только как цель для делегированного
   тултипа (см. wireStatsJournalTooltips), сама она не должна участвовать в
   layout, чтобы не портить выравнивание обложки внутри .feed-session-cover. */
.stats-journal-cover-wrap { display: contents; }
.stats-journal-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.stats-journal-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.stats-journal-category {
  font-size: 10px; color: #a58aef; background: rgba(165, 138, 239, 0.14);
  border: 1px solid rgba(165, 138, 239, 0.4); border-radius: 10px; padding: 1px 7px;
  flex-shrink: 0;
}
.feed-platform-badge { width: 14px; height: 14px; border-radius: 50%; object-fit: contain; flex-shrink: 0; opacity: 0.85; margin-left: auto; }
.stats-journal-text { font-size: 12px; color: var(--text); line-height: 1.4; white-space: pre-wrap; }
.stats-journal-card .journal-screenshots { margin-top: 2px; }

#stats-feed-more { margin-top: 12px; }
.day-tooltip-more { font-size: 10px; color: var(--text-dim); margin-top: 6px; text-align: center; }

/* Полный список ачивментов за день */
.day-modal { display: flex; flex-direction: column; max-height: 80vh; }
.day-modal-list {
  display: flex; flex-direction: column; gap: 3px;
  overflow-y: auto; margin: 0 -4px; padding: 0 4px; flex: 1;
}

/* Карточка "Наиграно" на экране статистики раскрывается в разбивку по играм
   (см. openPlaytimeModal) — курсор явно показывает, что по ней можно кликнуть. */
.stat-card-clickable { cursor: pointer; transition: border-color 0.15s; }
.stat-card-clickable:hover { border-color: var(--green); }

/* Иконка "плей" вместо подписи "Наиграно" (см. PLAYTIME_PLAY_ICON) — по
   центру карточки, без обводки, просто аккуратный треугольник. */
#stat-playtime-card .stat-label { display: flex; justify-content: center; }
.stat-label-play-icon { color: var(--green-bright); display: block; }

/* Разворот "Наиграно по играм" — вкладки платформ сверху (playtimeTabHtml),
   под ними горизонтальные полоски одной выбранной платформы, пропорционально
   максимуму СВОЕЙ платформы (см. playtimeSectionHtml). */
.playtime-modal-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.playtime-tab {
  display: flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: 16px;
  background: var(--row-bg); border: 1px solid var(--border); color: var(--text-dim);
  font-size: 12px; cursor: pointer; transition: border-color 0.15s, color 0.15s;
}
.playtime-tab:hover { border-color: var(--green); color: var(--text); }
.playtime-tab.active { border-color: var(--green-bright); color: var(--text); background: var(--green-dark); }
.playtime-tab-total { color: var(--green-bright); font-weight: 700; }

.playtime-section-rows { display: flex; flex-direction: column; gap: 4px; }

.playtime-row { display: flex; align-items: center; gap: 8px; padding: 3px 2px; border-radius: 5px; cursor: pointer; }
.playtime-row:hover { background: var(--row-bg); }
.playtime-row-cover {
  width: 26px; height: 26px; border-radius: 4px; overflow: hidden; flex-shrink: 0;
  background: var(--row-bg);
}
.playtime-row-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.playtime-row-cover.empty { background: var(--border); }
.playtime-row-body { flex: 1; min-width: 0; }
.playtime-row-name {
  font-size: 12px; color: var(--text); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; margin-bottom: 3px;
}
.playtime-row-bar-track { height: 5px; border-radius: 3px; background: var(--row-bg); overflow: hidden; }
.playtime-row-bar { height: 100%; border-radius: 3px; background: var(--green); }
.playtime-row-hours {
  font-size: 11px; color: var(--text-dim); width: 66px; text-align: right; flex-shrink: 0;
}

/* Тултип обложки в разворотe "Наиграно" — крупная обложка, прогресс
   ачивментов/трофеев, описание игры (IGDB/вики) и последние 4 полученных
   с описанием и "качеством" (редкость/очки/металл — см. playtimeTooltipHtml). */
.cursor-tooltip:has(.playtime-tooltip) { width: 320px; }
.playtime-tooltip-clear { clear: both; }
.playtime-tooltip .tooltip-title { margin-bottom: 3px; }
/* Портретные обложки (Steam, PS4/PS5, Switch 2) — их 2:3 не режем, показываем
   целиком, только уменьшаем: contain в рамке того же соотношения сторон,
   что и сама обложка, поэтому letterbox не появляется. */
.playtime-tooltip-cover {
  width: 66px; height: 99px; object-fit: contain; border-radius: 5px;
  float: left; margin: 0 8px 4px 0; shape-outside: margin-box;
}
/* boxart-платформы (см. isBoxartPlatform/.recent-cover.boxart-cover) — 3D-
   рендер коробки на прозрачном фоне, почти квадратный, а не портретный:
   своя, более широкая рамка, тоже contain — целиком, без обрезки. */
.playtime-tooltip-cover.boxart-cover {
  width: 66px; height: 66px; object-fit: contain; background: none; border-radius: 0;
  filter: drop-shadow(0 2px 5px rgba(0,0,0,0.55));
}
.playtime-tooltip .tooltip-title { font-size: 12px; font-weight: 700; margin-bottom: 4px; }
.playtime-tooltip-recent { display: flex; flex-direction: column; gap: 5px; margin-top: 6px; }
.playtime-tooltip-recent-row { display: flex; align-items: flex-start; gap: 6px; }
.playtime-tooltip-recent-icon { width: 22px; height: 22px; border-radius: 4px; flex-shrink: 0; object-fit: cover; }
.playtime-tooltip-recent-body { flex: 1; min-width: 0; }
.playtime-tooltip-recent-name { font-size: 11px; color: var(--text); line-height: 1.3; overflow-wrap: break-word; word-break: break-word; }
.playtime-tooltip-recent-desc { font-size: 10px; color: var(--text-dim); line-height: 1.3; overflow-wrap: break-word; word-break: break-word; }
.playtime-tooltip-recent-meta {
  font-size: 10px; color: var(--rare-gold); flex-shrink: 0; white-space: nowrap; padding-top: 1px;
}

/* ---------- Редкие ачивменты: пульсирующее свечение вокруг иконки ---------- */
/* Как в Steam: полученный редкий ачивмент подсвечивается сам, без подписи. */
@keyframes rare-pulse {
  0%, 100% {
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.15),
                0 0 3px 0 rgba(232,195,74,0.55), 0 0 7px 1px rgba(232,195,74,0.22);
  }
  50% {
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.15),
                0 0 7px 1px rgba(232,195,74,0.85), 0 0 15px 4px rgba(232,195,74,0.4);
  }
}
.ach-icon.rare {
  animation: rare-pulse 2.4s ease-in-out infinite;
  /* Свечение рисуется наружу, поэтому иконке нужен зазор от соседей. */
  outline: 1px solid rgba(232,195,74,0.45);
  outline-offset: 0;
}

/* Строка ачивмента, к которой перешли из статистики */
/* Подсветка строки, к которой перешли из статистики: сначала держится, чтобы
   её точно успели заметить после прокрутки, потом плавно тает. */
@keyframes ach-flash {
  0%, 25% { background: var(--green-dark); box-shadow: inset 0 0 0 2px var(--green-bright); }
  100% { background: transparent; box-shadow: inset 0 0 0 2px transparent; }
}
.ach-row.flash { animation: ach-flash 2.8s ease-out; }

/* Та же подсветка "доехали и мигнули", но без завязки на фон ach-row —
   для любого элемента, к которому переходят из поиска/статистики
   (например, запись журнала бэклога). */
@keyframes generic-flash {
  0%, 25% { box-shadow: inset 0 0 0 2px var(--green-bright); }
  100% { box-shadow: inset 0 0 0 2px transparent; }
}
.flash-highlight { animation: generic-flash 2.8s ease-out; }

.feed-row[data-platform], .rarest-item[data-platform],
.feed-group[data-platform], .pickup-card[data-platform], .feed-session[data-platform] { cursor: pointer; }

/* Анимации — вкус, а не смысл: кому они мешают, тот их отключил в системе. */
@media (prefers-reduced-motion: reduce) {
  .ach-icon.rare { animation: none; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.15), 0 0 6px 1px rgba(232,195,74,0.7); }
  .ach-row.flash { animation: none; box-shadow: inset 0 0 0 2px var(--green-bright); }
  .flash-highlight { animation: none; box-shadow: inset 0 0 0 2px var(--green-bright); }
}

/* Кнопка возврата в статистику — поверх списка, у нижнего края. */
.stats-return-btn {
  position: fixed; left: 16px; bottom: 16px; z-index: 90;
  background: var(--bg-panel); color: var(--text);
  border: 1px solid var(--green); border-radius: 5px;
  padding: 8px 12px; font-size: 12px; font-weight: 600; cursor: pointer;
  box-shadow: 0 6px 18px rgba(0,0,0,0.5);
}
.stats-return-btn:hover { background: var(--row-hover); }
.stats-return-btn.hidden { display: none; }

/* Кнопка переключения платформы у ачивмента, который есть и в Steam, и на Xbox.
   Живёт поверх иконки: место в строке она не занимает, а по клику меняет
   показанную версию. Скрыта, пока курсор не окажется конкретно над иконкой —
   наведение на остальную часть строки (название, описание) её не показывает,
   иначе кнопка мелькала бы почти на каждом движении мыши по ленте. */
.ach-icon.has-twin { position: relative; }
.feed-swap {
  position: absolute; right: -2px; bottom: -2px;
  width: 16px; height: 16px; line-height: 14px; padding: 0;
  border-radius: 4px; border: 1px solid var(--green);
  background: var(--bg-panel); color: var(--green-bright);
  font-size: 10px; cursor: pointer; opacity: 0; transition: opacity 0.12s;
}
.ach-icon.has-twin:hover .feed-swap, .feed-swap:focus-visible { opacity: 1; }
.feed-swap:hover { background: var(--green-dark); }

/* Кнопка исключения игры из "Самых редких" — видна при наведении на карточку,
   постоянный крестик на 12 карточках был бы визуальным шумом. */
.rarest-item { position: relative; }
.rarest-exclude-btn {
  position: absolute; top: 4px; right: 4px;
  width: 18px; height: 18px; line-height: 16px; padding: 0;
  border-radius: 3px; border: 1px solid var(--border);
  background: var(--row-bg); color: var(--text-dim);
  font-size: 11px; cursor: pointer; opacity: 0; transition: opacity 0.12s;
}
.rarest-item:hover .rarest-exclude-btn { opacity: 1; }
.rarest-exclude-btn:hover { background: rgba(255,80,80,0.18); border-color: #ff6b6b; color: #ff6b6b; }

.cover-editor-checkbox-row {
  display: flex; align-items: center; gap: 7px;
  font-size: 12px; color: var(--text-dim); margin: 10px 0 2px; cursor: pointer;
}
.cover-editor-checkbox-row input { margin: 0; }
