/* =========================================================
   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-rgb: 29, 200, 255;
  --theme-dim: #1497c2;
  --theme-glow: rgba(var(--theme-rgb), 0.45);
  --bg-deep: #05080c;
  --bg-deep-rgb: 5, 8, 12;
  --bg-panel: #0b1119;
  --bg-panel-2: #0f1826;
  --border-soft: rgba(var(--theme-rgb), 0.18);
  --online: #3ee07f;
  --online-rgb: 62, 224, 127;
  --online-glow: rgba(var(--online-rgb), 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(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),0.22), rgba(var(--theme-rgb),0.05));
  border: 1px solid rgba(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),0.65);
  background: linear-gradient(180deg, rgba(var(--theme-rgb),0.32), rgba(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),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: var(--bg-deep);
  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(var(--bg-deep-rgb),0.92) 0%,
      rgba(var(--bg-deep-rgb),0.86) 38%,
      rgba(var(--bg-deep-rgb),0.55) 66%,
      rgba(var(--bg-deep-rgb),0.15) 88%,
      transparent 100%),
    linear-gradient(180deg,
      rgba(var(--bg-deep-rgb),0.6) 0%,
      rgba(var(--bg-deep-rgb),0.14) 22%,
      rgba(var(--bg-deep-rgb),0.18) 66%,
      rgba(var(--bg-deep-rgb),0.85) 93%,
      var(--bg-deep) 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(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),0.4);
  background: linear-gradient(180deg, rgba(var(--theme-rgb),0.24), rgba(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),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: var(--theme); --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(var(--theme-rgb),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(var(--theme-rgb),0.15) 25%, rgba(var(--theme-rgb),0.35) 50%, rgba(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),0.08), transparent 55%);
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
}

.mode-card:hover {
  transform: translateY(-6px);
  border-color: rgba(var(--theme-rgb),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(var(--theme-rgb), 0.12);
  border: 1px solid rgba(var(--theme-rgb), 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(var(--theme-rgb),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(var(--theme-rgb),0.4), transparent);
}

.footer-glow {
  position: absolute;
  top: -220px;
  left: 50%;
  transform: translateX(-50%);
  width: 900px;
  height: 380px;
  background: radial-gradient(ellipse, rgba(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),0.13);
  border-color: rgba(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),0.1);
  border: 1px solid rgba(var(--theme-rgb),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(var(--theme-rgb),0.05);
  border: 1px solid rgba(var(--theme-rgb),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(var(--theme-rgb),0.09), rgba(255,255,255,0.015)),
    rgba(0,0,0,0.25);
  border: 1px solid rgba(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),0.12);
  border: 1px solid rgba(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),0.04);
}

.auth-panel-icon {
  width: 52px;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 15px;
  background: rgba(var(--theme-rgb),0.12);
  border: 1px solid rgba(var(--theme-rgb),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(var(--theme-rgb),0.5);
  box-shadow: 0 0 0 3px rgba(var(--theme-rgb),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(var(--theme-rgb),0.35);
  background: rgba(var(--theme-rgb),0.04);
}

.verify-card[data-state="verified"] {
  border-color: rgba(var(--theme-rgb),0.5);
  background: rgba(var(--theme-rgb),0.08);
  box-shadow: 0 0 0 1px rgba(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--theme-rgb),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(var(--theme-rgb),0.2), rgba(var(--theme-rgb),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(var(--theme-rgb),0.5), 0 0 90px rgba(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),0.85), transparent);
  box-shadow: 0 0 16px rgba(var(--theme-rgb),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(var(--theme-rgb),0.08);
  border: 1px solid rgba(var(--theme-rgb),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(var(--theme-rgb),0.12);
  box-shadow: inset 0 0 0 1px rgba(var(--theme-rgb),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;
  /* Top, not centred: the profile card heads every view, and a view that
     grows (settings opening a row) shouldn't drag it down the screen. */
  align-items: flex-start;
  padding: 52px 30px 90px;
  overflow: hidden;
}

