/* =========================================================
   LEXOGAME — Fonts
   ========================================================= */
@font-face {
  font-family: 'Minecraft';
  src: url('../fonts/mc-font.ttf') format('truetype');
  font-display: swap;
}

/* Vazirmatn — the Persian face, self-hosted.
   Five real weights rather than one, because the site leans on 600,
   700 and 800 constantly: with a single file the browser fakes those
   by smearing the outlines, which is what makes Persian text look
   muddy at headline sizes.
   Self-hosted rather than pulled from Google Fonts — that host is
   unreliable from Iran, and a font that arrives late or not at all
   reflows the whole page.
   Latin is included in the file, so Minecraft usernames, rank names
   and commands are drawn by the same family as the Persian around
   them instead of falling through to a system font. */
@font-face {
  font-family: 'Vazirmatn';
  src: url('../fonts/Vazirmatn-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Vazirmatn';
  src: url('../fonts/Vazirmatn-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Vazirmatn';
  src: url('../fonts/Vazirmatn-SemiBold.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Vazirmatn';
  src: url('../fonts/Vazirmatn-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Vazirmatn';
  src: url('../fonts/Vazirmatn-ExtraBold.woff2') format('woff2');
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

/* =========================================================
   Root / Reset
   ========================================================= */
:root {
  --theme: #1DC8FF;
  --theme-dim: #1497c2;
  --theme-glow: rgba(29, 200, 255, 0.45);
  --bg-deep: #05080c;
  --bg-panel: #0b1119;
  --bg-panel-2: #0f1826;
  --border-soft: rgba(29, 200, 255, 0.18);
  --online: #3ee07f;
  --online-glow: rgba(62, 224, 127, 0.55);
  --text-main: #eef6fb;
  --text-dim: #9db2c2;
  --radius-lg: 22px;
  --radius-md: 14px;
  --font-pixel: 'Minecraft', 'Courier New', monospace;
  --font-body: 'Vazirmatn', 'Segoe UI', Tahoma, 'Iranian Sans', 'B Nazanin', sans-serif;
}

* { box-sizing: border-box; }

/* The `hidden` attribute is only a UA-stylesheet `display: none`, so any
   author rule that sets display — every flex or grid block below — beats
   it. Pages here toggle whole sections with `hidden`, so it has to win. */
[hidden] { display: none !important; }

/* Text-selection deterrent (paired with js/no-copy.js). Inputs and
   textareas stay selectable so forms still work normally. */
body {
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
}
input, textarea {
  -webkit-user-select: text;
  -moz-user-select: text;
  user-select: text;
}
html { scroll-behavior: smooth; }

/* =========================================================
   Scrollbar — native browser scrollbar, themed to match the
   site accent color. Default appearance/behavior, just recolored.
   ========================================================= */
html {
  scrollbar-width: thin;
  scrollbar-color: var(--theme) transparent;
}

::-webkit-scrollbar {
  width: 12px;
  height: 12px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--theme-dim);
}

::-webkit-scrollbar-thumb:hover {
  background: var(--theme);
}

/* Offsets scrollIntoView / anchor targets so content doesn't land
   tucked under the fixed navbar */
.hero, .modes-section, .lb-section {
  scroll-margin-top: 90px;
}

body {
  margin: 0;
  background: var(--bg-deep);
  color: var(--text-main);
  font-family: var(--font-body);
  overflow-x: hidden;
}

a { text-decoration: none; color: inherit; }
button { font-family: inherit; cursor: pointer; }

/* =========================================================
   Navbar
   ========================================================= */
.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  transition: top 0.45s cubic-bezier(.22,.61,.36,1),
              left 0.45s cubic-bezier(.22,.61,.36,1),
              right 0.45s cubic-bezier(.22,.61,.36,1),
              background-color 0.45s ease,
              border-color 0.45s ease,
              box-shadow 0.45s ease,
              border-radius 0.45s ease,
              backdrop-filter 0.45s ease;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 0;
}

.navbar-inner {
  max-width: 1400px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 32px;
  gap: 24px;
}

/* --- Scrolled state --- */
.navbar.scrolled {
  top: 14px;
  left: 22px;
  right: 22px;
  background: rgba(8, 13, 20, 0.68);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  box-shadow: 0 10px 40px -12px rgba(0,0,0,0.55), 0 0 0 1px rgba(29,200,255,0.04);
}

.navbar.scrolled .navbar-inner {
  padding: 12px 26px;
}

/* --- Logo --- */
.nav-logo {
  font-family: var(--font-pixel);
  font-size: 22px;
  font-weight: 400;
  white-space: nowrap;
  display: flex;
  align-items: center;
  user-select: none;
  direction: ltr;
  unicode-bidi: isolate;
}

.logo-part.logo-blue {
  color: var(--theme);
  text-shadow: 0 0 14px var(--theme-glow), 0 0 2px rgba(29,200,255,0.6);
}
.logo-part.logo-white {
  color: #FFFFFF;
  text-shadow: 0 0 10px rgba(255,255,255,0.25);
}

/* --- Center links --- */
.nav-links {
  display: flex;
  align-items: center;
  gap: 6px;
  background: rgba(255,255,255,0.02);
  border: 1px solid rgba(255,255,255,0.04);
  border-radius: 999px;
  padding: 6px;
}

.nav-link {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 9px 16px;
  border-radius: 999px;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--text-dim);
  cursor: pointer;
  transition: color 0.25s ease, background-color 0.25s ease;
  position: relative;
}

.nav-link .nav-icon {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  opacity: 0.85;
}

.nav-link:hover {
  color: var(--text-main);
  background: rgba(255,255,255,0.05);
}

.nav-link.active {
  color: #04141c;
  background: var(--theme);
  box-shadow: 0 0 18px var(--theme-glow);
}

.nav-link.active .nav-icon { opacity: 1; }

/* --- Auth / login card --- */
.nav-auth { display: flex; align-items: center; }

/* Wraps the button and its dropdown so the menu can anchor to it. */
.nav-account { position: relative; display: flex; flex-direction: column; }

/* The navbar's own button. Same construction as .btn — lit top edge,
   slab underneath, press drops onto it — but tinted rather than solid:
   it sits on every page, and a second full-strength cyan button would
   argue with the hero's. */
.login-card {
  position: relative;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 20px;
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, rgba(29,200,255,0.22), rgba(29,200,255,0.05));
  border: 1px solid rgba(29,200,255,0.42);
  color: var(--text-main);
  font-size: 14.5px;
  font-weight: 600;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.16),
    0 2px 0 rgba(8,74,100,0.55),
    0 8px 20px -10px rgba(29,200,255,0.5);
  transition: transform 0.14s cubic-bezier(.22,.61,.36,1),
              box-shadow 0.25s ease, background 0.25s ease, border-color 0.25s ease;
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}

.login-card::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 34%, rgba(255,255,255,0.16) 47%, transparent 62%);
  transform: translateX(-130%);
  transition: transform 0.6s cubic-bezier(.22,.61,.36,1);
}

.login-card:hover::after { transform: translateX(130%); }

.login-card > * { position: relative; z-index: 1; }

.login-card:hover {
  transform: translateY(-2px);
  border-color: rgba(29,200,255,0.65);
  background: linear-gradient(180deg, rgba(29,200,255,0.32), rgba(29,200,255,0.08));
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.22),
    0 4px 0 rgba(8,74,100,0.55),
    0 14px 28px -10px rgba(29,200,255,0.65);
}

.login-card:active {
  transform: translateY(1px);
  box-shadow:
    inset 0 2px 5px rgba(0,0,0,0.35),
    0 1px 0 rgba(8,74,100,0.55);
}

.login-card:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--bg-deep), 0 0 0 4px rgba(29,200,255,0.8);
}

@media (prefers-reduced-motion: reduce) {
  .login-card::after { display: none; }
  .login-card:hover { transform: none; }
}

.login-icon { width: 18px; height: 18px; color: var(--theme); flex-shrink: 0; }

/* Signed-in state: the person icon gives way to the player's head, so
   the button keeps the same footprint either way. Driven by the
   .logged-in class rather than the hidden attribute — `hidden` is an
   HTML attribute and has no effect when set on an <svg> from script. */
.login-card.logged-in .login-icon { display: none; }
.login-card:not(.logged-in) .login-head-wrap { display: none; }

.login-head-wrap {
  position: relative;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  overflow: hidden;
  flex-shrink: 0;
  box-shadow: 0 0 0 1px rgba(29,200,255,0.4);
}

/* The head itself — see .player-head below. Every frame that holds one
   (navbar button, leaderboard row, dashboard avatar) just sets its own
   size, radius and overflow. */

/* The username is a Latin handle sitting in an RTL page — isolate it so
   it reads left-to-right. Scoped to the label, not the head wrapper. */
.login-card.logged-in > span:last-of-type {
  direction: ltr;
  unicode-bidi: isolate;
}

/* --- Account dropdown (signed in only) --- */
.login-chevron {
  width: 14px;
  height: 14px;
  color: var(--text-dim);
  flex-shrink: 0;
  transition: transform 0.25s ease;
}

.login-card:not(.logged-in) .login-chevron { display: none; }
.nav-account.open .login-chevron { transform: rotate(180deg); }

.account-menu {
  position: absolute;
  top: calc(100% + 10px);
  left: 0;
  right: 0;
  display: none;
  flex-direction: column;
  gap: 3px;
  padding: 6px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-soft);
  background: rgba(11, 17, 25, 0.96);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  box-shadow: 0 18px 40px -18px rgba(0,0,0,0.85);
  z-index: 10;
}

.nav-account.open .account-menu {
  display: flex;
  animation: accountMenuIn 0.18s cubic-bezier(.22,.61,.36,1);
}

@keyframes accountMenuIn {
  from { opacity: 0; transform: translateY(-6px); }
}

.account-menu-item {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 10px 12px;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--text-dim);
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 600;
  text-align: right;
  transition: background-color 0.2s ease, color 0.2s ease;
}

.account-menu-item svg { width: 16px; height: 16px; flex-shrink: 0; }

.account-menu-item:hover {
  background: rgba(29,200,255,0.09);
  color: var(--text-main);
}

.account-menu-logout:hover {
  background: rgba(255,92,108,0.10);
  color: #ff8d99;
}

/* Inside the burger menu there's nothing to float over, so the dropdown
   expands in place rather than hanging off the button. */
.mobile-menu .account-menu {
  position: static;
  margin-top: 6px;
}

/* --- Burger (mobile) --- */
.nav-burger {
  display: none;
  width: 40px;
  height: 40px;
  align-items: center;
  justify-content: center;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
  color: var(--text-main);
}
.nav-burger svg { width: 20px; height: 20px; }

.mobile-menu {
  display: none;
  flex-direction: column;
  gap: 4px;
  padding: 10px 18px 18px;
}

.mobile-link {
  padding: 12px 14px;
  border-radius: 10px;
  color: var(--text-dim);
  font-size: 15px;
  font-weight: 500;
  cursor: pointer;
}
.mobile-link:hover { background: rgba(255,255,255,0.05); color: var(--text-main); }

.mobile-login { justify-content: center; margin-top: 8px; }

/* =========================================================
   Hero
   ========================================================= */
.hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 150px 24px 90px;
  overflow: hidden;
  isolation: isolate;
}

.hero-bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-color: #05080c;
  background-size: cover;
  background-position: center;
  transform: scale(1.06);
}

/* Two jobs. The first is a pool of shadow under the column, so the type
   has a ground to sit on wherever the render happens to be bright,
   while the scene stays lit around it — the art is the reason anyone
   looks at this page. The second keeps the render out of the navbar and
   hands off to the section below. */
.hero-scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(ellipse 52% 50% at 50% 46%,
      rgba(5,8,12,0.92) 0%,
      rgba(5,8,12,0.86) 38%,
      rgba(5,8,12,0.55) 66%,
      rgba(5,8,12,0.15) 88%,
      transparent 100%),
    linear-gradient(180deg,
      rgba(5,8,12,0.6) 0%,
      rgba(5,8,12,0.14) 22%,
      rgba(5,8,12,0.18) 66%,
      rgba(5,8,12,0.85) 93%,
      #05080c 100%);
}

.hero-inner {
  position: relative;
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  justify-content: center;
}

.hero-content {
  max-width: 560px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 22px;
}

.hero-title {
  margin: 0;
  font-family: var(--font-body);
  font-weight: 700;
  line-height: 1.1;
  color: var(--text-main);
}

.hero-sub {
  /* The column already caps the measure; a tighter cap here only
     orphaned the last word onto its own line. */
  max-width: 100%;
  margin: -4px 0 0;
  color: #c6d6e2;
  font-size: 17px;
  line-height: 1.95;
}

.hero-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 2px;
  flex-wrap: wrap;
}

/* --- The server plate ---------------------------------------------
   Modelled on an entry in Minecraft's own multiplayer list: signal bars
   and the head-count on the top line, the address on the line under it,
   and the action on the far side of a divider. Hard edges, a small
   radius and a lit/shaded bevel on purpose — the soft 22px cards
   elsewhere on the site would make this read as one more panel instead
   of as something out of the game. */
/* =========================================================
   Server widget
   The server as Minecraft's own multiplayer list draws it: the
   server's icon, its MOTD in the colours it actually sends, and who
   is on it. All of it comes from our own Server List Ping, so what
   is on screen is what the server itself answered.
   ========================================================= */
.swidget {
  width: 100%;
  max-width: 460px;
  border-radius: var(--radius-lg);
  /* Nearly opaque, and blurred behind: this sits on top of the hero
     artwork, and a translucent panel let that artwork show through the
     MOTD, which is small monospace text and the first thing to become
     unreadable. */
  background:
    linear-gradient(170deg, rgba(255,255,255,0.05), rgba(255,255,255,0.015)),
    rgba(6, 11, 18, 0.9);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(29,200,255,0.22);
  box-shadow: 0 26px 54px -30px rgba(0,0,0,0.95), inset 0 1px 0 rgba(255,255,255,0.07);
  overflow: hidden;
  transition: border-color 0.25s ease, box-shadow 0.25s ease;
}

.swidget:hover {
  border-color: rgba(29,200,255,0.45);
  box-shadow: 0 30px 60px -28px rgba(0,0,0,0.95), inset 0 1px 0 rgba(255,255,255,0.1);
}

.swidget[data-state="offline"] { border-color: rgba(255,120,120,0.3); }

/* Laid out left-to-right inside a right-to-left page, so the server's
   icon sits on the physical left the way it does in Minecraft's own
   server list, with the MOTD filling the space beside it. */
.swidget-top {
  display: flex;
  direction: ltr;
  align-items: center;
  gap: 12px;
  padding: 14px;
}

/* The site's logo, not the server's 64x64 favicon — that one is a
   pixelated thumbnail of this same artwork. No plate and no border
   behind it: the PNG is already transparent, and a frame around a
   wordmark just boxes it in. */
.swidget-icon {
  flex-shrink: 0;
  /* Width only — the logo is a wordmark, so its height follows its own
     proportions rather than being forced into a box. */
  width: 96px;
  line-height: 0;
}

.swidget-icon img {
  display: block;
  width: 100%;
  height: auto;
}

/* The MOTD is written with spaces doing the centring, so it is set in
   a monospace face — in a proportional one that padding collapses and
   the art the server drew comes out crooked. */
/* Centred in the space next to the icon. The server's own padding
   spaces are stripped before this ever arrives (see trimMotd in
   server/api.js) — left in, they would fight this centring and push
   every line off to one side.
   Monospace because the MOTD still uses runs of spaces internally to
   set its pieces apart, and a proportional face collapses those. */
.swidget-motd {
  flex: 1;
  min-width: 0;
  direction: ltr;
  text-align: center;
  unicode-bidi: isolate;
  font-family: 'Courier New', monospace;
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--text-dim);
  overflow-x: auto;
  scrollbar-width: none;
  white-space: pre;
}

.swidget-motd::-webkit-scrollbar { display: none; }

.swidget-motd-off { color: rgba(255,140,140,0.85); font-family: var(--font-body); }

.swidget-motd-loading {
  display: block;
  margin: 0 auto;
  width: 70%;
  height: 10px;
  border-radius: 4px;
  background: linear-gradient(90deg, rgba(255,255,255,0.05), rgba(255,255,255,0.12), rgba(255,255,255,0.05));
  background-size: 200% 100%;
  animation: swShimmer 1.4s ease-in-out infinite;
}

@keyframes swShimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

.swidget-foot {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  border-top: 1px solid rgba(255,255,255,0.07);
  background: rgba(0,0,0,0.35);
}

.swidget-state {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

/* Four rising bars, lit when the server answers. */
.ping-bars {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 13px;
  flex-shrink: 0;
}

.ping-bars span {
  width: 3px;
  border-radius: 1px;
  background: rgba(255,255,255,0.16);
  transition: background 0.3s ease, box-shadow 0.3s ease;
}

.ping-bars span:nth-child(1) { height: 4px; }
.ping-bars span:nth-child(2) { height: 7px; }
.ping-bars span:nth-child(3) { height: 10px; }
.ping-bars span:nth-child(4) { height: 13px; }

/* Green, not the site's cyan: this is the one thing on the page that
   reports a live fact, so it answers in the colour everything reports
   "up" in rather than in the brand colour. */
.ping-bars[data-state="online"] span {
  background: var(--online);
  box-shadow: 0 0 9px var(--online-glow);
  animation: pingGleam 4.5s ease-in-out infinite;
}

/* A white gleam crossing the bars every few seconds. It is one flash
   per bar, staggered, rather than a gradient sliding over the whole
   group — the 2px gaps between the bars would show the streak too. The
   stagger runs from the first bar, which on an RTL page is the one on
   the right, so the gleam travels the way the page reads. */
@keyframes pingGleam {
  0%, 86%, 100% {
    background: var(--online);
    box-shadow: 0 0 9px var(--online-glow);
  }
  91% {
    background: #ffffff;
    box-shadow: 0 0 13px rgba(255,255,255,0.7);
  }
}

.ping-bars[data-state="online"] span:nth-child(2) { animation-delay: 0.11s; }
.ping-bars[data-state="online"] span:nth-child(3) { animation-delay: 0.22s; }
.ping-bars[data-state="online"] span:nth-child(4) { animation-delay: 0.33s; }

.ping-bars[data-state="offline"] span {
  background: rgba(255,120,120,0.45);
}

.swidget-live {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-main);
  white-space: nowrap;
}

