/* The launcher site's design, carried over.
   Tokens, the cut corner and the button are lifted from xero-site/src/index.template.html so
   play.c0unter.org and this site are visibly one thing. Everything below the token block is new
   -- that page is a single column of prose, this one is a database. */

:root {
  --bg:        #0b0e14;
  --bg-2:      #090c11;
  --panel:     #131822;
  --panel-2:   #0f141d;
  --line:      #1f2733;
  --line-soft: #171e28;
  --text:      #c8d0dd;
  --bright:    #ffffff;
  --dim:       #7d8797;
  --dimmer:    #5c6675;
  --accent:    #00a5f9;
  --accent-lo: #0b84c6;
  --ember:     #ff8a3d;
  --ember-lo:  #c95f1d;
  --warn:      #ffb648;
  --win:       #4ac97e;
  --loss:      #e5606b;

  --shell: 68rem;
  --shell-wide: 82rem;
  --cut: 14px;
  --cut-sm: 9px;
}

*, *::before, *::after { box-sizing: border-box; }

/* The page background: a wallpaper Gaussian-blurred and JPEG-recompressed for the web. The blur is
   baked into the file -- not a CSS filter -- which is what the -blur in the name says and what the
   see-through panels count on (see .panel): text sits on them over a soft wash, not a sharp scene.
   Fixed, so it stays put while the page scrolls.

   Where it is seen is worth knowing before changing anything above it. The panels are nearly
   opaque, so the picture shows in the band across the top, down the two strips either side of the
   content column, and behind the footer. Anything that paints a full-width layer in those places
   covers it -- which is what the hero's own gradient and the footer's solid fill used to do.

   Those strips are also why the window width matters: .shell is min(100% - 2.5rem, 68rem), so
   below about 1130px the content fills the page and the strips collapse to 20px. On a narrow
   window the top band is the only place this is really seen.

   The art is 1.9:1 and the page is taller than it is wide, so `cover` crops the sides off. It is
   anchored top-right to keep the figure in frame; the moon runs off to the left, which is the
   part that loses nothing by being cropped.

   The filename carries the picture, not a version query: assets are served with a long cache
   lifetime and the stylesheet's own ?v= does nothing for a URL inside it. Changing the image
   means changing this name, or every browser that has been here keeps showing the old one --
   which is exactly what happened while this was being built. */
