﻿/* ============================================================
   Icons -- self-hosted Lucide set (see js/shared/icons.js). Sizing/color
   come from width/height + currentColor on the <svg> itself; this rule is
   just the inline-with-text baseline fix every icon-as-svg-next-to-text
   layout needs (an inline SVG's default baseline sits noticeably below a
   text line otherwise).
   ============================================================ */
.icon{ vertical-align:middle; flex-shrink:0; }

/* ============================================================
   Card search input -- the "search my/their cards" box used by the
   Collection tab, the New Trade card picker (trades.html's #mySearch/
   #theirSearch), the admin Inventory viewer, and profile's card views.
   Previously only defined under index.css's Collection section, so every
   OTHER consumer (trades.html chief among them -- doesn't load index.css
   at all) silently got a completely unstyled browser-default <input>
   instead. Moved here since it's genuinely page-agnostic, and given a
   leading search-icon + focus glow to actually look designed rather than
   bare, matching the icon this project already self-hosts (js/shared/
   icons.js) -- inlined as a data-URI here rather than injected via JS
   since this is pure decoration with no interactive behavior of its own.
   ============================================================ */
.collection__search{ position:relative; }
.collection__search input{
  width:100%; max-width:360px; padding:11px 16px 11px 40px; border-radius:999px;
  border:1px solid var(--line); background:var(--ink-3); color:var(--paper);
  font-family:var(--font-body); font-size:0.88rem;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%239a968c' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m21 21-4.34-4.34'/%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:14px center;
  transition:border-color .2s var(--ease), box-shadow .2s var(--ease), background-color .2s var(--ease);
}
.collection__search input::placeholder{ color:var(--paper-dim); }
.collection__search input:focus{
  outline:none; border-color:var(--accent-dim); background-color:rgba(127,162,201,0.06);
  box-shadow:0 0 0 3px rgba(127,162,201,0.16);
}

/* ============================================================
   Layout shell
   ============================================================ */
.page{
  position:relative; z-index:1;
  min-height:100vh;
  display:flex;
  flex-direction:column;
}


/* ============================================================
   Top bar
   ============================================================ */
.topbar{
  display:grid;
  grid-template-columns:1fr auto 1fr;
  align-items:center;
  gap:16px;
  padding:26px clamp(20px,5vw,64px) 10px;
}
.topbar__side{ display:flex; align-items:center; gap:14px; position:relative; }
.topbar__side--left{ justify-content:flex-start; }
.topbar__side--right{ justify-content:flex-end; }

.lang-select{
  display:flex; align-items:center; gap:8px;
  background:rgba(236,231,220,0.04);
  border:1px solid var(--line);
  color:var(--paper-dim);
  padding:9px 14px;
  border-radius:999px;
  font-size:0.82rem;
  letter-spacing:0.02em;
  transition:border-color .25s var(--ease), color .25s var(--ease), background .25s var(--ease);
}
.lang-select:hover, .lang-select[aria-expanded="true"]{
  color:var(--paper); border-color:var(--accent-dim); background:rgba(127,162,201,0.08);
}
.lang-select__flag{ font-size:0.9rem; opacity:0.8; }
.lang-select__caret{ color:var(--paper-dim); transition:transform .25s var(--ease); }
.lang-select[aria-expanded="true"] .lang-select__caret{ transform:rotate(180deg); }

.lang-menu{
  position:absolute; top:calc(100% + 8px); left:0;
  list-style:none; margin:0; padding:6px;
  background:var(--ink-3);
  border:1px solid var(--line);
  border-radius:var(--radius-s);
  min-width:150px;
  box-shadow:0 18px 40px rgba(0,0,0,0.5);
  z-index:20;
}
.lang-menu[hidden]{ display:none; }
.lang-menu li{
  padding:9px 12px; border-radius:6px; font-size:0.85rem; color:var(--paper);
  display:flex; align-items:center; justify-content:space-between;
}
.lang-menu li[aria-selected="true"]{ background:rgba(127,162,201,0.12); color:var(--accent); }
.lang-menu li[aria-selected="true"]::after{ content:"✓"; }

.help-btn{
  display:flex; align-items:center; justify-content:center;
  width:34px; height:34px; border-radius:50%;
  background:rgba(236,231,220,0.04);
  border:1px solid var(--line);
  color:var(--paper-dim);
  font-family:var(--font-display);
  font-size:0.9rem;
  transition:border-color .25s var(--ease), color .25s var(--ease), background .25s var(--ease);
}
.help-btn:hover{ color:var(--paper); border-color:var(--accent-dim); background:rgba(127,162,201,0.08); }

.topbar__nav{
  display:flex; flex-wrap:wrap; gap:6px;
  background:rgba(236,231,220,0.035);
  border:1px solid var(--line);
  padding:5px;
  border-radius:999px;
}
/* Reused (with .admin-tabs, see below) as a plain tab strip on trades.html/
   moderation.html/admin.html -- shared here rather than in admin.css since
   moderation.html never loads admin.css but still carries this class. */
.admin-tabs{ display:flex; flex-wrap:wrap; gap:6px; margin-bottom:24px; }
.nav-pill{
  display:flex; align-items:center; gap:7px;
  border:none; background:transparent; color:var(--paper-dim);
  padding:10px 20px;
  border-radius:999px;
  font-size:0.86rem; font-weight:500; letter-spacing:0.01em;
  transition:color .25s var(--ease), background .3s var(--ease);
}
.nav-pill__icon{ font-size:0.8rem; opacity:0.75; }
.nav-pill:hover{ color:var(--paper); }
.nav-pill--active{
  background:linear-gradient(180deg, rgba(127,162,201,0.22), rgba(127,162,201,0.09));
  color:var(--paper);
  box-shadow:0 0 0 1px rgba(127,162,201,0.35) inset;
}
.nav-pill--active .nav-pill__icon{ color:var(--accent); opacity:1; }

.balance{
  display:flex; align-items:center; gap:8px;
  background:linear-gradient(180deg, rgba(205,166,95,0.12), rgba(205,166,95,0.04));
  border:1px solid rgba(205,166,95,0.28);
  padding:9px 16px;
  border-radius:999px;
  font-size:0.86rem; font-weight:600; color:var(--paper); letter-spacing:0.01em;
  transition:border-color .2s var(--ease), background .2s var(--ease);
}
.balance:hover{ border-color:rgba(205,166,95,0.5); background:linear-gradient(180deg, rgba(205,166,95,0.18), rgba(205,166,95,0.06)); }
.balance__coin{ color:var(--gold); font-size:0.78rem; }
.balance__amount{ font-variant-numeric:tabular-nums; transition:transform .2s var(--ease); }
.balance__amount.bump{ animation:balance-bump 380ms var(--ease); }
@keyframes balance-bump{
  0%{ transform:scale(1); color:var(--paper); }
  40%{ transform:scale(1.12); color:var(--gold); }
  100%{ transform:scale(1); color:var(--paper); }
}

.notif-btn{
  position:relative;
  display:flex; align-items:center; justify-content:center;
  width:38px; height:38px; border-radius:50%;
  background:rgba(236,231,220,0.04);
  border:1px solid var(--line);
  color:var(--paper-dim);
  transition:border-color .25s var(--ease), color .25s var(--ease), background .25s var(--ease);
}
.notif-btn:hover{ color:var(--paper); border-color:var(--accent-dim); background:rgba(127,162,201,0.08); }
.notif-btn[hidden]{ display:none; }
.notif-btn__badge{
  position:absolute; top:-3px; right:-3px;
  min-width:16px; height:16px; padding:0 4px;
  display:flex; align-items:center; justify-content:center;
  border-radius:999px;
  background:var(--gold);
  color:var(--ink);
  font-size:0.62rem; font-weight:700; line-height:1;
  box-shadow:0 0 0 2px var(--ink);
}
.notif-btn__badge[hidden]{ display:none; }

.notification-list{
  list-style:none; margin:0; padding:0;
  display:flex; flex-direction:column; gap:8px;
  max-height:52vh; overflow-y:auto;
}
.notification-item{
  display:flex; align-items:flex-start; gap:12px;
  padding:12px 14px;
  border-radius:var(--radius-s);
  border:1px solid var(--line);
  background:rgba(236,231,220,0.03);
}
.notification-item--unread{ border-color:var(--accent-dim); background:rgba(127,162,201,0.07); }
.notification-item--link{ cursor:pointer; transition:border-color .2s var(--ease); }
.notification-item--link:hover{ border-color:var(--accent-dim); }
.notification-item__icon{ font-size:1.2rem; line-height:1; flex-shrink:0; }
.notification-item__body{ min-width:0; }
.notification-item__text{ margin:0; font-size:0.86rem; color:var(--paper); line-height:1.5; }
.notification-item__time{ margin:3px 0 0; font-size:0.72rem; color:var(--paper-dim); }
.notification-empty{ font-size:0.9rem; color:var(--paper-dim); font-style:italic; }

