/* Prime Tanki Ratings - design system v2.
   Owner review 2026-08-11: single leaderboard + champions podium on home, layered
   living background, medal treatment for the top ranks, big real art on profiles.
   Profile redesign 2026-08-11: the profile is three framed windows holding nested
   trays (frame > well > tray > card), the section tab row is gone, and the six
   overview glyphs are one masked steel family.
   Palette per docs/design/PROMPT-rating-system.md 4.7 (dark bluish grey + dark green),
   WCAG AA floors, max-width 1200 shell, clean at 375px. */

:root {
  --bg:        #141d29;
  --panel:     #1a2532;
  --panel-2:   #223040;
  --line:      #2c3d4f;
  --text:      #e8edf2;
  --text-dim:  #93a4b5;
  --accent:    #2e7d4f;
  --accent-hi: #43a06b;
  --gold:      #d4a63f;
  --silver:    #b9c6d4;
  --bronze:    #c9925e;

  /* battle-mode quartet (borders, icons and glows only; body text stays AA) */
  --mode-dm:  #d08a3e;
  --mode-tdm: #4f8fd0;
  --mode-ctf: #c25e5e;
  --mode-jgr: #9a6ad0;

  --panel-glass: rgba(39, 56, 73, 0.5);
  --radius: 12px;
  --lift: 0 10px 24px -14px rgba(0, 0, 0, 0.65);
  --sheen: linear-gradient(155deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.015) 40%, transparent 62%);
  --hover-ms: 140ms;
  --font-display: "Exo 2", system-ui, "Segoe UI", Roboto, sans-serif;
  --font-body: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* Profile window framing: a lit outer edge, a dark ring painted under it, a
     recessed well inside, and trays raised one step back off that well. */
  --frame-edge:    #3a4f66;
  --frame-ring:    rgba(10, 16, 25, 0.65);
  --frame-lit:     rgba(255, 255, 255, 0.075);
  --tray-edge:     #2b3b4d;
  --tray-lit:      rgba(255, 255, 255, 0.05);
  --card-edge:     #33465b;
  --card-edge-hi:  #445c76;
  /* The single tint every overview glyph is masked to, and the steel used on the
     panel header strip (the lightest surface on the page, where dim text fails). */
  --stat-ink:      var(--text-dim);
  --stat-ink-hi:   #cfdcea;
  --note-ink:      #aebecd;
  /* The modification tier on garage cards: neon green, owner call 2026-08-14. */
  --mod-ink:       #76ff33;

  /* HUD geometry: the diagonal corner cut, and the accent rail that runs along
     the top of a panel and down the leading edge of a mode card. */
  --notch:      16px;
  --notch-sm:   10px;
  --rail:       rgba(67, 160, 107, 0.55);
}

@font-face {
  font-family: "Exo 2";
  src: url("../fonts/Exo2.ttf") format("truetype");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ---------- base ---------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* The texture layer below is absolute rather than fixed so it travels with the
     page; it needs body as its containing block to span the whole document. */
  position: relative;
  isolation: isolate;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  /* The living background, bottom to top: the battlefield art, a heavy scrim to
     hold it back, then the green aurora and cool depth over the base.

     The battlefield art is NOT here - it lives on .bg-art below, so it can be
     masked to transparent instead of faded to a colour that would seam. */
  background-color: var(--bg);
  background-image:
    radial-gradient(1200px 460px at 50% -140px, rgba(67, 160, 107, 0.10), transparent 65%),
    radial-gradient(900px 640px at 88% 12%, rgba(46, 125, 79, 0.05), transparent 60%),
    radial-gradient(1100px 800px at 6% 92%, rgba(38, 64, 99, 0.22), transparent 62%),
    linear-gradient(180deg, #17212f 0%, #141d29 34%, #111926 100%);
  background-attachment: fixed;
  background-repeat: no-repeat;
}

/* The battlefield art: pinned to the top of the document at its natural 16:9
   proportions, scrolling with the page like the steel above it, and masked so its
   lower half dissolves to nothing. Because it fades to transparent rather than to
   a colour, whatever is behind it simply becomes more visible - there is no edge
   to match and no seam at any width or scroll position.
   Strength is `opacity` now, which is the one number to tune. */
.bg-art {
  position: absolute;
  z-index: -2;
  top: 0;
  left: 0;
  right: 0;
  height: 58vw;
  pointer-events: none;
  opacity: 0.12;
  background: url("../img/battle-bg.jpg") top center / 100% auto no-repeat;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 42%, transparent 96%);
  mask-image: linear-gradient(180deg, #000 0%, #000 42%, transparent 96%);
}

/* Soft vignette, fixed to the viewport. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(130% 95% at 50% 32%, transparent 55%, rgba(7, 11, 17, 0.5) 100%);
}

/* Scratched steel plate (owner-supplied 2026-08-14) under the film grain, both
   on one layer behind the content, blended rather than painted so the scratches
   catch the light without lifting the page off its dark base.

   Absolute, so it travels with the page - and the battlefield art below it now
   scrolls too, so the two backdrop layers move as one surface rather than one
   sliding across the other (owner call 2026-08-17). */
body::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.028;
  mix-blend-mode: overlay;
  background-image:
    url("../img/background.jpg"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: cover, 180px 180px;
  background-position: center, top left;
  background-repeat: no-repeat, repeat;
}

h1, h2, h3, h4 { margin: 0; font-family: var(--font-display); }
p { margin: 0; }
ol, ul { margin: 0; padding: 0; list-style: none; }
img { max-width: 100%; }

a { color: var(--text); text-decoration: none; }

a, button, input {
  transition: color var(--hover-ms) ease-out, background-color var(--hover-ms) ease-out,
              border-color var(--hover-ms) ease-out, box-shadow var(--hover-ms) ease-out,
              opacity var(--hover-ms) ease-out, transform var(--hover-ms) ease-out;
}

:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 2px; }

::selection { background: var(--accent); color: #fff; }

.shell {
  width: 100%;
  max-width: 1200px;
  margin-inline: auto;
  padding-inline: 20px;
}

main.shell { flex: 1; padding-block: 28px 56px; }

.dim { color: var(--text-dim); }
.quiet { color: var(--text-dim); padding: 24px 0; }

.vh {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* The shared card recipe: glassy panel, top light edge, hover sheen + gentle raise. */
.card-lit {
  position: relative;
  background: linear-gradient(180deg, var(--panel-glass), rgba(26, 37, 50, 0.85));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04), 0 8px 22px -18px rgba(0, 0, 0, 0.6);
}
.card-lit::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--sheen);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--hover-ms) ease-out;
}
.card-lit:hover {
  transform: translateY(-2px);
  border-color: #3a5068;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), var(--lift);
}
.card-lit:hover::after { opacity: 1; }

/* ---------- header / footer ---------- */

.site-head {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(20, 29, 41, 0.88);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(44, 61, 79, 0.8);
  box-shadow: 0 8px 24px -18px rgba(0, 0, 0, 0.7);
}

.head-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: 58px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font-display);
  letter-spacing: 0.06em;
  white-space: nowrap;
}

.brand-mark {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  background: linear-gradient(145deg, var(--accent-hi), var(--accent));
  box-shadow: 0 0 10px rgba(67, 160, 107, 0.55);
}

.brand-name { font-weight: 700; font-size: 17px; color: var(--text); }
.brand-sub  { font-weight: 500; font-size: 12px; color: var(--accent-hi); letter-spacing: 0.22em; }

.search { flex: 0 1 260px; }

.search-input {
  width: 100%;
  padding: 7px 14px;
  background: rgba(26, 37, 50, 0.85);
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--text);
  font: inherit;
  font-size: 14px;
}
.search-input::placeholder { color: var(--text-dim); }
.search-input:hover { border-color: #3a5068; background: var(--panel-2); }
.search-input:focus {
  border-color: var(--accent);
  outline: none;
  box-shadow: 0 0 0 3px rgba(46, 125, 79, 0.25);
}

.site-foot {
  border-top: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(17, 25, 38, 0), rgba(11, 17, 26, 0.55));
  padding: 22px 0;
  font-size: 13px;
}
.foot-inner { display: flex; align-items: baseline; gap: 10px; }
.foot-brand { font-family: var(--font-display); font-weight: 600; letter-spacing: 0.05em; }
.foot-dim { color: var(--text-dim); }

/* ---------- favourites: the Save star + header bookmarks menu ---------- */