.dash-glow {
  position: absolute;
  top: -200px;
  left: 50%;
  transform: translateX(-50%);
  width: 1000px;
  height: 480px;
  background: radial-gradient(ellipse, rgba(var(--theme-rgb),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(var(--theme-rgb),0.5);
  box-shadow: 0 0 0 3px rgba(var(--theme-rgb),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(var(--theme-rgb),0.1);
  border: 1px solid rgba(var(--theme-rgb),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(var(--theme-rgb),0.14);
  border-color: rgba(var(--theme-rgb),0.5);
  color: var(--theme);
}

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

.link-step.done .link-step-num {
  background: rgba(var(--online-rgb),0.14);
  border-color: rgba(var(--online-rgb),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(var(--theme-rgb),0.07);
  border: 1px solid rgba(var(--theme-rgb),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(var(--theme-rgb),0.1);
  border: 1px solid rgba(var(--theme-rgb),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(var(--theme-rgb),0.18); border-color: rgba(var(--theme-rgb),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(var(--theme-rgb),0.1);
  border: 1px solid rgba(var(--theme-rgb),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(var(--theme-rgb),0.07);
  box-shadow: 0 0 0 3px rgba(var(--theme-rgb),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(var(--theme-rgb),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(var(--theme-rgb),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);
}

/* --- Settings -------------------------------------------------------
   Who the account is, then one row per thing that can change.

   The header is the one bold thing: the player's own head over the
   server's own art, their name in the game's face. Everything under it
   is quiet. A row says where it stands and opens into its form only on
   تغییر, so there is never a wall of empty fields and only one primary
   button on screen. The three rows carry the panel's section colours —
   cyan for the account, violet for its password, green for the game. */
/* The profile card above both views — same pieces as settings used to
   carry inside its own card. */
.dash-profile { width: 100%; max-width: 760px; margin: 0 auto; }
.dash-profile .dash-unlink { align-self: flex-end; margin-bottom: 4px; }

.dash-settings {
  width: 100%;
  max-width: 760px;
  /* Clear of the profile card above it. */
  margin: 28px auto 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

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

.set-card {
  border-radius: 22px;
  background: var(--bg-panel);
  border: 1px solid rgba(255,255,255,0.07);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.04),
    0 2px 0 rgba(0,0,0,0.3),
    0 26px 50px -34px rgba(0,0,0,0.95);
  overflow: hidden;
}

/* --- Profile --- */
.set-banner {
  position: relative;
  height: 128px;
  overflow: hidden;
  background: #0a1520;
}

.set-banner img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 40%;
  opacity: 0.6;
}

/* Fades the art into the card, so the name below reads on solid ground. */
.set-banner::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(11,17,25,0.05) 0%, rgba(11,17,25,0.55) 62%, var(--bg-panel) 100%);
}

.set-profile-body {
  position: relative;
  display: flex;
  align-items: flex-end;
  gap: 16px;
  margin-top: -46px;
  padding: 0 24px 22px;
}

.set-avatar {
  position: relative;
  width: 88px;
  height: 88px;
  flex-shrink: 0;
  border-radius: 20px;
  overflow: hidden;
  background: #0d141d;
  /* The card's own colour as a ring, cutting the head out of the art. */
  border: 4px solid var(--bg-panel);
  box-shadow: 0 12px 24px -12px rgba(0,0,0,0.9);
}

.set-who { display: flex; flex-direction: column; gap: 9px; min-width: 0; padding-bottom: 3px; }
.set-name-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  /* Prefix then name, the way they read in chat — left to right, but kept
     against the head on the right. */
  direction: ltr;
  justify-content: flex-end;
  gap: 10px;
}
.set-name-line .rank-prefix { font-size: 22px; }
.set-name-line > :empty { display: none; }

.set-name {
  font-family: var(--font-pixel);
  font-size: 24px;
  line-height: 1.15;
  color: #fff;
  text-shadow: 2px 2px 0 rgba(0,0,0,0.55);
  unicode-bidi: isolate;
  overflow-wrap: anywhere;
}

.set-meta { display: flex; flex-wrap: wrap; gap: 8px; }

.set-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: 999px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.07);
  font-size: 12px;
  font-weight: 700;
  color: var(--text-dim);
}
.set-meta-item svg { width: 15px; height: 15px; flex-shrink: 0; }

.set-meta-item.is-online {
  color: #6fe6a2;
  background: rgba(var(--online-rgb), 0.08);
  border-color: rgba(var(--online-rgb), 0.28);
}
.set-online-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--online);
  box-shadow: 0 0 0 3px rgba(var(--online-rgb), 0.2);
}
.set-meta-item bdi { color: var(--text-main); }
#setMc svg { color: var(--online); }
#setMc.is-off svg { color: var(--text-dim); }

/* --- Rows --- */
.set-row {
  --t: 29,200,255;
  border-top: 1px solid rgba(255,255,255,0.06);
  transition: background-color 0.25s ease;
}
.set-card > .set-row:first-child { border-top: 0; }

.set-row.is-open { background: linear-gradient(180deg, rgba(var(--t), 0.05), transparent 75%); }

.set-row-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  padding: 18px 24px;
}

.set-row-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: rgba(var(--t), 0.11);
  color: rgb(var(--t));
  box-shadow: inset 0 0 0 1px rgba(var(--t), 0.22);
}
.set-row-icon svg { width: 20px; height: 20px; }

.set-row-text { min-width: 0; }

.set-row-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 3px;
  font-size: 14.5px;
  font-weight: 800;
  color: var(--text-main);
}

.set-row-value { margin: 0; font-size: 13px; color: var(--text-dim); overflow-wrap: anywhere; }
.set-row-value bdi { color: var(--text-main); font-weight: 700; }
.set-dots { letter-spacing: 2px; }

.set-toggle {
  height: 36px;
  padding: 0 16px;
  border-radius: 10px;
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.04);
  color: var(--text-main);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.set-toggle:hover { background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.2); }
.set-toggle:focus-visible { outline: 2px solid var(--theme); outline-offset: 2px; }
.set-row.is-open .set-toggle { background: transparent; color: var(--text-dim); }

/* The row's own colour, for the one toggle that leads somewhere else. */
.set-toggle-link {
  color: rgb(var(--t));
  border-color: rgba(var(--t), 0.35);
  background: rgba(var(--t), 0.08);
}
.set-toggle-link:hover { background: rgba(var(--t), 0.15); border-color: rgba(var(--t), 0.5); }

/* "Saved" beside the title, for a few seconds after a row closes. */
.set-flash {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px 2px 8px;
  border-radius: 999px;
  background: rgba(var(--online-rgb), 0.12);
  color: #6fe6a2;
  font-size: 11px;
  font-weight: 800;
  opacity: 0;
  transform: translateY(2px);
  transition: opacity 0.25s ease, transform 0.25s ease;
  pointer-events: none;
}
.set-flash:empty { display: none; }
.set-flash.show { opacity: 1; transform: none; }
.set-flash::before {
  content: '';
  width: 10px;
  height: 10px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.2 6.3 4.9 9 9.8 3.4' fill='none' stroke='%236fe6a2' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* --- A row's form ---
   Opens by growing a grid track from 0fr to 1fr, which animates to the
   content's real height with no measuring. */
.set-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.28s cubic-bezier(.22,.61,.36,1);
}
.set-row.is-open .set-panel { grid-template-rows: 1fr; }
.set-panel-inner { min-height: 0; overflow: hidden; }

.set-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
  /* Lined up under the row's text, past its icon. */
  margin: 0 24px 22px;
  margin-inline-start: 78px;
  padding: 18px;
  border-radius: 14px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.06);
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.set-row.is-open .set-form { opacity: 1; transform: none; transition-delay: 0.06s; }

.set-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.set-field-newline { grid-column-start: 1; }

.set-field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.set-label { font-size: 12.5px; font-weight: 700; color: var(--text-dim); }
.set-hint { font-size: 11.5px; line-height: 1.7; color: var(--text-dim); opacity: 0.8; }

.set-input {
  position: relative;
  display: flex;
  align-items: center;
  height: 44px;
  border-radius: 11px;
  background: #070b11;
  border: 1px solid rgba(255,255,255,0.1);
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.35);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.set-input:hover { border-color: rgba(255,255,255,0.16); }
.set-input:focus-within {
  border-color: rgba(var(--theme-rgb), 0.65);
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.35), 0 0 0 3px rgba(var(--theme-rgb), 0.14);
}

.set-input input {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0 14px;
  border: 0;
  background: none;
  color: var(--text-main);
  font-family: inherit;
  font-size: 14.5px;
  outline: none;
}
.set-input input[type="password"] { letter-spacing: 2px; }
.set-input input:disabled { opacity: 0.5; }
/* Room for the eye, which sits at the end of the typed text. */
.set-input:has(.pw-reveal) input { padding-right: 44px; }

/* The rules a password has to meet, ticked off as it is typed. */
.set-reqs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.set-reqs li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  color: var(--text-dim);
  transition: color 0.15s ease;
}