.swidget-ip {
  flex: 1;
  min-width: 0;
  text-align: center;
  unicode-bidi: isolate;
  font-family: 'Courier New', monospace;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--theme);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Same construction as the site's other buttons — lit top edge, slab
   under it, press drops onto it. */
.swidget-copy {
  position: relative;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 14px;
  border-radius: 10px;
  border: 1px solid rgba(29,200,255,0.4);
  background: linear-gradient(180deg, rgba(29,200,255,0.24), rgba(29,200,255,0.06));
  color: var(--theme);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.16), 0 2px 0 rgba(8,74,100,0.55);
  transition: transform 0.14s cubic-bezier(.22,.61,.36,1),
              background 0.2s ease, color 0.2s ease,
              border-color 0.2s ease, box-shadow 0.22s ease;
}

.swidget-copy svg { width: 15px; height: 15px; flex-shrink: 0; position: relative; z-index: 1; }
.swidget-copy > .copy-label { position: relative; z-index: 1; }

.swidget-copy::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 34%, rgba(255,255,255,0.2) 47%, transparent 62%);
  transform: translateX(-130%);
  transition: transform 0.6s cubic-bezier(.22,.61,.36,1);
}

.swidget-copy:hover::after { transform: translateX(130%); }

.swidget-copy:hover {
  transform: translateY(-2px);
  border-color: rgba(29,200,255,0.65);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.22), 0 4px 0 rgba(8,74,100,0.55);
}

.swidget-copy:active {
  transform: translateY(1px);
  box-shadow: inset 0 2px 5px rgba(0,0,0,0.35), 0 1px 0 rgba(8,74,100,0.55);
}

.swidget-copy.copied {
  background: var(--theme);
  color: #04141c;
  border-color: var(--theme);
}

.swidget-copy:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--bg-deep), 0 0 0 4px rgba(29,200,255,0.8);
}

@media (prefers-reduced-motion: reduce) {
  .swidget-copy::after { display: none; }
  .swidget-copy:hover { transform: none; }
  .swidget-motd-loading { animation: none; }
}

/* =========================================================
   Buttons
   A button here is meant to read as a physical key rather than a
   coloured rectangle: a vertical gradient so the face catches light,
   a bright hairline along the top edge, a darker slab underneath it
   for thickness, and a glow that belongs to the button's own colour.
   Pressing it drops the face onto the slab, which is what makes the
   click feel like it landed.

   The whole set is built from three custom properties, so a new
   colour is three values and nothing else:
     --f  the face colour
     --d  the dark edge under it, and the bottom of the gradient
     --t  the text on top of it
   ========================================================= */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 14px 26px;
  border-radius: var(--radius-md);
  font-size: 15px;
  font-weight: 700;
  font-family: inherit;
  border: none;
  outline: none;
  cursor: pointer;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.14s cubic-bezier(.22,.61,.36,1),
              box-shadow 0.25s ease,
              filter 0.25s ease,
              background 0.25s ease,
              border-color 0.25s ease;
}

/* The gloss. Parked off one edge and swept across on hover — it is
   pure decoration, so it never takes a pointer event and it is hidden
   from anything reading the page aloud. */
.btn::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg,
    transparent 34%,
    rgba(255,255,255,0.26) 47%,
    transparent 62%);
  transform: translateX(-130%);
  transition: transform 0.6s cubic-bezier(.22,.61,.36,1);
}

.btn:hover::after { transform: translateX(130%); }

/* Above the gloss, so the label never dims as it passes. */
.btn > * { position: relative; z-index: 1; }

.btn svg { width: 18px; height: 18px; }

/* ---- the solid, coloured ones ---- */
.btn-primary,
.btn-magenta {
  color: var(--t);
  border: 1px solid rgba(255,255,255,0.28);
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--f) 78%, #fff) 0%,
    var(--f) 46%,
    color-mix(in srgb, var(--f) 82%, var(--d)) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.55),
    inset 0 -9px 16px -12px rgba(0,0,0,0.55),
    0 3px 0 var(--d),
    0 12px 26px -10px color-mix(in srgb, var(--f) 70%, transparent);
}

.btn-primary:hover,
.btn-magenta:hover {
  transform: translateY(-2px);
  filter: saturate(1.08);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.65),
    inset 0 -9px 16px -12px rgba(0,0,0,0.5),
    0 5px 0 var(--d),
    0 20px 38px -12px color-mix(in srgb, var(--f) 85%, transparent);
}

/* The face drops onto the slab: the lift is undone and the thickness
   under it shrinks to almost nothing. */
.btn-primary:active,
.btn-magenta:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 2px 5px rgba(0,0,0,0.3),
    0 1px 0 var(--d),
    0 6px 14px -8px color-mix(in srgb, var(--f) 60%, transparent);
}

.btn-primary { --f: #1DC8FF; --d: #0a6d90; --t: #04222e; }
.btn-magenta { --f: #d84ff5; --d: #7d1a9e; --t: #ffffff; }

/* ---- the quiet one ---- */
.btn-secondary {
  color: var(--text-main);
  background: linear-gradient(180deg, rgba(255,255,255,0.075), rgba(255,255,255,0.025));
  border: 1px solid rgba(255,255,255,0.16);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.1),
    0 3px 0 rgba(0,0,0,0.3),
    0 10px 22px -12px rgba(0,0,0,0.8);
}

.btn-secondary::after {
  background: linear-gradient(100deg, transparent 34%, rgba(255,255,255,0.1) 47%, transparent 62%);
}

.btn-secondary:hover {
  transform: translateY(-2px);
  background: linear-gradient(180deg, rgba(255,255,255,0.12), rgba(255,255,255,0.045));
  border-color: rgba(255,255,255,0.3);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.14),
    0 5px 0 rgba(0,0,0,0.3),
    0 16px 30px -14px rgba(0,0,0,0.85);
}

.btn-secondary:active {
  transform: translateY(2px);
  box-shadow: inset 0 2px 5px rgba(0,0,0,0.35), 0 1px 0 rgba(0,0,0,0.3);
}

/* ---- keyboard ----
   :focus-visible only, so a mouse click doesn't leave a ring behind. */
.btn:focus-visible {
  outline: none;
  box-shadow:
    0 0 0 2px var(--bg-deep),
    0 0 0 4px color-mix(in srgb, var(--f, var(--theme)) 80%, transparent),
    0 12px 26px -10px color-mix(in srgb, var(--f, var(--theme)) 60%, transparent);
}

/* ---- not yet ----
   A disabled button drops its colour entirely rather than wearing a
   faded version of it: a washed-out purple still looks like it wants
   to be pressed, a grey slab does not. */
.btn:disabled,
.btn[aria-disabled="true"] {
  cursor: not-allowed;
  transform: none;
  filter: none;
  color: rgba(238,246,251,0.4);
  background: rgba(255,255,255,0.05);
  border-color: rgba(255,255,255,0.08);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05), 0 2px 0 rgba(0,0,0,0.25);
}

.btn:disabled::after,
.btn[aria-disabled="true"]::after { display: none; }

/* No sweep, no lift — the colour and depth stay, only the motion goes. */
@media (prefers-reduced-motion: reduce) {
  .btn::after { display: none; }
  .btn:hover { transform: none; }
}

.hero-title .logo-hero {
  font-family: var(--font-pixel);
  font-weight: 400;
  letter-spacing: 1px;
  font-size: clamp(42px, 6.4vw, 72px);
  direction: ltr;
  unicode-bidi: isolate;
  display: inline-block;
}

.hero-title .logo-hero .logo-part.logo-blue {
  color: var(--theme);
  text-shadow: 0 0 28px var(--theme-glow), 0 0 60px rgba(29,200,255,0.25);
}

.hero-title .logo-hero .logo-part.logo-white {
  color: #FFFFFF;
  text-shadow: 0 0 18px rgba(255,255,255,0.25);
}

.stat-loading {
  display: inline-block;
  width: 34px;
  height: 16px;
  border-radius: 6px;
  background: linear-gradient(90deg, rgba(29,200,255,0.15) 25%, rgba(29,200,255,0.35) 50%, rgba(29,200,255,0.15) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.4s ease-in-out infinite;
}

@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* =========================================================
   Generic scroll-reveal — applied to any element with this class
   across the whole site (section headers, cards, filler content).
   JS toggles .in-view via IntersectionObserver as the user scrolls.
   ========================================================= */
.reveal-on-scroll {
  opacity: 0;
  transform: translateY(40px);
  transition: opacity 0.8s cubic-bezier(.22,.61,.36,1), transform 0.8s cubic-bezier(.22,.61,.36,1);
}

.reveal-on-scroll.in-view {
  opacity: 1;
  transform: translateY(0);
}

/* =========================================================
   Gamemodes
   ========================================================= */
.modes-section {
  padding: 56px 24px 110px;
  background: var(--bg-deep);
  position: relative;
  overflow: hidden;
}

/* Soft gradient seam instead of a hard border, so the hero flows
   into this section rather than feeling like two stacked blocks */
.modes-section::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(29,200,255,0.35), transparent);
}

.modes-section::before {
  content: '';
  position: absolute;
  top: -260px;
  left: 50%;
  transform: translateX(-50%);
  width: 1000px;
  height: 560px;
  background: radial-gradient(ellipse, rgba(29,200,255,0.12), transparent 65%);
  pointer-events: none;
}

.modes-inner {
  position: relative;
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.section-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}

.section-header-card {
  width: 64px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, rgba(255,255,255,0.035), rgba(255,255,255,0.012));
  border: 1px solid rgba(29,200,255,0.3);
  color: var(--theme);
  box-shadow: 0 0 30px -8px var(--theme-glow), inset 0 1px 0 rgba(255,255,255,0.05);
}
.section-header-card svg { width: 28px; height: 28px; }

.section-header-title {
  font-size: clamp(28px, 3.8vw, 40px);
  font-weight: 800;
  color: var(--text-main);
}

.modes-grid {
  width: 100%;
  margin-top: 44px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
}

.mode-card {
  position: relative;
  opacity: 0;
  transform: translateY(60px) scale(0.96);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: right;
  padding: 30px 26px;
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, rgba(255,255,255,0.035), rgba(255,255,255,0.012));
  border: 1px solid rgba(255,255,255,0.08);
  overflow: hidden;
  transition: opacity 0.8s cubic-bezier(.22,.61,.36,1), transform 0.8s cubic-bezier(.22,.61,.36,1),
              border-color 0.3s ease, box-shadow 0.3s ease;
}

.mode-card.in-view {
  opacity: 1;
  transform: translateY(0) scale(1);
}

.mode-card:nth-child(1) { transition-delay: 0s; }
.mode-card:nth-child(2) { transition-delay: 0.15s; }
.mode-card:nth-child(3) { transition-delay: 0.3s; }

.mode-card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(circle at 30% 0%, rgba(29,200,255,0.08), transparent 55%);
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
}

.mode-card:hover {
  transform: translateY(-6px);
  border-color: rgba(29,200,255,0.35);
  box-shadow: 0 20px 50px -20px rgba(0,0,0,0.6), 0 0 30px -12px var(--theme-glow);
}

.mode-card:hover::after { opacity: 1; }

.mode-icon {
  width: 54px;
  height: 54px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 15px;
  margin-bottom: 20px;
  flex-shrink: 0;
  transform: scale(0.7);
  opacity: 0;
  transition: transform 0.6s cubic-bezier(.34,1.56,.64,1), opacity 0.5s ease;
  transition-delay: 0.15s;
}

.mode-card.in-view .mode-icon {
  transform: scale(1);
  opacity: 1;
}

.mode-icon svg { width: 26px; height: 26px; }

.mode-icon-lifesteal {
  background: rgba(255, 71, 87, 0.12);
  border: 1px solid rgba(255, 71, 87, 0.35);
  color: #ff5c6c;
  box-shadow: 0 0 22px rgba(255, 71, 87, 0.2);
}

.mode-icon-practice {
  background: rgba(29, 200, 255, 0.12);
  border: 1px solid rgba(29, 200, 255, 0.35);
  color: var(--theme);
  box-shadow: 0 0 22px var(--theme-glow);
}

.mode-icon-spacesmp {
  background: rgba(0, 255, 0, 0.12);
  border: 1px solid rgba(0, 255, 0, 0.35);
  color: #00FF00;
  box-shadow: 0 0 22px rgba(0, 255, 0, 0.22);
}

.mode-name {
  margin: 0;
  font-size: 19px;
  font-weight: 800;
  color: var(--text-main);
  direction: ltr;
  text-align: right;
  width: 100%;
}

.mode-desc {
  margin: 10px 0 0;
  color: var(--text-dim);
  font-size: 13.8px;
  line-height: 1.9;
  min-height: 68px;
}

.mode-stats {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid rgba(255,255,255,0.08);
}

.mode-stat {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.mode-stat svg {
  width: 15px;
  height: 15px;
  color: var(--theme);
  flex-shrink: 0;
  opacity: 0.85;
}

.mode-stat-value {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-main);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  direction: ltr;
}

/* =========================================================
   Leaderboard
   --lb is the active gamemode's accent (an "r,g,b" triplet set by
   js/leaderboard.js on the section). Everything inside the card
   derives its color from it, so switching gamemode retints the
   whole block. --rc does the same per row for the podium colors.
   ========================================================= */
.lb-section {
  position: relative;
  padding: 90px 24px 120px;
  background: var(--bg-deep);
  overflow: hidden;
}

.lb-section::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(29,200,255,0.35), transparent);
}

.lb-inner {
  position: relative;
  max-width: 780px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* --- Gamemode switcher --- */
.lb-modes {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  margin-top: 36px;
  padding: 6px;
  border-radius: 999px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.07);
}

.lb-mode {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 20px;
  border-radius: 999px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-dim);
  font-size: 14.5px;
  font-weight: 700;
  letter-spacing: 0.2px;
  direction: ltr;
  transition: color 0.25s ease, background-color 0.25s ease, border-color 0.25s ease;
}

.lb-mode svg { width: 17px; height: 17px; opacity: 0.75; flex-shrink: 0; }

.lb-mode:hover { color: var(--text-main); background: rgba(255,255,255,0.05); }

.lb-mode.active {
  color: rgb(var(--m));
  background: rgba(var(--m), 0.11);
  border-color: rgba(var(--m), 0.36);
}

.lb-mode.active svg { opacity: 1; }
.lb-mode:focus-visible { outline: 2px solid var(--theme); outline-offset: 3px; }

/* --- Card --- */
.lb-card {
  position: relative;
  width: 100%;
  margin-top: 28px;
  border-radius: var(--radius-lg);
  background: linear-gradient(170deg, rgba(255,255,255,0.045), rgba(255,255,255,0.012));
  border: 1px solid rgba(255,255,255,0.08);
  box-shadow: 0 34px 70px -38px rgba(0,0,0,0.9);
  overflow: hidden;
}

/* Accent hairline along the top edge of the card */
.lb-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(var(--lb), 0.35), transparent);
  z-index: 1;
}

/* The wash is the card's last child, so the content blocks below
   need to be lifted over it */
.lb-card::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 240px;
  background: radial-gradient(ellipse 70% 100% at 50% 0%, rgba(var(--lb), 0.05), transparent 70%);
  pointer-events: none;
}

.lb-card-head,
.lb-list { position: relative; z-index: 1; }

.lb-card-head {
  padding: 24px 24px 16px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}

.lb-card-id {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
}

.lb-card-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: rgb(var(--lb));
}
.lb-card-icon svg { width: 26px; height: 26px; }

.lb-card-titles { display: flex; flex-direction: column; gap: 3px; }

.lb-card-mode {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: 0.2px;
  color: var(--text-main);
  direction: ltr;
  text-align: right;
}

.lb-card-sub { font-size: 12.5px; color: var(--text-dim); }

/* --- Stat picker --- */
.lb-stats { display: flex; flex-wrap: wrap; gap: 7px; }

.lb-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 13px;
  border-radius: 10px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.07);
  color: var(--text-dim);
  font-size: 12.5px;
  font-weight: 700;
  direction: ltr;
  white-space: nowrap;
  transition: color 0.22s ease, background-color 0.22s ease, border-color 0.22s ease;
}

.lb-chip svg { width: 14px; height: 14px; opacity: 0.7; flex-shrink: 0; }

.lb-chip:hover {
  color: var(--text-main);
  background: rgba(255,255,255,0.06);
  border-color: rgba(255,255,255,0.14);
}

.lb-chip.active {
  color: rgb(var(--lb));
  background: rgba(var(--lb), 0.12);
  border-color: rgba(var(--lb), 0.38);
}