.coin-history-list{
  list-style:none; margin:0; padding:0;
  display:flex; flex-direction:column; gap:8px;
  max-height:52vh; overflow-y:auto;
}
.coin-history-item{
  display:flex; align-items:center; gap:12px;
  padding:12px 14px; border-radius:var(--radius-s);
  border:1px solid var(--line); background:rgba(236,231,220,0.03);
}
.coin-history-item__amount{ flex-shrink:0; font-weight:700; font-variant-numeric:tabular-nums; min-width:70px; }
.coin-history-item__amount--pos{ color:#7fc97f; }
.coin-history-item__amount--neg{ color:#e08a8a; }
.coin-history-item__body{ min-width:0; display:flex; flex-direction:column; gap:2px; }
.coin-history-item__detail{ font-size:0.86rem; color:var(--paper); }
.coin-history-item__meta{ font-size:0.72rem; color:var(--paper-dim); }

.profile-btn{
  position:relative; width:44px; height:44px; border-radius:50%; border:none;
  background:var(--ink-3); display:flex; align-items:center; justify-content:center;
  color:var(--paper-dim); transition:color .25s var(--ease);
}
.profile-btn:hover{ color:var(--accent); }
.profile-btn__ring{ position:absolute; inset:0; width:100%; height:100%; }
.profile-btn__ring circle{ fill:none; stroke:var(--line); stroke-width:1.4; transition:stroke .25s var(--ease); }
.profile-btn:hover .profile-btn__ring circle{ stroke:var(--accent-dim); }
.profile-btn__emoji{ position:relative; z-index:1; font-size:20px; line-height:1; }

.profile-menu{
  position:absolute; top:calc(100% + 8px); right:0;
  list-style:none; margin:0; padding:6px;
  background:var(--ink-3);
  border:1px solid var(--line);
  border-radius:var(--radius-s);
  min-width:190px;
  box-shadow:0 18px 40px rgba(0,0,0,0.5);
  z-index:20;
}
.profile-menu[hidden]{ display:none; }
.profile-menu__user-info{
  display:flex; flex-direction:column; gap:1px;
  padding:8px 12px 10px; margin-bottom:4px;
  border-bottom:1px solid var(--line);
}
.profile-menu__user-info[hidden]{ display:none; }
.profile-menu__user-name{ font-size:0.85rem; color:var(--paper); font-weight:600; }
.profile-menu__user-email{ font-size:0.74rem; color:var(--paper-dim); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.profile-menu__item{
  width:100%; display:flex; align-items:center; gap:10px;
  padding:9px 12px; border-radius:6px; border:none; background:transparent;
  color:var(--paper); font-family:var(--font-body); font-size:0.85rem; text-align:left;
  text-decoration:none; transition:background .15s var(--ease), color .15s var(--ease);
}
/* Same [hidden]-vs-display:flex specificity tie as .btn (see above) -- without
   this, adminMenuLink.hidden = true (set for non-admins in applyAuthState)
   was silently ignored and the Admin link showed for everyone. */
.profile-menu__item[hidden]{ display:none; }
.profile-menu__item:hover{ background:rgba(127,162,201,0.1); color:var(--accent); }
.profile-menu__icon{ width:16px; height:16px; flex-shrink:0; color:var(--paper-dim); transition:color .15s var(--ease); }
.profile-menu__item:hover .profile-menu__icon{ color:var(--accent); }
.profile-menu__divider{ height:1px; margin:6px 4px; background:var(--line); }


.btn{
  border:1px solid var(--line); border-radius:999px; padding:15px 28px;
  font-size:0.92rem; font-weight:600; letter-spacing:0.01em;
  display:flex; align-items:center; gap:10px; text-decoration:none;
  transition:transform .2s var(--ease), box-shadow .3s var(--ease), border-color .25s var(--ease), background .25s var(--ease), opacity .2s var(--ease);
  background:transparent; color:var(--paper);
}
/* .btn's own display:flex has the same specificity as the browser's default
   [hidden]{display:none} rule, and author styles win ties over the UA
   stylesheet -- so a .btn toggled via the `hidden` DOM property (e.g.
   openFreePackBtn) would otherwise stay visible as an empty flex box. Same
   fix already applied to .wheel-fab below. */
.btn[hidden]{ display:none; }
.btn--primary{
  background:linear-gradient(180deg, #ddb977, var(--gold) 55%, var(--gold-dim));
  color:#1a1408; border:none;
  box-shadow:0 12px 28px rgba(205,166,95,0.28), inset 0 1px 0 rgba(255,255,255,0.35);
}
.btn--primary:hover{ transform:translateY(-2px); box-shadow:0 16px 34px rgba(205,166,95,0.4), inset 0 1px 0 rgba(255,255,255,0.4); }
.btn--primary:active{ transform:translateY(0); }
.btn--primary:disabled{ opacity:0.6; cursor:default; transform:none; }
.btn__cost{ display:flex; align-items:center; gap:5px; background:rgba(0,0,0,0.18); padding:3px 10px; border-radius:999px; font-size:0.82rem; }

.btn--danger{
  background:transparent; border:1px solid #e08a8a; color:#e08a8a;
}
.btn--danger:hover{ background:rgba(224,138,138,0.12); transform:translateY(-2px); }
.btn--danger:active{ transform:translateY(0); }

.btn__coin{ font-size:0.7rem; }

/* ============================================================
   Pagination -- shared by every "100 cards/page" surface (see
   pagination.js's createPager/renderPagerControls)
   ============================================================ */
.pager{ display:flex; gap:10px; align-items:center; justify-content:center; margin:20px 0; }
.pager__btn{
  border:1px solid var(--line); border-radius:999px; padding:8px 16px;
  background:rgba(236,231,220,0.03); color:var(--paper); font-size:0.82rem; font-weight:600;
  cursor:pointer; transition:border-color .2s var(--ease), color .2s var(--ease);
}
.pager__btn:hover:not(:disabled){ color:var(--accent); border-color:var(--accent-dim); }
.pager__btn:disabled{ opacity:0.4; cursor:not-allowed; }
.pager__indicator{ font-size:0.8rem; color:var(--paper-dim); min-width:70px; text-align:center; }


.btn--ghost{ background:rgba(236,231,220,0.03); color:var(--paper-dim); }
.btn--ghost:hover{ color:var(--paper); border-color:var(--accent-dim); background:rgba(127,162,201,0.06); }

.chip-row{ display:flex; flex-wrap:wrap; gap:8px; align-items:center; }
.chip-row__label{ font-size:0.76rem; color:var(--paper-dim); letter-spacing:0.06em; text-transform:uppercase; margin-right:4px; }
.chip{
  display:inline-flex; align-items:center; gap:6px;
  border:1px solid var(--line); background:rgba(236,231,220,0.03); color:var(--paper-dim);
  padding:8px 16px; border-radius:999px; font-size:0.8rem; font-weight:500;
  transition:color .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);
}
/* Same [hidden]-vs-display specificity tie as .btn above (see its comment)
   -- without this, a .chip toggled via the `hidden` DOM property (e.g.
   shopTitleTab in Browse mode) stays visible as an empty inline-flex box. */
.chip[hidden]{ display:none; }
.chip:hover{ color:var(--paper); border-color:var(--accent-dim); }
.chip--active{
  color:var(--paper); border-color:rgba(127,162,201,0.5); background:rgba(127,162,201,0.14);
}
.chip__count{
  font-size:0.7rem; font-weight:600; color:inherit; opacity:0.65;
  background:rgba(0,0,0,0.2); border-radius:999px; padding:1px 7px;
}
.chip--active .chip__count{ opacity:0.85; }
.chip__sort-arrow{ font-size:0.68rem; color:var(--gold); line-height:1; }
.chip__sort-arrow[hidden]{ display:none; }

.collection__grid{
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(180px, 1fr));
  gap:16px;
}
.collection__empty{ grid-column:1/-1; text-align:center; color:var(--paper-dim); font-size:0.9rem; padding:60px 0; }


.wiki-card{
  position:relative;
  border-radius:var(--radius-m);
  border:1px solid var(--line);
  background:linear-gradient(165deg, var(--ink-2), var(--ink));
  overflow:hidden;
  cursor:pointer;
  transition:transform .25s var(--ease), border-color .25s var(--ease), box-shadow .25s var(--ease);
  display:flex; flex-direction:column;
}
.wiki-card:hover{ transform:translateY(-4px); }
.wiki-card__thumb{
  width:100%; aspect-ratio:4/3; object-fit:cover; display:block;
  background:var(--ink-3);
  border-bottom:1px solid var(--line);
}
.wiki-card__thumb--placeholder{
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font-display); font-size:2rem; color:var(--paper-dim);
}

.wiki-card__body{ padding:12px 14px 14px; display:flex; flex-direction:column; gap:8px; flex:1; }
.wiki-card__title{ font-size:0.86rem; font-weight:600; line-height:1.3; color:var(--paper); }
.wiki-card__meta{ display:flex; align-items:center; gap:6px; font-size:0.68rem; color:var(--paper-dim); }
.wiki-card__id{ font-variant-numeric:tabular-nums; }

.wiki-card__copies{ font-variant-numeric:tabular-nums; color:var(--gold); }

.wiki-card__fav{
  position:absolute; top:8px; right:8px; z-index:2;
  width:26px; height:26px; display:flex; align-items:center; justify-content:center;
  border-radius:999px; border:1px solid var(--line);
  background:rgba(7,7,10,0.75); backdrop-filter:blur(3px);
  color:var(--paper-dim); font-size:0.82rem; line-height:1; cursor:pointer;
  transition:color .2s var(--ease), border-color .2s var(--ease), transform .15s var(--ease);
}
.wiki-card__fav:hover{ color:var(--gold); border-color:var(--gold-dim); transform:scale(1.08); }
.wiki-card__fav--active{ color:var(--gold); border-color:var(--gold-dim); background:rgba(205,166,95,0.14); }

.wiki-card__stats{ display:flex; flex-wrap:wrap; gap:6px; margin-top:auto; }
.stat-pill{
  display:flex; align-items:center; gap:4px; font-size:0.72rem; font-weight:600;
  padding:4px 8px; border-radius:6px; background:rgba(236,231,220,0.05); color:var(--paper);
}
.stat-pill--atk::before{ content:"⚔"; font-size:0.68rem; opacity:0.75; }
.stat-pill--hp::before{ content:"♥"; font-size:0.68rem; opacity:0.75; }
.stat-pill--armor::before{ content:"🛡"; font-size:0.68rem; opacity:0.75; }
.stat-pill--crit::before{ content:"💥"; font-size:0.68rem; opacity:0.75; }

.rarity-badge{
  position:absolute; top:10px; left:10px; z-index:2;
  font-size:0.66rem; font-weight:700; letter-spacing:0.04em;
  padding:4px 9px; border-radius:999px;
  background:rgba(7,7,10,0.75); backdrop-filter:blur(3px);
  border:1px solid currentColor;
}

/* "You already own a copy of this" -- shown on someone ELSE's cards (trade
   builder / public profile), never your own. Fixed offset to the right of
   .rarity-badge rather than measuring it (every rarity label is 1-2 chars,
   same static-offset approach .wiki-card__trade-lock already uses on the
   opposite corner). */
.wiki-card__dupe{
  position:absolute; top:10px; left:50px; z-index:2;
  width:22px; height:22px; display:flex; align-items:center; justify-content:center;
  border-radius:999px; border:1px solid var(--accent-dim);
  background:rgba(7,7,10,0.75); backdrop-filter:blur(3px);
  color:var(--accent); font-size:0.68rem; line-height:1;
}

/* rarity color mapping, shared by grid cards + reveal cards -- --r-current
   also feeds the persistent card glow below, so every place a rank shows up
   (text, badge border, or the card's own glow) pulls from the same ramp. */
[data-rarity="F"]  { color:var(--r-f);  --r-current:var(--r-f); }
[data-rarity="E"]  { color:var(--r-e);  --r-current:var(--r-e); }
[data-rarity="D"]  { color:var(--r-d);  --r-current:var(--r-d); }
[data-rarity="C"]  { color:var(--r-c);  --r-current:var(--r-c); }
[data-rarity="B"]  { color:var(--r-b);  --r-current:var(--r-b); }
[data-rarity="A"]  { color:var(--r-a);  --r-current:var(--r-a); }
[data-rarity="S"]  { color:var(--r-s);  --r-current:var(--r-s); }
[data-rarity="SS"] { color:var(--r-ss); --r-current:var(--r-ss); }

/* Persistent rarity glow -- one shared rule for every card-shaped surface
   (the generic card-tile picker used by Battle/Trades/Profile, pack-reveal
   cards, and Battle's own field cards) instead of the previous SS/S/A/B-
   only overrides duplicated per component. Reads as white-gray at the low
   end of the ramp through blue to gold at the top (see the --r-f..--r-ss
   tokens up top), via color-mix so there's no need for a second, alpha-
   baked rgba() per rank. Collection's .wiki-card keeps its own plain
   var(--line) border instead -- rarity there reads from the badge and stat
   pills, not from tinting the whole tile. */
.card-tile[data-rarity], .reveal-card[data-rarity], .battle-card[data-rarity]{
  border-color: color-mix(in srgb, var(--r-current) 55%, var(--line));
  box-shadow: 0 0 16px -4px color-mix(in srgb, var(--r-current) 55%, transparent);
}
.card-tile[data-rarity="SS"], .reveal-card[data-rarity="SS"], .battle-card[data-rarity="SS"]{
  box-shadow: 0 0 24px -2px color-mix(in srgb, var(--r-current) 65%, transparent);
}

.leaderboard{
  border:1px solid var(--line); border-radius:var(--radius-l);
  background:rgba(236,231,220,0.02); padding:24px clamp(18px,3vw,28px);
}
.leaderboard__header{ display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:12px; margin-bottom:18px; }
.leaderboard__title-group{ display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; }
.leaderboard__title{ margin:0; font-family:var(--font-display); font-weight:500; font-size:1.2rem; color:var(--paper); }
.leaderboard__countdown{ font-size:0.76rem; color:var(--paper-dim); font-variant-numeric:tabular-nums; }

.leaderboard__table-wrap{ overflow-x:auto; }
.leaderboard__table{ width:100%; border-collapse:collapse; font-size:0.85rem; }
.leaderboard__table th{
  text-align:left; padding:8px 12px; font-size:0.72rem; letter-spacing:0.06em; text-transform:uppercase;
  color:var(--paper-dim); border-bottom:1px solid var(--line);
}
.leaderboard__table td{ padding:10px 12px; border-bottom:1px solid var(--line); color:var(--paper); }
.leaderboard__empty{ text-align:center; color:var(--paper-dim); font-size:0.88rem; padding:36px 0; margin:0; }

/* Embedded-panel variant (Battle tab's own mode leaderboard + the Server
   Boss damage leaderboard) -- capped to roughly 10 data rows tall and
   scrollable, instead of pushing the whole page down to fit 49+ rows.
   NOT applied to the standalone leaderboards.html page or admin's account
   tables, which reuse the same .leaderboard__table markup but want their
   full height. */
.leaderboard__table-wrap--scroll{
  max-height:438px; overflow-y:auto; overflow-x:auto;
  border-radius:var(--radius-m);
}
.leaderboard__table-wrap--scroll .leaderboard__table thead th{
  position:sticky; top:0; z-index:1;
  background:var(--ink-2);
  box-shadow:0 1px 0 var(--line);
}
/* The viewer's own row, pinned via <tfoot> (see battle.js's loadLeaderboard)
   -- sticky to the bottom of the scroll area so it's always visible without
   scrolling, regardless of actual rank. Raised background + a brighter top
   border reads as "detached from the scrolling list above it", and the
   "Your rank" label row that precedes it (reuses .leaderboard__row--gap)
   makes that detachment explicit rather than just implied by position. */
.leaderboard__table-wrap--scroll tfoot{
  position:sticky; bottom:0; z-index:1;
}
.leaderboard__table-wrap--scroll tfoot .leaderboard__row--gap td{
  border-top:1px solid var(--gold-dim); border-bottom:none;
  padding:6px 12px 2px; font-size:0.66rem; letter-spacing:0.06em; text-transform:uppercase;
  color:var(--gold); background:var(--ink-3); text-align:left;
}
.leaderboard__table-wrap--scroll tfoot .leaderboard__row--me td{
  background:var(--ink-3); border-bottom:none;
}

/* Nice, themed scrollbars -- everywhere a panel scrolls internally instead
   of the bare OS default. One shared selector list rather than repeating
   these 4 rules per container (see each addition's own comment below for
   why it needed to join this list) -- .modal__panel alone is most of the
   win here, since nearly every modal on the site (Achievement Showcase
   picker included) inherits its scrollbar from that one base class rather
   than defining its own. Firefox via scrollbar-width/color, everything
   else via the ::-webkit-scrollbar family. */
.leaderboard__table-wrap--scroll,
.server-boss__history-list,
.modal__panel,
.notification-list,
.coin-history-list,
.detail-history__list,
.messages-layout__list,
.people-list,
.thread-active__messages,
.battle-picker__inventory,
.trade-builder__grid,
.leaderboard__table-wrap,
.help-table-wrap{
  scrollbar-width:thin;
  scrollbar-color:var(--gold-dim) transparent;
}
.leaderboard__table-wrap--scroll::-webkit-scrollbar,
.server-boss__history-list::-webkit-scrollbar,
.modal__panel::-webkit-scrollbar,
.notification-list::-webkit-scrollbar,
.coin-history-list::-webkit-scrollbar,
.detail-history__list::-webkit-scrollbar,
.messages-layout__list::-webkit-scrollbar,
.people-list::-webkit-scrollbar,
.thread-active__messages::-webkit-scrollbar,
.battle-picker__inventory::-webkit-scrollbar,
.trade-builder__grid::-webkit-scrollbar,
.leaderboard__table-wrap::-webkit-scrollbar,
.help-table-wrap::-webkit-scrollbar{
  width:8px; height:8px;
}
.leaderboard__table-wrap--scroll::-webkit-scrollbar-track,
.server-boss__history-list::-webkit-scrollbar-track,
.modal__panel::-webkit-scrollbar-track,
.notification-list::-webkit-scrollbar-track,
.coin-history-list::-webkit-scrollbar-track,
.detail-history__list::-webkit-scrollbar-track,
.messages-layout__list::-webkit-scrollbar-track,
.people-list::-webkit-scrollbar-track,
.thread-active__messages::-webkit-scrollbar-track,
.battle-picker__inventory::-webkit-scrollbar-track,
.trade-builder__grid::-webkit-scrollbar-track,
.leaderboard__table-wrap::-webkit-scrollbar-track,
.help-table-wrap::-webkit-scrollbar-track{
  background:transparent;
}
.leaderboard__table-wrap--scroll::-webkit-scrollbar-thumb,
.server-boss__history-list::-webkit-scrollbar-thumb,
.modal__panel::-webkit-scrollbar-thumb,
.notification-list::-webkit-scrollbar-thumb,
.coin-history-list::-webkit-scrollbar-thumb,
.detail-history__list::-webkit-scrollbar-thumb,
.messages-layout__list::-webkit-scrollbar-thumb,
.people-list::-webkit-scrollbar-thumb,
.thread-active__messages::-webkit-scrollbar-thumb,
.battle-picker__inventory::-webkit-scrollbar-thumb,
.trade-builder__grid::-webkit-scrollbar-thumb,
.leaderboard__table-wrap::-webkit-scrollbar-thumb,
.help-table-wrap::-webkit-scrollbar-thumb{
  background-color:var(--gold-dim);
  border-radius:999px;
  border:2px solid transparent;
  background-clip:padding-box;
}
.leaderboard__table-wrap--scroll::-webkit-scrollbar-thumb:hover,
.server-boss__history-list::-webkit-scrollbar-thumb:hover,
.modal__panel::-webkit-scrollbar-thumb:hover,
.notification-list::-webkit-scrollbar-thumb:hover,
.coin-history-list::-webkit-scrollbar-thumb:hover,
.detail-history__list::-webkit-scrollbar-thumb:hover,
.messages-layout__list::-webkit-scrollbar-thumb:hover,
.people-list::-webkit-scrollbar-thumb:hover,
.thread-active__messages::-webkit-scrollbar-thumb:hover,
.battle-picker__inventory::-webkit-scrollbar-thumb:hover,
.trade-builder__grid::-webkit-scrollbar-thumb:hover,
.leaderboard__table-wrap::-webkit-scrollbar-thumb:hover,
.help-table-wrap::-webkit-scrollbar-thumb:hover{
  background-color:var(--gold);
  background-clip:padding-box;
}

.leaderboard__rank{ font-variant-numeric:tabular-nums; color:var(--paper-dim); width:1%; white-space:nowrap; }
.leaderboard__medal{ font-size:1.05rem; }
.leaderboard__avatar{
  display:inline-flex; align-items:center; justify-content:center;
  width:24px; height:24px; margin-right:4px; border-radius:50%;
  font-size:0.9rem; vertical-align:middle;
}
/* Never blue, never underlined -- even on hover, which shifts to gold
   instead of a blue accent so it still reads as clickable without turning
   into a "visited link" blue anywhere in the app (covers this table --
   shared by the in-page Battle leaderboard, the standalone
   leaderboards.html, and admin.js's accounts table). */
.leaderboard__table a{ color:var(--paper); text-decoration:none; font-weight:500; }
.leaderboard__table a:hover{ color:var(--gold); }


.modal{ position:fixed; inset:0; z-index:50; display:flex; align-items:center; justify-content:center; padding:24px; }
/* Opened from a button inside #settingsModal without closing it first, so
   it needs to render above settings' own z-index:50, not just after it in
   DOM order. */
#blockedModal{ z-index:60; }
.modal[hidden]{ display:none; }
.modal__backdrop{
  position:absolute; inset:0; background:rgba(4,4,6,0.78); backdrop-filter:blur(6px);
  animation:backdrop-in .3s var(--ease);
}
@keyframes backdrop-in{ from{ opacity:0; } to{ opacity:1; } }

.modal__panel{
  position:relative; z-index:1; width:min(780px, 100%); max-height:88vh; overflow-y:auto;
  background:linear-gradient(180deg, var(--ink-3), var(--ink-2));
  border:1px solid var(--line); border-radius:var(--radius-l);
  padding:36px clamp(20px,4vw,44px) 40px; text-align:center;
  box-shadow:0 40px 90px rgba(0,0,0,0.6), 0 0 0 1px rgba(127,162,201,0.06);
  animation:panel-in .38s var(--ease);
}
@keyframes panel-in{
  from{ opacity:0; transform:translateY(18px) scale(0.97); }
  to{ opacity:1; transform:translateY(0) scale(1); }
}

.modal__close{
  position:absolute; top:16px; right:16px; width:34px; height:34px; border-radius:50%;
  border:1px solid var(--line); background:rgba(236,231,220,0.03); color:var(--paper-dim);
  display:flex; align-items:center; justify-content:center;
  transition:color .2s var(--ease), border-color .2s var(--ease);
}
.modal__close:hover{ color:var(--paper); border-color:var(--accent-dim); }

.modal__eyebrow{ margin:0 0 6px; font-size:0.7rem; letter-spacing:0.22em; text-transform:uppercase; color:var(--gold); }
.modal__title{ margin:0 0 30px; font-family:var(--font-display); font-weight:500; font-size:clamp(1.5rem, 3vw, 1.9rem); color:var(--paper); }

.modal__cta{ width:100%; justify-content:center; }
.modal__cta-row{ display:flex; gap:10px; }
.modal__cta-row .modal__cta{ width:auto; flex:1; }

.loading-line{
  display:flex; align-items:center; justify-content:center; gap:8px;
  padding:40px 0; color:var(--paper-dim); font-size:0.85rem;
}
.loading-dot{ width:6px; height:6px; border-radius:50%; background:var(--accent); animation:loading-bounce 1s ease-in-out infinite; }
.loading-dot:nth-child(2){ animation-delay:0.15s; }
.loading-dot:nth-child(3){ animation-delay:0.3s; }
@keyframes loading-bounce{ 0%,80%,100%{ opacity:0.3; transform:translateY(0); } 40%{ opacity:1; transform:translateY(-4px); } }

.modal__panel--detail{ text-align:left; max-width:520px; }
.modal__panel--settings{ text-align:left; }

/* .modal__panel--trade -- the wide, dual-grid modal shell shared by the New
   Trade card picker (trades.html) and the "Cards" view-all modal on
   someone else's profile (profile.html): both need real width for a
   multi-column card grid, not the narrow single-column .modal__panel--detail
   default just above. Lives here (not in trades.css, despite the class
   name) since profile.html never loads trades.css -- keeping this
   page-scoped left profile's own copy of the class silently doing nothing,
   stuck at .modal__panel--detail's 520px, showing barely 2 cards per row.

   `width` alone can't win here: max-width always clamps width down, never
   lets it through, so overriding max-width:none is required alongside it --
   without it every width bump above stays silently capped back to 520px by
   .modal__panel--detail's own max-width on the same element. Height is
   also given a taller budget than the base 88vh -- a two-column card grid's
   natural content height sits close enough to 88vh on a shorter laptop
   window that it could still trip the outer scrollbar even with each
   grid's own inner scroll already capped. */
.modal__panel--trade{ width:min(1400px, 96vw); max-width:none; height:min(820px, 96vh); max-height:97vh; }

.toggle-switch{
  position:relative; display:inline-flex; align-items:center; gap:10px;
  flex-shrink:0; width:44px; height:26px; cursor:pointer; user-select:none;
}
/* Full-size, invisible, on top -- the actual click/tap target is this
   whole 44x26 box, not just the visible 42x24 track drawn on top of it
   (.toggle-switch__track, further down next to the checked/focus states).
   Used to be split into two conflicting definitions (this one sizing it
   100%/100% to fill the box, a second one elsewhere overriding it to
   0x0 -- shrinking the real tap target to nothing while the track still
   rendered normally, since the track is drawn independently). */
.toggle-switch input{ position:absolute; inset:0; width:100%; height:100%; opacity:0; margin:0; cursor:pointer; z-index:1; }

.detail{ display:flex; flex-direction:column; gap:16px; }
.detail__thumb{ width:100%; aspect-ratio:16/9; object-fit:cover; border-radius:var(--radius-m); border:1px solid var(--line); }
.detail__top{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.detail__title{ font-family:var(--font-display); font-size:1.4rem; font-weight:500; margin:0; }
.detail__extract{ font-size:0.88rem; line-height:1.65; color:var(--paper-dim); }
.detail__stats{ display:flex; gap:10px; flex-wrap:wrap; }
.detail__stats .stat-pill{ font-size:0.82rem; padding:7px 12px; }
.detail__meta{ display:flex; flex-wrap:wrap; gap:8px; font-size:0.74rem; color:var(--paper-dim); }
.detail__meta span{ background:rgba(236,231,220,0.05); padding:5px 10px; border-radius:6px; }
.detail__link{
  align-self:flex-start; font-size:0.84rem; font-weight:600; color:var(--accent);
  border:1px solid var(--accent-dim); padding:9px 16px; border-radius:999px;
  transition:background .2s var(--ease);
}
.detail__link:hover{ background:rgba(127,162,201,0.1); }

.detail__owner{
  display:flex; flex-direction:column; gap:6px;
  padding:12px 14px; border-radius:var(--radius-m);
  border:1px solid var(--line); background:rgba(236,231,220,0.03);
}
.detail__owner-row{ display:flex; align-items:center; justify-content:space-between; gap:12px; margin:0; }
.detail__owner-row span:first-child{ font-size:0.76rem; color:var(--paper-dim); }
.detail__owner-row span:last-child{ font-size:0.84rem; font-weight:600; color:var(--paper); }
.detail-owner-link{ color:inherit; text-decoration:none; }
.detail-owner-link:hover{ color:var(--accent); }
.detail__history-btn{ align-self:flex-start; }

/* .modal__panel--detail defaults to max-width:520px (see above) -- widening
   it on demand (rather than always) keeps every other use of that class
   (achievements, etc.) at its original width, and the transition is what
   makes the history panel read as "sliding out" instead of just appearing. */
.modal__panel--detail{ transition:max-width .35s var(--ease); }
.modal__panel--detail.is-history-open{ max-width:860px; }

.detail-layout{ display:flex; gap:20px; align-items:flex-start; }
.detail-card{ display:flex; flex-direction:column; gap:16px; flex:1; min-width:0; }

.detail-history{
  flex-shrink:0; align-self:stretch;
  max-width:0; opacity:0; overflow:hidden;
  transition:max-width .35s var(--ease), opacity .25s var(--ease);
}
.detail-history--open{ max-width:280px; opacity:1; }
.detail-history__title{
  margin:0 0 10px; font-family:var(--font-body); font-weight:600;
  font-size:0.72rem; letter-spacing:0.08em; text-transform:uppercase; color:var(--paper-dim);
  width:260px;
}
.detail-history__list{
  list-style:none; margin:0; padding:0 0 0 8px; width:260px;
  display:flex; flex-direction:column; gap:10px;
  max-height:400px; overflow-y:auto;
}
.detail-history__item{
  position:relative; padding-left:16px;
  border-left:2px solid var(--line);
}
.detail-history__item::before{
  /* .detail-history has overflow:hidden (needed for the slide-out
     max-width transition), which was clipping the left half of this dot
     when it sat flush against the list's edge -- the list's own 8px
     left padding above is what gives it room to sit fully outside the
     border-left line without getting cut off. */
  content:""; position:absolute; left:-5px; top:3px;
  width:8px; height:8px; border-radius:50%; background:var(--accent);
}
.detail-history__date{ display:block; font-size:0.68rem; color:var(--paper-dim); }
.detail-history__label{ display:block; font-size:0.82rem; color:var(--paper); margin-top:2px; }

@media (max-width:760px){
  .detail-layout{ flex-direction:column; }
  .modal__panel--detail.is-history-open{ max-width:520px; }
  .detail-history--open{ max-width:100%; }
  .detail-history__title, .detail-history__list{ width:100%; }
}

.ranks-list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:6px; }
.ranks-list li{
  display:flex; align-items:center; justify-content:space-between;
  padding:10px 14px; border-radius:var(--radius-s);
  background:rgba(236,231,220,0.03); border:1px solid var(--line);
}
.ranks-list__grade{ font-family:var(--font-display); font-weight:600; font-size:1rem; color:var(--paper); min-width:32px; }
.ranks-list__grade[data-rank="S"], .ranks-list__grade[data-rank="SS"]{ color:var(--gold); }
.ranks-list__range{ font-size:0.84rem; color:var(--paper-dim); }

.avatar-preview{
  position:relative; width:96px; height:96px; margin:0 auto 26px;
  display:flex; align-items:center; justify-content:center;
}
.avatar-preview__ring{
  position:absolute; inset:0; border-radius:50%;
  background:var(--ink-3); border:1px solid var(--line);
}
.avatar-preview__emoji{ position:relative; z-index:1; font-size:2.6rem; line-height:1; }

.legal-page h3{
  margin:22px 0 10px; font-family:var(--font-body); font-weight:600;
  font-size:0.72rem; letter-spacing:0.08em; text-transform:uppercase; color:var(--paper-dim);
}

.card-tile-grid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(104px, 1fr)); gap:10px; }
.card-tile{
  position:relative; aspect-ratio:5/7.4; border-radius:var(--radius-m);
  border:1px solid var(--line); background:linear-gradient(160deg, var(--ink-2), var(--ink));
  display:flex; flex-direction:column; overflow:hidden; cursor:pointer;
  transition:border-color .2s var(--ease), transform .15s var(--ease), box-shadow .2s var(--ease);
}
.card-tile:hover{ transform:translateY(-2px); }
.card-tile.is-selected{ border-color:var(--gold-dim); box-shadow:0 0 0 2px rgba(205,166,95,0.28); }
.card-tile--empty{
  align-items:center; justify-content:center; padding:0;
  border-style:dashed; color:var(--paper-dim);
}
.card-tile--empty:hover{ border-color:var(--accent-dim); color:var(--accent); transform:translateY(-2px); }
.card-tile--static{ cursor:default; }
.card-tile--static:hover{ transform:none; box-shadow:none; }
.card-tile--empty.card-tile--static:hover{ border-color:var(--line); color:var(--paper-dim); transform:none; }
.card-tile__plus{ font-size:1.7rem; font-weight:300; line-height:1; }
.card-tile__rarity{
  position:absolute; top:6px; left:6px; z-index:2;
  font-size:0.56rem; font-weight:700; letter-spacing:0.04em; text-transform:uppercase;
  padding:3px 6px; border-radius:999px; background:rgba(7,7,10,0.75); border:1px solid currentColor;
}
/* Same "you already own a copy" marker as .wiki-card__dupe, sized down for
   this smaller tile -- fixed offset clearing the widest (2-char) rarity
   label. */