.set-reqs li::before {
  content: '';
  box-sizing: border-box;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1.5px solid rgba(255,255,255,0.22);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.set-reqs li.ok { color: #6fe6a2; }
.set-reqs li.ok::before {
  border-color: transparent;
  background: var(--online) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.6 6.2 5 8.6 9.4 3.8' fill='none' stroke='%2304141c' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 10px no-repeat;
}

.set-actions { display: flex; align-items: center; justify-content: space-between; gap: 14px; }

.set-note { margin: 0; font-size: 12.5px; line-height: 1.8; color: var(--text-dim); }
.set-note.error { color: #ff9c9c; }
.set-note.done { color: #6fe6a2; }

/* The one primary button on screen: the brand's colour, compact, lit
   from above, no glow. Asleep it keeps the colour faintly, so it reads
   as "not yet" rather than "broken". */
.set-save {
  flex-shrink: 0;
  margin-inline-start: auto;
  height: 40px;
  padding: 0 20px;
  border: 0;
  border-radius: 11px;
  background: var(--theme);
  color: #04141c;
  font-family: inherit;
  font-size: 13px;
  font-weight: 800;
  cursor: pointer;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.4),
    inset 0 -2px 0 rgba(0,0,0,0.18),
    0 6px 12px -8px rgba(0,0,0,0.9);
  transition: filter 0.15s ease, transform 0.1s ease, background-color 0.15s ease, color 0.15s ease;
}
.set-save:hover { filter: brightness(1.08); }
.set-save:active { transform: translateY(1px); }
.set-save:focus-visible { outline: 2px solid var(--text-main); outline-offset: 2px; }
.set-save:disabled {
  background: rgba(var(--theme-rgb), 0.14);
  color: rgba(var(--theme-rgb), 0.55);
  box-shadow: none;
  cursor: not-allowed;
  filter: none;
  transform: none;
}

/* For the one action here that takes something away. */
.set-save-danger {
  background: rgba(255,110,110,0.14);
  color: #ffb4b4;
  box-shadow: inset 0 0 0 1px rgba(255,110,110,0.35);
}
.set-save-danger:hover { background: rgba(255,110,110,0.22); filter: none; }
.set-save-danger:disabled { background: rgba(255,255,255,0.04); color: rgba(238,246,251,0.3); }

/* --- Devices --- */
.device-list { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; list-style: none; }

.device {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 12px;
  background: #070b11;
  border: 1px solid rgba(255,255,255,0.07);
}
.device.is-current { border-color: rgba(var(--theme-rgb), 0.35); }

.device-icon {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 11px;
  background: rgba(255,255,255,0.05);
  color: var(--text-dim);
}
.device-icon svg { width: 20px; height: 20px; }
.device.is-current .device-icon { background: rgba(var(--theme-rgb), 0.12); color: var(--theme); }

.device-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.device-name { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 700; color: var(--text-main); }
.device-here {
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(var(--theme-rgb), 0.14);
  color: var(--theme);
  font-size: 10.5px;
  font-weight: 800;
}
.device-meta { font-size: 12px; color: var(--text-dim); overflow-wrap: anywhere; }

.device-remove {
  height: 32px;
  padding: 0 12px;
  border-radius: 9px;
  border: 1px solid rgba(255,110,110,0.35);
  background: rgba(255,110,110,0.06);
  color: #ff9c9c;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}
.device-remove:hover { background: rgba(255,110,110,0.14); }
.device-remove:disabled { opacity: 0.5; cursor: wait; }

/* The eye inside a password field. */
.pw-reveal {
  position: absolute;
  top: 50%;
  right: 8px;
  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; }

@media (prefers-reduced-motion: reduce) {
  .set-panel, .set-form, .set-flash, .set-row { transition: none; }
}

@media (max-width: 640px) {
  .dash-section { padding-top: 26px; }
  .set-title { font-size: 21px; }
  .set-banner { height: 96px; }
  /* Head, then name, then chips: side by side the text column ran taller
     than the head and climbed into the art. */
  .set-profile-body { flex-direction: column; align-items: flex-start; gap: 10px; margin-top: -36px; padding: 0 16px 18px; }
  .set-avatar { width: 72px; height: 72px; border-radius: 17px; border-width: 3px; }
  .set-name { font-size: 20px; }
  .set-row-head { gap: 12px; padding: 16px; }
  .set-row-icon { width: 36px; height: 36px; border-radius: 11px; }
  .set-toggle { padding: 0 12px; }
  /* A long label would squeeze the row's text into a column of single
     words; it drops under the text instead. */
  .set-toggle-link { grid-column: 2 / -1; justify-self: start; }
  .set-form { margin: 0 14px 16px; padding: 14px; }
  .set-fields { grid-template-columns: 1fr; }
  .set-actions { flex-direction: column-reverse; align-items: stretch; }
  .set-save { width: 100%; margin: 0; }
}

.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; }
}


@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(var(--bg-deep-rgb),0.7) 0%,
        rgba(var(--bg-deep-rgb),0.84) 34%,
        rgba(var(--bg-deep-rgb),0.88) 66%,
        var(--bg-deep) 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-rgb: 245, 196, 81;
  --gold-dim: rgba(var(--gold-rgb), 0.16);
}

.shop {
  position: relative;
  min-height: 100vh;
  padding: 116px 0 90px;
  /* clip, not hidden: hidden makes .shop a scroll container, and the
     pinned category bar would then stick to nothing. */
  overflow-x: clip;
}

/* 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(var(--theme-rgb),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 ---------------------------------------------------------
   What this page is and the three things a first-time buyer wants to
   know. The tools that narrow the list live in .shop-bar below it. */
.shop-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px 28px;
  padding: 24px 26px;
  border-radius: var(--radius-lg);
  background:
    radial-gradient(ellipse 50% 120% at 100% 0%, rgba(var(--theme-rgb),0.1), transparent 70%),
    linear-gradient(180deg, rgba(255,255,255,0.045), rgba(255,255,255,0.012));
  border: 1px solid rgba(255,255,255,0.09);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), 0 20px 40px -30px rgba(0,0,0,0.9);
}

.shop-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.shop-facts li {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-dim);
}

.shop-facts svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--theme); }

/* Categories and search, pinned under the navbar so they are still at
   hand three sections down. The blur keeps cards legible beneath it. */