.lb-chip.active svg { opacity: 1; }
.lb-chip:focus-visible { outline: 2px solid rgb(var(--lb)); outline-offset: 2px; }

/* --- Rows --- */
.lb-list {
  list-style: none;
  margin: 0;
  padding: 12px 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

/* Nothing to rank yet — a fresh install, a gamemode with no stats, or a
   board nobody has scored on. It sits where the rows would. */
.lb-empty {
  list-style: none;
  padding: 26px 10px;
  text-align: center;
  font-size: 13.5px;
  color: var(--text-dim);
}

.lb-row {
  position: relative;
  display: grid;
  grid-template-columns: 40px 40px 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 10px 9px;
  border-radius: 12px;
  border: 1px solid transparent;
  background: rgba(255,255,255,0.018);
  overflow: hidden;
  opacity: 0;
  transform: translateY(10px);
  animation: lbRowIn 0.45s cubic-bezier(.22,.61,.36,1) forwards;
  transition: background-color 0.22s ease, border-color 0.22s ease;
}

@keyframes lbRowIn {
  to { opacity: 1; transform: translateY(0); }
}

/* Share of the leader's score, drawn from the start edge */
.lb-row-bar {
  position: absolute;
  top: 0;
  bottom: 0;
  inset-inline-start: 0;
  background: linear-gradient(to left, rgba(var(--rc), 0.06), rgba(var(--rc), 0));
  pointer-events: none;
}

.lb-row:hover {
  background: rgba(255,255,255,0.055);
  border-color: rgba(255,255,255,0.13);
}

.lb-row.podium {
  background: rgba(var(--rc), 0.042);
  border-color: rgba(var(--rc), 0.17);
}

.lb-row.podium:hover {
  background: rgba(var(--rc), 0.08);
  border-color: rgba(var(--rc), 0.32);
}

.lb-rank {
  position: relative;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 11px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.07);
  color: var(--text-dim);
  font-family: var(--font-pixel);
  font-size: 15px;
  line-height: 1;
  padding-top: 2px;
}

.lb-rank svg { width: 22px; height: 22px; }

.lb-row.podium .lb-rank {
  padding-top: 0;
  background: rgba(var(--rc), 0.11);
  border-color: rgba(var(--rc), 0.28);
  color: rgb(var(--rc));
}

/* A head rendered by api.mcheads.org, stacked over the Steve that
   assets/js/player-head.js puts under every one of them. Pixelated
   keeps the face blocky rather than smearing it the way a photo
   would scale. */
.player-head-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
}

/* The default head, for an account with no Minecraft name linked yet.
   The source is a whole 64x64 skin file, so the face is cropped out of
   it here. Blown up 8x (800%) the 8x8 face fills the frame exactly,
   which makes the skin an 8x8 grid of cells; a background-position
   percentage then picks a cell as cell / (8 - 1). Two layers, hat
   first: the face is cell (1,1) = 14.2857%, the hat overlay that goes
   over it is cell (5,1) = 71.4286%. */
.player-head-skin {
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  background-size: 800% 800%;
  background-position: 71.4286% 14.2857%, 14.2857% 14.2857%;
  image-rendering: pixelated;
}

.lb-head-wrap {
  position: relative;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,0.09);
  background: rgba(255,255,255,0.03);
}

.lb-name {
  position: relative;
  min-width: 0;
  direction: ltr;
  text-align: right;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.2px;
  color: var(--text-main);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.lb-value {
  position: relative;
  direction: ltr;
  padding-inline-start: 6px;
  font-size: 15.5px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--text-main);
  white-space: nowrap;
}

.lb-row.podium .lb-value { color: rgb(var(--rc)); }

/* =========================================================
   Footer
   A single centered column — brand, tagline, social row, then
   a soft divider and copyright. Larger logo, layered glow, and
   a subtle top seam so it reads as a real closing section
   instead of a flat afterthought.
   ========================================================= */
.site-footer {
  position: relative;
  overflow: hidden;
  background: var(--bg-panel);
}

.site-footer::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(29,200,255,0.4), transparent);
}

.footer-glow {
  position: absolute;
  top: -220px;
  left: 50%;
  transform: translateX(-50%);
  width: 900px;
  height: 380px;
  background: radial-gradient(ellipse, rgba(29,200,255,0.1), transparent 65%);
  pointer-events: none;
}

.footer-inner {
  position: relative;
  max-width: 640px;
  margin: 0 auto;
  padding: 44px 32px 22px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.footer-main {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

.footer-logo {
  font-size: 26px;
  filter: drop-shadow(0 0 18px rgba(29,200,255,0.25));
}

.footer-tagline {
  margin: 0;
  max-width: 380px;
  font-size: 14px;
  line-height: 1.8;
  color: var(--text-dim);
}

.footer-social-icons {
  display: flex;
  gap: 12px;
  margin-top: 4px;
}

.footer-social-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  border: 1px solid var(--border-soft);
  background: rgba(29,200,255,0.05);
  color: var(--text-dim);
  cursor: pointer;
  transition: color 0.22s ease, background-color 0.22s ease, border-color 0.22s ease,
    transform 0.22s ease, box-shadow 0.22s ease;
}

.footer-social-btn svg { width: 18px; height: 18px; }
.footer-social-btn img { width: 18px; height: 18px; object-fit: contain; border-radius: 4px; }

.footer-social-btn:hover {
  color: var(--theme);
  background: rgba(29,200,255,0.13);
  border-color: rgba(29,200,255,0.45);
  transform: translateY(-3px);
  box-shadow: 0 10px 24px -10px var(--theme-glow);
}

.footer-divider {
  width: 100%;
  max-width: 300px;
  height: 1px;
  margin: 26px 0 16px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.14), transparent);
}

.footer-bottom {
  font-size: 12.5px;
  color: var(--text-dim);
  letter-spacing: 0.2px;
}

@media (max-width: 640px) {
  .footer-inner { padding: 36px 22px 18px; }
  .footer-logo { font-size: 26px; }
  .footer-social-btn { width: 42px; height: 42px; }
}

/* =========================================================
   Play / Server Info Modal
   ========================================================= */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(4, 7, 11, 0.7);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0.3s ease;
}

.modal-overlay.open {
  opacity: 1;
  visibility: visible;
}

.modal-card {
  position: relative;
  width: 100%;
  max-width: 460px;
  background: linear-gradient(180deg, var(--bg-panel-2), var(--bg-panel));
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  padding: 34px 30px 30px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 16px;
  box-shadow: 0 30px 80px -20px rgba(0,0,0,0.7), 0 0 0 1px rgba(29,200,255,0.04);
  transform: scale(0.94) translateY(10px);
  transition: transform 0.3s cubic-bezier(.22,.61,.36,1);
}

.modal-overlay.open .modal-card {
  transform: scale(1) translateY(0);
}

.modal-close {
  position: absolute;
  top: 16px;
  left: 16px;
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.08);
  color: var(--text-dim);
  transition: background 0.2s ease, color 0.2s ease, transform 0.2s ease;
}
.modal-close svg { width: 16px; height: 16px; }
.modal-close:hover {
  background: rgba(255,255,255,0.1);
  color: var(--text-main);
  transform: rotate(90deg);
}

.modal-icon {
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 16px;
  background: rgba(29,200,255,0.1);
  border: 1px solid rgba(29,200,255,0.3);
  color: var(--theme);
  box-shadow: 0 0 24px var(--theme-glow);
}
.modal-icon svg { width: 26px; height: 26px; }

.modal-title {
  margin: 0;
  font-size: 22px;
  font-weight: 800;
  color: var(--text-main);
}

.modal-steps {
  margin: -6px 0 0;
  padding: 12px 16px;
  border-radius: var(--radius-md);
  background: rgba(29,200,255,0.05);
  border: 1px solid rgba(29,200,255,0.16);
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.95;
  text-align: right;
}

/* The address, set apart from the text around it: this is the one
   thing in the dialog somebody has to take away with them, so it gets
   a lit border and a ground of its own rather than sitting flat. */
.server-ip-box {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 12px;
  border-radius: var(--radius-md);
  background:
    linear-gradient(140deg, rgba(29,200,255,0.09), rgba(255,255,255,0.015)),
    rgba(0,0,0,0.25);
  border: 1px solid rgba(29,200,255,0.26);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06);
  margin-top: 4px;
  transition: border-color 0.22s ease;
}

.server-ip-box:hover { border-color: rgba(29,200,255,0.45); }

/* Copied: the whole box confirms, not just the button. */
.server-ip-box:has(.copy-btn.copied) { border-color: rgba(46,230,166,0.5); }

.server-ip-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  box-sizing: content-box;
  padding: 7px;
  border-radius: 10px;
  background: rgba(29,200,255,0.12);
  border: 1px solid rgba(29,200,255,0.2);
  color: var(--theme);
}

.server-ip-text {
  flex: 1;
  text-align: left;
  direction: ltr;
  font-family: 'Courier New', monospace;
  font-size: 15px;
  font-weight: 700;
  color: var(--text-main);
  letter-spacing: 0.3px;
}

.copy-btn {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 9px 15px;
  border-radius: 10px;
  border: 1px solid rgba(255,255,255,0.28);
  background: linear-gradient(180deg, #6fe2ff 0%, var(--theme) 46%, #109ccb 100%);
  color: #04222e;
  font-family: inherit;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  flex-shrink: 0;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.55),
    0 3px 0 #0a6d90,
    0 10px 22px -10px rgba(29,200,255,0.75);
  transition: transform 0.14s cubic-bezier(.22,.61,.36,1),
              box-shadow 0.22s ease, background 0.22s ease, filter 0.22s ease;
}

.copy-btn::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 34%, rgba(255,255,255,0.3) 47%, transparent 62%);
  transform: translateX(-130%);
  transition: transform 0.6s cubic-bezier(.22,.61,.36,1);
}

.copy-btn:hover::after { transform: translateX(130%); }
.copy-btn > * { position: relative; z-index: 1; }
/* "کپی" and "کپی شد" are different lengths, and swapping the text on
   click used to resize the button — which squeezed the IP beside it and
   shunted the whole row sideways every time somebody copied. Both
   labels now sit in the same grid cell, so the button is permanently as
   wide as the longer one and the click changes nothing but opacity. */
.copy-label {
  display: grid;
  align-items: center;
}

.copy-label > span {
  grid-area: 1 / 1;
  text-align: center;
  white-space: nowrap;
  transition: opacity 0.18s ease;
}

.copy-label-done { opacity: 0; }

.copied .copy-label-idle { opacity: 0; }
.copied .copy-label-done { opacity: 1; }

.copy-btn svg { width: 15px; height: 15px; }
.copy-btn:hover {
  transform: translateY(-2px);
  filter: saturate(1.08);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.65),
    0 5px 0 #0a6d90,
    0 18px 32px -12px rgba(29,200,255,0.9);
}

.copy-btn:active {
  transform: translateY(2px);
  box-shadow: inset 0 2px 5px rgba(0,0,0,0.3), 0 1px 0 #0a6d90;
}

.copy-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--bg-panel), 0 0 0 4px rgba(29,200,255,0.85);
}

.copy-btn.copied {
  background: linear-gradient(180deg, #7df3ce 0%, #2ee6a6 46%, #17b47d 100%);
  border-color: rgba(255,255,255,0.3);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.55),
    0 3px 0 #10855c,
    0 10px 22px -10px rgba(46,230,166,0.8);
}

.modal-info-grid {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-top: 6px;
}

/* Each tile carries its own --i, so the four facts read as four
   things rather than one grey block. The icon sits in a tinted chip
   of that colour; the tile itself stays dark so the values lead. */
.modal-info-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 12px 13px;
  border-radius: var(--radius-md);
  background: linear-gradient(140deg, rgba(var(--i), 0.08), rgba(255,255,255,0.02));
  border: 1px solid rgba(var(--i), 0.2);
  text-align: right;
  overflow: hidden;
  transition: border-color 0.22s ease, background 0.22s ease, transform 0.22s ease;
}

.modal-info-item:hover {
  transform: translateY(-2px);
  border-color: rgba(var(--i), 0.4);
  background: linear-gradient(140deg, rgba(var(--i), 0.14), rgba(255,255,255,0.03));
}

/* The icon's own plate, which is what carries the tile's colour. */
.modal-info-item svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  box-sizing: content-box;
  padding: 7px;
  border-radius: 10px;
  background: rgba(var(--i), 0.14);
  border: 1px solid rgba(var(--i), 0.22);
  color: rgb(var(--i));
}

.modal-info-item > div {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.modal-info-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-dim);
}

.modal-info-value {
  font-size: 15px;
  font-weight: 800;
  color: var(--text-main);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* "1.20 - 26.2" and "18 / 19" are Latin runs in a right-to-left page.
   Without isolation the browser reorders them around the separator and
   the player count comes out as max-then-online — the wrong way round,
   and wrong in a way that looks plausible. */
.modal-info-value.is-ltr {
  direction: ltr;
  unicode-bidi: isolate;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.modal-info-value.online { color: #2ee6a6; }
.modal-info-value.offline { color: #ff5c5c; }

.modal-cta {
  width: 100%;
  justify-content: center;
  margin-top: 8px;
}

/* =========================================================
   Auth pages (login.html / register.html)
   Full standalone pages, not a modal — same visual language
   (card, tabs-less since each page is its own form) as a
   centered panel over the site's background.
   ========================================================= */
.auth-page {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 110px 20px 60px;
  overflow: hidden;
}

.auth-page-glow {
  position: absolute;
  top: -220px;
  left: 50%;
  transform: translateX(-50%);
  width: 1000px;
  height: 520px;
  background: radial-gradient(ellipse, rgba(29,200,255,0.12), transparent 65%);
  pointer-events: none;
}

.auth-panel {
  position: relative;
  width: 100%;
  max-width: 400px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 18px;
  padding: 36px 30px 32px;
  border-radius: var(--radius-lg);
  background: linear-gradient(180deg, var(--bg-panel-2), var(--bg-panel));
  border: 1px solid var(--border-soft);
  box-shadow: 0 30px 80px -20px rgba(0,0,0,0.7), 0 0 0 1px rgba(29,200,255,0.04);
}

.auth-panel-icon {
  width: 52px;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 15px;
  background: rgba(29,200,255,0.12);
  border: 1px solid rgba(29,200,255,0.35);
  color: var(--theme);
  box-shadow: 0 0 30px -4px var(--theme-glow);
}

.auth-panel-icon svg { width: 24px; height: 24px; }

.auth-panel-title {
  margin: 0;
  font-size: 21px;
  font-weight: 800;
  color: var(--text-main);
}

.auth-panel-sub {
  margin: -8px 0 0;
  font-size: 13.5px;
  color: var(--text-dim);
  line-height: 1.8;
}

.auth-switch {
  font-size: 13.5px;
  color: var(--text-dim);
}

.auth-switch a {
  color: var(--theme);
  font-weight: 700;
  text-decoration: none;
}

.auth-switch a:hover { text-decoration: underline; }

.auth-error {
  width: 100%;
  margin: 0;
  padding: 10px 14px;
  border-radius: var(--radius-md);
  background: rgba(255,92,108,0.1);
  border: 1px solid rgba(255,92,108,0.3);
  color: #ff8792;
  font-size: 13px;
  line-height: 1.7;
  text-align: center;
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: 100%;
}

.auth-field {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  text-align: right;
}

.auth-field span:first-child {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-dim);
}

.auth-field input {
  width: 100%;
  padding: 12px 14px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-soft);
  background: var(--bg-deep);
  color: var(--text-main);
  font-family: var(--font-body);
  font-size: 14.5px;
  direction: ltr;
  text-align: left;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.auth-field input:focus {
  outline: none;
  border-color: rgba(29,200,255,0.5);
  box-shadow: 0 0 0 3px rgba(29,200,255,0.12);
}

.auth-hint {
  font-size: 11.5px;
  color: var(--text-dim);
  opacity: 0.75;
}

/* --- Honeypot field: present in the DOM for bots, invisible and
   unreachable for real users (off-screen, not display:none — some
   bots skip display:none fields specifically, so this is safer). --- */
.hp-field {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* --- Click-to-verify card (Cloudflare-Turnstile style) --- */
.verify-card {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 14px 16px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-soft);
  background: var(--bg-deep);
  cursor: pointer;
  text-align: right;
  transition: border-color 0.25s ease, background-color 0.25s ease, box-shadow 0.25s ease;
}

.verify-card:hover {
  border-color: rgba(29,200,255,0.35);
  background: rgba(29,200,255,0.04);
}

.verify-card[data-state="verified"] {
  border-color: rgba(29,200,255,0.5);
  background: rgba(29,200,255,0.08);
  box-shadow: 0 0 0 1px rgba(29,200,255,0.15);
  cursor: default;
}

.verify-box {
  position: relative;
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  border: 1.5px solid var(--border-soft);
  background: var(--bg-panel);
  transition: border-color 0.25s ease, background-color 0.25s ease;
}

.verify-box svg {
  position: absolute;
  width: 16px;
  height: 16px;
  color: var(--theme);
  opacity: 0;
  transition: opacity 0.2s ease, transform 0.2s ease;
}

/* Determinate progress ring: sweeps 0% -> 100% over --verify-duration,
   which verify-widget.js sets so the timing lives in one place.
   Scoped under .verify-box so it outranks the 16px `.verify-box svg`
   sizing above — the ring wants to fill the box, the tick doesn't. */
.verify-box .verify-progress {
  width: 22px;
  height: 22px;
  transform: rotate(-90deg); /* start the sweep at 12 o'clock */
  transform-origin: center;
}

.verify-progress circle {
  fill: none;
  stroke-width: 3.5;
  stroke-linecap: round;
}

.verify-progress-track { stroke: rgba(255,255,255,0.10); }

.verify-progress-bar {
  stroke: currentColor;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
}

@keyframes verifyFill {
  to { stroke-dashoffset: 0; }
}

.verify-card[data-state="verifying"] .verify-box {
  border-color: rgba(29,200,255,0.4);
}
.verify-card[data-state="verifying"] .verify-progress { opacity: 1; }
.verify-card[data-state="verifying"] .verify-progress-bar {
  animation: verifyFill var(--verify-duration, 3s) linear forwards;
}

/* A person who asked for less motion gets the ring filled straight away
   rather than a three-second sweep. */
@media (prefers-reduced-motion: reduce) {
  .verify-card[data-state="verifying"] .verify-progress-bar {
    animation-duration: 1ms;
  }
}

.verify-card[data-state="verified"] .verify-box {
  border-color: var(--theme);
  background: rgba(29,200,255,0.15);
}
.verify-card[data-state="verified"] .verify-check {
  opacity: 1;
  transform: scale(1);
}
.verify-card[data-state="idle"] .verify-check,
.verify-card[data-state="verifying"] .verify-check {
  transform: scale(0.5);
}

.verify-label {
  flex: 1;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text-main);
}

.verify-brand {
  font-family: var(--font-pixel);
  font-size: 10px;
  letter-spacing: 0.3px;
  color: var(--text-dim);
  opacity: 0.6;
  direction: ltr;
  white-space: nowrap;
}

.auth-submit {
  width: 100%;
  justify-content: center;
  margin-top: 2px;
}

/* The disabled look is the shared .btn:disabled one. */

@media (max-width: 480px) {
  .auth-panel { padding: 30px 22px 26px; }
}

/* =========================================================
   Not found (404)

   No card here — a card would make a dead end look like a form. The
   page is one centred stack over the site's background: the code
   itself, big, with a player head standing in for the zero.
   ========================================================= */
.notfound {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 130px 20px 80px;
  overflow: hidden;
  text-align: center;
}

.notfound-bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* Two crossed gradients draw a grid of blocks; the mask fades it out
   before the edges so it reads as texture rather than as a table. */
.notfound-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(29,200,255,0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(29,200,255,0.07) 1px, transparent 1px);
  background-size: 54px 54px;
  -webkit-mask-image: radial-gradient(ellipse 52% 46% at 50% 44%, #000, transparent 100%);
  mask-image: radial-gradient(ellipse 52% 46% at 50% 44%, #000, transparent 100%);
}

/* Sits over the grid, centred on the number, so the type has something
   to stand in front of. */
.notfound-glow {
  position: absolute;
  top: 44%;
  left: 50%;
  width: min(760px, 120vw);
  height: min(520px, 70vh);
  transform: translate(-50%, -50%);
  background: radial-gradient(ellipse, rgba(29,200,255,0.2), rgba(29,200,255,0.05) 45%, transparent 70%);
}

.notfound-inner {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  max-width: 460px;
}

.notfound-heading {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}

.notfound-code {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.06em;
  font-family: var(--font-pixel);
  font-size: clamp(88px, 24vw, 158px);
  font-weight: 400;
  line-height: 1;
  direction: ltr;
  unicode-bidi: isolate;
}

/* Lit from behind rather than outlined — a hard drop shadow at this
   size only muddies the pixels. */
.notfound-digit {
  color: #ffffff;
  text-shadow: 0 0 40px rgba(29,200,255,0.5), 0 0 90px rgba(29,200,255,0.25);
}

/* The spoken zero, kept off-screen behind the head that replaces it. */
.notfound-zero {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}

/* Sized in em so it tracks the digits either side of it at every
   viewport width. Filled by assets/js/player-head.js. */
.notfound-head {
  position: relative;
  flex-shrink: 0;
  width: 0.82em;
  height: 0.82em;
  border-radius: 0.1em;
  overflow: hidden;
  box-shadow:
    0 0 0 2px rgba(29,200,255,0.5),
    0 0 60px -8px var(--theme-glow);
  animation: notFoundBob 4s ease-in-out infinite;
}

@keyframes notFoundBob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-10px); }
}