.card-tile__dupe{
  position:absolute; top:6px; left:36px; z-index:2;
  width:16px; height:16px; display:flex; align-items:center; justify-content:center;
  border-radius:999px; border:1px solid var(--accent-dim);
  background:rgba(7,7,10,0.75);
  color:var(--accent); font-size:0.56rem; line-height:1;
}
.card-tile__remove{
  position:absolute; top:5px; right:5px; z-index:2; width:18px; height:18px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:rgba(7,7,10,0.75); border:1px solid var(--line); color:var(--paper-dim); font-size:0.7rem; line-height:1;
}
.card-tile__thumb{ width:100%; flex:1; object-fit:cover; background:var(--ink-3); }
.card-tile__thumb--placeholder{
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font-display); font-size:1.3rem; color:var(--paper-dim);
}
.card-tile__title{
  padding:6px 8px; font-size:0.64rem; font-weight:600; line-height:1.3; color:var(--paper);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

.stats-grid{ display:grid; grid-template-columns:repeat(auto-fit, minmax(130px, 1fr)); gap:10px; margin-bottom:8px; }
.stat-tile{ padding:14px 16px; border-radius:var(--radius-s); background:rgba(236,231,220,0.03); border:1px solid var(--line); }
.stat-tile__value{ display:block; font-family:var(--font-display); font-weight:600; font-size:1.5rem; color:var(--paper); }
.stat-tile__label{ display:block; margin-top:2px; font-size:0.74rem; color:var(--paper-dim); }

/* Admin Dashboard's summary stats -- same row-per-item look as .ranks-list,
   easier to scan a dozen labeled numbers than a grid of tiles. */
.stat-list{ list-style:none; margin:0 0 8px; padding:0; display:flex; flex-direction:column; gap:6px; }
.stat-list__row{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:10px 14px; border-radius:var(--radius-s);
  background:rgba(236,231,220,0.03); border:1px solid var(--line);
}
.stat-list__label{ font-size:0.84rem; color:var(--paper-dim); }
.stat-list__value{ font-family:var(--font-display); font-weight:600; font-size:1rem; color:var(--paper); }

.profile-layout__aside{
  position:sticky; top:24px;
  display:flex; flex-direction:column; gap:4px;
  padding:24px; border-radius:var(--radius-l);
  background:rgba(236,231,220,0.025); border:1px solid var(--line);
}
.profile-layout__aside h2{ margin:22px 0 10px; }
.profile-layout__aside #bioSection h2{ margin-top:14px; }

.btn--sm{ padding:8px 16px; font-size:0.78rem; gap:6px; }

.people-list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:8px; max-height:52vh; overflow-y:auto; }
.people-item{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:10px 12px; border-radius:var(--radius-s); border:1px solid var(--line);
  background:rgba(236,231,220,0.03);
}
.people-item__link{ display:flex; align-items:center; gap:10px; min-width:0; text-decoration:none; }
.people-item__avatar{
  flex-shrink:0; width:36px; height:36px; border-radius:50%;
  display:flex; align-items:center; justify-content:center; font-size:1.1rem;
  background:var(--ink-3); border:1px solid var(--line);
}
.people-item__name{ font-weight:600; color:var(--paper); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; transition:color .2s var(--ease); }
.people-item__link:hover .people-item__name{ color:var(--accent); }
.people-item__actions{ display:flex; gap:8px; flex-shrink:0; }