/* Everything here is injected by favourites.js, so none of it exists without
   JavaScript - there is no dead control to style around. */

.fav-ic { width: 16px; height: 16px; fill: currentColor; display: block; }
.fav-ic-lg { width: 22px; height: 22px; }

/* The star sits at the far end of the profile's own header strip. Icon only, and
   a FIXED box - a button that changes size on click drags its neighbours with
   it (owner call 2026-08-17). */
.fav-star {
  margin-left: auto;
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 38px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 0;
  clip-path: polygon(var(--notch-sm) 0, 100% 0, 100% calc(100% - var(--notch-sm)),
                     calc(100% - var(--notch-sm)) 100%, 0 100%, 0 var(--notch-sm));
  background: rgba(10, 16, 25, 0.4);
  color: var(--note-ink);
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}
.fav-star:hover { color: var(--text); border-color: #3a5068; }
.fav-star.is-saved { color: var(--gold); border-color: rgba(212, 166, 63, 0.5); }
.fav-star.is-saved .fav-ic { filter: drop-shadow(0 0 6px rgba(212, 166, 63, 0.45)); }

/* The header menu. */
.fav-menu { position: relative; flex: none; }

.fav-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 11px;
  border: 1px solid var(--line);
  border-radius: 0;
  background: rgba(26, 37, 50, 0.8);
  color: var(--text-dim);
  cursor: pointer;
}
.fav-toggle:hover { color: var(--text); border-color: #3a5068; }
/* Reserved width, always in the layout: visibility rather than display, so a
   count appearing cannot nudge the search box. */
.fav-count {
  width: 13px;
  text-align: center;
  font-family: var(--font-display);
  font-size: 11.5px;
  font-weight: 700;
  color: var(--gold);
}
.fav-count.is-empty { visibility: hidden; }

.fav-panel {
  position: absolute;
  z-index: 30;
  top: calc(100% + 8px);
  right: 0;
  width: min(280px, 78vw);
  padding: 12px 13px 13px;
  border: 1px solid var(--frame-edge);
  background: linear-gradient(180deg, #1e2c3b, #16212e);
  box-shadow: 0 26px 50px -28px rgba(0, 0, 0, 0.95);
  clip-path: polygon(var(--notch-sm) 0, 100% 0, 100% calc(100% - var(--notch-sm)),
                     calc(100% - var(--notch-sm)) 100%, 0 100%, 0 var(--notch-sm));
}
.fav-panel-head {
  margin-bottom: 9px;
  color: var(--note-ink);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.fav-empty { color: var(--text-dim); font-size: 12.5px; line-height: 1.45; }

.fav-list { display: flex; flex-direction: column; gap: 2px; max-height: 46vh; overflow-y: auto; }
.fav-row { display: flex; align-items: center; gap: 6px; }
.fav-link {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 8px;
  font-size: 13.5px;
}
.fav-link:hover { background: rgba(67, 160, 107, 0.12); color: var(--accent-hi); }
.fav-badge { flex: none; }
.fav-nick { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.fav-remove {
  flex: none;
  width: 24px;
  height: 24px;
  border: 0;
  background: none;
  color: var(--text-dim);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
}
.fav-remove:hover { color: var(--mode-ctf); }

/* ---------- flat-tinted icons ---------- */

.icon-flat {
  --m: none;
  display: inline-block;
  flex: none;
  width: 20px;
  height: 20px;
  background: currentColor;
  -webkit-mask: var(--m) center / contain no-repeat;
  mask: var(--m) center / contain no-repeat;
}
.icon-xs { width: 14px; height: 14px; }

.i-crystal { --m: url("../icons/stats/crystal.png"); }
.i-goldbox { --m: url("../icons/stats/goldbox.png"); }
.i-xp      { --m: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 1.8l3 6.5 7.2.9-5.3 4.9 1.4 7.1L12 17.6l-6.3 3.6 1.4-7.1L1.8 9.2 9 8.3z'/%3E%3C/svg%3E"); }

.i-dm  { --m: url("../icons/modes/dm.png"); }
.i-tdm { --m: url("../icons/modes/tdm.png"); }
.i-ctf { --m: url("../icons/modes/ctf.png"); }
.i-cp  { --m: url("../icons/modes/cp.png"); }

/* The `pixelated` that used to live here was written for icons/ranks/ - genuine
   13x13 pixel art shown at 2x. The markup now loads ranks_hq/ instead, which is
   106x103 artwork being scaled DOWN to 26px: nearest-neighbour throws away three
   pixels in four and shreds the badge. Smooth downscaling is what this art
   wants (fixed 2026-08-17). */
.row-badge img, .step-medal img { image-rendering: auto; }

/* ---------- home: category + window controls ---------- */

.lb-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 18px;
}

/* HUD pass 2026-08-14: the home page takes the profile's geometry - notched
   plates, square controls, an accent rail along each head. */
.seg {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 4px;
  background: rgba(26, 37, 50, 0.8);
  border: 1px solid var(--line);
  border-radius: 0;
  clip-path: polygon(var(--notch-sm) 0, 100% 0, 100% calc(100% - var(--notch-sm)),
                     calc(100% - var(--notch-sm)) 100%, 0 100%, 0 var(--notch-sm));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);
}

.seg-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 15px;
  border-radius: 0;
  color: var(--text-dim);
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.03em;
  white-space: nowrap;
}
.seg-btn:hover { color: var(--text); background: var(--panel-2); }
.seg-btn.is-active {
  color: #fff;
  background: linear-gradient(180deg, #38915a, var(--accent));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 3px 12px -4px rgba(46, 125, 79, 0.6);
}

/* ---------- home: the leaderboard ---------- */

.board {
  position: relative;
  background: linear-gradient(180deg, var(--panel-glass), rgba(26, 37, 50, 0.9));
  border-radius: 0;
  clip-path: polygon(var(--notch) 0, 100% 0, 100% calc(100% - var(--notch)),
                     calc(100% - var(--notch)) 100%, 0 100%, 0 var(--notch));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04), 0 18px 40px -28px rgba(0, 0, 0, 0.8);
  overflow: hidden;
  margin-bottom: 34px;
}
.board.is-loading { opacity: 0.55; pointer-events: none; }

.board-head {
  position: relative;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 13px 18px 12px;
  border-bottom: 1px solid rgba(9, 15, 23, 0.7);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);
  background: linear-gradient(180deg, rgba(60, 82, 105, 0.5), rgba(31, 44, 60, 0.12));
}
/* The same power line that crosses the top of every profile panel. */
.board-head::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, var(--accent-hi), var(--rail) 22%, transparent 70%);
}

.board-ic { width: 22px; height: 22px; color: var(--accent-hi); }

.board-title {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.lead-tag {
  padding: 3px 10px;
  border-radius: 999px;
  background: rgba(67, 160, 107, 0.14);
  border: 1px solid rgba(67, 160, 107, 0.35);
  color: var(--accent-hi);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
}

.countdown {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  padding: 5px 13px;
  border-radius: 999px;
  background: rgba(20, 29, 41, 0.7);
  border: 1px solid var(--line);
  color: var(--text-dim);
  font-family: var(--font-display);
  font-size: 13px;
  letter-spacing: 0.02em;
}
.countdown::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent-hi);
  box-shadow: 0 0 8px rgba(67, 160, 107, 0.8);
  animation: cd-pulse 2.2s ease-in-out infinite;
}
@keyframes cd-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

.board-rows { display: block; }

.row {
  position: relative;
  display: grid;
  grid-template-columns: 2.4rem 26px minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 9px 18px;
  border-top: 1px solid rgba(34, 48, 64, 0.7);
  transition: background-color var(--hover-ms) ease-out, box-shadow var(--hover-ms) ease-out;
}
.row:first-child { border-top: 0; }
.row:hover {
  background: linear-gradient(90deg, rgba(67, 160, 107, 0.07), rgba(34, 48, 64, 0.55) 40%, rgba(34, 48, 64, 0.3));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);
}

.pos {
  font-family: var(--font-display);
  font-size: 13px;
  color: var(--text-dim);
  text-align: center;
}

.row-badge { display: grid; place-items: center; }

.nick {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 14px;
}
.nick:hover { color: var(--accent-hi); }

.val {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  text-align: right;
}