.shop-bar {
  position: sticky;
  /* Just under the scrolled navbar, which settles 14px down and 81px
     tall. */
  top: 106px;
  z-index: 20;
  margin: 14px 0 0;
  padding: 10px;
  border-radius: 16px;
  background: rgba(var(--bg-deep-rgb), 0.78);
  border: 1px solid rgba(255,255,255,0.08);
  box-shadow: 0 14px 30px -20px rgba(0,0,0,0.95);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.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(var(--theme-rgb),0.24), rgba(var(--theme-rgb),0.07));
  border: 1px solid rgba(var(--theme-rgb),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: 26px; 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; justify-content: space-between; 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(var(--theme-rgb),0.5);
  background: rgba(var(--theme-rgb),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(var(--theme-rgb),0.5);
  box-shadow: 0 0 0 3px rgba(var(--theme-rgb),0.1);
}

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

.shop-cat-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}

.shop-cat-count {
  margin-inline-start: auto;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-dim);
}

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

.shop-cat-mark svg { width: 19px; height: 19px; }
.shop-cat-title { margin: 0; font-size: 19px; 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: linear-gradient(180deg, rgba(255,255,255,0.02), transparent 30%), var(--bg-panel);
  border: 1px solid rgba(255,255,255,0.075);
  overflow: hidden;
  /* Ordinary depth: a hairline of light on top, a dark edge and a soft
     shadow under. The product's colour stays on the product. */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.05),
    0 2px 0 rgba(0,0,0,0.3),
    0 18px 36px -26px rgba(0,0,0,0.9);
  transition: border-color 0.22s ease, transform 0.22s ease, box-shadow 0.22s ease;
}

.pcard:hover {
  transform: translateY(-4px);
  border-color: rgba(var(--c), 0.38);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.07),
    0 2px 0 rgba(0,0,0,0.3),
    0 30px 46px -28px rgba(0,0,0,0.95);
}

/* 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;
  /* Lit from one lamp above the art: a pale cone from the top edge, the
     product's colour pooled around the art, a little of it on the
     floor — and the floor itself darker than the top. */
  background-color: #070b12;
  background-image:
    radial-gradient(ellipse 46% 70% at 50% -8%, rgba(255,255,255,0.1), transparent 72%),
    radial-gradient(circle at 50% 48%, rgba(var(--p), 0.3), transparent 52%),
    radial-gradient(ellipse 60% 26% at 50% 100%, rgba(var(--p), 0.16), transparent 80%),
    linear-gradient(180deg, rgba(var(--p), 0.16), rgba(0,0,0,0.25)),
    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);
  border-bottom: 1px solid rgba(var(--c), 0.22);
}

/* The art's contact shadow. It tightens as the art lifts on hover. */
.pcard-plate:has(.pcard-art)::after {
  content: '';
  position: absolute;
  top: calc(50% + 34px);
  left: 50%;
  width: 70px;
  height: 12px;
  margin-left: -35px;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(0,0,0,0.65) 0 30%, transparent 70%);
  transition: transform 0.3s ease, opacity 0.3s ease;
  pointer-events: none;
}

.pcard:hover .pcard-plate::after { transform: scale(0.75); opacity: 0.6; }

.pcard-art {
  position: relative;
  z-index: 1;
  display: block;
  width: 70px;
  color: rgb(var(--c));
  /* Lit, not glowing: a bright rim where the lamp catches the top, a
     tight halo of its own colour, a soft shadow underneath. */
  filter:
    drop-shadow(0 -1px 0 color-mix(in srgb, rgb(var(--c)) 60%, #fff))
    drop-shadow(0 0 5px rgba(var(--c), 0.45))
    drop-shadow(0 8px 8px rgba(0,0,0,0.5));
  transition: transform 0.3s cubic-bezier(.22,.61,.36,1);
}

.pcard:hover .pcard-art { transform: translateY(-5px); }

.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.5);
  box-shadow:
    62px 16px 0 rgba(255,255,255,0.35),
    22px 72px 0 rgba(255,255,255,0.25),
    96px 58px 0 rgba(255,255,255,0.4),
    -8px 48px 0 rgba(255,255,255,0.22);
  pointer-events: none;
}