body {
  margin: 0;
  background: var(--bg) url("/assets/bg-city-moon-blur.jpg") 100% 0 / cover no-repeat fixed;
  color: var(--text);
  font: 400 15px/1.6 "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, "Inter", sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* The darkening over the background: a flat scrim across the whole picture, then a vignette that
   deepens the corners and the bottom. The brand and the hero heading sit on the background in the
   top band -- the part the vignette alone keeps clearest -- so the flat scrim is what lifts that
   text off the picture and makes the page easier to read; the vignette then adds more where no
   content is. Turn the scrim's --bg percentage up for a darker page, down for more of the picture.

   Fixed and behind the content, like the background it sits on. z-index -1 puts it above the
   body's own background and below everything in the page. */
body::after {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(color-mix(in srgb, var(--bg) 50%, transparent), color-mix(in srgb, var(--bg) 50%, transparent)),
    radial-gradient(120% 100% at 70% 15%, transparent 30%, color-mix(in srgb, var(--bg) 72%, transparent) 100%),
    linear-gradient(180deg, transparent 45%, color-mix(in srgb, var(--bg) 65%, transparent) 100%);
}

h1, h2, h3 { color: var(--bright); line-height: 1.15; margin: 0; font-weight: 600; }
p { margin: 0; }
img { max-width: 100%; }

a {
  color: var(--accent);
  text-decoration-color: color-mix(in srgb, var(--accent) 35%, transparent);
  text-underline-offset: .2em;
}
a:hover { text-decoration-color: currentColor; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }
::selection { background: var(--ember); color: #17100a; }

.shell { width: min(100% - 2.5rem, var(--shell)); margin-inline: auto; }
main.wide .shell { width: min(100% - 2.5rem, var(--shell-wide)); }
.shell.narrow { width: min(100% - 2.5rem, 30rem); }
.dim { color: var(--dim); }
.empty { color: var(--dimmer); padding: 1.4rem; text-align: center; }
.rule { border: 0; border-top: 1px solid var(--line-soft); margin: 1.6rem 0; }

/* The bevel the whole design is built on: the clip eats a border, so a frame is drawn as an
   inset background layer underneath rather than as a border property. */
.cut, .panel, .btn {
  clip-path: polygon(0 var(--cut-sm), var(--cut-sm) 0, 100% 0,
                     100% calc(100% - var(--cut-sm)), calc(100% - var(--cut-sm)) 100%, 0 100%);
}

/* ------------------------------------------------------------------- top bar */

.bar {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line-soft);
}
.bar-in { display: flex; align-items: center; gap: 1.1rem; height: 60px; }
main.wide ~ .bar .bar-in, .bar .bar-in { width: min(100% - 2.5rem, var(--shell-wide)); }

.brand { display: flex; align-items: center; gap: .6rem; text-decoration: none; color: var(--bright); }
.brand span { font-weight: 600; font-size: .78rem; letter-spacing: .2em; text-transform: uppercase; white-space: nowrap; }
/* The server's own logo, the same file the launcher uses. Its orange is the one warm thing in
   a blue header, which is what makes it read as the mark rather than as another button. */
.brand-mark {
  width: 24px; height: 24px; flex: none; object-fit: contain;
  filter: drop-shadow(0 0 10px rgba(255,138,61,.35));
}

.bar-nav { display: flex; gap: .2rem; }
.bar-nav a {
  color: var(--dim); text-decoration: none; font-size: .86rem; font-weight: 500;
  padding: .45rem .7rem; border-radius: 3px;
}
.bar-nav a:hover { color: var(--bright); background: var(--line-soft); }
.bar-nav a.on { color: var(--bright); box-shadow: inset 0 -2px 0 var(--accent); }

.search { margin-left: auto; }
.search input {
  background: var(--panel-2); border: 1px solid var(--line); color: var(--text);
  padding: .42rem .8rem; width: 15rem; max-width: 34vw; font: inherit; font-size: .86rem;
  border-radius: 3px;
}
.search input:focus { border-color: var(--accent-lo); outline: none; }
.search input::placeholder { color: var(--dimmer); }

/* Search suggestions. The list hangs off the form, which is why the form is positioned. */
.search { position: relative; }
.ac {
  position: absolute; top: calc(100% + .4rem); left: 0; right: 0; z-index: 60;
  list-style: none; margin: 0; padding: .25rem;
  background: var(--panel); border: 1px solid var(--line); border-radius: 3px;
  box-shadow: 0 18px 40px -18px rgba(0,0,0,.9);
  max-height: 22rem; overflow-y: auto;
}
.ac[hidden] { display: none; }
.ac a {
  display: flex; align-items: center; gap: .55rem;
  padding: .35rem .5rem; text-decoration: none; border-radius: 3px;
}
.ac a:hover, .ac a.on { background: var(--panel-2); }
.ac a.on { box-shadow: inset 2px 0 0 var(--accent); }
.ac .pl-name { font-size: .88rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ac-lvl { margin-left: auto; color: var(--dimmer); font-size: .76rem; display: flex; align-items: center; gap: .3rem; white-space: nowrap; }
.ac-lvl .grade { width: 20px; height: 20px; }
.ac-empty { padding: .6rem .5rem; color: var(--dimmer); font-size: .84rem; }

.bar-me { display: flex; align-items: center; gap: .6rem; }
.me { display: flex; align-items: center; gap: .5rem; color: var(--bright); text-decoration: none; font-size: .86rem; font-weight: 500; }
.me:hover { color: var(--accent); }

/* -------------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .78rem 1.7rem;
  background: linear-gradient(180deg, #22b6ff, var(--accent) 55%, #0090dd);
  color: #04121c; font-weight: 700; font-size: .95rem;
  text-decoration: none; border: 0; cursor: pointer; font-family: inherit;
  box-shadow: 0 8px 26px -12px rgba(0,165,249,.75);
  transition: transform .15s, box-shadow .15s, filter .15s;
}
.btn:hover { transform: translateY(-1px); filter: brightness(1.06); }
.btn:active { transform: none; }
.btn-sm { padding: .45rem 1rem; font-size: .82rem; }
.btn-ghost {
  background: transparent; color: var(--text); box-shadow: none;
  border: 1px solid var(--line); font-weight: 500; clip-path: none; border-radius: 3px;
}
.btn-ghost:hover { border-color: var(--accent-lo); color: var(--bright); filter: none; }

.linkish {
  background: none; border: 0; color: var(--dimmer); font: inherit; font-size: .8rem;
  cursor: pointer; padding: 0;
}
.linkish:hover { color: var(--loss); }
.inline-form { display: inline; }

/* --------------------------------------------------------------------- panels */

/* A little see-through, so the wallpaper carries into the boxes instead of stopping at their
   edges. Kept high enough that body text is still on an even ground -- the picture behind is
   already blurred, so no backdrop filter is needed to calm it. */
.panel {
  background: color-mix(in srgb, var(--panel) 82%, transparent);
  border-top: 1px solid var(--line);
  margin-bottom: 1.1rem;
}
.panel-h {
  font-size: .72rem; letter-spacing: .18em; text-transform: uppercase; color: var(--dim);
  padding: .9rem 1.1rem; border-bottom: 1px solid var(--line-soft); font-weight: 600;
}
.page-h { font-size: 1.6rem; letter-spacing: -.02em; margin: 1.8rem 0 1rem; }
.notice { padding: .7rem 1rem; margin: 0 0 1rem; font-size: .88rem; border-left: 3px solid; }
.notice.ok { border-color: var(--win); background: color-mix(in srgb, var(--win) 8%, transparent); }
.notice.bad { border-color: var(--loss); background: color-mix(in srgb, var(--loss) 10%, transparent); color: #ffd8dc; }

/* ----------------------------------------------------------------- front page */

.hero-slim {
  position: relative; isolation: isolate; overflow: hidden;
  padding: clamp(2.4rem, 6vw, 4rem) 0 clamp(1.6rem, 3vw, 2.4rem);
  border-bottom: 1px solid var(--line-soft);
}
.hero-slim::before { content: none; }
/* The halftone that keeps the dark from reading as flat black, same as the launcher page. */
.hero-slim::after { content: none; }
.hero-slim-in { display: grid; justify-items: center; text-align: center; gap: .7rem; }
.hero-slim h1 { font-size: clamp(2rem, 5.4vw, 3.1rem); letter-spacing: -.035em; font-weight: 700; }
.eyebrow {
  font-size: .68rem; letter-spacing: .3em; text-transform: uppercase; color: var(--accent);
  display: flex; align-items: center; gap: .7rem; margin: 0;
}
.eyebrow::before, .eyebrow::after { content: ""; height: 1px; width: 1.8rem; background: linear-gradient(90deg, transparent, var(--accent-lo)); }
.eyebrow::after { background: linear-gradient(90deg, var(--accent-lo), transparent); }
.lede { color: var(--dim); max-width: 34rem; text-wrap: balance; }
.stat-strip { display: flex; gap: 1.6rem; flex-wrap: wrap; justify-content: center; margin-top: .5rem; font-size: .84rem; color: var(--dim); }
.stat-strip b { color: var(--bright); font-weight: 600; }

.cols { display: grid; grid-template-columns: 17.5rem 1fr; gap: 1.4rem; padding: 1.8rem 0 3rem; align-items: start; }
@media (max-width: 60rem) { .cols { grid-template-columns: 1fr; } }

/* ---------------------------------------------------------------- leaderboards */

.board { list-style: none; margin: 0; padding: .35rem; }
.board-row { display: flex; align-items: center; gap: .6rem; padding: .4rem .5rem; border-radius: 3px; }
.board-row:hover { background: var(--panel-2); }
.place {
  width: 1.4rem; flex: none; text-align: center; font-size: .78rem; font-weight: 700;
  color: var(--dimmer);
}
.board-row:nth-child(1) .place { color: var(--warn); }
.board-row:nth-child(2) .place { color: #cbd5e1; }
.board-row:nth-child(3) .place { color: var(--ember-lo); }
.board-who { display: flex; align-items: center; gap: .55rem; text-decoration: none; min-width: 0; flex: 1; }
.board-name { display: grid; min-width: 0; }
.board-name .pl-name { color: var(--bright); font-size: .88rem; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-sub { color: var(--dimmer); font-size: .74rem; display: flex; align-items: center; gap: .25rem; }
.board-value { font-size: .82rem; color: var(--text); font-weight: 600; white-space: nowrap; }
.board-value small { color: var(--dimmer); font-weight: 400; margin-left: .25rem; font-size: .68rem; text-transform: uppercase; letter-spacing: .06em; }
.grade { width: 16px; height: 16px; object-fit: contain; vertical-align: -3px; }

/* --------------------------------------------------------------------- avatars */

.avatar {
  width: var(--size, 40px); height: var(--size, 40px); flex: none;
  border-radius: 50%; object-fit: cover;
  background: var(--panel-2); border: 1px solid var(--line);
}
.avatar-blank {
  display: grid; place-items: center;
  background: linear-gradient(160deg,
    hsl(var(--hue, 200) 42% 26%), hsl(calc(var(--hue, 200) + 30) 38% 15%));
  color: #dbe6f5; font-weight: 700;
  font-size: calc(var(--size, 40px) * .42);
}

.pl { text-decoration: none; display: inline-flex; align-items: center; gap: .4rem; }
.pl-name { color: var(--bright); font-weight: 500; }
.pl:hover .pl-name { color: var(--accent); }
.pl-staff .pl-name { color: var(--warn); }

/* ------------------------------------------------------------------ the feed */

.feed-h { font-size: .95rem; margin: 0 0 .9rem; display: flex; align-items: baseline; gap: .5rem; }
.feed-h small { color: var(--dimmer); font-weight: 400; font-size: .8rem; }
.feed-wide { margin-top: 1.2rem; }

.composer { display: flex; gap: .7rem; background: color-mix(in srgb, var(--panel) 82%, transparent); border-top: 1px solid var(--line); padding: .9rem; margin-bottom: 1rem; }
.composer-in { flex: 1; display: grid; gap: .5rem; }
.composer-foot { display: flex; align-items: center; justify-content: space-between; font-size: .78rem; }

/* Matched by what a control is not, rather than by an explicit type. `<input name="name">` is a
   text box with no type attribute at all, so an input[type=text] rule does not reach it and it
   keeps the browser's white default -- a glaring white box in the middle of a dark form. */
textarea,
input:not([type=checkbox]):not([type=radio]):not([type=submit]) {
  background: var(--panel-2); border: 1px solid var(--line); color: var(--text);
  font: inherit; padding: .55rem .7rem; border-radius: 3px; width: 100%;
}
textarea { resize: vertical; min-height: 3.4rem; }
textarea:focus, input:focus { border-color: var(--accent-lo); outline: none; }
textarea::placeholder, input::placeholder { color: var(--dimmer); }

/* The file button inside a file input is drawn by the browser and is white by default too. */
input[type=file] { padding: .4rem; cursor: pointer; }
input[type=file]::file-selector-button {
  background: var(--line); border: 1px solid var(--line); color: var(--text);
  font: inherit; font-size: .82rem; padding: .35rem .8rem; margin-right: .7rem;
  border-radius: 3px; cursor: pointer;
}
input[type=file]::file-selector-button:hover { border-color: var(--accent-lo); color: var(--bright); }

/* Chrome paints autofilled fields with its own near-white background. The inset shadow is the
   only way to override it -- background-color on an autofilled input is ignored. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text);
  -webkit-box-shadow: 0 0 0 40rem var(--panel-2) inset;
  caret-color: var(--text);
}

/* The dark form controls the browser draws itself: checkboxes, the search field's clear button,
   and the scrollbar inside a textarea. */
:root { color-scheme: dark; }
input[type=checkbox] { accent-color: var(--accent); width: 1rem; height: 1rem; }

.signed-out { background: color-mix(in srgb, var(--panel) 82%, transparent); border-top: 1px solid var(--line); padding: 1rem; margin-bottom: 1rem; color: var(--dim); font-size: .9rem; }

.comments { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; }
.comment { display: flex; gap: .7rem; background: color-mix(in srgb, var(--panel) 82%, transparent); border-top: 1px solid var(--line); padding: .85rem .9rem; }
.comment-av { flex: none; }
.comment-in { min-width: 0; flex: 1; }
.comment-head { display: flex; align-items: baseline; gap: .5rem; font-size: .8rem; flex-wrap: wrap; }
.comment-body { margin-top: .3rem; white-space: pre-wrap; overflow-wrap: anywhere; }

/* A YouTube player in a comment. Capped in width rather than filling the column: a video is
   something somebody is showing you, not the comment itself. */
.embed {
  margin-top: .6rem; max-width: 30rem; aspect-ratio: 16 / 9;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px; overflow: hidden;
}
.embed iframe { width: 100%; height: 100%; border: 0; display: block; }

/* The Embed control in the composer. A <details> element, so it is a small button when it is
   closed and a field when it is open, without a line of JavaScript. */
.embed-add { font-size: .82rem; }
.embed-add summary {
  display: inline-flex; align-items: center; gap: .35rem; cursor: pointer;
  color: var(--dim); border: 1px solid var(--line); border-radius: 3px;
  padding: .25rem .6rem; width: fit-content; list-style: none;
}
.embed-add summary::-webkit-details-marker { display: none; }
.embed-add summary::before { content: "▸"; font-size: .7em; }
.embed-add[open] summary::before { content: "▾"; }
.embed-add summary:hover { border-color: var(--accent-lo); color: var(--bright); }
.embed-add[open] summary { color: var(--bright); }
.embed-add input { margin-top: .5rem; }
.lvl { color: var(--dimmer); font-size: .74rem; border: 1px solid var(--line); padding: 0 .3rem; border-radius: 2px; }

/* ------------------------------------------------------------- profile header */

.phead { position: relative; isolation: isolate; padding: 2rem 0 0; border-bottom: 1px solid var(--line-soft); overflow: hidden; }
.phead-art {
  position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(40rem 20rem at 15% -6rem, rgba(0,165,249,.16), transparent 64%),
    radial-gradient(24rem 14rem at 88% 10%, rgba(255,138,61,.10), transparent 66%);
}
.phead-in { display: flex; align-items: flex-start; gap: 1.4rem; flex-wrap: wrap; }
.phead-id { display: flex; gap: 1.1rem; align-items: center; min-width: 0; }
.phead-id .avatar { border: 2px solid var(--line); box-shadow: 0 8px 30px -12px rgba(0,0,0,.9); }
.phead-name h1 { font-size: clamp(1.5rem, 3.6vw, 2.1rem); letter-spacing: -.02em; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.phead-clan {
  color: var(--text); font-size: .9rem; display: inline-flex; align-items: center; gap: .45rem;
  margin-top: .25rem; text-decoration: none; font-weight: 500;
}
a.phead-clan:hover { color: var(--accent); }

/* Clan marks. The size is passed in as --mark so the same markup works at 24px beside a name
   and larger on a clan's own page. */
.mark {
  width: var(--mark, 26px); height: var(--mark, 26px); flex: none; object-fit: contain;
  image-rendering: auto;
}
.mark-code {
  display: grid; place-items: center;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 3px;
  color: var(--dimmer); font-size: calc(var(--mark, 26px) * .3); letter-spacing: -.02em;
}

/* A generic mark: three cells of the client's sprite sheets stacked in place. Each layer is the
   whole sheet, scaled and offset so one cell shows -- the size and position come from the code,
   so they are inline. */
.mark-atlas { position: relative; display: block; overflow: hidden; }
.mark-atlas i {
  position: absolute; inset: 0; display: block;
  background-repeat: no-repeat;
  image-rendering: -webkit-optimize-contrast;
}
/* The size on a mark is inline, because a sprite-sheet offset has to be computed from it. So the
   big form is the caller passing a bigger number, not a class overriding one -- this only gives
   it room. */
.mark-big { display: block; flex: none; }
.phead-bio { color: var(--dim); font-size: .88rem; margin-top: .35rem; max-width: 40rem; }
.nametag { display: block; margin-top: .4rem; max-height: 22px; width: auto; }

.tag { font-size: .62rem; letter-spacing: .12em; padding: .18rem .4rem; border-radius: 2px; font-weight: 700; vertical-align: middle; }
.tag-staff { background: var(--warn); color: #1c1405; }
.tag-prem { background: var(--ember); color: #1c0e05; }
.tag-live { background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--accent); border: 1px solid var(--accent-lo); }

.phead-num { margin-left: auto; display: flex; gap: 1.4rem; font-size: .82rem; color: var(--dim); }
.phead-num b { color: var(--bright); font-size: 1.05rem; font-weight: 600; display: block; }

.xp { display: flex; align-items: center; gap: .8rem; padding: 1.2rem 0 1rem; flex-wrap: wrap; }
.xp-badge { flex: none; width: 34px; height: 34px; display: grid; place-items: center; }
.xp-badge img { width: 34px; height: 34px; object-fit: contain; }
.xp-badge b { color: var(--accent); font-size: 1rem; }
.xp-bar { flex: 1; min-width: 12rem; height: 7px; background: var(--panel-2); border: 1px solid var(--line); border-radius: 4px; overflow: hidden; }
.xp-fill { display: block; height: 100%; background: linear-gradient(90deg, var(--accent-lo), #35c2ff); }
.xp-text { font-size: .84rem; color: var(--text); white-space: nowrap; }
.xp-text small { color: var(--dimmer); margin-left: .35rem; }
.xp-record { font-size: .82rem; color: var(--dim); white-space: nowrap; display: flex; gap: .45rem; align-items: baseline; }
.xp-record b { color: var(--bright); }
.win { color: var(--win); }
.loss { color: var(--loss); }

/* ----------------------------------------------------------------------- tabs */

.tabs { display: flex; gap: .3rem; border-bottom: 1px solid var(--line-soft); margin-bottom: 1.2rem; overflow-x: auto; }
.tabs a {
  color: var(--dim); text-decoration: none; font-size: .8rem; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; padding: .85rem .9rem; white-space: nowrap;
}
.tabs a:hover { color: var(--bright); }
.tabs a.on { color: var(--bright); box-shadow: inset 0 -2px 0 var(--accent); }
.tabs small { color: var(--dimmer); font-weight: 400; letter-spacing: 0; }

/* ----------------------------------------------------------------- characters */

.chars { display: grid; grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); gap: 1.1rem; padding-bottom: 3rem; }
.char { margin: 0; }
.char-on { border-top-color: var(--accent-lo); }
.char-h { display: flex; align-items: center; gap: .5rem; padding: .8rem 1rem; border-bottom: 1px solid var(--line-soft); }
.char-slot { font-size: .74rem; letter-spacing: .16em; text-transform: uppercase; color: var(--bright); font-weight: 600; }
.char-h .dim { margin-left: auto; font-size: .78rem; }

.slots { list-style: none; margin: 0; padding: .8rem; display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; }
.slots-weap { grid-template-columns: repeat(4, 1fr); border-top: 1px solid var(--line-soft); }
/* Icon beside the name, not above it. Centred over the tile the artwork floated in a field of
   empty box; alongside, the row is as tall as the icon and the whole set reads as a list of
   things somebody is wearing. */
.slot {
  background: var(--panel-2); border: 1px solid var(--line-soft); border-radius: 3px;
  padding: .6rem .75rem; display: flex; align-items: center; gap: .85rem; min-width: 0;
}
.slot-text { display: grid; min-width: 0; }
.slot-label { font-size: .6rem; letter-spacing: .1em; text-transform: uppercase; color: var(--dimmer); }
.slot-name { font-size: .8rem; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.slot-icon { width: 38px; height: 38px; flex: none; object-fit: contain; }
.slot-icon-none { border: 1px dashed var(--line); border-radius: 3px; opacity: .5; }
.slot-empty { opacity: .45; }
.slot-ench { font-size: .68rem; color: var(--warn); margin-left: auto; }
.slots-weap .slot-name { font-size: .76rem; }

/* -------------------------------------------------------------- match history */

.matches { list-style: none; margin: 0; padding: 0; }
.match {
  display: grid;
  grid-template-columns: minmax(9rem, 1.6fr) 7rem 5rem 6rem 6.5rem 4.5rem 5.5rem;
  align-items: center; gap: .6rem;
  padding: .5rem .9rem; border-bottom: 1px solid var(--line-soft); font-size: .84rem;
  border-left: 3px solid transparent;
}
.match:last-child { border-bottom: 0; }
.match.won { border-left-color: color-mix(in srgb, var(--win) 60%, transparent); }
.match.lost { border-left-color: color-mix(in srgb, var(--loss) 55%, transparent); }
.match:hover { background: var(--panel-2); }
.m-map { display: flex; align-items: center; gap: .55rem; min-width: 0; color: var(--bright); }
.m-map img, .m-map-blank { width: 42px; height: 26px; object-fit: cover; border-radius: 2px; flex: none; background: var(--panel-2); border: 1px solid var(--line); }
.m-map span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-mode { color: var(--accent); }
.m-time, .m-kda, .m-exp { color: var(--dim); }
.m-kda i, .m-score i { color: var(--dimmer); font-style: normal; margin: 0 .15rem; }
.m-score { font-variant-numeric: tabular-nums; }
.m-score .alpha { color: #e05a63; }
.m-score .beta { color: #4aa3e0; }
.m-exp { color: var(--win); }
.m-res { font-size: .72rem; font-weight: 700; letter-spacing: .1em; text-align: right; }
.won .m-res { color: var(--win); }
.lost .m-res { color: var(--loss); }
@media (max-width: 54rem) {
  .match { grid-template-columns: 1fr auto; grid-auto-rows: auto; row-gap: .2rem; }
  .m-time, .m-kda, .m-exp { display: none; }
}

.pager { display: flex; align-items: center; justify-content: center; gap: 1.2rem; padding: 1rem; font-size: .84rem; }

/* --------------------------------------------------------------- player list */

.plist { list-style: none; margin: 0; padding: 0; }
.plist li { border-bottom: 1px solid var(--line-soft); }
.plist li:last-child { border-bottom: 0; }
.plist a { display: flex; align-items: center; gap: .7rem; padding: .6rem .9rem; text-decoration: none; }
.plist a:hover { background: var(--panel-2); }
.plist-lvl { margin-left: auto; color: var(--dim); font-size: .82rem; display: flex; align-items: center; gap: .4rem; }
/* Bigger here than in the leaderboards. A rank badge is the thing being read in a member list,
   and at 16px the seven tiers are not tellable apart. */
.plist-lvl .grade { width: 26px; height: 26px; }
.plist-exp { color: var(--dimmer); font-size: .8rem; width: 9rem; text-align: right; }
.plist-rank { color: var(--dim); font-size: .74rem; letter-spacing: .08em; text-transform: uppercase; }

/* Clan members read left to right in one group: who they are, what level, what they do in the
   clan. Nothing is pinned to the right margin, so the eye never has to cross the row -- but the
   three do need air between them, or they read as one run-on label. */
.plist-clan a { gap: 1.1rem; }
.plist-clan .plist-lvl { margin-left: .4rem; }
.plist-clan .plist-rank { margin-left: .4rem; }

/* The clan page is two columns for the same reason the front page is: a member list on its own
   left a band of empty page beside it, and narrowing the box only moved the emptiness. The fix
   was to put something in it -- who runs the clan, and what its members have been playing. */
.cols-clan { grid-template-columns: 1fr 19rem; padding-top: 1.4rem; }
@media (max-width: 60rem) { .cols-clan { grid-template-columns: 1fr; } }
.panel-members { margin-top: 0; }

.clan-main { min-width: 0; }
.feed-clan { margin-top: 1.4rem; }

/* Members as tiles rather than rows. Under a rank heading the rank no longer has to be printed
   on every line, which leaves room for the face and the name to be the whole tile. */
.member-grid {
  list-style: none; margin: 0; padding: .6rem;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); gap: .3rem;
}
.member-grid a {
  display: flex; align-items: center; gap: .6rem;
  padding: .45rem .55rem; text-decoration: none; border-radius: 3px; min-width: 0;
}
.member-grid a:hover { background: var(--panel-2); }
.member-who { display: grid; min-width: 0; }
.member-who .pl-name { font-size: .9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.member-lvl { color: var(--dimmer); font-size: .76rem; display: flex; align-items: center; gap: .3rem; }
.member-lvl .grade { width: 20px; height: 20px; }

.panel-h.rank-master { color: var(--warn); }
.panel-h.rank-staff { color: var(--accent); }

.panel-text { padding: .9rem 1.1rem; color: var(--text); font-size: .88rem; white-space: pre-wrap; overflow-wrap: anywhere; }

.facts { margin: 0; padding: .8rem 1.1rem; display: grid; grid-template-columns: auto 1fr; gap: .35rem .9rem; font-size: .86rem; }
.facts dt { color: var(--dimmer); font-size: .74rem; letter-spacing: .06em; text-transform: uppercase; align-self: center; }
.facts dd { margin: 0; color: var(--text); }

.clan-matches { list-style: none; margin: 0; padding: .3rem; display: grid; gap: .1rem; }
.clan-matches li {
  display: grid; grid-template-columns: 1fr auto; gap: 0 .5rem; align-items: baseline;
  padding: .4rem .5rem; border-left: 2px solid transparent; font-size: .82rem;
}
.clan-matches li.won { border-left-color: color-mix(in srgb, var(--win) 60%, transparent); }
.clan-matches li.lost { border-left-color: color-mix(in srgb, var(--loss) 55%, transparent); }
.clan-matches li:hover { background: var(--panel-2); }
.cm-map { grid-column: 1; color: var(--dim); font-size: .78rem; }
.cm-mode { grid-column: 1; color: var(--accent); font-size: .74rem; }
.cm-res { grid-row: 1 / span 3; grid-column: 2; font-weight: 700; align-self: center; }
.won .cm-res { color: var(--win); }
.lost .cm-res { color: var(--loss); }
.rank-master { color: var(--warn); font-weight: 600; }
.rank-staff { color: var(--accent); }

.clist { list-style: none; margin: 0; padding: 0; }
.clist li { border-bottom: 1px solid var(--line-soft); }
.clist li:last-child { border-bottom: 0; }
.clist a { display: flex; align-items: center; gap: .7rem; padding: .6rem .9rem; text-decoration: none; }
.clist a:hover { background: var(--panel-2); }
.clist-num { color: var(--dim); font-size: .82rem; margin-left: auto; white-space: nowrap; }
.search-wide { display: flex; gap: .6rem; margin-bottom: 1.2rem; }
.search-wide input { width: 100%; max-width: none; }

/* --------------------------------------------------------------------- forms */

.form-panel { padding: 1.4rem; margin-top: 2.4rem; }
.form-panel .page-h { margin-top: 0; }
.form-intro { margin-bottom: 1.2rem; font-size: .9rem; }
.form-panel label { display: grid; gap: .3rem; margin-bottom: 1rem; font-size: .86rem; color: var(--text); }
.form-panel label small { color: var(--dimmer); font-size: .76rem; }
.form-panel label.check { display: flex; align-items: center; gap: .5rem; }
.form-panel label.check input { width: auto; }
.form-foot { margin-top: 1rem; font-size: .86rem; color: var(--dim); }
.settings-av { display: flex; gap: 1.2rem; align-items: flex-start; margin-bottom: 1.4rem; flex-wrap: wrap; }
.settings-av form { display: grid; gap: .5rem; justify-items: start; margin-top: .6rem; }
.settings-av small { color: var(--dimmer); font-size: .76rem; }

/* -------------------------------------------------------------------- footer */

.foot { border-top: 1px solid var(--line-soft); margin-top: 2rem; }
.foot-in { display: flex; justify-content: space-between; gap: 1rem; padding: 1.4rem 0; font-size: .82rem; color: var(--dimmer); flex-wrap: wrap; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}