.chat-list-item__avatar-wrap{ position:relative; flex-shrink:0; }
.chat-list-item__avatar{
  width:40px; height:40px; border-radius:50%;
  display:flex; align-items:center; justify-content:center; font-size:1.2rem;
  background:var(--ink-3); border:1px solid var(--line);
}
.online-dot{
  position:absolute; right:-1px; bottom:-1px; width:11px; height:11px; border-radius:50%;
  background:#5fc26a; border:2px solid var(--ink-2);
}
.online-dot[hidden]{ display:none; }

.messages-layout__thread{
  display:flex; flex-direction:column; min-width:0;
  border-radius:var(--radius-l); border:1px solid var(--line); background:rgba(236,231,220,0.025);
  overflow:hidden;
}
.thread-placeholder{ flex:1; display:flex; align-items:center; justify-content:center; color:var(--paper-dim); font-size:0.9rem; text-align:center; padding:24px; }
.thread-placeholder[hidden]{ display:none; }
.thread-active{ display:flex; flex-direction:column; min-height:0; flex:1; }
.thread-active[hidden]{ display:none; }

.thread-active__header{
  padding:14px 18px; border-bottom:1px solid var(--line);
  display:flex; align-items:center; justify-content:space-between; gap:12px;
}
.thread-active__person{ display:flex; align-items:center; gap:10px; text-decoration:none; min-width:0; }
/* A single flex item, not two separate ones -- otherwise the header's own
   justify-content:space-between spreads Trade and Block apart from each
   other (evenly spacing all 3 children) instead of keeping them side by
   side as a pair on the right. */