/* Ties the number to the sentence under it, and gives the stack a
   waist so it doesn't read as three loose lines. */
.notfound-rule {
  width: 152px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, rgba(29,200,255,0.85), transparent);
  box-shadow: 0 0 16px rgba(29,200,255,0.5);
}

.notfound-title {
  font-size: clamp(21px, 4.2vw, 27px);
  font-weight: 800;
  color: var(--text-main);
  letter-spacing: -0.2px;
}

.notfound-sub {
  margin: 0;
  font-size: 15px;
  color: var(--text-dim);
  line-height: 1.9;
}

/* The address that missed, in the shape of a path — mono, ltr, and
   quiet enough to stay a detail. */
.notfound-path {
  margin: 0;
  max-width: 100%;
  padding: 7px 15px;
  border-radius: 999px;
  background: rgba(255,255,255,0.035);
  border: 1px solid rgba(255,255,255,0.08);
  font-family: 'Courier New', monospace;
  font-size: 12.5px;
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  unicode-bidi: isolate;
}

.notfound-back { margin-top: 10px; }

/* ---------- Maintenance page (reuses the 404 layout) ---------- */
.maintenance-icon {
  display: grid;
  place-items: center;
  width: 108px;
  height: 108px;
  border-radius: 28px;
  color: var(--theme);
  background: rgba(29,200,255,0.08);
  border: 1px solid rgba(29,200,255,0.3);
  box-shadow: 0 0 60px -10px var(--theme-glow);
  animation: notFoundBob 4s ease-in-out infinite;
}

.maintenance-icon svg { width: 54px; height: 54px; }

.maintenance-note {
  padding: 12px 18px;
  border-radius: 14px;
  background: rgba(255,255,255,0.035);
  border: 1px solid rgba(255,255,255,0.08);
  color: var(--text-main);
  white-space: pre-line;
}

.maintenance-wait {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 6px 0 0;
  font-size: 13px;
  color: var(--text-dim);
}

.maintenance-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--theme);
  box-shadow: 0 0 10px var(--theme);
  animation: maintenancePulse 1.6s ease-in-out infinite;
}

@keyframes maintenancePulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}

.maintenance-staff {
  margin-top: 18px;
  font-size: 12px;
  color: var(--text-dim);
  opacity: 0.6;
  text-decoration: none;
}

.maintenance-staff:hover { opacity: 1; color: var(--theme); }

@media (max-width: 560px) {
  .notfound { padding: 110px 18px 70px; }
  .notfound-grid { background-size: 40px 40px; }
  .notfound-heading { gap: 16px; }
  .notfound-rule { width: 110px; }
  .notfound-back { width: 100%; justify-content: center; }
}

/* =========================================================
   Dashboard sidebar

   The dashboard drops the navbar entirely — this fixed icon rail on the
   right (the start edge, the page being RTL) is its whole navigation:
   the logo mark on top, the sections in the middle, logout pinned to the
   bottom. No labels: every control names itself with aria-label/title.
   ========================================================= */
.dash-body {
  --sidebar-w: 104px;
  padding-right: var(--sidebar-w);
}

.sidebar {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 900;
  width: var(--sidebar-w);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px 12px;
  background: rgba(8, 13, 20, 0.92);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  border-left: 1px solid var(--border-soft);
}

/* Both logos below reuse .nav-logo, so the font, weight, colors and
   glow come from one place — the wordmark in the navbar. These rules
   only say how big it is and where it sits. */
.sidebar-logo {
  justify-content: center;
  flex-shrink: 0;
  padding-bottom: 18px;
  margin-bottom: 6px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  font-size: 14px;
  transition: opacity 0.25s ease;
}

.sidebar-logo:hover { opacity: 0.85; }

.sidebar-nav {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 18px;
  border-top: 1px solid rgba(255,255,255,0.06);
}

.sidebar-item {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  flex-shrink: 0;
  padding: 0;
  border: 0;
  border-radius: 14px;
  background: none;
  color: var(--text-dim);
  cursor: pointer;
  transition: background-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
}

.sidebar-icon { width: 20px; height: 20px; }

.sidebar-item:hover { background: rgba(255,255,255,0.06); color: var(--text-main); }

.sidebar-item[aria-current="page"] {
  color: var(--theme);
  background: rgba(29,200,255,0.12);
  box-shadow: inset 0 0 0 1px rgba(29,200,255,0.3);
}

.sidebar-logout {
  margin-top: 10px;
  color: #ff8d99;
  background: rgba(255,92,108,0.07);
  box-shadow: inset 0 0 0 1px rgba(255,92,108,0.22);
}

.sidebar-logout:hover {
  background: rgba(255,92,108,0.14);
  color: #ffb3bb;
}

@media (max-width: 560px) {
  .dash-body { --sidebar-w: 84px; }
  .sidebar { padding: 14px 9px; }
  .sidebar-logo { font-size: 11.5px; padding-bottom: 14px; }
  .sidebar-item { width: 40px; height: 40px; border-radius: 12px; }
  .sidebar-icon { width: 18px; height: 18px; }
}

/* =========================================================
   Dashboard page
   ========================================================= */
.dash-section {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  padding: 70px 30px 90px;
  overflow: hidden;
}

.dash-glow {
  position: absolute;
  top: -200px;
  left: 50%;
  transform: translateX(-50%);
  width: 1000px;
  height: 480px;
  background: radial-gradient(ellipse, rgba(29,200,255,0.1), transparent 65%);
  pointer-events: none;
}

.dash-inner {
  position: relative;
  width: 100%;
  max-width: 1080px;
  margin: 0 auto;
}

.dash-blocks {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  margin-top: 22px;
}

.dash-card-block {
  padding: 26px;
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, rgba(255,255,255,0.035), rgba(255,255,255,0.012));
  border: 1px solid var(--border-soft);
}

/* --- Minecraft account link card --- */
.mc-link-card {
  /* A short form reads better as a column than stretched across the
     dashboard's full width. */
  width: 100%;
  max-width: 440px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
  padding: 34px 30px 30px;
}

.mc-link-logo {
  justify-content: center;
  font-size: 34px;
}

.mc-link-title {
  margin: 0;
  font-size: 21px;
  font-weight: 800;
  color: var(--text-main);
  text-align: center;
}

.mc-link-form {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.mc-link-field {
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.mc-link-label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-dim);
}

.mc-link-label-icon { width: 16px; height: 16px; color: var(--theme); }

/* The icon sits inside the field, at the start edge. */
.mc-link-input {
  position: relative;
  display: block;
}

.mc-link-input-icon {
  position: absolute;
  top: 50%;
  right: 14px;
  transform: translateY(-50%);
  width: 17px;
  height: 17px;
  color: var(--text-dim);
  opacity: 0.7;
  pointer-events: none;
}

.mc-link-input input {
  width: 100%;
  padding: 14px 42px 14px 16px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-soft);
  background: var(--bg-deep);
  color: var(--text-main);
  font-family: var(--font-body);
  font-size: 14.5px;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.mc-link-input input::placeholder { color: var(--text-dim); opacity: 0.55; }

.mc-link-input input:focus {
  outline: none;
  border-color: rgba(29,200,255,0.5);
  box-shadow: 0 0 0 3px rgba(29,200,255,0.12);
}

.mc-link-submit {
  width: 100%;
  justify-content: center;
}

.mc-link-note {
  width: 100%;
  margin: 0;
  padding: 10px 14px;
  border-radius: var(--radius-md);
  background: rgba(29,200,255,0.1);
  border: 1px solid rgba(29,200,255,0.3);
  color: var(--theme);
  font-size: 13px;
  line-height: 1.7;
  text-align: center;
}

/* --- Link flow -----------------------------------------------------
   Two steps that swap places in the same card. The card always says
   which one you are on, because the second one sends you off to another
   window and you have to know what you were doing when you come back. */
.link-steps {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: -8px 0 0;
  padding: 0;
  list-style: none;
}

.link-step {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-dim);
  opacity: 0.5;
  transition: opacity 0.25s ease, color 0.25s ease;
}

/* A rule between the two, so they read as a sequence and not a list. */
.link-step + .link-step::before {
  content: '';
  width: 26px;
  height: 1px;
  margin-inline-end: 3px;
  background: rgba(255,255,255,0.18);
}

.link-step-num {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 21px;
  height: 21px;
  border-radius: 50%;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.14);
  font-size: 11.5px;
}

.link-step.current { opacity: 1; color: var(--text-main); }

.link-step.current .link-step-num {
  background: rgba(29,200,255,0.14);
  border-color: rgba(29,200,255,0.5);
  color: var(--theme);
}

.link-step.done { opacity: 0.75; }

.link-step.done .link-step-num {
  background: rgba(62,224,127,0.14);
  border-color: rgba(62,224,127,0.45);
  color: var(--online);
}