/* Medals: positions 1-3 get real metal. */
.medal {
  display: inline-grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 800;
  color: #141d29;
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.5), 0 2px 6px -2px rgba(0, 0, 0, 0.7);
}
.top-1 .medal { background: radial-gradient(circle at 32% 28%, #f5dd94, var(--gold) 58%, #8a6a20); }
.top-2 .medal { background: radial-gradient(circle at 32% 28%, #eef4fa, var(--silver) 58%, #77899b); }
.top-3 .medal { background: radial-gradient(circle at 32% 28%, #e8bd97, var(--bronze) 58%, #7d5433); }

/* The top three are rows like the rest, but bigger and lit (owner call
   2026-08-19, replacing the podium): more height, a metal rail down the leading
   edge, a wash across the row and the same glow the podium plinths carried. */
/* The match-up art sits behind the top three as ONE image spanning all of them
   (owner call 2026-08-19), not tiled per row - it is a scene, and repeating it
   three times would read as wallpaper. It lives on the list itself rather than
   on a row, so nothing in the markup or in boards.js has to change, and it is
   masked away to the right before it can reach the score column.

   Its height is the three tiers added up (74 + 62 + 52), so the art ends exactly
   where the ordinary rows begin. */
.board-rows { position: relative; }
.board-rows::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 0;
  height: 188px;
  background: url("../img/podium-banner.png") center top / auto 188px no-repeat;
  opacity: 0.12;
  pointer-events: none;
  /* Centred (owner call 2026-08-19), so it fades out on BOTH sides - it has to
     clear the rank column on the left as well as the scores on the right. */
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 22%, #000 78%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0%, #000 22%, #000 78%, transparent 100%);
}
/* The rows themselves sit above it. */
.board-rows .row { z-index: 1; }

/* Four steps down, not one (owner call 2026-08-19): gold is the biggest, silver
   a step under it, bronze a step under that, and the ordinary rows continue the
   descent. The badge column is fixed at 26px on a normal row, so each tier
   widens it to fit its own rank art. */
.row.top-1, .row.top-2, .row.top-3 {
  --metal: var(--silver);
  border-top-color: transparent;
}
.row.top-1 {
  --metal: var(--gold);
  padding-block: 18px;
  grid-template-columns: 2.7rem 38px minmax(0, 1fr) auto;
}
.row.top-2 {
  padding-block: 14px;
  grid-template-columns: 2.6rem 33px minmax(0, 1fr) auto;
}
.row.top-3 {
  --metal: var(--bronze);
  padding-block: 11px;
  grid-template-columns: 2.5rem 29px minmax(0, 1fr) auto;
}

.top-1 {
  background: linear-gradient(90deg, rgba(212, 166, 63, 0.16), rgba(212, 166, 63, 0.04) 45%, transparent);
  box-shadow: inset 4px 0 0 var(--gold), 0 0 28px -6px rgba(212, 166, 63, 0.36);
}
.top-2 {
  background: linear-gradient(90deg, rgba(185, 198, 212, 0.13), rgba(185, 198, 212, 0.03) 45%, transparent);
  box-shadow: inset 3px 0 0 var(--silver), 0 0 20px -9px rgba(185, 198, 212, 0.22);
}
.top-3 {
  background: linear-gradient(90deg, rgba(201, 146, 94, 0.13), rgba(201, 146, 94, 0.03) 45%, transparent);
  box-shadow: inset 2px 0 0 var(--bronze), 0 0 16px -10px rgba(201, 146, 94, 0.18);
}

/* Everything inside a row scales with its tier. */
.top-1 .row-badge img { width: 38px; height: 38px; }
.top-2 .row-badge img { width: 33px; height: 33px; }
.top-3 .row-badge img { width: 29px; height: 29px; }

/* Premium account. The gold plaque carries a frame the bare insignia does not, so
   it renders a step larger to read as the same badge - the swap the game makes
   (reference client UserTitle.as: PREMIUM_RANK_ICON_SIZE > RANK_ICON_SIZE). */
.row-badge.is-premium img { width: 30px; height: 30px; max-width: none; }
.top-1 .row-badge.is-premium img { width: 42px; height: 42px; }
.top-2 .row-badge.is-premium img { width: 37px; height: 37px; }
.top-3 .row-badge.is-premium img { width: 33px; height: 33px; }
.fav-badge.is-premium { width: 23px; height: 23px; }

.top-1 .val, .top-2 .val, .top-3 .val { font-weight: 700; color: var(--metal); }
.top-1 .val { font-size: 18px; }
.top-2 .val { font-size: 16.5px; }
.top-3 .val { font-size: 15px; }

.top-1 .medal { width: 32px; height: 32px; font-size: 15px; }
.top-2 .medal { width: 29px; height: 29px; font-size: 13.5px; }
.top-3 .medal { width: 27px; height: 27px; font-size: 12.5px; }

.top-1 .nick, .top-2 .nick, .top-3 .nick {
  font-family: var(--font-display);
  font-weight: 700;
}
.top-1 .nick { font-size: 20px; }
.top-2 .nick { font-size: 17.5px; }
.top-3 .nick { font-size: 15.5px; }
.top-1:hover, .top-2:hover, .top-3:hover {
  background-color: rgba(34, 48, 64, 0.45);
}

/* Positions 4-10: a quieter distinction. */
.notable .pos { color: var(--accent-hi); font-weight: 700; }
.notable .nick { font-family: var(--font-display); font-weight: 600; color: #dfe9f2; }

.row-empty {
  padding: 34px 18px;
  text-align: center;
  color: var(--text-dim);
  font-size: 13px;
}

.board-more {
  display: block;
  width: calc(100% - 28px);
  margin: 12px 14px 14px;
  padding: 9px 12px;
  background: rgba(34, 48, 64, 0.35);
  border: 1px solid var(--line);
  border-radius: 0;
  clip-path: polygon(var(--notch-sm) 0, 100% 0, 100% calc(100% - var(--notch-sm)),
                     calc(100% - var(--notch-sm)) 100%, 0 100%, 0 var(--notch-sm));
  color: var(--text-dim);
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.board-more:hover {
  background: var(--panel-2);
  border-color: #3a5068;
  color: var(--text);
  box-shadow: 0 6px 16px -12px rgba(0, 0, 0, 0.8);
}
.board-more:disabled { opacity: 0.55; cursor: default; }
.more-count { color: var(--text-dim); font-weight: 400; }

/* The leaderboard's own podium: the champions podium at board scale, sitting
   inside the board frame above row 4. Slightly roomier, because this one is the
   headline of the page rather than a summary card. */
/* ---------- home: previous champions (one line per period) ---------- */

.champ-strip {
  margin-bottom: 34px;
  display: flex;
  flex-direction: column;
  gap: 1px;                       /* the hairline between lines IS the gap */
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 0;
  clip-path: polygon(var(--notch-sm) 0, 100% 0, 100% calc(100% - var(--notch-sm)),
                     calc(100% - var(--notch-sm)) 100%, 0 100%, 0 var(--notch-sm));
  overflow: hidden;
}

.champ-line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 22px;
  padding: 12px 18px;
  background: linear-gradient(180deg, var(--panel-glass), rgba(26, 37, 50, 0.9));
}

.champ-when {
  flex: none;
  min-width: 92px;
  color: var(--text-dim);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.champ-wins {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 26px;
  min-width: 0;
}

.champ-win {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}
.champ-win .icon-flat {
  width: 15px;
  height: 15px;
  color: var(--accent-hi);
  align-self: center;
}

.champ-board {
  color: var(--text-dim);
  font-size: 12px;
  letter-spacing: 0.04em;
}

.champ-nick {
  font-family: var(--font-display);
  font-size: 14.5px;
  font-weight: 700;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.champ-nick:hover { color: var(--accent-hi); }

.champ-val {
  color: var(--text-dim);
  font-family: var(--font-display);
  font-size: 13px;
}

@media (max-width: 760px) {
  /* The three boards stack under the period label rather than squeezing. */
  .champ-line { gap: 8px 14px; padding: 12px 14px; }
  .champ-wins { flex-direction: column; align-items: flex-start; gap: 7px; }
}

/* ---------- home: champions podiums ---------- */

.champs { margin-bottom: 34px; }

.champs-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 14px;
}
.champs-head::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, var(--line), transparent);
}

.champs-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.champs-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  align-items: stretch;
}

.podium-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, var(--panel-glass), rgba(26, 37, 50, 0.85));
  border-radius: 0;
  clip-path: polygon(var(--notch-sm) 0, 100% 0, 100% calc(100% - var(--notch-sm)),
                     calc(100% - var(--notch-sm)) 100%, 0 100%, 0 var(--notch-sm));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04), 0 8px 22px -18px rgba(0, 0, 0, 0.6);
  overflow: hidden;
  transition: transform var(--hover-ms) ease-out, box-shadow var(--hover-ms) ease-out;
}
.podium-card:hover {
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), var(--lift);
}

