/* Shared styles of the site pages: palette, header bar, buttons, inputs, tables. Linked first in <head> by shell.wrap(),
   the page's own styles follow in <style>. The link carries ?v=<md5> (shell.asset), so the panel must be restarted after
   an edit here (install.sh does it). Every page uses it, the admin page too (its own CSS only adds to it). */

/* ---- base: palette, body, header bar, buttons, inputs ---- */
/* FACEIT level (FaceitBadge in static/js/shared/stats.js) */
.fcl { text-decoration: none; white-space: nowrap; }
.fci { width: 22px; height: 22px; margin-left: 8px; vertical-align: -6px; }
.fce { margin-left: 5px; font-size: 0.8rem; font-weight: 700; color: var(--text-2); }
.fcp { visibility: hidden; white-space: nowrap; } .fcp .fci { display: inline-block; }  /* the place of a badge still on its way */
.fc0 { display: inline-grid; place-items: center; width: 22px; height: 22px; margin-left: 8px; border-radius: 50%; border: 2px solid #6e6e73;
  color: #9a9aa0; font-size: 0.72rem; font-weight: 800; vertical-align: -6px; box-sizing: border-box; }
:root {
  color-scheme: dark;
  --bg: #0a0a0d; --surface: #17171c; --glass: rgba(22, 22, 28, 0.72);
  --stroke: rgba(255, 255, 255, 0.08); --stroke-2: rgba(255, 255, 255, 0.16);
  --text: #f5f5f7; --text-2: rgba(235, 235, 245, 0.62); --text-3: rgba(235, 235, 245, 0.38);
  --accent: #0a84ff; --accent-soft: rgba(10, 132, 255, 0.14); --green: #30d158; --red: #ff453a;
  --radius: 18px; --radius-sm: 11px;
  --shadow: 0 1px 0 rgba(255, 255, 255, 0.04) inset, 0 10px 30px -12px rgba(0, 0, 0, 0.6);
  --shadow-lg: 0 1px 0 rgba(255, 255, 255, 0.06) inset, 0 30px 80px -20px rgba(0, 0, 0, 0.75);
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);  /* strong ease-out for presses and things that appear */
}
* { box-sizing: border-box; }
/* no grey flash on tap (every control has its own :active), no font inflation in landscape; the scrollbar's place is kept
   even before the page is long enough to need it, so the page does not jump sideways when the content arrives */