.thread-active__actions{ display:flex; align-items:center; gap:8px; flex-shrink:0; }
.thread-active__avatar-wrap{ position:relative; flex-shrink:0; }
.thread-active__avatar{
  width:36px; height:36px; border-radius:50%;
  display:flex; align-items:center; justify-content:center; font-size:1.1rem;
  background:var(--ink-3); border:1px solid var(--line);
}
.thread-active__avatar-wrap .online-dot, .thread-active__avatar-wrap .presence-dot{ border-color:var(--ink-3); }
.thread-active__name{ font-weight:600; color:var(--paper); transition:color .2s var(--ease); }
.thread-active__person:hover .thread-active__name{ color:var(--accent); }

.friend-tag{
  display:inline-flex; align-items:center; margin-left:6px; padding:2px 8px;
  border-radius:999px; border:1px solid var(--gold-dim); background:rgba(205,166,95,0.1);
  font-size:0.62rem; font-weight:600; letter-spacing:0.03em; text-transform:uppercase; color:var(--gold);
  vertical-align:middle;
}
.friend-tag[hidden]{ display:none; }

.thread-active__messages{
  flex:1; min-height:0; overflow-y:auto; padding:18px; display:flex; flex-direction:column; gap:10px;
}
.thread-active__load-more{ align-self:center; margin:0 0 6px; font-size:0.76rem; color:var(--paper-dim); }
.thread-active__load-more[hidden]{ display:none; }