.pcard-badge {
  position: absolute;
  top: 12px;
  inset-inline-start: 12px;
  padding: 5px 11px;
  border-radius: 999px;
  background: rgba(var(--bg-deep-rgb),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 2px 0 rgba(0,0,0,0.55);
  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-price .pcard-per { color: var(--text-dim); opacity: 1; }

.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: var(--bg-deep);
  /* Pulled a little toward the panel so a pure #00FF00 accent reads as
     a lit button, not a light source. */
  background: linear-gradient(180deg,
    color-mix(in srgb, rgb(var(--c)) 74%, #fff) 0%,
    color-mix(in srgb, rgb(var(--c)) 90%, #0b1119) 50%,
    color-mix(in srgb, rgb(var(--c)) 68%, #000) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.45),
    0 3px 0 color-mix(in srgb, rgb(var(--c)) 45%, #000),
    0 10px 16px -10px rgba(0,0,0,0.85);
}

.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.55),
    0 5px 0 color-mix(in srgb, rgb(var(--c)) 45%, #000),
    0 16px 22px -12px rgba(0,0,0,0.9);
}

.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: #070b12;
  background-image:
    radial-gradient(ellipse 60% 70% at 50% -10%, rgba(255,255,255,0.1), transparent 72%),
    radial-gradient(circle at 50% 50%, rgba(var(--p), 0.3), transparent 60%),
    linear-gradient(180deg, rgba(var(--p), 0.14), rgba(0,0,0,0.25)),
    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);
  border: 1px solid rgba(var(--p), 0.26);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), 0 10px 20px -12px rgba(0,0,0,0.9);
}

.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 -1px 0 color-mix(in srgb, rgb(var(--c)) 60%, #fff))
    drop-shadow(0 0 5px rgba(var(--c), 0.45))
    drop-shadow(0 6px 6px rgba(0,0,0,0.5));
}

.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
   SMP perks work on DonutSMP 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;
  /* Toned like .pcard-buy: lit from above, not a light of its own. */
  background: linear-gradient(180deg,
    color-mix(in srgb, rgb(var(--c)) 74%, #fff) 0%,
    color-mix(in srgb, rgb(var(--c)) 90%, #0b1119) 50%,
    color-mix(in srgb, rgb(var(--c)) 68%, #000) 100%);
  color: var(--bg-deep);
  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.45),
    0 4px 0 color-mix(in srgb, rgb(var(--c)) 40%, #000),
    0 14px 20px -12px rgba(0,0,0,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.55),
    0 5px 0 color-mix(in srgb, rgb(var(--c)) 40%, #000),
    0 18px 24px -12px rgba(0,0,0,0.95);
}

.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 70% 45% at 50% 0%, rgba(255,255,255,0.06), transparent 70%),
    radial-gradient(ellipse 90% 55% at 50% 0%, rgba(var(--c), 0.16), transparent 72%);
  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-color: #070b12;
  background-image:
    radial-gradient(ellipse 60% 70% at 50% -10%, rgba(255,255,255,0.1), transparent 72%),
    radial-gradient(circle at 50% 50%, rgba(var(--p), 0.28), transparent 60%),
    linear-gradient(180deg, rgba(var(--p), 0.12), rgba(0,0,0,0.25));
  border: 1px solid rgba(var(--p), 0.26);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), 0 12px 24px -14px rgba(0,0,0,0.95);
}

.buy-art {
  display: block;
  width: 62px;
  color: rgb(var(--c));
  filter:
    drop-shadow(0 -1px 0 color-mix(in srgb, rgb(var(--c)) 60%, #fff))
    drop-shadow(0 0 5px rgba(var(--c), 0.45))
    drop-shadow(0 7px 7px rgba(0,0,0,0.5));
}

.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: var(--bg-deep);
  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); }

/* --- Currency amount (buy dialog) --- */
.shop-amount {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px 6px 14px;
  border-radius: 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(var(--c), 0.35);
  cursor: text;
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.shop-amount:focus-within { border-color: rgba(var(--c), 0.7); box-shadow: 0 0 0 3px rgba(var(--c), 0.14); }
.shop-amount-input {
  flex: 1;
  min-width: 0;
  padding: 8px 0;
  border: 0;
  background: none;
  color: var(--text-main);
  font-family: inherit;
  font-size: 20px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  outline: none;
}
.shop-amount-unit {
  padding: 6px 11px;
  border-radius: 9px;
  background: rgba(var(--c), 0.14);
  color: rgb(var(--c));
  font-size: 12.5px;
  font-weight: 800;
}
.shop-amount-presets { display: flex; flex-wrap: wrap; gap: 6px; }
.shop-amount-chip {
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.1);
  background: rgba(255,255,255,0.03);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.16s ease;
}
.shop-amount-chip:hover { color: var(--text-main); border-color: rgba(var(--c), 0.45); }
.shop-amount-chip.active { color: #fff; background: rgba(var(--c), 0.28); border-color: rgba(var(--c), 0.75); }
.shop-amount-hint { font-size: 11.5px; color: var(--text-dim); }
#buyAmountBlock.is-invalid .shop-amount { border-color: rgba(255,110,110,0.6); }
#buyAmountBlock.is-invalid .shop-amount-hint { color: #ff9c9c; }

/* --- Currency panel (shards) ---
   One wide panel per currency: the crystal, the amount, the bill.
   Lit like one object under one lamp: the light comes from above the
   crystal, pools on the floor under it, and everything else in the
   panel gets ordinary depth shadows rather than a coloured glow. */
.shard-list { display: flex; flex-direction: column; gap: 18px; }

.shard {
  --shard-dark: color-mix(in srgb, rgb(var(--c)) 42%, #000);
  --shard-light: color-mix(in srgb, rgb(var(--c)) 70%, #fff);
  position: relative;
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr) 250px;
  border-radius: 22px;
  background: linear-gradient(180deg, rgba(255,255,255,0.025), transparent 40%), var(--bg-panel);
  border: 1px solid rgba(var(--c), 0.22);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.05),
    0 2px 0 rgba(0,0,0,0.35),
    0 26px 50px -30px rgba(0,0,0,0.95);
  overflow: hidden;
  isolation: isolate;
}

/* --- The crystal and its light --- */
.shard-visual {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 260px;
  overflow: hidden;
  background-color: #070b12;
  background-image:
    radial-gradient(ellipse 70% 55% at 50% 0%, rgba(255,255,255,0.06), transparent 70%),
    radial-gradient(circle at 50% 50%, rgba(var(--c), 0.2), transparent 58%),
    repeating-linear-gradient(0deg, rgba(255,255,255,0.025) 0 1px, transparent 1px 14px),
    repeating-linear-gradient(90deg, rgba(255,255,255,0.025) 0 1px, transparent 1px 14px);
  border-inline-end: 1px solid rgba(255,255,255,0.06);
}

/* The lamp: a soft cone falling from the top edge onto the crystal. */
.shard-beam {
  position: absolute;
  top: 0;
  left: 50%;
  width: 150px;
  height: 62%;
  transform: translateX(-50%);
  clip-path: polygon(38% 0, 62% 0, 100% 100%, 0 100%);
  background: linear-gradient(180deg, rgba(255,255,255,0.09), rgba(var(--c), 0.1) 60%, transparent);
  filter: blur(8px);
  pointer-events: none;
}

.shard-ring {
  position: absolute;
  width: 150px;
  height: 150px;
  border-radius: 50%;
  border: 1px dashed rgba(var(--c), 0.3);
  animation: shard-spin 30s linear infinite;
}
.shard-ring.is-outer {
  width: 196px;
  height: 196px;
  border: 1px solid rgba(255,255,255,0.05);
  border-top-color: rgba(var(--c), 0.35);
  animation-duration: 16s;
  animation-direction: reverse;
}

/* Where the light lands: a pool of the crystal's colour with a dark
   contact shadow inside it. Both shrink as the crystal rises. */
.shard-floor {
  position: absolute;
  top: calc(50% + 58px);
  left: 50%;
  width: 96px;
  height: 18px;
  margin-left: -48px;
  border-radius: 50%;
  background:
    radial-gradient(ellipse at center, rgba(0,0,0,0.7) 0 28%, transparent 62%),
    radial-gradient(ellipse at center, rgba(var(--c), 0.35), transparent 70%);
  animation: shard-floor 4.2s ease-in-out infinite;
}

.shard-crystal {
  position: relative;
  z-index: 1;
  display: block;
  width: 92px;
  color: rgb(var(--c));
  /* A tight rim of its own colour and a soft shadow below — lit, not
     glowing. */
  filter:
    drop-shadow(0 -1px 0 var(--shard-light))
    drop-shadow(0 0 6px rgba(var(--c), 0.45))
    drop-shadow(0 10px 10px rgba(0,0,0,0.5));
  animation: shard-float 4.2s ease-in-out infinite;
}
.shard-crystal svg { display: block; width: 100%; height: auto; }

/* A few specks catching the light inside the beam. */
.shard-motes {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 3px;
  height: 3px;
  border-radius: 1px;
  background: rgba(255,255,255,0.7);
  box-shadow:
    -58px -60px 0 rgba(255,255,255,0.45),
    46px -74px 0 rgba(var(--c), 0.7),
    70px 22px 0 rgba(255,255,255,0.3),
    -78px 30px 0 rgba(var(--c), 0.6),
    -22px -94px 0 rgba(255,255,255,0.35),
    28px 70px 0 rgba(var(--c), 0.45);
  animation: shard-twinkle 3.6s ease-in-out infinite;
}

.shard .pcard-badge { z-index: 2; }

/* --- The amount --- */
.shard-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 24px 26px;
  min-width: 0;
}

.shard-server {
  align-self: flex-start;
  padding: 4px 11px;
  border-radius: 999px;
  background: rgba(var(--c), 0.12);
  border: 1px solid rgba(var(--c), 0.32);
  color: var(--shard-light);
  font-size: 11px;
  font-weight: 800;
}

.shard-name {
  margin: 0;
  font-family: var(--font-pixel);
  font-size: 30px;
  line-height: 1.2;
  font-weight: 400;
  color: #fff;
  text-shadow: 0 2px 0 rgba(0,0,0,0.55);
}

.shard-tag { margin: 0; font-size: 13px; line-height: 1.9; color: var(--text-dim); }
.shard-rate { font-size: 12.5px; font-weight: 700; color: var(--shard-light); }

.shard-picker { display: flex; flex-direction: column; gap: 12px; margin-top: 8px; }

.shard-amount { display: flex; align-items: stretch; gap: 8px; }

.shard-step {
  width: 46px;
  flex-shrink: 0;
  border-radius: 13px;
  border: 1px solid rgba(255,255,255,0.1);
  background: linear-gradient(180deg, rgba(255,255,255,0.07), rgba(255,255,255,0.02));
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.08), 0 2px 0 rgba(0,0,0,0.4);
  color: #fff;
  font-family: inherit;
  font-size: 20px;
  font-weight: 800;
  cursor: pointer;
  transition: background 0.16s ease, transform 0.1s ease, box-shadow 0.1s ease;
}
.shard-step:hover { background: linear-gradient(180deg, rgba(var(--c), 0.28), rgba(var(--c), 0.12)); border-color: rgba(var(--c), 0.4); }
.shard-step:active { transform: translateY(2px); box-shadow: inset 0 1px 0 rgba(255,255,255,0.05), 0 0 0 rgba(0,0,0,0.4); }

.shard-field {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 4px 8px 4px 16px;
  border-radius: 13px;
  background: #060a10;
  border: 1px solid rgba(255,255,255,0.1);
  /* Sunk into the panel: shadow on the inside top edge. */
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.6);
  cursor: text;
  transition: border-color 0.18s ease;
}
.shard-field:focus-within { border-color: rgba(var(--c), 0.7); }
.shard-field input {
  flex: 1;
  min-width: 0;
  padding: 10px 0;
  border: 0;
  background: none;
  color: #fff;
  font-family: inherit;
  font-size: 22px;
  font-weight: 800;
  outline: none;
}
.shard-field span {
  padding: 6px 12px;
  border-radius: 9px;
  background: rgba(var(--c), 0.16);
  color: var(--shard-light);
  font-size: 12.5px;
  font-weight: 800;
}
.shard.is-invalid .shard-field { border-color: rgba(255,110,110,0.65); }

.shard-range {
  --fill: 0%;
  width: 100%;
  height: 22px;
  margin: 0;
  background: none;
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
  direction: ltr;
}
.shard-range::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 999px;
  background: linear-gradient(90deg, rgb(var(--c)) var(--fill), rgba(255,255,255,0.08) var(--fill));
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.6);
}
.shard-range::-moz-range-track { height: 6px; border-radius: 999px; background: rgba(255,255,255,0.08); }
.shard-range::-moz-range-progress { height: 6px; border-radius: 999px; background: rgb(var(--c)); }
.shard-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  margin-top: -7px;
  border-radius: 50%;
  background: linear-gradient(180deg, #fff, #d9dde3);
  border: 4px solid rgb(var(--c));
  box-shadow: 0 2px 4px rgba(0,0,0,0.55);
}
.shard-range::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: linear-gradient(180deg, #fff, #d9dde3);
  border: 4px solid rgb(var(--c));
  box-shadow: 0 2px 4px rgba(0,0,0,0.55);
}
.shard-range:focus-visible { outline: none; }
.shard-range:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px rgba(var(--c), 0.3), 0 2px 4px rgba(0,0,0,0.55); }