html { -webkit-tap-highlight-color: transparent; -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }
body {
  margin: 0; min-height: 100vh; min-height: 100svh; color: var(--text);
  background: radial-gradient(1100px 520px at 50% -180px, rgba(64, 72, 120, 0.35), transparent 70%), var(--bg);
  background-attachment: fixed;
  font: 100%/1.5 system-ui, -apple-system, "SF Pro Text", "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; }
.bar {
  position: sticky; top: 0; z-index: 10; display: flex; align-items: center; gap: 16px;
  padding: 14px 24px; background: var(--glass);
  -webkit-backdrop-filter: blur(22px) saturate(180%); backdrop-filter: blur(22px) saturate(180%);
  box-shadow: 0 1px 0 var(--stroke);
}
/* the header shows in one piece: a slow phone network delivers the page in parts, and half a header was painted and then
   rebuilt (the account block came later and pushed the rest). Until the parser is past </header> its contents wait;
   a browser without :has() drops the rule and shows them at once */
.bar:not(:has(+ *)) > * { visibility: hidden; }
.bar h1 { margin: 0; font-size: 1.05rem; font-weight: 650; letter-spacing: -0.01em; }
.bar h1 a { text-decoration: none; }
.bar .nav { margin-left: auto; display: flex; gap: 6px; }
.bar .nav a { text-decoration: none; padding: 5px 12px; border-radius: 999px; color: var(--text-2); font-size: 0.88rem; }
@media (hover: hover) and (pointer: fine) { .bar .nav a:hover { background: rgba(255, 255, 255, 0.07); color: var(--text); } }
.bar .nav a.on { background: rgba(255, 255, 255, 0.1); color: var(--text); }
main { max-width: 1100px; margin: 0 auto; padding: 28px 24px 48px; }
h2 { margin: 0 0 6px; font-size: clamp(1.7rem, 3vw, 2.3rem); font-weight: 700; letter-spacing: -0.025em; line-height: 1.1; }
.lead { margin: 0 0 24px; color: var(--text-2); }
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font: inherit; font-size: 0.9rem; font-weight: 550; cursor: pointer; text-decoration: none;
  padding: 8px 16px; border: 0; border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.08); color: var(--text);
  transition: transform 160ms var(--ease-out), background-color 150ms ease;
  touch-action: manipulation; user-select: none; -webkit-user-select: none;  /* a tap clicks at once, a long press selects nothing */
}
@media (hover: hover) and (pointer: fine) { .btn:hover { background: rgba(255, 255, 255, 0.13); } }
.btn:active { transform: scale(0.97); }
.btn.primary { background: var(--accent); color: #fff; }
@media (hover: hover) and (pointer: fine) { .btn.primary:hover { background: #2a95ff; } }
button, summary, a { touch-action: manipulation; }
button { -webkit-user-select: none; user-select: none; }
/* press feedback for what is tapped on a phone (hover is mouse-only now): small things a little more, big cards barely */
.tabs button, .act, .mbox, .ib, .qt { transition: transform 160ms var(--ease-out); }  /* .vmap keeps its own (transform and border colour) */
.tabs button:active, .ib:active, .qt:active { transform: scale(0.97); }
.act:active, .mbox:active, .vmap.can:active { transform: scale(0.985); }
.bar .nav a:active { background: rgba(255, 255, 255, 0.1); }
input {
  font: inherit; color: var(--text); background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--stroke); border-radius: var(--radius-sm); padding: 10px 14px; width: 100%;
}
input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
input::placeholder { color: var(--text-3); }
/* Windows draws the list of a <select> on a white background and our light text becomes invisible: dark list everywhere */
select { color-scheme: dark; }
select option, select optgroup { background-color: #1c1c22; color: #f5f5f7; }
select option:checked { background-color: #0a84ff; color: #fff; }
/* iPhone zooms into a field with text under 16px and does not zoom back: 16px wherever the pointer is a finger */
@media (pointer: coarse) { input, select, textarea { font-size: 16px !important; } }  /* !important: pages set font: inherit inside small labels */
@media (prefers-reduced-motion: reduce) { * { transition-duration: 1ms !important; animation: none !important; } .btn:active { transform: none; } }
@media (prefers-reduced-transparency: reduce) { .bar { background: #141419; backdrop-filter: none; -webkit-backdrop-filter: none; } }
@media (prefers-contrast: more) { :root { --stroke: rgba(255, 255, 255, 0.3); --text-2: rgba(245, 245, 247, 0.85); --text-3: rgba(245, 245, 247, 0.7); } }
@media (max-width: 560px) { main { padding: 20px 16px 40px; } .bar { padding: 12px 16px; } }
@media (max-width: 1360px) {  /* 9 menu items do not fit next to the title and the donate pill: menu on its own row */
  .bar { flex-wrap: wrap; gap: 8px 12px; } .bar h1 { white-space: nowrap; }
  .bar .nav { order: 3; width: 100%; margin-left: 0; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .bar .nav::-webkit-scrollbar { display: none; } .bar .nav a { white-space: nowrap; }
}

/* ---- tables and lists: players, matches, tournaments ---- */
.back { display: inline-block; margin-bottom: 16px; color: var(--text-3); text-decoration: none; font-size: 0.9rem; }
@media (hover: hover) and (pointer: fine) { .back:hover { color: var(--text); } }
.tools { display: flex; gap: 10px; margin-bottom: 18px; flex-wrap: wrap; align-items: center; }
/* the field gives up room to the count: the count comes with the data, and a field of full width went to its own row on a phone
   and pushed the list down */
.tools input { flex: 1 1 200px; min-width: 0; max-width: 360px; border-radius: 999px; padding-left: 16px; }
.count { color: var(--text-3); font-size: 0.9rem; white-space: nowrap; }
.board { background: var(--surface); border: 1px solid var(--stroke); border-radius: var(--radius); box-shadow: var(--shadow); overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
th { text-align: right; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-3);
  padding: 12px 10px; border-bottom: 1px solid var(--stroke); white-space: nowrap; user-select: none; }
th.sort { cursor: pointer; } @media (hover: hover) and (pointer: fine) { th.sort:hover { color: var(--text); } } th.on { color: var(--text); }
th.sort:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }  /* .board clips the browser's own ring */
td { text-align: right; padding: 11px 10px; border-top: 1px solid var(--stroke); white-space: nowrap; }
tbody tr:first-child td { border-top: 0; }
th:first-child, td:first-child { text-align: left; padding-left: 16px; }
th:last-child, td:last-child { padding-right: 16px; }
td.player a, td.name a { color: var(--text); text-decoration: none; font-weight: 600; }
@media (hover: hover) and (pointer: fine) { td.player a:hover, td.name a:hover { text-decoration: underline; } }
td.rank { color: var(--text-3); width: 1%; }
td.player, th.pl { text-align: left; }
td.main { font-weight: 700; } td.rating { font-weight: 800; font-size: 1.02rem; }
.pos { color: #6fe08f; } .neg { color: #ff8a80; } .dim { color: var(--text-3); }
.tag { padding: 3px 11px; border-radius: 999px; font-size: 0.8rem; font-weight: 600; background: rgba(255, 255, 255, 0.07); color: var(--text-2); }
.tag.map { background: var(--accent-soft); color: #8cc6ff; }
.note { margin: 14px 4px 0; color: var(--text-3); font-size: 0.8rem; }
.empty { padding: 40px; text-align: center; color: var(--text-3); }
h3 { margin: 30px 4px 10px; font-size: 1.15rem; letter-spacing: -0.015em; }

/* ---- loading skeleton (static/js/shared/ui.js Skeleton): grey shapes where the content will be, instead of «Загрузка…».
   Invisible for the first 200 ms, so a page that loads quickly never flashes it; then a gentle pulse of opacity only
   (no layout or paint work). With reduced motion it simply stands still (the rule above stops animations). ---- */
.skel { display: grid; gap: 14px; animation: sk-in 200ms ease-out 200ms both; }
.sk { background: rgba(255, 255, 255, 0.06); border-radius: var(--radius); animation: sk-pulse 1.1s ease-in-out 400ms infinite alternate; }
.sk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.sk-card { height: 148px; } .sk-hero { height: 168px; border-radius: 22px; }
.sk-line { height: 16px; width: 58%; border-radius: 8px; } .sk-line.short { width: 34%; }
.sk-rows { display: grid; gap: 8px; } .sk-row { height: 42px; border-radius: 12px; }
@keyframes sk-in { from { opacity: 0; } }
@keyframes sk-pulse { from { opacity: 1; } to { opacity: 0.45; } }
/* reduced motion: no pulse, but the 200 ms before the skeleton shows stay (a fade is not motion), else it flashes on quick pages */
@media (prefers-reduced-motion: reduce) { .skel { animation: sk-in 200ms ease-out 200ms both !important; } }
/* the server's skeleton was already on screen when the module started (ui.js mount): the module's own shows at once */
.sk-now .skel { animation: none !important; }