.code-panel {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

/* Which account the boxes are for. The field it was typed into is gone by
   now, so this is the only way to check it before committing. */
.code-panel-for {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(29,200,255,0.07);
  border: 1px solid rgba(29,200,255,0.22);
  font-size: 12.5px;
  color: var(--text-dim);
}

.code-panel-for strong {
  color: var(--theme);
  font-weight: 800;
  unicode-bidi: isolate;
}

/* The head of the name that was typed — a typo shows up here as the wrong
   face before the code is ever entered. */
.code-panel-for-head {
  position: relative;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  overflow: hidden;
  flex-shrink: 0;
  background: rgba(255,255,255,0.06);
}

/* The command has to be reproduced exactly in another window, so it is set
   apart from the sentence and carries its own copy button. */
.code-cmd {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 8px 8px 8px;
  border-radius: 10px;
  background: rgba(255,255,255,0.035);
  border: 1px solid rgba(255,255,255,0.1);
}

.code-cmd-text {
  flex: 1;
  min-width: 0;
  padding-inline-start: 8px;
  font-family: 'Courier New', monospace;
  font-size: 14.5px;
  font-weight: 700;
  color: var(--theme);
  unicode-bidi: isolate;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.code-cmd-copy {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 7px 12px;
  border-radius: 7px;
  background: rgba(29,200,255,0.1);
  border: 1px solid rgba(29,200,255,0.35);
  color: var(--theme);
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.code-cmd-copy svg { width: 13px; height: 13px; }
.code-cmd-copy:hover { background: rgba(29,200,255,0.18); border-color: rgba(29,200,255,0.6); }

.code-cmd-copy.copied {
  background: var(--online);
  border-color: var(--online);
  color: #04141c;
}

.code-panel-step {
  margin: 0;
  font-size: 13.5px;
  line-height: 2;
  color: var(--text-dim);
  text-align: center;
}

/* The command is the one thing on this card a player has to copy by eye,
   so it is set apart from the sentence around it. */
.code-panel-cmd {
  display: inline-block;
  margin: 0 3px;
  padding: 3px 9px;
  border-radius: 6px;
  background: rgba(29,200,255,0.1);
  border: 1px solid rgba(29,200,255,0.3);
  color: var(--theme);
  font-family: 'Courier New', monospace;
  font-size: 13px;
  font-weight: 700;
  unicode-bidi: isolate;
}

.code-boxes {
  display: flex;
  justify-content: center;
  gap: 9px;
}

.code-boxes input {
  width: 46px;
  height: 56px;
  padding: 0;
  border-radius: 10px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.12);
  color: var(--text-main);
  font-family: var(--font-pixel);
  font-size: 24px;
  text-align: center;
  outline: none;
  transition: border-color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}

.code-boxes input:focus {
  border-color: var(--theme);
  background: rgba(29,200,255,0.07);
  box-shadow: 0 0 0 3px rgba(29,200,255,0.14);
}

/* A filled box reads as done without needing a tick next to it. */
.code-boxes input:not(:placeholder-shown),
.code-boxes input:valid {
  border-color: rgba(29,200,255,0.4);
}

.code-panel-actions {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.code-submit { width: 100%; justify-content: center; }

.code-back {
  background: none;
  border: none;
  color: var(--text-dim);
  font-family: inherit;
  font-size: 12.5px;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.code-back:hover { color: var(--text-main); }

.mc-link-note.error { color: #ff8f8f; }

/* =========================================================
   Dashboard — the linked view

   The gamemode buttons and the card are the leaderboard's, reused as-is:
   the same product should not have two ways of drawing the same thing.
   What is different is inside the card — one player's numbers rather
   than ten players' ranks.
   ========================================================= */
.dash-stats {
  width: 100%;
  max-width: 760px;
  margin: 22px auto 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* Who this account is in game, above the numbers so there is never a
   doubt whose they are. */
.dash-identity {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 20px;
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, rgba(255,255,255,0.045), rgba(255,255,255,0.012));
  border: 1px solid rgba(255,255,255,0.08);
}

.dash-identity-head {
  position: relative;
  width: 46px;
  height: 46px;
  border-radius: 11px;
  overflow: hidden;
  flex-shrink: 0;
  background: rgba(255,255,255,0.05);
  box-shadow: 0 0 0 1px rgba(29,200,255,0.35);
}

.dash-identity-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.dash-identity-name {
  font-size: 17px;
  font-weight: 800;
  color: var(--text-main);
  unicode-bidi: isolate;
}

.dash-identity-sub { font-size: 12.5px; color: var(--text-dim); }

.dash-unlink {
  margin-inline-start: auto;
  flex-shrink: 0;
  padding: 8px 14px;
  border-radius: 9px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.12);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
}

.dash-unlink:hover {
  color: #ff8f8f;
  border-color: rgba(255,143,143,0.4);
  background: rgba(255,143,143,0.08);
}

.dash-unlink:disabled { opacity: 0.5; cursor: not-allowed; }

.dash-modes { margin-top: 22px; }
.dash-stats-card { margin-top: 18px; }

/* The leaderboard's card head carries a row of stat chips under the
   title; this one doesn't, so it keeps neither the room for them nor the
   padding that framed them. */
.dash-stats-card .lb-card-head { padding: 16px 18px; }
.dash-stats-card .lb-card-id { margin-bottom: 0; gap: 11px; }
.dash-stats-card .lb-card-icon svg { width: 21px; height: 21px; }
.dash-stats-card .lb-card-mode { font-size: 16px; }
.dash-stats-card .lb-card-sub { font-size: 12px; }

/* --- The player's own numbers ---
   Small tiles on a grid that reflows by width rather than by count, so
   five stats and nine stats both end up evenly spread instead of leaving
   a half-empty last row. */
.dash-stat-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(146px, 1fr));
  gap: 9px;
  padding: 14px;
}

.dash-stat {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 12px 13px;
  border-radius: 13px;
  background: rgba(255,255,255,0.028);
  border: 1px solid rgba(255,255,255,0.055);
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.dash-stat:hover {
  background: rgba(var(--lb), 0.05);
  border-color: rgba(var(--lb), 0.28);
}

/* Icon and name share a line above the number, which lets the number be
   the biggest thing in the tile without the tile growing to fit it. */
.dash-stat-head {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.dash-stat-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 23px;
  height: 23px;
  flex-shrink: 0;
  border-radius: 7px;
  background: rgba(var(--lb), 0.11);
  color: rgb(var(--lb));
}

.dash-stat-icon svg { width: 13px; height: 13px; }

.dash-stat-label {
  font-size: 11.5px;
  font-weight: 700;
  color: var(--text-dim);
  direction: ltr;
  text-align: start;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dash-stat-value {
  font-size: 19px;
  font-weight: 800;
  color: var(--text-main);
  direction: ltr;
  text-align: start;
  unicode-bidi: isolate;
  /* Same-width digits, so a column of numbers lines up down the grid. */
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A stat the server defines but whose placeholder returned nothing —
   shown greyed rather than hidden, so the gap is visible and fixable. */
.dash-stat.missing { border-style: dashed; }
.dash-stat.missing:hover { background: rgba(255,255,255,0.028); border-color: rgba(255,255,255,0.1); }
.dash-stat.missing .dash-stat-value { color: var(--text-dim); opacity: 0.6; }
.dash-stat.missing .dash-stat-icon { background: rgba(255,255,255,0.04); color: var(--text-dim); }

.dash-stat-empty {
  grid-column: 1 / -1;
  margin: 0;
  padding: 26px 20px;
  text-align: center;
  font-size: 13.5px;
  color: var(--text-dim);
}

/* --- A titled panel under the stats ---------------------------------
   Same surface as the stats card, but it holds a form rather than a
   grid. Only one so far (the game password), which is why it is a
   generic shell rather than named after it. */
.dash-panel {
  width: 100%;
  margin-top: 18px;
  border-radius: var(--radius-lg);
  background: linear-gradient(170deg, rgba(255,255,255,0.04), rgba(255,255,255,0.012));
  border: 1px solid rgba(255,255,255,0.08);
  overflow: hidden;
}

.dash-panel-head {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 16px 18px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}

.dash-panel-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: 10px;
  background: rgba(29,200,255,0.1);
  color: var(--theme);
}

.dash-panel-icon svg { width: 18px; height: 18px; }

.dash-panel-titles { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.dash-panel-title { font-size: 15px; font-weight: 800; color: var(--text-main); }
.dash-panel-sub { font-size: 12px; color: var(--text-dim); }

/* --- Game password form --- */
/* The two fields are one thought, so they sit side by side and the
   button spans them. */
.dash-password-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px 16px;
  padding: 18px;
}

.dash-password-submit {
  grid-column: 1 / -1;
  justify-content: center;
}

.dash-password-submit svg { width: 17px; height: 17px; }
/* .dash-password-submit is a .btn — see .btn:disabled. */

/* The eye sits where the link form's icon does, but this one is a
   button, so it takes the pointer events that one gives up. */
.pw-reveal {
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text-dim);
  opacity: 0.7;
  cursor: pointer;
  transition: color 0.2s ease, opacity 0.2s ease, background-color 0.2s ease;
}

.pw-reveal svg { width: 17px; height: 17px; }
.pw-reveal:hover { opacity: 1; color: var(--text-main); background: rgba(255,255,255,0.05); }
.pw-reveal[aria-pressed="true"] { color: var(--theme); opacity: 1; }
.pw-reveal:focus-visible { outline: 2px solid var(--theme); outline-offset: 1px; }

.dash-password-note {
  margin: 0 18px 18px;
  width: auto;
}

/* Waiting on the proxy to pick the change up — the one state here that
   isn't over in a single request. */
.dash-password-note.pending {
  background: rgba(255,255,255,0.04);
  border-color: rgba(255,255,255,0.12);
  color: var(--text-dim);
}

.dash-password-note.done {
  background: rgba(62,224,127,0.1);
  border-color: rgba(62,224,127,0.32);
  color: #6fe6a2;
}

.dash-error {
  margin: 24px 0 0;
  font-size: 13.5px;
  color: #ff8f8f;
  text-align: center;
}

@media (max-width: 560px) {
  .code-boxes { gap: 6px; }
  .code-boxes input { width: 40px; height: 50px; font-size: 21px; }
  .dash-identity { flex-wrap: wrap; }
  .dash-unlink { margin-inline-start: 0; width: 100%; }
  .dash-stat-grid { grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); gap: 8px; padding: 12px; }
  .dash-stat-value { font-size: 17px; }
  /* Two fields stacked: side by side at this width leaves neither of
     them wide enough to read a password in. */
  .dash-password-form { grid-template-columns: 1fr; }
}


@media (max-width: 760px) {
  .dash-section { padding: 46px 18px 70px; }
}

/* =========================================================
   Responsive
   ========================================================= */
@media (max-width: 980px) {
  .nav-links { display: none; }
  .nav-burger { display: flex; }
  .mobile-menu.open { display: flex; }
  .nav-auth { display: none; }
  .navbar-inner { padding: 14px 20px; }
  .modes-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 760px) {
  .lb-stats {
    flex-wrap: nowrap;
    overflow-x: auto;
    padding-bottom: 4px;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .lb-stats::-webkit-scrollbar { display: none; }
  .lb-chip { flex: 0 0 auto; }
}

@media (max-width: 640px) {
  .hero { padding: 120px 20px 80px; }

  /* No room to leave half the picture open, so the scrim covers the
     whole frame — heaviest across the middle, which is where the type
     lands, rather than at the edges where nothing is. */
  .hero-scrim {
    background:
      linear-gradient(180deg,
        rgba(5,8,12,0.7) 0%,
        rgba(5,8,12,0.84) 34%,
        rgba(5,8,12,0.88) 66%,
        #05080c 100%);
  }

  .hero-content { max-width: 100%; width: 100%; gap: 18px; }
  .hero-sub { max-width: 100%; font-size: 15.5px; }
  .swidget { max-width: 100%; }
  .swidget-top { padding: 12px; gap: 10px; }
  .swidget-icon { width: 72px; }
  .swidget-motd { font-size: 10px; }
  .swidget-foot { flex-wrap: wrap; gap: 8px; padding: 10px 12px; }
  .swidget-ip { order: 3; width: 100%; flex: none; text-align: center; }
  .swidget-copy { margin-inline-start: auto; }
  .swidget-copy svg { width: 14px; height: 14px; }
  .hero-actions { width: 100%; }
  .hero-actions .btn { flex: 1 1 auto; justify-content: center; }
  .lb-section { padding: 70px 16px 90px; }
  .lb-mode { padding: 10px 15px; font-size: 13.5px; gap: 7px; }
  .lb-mode svg { width: 15px; height: 15px; }
  .lb-list { padding: 10px 10px 12px; }
  .lb-row { grid-template-columns: 34px 34px 1fr auto; gap: 10px; padding: 11px 7px; }
  .lb-rank { width: 34px; height: 34px; border-radius: 9px; font-size: 13px; }
  .lb-rank svg { width: 19px; height: 19px; }
  .lb-head-wrap { width: 34px; height: 34px; border-radius: 8px; }
  .lb-name { font-size: 14px; }
  .lb-value { font-size: 14px; }
  .lb-card-head { padding: 20px 18px 14px; }
  .lb-card-mode { font-size: 17px; }
  .navbar.scrolled { left: 12px; right: 12px; top: 10px; }
  .modal-info-grid { grid-template-columns: 1fr; }
  .modal-card { padding: 28px 20px 24px; }
  .modes-grid { grid-template-columns: 1fr; }
  .modes-section { padding: 80px 20px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
  html { scroll-behavior: auto; }
}

/* =========================================================
   Shop — /store and /store/result

   Everything in Minecraft is a grid of coloured squares, so the product
   art is too: hand-drawn pixel marks on a plate tinted with that
   product's own colour, carried in as --c. The art is the one loud thing
   on the page; the rest — type, spacing, buttons — stays quiet so a wall
   of nine cards reads as nine products rather than nine posters.

   Money is gold and the interface is cyan, everywhere. A price never
   wears the same colour as a button.
   ========================================================= */
:root {
  --gold: #f5c451;
  --gold-dim: rgba(245, 196, 81, 0.16);
}

.shop {
  position: relative;
  min-height: 100vh;
  padding: 116px 0 90px;
  overflow: hidden;
}

/* One wash behind the header, tinted toward the site accent. It is the
   only decoration on the page that isn't a product. */
.shop-aurora {
  position: absolute;
  top: -260px;
  left: 50%;
  transform: translateX(-50%);
  width: 1100px;
  height: 640px;
  background:
    radial-gradient(ellipse 50% 60% at 40% 50%, rgba(29,200,255,0.14), transparent 70%),
    radial-gradient(ellipse 45% 55% at 68% 40%, rgba(138,123,255,0.11), transparent 72%);
  pointer-events: none;
}

.shop-inner {
  position: relative;
  z-index: 1;
  width: min(1220px, 92%);
  margin: 0 auto;
}

/* --- Header ---------------------------------------------------------
   Who you are and what you can narrow it down by, in one band. */
.shop-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 20px 22px;
  border-radius: var(--radius-lg);
  background: linear-gradient(150deg, rgba(255,255,255,0.055), rgba(255,255,255,0.012));
  border: 1px solid rgba(255,255,255,0.09);
}

.shop-head-id { display: flex; align-items: center; gap: 14px; min-width: 0; }

.shop-head-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 50px;
  height: 50px;
  flex-shrink: 0;
  border-radius: 15px;
  background: linear-gradient(150deg, rgba(29,200,255,0.24), rgba(29,200,255,0.07));
  border: 1px solid rgba(29,200,255,0.35);
  color: var(--theme);
}

.shop-head-mark svg { width: 24px; height: 24px; }

.shop-head-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.shop-head-title { margin: 0; font-size: 22px; font-weight: 800; color: var(--text-main); }

.shop-head-sub {
  margin: 0;
  max-width: 46ch;
  font-size: 12.5px;
  line-height: 1.9;
  color: var(--text-dim);
}

.shop-head-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }

.shop-cats { display: flex; flex-wrap: wrap; gap: 7px; }

.shop-cat {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 10px 14px;
  border-radius: 11px;
  background: rgba(255,255,255,0.035);
  border: 1px solid rgba(255,255,255,0.09);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: color 0.18s ease, border-color 0.18s ease, background-color 0.18s ease;
}

.shop-cat svg { width: 16px; height: 16px; flex-shrink: 0; opacity: 0.8; }
.shop-cat small { font-size: 10.5px; opacity: 0.6; }
.shop-cat:hover { color: var(--text-main); background: rgba(255,255,255,0.06); }

.shop-cat.active {
  color: var(--theme);
  border-color: rgba(29,200,255,0.5);
  background: rgba(29,200,255,0.13);
}

.shop-cat.active svg { opacity: 1; }
.shop-cat:focus-visible { outline: 2px solid var(--theme); outline-offset: 2px; }

.shop-search { position: relative; flex: 1 1 200px; min-width: 170px; }

.shop-search svg {
  position: absolute;
  top: 50%;
  right: 13px;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: var(--text-dim);
  opacity: 0.65;
  pointer-events: none;
}

.shop-search input {
  width: 100%;
  padding: 11px 38px 11px 14px;
  border-radius: 11px;
  border: 1px solid rgba(255,255,255,0.1);
  background: var(--bg-deep);
  color: var(--text-main);
  font-family: var(--font-body);
  font-size: 13px;
}

.shop-search input::placeholder { color: var(--text-dim); opacity: 0.55; }
.shop-search input:focus {
  outline: none;
  border-color: rgba(29,200,255,0.5);
  box-shadow: 0 0 0 3px rgba(29,200,255,0.1);
}

/* --- One category --------------------------------------------------- */
.shop-cat-block { margin-top: 40px; }

.shop-cat-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
}

.shop-cat-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  border-radius: 12px;
  background: rgba(29,200,255,0.12);
  border: 1px solid rgba(29,200,255,0.28);
  color: var(--theme);
}

.shop-cat-mark svg { width: 19px; height: 19px; }
.shop-cat-title { margin: 0; font-size: 17px; font-weight: 800; color: var(--text-main); }

.shop-cat-note {
  font-size: 12.5px;
  color: var(--text-dim);
  padding-inline-start: 12px;
  border-inline-start: 1px solid rgba(255,255,255,0.12);
}

.shop-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
  gap: 16px;
}

.shop-empty {
  margin: 56px 0 0;
  text-align: center;
  font-size: 14px;
  color: var(--text-dim);
}

/* --- A product ------------------------------------------------------ */
.pcard {
  position: relative;
  display: flex;
  flex-direction: column;
  border-radius: 20px;
  background: var(--bg-panel);
  border: 1px solid rgba(255,255,255,0.075);
  overflow: hidden;
  transition: border-color 0.22s ease, transform 0.22s ease, box-shadow 0.22s ease;
}

.pcard:hover {
  transform: translateY(-3px);
  border-color: rgba(var(--c), 0.45);
  box-shadow: 0 26px 54px -30px rgba(var(--c), 0.75);
}

/* The plate the art sits on. The faint grid is the game's own texture
   grid, which is what stops it reading as a generic gradient banner. */
.pcard-plate {
  --p: var(--c);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 148px;
  overflow: hidden;
  background-color: #060a10;
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,0.03) 0 1px, transparent 1px 12px),
    repeating-linear-gradient(90deg, rgba(255,255,255,0.03) 0 1px, transparent 1px 12px),
    radial-gradient(ellipse 105% 82% at 50% 122%, rgba(var(--p), 0.72), rgba(var(--p), 0.12) 58%, transparent 74%),
    linear-gradient(168deg, rgba(var(--p), 0.34), transparent 64%);
  border-bottom: 1px solid rgba(var(--c), 0.3);
}

.pcard-art {
  display: block;
  width: 74px;
  color: rgb(var(--c));
  filter: drop-shadow(0 0 13px rgba(var(--c), 0.7)) drop-shadow(0 3px 5px rgba(0,0,0,0.5));
}

.pcard-art svg { display: block; width: 100%; height: auto; }

/* --- Pictures on the plate ---
   A product can carry several, stacked in the order they were added.
   contain/cover cover the plate; custom is placed by hand from the
   panel's x, y and scale. */
.pcard-layer,
.buy-layer,
.info-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
}

.pcard-layer.is-custom,
.buy-layer.is-custom,
.info-layer.is-custom {
  inset: auto;
  width: auto;
  transform: translate(-50%, -50%);
  object-fit: contain;
}

/* Inside the two dialogs the plate is square and small, so a picture
   placed for a wide card still has to sit inside it. */
.buy-plate,
.info-plate { overflow: hidden; }

.buy-art.has-images,
.info-art.has-images {
  width: 100%;
  height: 100%;
  filter: none;
}

/* Four specks of light around the art, from one element. */
.pcard-spark {
  position: absolute;
  top: 34px;
  left: 30%;
  width: 3px;
  height: 3px;
  border-radius: 1px;
  background: rgba(255,255,255,0.85);
  box-shadow:
    62px 16px 0 rgba(255,255,255,0.6),
    22px 72px 0 rgba(255,255,255,0.45),
    96px 58px 0 rgba(255,255,255,0.7),
    -8px 48px 0 rgba(255,255,255,0.4);
  pointer-events: none;
}

.pcard-badge {
  position: absolute;
  top: 12px;
  inset-inline-start: 12px;
  padding: 5px 11px;
  border-radius: 999px;
  background: rgba(5,8,12,0.72);
  border: 1px solid rgba(var(--c), 0.55);
  color: rgb(var(--c));
  font-size: 10.5px;
  font-weight: 800;
  backdrop-filter: blur(4px);
}

.pcard-body {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 16px 17px 12px;
  flex: 1 1 auto;
}

/* The game's own face, at the size a product name deserves. */
.pcard-name {
  font-family: var(--font-pixel);
  font-size: 21px;
  line-height: 1.25;
  color: rgb(var(--c));
  text-shadow: 0 0 22px rgba(var(--c), 0.45);
  unicode-bidi: isolate;
}