.podium-head {
  position: relative;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 11px 16px 10px;
  color: var(--accent-hi);
  background: linear-gradient(180deg, rgba(60, 82, 105, 0.42), transparent);
}
.podium-head::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, var(--accent-hi), var(--rail) 30%, transparent 80%);
}
.podium-head .icon-flat { width: 17px; height: 17px; }

.podium-title {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text);
}

.podium {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-items: end;
  gap: 8px;
  padding: 6px 14px 14px;
  flex: 1;
}

.step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  min-width: 0;
}
.step-empty { visibility: hidden; }

.step-medal {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--panel-2);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.25), 0 3px 8px -3px rgba(0, 0, 0, 0.7);
}
.step-1 .step-medal {
  background: radial-gradient(circle at 32% 28%, #f5dd94, var(--gold) 62%, #8a6a20);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.5), 0 0 14px rgba(212, 166, 63, 0.35);
}
.step-2 .step-medal { background: radial-gradient(circle at 32% 28%, #eef4fa, var(--silver) 62%, #77899b); }
.step-3 .step-medal { background: radial-gradient(circle at 32% 28%, #e8bd97, var(--bronze) 62%, #7d5433); }

.step-nick {
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 12.5px;
  font-weight: 600;
}
.step-nick:hover { color: var(--accent-hi); }

.step-val {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  color: var(--text-dim);
}

/* Pedestals are cut plates too: the top outer corner is chamfered, so the three
   steps read as machined blocks rather than rounded bars. */
.pedestal {
  width: 100%;
  display: grid;
  place-items: center;
  border-radius: 0;
  clip-path: polygon(var(--notch-sm) 0, 100% 0, 100% 100%, 0 100%, 0 var(--notch-sm));
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 15px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
}
.step-1 .pedestal {
  height: 66px;
  color: #e9c46a;
  background: linear-gradient(180deg, rgba(212, 166, 63, 0.3), rgba(212, 166, 63, 0.05));
  border: 1px solid rgba(212, 166, 63, 0.4);
}
.step-2 .pedestal {
  height: 46px;
  color: var(--silver);
  background: linear-gradient(180deg, rgba(185, 198, 212, 0.22), rgba(185, 198, 212, 0.04));
  border: 1px solid rgba(185, 198, 212, 0.3);
}
.step-3 .pedestal {
  height: 34px;
  color: var(--bronze);
  background: linear-gradient(180deg, rgba(201, 146, 94, 0.22), rgba(201, 146, 94, 0.04));
  border: 1px solid rgba(201, 146, 94, 0.3);
}

/* ==========================================================================
   PROFILE - the framed windows
   The game's garage framing, rebuilt in CSS. Four surfaces, always in the same
   order, so the eye reads a real window inside a window:

     1. .panel       the outer frame - a lit edge, a dark ring painted just
                     inside it, and a light lip over the top of that ring
     2. .panel-body  the well - the interior visibly sits deeper than the frame
     3. .tray        the sub-window - raised back off the well, own lit lip
     4. cards        one step brighter again, so they float inside the tray

   Depth is layered hairlines and shallow gradients only, never a blurry drop
   shadow. Owner call 2026-08-11: "window within a window", tab row deleted.
   ========================================================================== */

/* HUD pass 2026-08-14: panels are notched plates, not rounded cards. Two corners
   are cut on the diagonal - top-left and bottom-right - so the shape reads as
   machined rather than soft. The cut is a clip, so no border survives on the
   diagonal: the edge IS the cut, which is the look. */
.panel {
  position: relative;
  margin-bottom: 22px;
  border-radius: 0;
  clip-path: polygon(var(--notch) 0, 100% 0, 100% calc(100% - var(--notch)),
                     calc(100% - var(--notch)) 100%, 0 100%, 0 var(--notch));
  background: linear-gradient(180deg, rgba(38, 54, 71, 0.55), rgba(23, 33, 46, 0.66));
  box-shadow: 0 22px 44px -40px rgba(0, 0, 0, 0.95);
}
.panel:last-child { margin-bottom: 0; }

.panel-head {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 16px;
  padding: 12px 20px 11px;
  border-radius: 0;
  background: linear-gradient(180deg, rgba(60, 82, 105, 0.5), rgba(31, 44, 60, 0.12));
  border-bottom: 1px solid rgba(9, 15, 23, 0.7);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);
}
/* The accent rail across the top edge of every panel: the HUD's power line. */
.panel-head::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, var(--accent-hi), var(--rail) 22%, transparent 70%);
}

.panel-title {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  color: #dbe5ef;
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
/* The accent tick, the game's own list marker, at panel scale. */
.panel-title::before {
  content: "";
  width: 3px;
  height: 14px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--accent-hi), var(--accent));
  box-shadow: 0 0 10px rgba(67, 160, 107, 0.45);
}

/* Steel rather than --text-dim: the header strip is the lightest surface on the
   page, where dim text measures 4.16:1. This lands at 5.6:1, clear of AA. */
.panel-note {
  margin-left: auto;
  color: var(--note-ink);
  font-family: var(--font-display);
  font-size: 12px;
  letter-spacing: 0.04em;
}

/* Flatten pass 2026-08-14: the panel is the ONLY raised surface on the page.
   Its body is a plain field - no second well - and the groups inside are told
   apart by whitespace, alignment and their label rule instead of by more boxes.
   The generous gap is what now does the work the tray borders used to. */
.panel-body {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 30px;
  padding: 22px 20px 24px;
  border-radius: 0 0 13px 13px;
}

/* A tray is no longer a window within a window: it is simply a labelled group.
   Its head rule and the space around it carry the grouping. */
.tray {
  position: relative;
}

.tray-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}
/* The hairline that runs from the label out to the tray edge. */
.tray-head::after {
  content: "";
  order: 1;
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, rgba(63, 86, 110, 0.9), rgba(63, 86, 110, 0));
}

.tray-title {
  color: var(--note-ink);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
/* The same accent tick as the panel head, one step smaller and without glow. */
.tray-title::before {
  content: "";
  display: inline-block;
  width: 3px;
  height: 11px;
  margin-right: 9px;
  vertical-align: -1px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--accent-hi), rgba(46, 125, 79, 0.35));
}

/* The bare number said nothing on its own, so it is labelled now. The label is
   the quiet half and the figure the loud one, which keeps the count scannable
   at the end of the tray rule. */
.tray-count {
  order: 2;
  flex: none;
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  /* No chip at all (owner call 2026-08-15): the count is bare text on the tray
     rule. The padding is only breathing room where the rule meets it. */
  padding: 0 0 0 4px;
  background: none;
  border: 0;
  color: var(--text-dim);
  font-family: var(--font-display);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
}
.tray-count-n {
  color: var(--stat-ink-hi);
  font-size: 10px;
  font-weight: 700;
}

/* ---------- profile: the identity tray ---------- */

/* The tank runs the full height of the frame beside the rank tray and the
   overview tray, so panel A has no dead space at any width. */
/* Owner call 2026-08-14: the tank sits beside the identity block ONLY, matching
   its height, and the overview runs the full width underneath both - rather than
   the tank spanning two rows and squeezing the figures into a half-width column. */
.ident-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(320px, 46%);
  grid-template-areas:
    "ident tank"
    "stats stats";
  gap: 20px;
  align-items: stretch;
}
.ident-grid > .tray-ident   { grid-area: ident; }
.ident-grid > .viewer-well  { grid-area: tank; }
.ident-grid > .tray-stats   { grid-area: stats; }

.tray-ident {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 18px;
  min-width: 0;
}

.ident-row {
  display: flex;
  align-items: center;
  gap: 20px;
  min-width: 0;
}

.badge-wrap {
  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  width: 104px;
  height: 104px;
}
/* A quiet pool of shade under the art instead of a competing frame: the
   premium rank png already carries its own gold frame. */