.shard-presets { display: flex; flex-wrap: wrap; gap: 7px; }
.shard-preset {
  padding: 7px 14px;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.1);
  background: rgba(255,255,255,0.03);
  box-shadow: 0 2px 0 rgba(0,0,0,0.35);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
  transition: color 0.16s ease, border-color 0.16s ease, background 0.16s ease;
}
.shard-preset:hover { color: #fff; border-color: rgba(var(--c), 0.45); }
.shard-preset.active {
  color: #fff;
  background: rgba(var(--c), 0.26);
  border-color: rgba(var(--c), 0.7);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.12), 0 2px 0 var(--shard-dark);
}
.shard-hint { font-size: 11.5px; color: var(--text-dim); }

/* --- The bill --- */
.shard-checkout {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 8px;
  padding: 24px 22px;
  background: linear-gradient(180deg, rgba(255,255,255,0.02), rgba(0,0,0,0.22));
  border-inline-start: 1px solid rgba(255,255,255,0.06);
}

.shard-total-label { font-size: 12px; color: var(--text-dim); }
.shard-total { display: flex; align-items: baseline; gap: 6px; }
.shard-total b {
  font-size: 30px;
  font-weight: 800;
  color: #fff;
  text-shadow: 0 2px 0 rgba(0,0,0,0.45);
}
.shard-total small { font-size: 12px; color: var(--text-dim); }
.shard-gets { font-size: 12.5px; font-weight: 700; color: var(--shard-light); }

.shard-buy {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 14px;
  border-radius: 13px;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 800;
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.12s ease, filter 0.16s ease;
}
.shard-buy svg { width: 18px; height: 18px; }

/* A slab you press: lit from above, its own darker edge underneath. */
.shard-buy {
  margin-top: 6px;
  border: 1px solid rgba(255,255,255,0.18);
  color: #fff;
  background: linear-gradient(180deg, var(--shard-light) -40%, rgb(var(--c)) 55%, color-mix(in srgb, rgb(var(--c)) 85%, #000));
  text-shadow: 0 1px 0 rgba(0,0,0,0.3);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.4),
    0 4px 0 var(--shard-dark),
    0 12px 18px -10px rgba(0,0,0,0.85);
}
.shard-buy:hover {
  transform: translateY(-1px);
  filter: brightness(1.06);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.45),
    0 5px 0 var(--shard-dark),
    0 16px 22px -12px rgba(0,0,0,0.9);
}
.shard-buy:active {
  transform: translateY(3px);
  box-shadow: inset 0 2px 4px rgba(0,0,0,0.3), 0 1px 0 var(--shard-dark);
}
.shard-buy:disabled { opacity: 0.4; cursor: not-allowed; transform: none; filter: grayscale(0.4); }