.pcard-tag { font-size: 12px; color: var(--text-dim); }

.pcard-foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin: 0 17px;
  padding: 13px 0;
  border-top: 1px solid rgba(255,255,255,0.07);
}

.pcard-price {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  color: var(--gold);
}

.pcard-price b { font-size: 19px; font-weight: 800; letter-spacing: -0.2px; }
.pcard-price small { font-size: 11px; font-weight: 700; opacity: 0.75; }

.pcard-meta {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-dim);
  padding: 3px 9px;
  border-radius: 7px;
  background: rgba(255,255,255,0.045);
}

.pcard-actions {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px;
  margin: 0 17px 17px;
}

.pcard-more,
.pcard-more,
.pcard-buy {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 12px 14px;
  border-radius: 12px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 800;
  cursor: pointer;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.14s cubic-bezier(.22,.61,.36,1),
              background-color 0.18s ease, color 0.18s ease,
              border-color 0.18s ease, box-shadow 0.22s ease;
}

.pcard-more > *,
.pcard-buy > * { position: relative; z-index: 1; }

.pcard-more svg,
.pcard-buy svg { width: 16px; height: 16px; flex-shrink: 0; }

.pcard-more {
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.035);
  color: var(--text-dim);
}

.pcard-more {
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.07), 0 3px 0 rgba(0,0,0,0.3);
}

.pcard-more:hover {
  transform: translateY(-2px);
  color: var(--text-main);
  background: rgba(255,255,255,0.08);
  border-color: rgba(255,255,255,0.22);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.1), 0 5px 0 rgba(0,0,0,0.3);
}

.pcard-more:active {
  transform: translateY(2px);
  box-shadow: inset 0 2px 5px rgba(0,0,0,0.35), 0 1px 0 rgba(0,0,0,0.3);
}

.pcard-more:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--bg-panel), 0 0 0 4px rgba(255,255,255,0.45);
}

/* خرید is the card's real action, so it is the solid one — built the
   same way as .btn but tinted with the product's own accent, which is
   why the colours are rgba(var(--c)) rather than fixed. جزئیات stays
   quiet beside it; two buttons of equal weight ask the buyer to choose
   between them instead of pointing at one. */
.pcard-buy {
  border: 1px solid rgba(255,255,255,0.26);
  color: #05080c;
  background: linear-gradient(180deg,
    color-mix(in srgb, rgb(var(--c)) 76%, #fff) 0%,
    rgb(var(--c)) 48%,
    color-mix(in srgb, rgb(var(--c)) 74%, #000) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.5),
    0 3px 0 color-mix(in srgb, rgb(var(--c)) 45%, #000),
    0 10px 22px -10px rgba(var(--c), 0.75);
}

.pcard-buy::after,
.pcard-more::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 34%, rgba(255,255,255,0.26) 47%, transparent 62%);
  transform: translateX(-130%);
  transition: transform 0.6s cubic-bezier(.22,.61,.36,1);
}

.pcard-more::after {
  background: linear-gradient(100deg, transparent 34%, rgba(255,255,255,0.1) 47%, transparent 62%);
}

.pcard-buy:hover::after,
.pcard-more:hover::after { transform: translateX(130%); }

.pcard-buy:hover {
  transform: translateY(-2px);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.6),
    0 5px 0 color-mix(in srgb, rgb(var(--c)) 45%, #000),
    0 18px 32px -12px rgba(var(--c), 0.95);
}

.pcard-buy:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 2px 5px rgba(0,0,0,0.3),
    0 1px 0 color-mix(in srgb, rgb(var(--c)) 45%, #000);
}

.pcard-buy:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--bg-panel), 0 0 0 4px rgb(var(--c));
}

/* The dialogs scroll inside themselves, so their scrollbars are part of
   the card rather than the window. */
.info,
.buy-main,
.buy-side {
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--c), 0.45) transparent;
}

.info::-webkit-scrollbar,
.buy-main::-webkit-scrollbar,
.buy-side::-webkit-scrollbar { width: 6px; }

.info::-webkit-scrollbar-thumb,
.buy-main::-webkit-scrollbar-thumb,
.buy-side::-webkit-scrollbar-thumb {
  border-radius: 3px;
  background: rgba(var(--c), 0.45);
}

/* =========================================================
   Details — what the card left out
   ========================================================= */
.info-overlay { padding: 28px 16px; }

.info {
  --c: 29,200,255;
  position: relative;
  width: min(520px, 100%);
  max-height: calc(100vh - 56px);
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 26px;
  /* The card scrolls, not the page behind it. */
  overflow-y: auto;
  overscroll-behavior: contain;
  border-radius: 24px;
  background: var(--bg-panel);
  border: 1px solid rgba(255,255,255,0.1);
  box-shadow: 0 50px 110px -40px rgba(0,0,0,0.95);
  opacity: 0;
  transform: translateY(14px) scale(0.985);
  transition: opacity 0.22s ease, transform 0.22s ease;
}

.modal-overlay.open .info { opacity: 1; transform: none; }

.info-close {
  top: 16px;
  inset-inline-end: 16px;
  z-index: 3;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.1);
}

.info-head { display: flex; align-items: center; gap: 16px; padding-inline-end: 40px; }

.info-plate {
  --p: var(--c);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 96px;
  height: 96px;
  flex-shrink: 0;
  border-radius: 22px;
  background-color: #060a10;
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,0.03) 0 1px, transparent 1px 12px),
    repeating-linear-gradient(90deg, rgba(255,255,255,0.03) 0 1px, transparent 1px 12px),
    radial-gradient(ellipse 105% 82% at 50% 122%, rgba(var(--p), 0.72), rgba(var(--p), 0.12) 58%, transparent 74%),
    linear-gradient(168deg, rgba(var(--p), 0.34), transparent 64%);
  border: 1px solid rgba(var(--p), 0.3);
}

.info-spark {
  position: absolute;
  top: 18px;
  left: 20%;
  width: 3px;
  height: 3px;
  border-radius: 1px;
  background: rgba(255,255,255,0.8);
  box-shadow: 46px 10px 0 rgba(255,255,255,0.55), 14px 52px 0 rgba(255,255,255,0.4);
  pointer-events: none;
}

.info-art {
  display: block;
  width: 54px;
  color: rgb(var(--c));
  filter: drop-shadow(0 0 13px rgba(var(--c), 0.7));
}

.info-art svg { display: block; width: 100%; height: auto; }

.info-id { display: flex; flex-direction: column; gap: 7px; min-width: 0; }

.info-name {
  font-family: var(--font-pixel);
  font-size: 25px;
  line-height: 1.2;
  color: rgb(var(--c));
  text-shadow: 0 0 24px rgba(var(--c), 0.5);
  unicode-bidi: isolate;
}

.info-tag { font-size: 12.5px; color: var(--text-dim); }

.info-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }

.info-chip {
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.09);
  color: var(--text-dim);
  font-size: 10.5px;
  font-weight: 700;
}

.info-chip.is-badge {
  background: rgba(var(--c), 0.14);
  border-color: rgba(var(--c), 0.45);
  color: rgb(var(--c));
}

.info-block { display: flex; flex-direction: column; gap: 11px; }

.info-label {
  margin: 0;
  padding-top: 18px;
  border-top: 1px solid rgba(255,255,255,0.08);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-dim);
}

/* Perks, grouped by where they apply. A rank usually does one thing
   everywhere and something extra on a particular server, so the
   grouping is the information — an ungrouped list would claim the
   Lifesteal perks work on SpaceSMP too. */
.info-perks {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.info-perk-group {
  padding: 12px 14px 13px;
  border-radius: 13px;
  background: rgba(255,255,255,0.022);
  border: 1px solid rgba(255,255,255,0.06);
}

/* The everywhere group leads, and is tinted to say so. */
.info-perk-group.is-global {
  background: linear-gradient(140deg, rgba(var(--c),0.09), rgba(255,255,255,0.015));
  border-color: rgba(var(--c),0.22);
}

.info-perk-where {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 10px;
  font-size: 12px;
  font-weight: 800;
  color: var(--text-dim);
}

.info-perk-group.is-global .info-perk-where { color: rgb(var(--c)); }

.info-perk-where svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  opacity: 0.9;
}

/* A server name is Latin in a right-to-left row — isolate keeps it from
   being reordered against the icon beside it. */
.info-perk-where span { unicode-bidi: isolate; }

.info-perk-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 9px;
  font-size: 13px;
  line-height: 1.65;
  color: rgba(238,246,251,0.86);
}

.info-perk-list li { position: relative; padding-inline-start: 24px; }

/* A tick, drawn from two physical borders: the logical ones would flip
   to the other corner in RTL and come out as a chevron. */
.info-perk-list li::before {
  content: '';
  position: absolute;
  inset-inline-start: 2px;
  top: 6px;
  width: 10px;
  height: 5px;
  border-left: 2px solid rgb(var(--c));
  border-bottom: 2px solid rgb(var(--c));
  transform: rotate(-45deg);
}

.info-perks-none {
  margin: 0;
  font-size: 13px;
  color: var(--text-dim);
}

.info-buy {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  width: 100%;
  padding: 15px 20px;
  border-radius: 14px;
  border: 0;
  background: linear-gradient(180deg,
    color-mix(in srgb, rgb(var(--c)) 76%, #fff) 0%,
    rgb(var(--c)) 48%,
    color-mix(in srgb, rgb(var(--c)) 74%, #000) 100%);
  color: #05080c;
  font-family: inherit;
  font-size: 14.5px;
  font-weight: 800;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.5),
    0 3px 0 color-mix(in srgb, rgb(var(--c)) 45%, #000),
    0 16px 34px -16px rgba(var(--c), 0.9);
  transition: transform 0.14s cubic-bezier(.22,.61,.36,1),
              filter 0.18s ease, box-shadow 0.22s ease;
}

.info-buy::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 34%, rgba(255,255,255,0.26) 47%, transparent 62%);
  transform: translateX(-130%);
  transition: transform 0.6s cubic-bezier(.22,.61,.36,1);
}

.info-buy:hover::after { transform: translateX(130%); }
.info-buy > * { position: relative; z-index: 1; }

.info-buy svg { width: 18px; height: 18px; position: relative; z-index: 1; }

.info-buy:hover {
  transform: translateY(-2px);
  filter: saturate(1.06);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.6),
    0 5px 0 color-mix(in srgb, rgb(var(--c)) 45%, #000),
    0 24px 44px -16px rgba(var(--c), 1);
}

.info-buy:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 2px 5px rgba(0,0,0,0.3),
    0 1px 0 color-mix(in srgb, rgb(var(--c)) 45%, #000);
}
.info-buy:focus-visible { outline: 2px solid rgb(var(--c)); outline-offset: 3px; }

/* =========================================================
   Buying — the dialog

   The product on one side and every choice on the other, with the total
   directly under the things that change it.
   ========================================================= */
.buy-overlay { padding: 28px 16px; }

.buy {
  --c: 29,200,255;
  position: relative;
  width: min(880px, 100%);
  max-height: calc(100vh - 56px);
  display: grid;
  grid-template-columns: 290px 1fr;
  border-radius: 24px;
  background: var(--bg-panel);
  border: 1px solid rgba(255,255,255,0.1);
  box-shadow: 0 50px 110px -40px rgba(0,0,0,0.95);
  overflow: hidden;
  opacity: 0;
  transform: translateY(14px) scale(0.985);
  transition: opacity 0.22s ease, transform 0.22s ease;
}

.modal-overlay.open .buy { opacity: 1; transform: none; }

.buy-close {
  top: 14px;
  inset-inline-end: 14px;
  z-index: 3;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.1);
}

/* The product, restated — you are about to pay for it, so it is on
   screen the whole time rather than a title you scrolled past. */
.buy-side {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 30px 22px;
  text-align: center;
  background:
    repeating-linear-gradient(0deg, rgba(255,255,255,0.025) 0 1px, transparent 1px 12px),
    repeating-linear-gradient(90deg, rgba(255,255,255,0.025) 0 1px, transparent 1px 12px),
    radial-gradient(ellipse 100% 60% at 50% 0%, rgba(var(--c), 0.28), transparent 70%),
    linear-gradient(180deg, rgba(var(--c), 0.1), transparent 60%);
  border-inline-end: 1px solid rgba(255,255,255,0.07);
}

.buy-plate {
  --p: var(--c);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 108px;
  height: 108px;
  margin-bottom: 4px;
  border-radius: 24px;
  background: rgba(5,8,12,0.4);
  border: 1px solid rgba(var(--p), 0.28);
}

.buy-art {
  display: block;
  width: 62px;
  color: rgb(var(--c));
  filter: drop-shadow(0 0 14px rgba(var(--c), 0.7));
}

.buy-art svg { display: block; width: 100%; height: auto; }

.buy-name {
  font-family: var(--font-pixel);
  font-size: 23px;
  color: rgb(var(--c));
  text-shadow: 0 0 24px rgba(var(--c), 0.5);
  unicode-bidi: isolate;
}

.buy-tag { font-size: 12px; color: var(--text-dim); }

.buy-perks {
  list-style: none;
  margin: 12px 0 0;
  padding: 14px 0 0;
  width: 100%;
  border-top: 1px solid rgba(255,255,255,0.08);
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 11.5px;
  line-height: 1.6;
  color: rgba(238,246,251,0.74);
  text-align: start;
}

.buy-perks li { position: relative; padding-inline-start: 18px; }

.buy-perks li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  top: 5px;
  width: 8px;
  height: 4px;
  border-left: 2px solid rgb(var(--c));
  border-bottom: 2px solid rgb(var(--c));
  transform: rotate(-45deg);
}

.buy-main {
  padding: 26px 26px 24px;
  display: flex;
  flex-direction: column;
  gap: 20px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.buy-side { overflow-y: auto; overscroll-behavior: contain; }

.buy-block { display: flex; flex-direction: column; gap: 10px; }

.buy-label {
  margin: 0;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-dim);
}

/* --- For me / for someone else --- */
.shop-choice { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }

.shop-choice-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 10px;
  border-radius: 12px;
  background: rgba(255,255,255,0.035);
  border: 1px solid rgba(255,255,255,0.09);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
  transition: color 0.18s ease, border-color 0.18s ease, background-color 0.18s ease;
}

.shop-choice-btn svg { width: 16px; height: 16px; flex-shrink: 0; }
.shop-choice-btn:hover { color: var(--text-main); background: rgba(255,255,255,0.06); }

.shop-choice-btn.active {
  color: rgb(var(--c));
  border-color: rgba(var(--c), 0.5);
  background: rgba(var(--c), 0.13);
}

.shop-choice-btn:focus-visible { outline: 2px solid rgb(var(--c)); outline-offset: 2px; }

.shop-target {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 13px;
  border-radius: 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.08);
}

.shop-target-head {
  position: relative;
  width: 36px;
  height: 36px;
  flex-shrink: 0;
  border-radius: 10px;
  overflow: hidden;
  background: rgba(255,255,255,0.05);
  box-shadow: 0 0 0 1px rgba(var(--c), 0.35);
}

.shop-target-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.shop-target-label { font-size: 11px; color: var(--text-dim); }

.shop-target-name {
  font-size: 14.5px;
  font-weight: 800;
  color: var(--text-main);
  unicode-bidi: isolate;
}

.shop-gift { display: flex; flex-direction: column; gap: 10px; }

/* --- Duration tiers --- */
.shop-tiers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(94px, 1fr));
  gap: 8px;
}

.shop-tier {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 13px 8px 11px;
  border-radius: 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.09);
  color: var(--text-dim);
  font-family: inherit;
  cursor: pointer;
  transition: color 0.18s ease, border-color 0.18s ease, background-color 0.18s ease;
}

.shop-tier-label { font-size: 12.5px; font-weight: 800; }
.shop-tier-price { font-size: 12px; font-weight: 700; color: var(--gold); opacity: 0.9; }

.shop-tier-off {
  position: absolute;
  top: -7px;
  inset-inline-end: 8px;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--online);
  color: #05080c;
  font-size: 9.5px;
  font-weight: 800;
  white-space: nowrap;
}

.shop-tier:hover { color: var(--text-main); background: rgba(255,255,255,0.06); }

.shop-tier.active {
  color: rgb(var(--c));
  border-color: rgba(var(--c), 0.55);
  background: rgba(var(--c), 0.13);
}

.shop-tier.active .shop-tier-price { opacity: 1; }
.shop-tier:focus-visible { outline: 2px solid rgb(var(--c)); outline-offset: 2px; }

/* --- Quantity --- */
.shop-qty {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 11px;
  border-radius: 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.09);
}

.shop-qty-btn {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: 10px;
  border: 1px solid rgba(var(--c), 0.35);
  background: rgba(var(--c), 0.1);
  color: rgb(var(--c));
  font-family: inherit;
  font-size: 18px;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
}

.shop-qty-btn:disabled { opacity: 0.32; cursor: not-allowed; }
.shop-qty-btn:focus-visible { outline: 2px solid rgb(var(--c)); outline-offset: 2px; }

.shop-qty-value {
  min-width: 52px;
  text-align: center;
  font-size: 17px;
  font-weight: 800;
  color: var(--text-main);
  font-variant-numeric: tabular-nums;
}

.shop-qty-max { margin-inline-start: auto; font-size: 11px; color: var(--text-dim); }

/* --- Discount code ---
   Most people don't have one, so the field is a door rather than a box:
   an offer, then the box, then the code that worked. Only ever one of
   the three on screen. */
.buy-code-block { gap: 0; }