.badge-wrap::before {
  content: "";
  position: absolute;
  inset: 4px;
  border-radius: 16px;
  background: radial-gradient(62% 58% at 50% 46%, rgba(0, 0, 0, 0.38), transparent 74%);
}
/* Premium accounts get a whisper of gold in that pool, matching their chip. */
.badge-wrap.is-premium::before {
  background:
    radial-gradient(58% 54% at 50% 46%, rgba(212, 166, 63, 0.16), transparent 72%),
    radial-gradient(62% 58% at 50% 46%, rgba(0, 0, 0, 0.34), transparent 74%);
}
/* The art stands on the tray rather than floating over it. */
.badge-wrap::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -2px;
  transform: translateX(-50%);
  width: 70%;
  height: 12px;
  border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(0, 0, 0, 0.45), transparent 70%);
}
.badge-img { position: relative; display: block; height: auto; }

.ident-names { min-width: 0; }

.nickname {
  font-size: 30px;
  font-weight: 700;
  line-height: 1.14;
  overflow-wrap: anywhere;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.4);
}

.ident-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 9px;
}

/* The standing tags, on their own line between the identity row and the
   experience bar (owner call 2026-08-19). tray-ident already puts 18px either
   side of this row, which reads as detached from the name above it - the
   negative top margin pulls it back under the rank it belongs to. */
.ident-tags {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: -8px;
}

.rank-name {
  padding-right: 4px;
  color: #b3c2d0;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.05em;
}

/* One chip geometry, three tints: gold for premium, steel for the staff role,
   green for the rating position. The role name replaces the old role image
   (owner call 2026-08-11), so it has to share the geometry exactly. */
.premium-tag, .role-chip, .rating-chip {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 10px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-family: var(--font-display);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07);
}

.premium-tag {
  background: linear-gradient(180deg, rgba(212, 166, 63, 0.25), rgba(212, 166, 63, 0.08));
  border-color: rgba(212, 166, 63, 0.5);
  color: #e9c46a;
}

.role-chip {
  background: linear-gradient(180deg, rgba(147, 164, 181, 0.18), rgba(147, 164, 181, 0.06));
  border-color: rgba(158, 178, 197, 0.45);
  color: #cfdae4;
}

.rating-chip {
  background: linear-gradient(180deg, rgba(67, 160, 107, 0.2), rgba(67, 160, 107, 0.07));
  border-color: rgba(67, 160, 107, 0.45);
  color: #6cc191;
}

.ident-since { margin-top: 7px; color: var(--text-dim); font-size: 13px; }

.xpbar { max-width: 480px; }

.xpbar-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 7px;
}

.xpbar-cap {
  color: var(--text-dim);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.xpbar-val {
  font-family: var(--font-display);
  font-size: 13.5px;
  font-weight: 600;
  white-space: nowrap;
}

.xpbar-track {
  height: 11px;
  border-radius: 999px;
  background: rgba(9, 15, 23, 0.9);
  border: 1px solid rgba(9, 15, 23, 0.9);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.55), 0 1px 0 rgba(255, 255, 255, 0.045);
  overflow: hidden;
}

/* Same neon the M3 badges use (owner call 2026-08-19), running out of the
   darker accent so the bar still has depth rather than reading as a flat slab.
   position:relative carries the travelling spark below. */
.xpbar-fill {
  position: relative;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent-hi), var(--mod-ink));
}

/* The sweep, driven by modebars.js exactly as the battle-mode shares are. */
#profile.bars-armed .xpbar-fill {
  transition: width 1500ms cubic-bezier(0.62, 0.02, 0.28, 1);
}
.xpbar-fill::after {
  content: "";
  position: absolute;
  top: 50%;
  right: -3px;
  width: 13px;
  height: 13px;
  margin-top: -6.5px;
  border-radius: 50%;
  background: var(--mod-ink);
  box-shadow:
    0 0 10px 4px rgba(118, 255, 51, 0.95),
    0 0 26px 10px rgba(118, 255, 51, 0.5),
    0 0 44px 18px rgba(118, 255, 51, 0.22);
  opacity: 0;
  pointer-events: none;
  transition: opacity 450ms ease-out;
}
#profile.bars-firing .xpbar-fill::after {
  opacity: 1;
  transition: opacity 120ms ease-in;
}

.xpbar-label { margin-top: 7px; color: var(--text-dim); font-size: 12.5px; }

/* ---------- profile: the tank well ---------- */

/* Deliberately NOT a bright panel: a dark inset well the tank sits inside. It
   now takes its height from the identity block beside it, with a floor so a
   sparse profile (no chips, no "tanker since") cannot squash the tank. */
.viewer-well {
  position: relative;
  min-height: 250px;
  border-radius: 0;
  clip-path: polygon(var(--notch-sm) 0, 100% 0, 100% calc(100% - var(--notch-sm)),
                     calc(100% - var(--notch-sm)) 100%, 0 100%, 0 var(--notch-sm));
  display: grid;
  /* A definite 1fr column, not an auto one: the viewer's own min(90vw,520px)
     would otherwise size the column and escape the well on a phone. */
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
  min-width: 0;
  padding: 10px;
  border: 1px solid rgba(8, 13, 21, 0.85);
  border-radius: 10px;
  background:
    radial-gradient(110% 80% at 50% 8%, rgba(46, 66, 88, 0.34), transparent 62%),
    linear-gradient(180deg, rgba(11, 17, 26, 0.72), rgba(8, 13, 20, 0.88));
  box-shadow: inset 0 3px 16px rgba(0, 0, 0, 0.6), 0 1px 0 rgba(255, 255, 255, 0.04);
  overflow: hidden;
}
/* The rating sits at the far end of the Tanker panel head as plain text - no
   chip, no fill (owner call 2026-08-15). It inherits .panel-note for placement
   and steel colour; only the tracking is its own. */
.viewer-rating {
  color: #ffffff;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
}

/* A faint green floor glow under the tank. */
.viewer-well::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 8%;
  transform: translateX(-50%);
  width: 76%;
  height: 20%;
  border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(67, 160, 107, 0.13), transparent 70%);
  pointer-events: none;
}

/* The viewer keeps its verbatim inline width; max-width only stops it from
   outgrowing the well on a narrow screen. */
#tankview { position: relative; max-width: 100%; }
#tankview.tankview-flat { display: grid; place-items: center; }
#tankview.tankview-empty { opacity: 0.4; }

/* ---------- profile: overview stat cards ---------- */

/* Two deliberate lines (owner call 2026-08-14): kills / deaths / K-D lead at full
   size, then crystals / gold boxes / time in game sit a step down. Hairlines
   between the columns replace the cell borders entirely. */
.stats {
  display: grid;
  gap: 22px 0;
}
/* Two lines, two grids: the lead runs three across, the support line four, which
   one grid cannot express. Each line draws its own column hairlines. */
/* Four over four (owner call 2026-08-15): both lines now share the same column
   edges, which is what the 3-over-4 split could never do. */
.stats-lead { grid-template-columns: repeat(4, 1fr); }
.stats-sub  { grid-template-columns: repeat(4, 1fr); margin-top: 22px; }
.stat-card + .stat-card { padding-left: 22px; border-left: 1px solid rgba(44, 61, 80, 0.9); }

/* Both lines now share one size (owner call 2026-08-14): the step down read as
   an inconsistency rather than a hierarchy, so the six figures are one family
   and the line break alone groups them. */

/* Left-aligned, not centred (owner call 2026-08-16). Centring positioned each
   cell's contents by its own text width, so "54,229" and "2,981,669" started at
   different x and no column had a shared edge. Flush left gives every icon in a
   column one vertical line, which is the only thing that reads as a grid when
   the cells themselves are invisible. Padding comes from the hairline rule
   below, so the first column sits flush with the tray label. */
.stats-lead .stat-card, .stats-sub .stat-card {
  justify-content: flex-start;
}

.stat-card, .g-card, .skin-tile, .supply-card {
  position: relative;
  min-width: 0;
  transition: transform var(--hover-ms) ease-out, border-color var(--hover-ms) ease-out,
              box-shadow var(--hover-ms) ease-out;
}

/* Owner call 2026-08-15: each item sits in its own outlined box again. An
   outline only - no fill - so the tray still reads as one field of items rather
   than a stack of filled cards. No corner cut here: a clip breaks the outline
   on the diagonal, and on a small box that reads as a damaged border rather
   than a deliberate chamfer. Overview stats stay unboxed - they are a strip,
   not a set of objects. */