@keyframes shard-float {
  0%, 100% { transform: translateY(4px); }
  50% { transform: translateY(-8px); }
}
/* In step with the float: high crystal, small faint shadow. */
@keyframes shard-floor {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(0.72); opacity: 0.6; }
}
@keyframes shard-spin { to { transform: rotate(360deg); } }
@keyframes shard-twinkle {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 0.9; }
}

@media (prefers-reduced-motion: reduce) {
  .shard-ring, .shard-crystal, .shard-motes, .shard-floor { animation: none; }
}

@media (max-width: 980px) {
  .shard { grid-template-columns: 200px minmax(0, 1fr); }
  .shard-checkout {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: center;
    border-inline-start: 0;
    border-top: 1px solid rgba(255,255,255,0.06);
  }
  .shard-total-label, .shard-total, .shard-gets { grid-column: 1; }
  .shard-buy { grid-column: 2; grid-row: 1 / 4; margin-top: 0; }
}

@media (max-width: 620px) {
  .shard { grid-template-columns: 1fr; }
  .shard-visual { min-height: 210px; border-inline-end: 0; border-bottom: 1px solid rgba(255,255,255,0.06); }
  .shard-body { padding: 20px 18px; }
  .shard-checkout { padding: 18px; }
  .shard-name { font-size: 26px; }
}