.buy-code-toggle {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px dashed rgba(255,255,255,0.16);
  background: rgba(255,255,255,0.022);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
  transition: color 0.18s ease, border-color 0.18s ease, background-color 0.18s ease;
}

.buy-code-toggle svg { width: 17px; height: 17px; flex-shrink: 0; }
.buy-code-chevron { margin-inline-start: auto; width: 15px; height: 15px; opacity: 0.6; }

.buy-code-toggle:hover {
  color: rgb(var(--c));
  border-color: rgba(var(--c), 0.45);
  background: rgba(var(--c), 0.07);
}

.buy-code-toggle:focus-visible { outline: 2px solid rgb(var(--c)); outline-offset: 2px; }

.buy-code-card {
  padding: 13px;
  border-radius: 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(var(--c), 0.25);
}

/* The code that worked, and what it saved. */
.buy-code-applied {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 13px;
  border-radius: 12px;
  background: rgba(62,224,127,0.09);
  border: 1px solid rgba(62,224,127,0.32);
}

.buy-code-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border-radius: 9px;
  background: rgba(62,224,127,0.18);
  color: var(--online);
}

.buy-code-mark svg { width: 15px; height: 15px; }

.buy-code-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.buy-code-text b { font-size: 13px; font-weight: 800; color: #6fe6a2; unicode-bidi: isolate; }
.buy-code-text small { font-size: 11px; color: var(--text-dim); }

.buy-code-remove {
  margin-inline-start: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  padding: 0;
  border-radius: 9px;
  border: 1px solid rgba(255,255,255,0.12);
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
  transition: color 0.18s ease, border-color 0.18s ease, background-color 0.18s ease;
}

.buy-code-remove svg { width: 14px; height: 14px; }

.buy-code-remove:hover {
  color: #ff9c9c;
  border-color: rgba(255,143,143,0.4);
  background: rgba(255,143,143,0.1);
}

.shop-code { display: flex; gap: 8px; }

.shop-code input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 11px 14px;
  border-radius: 12px;
  border: 1px solid rgba(255,255,255,0.1);
  background: var(--bg-deep);
  color: var(--text-main);
  font-family: inherit;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.shop-code input::placeholder { text-transform: none; letter-spacing: 0; color: var(--text-dim); opacity: 0.55; }
.shop-code input:focus { outline: none; border-color: rgba(29,200,255,0.5); }

.shop-code button {
  flex-shrink: 0;
  padding: 0 18px;
  border-radius: 12px;
  border: 1px solid rgba(255,255,255,0.14);
  background: rgba(255,255,255,0.04);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}

.shop-code button:hover { color: var(--text-main); background: rgba(255,255,255,0.08); }
.shop-code button:disabled { opacity: 0.5; cursor: not-allowed; }

/* --- Total and pay --- */
.buy-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding-top: 16px;
  border-top: 1px solid rgba(255,255,255,0.08);
}

.buy-total-label { font-size: 12.5px; color: var(--text-dim); }

.buy-total-value {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  color: var(--gold);
}

.buy-total-value b { font-size: 25px; font-weight: 800; letter-spacing: -0.4px; }
.buy-total-value small { font-size: 12px; font-weight: 700; opacity: 0.75; }

.buy-total-was {
  font-size: 13px;
  color: var(--text-dim);
  text-decoration: line-through;
  opacity: 0.65;
}

.buy-pay {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  width: 100%;
  padding: 15px 20px;
  border-radius: 14px;
  border: 0;
  background: linear-gradient(180deg,
    color-mix(in srgb, rgb(var(--c)) 76%, #fff) 0%,
    rgb(var(--c)) 48%,
    color-mix(in srgb, rgb(var(--c)) 74%, #000) 100%);
  color: #05080c;
  font-family: inherit;
  font-size: 14.5px;
  font-weight: 800;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.5),
    0 3px 0 color-mix(in srgb, rgb(var(--c)) 45%, #000),
    0 16px 34px -16px rgba(var(--c), 0.9);
  transition: transform 0.14s cubic-bezier(.22,.61,.36,1),
              filter 0.18s ease, box-shadow 0.22s ease;
}

.buy-pay::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 34%, rgba(255,255,255,0.26) 47%, transparent 62%);
  transform: translateX(-130%);
  transition: transform 0.6s cubic-bezier(.22,.61,.36,1);
}

.buy-pay:hover::after { transform: translateX(130%); }
.buy-pay > * { position: relative; z-index: 1; }

.buy-pay svg { width: 18px; height: 18px; position: relative; z-index: 1; }

.buy-pay:hover {
  transform: translateY(-2px);
  filter: saturate(1.06);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.6),
    0 5px 0 color-mix(in srgb, rgb(var(--c)) 45%, #000),
    0 24px 44px -16px rgba(var(--c), 1);
}

.buy-pay:active {
  transform: translateY(2px);
  box-shadow:
    inset 0 2px 5px rgba(0,0,0,0.3),
    0 1px 0 color-mix(in srgb, rgb(var(--c)) 45%, #000);
}
.buy-pay:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
.buy-pay:focus-visible { outline: 2px solid rgb(var(--c)); outline-offset: 3px; }

.buy-note {
  margin: 0;
  padding: 11px 14px;
  border-radius: 12px;
  background: rgba(29,200,255,0.1);
  border: 1px solid rgba(29,200,255,0.3);
  color: var(--theme);
  font-size: 12.5px;
  line-height: 1.8;
}

.buy-note.error { background: rgba(255,110,110,0.1); border-color: rgba(255,110,110,0.32); color: #ff9c9c; }
.buy-note.done { background: rgba(62,224,127,0.1); border-color: rgba(62,224,127,0.32); color: #6fe6a2; }
.buy-note.pending { background: rgba(255,255,255,0.04); border-color: rgba(255,255,255,0.12); color: var(--text-dim); }

.buy-gateway { margin: 0; text-align: center; font-size: 11px; color: var(--text-dim); }
.buy-gateway strong { color: var(--text-main); }

/* --- Result page ---------------------------------------------------- */
.shop-result-inner { display: flex; justify-content: center; padding-top: 16px; }

.shop-result {
  --c: 29,200,255;
  width: 100%;
  max-width: 470px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 36px 30px 30px;
  text-align: center;
}

/* One mark, three colours — set by data-state on the card, so the
   markup doesn't have to know which outcome it is showing. */
.shop-result[data-state="ok"] { --c: 62,224,127; }
.shop-result[data-state="bad"] { --c: 255,110,110; }
.shop-result[data-state="wait"] { --c: 255,193,64; }

.shop-result-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 66px;
  height: 66px;
  border-radius: 20px;
  background: rgba(var(--c), 0.12);
  border: 1px solid rgba(var(--c), 0.4);
  color: rgb(var(--c));
}

.shop-result-mark svg { width: 30px; height: 30px; }
.shop-result-title { margin: 0; font-size: 20px; font-weight: 800; color: var(--text-main); }
.shop-result-text { margin: 0; font-size: 13.5px; line-height: 2; color: var(--text-dim); }

.shop-result-rows {
  width: 100%;
  margin: 4px 0 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
  border-radius: var(--radius-md);
  background: rgba(255,255,255,0.07);
  border: 1px solid rgba(255,255,255,0.07);
  overflow: hidden;
}

.shop-result-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 11px 14px;
  background: #0a0f16;
  font-size: 12.5px;
}

.shop-result-row dt { color: var(--text-dim); }
.shop-result-row dd { margin: 0; font-weight: 700; color: var(--text-main); unicode-bidi: isolate; }

.shop-result-actions { display: flex; gap: 10px; width: 100%; margin-top: 4px; }
.shop-result-actions .btn { flex: 1 1 0; justify-content: center; }

@media (max-width: 820px) {
  .buy { grid-template-columns: 1fr; }
  /* Stacked, the whole card is one scrolling column. */
  .buy { overflow-y: auto; overscroll-behavior: contain; }
  .buy-side, .buy-main { overflow: visible; }
  /* The art shrinks to a strip rather than eating the first screenful. */
  .buy-side {
    flex-direction: row;
    align-items: center;
    gap: 14px;
    padding: 18px;
    text-align: start;
    border-inline-end: 0;
    border-bottom: 1px solid rgba(255,255,255,0.07);
  }
  .buy-plate { width: 68px; height: 68px; margin: 0; border-radius: 18px; flex-shrink: 0; }
  .buy-art { width: 40px; }
  .buy-name { font-size: 19px; }
  .buy-perks { display: none; }
  .buy-main { padding: 20px 18px 18px; }
}

@media (max-width: 560px) {
  .shop { padding-top: 98px; }
  .shop-head { padding: 16px; }
  .shop-head-tools { width: 100%; }
  .shop-search { flex-basis: 100%; }
  .shop-grid { grid-template-columns: 1fr; }
  .shop-choice { grid-template-columns: 1fr; }
  .info { padding: 20px; }
  .info-head { flex-direction: column; align-items: flex-start; padding-inline-end: 44px; }
  .info-plate { width: 76px; height: 76px; }
  .shop-result-actions { flex-direction: column; }
}

/* =========================================================
   Admin panel — /admin and /admin/panel

   A control room, not a storefront. Denser than the rest of the site,
   flatter, and more information per screen. Colour is never decoration
   here: gold is money, green is done, amber is waiting, red is broken.
   If a thing isn't one of those, it's grey.
   ========================================================= */
.admin-body { background: #070b12; }

/* --- The gate ---
   Three fields on a dark plate. Nothing else on screen, because there is
   nothing else to do here. */
.admin-gate {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
}

.admin-gate-glow {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 720px;
  height: 480px;
  background: radial-gradient(ellipse at center, rgba(29,200,255,0.1), transparent 70%);
  pointer-events: none;
}

.admin-gate-card {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 400px;
  display: flex;
  flex-direction: column;
  gap: 15px;
  padding: 34px 30px 30px;
  border-radius: 22px;
  background: linear-gradient(160deg, rgba(255,255,255,0.05), rgba(255,255,255,0.012));
  border: 1px solid rgba(255,255,255,0.1);
  box-shadow: 0 40px 90px -40px rgba(0,0,0,0.95);
}

.admin-gate-logo { justify-content: center; font-size: 20px; }
.admin-gate-title { margin: 4px 0 0; text-align: center; font-size: 19px; font-weight: 800; color: var(--text-main); }
.admin-gate-sub { margin: -9px 0 4px; text-align: center; font-size: 12.5px; color: var(--text-dim); }

/* --- The shell --- */
.admin-shell { display: flex; min-height: 100vh; }

.admin-side {
  position: sticky;
  top: 0;
  align-self: flex-start;
  height: 100vh;
  width: 226px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 22px 12px 18px;
  background: linear-gradient(200deg, #0d1422, #080c14 55%);
  border-inline-start: 1px solid rgba(255,255,255,0.08);
}

.admin-side-logo { justify-content: flex-start; margin: 0 10px 20px; font-size: 17px; }

.admin-side-label {
  margin: 0 12px 8px;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--text-dim);
  opacity: 0.6;
}

.admin-nav { display: flex; flex-direction: column; gap: 3px; }

.admin-nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 11px 13px;
  border: 0;
  border-radius: 11px;
  background: transparent;
  color: var(--text-dim);
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 700;
  text-align: start;
  cursor: pointer;
  transition: color 0.15s ease, background-color 0.15s ease;
}

.admin-nav-item svg { width: 18px; height: 18px; flex-shrink: 0; color: rgb(var(--v)); opacity: 0.92; }
.admin-nav-item:hover { color: var(--text-main); background: rgba(255,255,255,0.05); }
.admin-nav-item:hover svg { opacity: 1; }

.admin-nav-item.active {
  color: rgb(var(--v));
  background: linear-gradient(90deg, rgba(var(--v), 0.18), rgba(var(--v), 0.06));
}

.admin-nav-item.active svg { opacity: 1; }

/* A bar on the reading edge, so which section you are in survives a
   glance at the icons alone. */
.admin-nav-item.active::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 22px;
  border-radius: 0 3px 3px 0;
  background: rgb(var(--v));
  box-shadow: 0 0 12px rgba(var(--v), 0.9);
}

.admin-logout { margin-top: auto; }
.admin-logout:hover { color: #ff8f8f; background: rgba(255,143,143,0.08); }

.admin-main {
  --v: 29,200,255;
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  padding: 24px 28px 64px;
}

/* A wash in the active section's colour, so switching views is felt as
   well as read. */
.admin-main::before {
  content: '';
  position: absolute;
  top: 0;
  inset-inline-end: 0;
  width: 70%;
  height: 340px;
  background: radial-gradient(ellipse 70% 100% at 80% 0%, rgba(var(--v), 0.12), transparent 70%);
  pointer-events: none;
  transition: background 0.35s ease;
}

.admin-view,
.admin-head { position: relative; z-index: 1; }

.admin-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 18px;
  margin-bottom: 20px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
}

.admin-head-title {
  margin: 0;
  font-size: 23px;
  font-weight: 800;
  color: var(--text-main);
  text-shadow: 0 0 34px rgba(var(--v), 0.55);
}

.admin-head-who {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 13px;
  border-radius: 999px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.09);
  font-size: 12.5px;
  color: var(--text-dim);
}

.admin-head-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--online);
  box-shadow: 0 0 9px var(--online-glow);
}

.admin-side-logo { position: relative; z-index: 1; }

.admin-view { display: none; flex-direction: column; gap: 16px; }
.admin-view.active { display: flex; }

/* --- Something needs a person --- */
.admin-alert {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 17px;
  border-radius: 14px;
  background: rgba(255,110,110,0.09);
  border: 1px solid rgba(255,110,110,0.32);
  color: #ffb4b4;
  font-size: 13px;
}

.admin-alert svg { width: 20px; height: 20px; flex-shrink: 0; }

.admin-alert button {
  margin-inline-start: auto;
  flex-shrink: 0;
  padding: 7px 14px;
  border-radius: 9px;
  border: 1px solid rgba(255,110,110,0.4);
  background: rgba(255,110,110,0.12);
  color: #ffb4b4;
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}

.admin-alert button:hover { background: rgba(255,110,110,0.2); }

/* --- Cards --- */
.admin-panel-card {
  padding: 18px;
  border-radius: 18px;
  background: linear-gradient(165deg, rgba(255,255,255,0.045), rgba(255,255,255,0.012));
  border: 1px solid rgba(255,255,255,0.085);
}

.admin-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}

.admin-card-title {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0;
  font-size: 14px;
  font-weight: 800;
  color: var(--text-main);
}

.admin-card-title svg { width: 17px; height: 17px; color: rgb(var(--v)); flex-shrink: 0; }
.admin-card-note { font-size: 11.5px; color: var(--text-dim); }

.admin-two { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }

/* --- The numbers ---
   Money is gold; everything countable is white. That one rule is what
   lets the row be read without labels. */
.admin-stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(178px, 1fr));
  gap: 12px;
}

.admin-stat {
  --t: 245,196,81;
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 16px;
  border-radius: 16px;
  background: linear-gradient(160deg, rgba(var(--t), 0.14), rgba(255,255,255,0.015) 62%);
  border: 1px solid rgba(var(--t), 0.28);
  overflow: hidden;
}

/* A hairline in the tile's own colour along the top, the same device the
   product cards use. */
.admin-stat::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, rgb(var(--t)), transparent);
}

.admin-stat-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border-radius: 13px;
  background: rgba(var(--t), 0.18);
  border: 1px solid rgba(var(--t), 0.3);
  color: rgb(var(--t));
}

.admin-stat-mark svg { width: 20px; height: 20px; }

.admin-stat-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.admin-stat-label { font-size: 11.5px; color: var(--text-dim); }

.admin-stat-value {
  font-size: 22px;
  font-weight: 800;
  line-height: 1.15;
  color: rgb(var(--t));
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.3px;
  text-shadow: 0 0 26px rgba(var(--t), 0.4);
}
.admin-stat-value small { margin-inline-start: 4px; font-size: 10.5px; font-weight: 700; opacity: 0.6; }
.admin-stat-sub { font-size: 11px; color: var(--text-dim); }

/* --- Takings, by day --- */
.admin-chart {
  position: relative;
  display: flex;
  align-items: flex-end;
  gap: 5px;
  height: 172px;
  padding-top: 8px;
  /* Four gridlines, so a bar's height is readable as a number rather
     than only as "taller than that one". */
  background-image: repeating-linear-gradient(
    to top, rgba(255,255,255,0.05) 0 1px, transparent 1px 25%);
  /* Days read left-to-right even on an RTL page; that's how a timeline
     is read everywhere. */
  direction: ltr;
}

.admin-bar {
  position: relative;
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  height: 100%;
}

.admin-bar-fill {
  width: 100%;
  max-width: 38px;
  border-radius: 5px 5px 2px 2px;
  background: linear-gradient(180deg, var(--gold), rgba(245,196,81,0.22));
  box-shadow: 0 0 18px -4px rgba(245,196,81,0.5);
  transition: filter 0.15s ease;
}

.admin-bar-fill.empty { background: rgba(255,255,255,0.14); border-radius: 2px; }
.admin-bar:hover .admin-bar-fill { filter: brightness(1.2); }
.admin-bar-day { font-size: 9.5px; color: var(--text-dim); white-space: nowrap; }

/* --- Tables --- */
.admin-table-wrap { overflow-x: auto; }

.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
}

.admin-table th {
  padding: 0 10px 11px;
  text-align: start;
  font-weight: 700;
  font-size: 11px;
  color: var(--text-dim);
  border-bottom: 1px solid rgba(255,255,255,0.09);
  white-space: nowrap;
}