.g-card, .skin-tile, .supply-card {
  border: 1px solid var(--card-edge);
  /* Square corners (owner call 2026-08-19). Kept as a real border rather than a
     clip-path chamfer, so all four edges keep their outline - a clip cuts the
     border away on the diagonal, which is what made the notched version look
     broken at this size. */
  border-radius: 0;
  /* Raised, not recessed (owner call 2026-08-15: "like tabs, more 3d"): a lit
     top lip, a dark bottom lip and a soft floor shadow, with the sheen laid over
     the fill so the top third catches light. Hover pushes the whole thing one
     step further off the page. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.12),
    0 12px 22px -16px rgba(0, 0, 0, 0.9);
  /* The recessed treatment the art well used to have, moved out to the whole
     card (owner call 2026-08-15): one dark plate holding art and caption
     together, rather than a box inside a box. */
  background:
    var(--sheen),
    linear-gradient(180deg, rgba(56, 78, 101, 0.5), rgba(24, 34, 47, 0.92) 64%);
}
.g-card:hover, .skin-tile:hover, .supply-card:hover {
  transform: translateY(-3px);
  border-color: var(--card-edge-hi);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    0 18px 30px -18px rgba(0, 0, 0, 0.95);
}

.stat-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 2px 0;
}

/* The glyph lost its recessed plate: it now sits inline at low contrast, as a
   marker beside the figure rather than an object in its own frame. */
.stat-art {
  --icon: 28px;
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  color: var(--stat-ink);
  transition: color var(--hover-ms) ease-out;
}
.stat-card:hover .stat-art { color: var(--stat-ink-hi); }

/* Every overview glyph is the same masked silhouette in one steel tint: the
   colour art is stripped, only the shape survives (owner call 2026-08-11).
   Each source carries a different amount of padding around its own drawing, so
   the box is tuned per icon - what has to match optically is the drawn glyph,
   not the file. Measured glyph coverage: kills 79%, deaths 98% wide by 64%
   tall, K/D 88%, crystal 100%, gold box 58%. */
.stat-ic {
  --m: none;
  --s: 1;
  display: block;
  width: calc(var(--icon) * var(--s));
  height: calc(var(--icon) * var(--s));
  background-color: currentColor;
  -webkit-mask: var(--m) center / contain no-repeat;
  mask: var(--m) center / contain no-repeat;
}
.i-s-kills   { --m: url("../icons/stats/kills.png");       --s: 1.04; }
.i-s-deaths  { --m: url("../icons/stats/deaths.png");      --s: 1.00; }
.i-s-kd      { --m: url("../icons/stats/kd.png");          --s: 0.98; }
.i-s-crystal { --m: url("../icons/stats/crystal_big.png"); --s: 0.84; }
/* The site's outline gold box, the same art the home leaderboard already masks.
   The garage variant (goldbox_game.png) is 55% solid alpha with no internal
   detail, so as a mask it collapses into a featureless slab. */
.i-s-goldbox { --m: url("../icons/stats/goldbox.png");     --s: 1.38; }
/* The game's own effect-indicator bolt, owner-supplied 2026-08-14. Its drawing
   fills 60% of its 40px canvas, so it is scaled up to sit at the same optical
   weight as the rest - the same correction the gold box needs. */
.i-s-supplies { --m: url("../icons/stats/supplies.png");   --s: 1.32; }

.stat-clock svg { display: block; width: calc(var(--icon) * 1.07); height: calc(var(--icon) * 1.07); }

.stat-body { display: flex; flex-direction: column; min-width: 0; }

/* The figures are the product: with the chrome gone they take the space it was
   using rather than the page simply getting shorter. */
.stat-value {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 700;
  line-height: 1.15;
  white-space: nowrap;
}

.stat-label {
  color: var(--text-dim);
  font-size: 11px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

/* The rating position rides beside its own figure instead of being pinned to the
   cell corner, where it collided with the column hairline (owner call
   2026-08-14). Baseline-aligned, so it reads as a suffix rather than a badge. */
.stat-line {
  display: flex;
  align-items: baseline;
  gap: 7px;
  min-width: 0;
}

.stat-pos {
  flex: none;
  /* Superscript, not a baseline suffix: it rides at the cap height of the figure
     beside it, the way a rank marker should (owner call 2026-08-14). */
  align-self: flex-start;
  /* line-height:1 collapses its own box to the glyph, otherwise the inherited
     1.5 leaves it tall enough to sit centred against the figure instead of high. */
  line-height: 1;
  margin-top: 1px;
  font-family: var(--font-display);
  font-size: 11.5px;
  font-weight: 700;
  color: var(--text-dim);
}

/* ---------- profile: battle modes (a ranked list, not a card grid) ---------- */

/* Owner call 2026-08-15: one full-width row per mode with a share bar, replacing
   the four-card grid. The list is already ordered by time, so the bars step down
   the page and the split between modes is readable without comparing numbers. */
.modes {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.mode-row {
  --hue: var(--accent-hi);
  position: relative;
  min-width: 0;
}
.mode-dm  { --hue: var(--mode-dm); }
.mode-tdm { --hue: var(--mode-tdm); }
.mode-ctf { --hue: var(--mode-ctf); }
.mode-jgr { --hue: var(--mode-jgr); }

.mode-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 7px;
}

/* Battle-type button art from the game's own mode panel. */
.mode-art {
  flex: none;
  width: 30px;
  height: 30px;
  object-fit: contain;
  filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.5));
}

.mode-name {
  font-family: var(--font-display);
  font-size: 17.5px;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

/* The figures sit at the far end of the row, opposite the name. */
.mode-usage {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 2px 8px;
  margin-left: auto;
  padding-left: 12px;
  color: var(--text-dim);
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  text-align: right;
}
.mode-dot { opacity: 0.55; }

/* The share bar: a dark channel with a lit fill, rounded at both ends so a very
   short bar still reads as a bar rather than a dash. */
.mode-bar {
  position: relative;
  height: 9px;
  border-radius: 999px;
  background: rgba(9, 15, 23, 0.55);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5);
  overflow: hidden;
}
/* Held empty from the head script until modebars.js takes over, so the first
   painted frame is already at zero. !important because the width it is beating
   is an inline style written by the template. */
.pre-sweep .mode-fill,
.pre-sweep .xpbar-fill {
  width: 0 !important;
  min-width: 0 !important;
  transition: none !important;
}
/* The figure is hidden for the same handful of milliseconds: otherwise the real
   total is painted, then the script rewrites it to 0, and the count-up looks
   like it counts DOWN first. Hidden rather than blanked, so the line keeps its
   height and nothing reflows when the digits arrive. */
.pre-sweep .xpbar-val,
.pre-sweep .stat-value.is-counted { visibility: hidden; }

/* The sweep is armed by modebars.js only after it has collapsed the bars, so a
   page without that script never transitions and never sits empty. Ease-out, so
   each bar decelerates into its final share rather than stopping dead. */
/* Ease in AND out (owner call 2026-08-16): the old curve started at full speed,
   so the bar was already moving before the eye caught it. This one builds from
   a standstill, runs quickest through the middle, and settles gently. */
#modes.bars-armed .mode-fill {
  transition: width 1500ms cubic-bezier(0.62, 0.02, 0.28, 1);
}

/* A spark riding the leading edge while the bar travels. It lives on the fill's
   right edge, is lit only for the duration of the run, and fades rather than
   snapping off - so a finished bar carries no permanent glow. */
/* The spark rides the leading edge only - the bar itself never glows, so the
   light reads as something travelling rather than the whole bar being lit. */
.mode-fill::after {
  content: "";
  position: absolute;
  top: 50%;
  right: -3px;
  width: 13px;
  height: 13px;
  margin-top: -6.5px;
  border-radius: 50%;
  /* The bar's own end colour, not white: the spark should read as the bar's tip
     glowing, not as a separate object riding on it. */
  background: var(--mod-ink);
  box-shadow:
    0 0 10px 4px rgba(118, 255, 51, 0.95),
    0 0 26px 10px rgba(118, 255, 51, 0.5),
    0 0 44px 18px rgba(118, 255, 51, 0.22);
  opacity: 0;
  pointer-events: none;
  transition: opacity 450ms ease-out;
}
#modes.bars-firing .mode-fill::after {
  opacity: 1;
  transition: opacity 120ms ease-in;
}