/* --- 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(var(--online-rgb),0.09);
  border: 1px solid rgba(var(--online-rgb),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(var(--online-rgb),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(var(--theme-rgb),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;
  /* Toned like .pcard-buy: lit from above, not a light of its own. */
  background: linear-gradient(180deg,
    color-mix(in srgb, rgb(var(--c)) 74%, #fff) 0%,
    color-mix(in srgb, rgb(var(--c)) 90%, #0b1119) 50%,
    color-mix(in srgb, rgb(var(--c)) 68%, #000) 100%);
  color: var(--bg-deep);
  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.45),
    0 4px 0 color-mix(in srgb, rgb(var(--c)) 40%, #000),
    0 14px 20px -12px rgba(0,0,0,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.55),
    0 5px 0 color-mix(in srgb, rgb(var(--c)) 40%, #000),
    0 18px 24px -12px rgba(0,0,0,0.95);
}

.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(var(--theme-rgb),0.1);
  border: 1px solid rgba(var(--theme-rgb),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(var(--online-rgb),0.1); border-color: rgba(var(--online-rgb),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: 18px; }
  .shop-head-title { font-size: 22px; }
  .shop-facts { flex-direction: column; gap: 8px; }
  /* Not pinned on a phone: two rows of tools would cover a third of the
     screen. The categories become one row that swipes sideways. */
  .shop-bar { position: static; padding: 8px; }
  .shop-head-tools { width: 100%; }
  .shop-cats { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; width: 100%; }
  .shop-cats::-webkit-scrollbar { display: none; }
  .shop-cat { flex-shrink: 0; }
  .shop-search { flex-basis: 100%; }
  .shop-cat-note { display: none; }

  /* Two to a row: one card per screen made a phone scroll past every
     product one at a time. The card gives up padding, not content. */
  .shop-grid { grid-template-columns: 1fr 1fr; gap: 10px; }
  .pcard { border-radius: 16px; }
  .pcard-plate { height: 108px; }
  .pcard-art { width: 50px; }
  .pcard-plate:has(.pcard-art)::after { top: calc(50% + 24px); width: 50px; margin-left: -25px; }
  .pcard-badge { top: 8px; inset-inline-start: 8px; padding: 3px 8px; font-size: 9.5px; }
  .pcard-body { padding: 12px 12px 8px; }
  .pcard-name { font-size: 16px; }
  .pcard-tag { font-size: 11px; }
  .pcard-foot { flex-direction: column; align-items: flex-start; gap: 6px; margin: 0 12px; padding: 10px 0; }
  .pcard-price b { font-size: 16px; }
  .pcard-actions { margin: 0 12px 12px; gap: 6px; }
  .pcard-more, .pcard-buy { padding: 10px; font-size: 12.5px; }
  /* The eye alone says "look closer"; the word would not fit. */
  .pcard-more span { display: none; }
  .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(var(--theme-rgb),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(var(--gold-rgb),0.22));
  box-shadow: 0 0 18px -4px rgba(var(--gold-rgb),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(var(--online-rgb),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(var(--theme-rgb),0.07), rgba(255,255,255,0.015));
  border-color: rgba(var(--theme-rgb),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(var(--theme-rgb),0.45);
  box-shadow: 0 0 0 3px rgba(var(--theme-rgb),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(var(--online-rgb),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: var(--online);
  box-shadow: 0 0 8px var(--online);
}

.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, var(--online), rgba(var(--online-rgb),0.7)); box-shadow: 0 12px 28px -12px rgba(var(--online-rgb),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(var(--theme-rgb),0.5);
  box-shadow: 0 0 0 3px rgba(var(--theme-rgb),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(var(--online-rgb),0.4); color: #6fe6a2; }
.admin-toast.error { border-color: rgba(255,110,110,0.4); color: #ff9c9c; }

/* --- Rank prefixes --- */
.admin-field[hidden] { display: none; }
.admin-field input[type="color"] { height: 44px; padding: 4px; cursor: pointer; }

.rank-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }

.rank-card {
  display: flex;
  flex-direction: column;
  border-radius: 14px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.07);
  overflow: hidden;
}

/* The prefix as it sits in chat: in front of a name, on a dark ground. */
.rank-card-preview,
.rank-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 22px 14px;
  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),
    #060a10;
  font-size: 17px;
  direction: ltr;
}
.rank-preview { border-radius: 12px; border: 1px solid rgba(255,255,255,0.06); font-size: 20px; padding: 26px 14px; }

.rank-card-name {
  font-family: var(--font-pixel);
  color: #fff;
  filter: drop-shadow(2px 2px 0 rgba(0,0,0,0.55));
}

.rank-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border-top: 1px solid rgba(255,255,255,0.06);
}
.rank-card-foot > span:first-child { display: flex; flex-direction: column; gap: 2px; }
.rank-card-foot code { font-size: 12.5px; color: var(--text-main); }
.rank-card-foot small { font-size: 11px; color: var(--text-dim); }
.rank-card-actions { display: flex; gap: 6px; }

.rank-suggest { display: flex; flex-wrap: wrap; gap: 8px; }
.rank-suggest-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: 11px;
  background: #060a10;
  border: 1px dashed rgba(255,255,255,0.16);
  color: var(--text-dim);
  font-family: inherit;
  font-size: 14px;
  cursor: pointer;
}
.rank-suggest-item:hover { border-color: rgba(var(--v), 0.6); }
.rank-suggest-item small { font-size: 11px; }

/* --- Products, as the shop shows them ---
   The cards are the shop's own (.pcard, product-card.js); this only
   fits them into the panel. */
.admin-pgroups { display: flex; flex-direction: column; gap: 30px; margin-top: 18px; }
.admin-pgrid .pcard { cursor: pointer; }
.admin-pgrid .pcard-actions:has(> :only-child) { grid-template-columns: 1fr; }

/* The admin's warning over a plate — opposite corner to the badge. */
.pcard-flag {
  position: absolute;
  top: 12px;
  inset-inline-end: 12px;
  z-index: 2;
  padding: 5px 10px;
  border-radius: 999px;
  background: rgba(40,8,10,0.85);
  border: 1px solid rgba(255,110,110,0.55);
  color: #ff9c9c;
  font-size: 10.5px;
  font-weight: 800;
}

/* The editor's live preview: one card at shop width on the shop's floor. */
.admin-pcard-preview {
  display: grid;
  place-items: center;
  padding: 22px;
  border-radius: 14px;
  background: var(--bg-deep);
  border: 1px solid rgba(255,255,255,0.06);
}
.admin-pcard-preview .pcard { width: min(270px, 100%); }
.admin-pcard-preview .pcard-more,
.admin-pcard-preview .pcard-buy { pointer-events: none; }

/* --- Site editor --- */
.site-page { flex: 0 1 200px; }
.site-hint { margin: 12px 0; line-height: 1.9; }

.site-frame-wrap {
  margin-bottom: 18px;
  border-radius: var(--radius-md);
  border: 1px solid rgba(var(--v), 0.3);
  overflow: hidden;
  background: #04070b;
  box-shadow: 0 24px 50px -30px rgba(0,0,0,0.9);
}
.site-frame { display: block; width: 100%; height: 72vh; min-height: 460px; border: 0; background: var(--bg-deep); }

.site-colors {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 10px;
  margin-bottom: 16px;
}
.site-color {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 11px;
  border-radius: 11px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.07);
  cursor: pointer;
}
.site-color input[type="color"] {
  flex: none;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 9px;
  background: none;
  cursor: pointer;
}
.site-color input[type="color"]::-webkit-color-swatch-wrapper { padding: 3px; }
.site-color input[type="color"]::-webkit-color-swatch { border: 0; border-radius: 6px; }
.site-color span { flex: 1; font-size: 12.5px; font-weight: 700; color: var(--text-main); }
.site-color code { font-size: 11px; color: var(--text-dim); }

.site-css textarea { min-height: 130px; }

.site-current {
  margin: 0;
  padding: 10px 13px;
  border-radius: 11px;
  background: rgba(255,255,255,0.03);
  border: 1px dashed rgba(255,255,255,0.12);
  font-size: 13px;
  line-height: 1.9;
  color: var(--text-dim);
  word-break: break-word;
}

.site-img-preview {
  display: grid;
  place-items: center;
  height: 190px;
  padding: 10px;
  border-radius: 12px;
  background: repeating-conic-gradient(rgba(255,255,255,0.04) 0 25%, transparent 0 50%) 0 0 / 18px 18px, #04070b;
  border: 1px solid rgba(255,255,255,0.08);
}
.site-img-preview img { max-width: 100%; max-height: 100%; object-fit: contain; }

.site-thumb { display: block; width: 72px; height: 44px; object-fit: cover; border-radius: 7px; background: #04070b; }
.site-was { color: var(--text-dim); text-decoration: line-through; text-decoration-color: rgba(255,143,143,0.5); }
.site-was .site-thumb { opacity: 0.6; }
#siteChanges td { max-width: 340px; word-break: break-word; line-height: 1.8; }

/* --- Site config --- */
.cfg-title { margin: 22px 0 10px; font-size: 14px; font-weight: 800; color: var(--text-main); }
.cfg-title:first-child { margin-top: 0; }
.cfg-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.cfg-limits { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
/* Inside a column-flex label .admin-input's flex-basis would be its height. */
#cfgForm .admin-field .admin-input { flex: none; width: 100%; }
#cfgForm textarea.admin-input { resize: vertical; line-height: 1.8; }
#cfgModes { display: flex; flex-direction: column; gap: 8px; margin: 10px 0; }
.cfg-row { display: grid; grid-template-columns: 1fr 1.2fr 1.4fr 0.8fr auto; gap: 8px; align-items: center; }
.cfg-row .admin-input { flex: none; width: 100%; }

@media (max-width: 900px) {
  .cfg-pair, .cfg-limits { grid-template-columns: 1fr 1fr; }
  .cfg-row { grid-template-columns: 1fr 1fr; }
  .site-frame { height: 60vh; }
}

@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;
  /* Same lighting as .pcard-plate, so the preview is what the shop shows. */
  background-color: #070b12;
  background-image:
    radial-gradient(ellipse 46% 70% at 50% -8%, rgba(255,255,255,0.1), transparent 72%),
    radial-gradient(circle at 50% 48%, rgba(var(--p), 0.3), transparent 52%),
    radial-gradient(ellipse 60% 26% at 50% 100%, rgba(var(--p), 0.16), transparent 80%),
    linear-gradient(180deg, rgba(var(--p), 0.16), rgba(0,0,0,0.25)),
    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);
  border: 1px solid rgba(var(--p), 0.26);
}

.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; }

/* --- A rank's prefix ---
   The text in front of a player's name in chat, in the game's own face —
   one colour, or a gradient between two. The drop shadow is a filter, not
   a text-shadow, because a gradient is painted through transparent text
   and a text-shadow would show through it. */
.rank-prefix {
  --rc: #9db2c2;
  --rc2: var(--rc);
  display: inline-block;
  font-family: var(--font-pixel);
  font-size: 1em;
  line-height: 1.2;
  color: var(--rc);
  white-space: nowrap;
  filter: drop-shadow(2px 2px 0 rgba(0,0,0,0.55));
  unicode-bidi: isolate;
}

.rank-prefix.is-gradient {
  background: linear-gradient(90deg, var(--rc), var(--rc2));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* --- 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: var(--bg-deep);
  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; }
}