.admin-table td {
  padding: 12px 10px;
  color: var(--text-main);
  border-bottom: 1px solid rgba(255,255,255,0.04);
  vertical-align: middle;
}

.admin-table tr:last-child td { border-bottom: 0; }
.admin-table tbody tr { transition: background-color 0.12s ease; }
.admin-table tbody tr:hover { background: rgba(var(--v), 0.055); }
.admin-table small { display: inline-block; color: var(--text-dim); font-size: 10.5px; }
.admin-table .money { color: var(--gold); font-weight: 700; font-variant-numeric: tabular-nums; }

.admin-empty { margin: 0; padding: 30px 10px; text-align: center; font-size: 13px; color: var(--text-dim); }

/* A product's own art, at table size. */
.admin-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: rgba(var(--c), 0.13);
  border: 1px solid rgba(var(--c), 0.25);
  color: rgb(var(--c));
}

.admin-icon svg { width: 20px; height: auto; }

.admin-code {
  display: inline-block;
  max-width: 340px;
  padding: 4px 8px;
  border-radius: 7px;
  background: rgba(255,255,255,0.05);
  font-family: 'Courier New', monospace;
  font-size: 11px;
  color: rgba(238,246,251,0.85);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
}

.admin-error-text { color: #ff9c9c; }

.admin-chip {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}

.admin-chip.green { background: rgba(62,224,127,0.13); color: #6fe6a2; }
.admin-chip.amber { background: rgba(255,193,64,0.13); color: #ffc98a; }
.admin-chip.red { background: rgba(255,110,110,0.13); color: #ff9c9c; }
.admin-chip.grey { background: rgba(255,255,255,0.06); color: var(--text-dim); }

/* --- Controls --- */
.admin-toolbar { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }

.admin-input {
  flex: 1 1 220px;
  min-width: 0;
  padding: 11px 14px;
  border-radius: 11px;
  border: 1px solid rgba(255,255,255,0.1);
  background: #04070b;
  color: var(--text-main);
  font-family: inherit;
  font-size: 13px;
}

.admin-input::placeholder { color: var(--text-dim); opacity: 0.55; }
.admin-input:focus { outline: none; border-color: rgba(var(--v), 0.55); box-shadow: 0 0 0 3px rgba(var(--v), 0.14); }
.admin-select { flex: 0 0 auto; min-width: 176px; }

/* ---- ادیتور پرک‌ها ----
   One card per "where": a server picker, the lines, and a way to drop
   the group. The global group is tinted so the everywhere-perks are
   findable at a glance in a product with five of these. */
.perked {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.perked-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.perked-none {
  margin: 0;
  padding: 18px 12px;
  text-align: center;
  font-size: 12.5px;
  color: var(--text-dim);
  border: 1px dashed rgba(255,255,255,0.1);
  border-radius: 12px;
}

.perked-group {
  padding: 11px 12px 12px;
  border-radius: 13px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.07);
}

.perked-group.is-global {
  background: linear-gradient(140deg, rgba(29,200,255,0.07), rgba(255,255,255,0.015));
  border-color: rgba(29,200,255,0.2);
}

.perked-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 9px;
}

.perked-server {
  flex: 1;
  min-width: 0;
}

.perked-count {
  flex-shrink: 0;
  padding: 4px 9px;
  border-radius: 8px;
  background: rgba(255,255,255,0.05);
  font-size: 11px;
  font-weight: 700;
  color: var(--text-dim);
  white-space: nowrap;
}

.perked-x {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 31px;
  height: 31px;
  padding: 0;
  border: 1px solid rgba(255,92,108,0.25);
  border-radius: 9px;
  background: rgba(255,92,108,0.09);
  color: #ff8d98;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.perked-x:hover {
  background: rgba(255,92,108,0.2);
  border-color: rgba(255,92,108,0.5);
  color: #fff;
}

.perked-x svg { width: 15px; height: 15px; }

.perked-lines {
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid rgba(255,255,255,0.09);
  background: rgba(0,0,0,0.28);
  font-family: var(--font-body);
  font-size: 12.5px;
  line-height: 1.9;
  color: var(--text-main);
  resize: vertical;
}

.perked-lines:focus {
  outline: none;
  border-color: rgba(29,200,255,0.45);
  box-shadow: 0 0 0 3px rgba(29,200,255,0.1);
}

.perked-add { align-self: flex-start; }


.admin-hint { font-size: 11.5px; color: var(--text-dim); }

.admin-add {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 17px;
  border-radius: 11px;
  border: 0;
  background: linear-gradient(135deg, rgb(var(--v)), rgba(var(--v), 0.68));
  color: #04070b;
  font-family: inherit;
  font-size: 13px;
  font-weight: 800;
  cursor: pointer;
  box-shadow: 0 12px 28px -12px rgba(var(--v), 0.95);
}

.admin-add svg { width: 15px; height: 15px; }
.admin-add:hover { filter: brightness(1.08); }

.admin-ghost {
  flex: 0 0 auto;
  padding: 11px 16px;
  border-radius: 11px;
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.03);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}

.admin-ghost:hover { color: var(--text-main); background: rgba(255,255,255,0.06); }

.admin-mini {
  padding: 6px 12px;
  margin-inline-end: 5px;
  border-radius: 8px;
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.04);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}

.admin-mini:hover { color: var(--text-main); background: rgba(255,255,255,0.08); }
.admin-mini.danger:hover { color: #ff8f8f; border-color: rgba(255,143,143,0.4); background: rgba(255,143,143,0.09); }

/* --- Online / backups / maintenance --- */
.admin-nav-badge {
  margin-inline-start: auto;
  min-width: 22px;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(62,224,127,0.16);
  color: #6fe6a2;
  font-size: 11px;
  font-weight: 800;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.admin-nav-badge.warn { background: rgba(255,128,82,0.18); color: #ffa27d; letter-spacing: 0.5px; }

.admin-online-user { display: inline-flex; align-items: center; gap: 9px; }

.admin-online-user img {
  width: 26px;
  height: 26px;
  border-radius: 6px;
  image-rendering: pixelated;
  background: rgba(255,255,255,0.05);
}

.admin-live-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-inline-end: 6px;
  border-radius: 50%;
  background: #3ee07f;
  box-shadow: 0 0 8px #3ee07f;
}

.admin-live-dot.idle { background: #ffc140; box-shadow: 0 0 8px #ffc140; }

a.admin-ghost { display: inline-flex; align-items: center; text-decoration: none; }

.admin-maint-text { margin: 0 0 16px; font-size: 13px; line-height: 2; color: var(--text-dim); }
.admin-maint-message { width: 100%; resize: vertical; min-height: 78px; line-height: 1.9; }
.admin-maint-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.admin-maint-since { margin: 12px 0 0; font-size: 12px; color: var(--text-dim); }

.admin-maint.on {
  border-color: rgba(255,128,82,0.45);
  box-shadow: 0 0 0 1px rgba(255,128,82,0.15), 0 20px 50px -30px rgba(255,128,82,0.8);
}

.admin-add.stop { background: linear-gradient(135deg, #3ee07f, rgba(62,224,127,0.7)); box-shadow: 0 12px 28px -12px rgba(62,224,127,0.95); }

/* --- The editor dialog --- */
.admin-modal-overlay { align-items: flex-start; overflow-y: auto; padding: 40px 20px; }

.admin-modal {
  max-width: 640px;
  text-align: start;
  display: flex;
  flex-direction: column;
  gap: 18px;
  background: var(--bg-panel);
  border-radius: 22px;
}

.admin-modal-title {
  margin: 0;
  padding-bottom: 16px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
  font-size: 17px;
  font-weight: 800;
  color: var(--text-main);
}

.admin-form { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

.admin-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.admin-field.wide { grid-column: 1 / -1; }
.admin-field > span { font-size: 12.5px; font-weight: 700; color: var(--text-dim); }
.admin-field small { font-size: 11px; color: var(--text-dim); opacity: 0.75; line-height: 1.75; }

.admin-field input,
.admin-field select,
.admin-field textarea {
  width: 100%;
  padding: 11px 13px;
  border-radius: 11px;
  border: 1px solid rgba(255,255,255,0.1);
  background: #04070b;
  color: var(--text-main);
  font-family: inherit;
  font-size: 13px;
  resize: vertical;
}

.admin-field textarea { font-family: 'Courier New', monospace; font-size: 12px; line-height: 1.85; }
.admin-field input:focus,
.admin-field select:focus,
.admin-field textarea:focus {
  outline: none;
  border-color: rgba(29,200,255,0.5);
  box-shadow: 0 0 0 3px rgba(29,200,255,0.1);
}

.admin-field input[readonly] { opacity: 0.55; cursor: not-allowed; }

.admin-modal-note { width: 100%; margin: 0; }
.admin-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding-top: 16px;
  border-top: 1px solid rgba(255,255,255,0.08);
}

/* --- Toast --- */
.admin-toast {
  position: fixed;
  bottom: 24px;
  inset-inline-start: 24px;
  z-index: 200;
  padding: 13px 18px;
  border-radius: 13px;
  background: #0f1826;
  border: 1px solid rgba(255,255,255,0.12);
  color: var(--text-main);
  font-size: 13px;
  box-shadow: 0 20px 44px -20px rgba(0,0,0,0.95);
}

.admin-toast.ok { border-color: rgba(62,224,127,0.4); color: #6fe6a2; }
.admin-toast.error { border-color: rgba(255,110,110,0.4); color: #ff9c9c; }

@media (max-width: 900px) {
  .admin-two { grid-template-columns: 1fr; }
  .admin-side { width: 62px; padding: 18px 8px; }
  .admin-side-logo,
  .admin-side-label,
  .admin-nav-item span { display: none; }
  .admin-nav-item { justify-content: center; padding: 12px 0; }
  .admin-main { padding: 20px 16px 50px; }
  .admin-form { grid-template-columns: 1fr; }
}

/* =========================================================
   Admin — the picture editor

   Six numbers decide how a picture sits on a card, and none of them mean
   anything written down. So the preview is the control: it is the same
   plate the shop draws, at the same proportions, updating as the sliders
   move.
   ========================================================= */
.imged { display: flex; flex-direction: column; gap: 12px; }

.imged-plate {
  --p: 29,200,255;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 148px;
  border-radius: 14px;
  overflow: hidden;
  background-color: #060a10;
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,0.03) 0 1px, transparent 1px 12px),
    repeating-linear-gradient(90deg, rgba(255,255,255,0.03) 0 1px, transparent 1px 12px),
    radial-gradient(ellipse 105% 82% at 50% 122%, rgba(var(--p), 0.72), rgba(var(--p), 0.12) 58%, transparent 74%),
    linear-gradient(168deg, rgba(var(--p), 0.34), transparent 64%);
  border: 1px solid rgba(var(--p), 0.3);
}

.imged-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

.imged-layer.is-custom {
  inset: auto;
  width: auto;
  transform: translate(-50%, -50%);
  object-fit: contain;
}

.imged-none { font-size: 12px; color: var(--text-dim); }

.imged-list { display: flex; flex-direction: column; gap: 10px; }

.imged-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 11px;
  border-radius: 13px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.08);
}

.imged-thumb {
  width: 54px;
  height: 54px;
  flex-shrink: 0;
  border-radius: 10px;
  object-fit: cover;
  background: #04070b;
  border: 1px solid rgba(255,255,255,0.1);
}

.imged-controls { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.imged-fit { width: 100%; }

.imged-slider {
  display: grid;
  grid-template-columns: 52px 1fr 44px;
  align-items: center;
  gap: 9px;
  font-size: 11.5px;
  color: var(--text-dim);
}

.imged-slider b {
  font-weight: 700;
  color: var(--text-main);
  font-variant-numeric: tabular-nums;
  text-align: end;
}

.imged-slider input[type="range"] {
  width: 100%;
  height: 4px;
  padding: 0;
  border: 0;
  border-radius: 2px;
  background: rgba(255,255,255,0.14);
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
}

.imged-slider input[type="range"]::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 0;
  background: rgb(var(--v, 29,200,255));
  cursor: pointer;
}

.imged-slider input[type="range"]::-moz-range-thumb {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 0;
  background: rgb(var(--v, 29,200,255));
  cursor: pointer;
}

.imged-order { display: flex; flex-direction: column; gap: 5px; flex-shrink: 0; }
.imged-order .admin-mini { margin: 0; padding: 5px 9px; }
.imged-order .admin-mini:disabled { opacity: 0.3; cursor: not-allowed; }

.imged-actions { display: flex; gap: 8px; }

/* Everything uploaded before, so one render can go on several products. */
.imged-library {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  gap: 7px;
  max-height: 190px;
  overflow-y: auto;
  padding: 9px;
  border-radius: 13px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.08);
}

.imged-library button {
  padding: 0;
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 9px;
  background: #04070b;
  cursor: pointer;
  overflow: hidden;
  aspect-ratio: 1;
}

.imged-library button:hover { border-color: rgba(var(--v, 29,200,255), 0.6); }
.imged-library img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* A product's own art in the products table, picture or icon. */
.admin-icon img { width: 100%; height: 100%; object-fit: cover; border-radius: 9px; }

/* =========================================================
   Roles

   A role is a name and a colour, and the colour does the work: the same
   hue marks the badge by a player's name, the shield in their rail, and
   the row in the panel. A Helper's green and an Administrator's red are
   never mistaken for one another at a glance.
   ========================================================= */
.role-badge {
  --c: 29,200,255;
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  background: rgba(var(--c), 0.14);
  border: 1px solid rgba(var(--c), 0.42);
  color: rgb(var(--c));
  font-size: 10.5px;
  font-weight: 800;
  white-space: nowrap;
  unicode-bidi: isolate;
}

.dash-identity-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* --- The way in, for someone who has one ---
   It sits with the rail's other controls but is plainly not one of them:
   a filled tile in the role's colour with a glow under it, so it reads
   as a door rather than another icon. */
.sidebar-admin {
  --c: 29,200,255;
  position: relative;
  margin-top: auto;
  margin-bottom: 8px;
  color: rgb(var(--c));
  background: linear-gradient(150deg, rgba(var(--c), 0.22), rgba(var(--c), 0.07));
  box-shadow: inset 0 0 0 1px rgba(var(--c), 0.4);
}

/* .sidebar-logout already claims margin-top: auto in the rail; once the
   shield is there it takes that job instead. */
.sidebar-admin:not([hidden]) ~ .sidebar-logout { margin-top: 0; }

.sidebar-admin-glow {
  position: absolute;
  inset: -6px;
  border-radius: 20px;
  background: radial-gradient(circle at 50% 50%, rgba(var(--c), 0.35), transparent 70%);
  opacity: 0.55;
  pointer-events: none;
  transition: opacity 0.25s ease;
}

.sidebar-admin:hover {
  color: #05080c;
  background: linear-gradient(150deg, rgb(var(--c)), rgba(var(--c), 0.75));
  box-shadow: inset 0 0 0 1px rgba(var(--c), 0.6), 0 10px 26px -10px rgba(var(--c), 0.95);
}

.sidebar-admin:hover .sidebar-admin-glow { opacity: 1; }
.sidebar-admin:focus-visible { outline: 2px solid rgb(var(--c)); outline-offset: 3px; }
.sidebar-admin .sidebar-icon { position: relative; z-index: 1; }

/* --- Permission checkboxes, in the role editor ---
   Twenty-five in one run is a wall, so they come in the groups they
   belong to, each with a toggle for the whole section — which is how
   these actually get set: by section, then trimmed. */
.perm-groups { display: flex; flex-direction: column; gap: 14px; }

.perm-group-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 7px;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
  font-size: 11.5px;
  font-weight: 700;
  color: var(--text-dim);
}

.perm-all {
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.14);
  background: transparent;
  color: var(--text-dim);
  font-family: inherit;
  font-size: 10.5px;
  font-weight: 700;
  cursor: pointer;
}

.perm-all:hover {
  color: rgb(var(--v, 29,200,255));
  border-color: rgba(var(--v, 29,200,255), 0.5);
  background: rgba(var(--v, 29,200,255), 0.1);
}

.perm-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
  gap: 7px;
}

.perm {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 11px 13px;
  border-radius: 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.08);
  font-size: 12.5px;
  color: var(--text-dim);
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease, background-color 0.15s ease;
}

.perm:hover { color: var(--text-main); background: rgba(255,255,255,0.055); }

.perm input { position: absolute; opacity: 0; pointer-events: none; }

.perm-box {
  position: relative;
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  border-radius: 5px;
  border: 1px solid rgba(255,255,255,0.22);
  background: rgba(0,0,0,0.3);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.perm input:checked + .perm-box {
  background: rgb(var(--v, 29,200,255));
  border-color: rgb(var(--v, 29,200,255));
}

.perm input:checked + .perm-box::after {
  content: '';
  position: absolute;
  left: 5px;
  top: 2px;
  width: 5px;
  height: 9px;
  border-right: 2px solid #04070b;
  border-bottom: 2px solid #04070b;
  transform: rotate(45deg);
}

.perm input:checked ~ span { color: var(--text-main); font-weight: 700; }
.perm input:focus-visible + .perm-box { outline: 2px solid rgb(var(--v, 29,200,255)); outline-offset: 2px; }
.perm.is-locked { opacity: 0.45; cursor: not-allowed; }


@media (prefers-reduced-motion: reduce) {
  .copy-btn::after { display: none; }
  .copy-btn:hover,
  .modal-info-item:hover { transform: none; }
}