.thread-bubble{
  max-width:70%; align-self:flex-start;
  padding:9px 13px; border-radius:14px 14px 14px 4px;
  background:var(--ink-3); border:1px solid var(--line);
}
.thread-bubble--mine{
  align-self:flex-end; border-radius:14px 14px 4px 14px;
  background:linear-gradient(180deg, rgba(127,162,201,0.22), rgba(127,162,201,0.09));
  border-color:var(--accent-dim);
}
.thread-bubble__body{ margin:0; font-size:0.88rem; line-height:1.5; color:var(--paper); white-space:pre-wrap; word-break:break-word; }
.thread-bubble__time{
  display:flex; align-items:center; justify-content:flex-end; gap:4px;
  margin-top:4px; font-size:0.66rem; color:var(--paper-dim); text-align:right;
}
.thread-bubble__status{ font-size:0.72rem; letter-spacing:-1px; color:var(--paper-dim); }
.thread-bubble__status--read{ color:var(--accent); }

.thread-active__blocked-note{
  margin:0; padding:10px 18px; font-size:0.8rem; color:var(--paper-dim); font-style:italic;
  border-top:1px solid var(--line);
}
.thread-active__blocked-note[hidden]{ display:none; }

/* ============================================================
   Footer
   ============================================================ */
.footer{ text-align:center; padding:18px 20px 26px; font-size:0.72rem; color:#5c5d64; letter-spacing:0.01em; }
.footer__telegram-btn{
  display:inline-flex; align-items:center; gap:8px; margin-bottom:16px; padding:9px 18px;
  border-radius:999px; border:1px solid var(--line); background:var(--ink-3); color:var(--paper);
  font-size:0.78rem; font-weight:600; text-decoration:none;
  transition:border-color .2s var(--ease), color .2s var(--ease);
}
.footer__telegram-btn:hover{ border-color:#4fa9e0; color:#4fa9e0; }
.footer__disclaimer{ margin:0 0 6px; }
.footer__links{ margin-top:10px; display:flex; align-items:center; justify-content:center; gap:8px; flex-wrap:wrap; }
.footer__links a{ color:#5c5d64; text-decoration:none; transition:color .2s var(--ease); }
.footer__links a:hover{ color:var(--paper-dim); }


/* ============================================================
   Standalone legal pages (privacy / terms / contacts)
   ============================================================ */
.legal-page{ max-width:720px; margin:0 auto; padding:60px 24px 100px; }

/* Plain text + arrow, no pill/border/background -- matches how this link
   already rendered on help.html (whose .help-page wrapper never matched
   the old ".legal-page .legal-page__back" pill rule below, so it fell
   back to an unstyled link -- adopted here as the deliberate, single
   shared look instead of an accident one page happened to have).
   Specificity note: qualified with .legal-page/.help-page so this beats
   the plain ".legal-page a" link styling (accent color) below -- a bare
   ".legal-page__back" class selector loses that fight since ".legal-page a"
   carries an extra type selector. */
.legal-page .legal-page__back, .help-page .legal-page__back{
  display:inline-flex; align-items:center; gap:6px; margin-bottom:34px;
  font-size:0.82rem; font-weight:600; color:var(--paper); text-decoration:none;
  transition:color .2s var(--ease), transform .2s var(--ease);
}
.legal-page .legal-page__back:hover, .help-page .legal-page__back:hover{
  color:var(--gold); transform:translateX(-3px);
}
.legal-page__eyebrow{ margin:0 0 8px; font-size:0.72rem; letter-spacing:0.22em; text-transform:uppercase; color:var(--gold); }
.legal-page h1{ margin:0 0 40px; font-family:var(--font-display); font-weight:500; font-size:clamp(1.7rem, 4vw, 2.2rem); color:var(--paper); }
.legal-page h2{ margin:34px 0 10px; font-family:var(--font-display); font-weight:500; font-size:1.15rem; color:var(--paper); }
.legal-page p{ margin:0 0 14px; font-size:0.92rem; line-height:1.75; color:var(--paper-dim); }
.legal-page a{ color:var(--accent); text-decoration:none; }
.legal-page a:hover{ color:var(--paper); }
.legal-page__empty{ font-size:0.92rem; color:var(--paper-dim); font-style:italic; }

.profile-gate{
  border:1px solid var(--line); border-radius:var(--radius-l);
  background:rgba(236,231,220,0.02); padding:32px clamp(20px,4vw,40px);
  text-align:center; margin-top:8px;
}
.profile-gate p{ margin:0 0 20px; }
.profile-gate .btn{ display:inline-flex; text-decoration:none; }


.legal-page--wide{ max-width:980px; }

/* Unlock toast -- shared markup/id names on index.html (after a pack open)
   and achievements.html (on load, for anything just caught up). */
.achv-toast{
  position:fixed; right:20px; bottom:20px; z-index:60;
  display:flex; align-items:center; gap:12px;
  padding:14px 18px; border-radius:var(--radius-m);
  border:1px solid var(--gold-dim); background:var(--ink-2);
  box-shadow:0 16px 40px rgba(0,0,0,0.5);
  opacity:0; transform:translateY(12px);
  transition:opacity .3s var(--ease), transform .3s var(--ease);
  pointer-events:none; max-width:min(320px, calc(100vw - 40px));
}
.achv-toast[hidden]{ display:none; }

/* Back to Top -- fixed bottom-right, sits above where .achv-toast pops up
   so the two never overlap even when a toast fires mid-scroll. */
.back-to-top{
  position:fixed; right:24px; bottom:90px; z-index:55;
  width:44px; height:44px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  border:1px solid var(--line); background:var(--ink-2); color:var(--paper);
  box-shadow:0 12px 30px rgba(0,0,0,0.45);
  opacity:0; transform:translateY(10px); pointer-events:none;
  transition:opacity .25s var(--ease), transform .25s var(--ease),
    border-color .2s var(--ease), background .2s var(--ease);
}
.back-to-top--visible{ opacity:1; transform:translateY(0); pointer-events:auto; }
.back-to-top:hover{ border-color:var(--accent-dim); background:rgba(127,162,201,0.14); }
.achv-toast--visible{ opacity:1; transform:translateY(0); }
.achv-toast__icon{ font-size:1.4rem; flex:none; }
.achv-toast__body{ min-width:0; }
.achv-toast__title{
  margin:0; font-family:var(--font-display); font-weight:500;
  font-size:0.92rem; color:var(--paper);
}
.achv-toast__reward{ margin:2px 0 0; font-size:0.78rem; color:var(--accent); }

.nav-pill:disabled, .nav-pill--locked{ opacity:0.4; pointer-events:none; cursor:default; }

.chip--favorites{ margin-left:auto; }

/* Fixed 2-column grid, not flex-wrap -- with flex-wrap, how many of the 4
   pills fit per line depends on each pill's rendered text width (a 4-digit
   ATK vs a 2-digit one, "90%" vs "0%"), so the stats block's height (and
   therefore how much room is left for .card-tile__thumb's flex:1) varied
   card to card -- some tiles ended up with a tall image, others a thin
   strip, for no reason a player could see. A fixed 2-per-row grid always
   takes the same 2 rows for these 4 stats regardless of digit count, so
   every tile's image gets the exact same amount of space. */
.card-tile__stats{ display:grid; grid-template-columns:repeat(2, 1fr); gap:4px; padding:0 8px 8px; }
.card-tile__stats .stat-pill{
  padding:2px 6px; font-size:0.58rem; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

.leaderboard__row--me td{ background:rgba(205,166,95,0.08); font-weight:600; }
.leaderboard__you{ margin-left:6px; font-size:0.72rem; font-weight:500; color:var(--gold); }
.leaderboard__row--gap td{ padding:4px 0; border-bottom:none; text-align:center; letter-spacing:0.3em; color:var(--paper-dim); }
.leaderboard__row--empty td{ color:var(--paper-dim); opacity:0.55; }
.leaderboard__reward{ color:var(--gold); font-weight:600; white-space:nowrap; }
.leaderboard__row--empty .leaderboard__reward{ color:var(--gold); opacity:0.85; }
.leaderboard__reward-pack{
  width:18px; height:18px; object-fit:contain; vertical-align:-4px; margin-left:2px;
}
.leaderboard__reward-count{ font-size:0.72rem; margin-left:1px; }

.notif-btn__icon--emoji{ font-size:1.05rem; line-height:1; }

.settings-radio-row{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:12px 24px;
  padding:12px 0;
}
.settings-radio-row .chip-row{ flex-shrink:0; }

.wiki-card__trade-lock{
  position:absolute; top:8px; right:40px; z-index:2;
  width:26px; height:26px; display:flex; align-items:center; justify-content:center;
  border-radius:999px; border:1px solid var(--gold-dim);
  background:rgba(7,7,10,0.75); backdrop-filter:blur(3px);
  font-size:0.8rem; line-height:1;
}

/* ---- Reusable toggle switch (Active/Inactive, etc.) -- .toggle-switch
   itself and .toggle-switch input are defined once, up near
   .modal__panel--trade, not here (see that definition's own comment on
   why they used to be split/conflicting). ---- */
.toggle-switch__track{
  position:relative; width:42px; height:24px; border-radius:999px; flex-shrink:0;
  background:var(--ink-3); border:1px solid var(--line);
  transition:background .2s var(--ease), border-color .2s var(--ease);
}
.toggle-switch__track::before{
  content:""; position:absolute; top:2px; left:2px; width:18px; height:18px; border-radius:50%;
  background:var(--paper-dim); transition:transform .2s var(--ease), background .2s var(--ease);
}
.toggle-switch input:checked + .toggle-switch__track{ background:rgba(205,166,95,0.25); border-color:var(--gold-dim); }
.toggle-switch input:checked + .toggle-switch__track::before{ transform:translateX(18px); background:var(--gold); }
.toggle-switch input:focus-visible + .toggle-switch__track{ outline:2px solid var(--accent-dim); outline-offset:2px; }

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width:760px){
  /* Full-width stacked rows, not a 2-column split -- .topbar__side--right
     alone (trades/messages/notifications/balance/profile, all visible at
     once for a signed-in account) needs ~270px to render without
     clipping, which never fits in half of even a large phone's width. A
     single column gives each side (and the nav below them) the full
     viewport to lay out its own row instead of fighting for half of it.
     order:0 (both sides' default) keeps them in DOM order -- left above
     right -- with .topbar__nav's own order:3 still placing it last. */
  .topbar{ grid-template-columns:1fr; row-gap:12px; padding-top:18px; }
  .topbar__side{ justify-content:center; }
  /* Wrapping is the default now (see .topbar__nav's base rule) -- this
     just softens the pill-track's 999px border-radius to something sane
     for a strip that may now be 2+ rows tall (a fully-rounded capsule
     looks broken once it's not a single row). Also covers .admin-tabs/
     .trades-tabs, which share this class on trades.html/moderation.html/
     admin.html. */
  .topbar__nav, .admin-tabs{ order:3; justify-content:center; border-radius:var(--radius-l); }
  .lang-select__label{ display:none; }
  .pack-stage{ width:min(70vw, 300px); }
  .nav-pill{ padding:9px 14px; font-size:0.8rem; min-height:38px; }
  .store__grid{ grid-template-columns:repeat(auto-fill, minmax(160px, 1fr)); gap:12px; }
  .store-card{ padding:14px; }

  /* Touch targets -- several icon-buttons/pills sit in the 33-38px range
     at desktop sizing (fine with a precise mouse cursor, tight for a
     fingertip). Bumped here rather than in each component's own base
     rule so desktop sizing/density is untouched. */
  .notif-btn{ width:42px; height:42px; }
  .help-btn{ width:40px; height:40px; }
  .admin-avatar-btn{ width:42px; height:42px; }
  .lang-select{ padding:11px 14px; }
  .chip{ padding:10px 16px; min-height:38px; }
  .pager__btn{ padding:10px 16px; min-height:38px; }
}

@media (max-width:420px){
  .hero__cta-row{ flex-direction:column; width:100%; max-width:280px; }
  .btn{ justify-content:center; width:100%; }
  .balance__amount{ display:none; }
}


/* ============================================================
   Moderation -- Report modal + restriction banner (report.js, injected
   into every page that includes it), the Rules page, and the Moderation
   panel (moderation.html/js). See moderation.py's module docstring for the
   system this all sits on top of.
   ============================================================ */
.report-modal__panel{ display:flex; flex-direction:column; gap:12px; transition:box-shadow .15s var(--ease); }
.report-modal__panel--dragover{
  box-shadow:inset 0 0 0 2px var(--gold), 0 0 24px -6px rgba(205,166,95,0.5);
  border-radius:var(--radius-l);
}
.report-modal__categories .chip{ font-size:0.78rem; padding:7px 13px; }
.report-modal__rule{
  margin:0; padding:10px 14px; border-radius:var(--radius-m);
  background:rgba(205,166,95,0.06); border:1px solid var(--gold-dim);
  font-size:0.82rem; color:var(--paper-dim); line-height:1.5;
}
.report-modal__comment{ min-height:76px; }
.report-modal__title-input{
  display:block; width:100%; padding:12px 16px; border-radius:var(--radius-m);
  border:1px solid var(--line); background:var(--ink-3); color:var(--paper);
  font-family:var(--font-body); font-size:0.88rem; transition:border-color .2s var(--ease);
}
.report-modal__title-input:focus{ outline:none; border-color:var(--accent-dim); }

.report-modal__media-controls{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.report-modal__media-hint{ font-size:0.76rem; color:var(--paper-dim); }
.report-modal__media-previews{ display:flex; flex-wrap:wrap; gap:8px; margin-top:10px; }
.report-modal__media-previews:empty{ margin-top:0; }
.report-modal__media-chip{
  position:relative; width:64px; height:64px; border-radius:var(--radius-s);
  overflow:hidden; background:var(--ink-3); border:1px solid var(--line);
}
.report-modal__media-chip img, .report-modal__media-chip video{
  width:100%; height:100%; object-fit:cover; display:block;
}
.report-modal__media-chip-file{
  width:100%; height:100%; display:flex; align-items:center; justify-content:center; font-size:1.4rem;
}
.report-modal__media-chip-remove{
  position:absolute; top:2px; right:2px; width:18px; height:18px; border-radius:50%;
  border:none; background:rgba(4,4,6,0.75); color:var(--paper); font-size:0.9rem; line-height:1;
  cursor:pointer; display:flex; align-items:center; justify-content:center;
}
.report-modal__media-chip-remove:hover{ background:#a3403f; }

.report-modal__actions{ display:flex; align-items:center; gap:16px; flex-wrap:wrap; }
.report-modal__rules-link{ font-size:0.78rem; color:var(--paper-dim); text-decoration:underline; }
.report-modal__rules-link:hover{ color:var(--gold); }
.report-modal__note{ margin:0; font-size:0.82rem; color:var(--gold); min-height:1.2em; }

/* A small, unmissable-but-not-alarming strip pinned above everything else
   -- reused verbatim by every page that includes report.js, since a
   restricted account should never have to go hunting for why. */
.restriction-banner{
  position:relative; z-index:40; padding:10px clamp(16px,4vw,32px);
  background:linear-gradient(90deg, rgba(163,64,63,0.22), rgba(163,64,63,0.08));
  border-bottom:1px solid rgba(163,64,63,0.45);
  text-align:center;
}
.restriction-banner p{ margin:2px 0; font-size:0.82rem; color:var(--paper); }
.restriction-banner strong{ color:#e08a8a; }

/* Floating site-issue report trigger (report.js) -- deliberately small and
   low-contrast at rest so it reads as "always there if you need it"
   rather than competing with the page's own primary actions. */
.report-bug-trigger{
  position:fixed; right:20px; bottom:20px; z-index:30;
  width:42px; height:42px; border-radius:50%;
  display:flex; align-items:center; justify-content:center; font-size:1.15rem;
  background:var(--ink-2); border:1px solid var(--line); color:var(--paper-dim);
  cursor:pointer; opacity:0.6; transition:opacity .2s var(--ease), border-color .2s var(--ease), transform .2s var(--ease);
}
.report-bug-trigger:hover{ opacity:1; border-color:var(--accent-dim); transform:translateY(-2px); }
.report-bug-trigger--suggest{ bottom:70px; }
@media (max-width:640px){
  .report-bug-trigger{ right:14px; bottom:14px; }
  .report-bug-trigger--suggest{ bottom:62px; }
  /* These two (plus index.html's own bottom-left wheel-fab) are
     position:fixed, so on a short mobile viewport ordinary page content
     can scroll to sit directly underneath them -- reserving this much
     bottom space keeps real content (the last paragraph, a button row)
     from ever landing behind a floating button. */
  .page{ padding-bottom:96px; }
}

/* ---- Moderation panel (moderation.html/js) ---- */
.mod-toolbar{ margin-bottom:18px; align-items:center; }
.mod-search-input{
  flex:1 1 220px; min-width:160px; padding:10px 14px; border-radius:999px;
  border:1px solid var(--line); background:var(--ink-3); color:var(--paper);
  font-family:var(--font-body); font-size:0.85rem; transition:border-color .2s var(--ease);
}
.mod-search-input:focus{ outline:none; border-color:var(--accent-dim); }

.mod-badge{
  display:inline-flex; align-items:center; padding:3px 10px; border-radius:999px;
  font-size:0.66rem; font-weight:600; letter-spacing:0.03em; text-transform:uppercase;
}
.mod-badge--category{ background:rgba(127,162,201,0.14); color:var(--accent); }
.mod-badge--pending{ background:rgba(205,166,95,0.16); color:var(--gold); }
.mod-badge--reviewing{ background:rgba(160,132,214,0.16); color:#a084d6; }
.mod-badge--actioned{ background:rgba(224,138,138,0.16); color:#e08a8a; }
.mod-badge--dismissed{ background:rgba(236,231,220,0.08); color:var(--paper-dim); }

.mod-report-list{ display:flex; flex-direction:column; gap:8px; }
.mod-report-row{
  display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
  padding:12px 16px; border-radius:var(--radius-m); border:1px solid var(--line);
  background:rgba(236,231,220,0.02); cursor:pointer; transition:border-color .2s var(--ease);
}
.mod-report-row:hover{ border-color:var(--accent-dim); }
.mod-report-row__main{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.mod-report-row__text{ font-size:0.86rem; color:var(--paper); }
.mod-report-row__time{ flex-shrink:0; font-size:0.72rem; color:var(--paper-dim); }
.mod-report-row--compact{ padding:9px 14px; }
.mod-report-row--block{ flex-direction:column; align-items:stretch; cursor:default; gap:10px; }
.mod-report-row--block:hover{ border-color:var(--line); }
.mod-report-row--block .mod-report-row__main{ justify-content:flex-start; }

.mod-detail-grid{
  display:grid; grid-template-columns:1fr 1fr; gap:6px 18px; margin:12px 0;
  font-size:0.84rem; color:var(--paper-dim);
}
.mod-detail-grid p{ margin:0; }
.mod-detail-grid strong{ color:var(--paper); }
@media (max-width:560px){ .mod-detail-grid{ grid-template-columns:1fr; } }

.mod-media-gallery{ display:flex; flex-wrap:wrap; gap:8px; margin:4px 0 12px; }
.mod-media-chip{
  display:block; width:96px; height:96px; border-radius:var(--radius-s); padding:0;
  overflow:hidden; background:var(--ink-3); border:1px solid var(--line); cursor:pointer;
  transition:border-color .2s var(--ease);
}
.mod-media-chip:hover{ border-color:var(--accent-dim); }
.mod-media-chip img, .mod-media-chip video{ width:100%; height:100%; object-fit:cover; display:block; pointer-events:none; }

/* ---- Evidence lightbox (moderation.html/js) ---- */
.mod-lightbox__panel{ max-width:min(900px, 92vw); text-align:center; }
.mod-lightbox__stage{ display:flex; align-items:center; gap:10px; }
.mod-lightbox__media{
  flex:1; min-width:0; min-height:200px; max-height:72vh;
  display:flex; align-items:center; justify-content:center; border-radius:var(--radius-m); overflow:hidden;
  background:rgba(0,0,0,0.3);
}
.mod-lightbox__media img, .mod-lightbox__media video{ max-width:100%; max-height:72vh; display:block; }
.mod-lightbox__arrow{
  flex-shrink:0; width:36px; height:36px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  border:1px solid var(--line); background:var(--ink-3); color:var(--paper); font-size:1.2rem;
  cursor:pointer; transition:border-color .2s var(--ease), color .2s var(--ease);
}
.mod-lightbox__arrow:hover{ border-color:var(--accent-dim); color:var(--accent); }
.mod-lightbox__counter{ margin:10px 0 0; font-size:0.78rem; color:var(--paper-dim); font-variant-numeric:tabular-nums; }


