/* gamelog — дизайн-система.
   Первый блок — токены и компоненты один в один из макета
   «gamelog — дизайн-система.html»: цвета, типографика, отступы, все
   компоненты. Менять оформление только здесь; в шаблонах — только классы.
   Второй блок, GAMELOG, добавляет то, чего в статичном макете не было. */

  /* ============ TOKENS ============ */
  :root{
    color-scheme: dark;

    /* — surfaces — */
    --bg:            #14161b;
    --bg-elevated:   #191c22;
    --surface:       #1e2128;
    --surface-hover: #262a32;
    --surface-sunken:#101216;

    /* — borders — */
    --border:        #2b2f38;
    --border-subtle: #21242b;
    --border-strong: #3a3f4b;

    /* — text — */
    --text-primary:   #e7e9ed;
    --text-secondary: #9aa0ab;  /* level 2 */
    --text-tertiary:  #6a7080;

    /* — accent (UI / interactive, not a status) — */
    --accent:      #4f9b93;
    --accent-fg:   #8fd0c8;
    --accent-soft: rgba(79,155,147,.14);
    --accent-border: rgba(79,155,147,.4);

    /* — status colors (5) — */
    --status-completed:      #5f9e6a;
    --status-completed-fg:   #93c99c;
    --status-completed-bg:   rgba(95,158,106,.14);
    --status-completed-bd:   rgba(95,158,106,.38);

    --status-playing:        #4f8fd0;
    --status-playing-fg:     #8fbcec;
    --status-playing-bg:     rgba(79,143,208,.14);
    --status-playing-bd:     rgba(79,143,208,.38);

    --status-paused:        #c9974f;
    --status-paused-fg:     #e6bb7d;
    --status-paused-bg:     rgba(201,151,79,.14);
    --status-paused-bd:     rgba(201,151,79,.38);

    --status-planned:        #8b7fc7;
    --status-planned-fg:     #b3aae0;
    --status-planned-bg:     rgba(139,127,199,.14);
    --status-planned-bd:     rgba(139,127,199,.38);

    --status-dropped:        #c0645a;
    --status-dropped-fg:     #e2988f;
    --status-dropped-bg:     rgba(192,100,90,.14);
    --status-dropped-bd:     rgba(192,100,90,.38);

    --status-100:            #b9c0cb;
    --status-100-fg:         #e6e9ee;
    --status-100-bg:         rgba(185,192,203,.14);
    --status-100-bd:         rgba(185,192,203,.4);

    /* — трофейные тиры личной оценки (кубки: бронза/серебро/золото/платина) — */
    --tier-bronze:   #b3773f;
    --tier-silver:   #b8c0ca;
    --tier-gold:     #d9ac3f;
    --tier-platinum: #d7ecf2;

    /* — cover placeholder family (art, not semantic) — */
    --cover-1: #384a5c; --cover-2: #4a3f57; --cover-3: #4f4636;
    --cover-4: #2f4a48; --cover-5: #55403f; --cover-6: #3d4a3a;
    --cover-7: #443a5c; --cover-8: #57492f;

    /* — type — */
    --font-ui:   "Golos Text", "Segoe UI", system-ui, sans-serif;
    --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Consolas, monospace;

    --text-2xs: 0.6875rem;  /* 11 */
    --text-xs:  0.75rem;    /* 12 */
    --text-sm:  0.8125rem;  /* 13 */
    --text-base:0.875rem;   /* 14 */
    --text-md:  1rem;       /* 16 */
    --text-lg:  1.25rem;    /* 20 */
    --text-xl:  1.625rem;   /* 26 */
    --text-2xl: 2.125rem;   /* 34 */

    /* — spacing — */
    --space-1: 0.25rem; --space-2: 0.5rem;  --space-3: 0.75rem;
    --space-4: 1rem;    --space-5: 1.25rem; --space-6: 1.5rem;
    --space-8: 2rem;    --space-10: 2.5rem;

    /* — radii — */
    --radius-xs: 0.1875rem;
    --radius-sm: 0.375rem;
    --radius-md: 0.5rem;
    --radius-lg: 0.75rem;
    --radius-full: 999px;

    /* — shadow — */
    --shadow-sm: 0 1px 2px rgba(0,0,0,.35);
    --shadow-md: 0 6px 16px -4px rgba(0,0,0,.5);
    --shadow-lg: 0 16px 36px -10px rgba(0,0,0,.55);

    --topbar-h: 56px;
    --tabbar-h: 46px;
  }

  *,*::before,*::after{ box-sizing:border-box; }
  html{ -webkit-text-size-adjust:100%; }
  body{
    background: var(--bg);
    color: var(--text-primary);
    font-family: var(--font-ui);
    font-size: var(--text-base);
    line-height: 1.45;
    overflow-x: hidden;
  }
  h1,h2,h3,h4{ margin:0; font-weight:700; text-wrap:balance; }
  p{ margin:0; }
  ul{ margin:0; padding:0; list-style:none; }
  button{ font-family:inherit; }
  a{ color:inherit; }
  img,svg{ display:block; }
  ::selection{ background: var(--accent-soft); color:var(--text-primary); }

  :focus-visible{
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-xs);
  }

  .tabular{ font-variant-numeric: tabular-nums; font-feature-settings:"tnum" 1; }
  .mono{ font-family: var(--font-mono); }

  /* ============ SHELL LAYOUT ============ */
  .shell{ display:flex; flex-direction:column; min-height:100vh; }
  .main{ display:flex; flex-direction:column; min-width:0; }

  /* — Brand — */
  .brand{
    display:flex;
    align-items:center;
    gap: 5px;
    font-family: var(--font-mono);
    font-weight:600;
    font-size: var(--text-md);
    letter-spacing:-0.02em;
    flex:none;
  }
  .brand-mark{ color: var(--accent); }
  .brand-name{ color: var(--text-primary); }
  .brand small{
    font-family: var(--font-ui);
    font-weight:500;
    font-size: var(--text-2xs);
    color: var(--text-tertiary);
    margin-left:2px;
  }

  /* — Top bar (profile row) — */
  .topbar{
    height: var(--topbar-h);
    position: sticky; top:0; z-index:6;
    background: rgba(20,22,27,.9);
    backdrop-filter: blur(6px);
    border-bottom:1px solid var(--border-subtle);
    display:flex;
    align-items:center;
    gap: var(--space-5);
    padding: 0 var(--space-6);
  }

  /* — Tab bar (top navigation, replaces the old sidebar) — */
  .tabbar{
    position: sticky; top: var(--topbar-h); z-index:5;
    background: var(--bg-elevated);
    border-bottom:1px solid var(--border-subtle);
    display:flex;
    align-items:stretch;
    gap: var(--space-1);
    padding: 0 var(--space-6);
    overflow-x:auto;
    scrollbar-width:none;
  }
  .tabbar::-webkit-scrollbar{ display:none; }
  .nav-item{
    display:flex;
    align-items:center;
    gap: var(--space-2);
    padding: 0 var(--space-3);
    height: var(--tabbar-h);
    color: var(--text-secondary);
    font-size: var(--text-sm);
    font-weight:500;
    border:none;
    border-bottom:2px solid transparent;
    background:none;
    white-space:nowrap;
    cursor:pointer;
    transition: background-color .12s ease, color .12s ease, border-color .12s ease;
  }
  .nav-item svg{ width:16px; height:16px; flex:none; stroke: currentColor; }
  .nav-item:hover{ background: var(--surface-hover); color: var(--text-primary); }
  .nav-item[aria-current="page"]{
    color: var(--accent-fg);
    border-bottom-color: var(--accent);
  }
  .nav-item[aria-current="page"] svg{ stroke: var(--accent-fg); }

  .search{
    position:relative;
    flex:1;
    max-width:420px;
  }
  .search input{
    width:100%;
    background: var(--surface);
    border:1px solid var(--border);
    color: var(--text-primary);
    font-family:inherit;
    font-size: var(--text-sm);
    padding: var(--space-2) var(--space-8) var(--space-2) var(--space-8);
    border-radius: var(--radius-sm);
    transition: border-color .12s ease, background-color .12s ease;
  }
  .search input::placeholder{ color: var(--text-tertiary); }
  .search input:focus{ outline:none; border-color: var(--accent-border); background: var(--surface-sunken); }
  .search svg{
    position:absolute; left:10px; top:50%; transform:translateY(-50%);
    width:15px; height:15px; stroke: var(--text-tertiary); pointer-events:none;
  }
  .search kbd{
    position:absolute; right:8px; top:50%; transform:translateY(-50%);
    font-family: var(--font-mono);
    font-size: var(--text-2xs);
    color: var(--text-tertiary);
    background: var(--bg-elevated);
    border:1px solid var(--border);
    border-radius: var(--radius-xs);
    padding: 1px 5px;
  }

  .topbar-spacer{ flex:1; }

  /* Поиск — по центру шапки. Авто-поля слева и справа забирают всё
     свободное место поровну, поэтому на экранах с поиском правый
     spacer больше не нужен и схлопывается. На «Входе»/«Регистрации»
     поиска нет — spacer работает как раньше и прижимает кнопки вправо. */
  .topbar .search{ flex: 0 1 420px; margin-inline: auto; }
  .topbar:has(.search) .topbar-spacer{ display:none; }

  .account{
    display:flex; align-items:center; gap: var(--space-2);
    padding: var(--space-1) var(--space-2) var(--space-1) var(--space-1);
    border-radius: var(--radius-full);
    border:1px solid transparent;
  }
  .account:hover{ background: var(--surface); border-color: var(--border); }
  .avatar{
    width:30px; height:30px; border-radius: var(--radius-sm);
    background: linear-gradient(155deg, var(--cover-7), var(--cover-1));
    display:flex; align-items:center; justify-content:center;
    font-family: var(--font-mono); font-weight:700; font-size:11px;
    color: var(--text-primary);
    flex:none;
  }
  .account-name{ display:flex; flex-direction:column; line-height:1.2; }
  .account-name b{ font-size: var(--text-xs); font-weight:600; }
  .account-name span{ font-size: var(--text-2xs); color: var(--text-tertiary); }

  /* ============ CONTENT ============ */
  .content{ padding: var(--space-6) var(--space-6) var(--space-10); display:flex; flex-direction:column; gap: var(--space-8); max-width:1280px; width:100%; margin-inline:auto; }

  .page-head{ display:flex; align-items:baseline; gap: var(--space-3); flex-wrap:wrap; }
  .page-head h1{ font-size: var(--text-xl); }
  .page-head .count{ color: var(--text-tertiary); font-size: var(--text-sm); }

  /* — Profile header — */
  .profile-header{
    background: var(--surface);
    border:1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-5);
    display:flex;
    align-items:center;
    flex-wrap:wrap;
    gap: var(--space-5);
  }
  .profile-id-group{ display:flex; align-items:flex-start; flex-wrap:wrap; gap: var(--space-4); flex:1; min-width:220px; }
  .profile-avatar-col{ display:flex; flex-direction:column; align-items:center; gap:9px; flex:none; }
  .profile-avatar{
    width:88px; height:88px; flex:none;
    border-radius: var(--radius-lg);
    background: linear-gradient(155deg, var(--cover-7), var(--cover-1));
    display:flex; align-items:center; justify-content:center;
    font-family: var(--font-mono); font-weight:700; font-size: var(--text-xl);
    color: var(--text-primary);
  }
  /* Полоса статов: своя строка под аватаром и именем, прижата влево. */
  .avatar-stats{ flex-basis:100%; display:flex; flex-direction:row; flex-wrap:wrap; justify-content:flex-start; gap:10px 16px; }
  .avatar-stats li{ display:flex; align-items:baseline; gap:5px; font-size: var(--text-xs); color: var(--text-tertiary); white-space:nowrap; }
  .avatar-stats .emoji{ font-size: var(--text-sm); line-height:1; }
  .avatar-stats b{ font-family: var(--font-mono); color: var(--text-primary); font-weight:600; font-size: var(--text-sm); }
  .profile-id{ display:flex; flex-direction:column; gap:4px; min-width:0; padding-top:4px; }
  .profile-name{ font-size: var(--text-lg); }
  .profile-meta{ font-size: var(--text-xs); color: var(--text-tertiary); }
  .profile-meta .sep{ margin:0 6px; opacity:.5; }
  .sync-link{
    background:none; border:none; padding:0; cursor:pointer;
    font-family:inherit; font-size:inherit; color: var(--text-tertiary);
    text-decoration: underline dotted; text-underline-offset:2px;
  }
  .sync-link:hover{ color: var(--accent-fg); }

  .profile-level{ display:flex; align-items:center; gap: var(--space-3); flex:none; }
  .level-ring{ position:relative; width:60px; height:60px; flex:none; }
  .level-ring svg{ width:100%; height:100%; transform:rotate(-90deg); }
  .level-ring .ring-track{ fill:none; stroke: var(--border); stroke-width:5; }
  .level-ring .ring-fill{ fill:none; stroke: var(--accent); stroke-width:5; stroke-linecap:round; }
  .level-ring .level-num{
    position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
    font-family: var(--font-mono); font-weight:700; font-size: var(--text-md);
    /* Внутри кольца помещается уровень до четырёх знаков — поджимаем трекинг. */
    letter-spacing:-0.04em;
    color: var(--text-primary);
  }
  .level-text{ display:flex; flex-direction:column; gap:2px; }
  .level-text .level-label{ font-size: var(--text-sm); font-weight:600; color: var(--accent-fg); }
  .level-text .level-sub{ font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-tertiary); }

  /* — Page layout: main column + right rail — */
  .page-layout{ display:grid; grid-template-columns: 1fr 300px; align-items:start; gap: var(--space-6); }
  .page-main{ display:flex; flex-direction:column; gap: var(--space-8); min-width:0; }
  /* Пустой маунт-поинт синка не должен есть gap колонки — иначе
     первый блок съезжает вниз относительно правого сайдбара. */
  #sync-progress:not(:has(*)){ display:none; }
  .page-aside{
    display:flex; flex-direction:column; gap: var(--space-5);
  }

  /* — Recently played rail — */
  .recent-card{
    background: var(--surface);
    border:1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-4);
    display:flex; flex-direction:column; gap: var(--space-3);
  }
  .recent-rows{ display:flex; flex-direction:column; gap:2px; }
  .recent-row{
    display:flex; align-items:center; gap: var(--space-3);
    padding: 5px; border-radius: var(--radius-sm);
  }
  .recent-row:hover{ background: var(--surface-hover); }
  .recent-cover{
    width:30px; aspect-ratio:3/4; flex:none; border-radius:3px;
    display:flex; align-items:center; justify-content:center;
    font-family: var(--font-mono); font-weight:700; font-size:8.5px;
    color: rgba(255,255,255,.4);
  }
  .recent-info{ display:flex; flex-direction:column; gap:1px; min-width:0; }
  .recent-info b{
    font-size: var(--text-xs); font-weight:600; color: var(--text-primary);
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .recent-info span{ font-size:10.5px; color: var(--text-tertiary); font-family: var(--font-mono); }

  /* — Friends rail — */
  .friends-card{
    background: var(--surface);
    border:1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-4);
    display:flex; flex-direction:column; gap: var(--space-3);
  }
  .friend-rows{ display:flex; flex-direction:column; gap:2px; }
  .friend-row{
    display:flex; align-items:center; gap: var(--space-3);
    padding: 5px; border-radius: var(--radius-sm);
  }
  .friend-row:hover{ background: var(--surface-hover); }
  .friend-row .friend-avatar{
    width:36px; height:36px; flex:none; border-radius: var(--radius-sm);
    display:flex; align-items:center; justify-content:center;
    font-family: var(--font-mono); font-weight:700; font-size:10.5px;
    color: var(--text-primary);
  }
  .friend-row .friend-name{
    font-size: var(--text-xs); color: var(--text-secondary);
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }

  section.block{ display:flex; flex-direction:column; gap: var(--space-4); }
  .block-head{ display:flex; align-items:center; justify-content:space-between; gap: var(--space-3); flex-wrap:wrap; }
  .block-head h2{ font-size: var(--text-md); }
  .block-head .hint{ font-size: var(--text-xs); color: var(--text-tertiary); }

  /* — Stat strip — */
  .stat-grid{
    display:grid;
    grid-template-columns: repeat(3, minmax(0,1fr));
    gap: var(--space-3);
  }
  .stat-card{
    background: var(--surface);
    border:1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-4);
    display:flex; flex-direction:column; gap: var(--space-1);
  }
  .stat-card .label{
    font-size: var(--text-2xs); text-transform:uppercase; letter-spacing:.07em;
    color: var(--text-tertiary);
  }
  .stat-card .value{
    font-family: var(--font-mono); font-weight:600; font-size: var(--text-xl);
    color: var(--text-primary);
  }
  .stat-card .sub{ font-size: var(--text-xs); color: var(--text-secondary); }
  .stat-card .sub em{ color: var(--status-completed-fg); font-style:normal; font-weight:600; }
  .stat-card .sub.warn em{ color: var(--status-dropped-fg); }

  /* — Status distribution chart — */
  .status-chart{
    background: var(--surface);
    border:1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-4);
    display:flex; flex-direction:column; gap: var(--space-3);
  }
  .status-chart-bar{
    display:flex;
    height:14px;
    border-radius: var(--radius-full);
    overflow:hidden;
    background: var(--surface-sunken);
    border:1px solid var(--border-subtle);
  }
  .status-chart-bar .seg{ height:100%; }
  .status-chart-bar .seg:not(:last-child){ border-right:1px solid var(--bg); }
  .status-chart-legend{ display:flex; flex-wrap:wrap; column-gap: var(--space-5); row-gap: var(--space-2); }
  .status-chart-legend li{ display:flex; align-items:center; gap:7px; font-size: var(--text-xs); color: var(--text-secondary); }
  .status-chart-legend .dot{ width:8px; height:8px; border-radius:50%; flex:none; }
  .status-chart-legend b{ font-family: var(--font-mono); color: var(--text-primary); font-weight:600; }

  /* — Status distribution pie/donut — тот же датасет, что и status-chart-bar,
       но по кругу: удобнее, когда статусов пять и в узкой колонке-сайдбаре. — */
  .status-donut-wrap{ display:flex; justify-content:center; padding: var(--space-1) 0 var(--space-2); }
  .status-donut{ position:relative; width:112px; height:112px; border-radius:50%; flex:none; }
  .status-donut::after{
    content:""; position:absolute; inset:24%; border-radius:50%;
    background: var(--surface);
    box-shadow: inset 0 0 0 1px var(--border-subtle);
  }

  /* — Оценки критиков (Metacritic / OpenCritic / IGN и т.п.) — */
  .critic-card{
    background: var(--surface);
    border:1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-4);
    display:flex; flex-direction:column; gap: var(--space-2);
  }
  .critic-list{ display:flex; flex-direction:column; }
  .critic-row{
    display:flex; align-items:center; justify-content:space-between; gap: var(--space-3);
    padding: var(--space-2) 3px;
  }
  .critic-row:not(:last-child){ border-bottom:1px solid var(--border-subtle); }
  .critic-source{ display:flex; align-items:center; gap: var(--space-3); min-width:0; }
  .critic-badge{
    width:30px; height:30px; flex:none; border-radius: var(--radius-sm);
    display:flex; align-items:center; justify-content:center;
    font-family: var(--font-mono); font-weight:700; font-size:10px;
    color: var(--text-primary);
  }
  .critic-name{ font-size: var(--text-sm); color: var(--text-secondary); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .critic-score{ font-family: var(--font-mono); font-weight:700; font-size: var(--text-md); flex:none; }
  .critic-score.is-high{ color: var(--status-completed-fg); }
  .critic-score.is-mid{ color: var(--status-paused-fg); }
  .critic-score.is-low{ color: var(--status-dropped-fg); }

  /* — Оценка сайта: средняя по оценкам пользователей Gamelog — */
  .site-score-label{ font-size: var(--text-sm); color: var(--text-secondary); }
  .site-score-sub{ font-size: var(--text-2xs); color: var(--text-tertiary); }
  .site-score-value{ font-family: var(--font-mono); font-weight:700; font-size: var(--text-lg); color: var(--accent-fg); flex:none; }
  .site-score-value .site-score-max{ font-size: var(--text-xs); font-weight:600; color: var(--text-tertiary); margin-left:2px; }

  /* — Сколько проходят игру (HowLongToBeat) — */
  .hltb-card{
    background: var(--surface);
    border:1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-4);
    display:flex; flex-direction:column; gap: var(--space-2);
  }
  .hltb-list{ display:flex; flex-direction:column; }
  .hltb-row{
    display:flex; align-items:center; justify-content:space-between; gap: var(--space-3);
    padding: var(--space-2) 3px;
  }
  .hltb-row:not(:last-child){ border-bottom:1px solid var(--border-subtle); }
  .hltb-label{ font-size: var(--text-sm); color: var(--text-secondary); }
  .hltb-value{ font-family: var(--font-mono); font-weight:600; font-size: var(--text-sm); color: var(--text-primary); flex:none; }

  /* — Status legend / filters — */
  .status-filters{ display:flex; flex-wrap:wrap; gap: var(--space-2); }

  /* — StatusBadge — */
  .status-badge{
    display:inline-flex; align-items:center; gap:6px;
    font-size: var(--text-2xs); font-weight:600;
    padding: 3px 9px 3px 7px;
    border-radius: var(--radius-full);
    border:1px solid transparent;
    white-space:nowrap;
    cursor:default;
    line-height:1.6;
  }
  .status-badge .dot{ width:6px; height:6px; border-radius:50%; flex:none; }
  button.status-badge{ cursor:pointer; background:none; font-family:inherit; transition:filter .12s ease, opacity .12s ease; }
  button.status-badge:hover{ filter:brightness(1.15); }
  button.status-badge:not(.is-active){ opacity:.55; }

  .status-badge.st-completed{ color:var(--status-completed-fg); background:var(--status-completed-bg); border-color:var(--status-completed-bd); }
  .status-badge.st-completed .dot{ background:var(--status-completed); }
  .status-badge.st-playing{ color:var(--status-playing-fg); background:var(--status-playing-bg); border-color:var(--status-playing-bd); }
  .status-badge.st-playing .dot{ background:var(--status-playing); }
  .status-badge.st-paused{ color:var(--status-paused-fg); background:var(--status-paused-bg); border-color:var(--status-paused-bd); }
  .status-badge.st-paused .dot{ background:var(--status-paused); }
  .status-badge.st-planned{ color:var(--status-planned-fg); background:var(--status-planned-bg); border-color:var(--status-planned-bd); }
  .status-badge.st-planned .dot{ background:var(--status-planned); }
  .status-badge.st-dropped{ color:var(--status-dropped-fg); background:var(--status-dropped-bg); border-color:var(--status-dropped-bd); }
  .status-badge.st-dropped .dot{ background:var(--status-dropped); }
  .status-badge.st-100{ color:var(--status-100-fg); background:var(--status-100-bg); border-color:var(--status-100-bd); }
  .status-badge.st-100 .dot{ background:var(--status-100); }

  /* — GameCard grid — */
  .card-grid{
    display:grid;
    grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
    gap: var(--space-4);
  }
  .game-card{
    background: var(--surface);
    border:1px solid var(--border);
    border-radius: var(--radius-md);
    overflow:hidden;
    display:flex; flex-direction:column;
    transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
  }
  .game-card:hover{ border-color: var(--border-strong); box-shadow: var(--shadow-md); transform: translateY(-2px); }
  .game-card[data-status="100"]{ border-color: var(--status-100-bd); box-shadow: 0 0 0 1px var(--status-100-bd) inset; }
  .game-card[data-status="100"]:hover{ border-color: var(--status-100); box-shadow: 0 0 0 1px var(--status-100) inset, var(--shadow-md); }
  .js-open-game{ cursor:pointer; }
  .game-card[hidden]{ display:none; }

  .cover{
    aspect-ratio: 3/4;
    position:relative;
    display:flex; align-items:center; justify-content:center;
    overflow:hidden;
    background-image:
      repeating-linear-gradient(135deg, rgba(255,255,255,.05) 0 2px, transparent 2px 14px);
  }
  .cover .mono-letters{
    font-family: var(--font-mono); font-weight:700;
    font-size: 2.4rem; letter-spacing:-0.03em;
    color: rgba(255,255,255,.16);
  }
  .cover .cover-badge{
    position:absolute; top:6px; left:6px;
    display:flex; align-items:center; gap:4px;
    background: rgba(10,11,14,.55);
    border:1px solid rgba(255,255,255,.08);
    border-radius: var(--radius-xs);
    padding: 2px 6px;
    font-size:10px; color: rgba(233,235,239,.85);
  }
  .cover .cover-badge svg{ width:10px; height:10px; stroke:currentColor; }

  .game-body{ padding: var(--space-3); display:flex; flex-direction:column; gap: var(--space-2); flex:1; }
  .game-title{
    font-size: var(--text-sm); font-weight:600; color: var(--text-primary);
    display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
    line-height:1.3; min-height:2.6em;
  }
  .game-meta-row{ display:flex; align-items:center; justify-content:space-between; gap: var(--space-2); }
  .playtime{ font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-secondary); }

  .progress{ display:flex; flex-direction:column; gap:4px; margin-top:auto; }
  .progress-track{ height:5px; background: var(--surface-sunken); border:1px solid var(--border-subtle); border-radius: var(--radius-full); overflow:hidden; }
  .progress-fill{ height:100%; background: var(--accent); border-radius: var(--radius-full); }
  .progress-label{ font-family: var(--font-mono); font-size:10.5px; color: var(--text-tertiary); display:flex; justify-content:space-between; }
  .progress-label .pct{ color: var(--text-secondary); }

  /* — GameRow list — */
  .row-list{ display:flex; flex-direction:column; border-top:1px solid var(--border-subtle); }
  .game-row{
    display:grid;
    grid-template-columns: 34px 1fr 96px 88px 150px;
    align-items:center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-2);
    border-bottom:1px solid var(--border-subtle);
    transition: background-color .1s ease;
  }
  .game-row:hover{ background: var(--surface-hover); }
  .game-row[data-status="100"]{ background: var(--status-100-bg); box-shadow: inset 2px 0 0 var(--status-100); }
  .game-row[data-status="100"]:hover{ background: var(--status-100-bg); filter:brightness(1.15); }
  .game-row[hidden]{ display:none; }
  .row-cover{
    width:34px; aspect-ratio:3/4; border-radius:3px; overflow:hidden;
    display:flex; align-items:center; justify-content:center;
    font-family: var(--font-mono); font-weight:700; font-size:10px; color: rgba(255,255,255,.35);
    flex:none;
  }
  .row-title{ display:flex; flex-direction:column; gap:1px; min-width:0; }
  .row-title b{ font-size: var(--text-sm); font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .row-platform{ display:flex; align-items:center; gap:4px; font-size:10.5px; color: var(--text-tertiary); }
  .row-platform svg{ width:10px; height:10px; stroke:currentColor; }
  .row-playtime{ font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-secondary); text-align:right; }
  .row-progress{ display:flex; flex-direction:column; gap:3px; }
  .row-progress .progress-track{ height:4px; }
  .row-progress .progress-label{ font-size:10px; }

  /* — Achievements panel — */
  .ach-panel{
    background: var(--surface);
    border:1px solid var(--border);
    border-radius: var(--radius-md);
    overflow:hidden;
  }
  .ach-panel-head{
    display:flex; align-items:center; gap: var(--space-3);
    padding: var(--space-4);
    border-bottom:1px solid var(--border-subtle);
    background: var(--bg-elevated);
  }
  .ach-panel-head .cover-mini{
    width:44px; aspect-ratio:3/4; border-radius: var(--radius-xs); flex:none;
    background: var(--cover-4);
  }
  .ach-panel-head-text{ display:flex; flex-direction:column; gap:2px; flex:1; min-width:0; }
  .ach-panel-head-text b{ font-size: var(--text-md); }
  .ach-panel-head-text .note{ font-size: var(--text-xs); color: var(--status-playing-fg); }
  .ach-panel-head .progress{ width:160px; margin-top:0; }

  .ach-list{ display:flex; flex-direction:column; }
  .ach-row{
    display:flex; align-items:center; gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-bottom:1px solid var(--border-subtle);
  }
  .ach-row:last-child{ border-bottom:none; }
  .ach-row[hidden]{ display:none; }
  .ach-icon{
    width:64px; height:64px; flex:none; border-radius: var(--radius-sm);
    display:flex; align-items:center; justify-content:center;
    background: var(--surface-sunken); border:1px solid var(--border);
  }
  .ach-icon svg{ width:30px; height:30px; stroke: var(--accent-fg); fill:none; }
  .ach-row.is-locked .ach-icon{ filter:grayscale(1); opacity:.4; }
  .ach-row.is-locked .ach-icon svg{ stroke: var(--text-tertiary); }
  .ach-text{ flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
  .ach-text b{ font-size: var(--text-sm); font-weight:600; }
  .ach-row.is-locked .ach-text b{ color: var(--text-secondary); font-weight:500; }
  .ach-text p{ font-size: var(--text-xs); color: var(--text-secondary); }
  .ach-row.is-locked .ach-text p{ color: var(--text-tertiary); }
  .ach-meta{ flex:none; text-align:right; display:flex; flex-direction:column; gap:3px; min-width:118px; }
  .ach-meta .date{ font-size: var(--text-xs); color: var(--text-secondary); }
  .ach-row.is-locked .ach-meta .date{ color: var(--text-tertiary); font-style:normal; }
  .ach-meta .rarity{ font-family: var(--font-mono); font-size:10.5px; color: var(--text-tertiary); }

  /* — EmptyState — */
  .empty-state{
    display:flex; flex-direction:column; align-items:center; text-align:center;
    gap: var(--space-3);
    padding: var(--space-10) var(--space-6);
    border:1px dashed var(--border);
    border-radius: var(--radius-lg);
    color: var(--text-secondary);
  }
  .empty-state .icon-wrap{
    width:44px; height:44px; border-radius:50%;
    background: var(--surface); border:1px solid var(--border);
    display:flex; align-items:center; justify-content:center;
  }
  .empty-state .icon-wrap svg{ width:19px; height:19px; stroke: var(--text-tertiary); }
  .empty-state h3{ font-size: var(--text-sm); color: var(--text-primary); font-weight:600; }
  .empty-state p{ font-size: var(--text-xs); max-width:34ch; }

  /* — SkeletonCard — */
  @keyframes shimmer{ 0%{ opacity:.55 } 50%{ opacity:1 } 100%{ opacity:.55 } }
  .skel-cover, .skel-line{ background: var(--surface-hover); border-radius: var(--radius-xs); animation: shimmer 1.6s ease-in-out infinite; }
  .skeleton-card{ background: var(--surface); border:1px solid var(--border); border-radius: var(--radius-md); overflow:hidden; display:flex; flex-direction:column; }
  .skel-cover{ aspect-ratio:3/4; border-radius:0; }
  .skel-body{ padding: var(--space-3); display:flex; flex-direction:column; gap: var(--space-2); }
  .skel-line{ height:9px; }
  .skel-line.w-80{ width:80%; }
  .skel-line.w-50{ width:50%; }
  .skel-line.w-100{ width:100%; height:5px; margin-top:6px; }
  @media (prefers-reduced-motion: reduce){
    .skel-cover, .skel-line{ animation:none; opacity:.7; }
  }

  /* ============ TOKEN REFERENCE (appendix) ============ */
  .tokens-appendix{
    border-top:1px solid var(--border);
    padding-top: var(--space-8);
    display:flex; flex-direction:column; gap: var(--space-8);
  }
  .tokens-appendix > .appendix-head{ display:flex; flex-direction:column; gap:4px; }
  .appendix-head h2{ font-size: var(--text-lg); }
  .appendix-head p{ font-size: var(--text-sm); color: var(--text-secondary); max-width:70ch; }

  .swatch-grid{ display:grid; grid-template-columns: repeat(auto-fill, minmax(150px,1fr)); gap: var(--space-3); }
  .swatch{ border:1px solid var(--border); border-radius: var(--radius-md); overflow:hidden; background: var(--surface); }
  .swatch-fill{ height:52px; }
  .swatch-meta{ padding: var(--space-2) var(--space-3); display:flex; flex-direction:column; gap:1px; }
  .swatch-meta b{ font-size: var(--text-xs); }
  .swatch-meta span{ font-family: var(--font-mono); font-size:10.5px; color: var(--text-tertiary); }

  .type-specimen{ display:flex; flex-direction:column; gap: var(--space-3); }
  .type-row{ display:flex; align-items:baseline; gap: var(--space-4); padding: var(--space-2) 0; border-bottom:1px solid var(--border-subtle); }
  .type-row .tag{ width:150px; flex:none; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-tertiary); }
  .type-row .sample{ color: var(--text-primary); font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

  .misc-specimen-grid{ display:grid; grid-template-columns: repeat(auto-fit, minmax(220px,1fr)); gap: var(--space-6); }
  .radius-row, .shadow-row{ display:flex; align-items:center; gap: var(--space-3); padding: var(--space-2) 0; }
  .radius-box{ width:44px; height:44px; background: var(--surface); border:1px solid var(--border-strong); flex:none; }
  .shadow-box{ width:60px; height:44px; background: var(--surface); border:1px solid var(--border); flex:none; border-radius: var(--radius-sm); }
  .spec-label{ font-size: var(--text-xs); color: var(--text-secondary); }
  .spec-label .mono{ display:block; color: var(--text-tertiary); font-size:10.5px; }

  /* ============ GAME PAGE ============ */
  #view-library{ display:flex; flex-direction:column; gap: var(--space-8); }
  #view-game{ display:flex; flex-direction:column; gap: var(--space-6); }

  .back-link{
    display:inline-flex; align-items:center; gap:6px; align-self:flex-start;
    background:none; border:none; cursor:pointer;
    font-family: inherit; font-size: var(--text-sm); font-weight:600;
    color: var(--text-secondary); padding: var(--space-1) 0;
  }
  .back-link:hover{ color: var(--accent-fg); }
  .back-link svg{ width:15px; height:15px; stroke:currentColor; }

  /* — Game header — */
  .game-header{
    position:relative;
    background: var(--surface);
    border:1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--space-6);
    display:flex;
    align-items:center;
    flex-wrap:wrap;
    gap: var(--space-6);
  }
  /* — Оценка сайта: приколота к верхнему правому углу шапки — */
  .game-header-score{
    position:absolute; top: var(--space-5); right: var(--space-6);
    display:flex; flex-direction:column; align-items:flex-end; gap:1px;
  }
  .game-header-cover{
    width:144px; aspect-ratio:3/4; flex:none;
    border-radius: var(--radius-md);
    position:relative; overflow:hidden;
    display:flex; align-items:center; justify-content:center;
    background-image: repeating-linear-gradient(135deg, rgba(255,255,255,.05) 0 2px, transparent 2px 14px);
  }
  .game-header-cover .mono-letters{
    font-family: var(--font-mono); font-weight:700; font-size:3.2rem; letter-spacing:-0.03em;
    color: rgba(255,255,255,.16);
  }

  /* — Обложка + личная оценка кубками под ней — */
  .game-header-cover-col{ display:flex; flex-direction:column; align-items:center; gap:10px; width:144px; flex:none; }
  .game-header-cover-col .game-header-cover{ width:100%; }

  /* Личная оценка 1–10: 5 кубков по 2 балла каждый (половина = нечётное
     значение). Цвет заливки — по тиру итоговой оценки: 1-3 бронза, 4-6
     серебро, 7-9 золото, 10 — платина, у неё поверх ряда бежит блик. */
  .cup-rating{ display:flex; flex-direction:column; align-items:center; gap:6px; }
  .cup-rating-icons{ position:relative; display:flex; gap:5px; }
  .cup-slot{ --cup-size:26px; position:relative; width:var(--cup-size); height:var(--cup-size); flex:none; }
  .cup-slot .cup-bg{ position:absolute; inset:0; width:100%; height:100%; stroke: var(--border-strong); fill:none; }
  .cup-slot .cup-fill-wrap{
    position:absolute; top:0; left:0; height:100%; width:0%;
    overflow:hidden; color: var(--text-tertiary);
    transition: width .15s ease;
  }
  .cup-slot .cup-fill-wrap svg{ position:absolute; top:0; left:0; width:var(--cup-size); height:var(--cup-size); fill:none; stroke: currentColor; }
  .cup-rating.tier-bronze .cup-fill-wrap{ color: var(--tier-bronze); }
  .cup-rating.tier-silver .cup-fill-wrap{ color: var(--tier-silver); }
  .cup-rating.tier-gold .cup-fill-wrap{ color: var(--tier-gold); }
  .cup-rating.tier-platinum .cup-fill-wrap{ color: var(--tier-platinum); }
  .cup-hit{ position:absolute; top:0; bottom:0; width:50%; background:none; border:none; padding:0; margin:0; cursor:pointer; }
  .cup-hit--left{ left:0; }
  .cup-hit--right{ right:0; }
  .cup-rating-label{ font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-secondary); }
  .cup-rating-label .tier-name{ color: var(--text-tertiary); }
  /* блик на платине — заведён на каждый кубок отдельно и обрезан маской
     по силуэту i-trophy, поэтому светится именно кубок, а не весь ряд. */
  .cup-rating.tier-platinum .cup-slot::after{
    content:"";
    position:absolute; inset:0;
    mask: url(#cup-trophy-mask); -webkit-mask: url(#cup-trophy-mask);
    mask-repeat:no-repeat; -webkit-mask-repeat:no-repeat;
    background: linear-gradient(100deg, transparent 42%, rgba(255,255,255,.85) 50%, transparent 58%);
    background-size:260% 100%;
    animation: cup-shine 2.4s ease-in-out infinite;
    pointer-events:none;
    mix-blend-mode: screen;
  }
  @keyframes cup-shine{
    0%{ background-position: 140% 0; }
    65%{ background-position: -40% 0; }
    100%{ background-position: -40% 0; }
  }
  @media (prefers-reduced-motion: reduce){
    .cup-rating.tier-platinum .cup-slot::after{ animation:none; }
  }

  /* — Статус игры под обложкой: та же пилюля-<select>, растянута по
       ширине обложки, без заливки — и со стрелкой раскрытия справа. — */
  .game-status-picker{ position:relative; width:100%; }
  .game-status-picker select.status-badge{
    width:100%; justify-content:center; text-align:center;
    background:none; border-color: var(--border);
    border-radius: var(--radius-sm);
    padding: 5px 24px;
  }
  .game-status-picker select.status-badge:hover{ background: var(--surface-hover); }
  .game-status-caret{
    position:absolute; right:9px; top:50%; transform:translateY(-50%);
    width:12px; height:12px; stroke: var(--text-tertiary);
    pointer-events:none;
  }
  /* Полупрозрачные строки в раскрытом списке — только у этого пикера. */
  .game-status-picker select.status-badge option{
    background: rgba(30,33,40,.72);
    color: var(--text-primary);
  }

  .game-header-info{ display:flex; flex-direction:column; gap:8px; flex:1; min-width:220px; align-self:flex-start; }
  .game-header-title-row{ display:flex; align-items:center; gap: var(--space-3); flex-wrap:wrap; }
  .game-header-info h1{ font-size: var(--text-xl); }
  .xp-pill{
    display:inline-flex; align-items:center;
    font-family: var(--font-mono); font-weight:700; font-size: var(--text-xs);
    color: var(--accent-fg); background: var(--accent-soft);
    border:1px solid var(--accent-border); border-radius: var(--radius-full);
    padding: 3px 10px; white-space:nowrap;
  }
  .game-header-meta{ display:flex; align-items:center; gap:6px; font-size: var(--text-xs); color: var(--text-tertiary); }
  .game-header-meta .sep{ opacity:.5; }
  .platform-tag{ display:inline-flex; align-items:center; gap:4px; }
  .platform-tag svg{ width:11px; height:11px; stroke:currentColor; }
  .game-header-row{ display:flex; align-items:center; gap: var(--space-4); flex-wrap:wrap; font-size: var(--text-xs); color: var(--text-secondary); }
  .game-header-row .stat-inline b{ font-family: var(--font-mono); color: var(--text-primary); font-weight:600; }

  .ach-ring-wrap{ display:flex; align-items:center; gap: var(--space-3); flex:none; }
  .ach-ring{ position:relative; width:72px; height:72px; flex:none; }
  .ach-ring svg{ width:100%; height:100%; transform:rotate(-90deg); }
  .ach-ring .ring-track{ fill:none; stroke: var(--border); stroke-width:6; }
  .ach-ring .ring-fill{ fill:none; stroke: var(--accent); stroke-width:6; stroke-linecap:round; }
  .ach-ring .ach-ring-pct{
    position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
    font-family: var(--font-mono); font-weight:700; font-size: var(--text-sm);
    color: var(--text-primary);
  }
  .ach-ring-text{ font-size: var(--text-xs); color: var(--text-secondary); }
  .ach-ring-text b{ font-family: var(--font-mono); color: var(--text-primary); }

  /* — Personal note (inline edit) — */
  .note-card{
    background: var(--surface);
    border:1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-4);
    display:flex; flex-direction:column; gap: var(--space-2);
  }
  .note-head{ display:flex; align-items:center; gap:6px; font-size: var(--text-xs); font-weight:600; color: var(--text-tertiary); text-transform:uppercase; letter-spacing:.06em; }
  .note-head svg{ width:13px; height:13px; stroke:currentColor; }
  .note-body{
    font-size: var(--text-sm); color: var(--text-primary); line-height:1.55;
    border:1px solid transparent; border-radius: var(--radius-sm);
    padding: var(--space-2); margin: calc(var(--space-2) * -1);
    outline:none; cursor:text;
    transition: border-color .12s ease, background-color .12s ease;
  }
  .note-body:hover{ background: var(--surface-hover); }
  .note-body:focus{ border-color: var(--accent-border); background: var(--surface-sunken); }
  .note-body:empty::before{ content: attr(data-placeholder); color: var(--text-tertiary); }

  /* — Game tabs — */
  .game-tabs{ display:flex; gap: var(--space-1); border-bottom:1px solid var(--border-subtle); }
  .game-tab{
    background:none; border:none; border-bottom:2px solid transparent;
    padding: var(--space-2) var(--space-1); margin-right: var(--space-4);
    font-family:inherit; font-size: var(--text-sm); font-weight:600;
    color: var(--text-secondary); cursor:pointer;
  }
  .game-tab:hover{ color: var(--text-primary); }
  .game-tab[aria-selected="true"]{ color: var(--accent-fg); border-bottom-color: var(--accent); }
  .tab-panel{ display:flex; flex-direction:column; gap: var(--space-5); }

  /* — Achievements toolbar — */
  .ach-toolbar{ display:flex; align-items:center; justify-content:space-between; gap: var(--space-3); flex-wrap:wrap; }
  .filter-toggle{
    display:inline-flex; align-items:center; gap:7px;
    padding: 6px 12px 6px 9px;
    border-radius: var(--radius-full);
    border:1px solid var(--border);
    background: var(--surface);
    color: var(--text-secondary);
    font-family:inherit; font-size: var(--text-xs); font-weight:600;
    cursor:pointer;
  }
  .filter-toggle .box{ width:13px; height:13px; border-radius:3px; border:1px solid var(--border-strong); flex:none; display:flex; align-items:center; justify-content:center; }
  .filter-toggle .box svg{ width:9px; height:9px; stroke: var(--bg); opacity:0; }
  .filter-toggle[aria-pressed="true"]{ background: var(--accent-soft); border-color: var(--accent-border); color: var(--accent-fg); }
  .filter-toggle[aria-pressed="true"] .box{ background: var(--accent); border-color: var(--accent); }
  .filter-toggle[aria-pressed="true"] .box svg{ opacity:1; stroke: var(--bg-elevated); }
  .sort-select{
    background: var(--surface); border:1px solid var(--border); color: var(--text-primary);
    font-family:inherit; font-size: var(--text-xs); padding: 6px 10px;
    border-radius: var(--radius-sm);
  }

  .ach-hidden-block{ display:flex; flex-direction:column; gap: var(--space-3); padding-top: var(--space-2); border-top:1px solid var(--border-subtle); }
  .ach-hidden-block h3{ font-size: var(--text-sm); font-weight:600; }
  .ach-row.is-hidden-ach .ach-text b{ font-style:italic; }
  .ach-row .reveal-tag{ font-size:10px; color: var(--text-tertiary); font-weight:500; }

  /* — «Показать ещё» под усечённым списком достижений — */
  .ach-show-more{
    display:flex; align-items:center; justify-content:center; gap:6px;
    width:100%; background:none; border:none; cursor:pointer;
    padding: var(--space-3) var(--space-4);
    font-family:inherit; font-size: var(--text-sm); font-weight:600;
    color: var(--text-secondary);
  }
  .ach-show-more:hover{ background: var(--surface-hover); color: var(--text-primary); }
  .ach-show-more svg{ width:14px; height:14px; stroke:currentColor; transition: transform .15s ease; }
  .ach-show-more[aria-expanded="true"] svg{ transform: rotate(180deg); }

  /* — Friends-on-this-game list — */
  .friend-game-list{ display:flex; flex-direction:column; border-top:1px solid var(--border-subtle); }
  .friend-game-row{
    display:grid;
    grid-template-columns: 38px 130px 108px 72px 60px 1fr;
    align-items:center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-2);
    border-bottom:1px solid var(--border-subtle);
  }
  .friend-game-row:hover{ background: var(--surface-hover); }
  .friend-game-row .friend-avatar{ width:38px; height:38px; font-size:11px; border-radius: var(--radius-sm); display:flex; align-items:center; justify-content:center; font-family:var(--font-mono); font-weight:700; color:var(--text-primary); flex:none; }
  .friend-game-row .fg-name{ font-size: var(--text-sm); font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .friend-game-row .fg-playtime{ font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-secondary); }
  .friend-game-row .fg-pct{ font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-secondary); }
  .friend-game-row .fg-note{ font-size: var(--text-xs); color: var(--text-tertiary); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-style:italic; }

  /* ============ COLLECTIONS PAGE ============ */
  #view-collections{ display:flex; flex-direction:column; gap: var(--space-8); }
  .stat-grid-5{ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

  .shelf{ display:flex; flex-direction:column; gap: var(--space-4); }
  .shelf-row{ display:flex; gap: var(--space-4); overflow-x:auto; padding-bottom:4px; }
  .shelf-row .game-card{ width:172px; flex:none; }

  .card-note{
    display:flex; align-items:center; gap:5px;
    font-size:10.5px; color: var(--text-tertiary); margin-top:2px;
  }
  .card-missing{ display:flex; flex-direction:column; gap:3px; margin-top:2px; }
  .card-missing .missing-label{ font-size:10px; text-transform:uppercase; letter-spacing:.05em; color: var(--text-tertiary); }
  .card-missing ul{ display:flex; flex-direction:column; gap:2px; }
  .card-missing li{
    font-size:10.5px; color: var(--text-secondary);
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
    padding-left:11px; position:relative;
  }
  .card-missing li::before{ content:"·"; position:absolute; left:2px; color: var(--text-tertiary); }

  /* — Roulette — */
  .roulette-card{
    background: var(--surface); border:1px solid var(--border); border-radius: var(--radius-md);
    padding: var(--space-5); display:flex; flex-direction:column; gap: var(--space-4);
  }
  .roulette-head{ display:flex; align-items:center; justify-content:space-between; gap: var(--space-3); flex-wrap:wrap; }
  .roulette-tabs{ display:flex; gap: var(--space-2); flex-wrap:wrap; }
  .roulette-tab{
    display:inline-flex; align-items:center; padding:6px 12px;
    border-radius: var(--radius-full); border:1px solid var(--border);
    background: var(--surface); color: var(--text-secondary);
    font-family:inherit; font-size: var(--text-xs); font-weight:600; cursor:pointer;
  }
  .roulette-tab[aria-checked="true"]{ background: var(--accent-soft); border-color: var(--accent-border); color: var(--accent-fg); }
  #rouletteSpin[disabled]{ opacity:.55; cursor:default; }

  .reel-wrap{
    position:relative; overflow:hidden;
    border:1px solid var(--border-subtle); border-radius: var(--radius-sm);
    background: var(--surface-sunken); padding: 12px 0;
  }
  .reel-pointer{ position:absolute; left:50%; top:0; bottom:0; width:2px; background: var(--accent); transform:translateX(-50%); z-index:2; }
  .reel-pointer::before, .reel-pointer::after{ content:""; position:absolute; left:50%; width:0; height:0; border-left:5px solid transparent; border-right:5px solid transparent; transform:translateX(-50%); }
  .reel-pointer::before{ top:-1px; border-top:6px solid var(--accent); }
  .reel-pointer::after{ bottom:-1px; border-bottom:6px solid var(--accent); }
  .reel-track{ display:flex; gap:10px; padding-left: calc(50% - 28px); will-change:transform; }
  .reel-tile{ flex:none; width:56px; aspect-ratio:3/4; border-radius: var(--radius-xs); position:relative; overflow:hidden;
    display:flex; align-items:center; justify-content:center;
    background-image: repeating-linear-gradient(135deg, rgba(255,255,255,.05) 0 2px, transparent 2px 14px);
    opacity:.5; transition: opacity .2s ease, box-shadow .2s ease, transform .2s ease;
  }
  .reel-tile span{ font-family: var(--font-mono); font-weight:700; font-size:13px; color: rgba(255,255,255,.7); }
  .reel-tile.is-winner{ opacity:1; box-shadow: 0 0 0 2px var(--accent); transform:scale(1.06); }

  .roulette-result{ display:flex; align-items:baseline; gap: var(--space-2); }
  .roulette-result .result-label{ font-size: var(--text-xs); color: var(--text-tertiary); }
  .roulette-result .result-title{ font-size: var(--text-md); font-weight:700; color: var(--text-primary); }

  /* ============ IMPORT PAGE ============ */
  #view-import{ display:flex; flex-direction:column; gap: var(--space-6); }
  .import-card{
    background: var(--surface); border:1px solid var(--border); border-radius: var(--radius-md);
    padding: var(--space-5); display:flex; flex-direction:column; gap: var(--space-4);
  }
  .import-card h2{ font-size: var(--text-md); }
  .import-card .subtitle{ font-size: var(--text-xs); color: var(--text-tertiary); margin-top:-8px; }

  .sync-progress-label{ display:flex; justify-content:space-between; align-items:baseline; font-size: var(--text-xs); color: var(--text-secondary); }
  .sync-progress-label b{ font-family: var(--font-mono); color: var(--text-primary); }
  .sync-progress-track{ height:9px; background: var(--surface-sunken); border:1px solid var(--border-subtle); border-radius: var(--radius-full); overflow:hidden; }
  .sync-progress-fill{ height:100%; background: var(--accent); border-radius: var(--radius-full); }

  .sync-current{ display:flex; align-items:center; gap:9px; font-size: var(--text-sm); color: var(--text-secondary); }
  .sync-current b{ color: var(--text-primary); }
  .pulse-dot{ width:8px; height:8px; border-radius:50%; background: var(--accent); flex:none; animation: pulse-dot 1.4s ease-in-out infinite; }
  @keyframes pulse-dot{ 0%,100%{ opacity:1; transform:scale(1); } 50%{ opacity:.4; transform:scale(.7); } }
  @media (prefers-reduced-motion: reduce){ .pulse-dot{ animation:none; } }

  .import-log{ display:flex; flex-direction:column; gap:2px; font-family: var(--font-mono); font-size:11.5px; max-height:220px; overflow-y:auto; }
  .import-log-row{ display:flex; gap: var(--space-3); padding:4px 2px; border-radius: var(--radius-xs); }
  .import-log-row:hover{ background: var(--surface-hover); }
  .import-log-row .ts{ color: var(--text-tertiary); flex:none; }
  .import-log-row .msg{ color: var(--text-secondary); }
  .import-log-row.is-warn .msg{ color: var(--status-dropped-fg); }
  .import-log-row .msg b{ color: var(--text-primary); font-weight:600; }

  .import-errors-note{ font-size: var(--text-xs); color: var(--text-secondary); }
  .import-error-row{ display:flex; align-items:flex-start; gap: var(--space-3); padding: var(--space-2) 2px; border-bottom:1px solid var(--border-subtle); }
  .import-error-row:last-child{ border-bottom:none; }
  .import-error-row svg{ width:15px; height:15px; flex:none; margin-top:2px; stroke: var(--status-dropped-fg); }
  .import-error-row .err-text{ display:flex; flex-direction:column; gap:1px; }
  .import-error-row .err-text b{ font-size: var(--text-xs); font-weight:600; }
  .import-error-row .err-text span{ font-size: var(--text-2xs); color: var(--text-tertiary); }

  .import-divider{ display:flex; align-items:center; gap: var(--space-3); color: var(--text-tertiary); font-size: var(--text-2xs); text-transform:uppercase; letter-spacing:.06em; }
  .import-divider::before, .import-divider::after{ content:""; flex:1; height:1px; background: var(--border); }

  .import-private{
    background: var(--surface); border:1px solid var(--status-dropped-bd); border-radius: var(--radius-md);
    padding: var(--space-5); display:flex; gap: var(--space-4);
  }
  .import-private .icon-wrap{
    width:40px; height:40px; border-radius:50%; flex:none;
    background: var(--status-dropped-bg); border:1px solid var(--status-dropped-bd);
    display:flex; align-items:center; justify-content:center;
  }
  .import-private .icon-wrap svg{ width:18px; height:18px; stroke: var(--status-dropped-fg); }
  .import-private-body{ display:flex; flex-direction:column; gap: var(--space-3); flex:1; }
  .import-private-body h3{ font-size: var(--text-md); }
  .import-private-body > p{ font-size: var(--text-sm); color: var(--text-secondary); }
  .import-private-steps{ display:flex; flex-direction:column; gap:6px; counter-reset: step; }
  .import-private-steps li{ display:flex; gap: var(--space-2); font-size: var(--text-xs); color: var(--text-secondary); counter-increment: step; }
  .import-private-steps li::before{
    content: counter(step); flex:none; width:18px; height:18px; border-radius:50%;
    background: var(--surface-hover); color: var(--text-primary); font-family: var(--font-mono); font-size:10px; font-weight:700;
    display:flex; align-items:center; justify-content:center;
  }

  .btn-primary{
    align-self:flex-start;
    background: var(--accent); color: var(--bg-elevated); border:none;
    border-radius: var(--radius-sm); padding: 8px 14px;
    font-family:inherit; font-size: var(--text-sm); font-weight:600; cursor:pointer;
  }
  .btn-primary:hover{ filter:brightness(1.08); }

  /* ============ RESPONSIVE ============ */
  @media (max-width: 980px){
    .brand small{ display:none; }
    .page-layout{ grid-template-columns: 1fr; }
    .friend-rows{ flex-direction:row; flex-wrap:wrap; }
    .friend-row{ flex-direction:column; gap: var(--space-1); width:64px; text-align:center; }
    .friend-row .friend-name{ max-width:64px; }
    .game-row{ grid-template-columns: 30px 1fr 76px; }
    .row-progress, .row-platform, .game-row > .status-badge{ display:none; }
    .friend-game-row{ grid-template-columns: 38px 1fr 96px; }
    .friend-game-row .fg-pct, .friend-game-row .fg-note{ display:none; }
  }
  @media (max-width: 620px){
    .content{ padding: var(--space-4); }
    .topbar, .tabbar{ padding: 0 var(--space-3); }
    .topbar{ gap: var(--space-2); }
    .account-name{ display:none; }
    .nav-item span{ display:none; }
    .nav-item{ padding: 0 var(--space-2); }
    .stat-grid{ grid-template-columns: 1fr; }
    .card-grid{ grid-template-columns: repeat(auto-fill, minmax(130px,1fr)); }
    .profile-header{ padding: var(--space-4); }
    .profile-avatar{ width:68px; height:68px; font-size: var(--text-lg); }
    .level-ring{ width:48px; height:48px; }
    .game-header{ padding: var(--space-4); }
    .game-header-cover{ width:84px; }
    .game-header-cover-col{ width:84px; }
    .cup-slot{ --cup-size:15px; }
    .cup-rating-icons{ gap:2px; }
    .friend-game-row{ grid-template-columns: 38px 1fr; }
    .friend-game-row .fg-playtime{ display:none; }
  }

  /* ============================================================
     GAMELOG — дополнения к макету
     Всё, чего в статичном макете не было: обложки-картинки,
     формы входа и регистрации, служебные состояния Django.
     Значения берутся только из токенов выше.
     ============================================================ */

  /* — Шестой хранимый статус: «Играл». В макете его не было, поэтому
       токены и пилюля живут здесь, а не в блоке выше. Оттенок взят
       холоднее акцента и зеленее «Играю», чтобы на полосе распределения
       и в кольце эти три не слипались. — */
  :root{
    --status-played:        #4aa3b5;
    --status-played-fg:     #8ecbd8;
    --status-played-bg:     rgba(74,163,181,.14);
    --status-played-bd:     rgba(74,163,181,.38);
  }
  .status-badge.st-played{ color:var(--status-played-fg); background:var(--status-played-bg); border-color:var(--status-played-bd); }
  .status-badge.st-played .dot{ background:var(--status-played); }

  /* — Сотня отмечается атрибутом, а не статусом —
       Раньше «100%» был вычисляемым седьмым статусом: он подменял собой
       хранимый, из-за чего в списке библиотеки статус такой игры нельзя
       было сменить вовсе. Теперь пилюля всегда показывает хранимый статус,
       а сотня висит отдельным `data-perfect` — рамка и подсветка те же.

       Правила макета по [data-status="100"] остаются на месте мёртвыми:
       первый блок держим равным присланному макету. Медиазапрос тут не
       нужен — подсветку узкая раскладка не переопределяет, она правит
       только сетку колонок. */
  .game-card[data-perfect]{ border-color: var(--status-100-bd); box-shadow: 0 0 0 1px var(--status-100-bd) inset; }
  .game-card[data-perfect]:hover{ border-color: var(--status-100); box-shadow: 0 0 0 1px var(--status-100) inset, var(--shadow-md); }
  .game-row[data-perfect]{ background: var(--status-100-bg); box-shadow: inset 2px 0 0 var(--status-100); }
  .game-row[data-perfect]:hover{ background: var(--status-100-bg); filter:brightness(1.15); }

  /* — Текст статусной пилюли по центру —
       Пилюля и пилюля-<select> живут в колонках сетки и растягиваются на
       всю ширину колонки, а `<select>` вдобавок шире своего значения: он
       меряется по самому длинному варианту списка («Не в библиотеке»), и
       короткое «Играю» прилипало к левому краю. `text-align-last` нужен
       рядом с `text-align`: у select'а одна строка, и часть браузеров
       слушает только его. */
  .status-badge{ justify-content:center; }
  select.status-select{ text-align:center; text-align-last:center; }

  /* — Обложки: картинка ложится поверх плашки с инициалами.
       Если Steam CDN не отдал файл, onerror убирает <img>, и видно плашку. — */
  .row-cover, .recent-cover, .profile-avatar, .friend-avatar,
  .avatar, .cover-mini, .game-header-cover{ position:relative; overflow:hidden; }
  .cover img, .row-cover img, .recent-cover img, .game-header-cover img,
  .profile-avatar img, .friend-avatar img, .avatar img, .cover-mini img{
    position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  }
  .cover .cover-badge{ z-index:2; }

  /* — Ссылки вместо кнопок: разметка макета, семантика сайта — */
  a{ text-decoration:none; }
  a.game-card, a.game-row, a.recent-row, a.friend-row,
  a.nav-item, a.brand, a.account, a.status-badge, a.friend-game-row{ color:inherit; }
  a.game-row:hover, a.recent-row:hover, a.friend-row:hover{ background: var(--surface-hover); }
  a.status-badge{ cursor:pointer; transition:filter .12s ease, opacity .12s ease; }
  a.status-badge:hover{ filter:brightness(1.15); }
  a.status-badge:not(.is-active){ opacity:.55; }
  .link-inline{ color: var(--accent-fg); text-decoration: underline dotted; text-underline-offset:2px; }
  .link-inline:hover{ color: var(--accent); }
  /* Та же ссылка кнопкой — у действий, которые что-то меняют (POST). */
  button.link-inline{ background:none; border:0; padding:0; font:inherit; cursor:pointer; }

  /* — Кнопки — */
  .btn-ghost{
    display:inline-flex; align-items:center; gap: var(--space-2);
    background: var(--surface); color: var(--text-secondary);
    border:1px solid var(--border); border-radius: var(--radius-sm);
    padding: 7px 13px; font-family:inherit; font-size: var(--text-sm); font-weight:500; cursor:pointer;
  }
  .btn-ghost:hover{ background: var(--surface-hover); color: var(--text-primary); border-color: var(--border-strong); }
  .btn-ghost svg{ width:14px; height:14px; stroke:currentColor; }
  .btn-danger{ color: var(--status-dropped-fg); border-color: var(--status-dropped-bd); }
  .btn-danger:hover{ background: var(--status-dropped-bg); color: var(--status-dropped-fg); }
  a.btn-primary{ display:inline-flex; align-items:center; }
  .btn-row{ display:flex; flex-wrap:wrap; gap: var(--space-2); align-items:center; }
  .link-btn{
    background:none; border:none; padding:0; cursor:pointer;
    font-family:inherit; font-size: var(--text-2xs); color: var(--text-tertiary);
    text-decoration: underline dotted; text-underline-offset:2px;
  }
  .link-btn:hover{ color: var(--accent-fg); }

  /* — Формы: вход, регистрация, добавление друга — */
  .form-shell{ max-width:400px; width:100%; margin-inline:auto; display:flex; flex-direction:column; gap: var(--space-5); }
  .form-card{
    background: var(--surface); border:1px solid var(--border); border-radius: var(--radius-md);
    padding: var(--space-6); display:flex; flex-direction:column; gap: var(--space-4);
  }
  .form-card h1{ font-size: var(--text-lg); }
  .form-card .subtitle{ font-size: var(--text-xs); color: var(--text-tertiary); margin-top:-8px; }
  .field{ display:flex; flex-direction:column; gap:5px; }
  .field > label{ font-size: var(--text-2xs); font-weight:600; text-transform:uppercase; letter-spacing:.07em; color: var(--text-tertiary); }
  .field .helptext{ font-size: var(--text-2xs); color: var(--text-tertiary); }
  /* Селекторы намеренно узкие: у поиска в шапке своё оформление,
     и общее правило по типу поля перебивало бы его отступы. */
  .field input, .field textarea, .field select, .add-friend input{
    width:100%; background: var(--surface-sunken); color: var(--text-primary);
    border:1px solid var(--border); border-radius: var(--radius-sm);
    padding: 9px 11px; font-family:inherit; font-size: var(--text-sm);
  }
  .field input:focus, .field textarea:focus, .field select:focus, .add-friend input:focus{ outline:none; border-color: var(--accent-border); background: var(--bg-elevated); }
  .field textarea{ min-height:110px; resize:vertical; line-height:1.5; }
  .errorlist{ display:flex; flex-direction:column; gap:2px; }
  .errorlist li{ font-size: var(--text-2xs); color: var(--status-dropped-fg); }
  .field.has-error input{ border-color: var(--status-dropped-bd); }
  .form-foot{ font-size: var(--text-xs); color: var(--text-tertiary); text-align:center; }

  /* — Сообщения Django — */
  .messages{ display:flex; flex-direction:column; gap: var(--space-2); }
  .messages li{
    font-size: var(--text-xs); padding: 9px 13px;
    border-radius: var(--radius-sm); border:1px solid var(--border);
    background: var(--surface); color: var(--text-secondary);
  }
  .messages li.success{ border-color: var(--status-completed-bd); background: var(--status-completed-bg); color: var(--status-completed-fg); }
  .messages li.error{ border-color: var(--status-dropped-bd); background: var(--status-dropped-bg); color: var(--status-dropped-fg); }
  .messages li.warning{ border-color: var(--status-planned-bd); background: var(--status-planned-bg); color: var(--status-planned-fg); }

  /* — Гостевая главная — */
  .hero{
    background: var(--surface); border:1px solid var(--border); border-radius: var(--radius-lg);
    padding: var(--space-10) var(--space-8); display:flex; flex-direction:column; gap: var(--space-4);
    align-items:flex-start; max-width:720px; margin-inline:auto;
  }
  .hero h1{ font-size: var(--text-2xl); }
  .hero p{ font-size: var(--text-base); color: var(--text-secondary); max-width:52ch; }
  .hero ul{ display:flex; flex-direction:column; gap: var(--space-2); }
  .hero ul li{ font-size: var(--text-sm); color: var(--text-secondary); display:flex; gap: var(--space-2); }
  .hero ul li::before{ content:"—"; color: var(--text-tertiary); }

  /* — Плашка «Steam не подключён» и прочие подсказки — */
  .callout{
    display:flex; align-items:center; gap: var(--space-4); flex-wrap:wrap;
    background: var(--surface); border:1px solid var(--accent-border); border-radius: var(--radius-md);
    padding: var(--space-4) var(--space-5);
  }
  .callout .callout-text{ display:flex; flex-direction:column; gap:2px; flex:1; min-width:220px; }
  .callout b{ font-size: var(--text-sm); }
  .callout span{ font-size: var(--text-xs); color: var(--text-secondary); }

  /* — Отзывы — */
  .review-list{ display:flex; flex-direction:column; gap: var(--space-3); }
  .review{
    background: var(--surface); border:1px solid var(--border); border-radius: var(--radius-md);
    padding: var(--space-4); display:flex; flex-direction:column; gap: var(--space-2);
  }
  .review-head{ display:flex; align-items:center; gap: var(--space-2); font-size: var(--text-xs); color: var(--text-tertiary); }
  .review-head b{ color: var(--text-primary); font-size: var(--text-sm); }
  .review p{ font-size: var(--text-sm); color: var(--text-secondary); line-height:1.55; }

  /* — Мелочи — */
  .search form{ display:contents; }
  .inline-form{ display:inline-flex; align-items:center; gap: var(--space-2); }
  .friend-row-actions{ display:flex; align-items:center; gap: var(--space-2); }
  .friend-rows .friend-row{ justify-content:space-between; }
  .friend-row .friend-body{ display:flex; align-items:center; gap: var(--space-3); min-width:0; }
  .friend-text{ display:flex; flex-direction:column; gap:1px; min-width:0; }
  .friend-text .friend-sub{ font-size:10.5px; color: var(--text-tertiary); font-family: var(--font-mono); }
  .add-friend{ display:flex; gap: var(--space-2); align-items:flex-start; }
  .add-friend input{ font-size: var(--text-xs); padding: 6px 9px; }
  .stat-card.is-link:hover{ border-color: var(--border-strong); }
  .empty-state.is-compact{ padding: var(--space-6) var(--space-4); }

  /* — Градиенты аватаров-заглушек: у человека номер постоянный — */
  .tint-1{ background: linear-gradient(155deg, var(--cover-1), var(--cover-4)); }
  .tint-2{ background: linear-gradient(155deg, var(--cover-2), var(--cover-5)); }
  .tint-3{ background: linear-gradient(155deg, var(--cover-3), var(--cover-6)); }
  .tint-4{ background: linear-gradient(155deg, var(--cover-4), var(--cover-7)); }
  .tint-5{ background: linear-gradient(155deg, var(--cover-5), var(--cover-8)); }
  .tint-6{ background: linear-gradient(155deg, var(--cover-6), var(--cover-1)); }
  .tint-7{ background: linear-gradient(155deg, var(--cover-7), var(--cover-2)); }
  .tint-8{ background: linear-gradient(155deg, var(--cover-8), var(--cover-3)); }

  /* — Статус-пилюля, которая одновременно редактор: тот же вид, но <select> — */
  select.status-select{
    appearance:none; -webkit-appearance:none;
    cursor:pointer; font-family:inherit; width:auto;
    padding: 3px 9px; line-height:1.6;
  }
  select.status-select:hover{ filter:brightness(1.15); }
  select.status-select option{ background: var(--surface); color: var(--text-primary); }

  /* — Иконка достижения: картинка Steam поверх запасного кубка — */
  .ach-icon{ position:relative; overflow:hidden; }
  .ach-icon img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }

  /* Невыбитое достижение приезжает со Steam уже серой картинкой
     (icon_gray_url), а правило макета гасит её второй раз: прозрачность
     .4 поверх серого на тёмном фоне съедала иконку до пятна. Гасим
     заметно слабее. grayscale из макета остаётся — он нужен тем играм,
     у которых серой версии нет и в дело идёт цветная. */
  .ach-row.is-locked .ach-icon{ opacity:.72; }

  /* Игра на сотню: шапка получает ту же платиновую рамку, что карточка в
     сетке и строка в списке, только заметнее — это главный блок страницы.
     Цвет из семейства --status-100: «сотня» на всех экранах читается одним
     и тем же цветом. Признак — свой атрибут data-perfect, а не статус:
     статус теперь всегда хранимый и сотню собой не подменяет. */
  .game-header[data-perfect]{
    border-color: var(--status-100-bd);
    box-shadow: 0 0 0 1px var(--status-100-bd) inset, 0 0 26px -10px var(--status-100);
  }

  /* Платиновая оценка: над шапкой тихо сыплются кубки.
     Слой уходит под содержимое отрицательным z-index, а не подъёмом всех
     соседей: подъём делался через `position:relative` для всех детей и
     ломал «Оценку сайта» — она прибита к углу через `position:absolute`,
     и правило сбрасывало её в обычный поток, к левому краю.
     Отрицательный слой не проваливается за фон шапки, потому что
     `isolation` делает её собственным контекстом наложения; фон и рамка
     рисуются раньше отрицательных детей, а содержимое — позже. */
  .game-header{ isolation:isolate; }
  .platinum-snow{
    /* Один множитель на все кубки: на узком экране шапка ниже, и крупные
       кубки в ней смотрятся не снежком, а помехой. */
    --flake: 1;
    position:absolute; inset:0; z-index:-1;
    overflow:hidden; border-radius:inherit; pointer-events:none;
  }
  /* `backwards` обязателен: с положительной задержкой элемент до старта
     стоит в собственном виде — вверху и непрозрачный, — и кубки висели
     под рамкой, пока их очередь не подойдёт. С ним ещё до старта
     применяется нулевой кадр, где кубок поднят и прозрачен. */
  .platinum-snow span{
    position:absolute; top:0; display:block; opacity:0;
    animation: platinum-fall linear infinite backwards;
  }
  .platinum-snow svg{
    width:100%; height:100%; fill:none;
    stroke: var(--tier-platinum); stroke-width:1.4;
  }
  @keyframes platinum-fall{
    0%   { transform: translate3d(0, -48px, 0) rotate(-14deg); opacity:0; }
    12%  { opacity:.5; }
    85%  { opacity:.5; }
    100% { transform: translate3d(18px, 420px, 0) rotate(18deg); opacity:0; }
  }
  .platinum-snow span:nth-child(1){ left:3%; width:calc(22px * var(--flake)); height:calc(22px * var(--flake)); animation-duration:8s; animation-delay:0s; }
  .platinum-snow span:nth-child(2){ left:12%; width:calc(15px * var(--flake)); height:calc(15px * var(--flake)); animation-duration:11s; animation-delay:2.4s; }
  .platinum-snow span:nth-child(3){ left:21%; width:calc(26px * var(--flake)); height:calc(26px * var(--flake)); animation-duration:9.5s; animation-delay:5.1s; }
  .platinum-snow span:nth-child(4){ left:33%; width:calc(13px * var(--flake)); height:calc(13px * var(--flake)); animation-duration:12.5s; animation-delay:1.2s; }
  .platinum-snow span:nth-child(5){ left:44%; width:calc(30px * var(--flake)); height:calc(30px * var(--flake)); animation-duration:8.5s; animation-delay:6.3s; }
  .platinum-snow span:nth-child(6){ left:55%; width:calc(17px * var(--flake)); height:calc(17px * var(--flake)); animation-duration:10.5s; animation-delay:3.7s; }
  .platinum-snow span:nth-child(7){ left:66%; width:calc(28px * var(--flake)); height:calc(28px * var(--flake)); animation-duration:9s; animation-delay:7.8s; }
  .platinum-snow span:nth-child(8){ left:76%; width:calc(14px * var(--flake)); height:calc(14px * var(--flake)); animation-duration:12s; animation-delay:0.8s; }
  .platinum-snow span:nth-child(9){ left:86%; width:calc(24px * var(--flake)); height:calc(24px * var(--flake)); animation-duration:9.8s; animation-delay:4.5s; }
  .platinum-snow span:nth-child(10){ left:94%; width:calc(12px * var(--flake)); height:calc(12px * var(--flake)); animation-duration:11.5s; animation-delay:6.9s; }
  @media (max-width: 620px){
    .platinum-snow{ --flake: .6; }
  }
  @media (prefers-reduced-motion: reduce){
    /* Замереть на месте здесь некрасиво: десять кубков посреди шапки
       выглядят мусором. Убираем слой целиком — он декоративный. */
    .platinum-snow{ display:none; }
  }

  /* — Живой поиск в шапке. Список висит под полем; `.search` уже
       position:relative, так что достаточно прижать его к низу. — */
  .search-results{ position:absolute; top:calc(100% + 6px); left:0; right:0; z-index:20; }
  .search-panel{
    background: var(--bg-elevated);
    border:1px solid var(--border-strong);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    overflow:hidden auto;
    max-height:min(60vh, 420px);
  }
  .search-result{
    display:flex; align-items:center; gap: var(--space-3);
    padding: var(--space-2) var(--space-3); color:inherit;
  }
  .search-result:not(:last-child){ border-bottom:1px solid var(--border-subtle); }
  .search-result:hover, .search-result:focus-visible{ background: var(--surface-hover); }
  .search-result-text{ display:flex; flex-direction:column; gap:1px; min-width:0; flex:1; }
  .search-result-text b{
    font-size: var(--text-sm); font-weight:600;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .search-result-text span{
    font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-tertiary);
  }
  .search-result-all{ justify-content:center; font-size: var(--text-xs); color: var(--text-secondary); }
  .search-empty{
    padding: var(--space-4); text-align:center;
    font-size: var(--text-xs); color: var(--text-tertiary);
  }

  /* — Руководства по достижениям. Карточки в макете не было: сделана по
       образцу hltb-card, но строки здесь ссылки — длинное название в две
       строки слева, число плюсов справа. — */
  .guides-card{
    background: var(--surface);
    border:1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-4);
    display:flex; flex-direction:column; gap: var(--space-2);
  }
  .guide-list{ display:flex; flex-direction:column; }
  .guide-row:not(:last-child){ border-bottom:1px solid var(--border-subtle); }
  .guide-row a{
    display:flex; align-items:flex-start; justify-content:space-between;
    gap: var(--space-3); padding: var(--space-2) 3px; color:inherit;
  }
  .guide-row a:hover .guide-title{ color: var(--accent-fg); }
  .guide-title{
    font-size: var(--text-sm); color: var(--text-secondary); min-width:0;
    display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
  }
  .guide-votes{
    font-family: var(--font-mono); font-size: var(--text-xs);
    color: var(--text-tertiary); flex:none; padding-top:1px;
  }

  /* Строка критика — ссылка на источник; в макете это был просто span.
     В бейдже своя звезда вместо инициалов: логотипы источников — чужие
     знаки, а название и так написано рядом. */
  .critic-badge svg{ width:15px; height:15px; stroke:currentColor; fill:none; }
  a.critic-source{ color:inherit; }
  a.critic-source:hover .critic-name{ color: var(--accent-fg); }

  /* — «Друзья» —
       Блок переехал в правую колонку, а там 300 px: шестиколоночная строка
       макета (.friend-game-row) туда не влезает и больше не используется.
       Вместо неё карточка в две строки: имя со статусом, под ними цифры.
       Аватар занимает обе строки. — */
  .friend-card{
    background: var(--surface);
    border:1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-4);
    display:flex; flex-direction:column; gap: var(--space-2);
  }
  .friend-game-card{
    display:grid;
    grid-template-columns: 34px minmax(0,1fr) auto;
    align-items:center;
    column-gap: var(--space-3); row-gap:1px;
    padding: var(--space-2) 0;
    border-bottom:1px solid var(--border-subtle);
  }
  .friend-game-card:last-child{ border-bottom:0; padding-bottom:0; }
  .friend-game-card:hover .fgc-name{ color: var(--accent-fg); }
  .friend-game-card .friend-avatar{
    grid-row: 1 / span 2; width:34px; height:34px; font-size:11px;
    border-radius: var(--radius-sm);
    display:flex; align-items:center; justify-content:center;
    font-family: var(--font-mono); font-weight:700; color: var(--text-primary); flex:none;
  }
  .fgc-name{
    grid-column:2; font-size: var(--text-sm); font-weight:600;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .friend-game-card > .status-badge{ grid-column:3; grid-row:1; }
  .fgc-meta{
    grid-column: 2 / span 2;
    font-size: var(--text-2xs); color: var(--text-tertiary);
  }

  /* — Фильтры списка достижений —
       Ряд ссылок в шапке блока. Свой нейтральный вид, а не .status-badge:
       у той пилюли цвет всегда означает статус игры, и красить ею
       сортировку значило бы врать глазом. — */
  .ach-filters{ display:flex; flex-wrap:wrap; gap: var(--space-2); }
  .ach-filter{
    font-size: var(--text-2xs); font-weight:600; line-height:1.6;
    padding: 3px 10px; border-radius: var(--radius-full);
    border:1px solid var(--border); color: var(--text-tertiary);
    white-space:nowrap; transition: color .12s ease, border-color .12s ease, background-color .12s ease;
  }
  .ach-filter:hover{ color: var(--text-primary); border-color: var(--border-strong); }
  .ach-filter.is-active{
    color: var(--accent-fg); border-color: var(--accent-border); background: var(--accent-soft);
  }

  /* — Действия над аккаунтом в шапке: Steam и выход — */
  .topbar-actions{ display:flex; align-items:center; gap: var(--space-2); flex:none; }
  .topbar-actions .btn-ghost{ padding: 5px 10px; font-size: var(--text-xs); }
  .topbar-actions svg{ width:13px; height:13px; stroke:currentColor; }

  /* — Блок «Любимые игры»: панель на игру, под ней её достижения — */
  .favourites{ display:flex; flex-direction:column; gap: var(--space-4); }
  .favourites .ach-panel-head .status-badge{ flex:none; }
  .favourites .ach-panel-head-text a{ color:inherit; }
  .favourites .ach-panel-head-text a:hover{ color: var(--accent-fg); }
  .favourites .ach-icon{ width:44px; height:44px; }
  .favourites .ach-icon svg{ width:22px; height:22px; }

  /* Достижения в панели — только иконки в ряд. Название с описанием
     и рядность прячутся и всплывают подсказкой при наведении на иконку. */
  .favourites .ach-panel{ overflow:visible; }
  /* Шапка панели — широкий фон игры вместо иконки: картинка лежит под
     контентом, поверх неё градиент, иначе текст по ней не читается. */
  .favourites .ach-panel-head{
    position:relative;
    overflow:hidden;
    min-height:110px;
    padding: var(--space-4) var(--space-5);
    border-radius: var(--radius-md) var(--radius-md) 0 0;
  }
  .favourites .ach-panel-bg{
    position:absolute; inset:0; width:100%; height:100%;
    object-fit:cover; object-position:center;
  }
  .favourites .ach-panel-head::after{
    content:""; position:absolute; inset:0;
    background: linear-gradient(90deg,
      rgba(20,22,27,.95) 0%, rgba(20,22,27,.88) 42%, rgba(20,22,27,.5) 100%);
  }
  .favourites .ach-panel-head > *:not(.ach-panel-bg){ position:relative; z-index:1; }

  /* Текст в панели крупнее: блок читается с расстояния, а не только вблизи. */
  .favourites .ach-panel-head-text b{ font-size: var(--text-lg); }
  .favourites .ach-panel-head-text .note{ font-size: var(--text-sm); }

  /* Нижний блок панели — одна строка: иконки слева, статус и полоса
     справа, на том же уровне. На узком экране строка переносится, и
     margin-left:auto по-прежнему держит их у правого края. */
  .favourites .ach-panel-body{
    display:flex; align-items:center; flex-wrap:wrap;
    gap: var(--space-4);
    padding-right: var(--space-5);
  }
  .favourites .ach-panel-body > .ach-list,
  .favourites .ach-panel-body > .ach-empty{ flex:1; min-width:0; }
  .favourites .ach-panel-meta{
    display:flex; align-items:center; flex-wrap:wrap;
    gap: var(--space-4);
    margin-left:auto;
    padding: var(--space-4) 0;
  }
  .favourites .ach-panel-meta .progress{
    flex:none; width:300px; max-width:100%; margin-top:0;
  }
  .favourites .ach-panel-meta .progress-label{ font-size: var(--text-xs); }
  .favourites .ach-panel-meta .status-badge{ font-size: var(--text-xs); padding: 4px 11px 4px 9px; }

  /* Строка легенды в «Сводке» сама стала ссылкой в библиотеку с фильтром.
     На чужом профиле href нет — оформление не должно обещать переход. */
  .status-chart-legend a{ display:flex; align-items:center; gap:7px; color:inherit; }
  .status-chart-legend a[href]:hover{ color: var(--text-primary); }
  .status-chart-legend a[href]:hover .dot{ box-shadow: 0 0 0 3px var(--surface-hover); }
  .favourites .ach-list{
    display:flex;
    flex-direction:row;
    flex-wrap:wrap;
    align-items:flex-start;
    gap: var(--space-3);
    padding: var(--space-4);
  }
  .favourites .ach-list .ach-row{
    position:relative;
    flex:none;
    gap:0;
    padding:0;
    border-bottom:none;
  }
  .favourites .ach-list .ach-icon{ cursor:help; }

  /* Подсказка: название + описание над иконкой, редкость под ней. */
  .favourites .ach-list .ach-text,
  .favourites .ach-list .ach-meta{
    position:absolute;
    left:50%;
    width:220px;
    padding: var(--space-2) var(--space-3);
    background: var(--bg-elevated);
    border:1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    opacity:0;
    visibility:hidden;
    pointer-events:none;
    transition: opacity .12s ease, transform .12s ease, visibility 0s linear .12s;
    z-index:6;
  }
  .favourites .ach-list .ach-text{
    bottom: calc(100% + 8px);
    transform: translateX(-50%) translateY(4px);
  }
  .favourites .ach-list .ach-meta{
    top: calc(100% + 8px);
    min-width:0;
    text-align:left;
    align-items:flex-start;
    transform: translateX(-50%) translateY(-4px);
  }
  .favourites .ach-list .ach-row:hover .ach-text,
  .favourites .ach-list .ach-row:hover .ach-meta{
    opacity:1;
    visibility:visible;
    transform: translateX(-50%);
    transition: opacity .12s ease, transform .12s ease;
  }
  .ach-empty{
    padding: var(--space-4); font-size: var(--text-xs); color: var(--text-tertiary);
  }

  /* Правая колонка стала шире — обложки и аватары в ней тоже. */
  .page-aside .recent-cover{ width:36px; }
  .page-aside .recent-info b{ font-size: var(--text-sm); }
  .page-aside .recent-info span{ font-size: var(--text-xs); }
  .page-aside .friend-row .friend-avatar{ width:40px; height:40px; }
  .page-aside .friend-name{ font-size: var(--text-sm); color: var(--text-primary); }

  /* — Шестерёнка в шапке — */
  .icon-btn{
    display:inline-flex; align-items:center; justify-content:center;
    width:30px; height:30px; flex:none;
    border:1px solid transparent; border-radius: var(--radius-sm);
    color: var(--text-secondary);
  }
  .icon-btn svg{ width:17px; height:17px; stroke: currentColor; }
  .icon-btn:hover{ background: var(--surface); border-color: var(--border); color: var(--text-primary); }
  .icon-btn[aria-current="page"]{ color: var(--accent-fg); border-color: var(--accent-border); }
  /* Тумблер языка: глобус плюс код языка, на который переключаемся. */
  .icon-btn.lang-btn{ width:auto; gap:5px; padding:0 8px; font:inherit; font-size: var(--text-2xs); font-weight:600; letter-spacing:.04em; }
  .lang-form{ display:inline-flex; }

  /* — Страница настроек — */
  .settings{ display:flex; flex-direction:column; gap: var(--space-8); max-width:760px; }
  .settings-card{
    background: var(--surface); border:1px solid var(--border); border-radius: var(--radius-md);
    padding: var(--space-5); display:flex; flex-direction:column; gap: var(--space-4);
  }
  .settings-row{
    display:flex; align-items:center; gap: var(--space-3); flex-wrap:wrap;
    padding-bottom: var(--space-4); border-bottom:1px solid var(--border-subtle);
  }
  .settings-row-text{ display:flex; flex-direction:column; gap:2px; flex:1; min-width:200px; }
  .settings-row-text b{ font-size: var(--text-md); }
  .settings-row-text span{ font-size: var(--text-xs); color: var(--text-tertiary); }
  .settings-form{ display:flex; flex-direction:column; gap: var(--space-3); align-items:flex-start; }
  .settings-form .field{ width:100%; }
  .field-row{ display:flex; gap: var(--space-2); align-items:stretch; }
  .field-row input{ flex:1; }
  .settings-note{
    font-size: var(--text-xs); color: var(--text-tertiary); max-width:70ch; line-height:1.5;
  }
  .checkbox-row{ display:flex; align-items:flex-start; gap: var(--space-3); cursor:pointer; }
  .checkbox-row input{ margin-top:3px; width:16px; height:16px; accent-color: var(--accent); }
  .checkbox-row > span{ display:flex; flex-direction:column; gap:2px; }
  .checkbox-row b{ font-size: var(--text-sm); }
  .checkbox-row .helptext{ font-size: var(--text-2xs); color: var(--text-tertiary); }

  /* — Убрать игру из библиотеки —
       Последняя колонка строки: место под крестик резервируется всегда, иначе
       названия дёргались бы при наведении. Сам крестик виден только на строке
       под курсором и при фокусе с клавиатуры.

       Колонку добавляем только на широком экране: с 980px макет схлопывает
       строку до трёх колонок, и правка вне медиазапроса переехала бы поверх
       неё. Там крестика просто нет — удалять удобнее со страницы игры. */
  @media (min-width: 981px){
    .game-row{ grid-template-columns: 34px 1fr 96px 60px 88px 150px 22px; }
  }
  @media (max-width: 980px){
    .row-remove{ display:none; }
    /* На узком экране макет схлопывает строку до трёх колонок — оценка
       уезжает вместе с полосой достижений, иначе она встала бы во вторую
       строку сетки под обложкой. */
    .row-rating{ display:none; }
  }
  .row-remove button{
    width:22px; height:22px; display:flex; align-items:center; justify-content:center;
    background:none; border:0; padding:0; cursor:pointer; border-radius: var(--radius-sm);
    color: var(--text-tertiary); opacity:0;
    transition: opacity .1s ease, color .1s ease, background-color .1s ease;
  }
  .row-remove button svg{ width:13px; height:13px; stroke:currentColor; fill:none; }
  .game-row:hover .row-remove button,
  .row-remove button:focus-visible{ opacity:1; }
  .row-remove button:hover{ color: var(--status-dropped-fg); background: var(--surface-hover); }

  /* — Своя оценка в строке библиотеки —
       Числом, а не кубками: пять кубков рядом с часами и полосой достижений
       превратили бы строку в кашу, а цвет тира тот же, что у кубков на
       странице игры, — оценка узнаётся по нему и в списке.
       «/10» остаётся приглушённой: красить надо само число. */
  .row-rating{
    display:flex; align-items:center; justify-content:flex-end; gap:3px;
    font-family: var(--font-mono); font-size: var(--text-xs);
    color: var(--text-secondary); white-space:nowrap;
  }
  .row-rating svg{ width:12px; height:12px; stroke:currentColor; fill:none; flex:none; }
  .row-rating .row-rating-max{ color: var(--text-tertiary); }
  .row-rating.tier-bronze{ color: var(--tier-bronze); }
  .row-rating.tier-silver{ color: var(--tier-silver); }
  .row-rating.tier-gold{ color: var(--tier-gold); }
  .row-rating.tier-platinum{ color: var(--tier-platinum); }

  /* Выбор файла аватара. Нативную кнопку внутри input[type=file] красит
     только ::file-selector-button — без этого правила посреди тёмной
     карточки стоит светлая системная плашка. */
  .field input[type="file"]{ padding: 7px 10px; cursor:pointer; }
  .field input[type="file"]::file-selector-button{
    margin-right: var(--space-3); padding: 5px 10px; cursor:pointer;
    font:inherit; color: var(--text-secondary); background: var(--surface-hover);
    border:1px solid var(--border-subtle); border-radius: var(--radius-sm);
  }
  .field input[type="file"]::file-selector-button:hover{ color: var(--text-primary); }

  /* Описание игры из IGDB. Ширина строки ограничена: блок занимает всю
     основную колонку, а сплошной текст на 900 px читается плохо. */
  /* — Подвал шапки игры —
       Строка цифр про тебя уехала в самый низ карточки. Блок полной
       ширины: .game-header — flex с переносом, и flex-basis:100%
       отправляет подвал на свою строку, не трогая раскладку обложки,
       названия и кольца. — */
  .game-header-foot{
    flex-basis:100%; min-width:0;
    display:flex; flex-direction:column; gap: var(--space-4);
    padding-top: var(--space-4);
    border-top:1px solid var(--border-subtle);
  }

  /* — «Об игре» под годом и жанрами —
       Отступ сверху больше собственного gap колонки: описание — это уже
       не подпись к названию, а свой блок. Обложку при этом прижимаем к
       верху: с длинным описанием колонка становится высокой, и обложка,
       которую .game-header центрирует, повисала бы посреди карточки.
       Кольцо достижений оставляем по центру — сверху его место занято
       приколотой к углу «Оценкой сайта». — */
  .game-about-block{
    display:flex; flex-direction:column; gap: var(--space-2);
    margin-top: var(--space-2);
  }
  .game-about-block h2{ font-size: var(--text-md); }
  .game-header-cover-col{ align-self: flex-start; }

  /* — Прогресс достижений: четверть круга в углу карточки —
       Кольцо стояло в потоке справа и отъедало ширину у описания. В углу
       оно ничего не занимает: absolute, мышь не ловит (кроме подсказки со
       счётчиком), и не спорит с «Оценкой сайта» в противоположном углу.

       Дуга нарисована в координатах 120×120 с углом в точке (120,120), так
       что поворачивать SVG, как круглое кольцо, не нужно. Заливка идёт от
       нижнего края к правому: штрих начинается с начала пути. — */
  .ach-corner{
    /* Отступ от края: концы дуги лежат ровно на краях своей коробки, а
       круглый колпачок штриха выходит за них ещё на полтолщины. Без
       отступа он торчал бы за карточку. */
    position:absolute; right:10px; bottom:10px;
    width:116px; height:116px; pointer-events:none;
  }
  .ach-corner svg{ width:100%; height:100%; overflow:visible; }
  .quarter-track{ fill:none; stroke: var(--border); stroke-width:8; }
  .quarter-fill{
    fill:none; stroke: var(--accent); stroke-width:8; stroke-linecap:round;
  }
  .quarter-pct{
    fill: var(--text-primary);
    font-family: var(--font-mono); font-weight:700; font-size:25px;
  }
  .quarter-count{
    fill: var(--text-tertiary);
    font-family: var(--font-mono); font-weight:600; font-size:13px;
  }
  /* Сотня — платиновая: тот же цвет, что у рамки карточки и пилюли «100%». */
  .game-header[data-perfect] .quarter-fill{ stroke: var(--status-100); }

  /* — Знак Steam шире, чем выше —
       В квадратной коробке он вписывается по ширине, и на 10px от него
       остаётся 7,6px по высоте — рядом с текстом это уже пыль. Мелким
       местам добавлено по паре пикселей; ширина строки от этого не едет,
       коробка и так была в потоке. — */
  .cover .cover-badge svg, .row-platform svg{ width:13px; height:13px; }

  /* — Плашка платформы стала ссылкой на витрину —
       Значок подрос с 11 до 13px: на 11 он читался кляксой рядом со
       словом, а не значком. Цвет меняется только на наведении, чтобы в
       строке с годом и жанрами ссылка не кричала. — */
  .platform-tag svg{ width:13px; height:13px; }
  a.platform-tag:hover{ color: var(--accent-fg); }

  /* Строка цифр не должна заезжать под угол. */
  .game-header-foot{ padding-right:132px; }

  @media (max-width: 620px){
    /* Меньше 96px счётчик под процентом перестаёт читаться, а не просто
       мельчает: обе строки уезжают вниз вместе с коробкой. */
    .ach-corner{ right:8px; bottom:8px; width:96px; height:96px; }
    .game-header-foot{ padding-right:108px; }
  }
  .game-about{
    margin:0; padding:0;
    color: var(--text-secondary); font-size:.9rem; line-height:1.65; max-width:78ch;
  }

  /* ============ Рулетка на странице подборок ============
     Колесо рисуется одним SVG в координатах 240×240 и масштабируется
     шириной .wheel-box — никаких размеров в пикселях внутри. Цвета
     секторов — палитра плашек обложек из токенов, восемь штук по кругу. */
  .roulette-filters{
    display:flex; flex-wrap:wrap; gap: var(--space-3); align-items:flex-end;
  }
  .roulette-pools{ flex:1 1 280px; align-items:center; }
  .roulette-filters .field{ min-width:150px; }

  /* Пилюля-переключатель: тот же .status-badge из макета, но с радиокнопкой
     внутри. Саму кнопку убираем с глаз, а рамку фокуса возвращаем на
     пилюлю — иначе с клавиатуры не видно, что выбрано. */
  label.status-badge{ cursor:pointer; }
  label.status-badge:not(.is-active){ opacity:.55; }
  label.status-badge:hover{ filter:brightness(1.15); }
  label.status-badge input{ appearance:none; width:0; height:0; margin:0; border:0; }
  label.status-badge:has(input:focus-visible){ outline:2px solid var(--accent); outline-offset:2px; }

  /* Колесо — в средней колонке, карточка выпавшей игры в правой, левая
     пустая: боковые колонки равны, поэтому барабан стоит ровно посередине
     блока и не съезжает вбок, когда карточка появляется. Высота колонки с
     карточкой задана и равна колесу — иначе строка сетки росла бы в момент
     выпадения игры и блок подскакивал. 410px — карточка (352) плюс кнопка
     и отступ, с запасом на игру без достижений. */
  .roulette-stage{
    display:grid; grid-template-columns: 1fr auto 1fr;
    align-items:center; gap: var(--space-6);
  }

  .wheel-box{ grid-column:2; position:relative; width:min(410px, 62vw); aspect-ratio:1; }
  /* Пустой набор занимает место колеса, чтобы блок не менял размер. */
  .wheel-box-empty{ display:flex; align-items:center; justify-content:center; }
  .wheel{ width:100%; height:auto; transform-origin:50% 50%; transition: transform 4.2s cubic-bezier(.16,.84,.26,1); }
  /* Человеку, который выключил анимации, колесо доворачивается сразу;
     скрипт в этом случае и карточку показывает без задержки. */
  @media (prefers-reduced-motion: reduce){
    .wheel{ transition:none; }
  }
  /* Границы клиньев рисует .wheel-edge поверх обложки, плашке обводка не
     нужна — иначе под полупрозрачной картинкой проступала бы вторая линия. */
  .wheel-slice{ stroke:none; }
  .wheel-slice.t1{ fill: var(--cover-1); }
  .wheel-slice.t2{ fill: var(--cover-2); }
  .wheel-slice.t3{ fill: var(--cover-3); }
  .wheel-slice.t4{ fill: var(--cover-4); }
  .wheel-slice.t5{ fill: var(--cover-5); }
  .wheel-slice.t6{ fill: var(--cover-6); }
  .wheel-slice.t7{ fill: var(--cover-7); }
  .wheel-slice.t8{ fill: var(--cover-8); }
  /* Размер подписи — в координатах viewBox, не в пикселях экрана: SVG
     масштабируется целиком, и на широком колесе текст растёт вместе с ним. */
  /* Обложка в секторе — фон, а не картинка: приглушена и не перехватывает
     клики по колесу. Грань сектора рисуется поверх неё отдельным контуром,
     иначе картинка закрывала бы линию между клиньями. */
  .wheel-cover{
    opacity:.36; pointer-events:none;
    /* Светлые обложки без этого выбеливают свой клин и съедают подпись;
       тёмные от того же коэффициента почти не меняются. */
    filter: brightness(.78) saturate(.9);
    transition: opacity .12s ease, filter .12s ease;
  }
  /* Контур обрезан по своему же сектору, поэтому наружу торчит только
     внутренняя половина штриха. Это не косметика: соседний клин рисуется
     позже и закрывал бы обводку подсвеченного сектора с одной стороны —
     подсветка выходила бы разной толщины слева и справа. Ширина взята
     вдвое, чтобы видимая половина осталась прежней. */
  .wheel-edge{
    fill:none; stroke: var(--bg); stroke-width:3;
    transition: stroke .12s ease, stroke-width .12s ease;
  }

  /* Наведение на сектор: обводка акцентом, обложка ярче. Ловит вся группа —
     плашка, картинка и подпись, — поэтому клин подсвечивается целиком. */
  .wheel-sector:hover .wheel-edge{ stroke: var(--accent-fg); stroke-width:6; }
  .wheel-sector:hover .wheel-cover{ opacity:.55; filter: brightness(1) saturate(1); }
  .wheel-sector:hover .wheel-slice{ filter: brightness(1.2); }
  .wheel-label{
    font-family: var(--font-ui); font-size:8px; font-weight:600;
    fill: var(--text-primary); pointer-events:none;
    /* Тёмная обводка под буквами: поверх светлого места обложки белая
       подпись иначе теряется. paint-order кладёт обводку под заливку. */
    paint-order:stroke; stroke: rgba(0,0,0,.6); stroke-width:2px; stroke-linejoin:round;
  }
  .wheel-hole{ fill: var(--bg-elevated); stroke: var(--border-strong); }

  .wheel-pointer{
    position:absolute; top:-4px; left:50%; transform:translateX(-50%); z-index:2;
    width:0; height:0;
    border-left:9px solid transparent; border-right:9px solid transparent;
    border-top:18px solid var(--accent-fg);
    filter: drop-shadow(var(--shadow-sm));
  }
  .wheel-hub{
    position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); z-index:2;
    width:23%; height:23%; border-radius: var(--radius-full);
    background: var(--surface); color: var(--text-primary);
    border:1px solid var(--border-strong); box-shadow: var(--shadow-md);
    font-family:inherit; font-size: var(--text-2xs); font-weight:700;
    letter-spacing:.06em; text-transform:uppercase; cursor:pointer;
  }
  .wheel-hub:hover{ background: var(--surface-hover); color: var(--accent-fg); border-color: var(--accent-border); }

  /* Список выпавшего слева от колеса. Ширина та же, что у колонки с
     карточкой: боковые колонки сетки должны быть равны, иначе колесо
     перестанет стоять ровно посередине. Высота ограничена высотой колеса
     по той же причине, что и справа, — блок не должен расти. */
  .roulette-history{
    grid-column:1; width:182px; justify-self:end;
    max-height:410px; overflow:hidden;
    display:flex; flex-direction:column; gap: var(--space-2);
  }
  .roulette-history h3{ font-size: var(--text-sm); }
  .roulette-history .recent-row b{ font-size: var(--text-xs); }

  .roulette-prizes{
    grid-column:3; width:182px; min-height:410px;
    display:flex; flex-direction:column; justify-content:center; gap: var(--space-4);
  }
  /* Узкий экран: колонки в столбик, колесо сверху. Место под карточку тут
     не резервируем — на телефоне пустая треть экрана хуже, чем сдвиг. */
  @media (max-width: 900px){
    .roulette-stage{ grid-template-columns:1fr; justify-items:center; }
    .wheel-box, .roulette-prizes, .roulette-history{ grid-column:auto; justify-self:center; }
    .roulette-prizes{ min-height:0; }
    /* В столбик история уезжает вниз: сверху нужен барабан, а не список
       того, что выпало в прошлый раз. */
    .wheel-box{ order:1; }
    .roulette-prizes{ order:2; }
    .roulette-history{ order:3; max-height:none; }
  }
  .roulette-prize{ display:flex; flex-direction:column; gap: var(--space-3); align-items:flex-start; }
  /* Свой display перебивает браузерное [hidden]{display:none}: без этой
     строки на странице висят сразу все карточки барабана, а не выпавшая. */
  .roulette-prize[hidden]{ display:none; }
  .roulette-prize .game-card{ width:172px; }
  /* Кнопка во всю ширину карточки: макетное align-self:flex-start ужимало
     её до текста, и подпись ломалась на две строки посреди колонки. */
  .roulette-prize .btn-primary{ align-self:stretch; text-align:center; }

  /* — Лента событий: те же строки, что у «Недавних игр», плюс значок вида.
       Значок отдельным span, а не частью подписи: подпись переводится, а
       эмодзи в строке перевода живёт плохо. — */
  .event-mark{ margin-right:4px; line-height:1; }

  /* — Страница «Статистика»: гистограммы по месяцам.
       Цвет у каждого ряда свой и по смыслу: пройденные — цветом статуса
       «Пройдено», опыт — золотом трофейных тиров, достижения — акцентом.
       Ряд на графике один, поэтому легенды нет — ряд называет заголовок.
       Столбик ужат до 86% высоты поля: сверху остаётся место под число. — */
  .mchart{
    --bar: var(--accent);
    display:grid; grid-template-columns: repeat(12, minmax(0,1fr)); gap:2px;
    background: var(--surface); border:1px solid var(--border); border-radius: var(--radius-md);
    padding: var(--space-4) var(--space-4) var(--space-3);
  }
  .mchart-xp{ --bar: var(--tier-gold); }
  .mchart-launches{ --bar: var(--status-playing); }
  .mchart-completed{ --bar: var(--status-completed); }
  .mchart-col{
    display:flex; flex-direction:column; gap: var(--space-2);
    border-radius: var(--radius-xs); outline:none; cursor:default;
  }
  .mchart-col:focus-visible{ box-shadow: 0 0 0 2px var(--accent-border); }
  .mchart-plot{
    position:relative; height:160px;
    border-bottom:1px solid var(--border-strong);
  }
  .mchart-bar{
    position:absolute; left:14%; right:14%; bottom:0;
    height: calc(var(--h) * .86); min-height:2px;
    background: var(--bar); border-radius: 4px 4px 0 0;
    transition: filter .12s ease;
  }
  /* Столбик запусков сложен из кусков по играм. Куски идут сверху вниз в
     том же порядке, что строки в подсказке, и разделены линией фона, а не
     зазором: зазор на низком столбике съедал бы сам кусок. */
  .mchart-bar.is-split{ background:none; display:flex; flex-direction:column; overflow:hidden; }
  .mchart-seg{ flex:none; }
  .mchart-seg + .mchart-seg{ border-top:1px solid var(--surface); }

  /* Подсказка со списком игр: всплывает по наведению и по фокусу с
     клавиатуры. Отсчитывается от верха поля графика и растёт вниз, а не
     вверх над столбиком: список из восьми игр, поднятый над карточкой,
     уезжал за верх экрана. У крайних месяцев прижимается к своему краю —
     иначе половина уходила бы за карточку. */
  .mchart-col{ position:relative; }
  .mchart-tip{
    display:none; position:absolute; z-index:20;
    left:50%; transform:translateX(-50%); top:0;
    min-width:210px; max-width:280px;
    flex-direction:column; gap: var(--space-2);
    padding: var(--space-3);
    background: var(--bg-elevated); border:1px solid var(--border-strong);
    border-radius: var(--radius-md); box-shadow: var(--shadow-md);
    text-align:left; cursor:default;
  }
  .mchart-col:hover .mchart-tip, .mchart-col:focus-visible .mchart-tip{ display:flex; }
  .mchart-col:first-child .mchart-tip{ left:0; transform:none; }
  .mchart-col:last-child .mchart-tip{ left:auto; right:0; transform:none; }
  .mchart-tip-head{ font-size: var(--text-xs); color: var(--text-primary); }
  .mchart-tip-list{ display:flex; flex-direction:column; gap:5px; }
  .mchart-tip-row{
    display:grid; grid-template-columns: 8px 1fr auto; align-items:center; gap: var(--space-2);
    font-size: var(--text-2xs); color: var(--text-secondary);
  }
  .mchart-tip-row .dot{ width:8px; height:8px; border-radius:50%; }
  /* У опыта точек нет — цвет там ничего не значит, и колонка под них не нужна. */
  .mchart-tip-row.no-dot{ grid-template-columns: 1fr auto; }
  .mchart-tip-title{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .mchart-tip-num{ font-family: var(--font-mono); color: var(--text-tertiary); }
  .mchart-tip-more{ font-size: var(--text-2xs); color: var(--text-tertiary); }
  .mchart-col:hover .mchart-bar, .mchart-col:focus-visible .mchart-bar{ filter:brightness(1.2); }
  .mchart-value{
    position:absolute; left:0; right:0; bottom: calc(var(--h) * .86 + 4px);
    text-align:center; white-space:nowrap;
    font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-secondary);
    opacity:0; transition: opacity .12s ease;
  }
  .mchart-col.is-peak .mchart-value,
  .mchart-col:hover .mchart-value,
  .mchart-col:focus-visible .mchart-value{ opacity:1; }
  .mchart-col:hover .mchart-value, .mchart-col:focus-visible .mchart-value{ color: var(--text-primary); }
  .mchart-note{ font-size: var(--text-xs); color: var(--text-tertiary); max-width:70ch; margin:0; }
  .mchart-month{
    text-align:center; font-size: var(--text-2xs); color: var(--text-tertiary);
    text-transform: capitalize; white-space:nowrap; overflow:hidden;
  }
  @media (max-width: 620px){
    .mchart{ padding: var(--space-3) var(--space-2) var(--space-2); gap:1px; position:relative; }
    .mchart-plot{ height:120px; }
    /* На телефоне столбик уже подсказки, и центровать её по нему негде:
       подсказка растягивается на всю карточку графика. Для этого точкой
       отсчёта становится сама карточка, а не столбик. */
    .mchart-col{ position:static; }
    /* Правила для крайних месяцев специфичнее — их тоже надо перебить,
       иначе январь и декабрь останутся с шириной по содержимому. */
    .mchart-tip,
    .mchart-col:first-child .mchart-tip,
    .mchart-col:last-child .mchart-tip{
      left: var(--space-2); right: var(--space-2); transform:none;
      min-width:0; max-width:none;
    }
  }

  /* — Внешний вид профиля: выбор любимых игр —
       Полей под игры в разметке всегда шесть, лишние прячутся по выбранному
       количеству через :has — без скрипта. Браузер без :has покажет все
       шесть, а сервер всё равно возьмёт только первые N. */
  .fav-count{ max-width:240px; }
  .fav-slots{
    display:grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: var(--space-3); width:100%;
  }
  .fav-picker:has(select[name="count"] option[value="1"]:checked) .fav-slot:nth-child(n+2),
  .fav-picker:has(select[name="count"] option[value="2"]:checked) .fav-slot:nth-child(n+3),
  .fav-picker:has(select[name="count"] option[value="3"]:checked) .fav-slot:nth-child(n+4),
  .fav-picker:has(select[name="count"] option[value="4"]:checked) .fav-slot:nth-child(n+5),
  .fav-picker:has(select[name="count"] option[value="5"]:checked) .fav-slot:nth-child(n+6){ display:none; }
  .block-head a.hint:hover{ color: var(--text-secondary); }

  /* — Таблица лидеров —
       Сетка, а не <table>: строка целиком — ссылка на профиль, а <a>
       вокруг <tr> не бывает. Роли table/row/cell возвращают семантику.
       Места 1–3 — цвета кубков из токенов тиров. */
  .leader-list{
    display:flex; flex-direction:column;
    background: var(--surface); border:1px solid var(--border);
    border-radius: var(--radius-md); overflow:hidden;
  }
  .leader-row{
    display:grid;
    grid-template-columns: 40px minmax(0,1fr) 80px 110px 90px 90px;
    align-items:center; gap: var(--space-3);
    padding: var(--space-2) var(--space-4);
    border-bottom:1px solid var(--border-subtle);
  }
  .leader-row:last-child{ border-bottom:none; }
  a.leader-row{ color:inherit; }
  a.leader-row:hover{ background: var(--surface-hover); }
  .leader-row.is-me{ background: var(--accent-soft); }
  .leader-head{
    font-size: var(--text-2xs); color: var(--text-tertiary);
    text-transform: uppercase; letter-spacing:.04em; font-weight:600;
    padding-top: var(--space-3); padding-bottom: var(--space-3);
  }
  .leader-head > span:nth-child(n+3){ text-align:right; }
  .leader-head .is-sorted{ color: var(--accent-fg); }
  .leader-rank{
    font-family: var(--font-mono); font-weight:700; font-size: var(--text-sm);
    color: var(--text-tertiary); text-align:center;
  }
  .leader-row.rank-1 .leader-rank{ color: var(--tier-gold); }
  .leader-row.rank-2 .leader-rank{ color: var(--tier-silver); }
  .leader-row.rank-3 .leader-rank{ color: var(--tier-bronze); }
  .leader-player{ display:flex; align-items:center; gap: var(--space-3); min-width:0; }
  .leader-player .friend-avatar{
    width:36px; height:36px; flex:none; border-radius: var(--radius-sm);
    display:flex; align-items:center; justify-content:center;
    font-family: var(--font-mono); font-weight:700; font-size:10.5px;
    color: var(--text-primary);
  }
  .leader-name{
    font-size: var(--text-sm); font-weight:600;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .leader-you{
    flex:none; font-size: var(--text-2xs); color: var(--accent-fg);
    border:1px solid var(--accent-border); border-radius: var(--radius-full);
    padding: 0 var(--space-2);
  }
  .leader-num{
    font-family: var(--font-mono); font-size: var(--text-sm);
    color: var(--text-secondary); text-align:right; white-space:nowrap;
  }
  .leader-num.is-sorted{ color: var(--text-primary); font-weight:700; }
  .leader-label{ display:none; }
  .leader-gap{
    text-align:center; color: var(--text-tertiary);
    padding: var(--space-1); border-bottom:1px solid var(--border-subtle);
  }
  @media (max-width: 620px){
    /* На телефоне шести колонок не уместить: место и игрок — первой
       строкой, четыре числа — второй, каждое со своей подписью. */
    .leader-head{ display:none; }
    .leader-row{
      grid-template-columns: 28px repeat(4, minmax(0,1fr));
      row-gap: var(--space-2); column-gap: var(--space-2);
      padding: var(--space-3);
    }
    .leader-player{ grid-column: 2 / -1; }
    .leader-num{ grid-row:2; text-align:left; display:flex; flex-direction:column; gap:2px; }
    .leader-num:nth-child(3){ grid-column:2; }
    .leader-num:nth-child(4){ grid-column:3; }
    .leader-num:nth-child(5){ grid-column:4; }
    .leader-num:nth-child(6){ grid-column:5; }
    .leader-label{
      display:block; font-family: var(--font-ui); font-size: var(--text-2xs);
      color: var(--text-tertiary); font-weight:400;
      overflow:hidden; text-overflow:ellipsis;
    }
  }