.mode-fill {
  position: relative;
  display: block;
  height: 100%;
  min-width: 9px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent-hi), var(--mod-ink));
}

/* ---------- profile: garage trays ---------- */

/* Wide rows scroll inside their own tray, never the page. */
.hscroll {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 204px;
  gap: 12px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding: 2px 2px 10px;
  scrollbar-width: thin;
  scrollbar-color: #3d5670 transparent;
}
.hscroll::-webkit-scrollbar { height: 8px; }
.hscroll::-webkit-scrollbar-track {
  background: rgba(9, 15, 23, 0.55);
  border-radius: 999px;
}
.hscroll::-webkit-scrollbar-thumb {
  background: #3d5670;
  border-radius: 999px;
}
.hscroll::-webkit-scrollbar-thumb:hover { background: #4d6b89; }

.g-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 9px;
  padding: 10px 11px 12px;
}

/* The art sits in its own shallow well, like the item slots in the garage. A
   fixed height keeps every card in a row aligned even if a preview is missing. */
/* Owner call 2026-08-15: no well behind the art. The card's own outline is the
   only box, and the item floats on it. The element survives purely as a fixed
   height, which is what keeps every caption in a row on one baseline. */
.g-art, .skin-plate, .supply-art {
  position: relative;
  display: grid;
  place-items: center;
  overflow: hidden;
}
/* Each well is sized well clear of the art it holds (owner call 2026-08-14: the
   items were "almost touching the top"). The old boxes left only 8px of total
   slack, so any off-centre transparent padding inside a PNG - and the game art
   is full of it - read as the item riding high. ~32px of slack absorbs it. */
.g-art { width: 100%; height: 138px; }
.supply-art { width: 100%; height: 106px; }
.skin-plate { width: 100%; height: 128px; }

/* Augment icons are square badges, not landscape renders. */
.g-aug { width: 106px; height: 106px; }
/* The game's own alteration icons are 64-66px glyphs: shown at 2x on a dark plate
   rather than stretched to the 106px art box. */
.g-aug[src*="augments_game"] {
  width: 84px;
  height: 84px;
  padding: 10px;
  margin: 11px;
  border-radius: 14px;
  background: radial-gradient(circle at 50% 40%, rgba(255, 255, 255, 0.07), rgba(0, 0, 0, 0.35) 75%);
  box-sizing: border-box;
  image-rendering: auto;
}

/* Game preview art is 164x106: native size, never downscaled. */
.g-preview {
  width: 164px;
  height: 106px;
  object-fit: contain;
  filter: drop-shadow(0 5px 9px rgba(0, 0, 0, 0.45));
}

/* Owner call 2026-08-15: the title heads the card from the top left, and the art
   drops below it. Ordered in CSS rather than moved in the template, so the
   markup keeps its reading order - art, name, figures - for screen readers. */
.g-name, .skin-name, .supply-name {
  order: -1;
  align-self: stretch;
  margin-top: 0;
  justify-content: flex-start;
  text-align: left;
  /* Caps as a card heading (owner call 2026-08-15). Uppercase sets wider than
     mixed case, and "Thunder Protection M1" is the longest title on the site -
     size and tracking are set so it still holds one line on a 204px card. */
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
/* A little air under the title before the art starts. */
.g-art, .skin-plate, .supply-art { margin-top: 4px; }

.g-name {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 16.5px;
  font-weight: 700;
  line-height: 1.3;
}
.g-nm { overflow-wrap: anywhere; }

/* Which turret an augment is for. Ordered alongside the title so it sits with it
   at the top of the card, but set as a quiet caption - it identifies the card,
   it is not the card's name. */
.g-for {
  order: -1;
  align-self: stretch;
  margin-top: -5px;
  color: var(--text-dim);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: left;
}

/* The modification tier, back to plain text after the name ("Wasp M0") in place
   of the mod logo. Secondary to the item name, so it is dimmed rather than
   chipped, and it is omitted on paints, which have no tiers. */
.g-mod {
  flex: none;
  color: var(--mod-ink);
  font-family: var(--font-display);
  font-weight: 700;
}

/* Bigger than it was, and pinned to the card floor so the line sits on one
   baseline across a whole row (owner call 2026-08-11). */
.g-usage {
  display: flex;
  flex-direction: column;
  gap: 3px;
  /* The card centres its children, so the block has to claim the full width
     itself or the rows would only be as wide as their own text. */
  width: 100%;
  margin-top: auto;
  font-family: var(--font-display);
  line-height: 1.25;
  text-align: left;
}
/* One row per figure: label pinned left, figure pinned right, so the two rows
   form a small ledger and the numbers share a right edge (owner call
   2026-08-14). min-width:0 lets a long label shrink rather than push the
   figure out of the card. */
/* Icons replace the written labels (owner call 2026-08-15): a clock for time, an
   XP badge for experience. The words survive for screen readers via .vh and as
   a title tooltip, so nothing is lost - only the repetition on twenty cards. */
.g-stat {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  width: 100%;
}
/* A fixed marker column: the clock is square and the XP wordmark is wide, so
   without this the two figures would start at different x and the little ledger
   would lose its left edge. */
.g-key {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  color: var(--stat-ink);
}
/* Both markers are solid shapes now, not outlines: a filled clock face with the
   hands cut out of it, and a filled star for experience. The star is drawn one
   step larger because a star's points make it read smaller than a disc of the
   same box. */
.g-ic { display: block; }
.g-num { flex: none; }
/* Figure and marker share one tint (owner call 2026-08-15), so each row reads as
   a single object rather than a white number with a grey badge beside it. */
.g-num {
  color: var(--stat-ink);
  font-size: 13.5px;
  font-weight: 700;
}

/* A designed empty garage: the same recessed well the trays sit in, with the
   site's own tank mark in the overview icon tint. */
.empty-state {
  display: grid;
  place-items: center;
  padding: 40px 22px 42px;
  text-align: center;
  border: 1px solid var(--tray-edge);
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(10, 16, 25, 0.42), rgba(10, 16, 25, 0.16));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03), inset 0 6px 14px -10px rgba(0, 0, 0, 0.9);
}

.empty-art {
  display: grid;
  place-items: center;
  width: 68px;
  height: 68px;
  margin-bottom: 14px;
  border-radius: 14px;
  color: #6f8296;
  background: linear-gradient(180deg, rgba(12, 18, 28, 0.7), rgba(20, 29, 41, 0.4));
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.04), inset 0 2px 7px rgba(0, 0, 0, 0.5);
}

.empty-title { font-family: var(--font-display); font-weight: 600; font-size: 15px; }
.empty-sub { color: var(--text-dim); font-size: 13px; margin-top: 4px; }

/* ---------- profile: skins ---------- */

/* Skins ride the same one-line scroller as the garage trays. The track is sized
   to the 163px native art plus the card's padding - narrower than a garage card,
   which also has to carry a usage line. */
.skins {
  grid-auto-columns: 187px;
}

.skin-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 10px 11px 12px;
}

/* Art is 163px wide natively: never upscaled, and only allowed to shrink when the
   track itself is narrower than that (two columns on a small phone). */
.skin-art {
  width: 163px;
  max-width: 100%;
  height: 96px;
  object-fit: contain;
  filter: drop-shadow(0 5px 9px rgba(0, 0, 0, 0.45));
}

/* No render for this item+code pair: the old family icon, at its own size. */
.skin-art.is-fallback {
  width: 58px;
  height: 58px;
  filter: drop-shadow(0 4px 7px rgba(0, 0, 0, 0.45));
}

/* The item carries identity, the code rides beside it as a chip - the render
   already says which turret this is, so the name no longer has to work alone. */
.skin-name {
  margin-top: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  font-size: 16.5px;
  font-weight: 700;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

.skin-code {
  flex: none;
  padding: 1px 6px;
  border: 1px solid var(--card-edge-hi);
  border-radius: 5px;
  background: rgba(11, 17, 26, 0.45);
  color: var(--stat-ink-hi);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

/* ---------- profile: supplies ---------- */

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

.supply-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 10px 11px 12px;
}

.supply-img {
  width: 120px;
  height: 78px;
  object-fit: contain;
  filter: drop-shadow(0 5px 9px rgba(0, 0, 0, 0.45));
}

/* Centred, unlike the garage titles: a supply name is one or two words over a
   wide card, and left-aligning it strands it against the edge. */
.supply-name {
  color: var(--text-dim);
  font-size: 16.5px;
  font-weight: 700;
  text-align: center;
}

.supply-count {
  margin-top: auto;
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 700;
  line-height: 1.15;
}

/* ---------- search + 404 ---------- */

.page-narrow { max-width: 560px; margin-inline: auto; padding-top: 16px; }

.page-title { font-size: 24px; font-weight: 700; margin-bottom: 8px; overflow-wrap: anywhere; }

.page-sub { color: var(--text-dim); margin-bottom: 20px; }

.search-hits { display: flex; flex-direction: column; gap: 8px; }

/* HUD pass 2026-08-14: a hit is a notched plate with an accent spine down its
   leading edge - the same device the battle-mode cards use, at list scale. */
.search-hit {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px 12px 20px;
  background: linear-gradient(180deg, var(--panel-glass), rgba(26, 37, 50, 0.85));
  border-radius: 0;
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--notch-sm)),
                     calc(100% - var(--notch-sm)) 100%, 0 100%);
  font-size: 15px;
  transition: transform var(--hover-ms) ease-out, color var(--hover-ms) ease-out,
              box-shadow var(--hover-ms) ease-out;
}
.search-hit::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: linear-gradient(180deg, var(--accent-hi), rgba(46, 125, 79, 0.25));
  opacity: 0.75;
  transition: opacity var(--hover-ms) ease-out;
}
.search-hit:hover {
  transform: translateY(-1px);
  color: var(--accent-hi);
  box-shadow: var(--lift);
}
.search-hit:hover::before { opacity: 1; }
.hit-go { color: var(--text-dim); font-size: 18px; line-height: 1; }
.search-hit:hover .hit-go { color: var(--accent-hi); }

/* The 404 gets the page's one notched plate to sit on, so it reads as part of
   the same machine rather than loose text on the background. */
.page-missing {
  position: relative;
  text-align: center;
  margin-top: 26px;
  padding: 40px 26px 34px;
  background: linear-gradient(180deg, var(--panel-glass), rgba(26, 37, 50, 0.9));
  clip-path: polygon(var(--notch) 0, 100% 0, 100% calc(100% - var(--notch)),
                     calc(100% - var(--notch)) 100%, 0 100%, 0 var(--notch));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04), 0 18px 40px -28px rgba(0, 0, 0, 0.8);
}
.page-missing::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, var(--accent-hi), var(--rail) 22%, transparent 70%);
}

.missing-code {
  font-family: var(--font-display);
  font-size: 64px;
  font-weight: 800;
  letter-spacing: 0.06em;
  line-height: 1;
  margin-bottom: 10px;
  background: linear-gradient(180deg, #3f5670, #223040);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.btn {
  display: inline-block;
  margin-top: 8px;
  padding: 10px 22px;
  background: linear-gradient(180deg, #38915a, var(--accent));
  border-radius: 0;
  clip-path: polygon(var(--notch-sm) 0, 100% 0, 100% calc(100% - var(--notch-sm)),
                     calc(100% - var(--notch-sm)) 100%, 0 100%, 0 var(--notch-sm));
  color: #fff;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 4px 14px -6px rgba(46, 125, 79, 0.7);
}
.btn:hover { background: linear-gradient(180deg, #43a06b, #38915a); transform: translateY(-1px); }

/* ---------- responsive ---------- */

@media (max-width: 1120px) {
  /* Below this the left column can no longer hold two stat cards beside the
     tank: the three sub-windows stack instead, the tank in the middle. */
  .ident-grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "ident" "tank" "stats";
  }
}

@media (max-width: 1060px) {
  .modes { grid-template-columns: repeat(2, 1fr); }
  .viewer-well { padding: 6px; }
  /* Four columns get tight here and "Gold Box Caught" wraps to two lines. The
     figures stay one size at every width - only the caption tightens. */
  .stat-label { font-size: 10px; letter-spacing: 0.03em; }
}

@media (max-width: 940px) {
  .champs-grid { grid-template-columns: 1fr; }
  .lb-controls { justify-content: center; }
}

@media (max-width: 760px) {
  /* Three columns of figures stop fitting: fall back to two, and rebuild the
     hairlines on the new column boundary instead of the old one. */
  /* Two columns per line, and the size step goes away: at this width a lead
     figure and a support figure can sit side by side, and the mismatch reads as
     a mistake rather than a hierarchy. */
  .stats-lead, .stats-sub { grid-template-columns: repeat(2, 1fr); }
  .stat-card + .stat-card { padding-left: 18px; }
  .stat-card:nth-child(odd) { padding-left: 0; border-left: 0; }
  .stat-card:nth-child(even) { border-left: 1px solid rgba(44, 61, 80, 0.9); }
  .stats-lead .stat-value, .stats-sub .stat-value { font-size: 22px; }
  .stats-sub .stat-art { --icon: 28px; width: 32px; height: 32px; }
  .stats-sub .stat-label { font-size: 11px; }
}

@media (max-width: 640px) {
  /* The tiers compress on a phone, so the art has to shrink with them or it
     would overhang the ordinary rows. */
  .board-rows::before { height: 132px; background-size: auto 132px; }

  .head-inner { gap: 10px; }
  .brand-sub { display: none; }
  .board-head { padding: 12px 14px; }
  .countdown { margin-left: 0; width: 100%; justify-content: center; }
  .row { padding: 9px 12px; gap: 9px; grid-template-columns: 2.1rem 26px minmax(0, 1fr) auto; }

  .panel-head { padding: 12px 15px 11px; }
  .panel-note { margin-left: 0; width: 100%; }
  /* ...but the rating is short enough to stay on the title's line. */
  .viewer-rating { margin-left: auto; width: auto; font-size: 11px; }
  .panel-body { padding: 16px 14px 18px; gap: 24px; }
  .tray-ident { gap: 15px; }
  .ident-row { gap: 15px; }
  .nickname { font-size: 25px; }
  /* Explicit heights, so both rank sets keep the weight they were tuned to:
     width:auto alone would drop each png back to its own intrinsic size
     (74x74 premium, 60x58 default) and the two would stop matching. */
  .badge-wrap { width: 96px; height: 96px; }
  .badge-img { height: 88px; width: auto; }
  .badge-wrap:not(.is-premium) .badge-img { height: 82px; }
}

@media (max-width: 620px) {
  /* Name and figures stop fitting on one line: the figures drop under the name,
     still above the bar, rather than both wrapping into a tangle. */
  .mode-head { flex-wrap: wrap; row-gap: 2px; }
  .mode-name { font-size: 15.5px; }
  .mode-usage {
    width: 100%;
    margin-left: 0;
    padding-left: 40px;
    justify-content: flex-start;
    text-align: left;
    font-size: 13px;
  }
}

@media (max-width: 520px) {
  /* Stack the stat cell so a seven-digit value can never widen the grid - still
     centred, so the phone layout matches the desktop one. */
  .stat-card { flex-direction: column; align-items: center; gap: 6px; padding: 2px 0; }
  .stats-lead .stat-card, .stats-sub .stat-card { padding-inline: 0; }
  .stat-body { align-items: center; text-align: center; }
  .stat-art { --icon: 24px; width: 26px; height: 26px; }
  .stat-value { font-size: 21px; }
  .stat-pos { top: 0; right: 0; }
}

@media (max-width: 420px) {
  /* One mode per row: "Team Deathmatch" and "Capture the Flag" are never
     abbreviated, so they get the full width rather than wrapping in a column. */
  .modes { grid-template-columns: 1fr; }
  :root { --notch: 12px; --notch-sm: 8px; }
  .seg-btn { padding: 8px 11px; }
  .supplies { grid-template-columns: repeat(2, 1fr); }
  .supply-art { height: 92px; }
  .supply-img { width: 100px; height: 65px; }
  .ident-row { flex-direction: column; align-items: flex-start; gap: 12px; }
}

/* ---------- motion ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
  .card-lit:hover, .stat-card:hover, .g-card:hover,
  .skin-tile:hover, .supply-card:hover, .podium-card:hover,
  .search-hit:hover, .btn:hover { transform: none; }
}

/* Augment cards (2026-09-05): the mounted marker beside the turret name, and a
   text label in the usage row where the other cards carry a glyph. */
.g-eq {
  margin-left: 6px;
  color: var(--mod-ink);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.g-key-text {
  margin-right: 6px;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
