/* ==========================================================================
   R6DATA — page-level styles.

   `css/r6-ui.css` carries the shared vocabulary; this file carries the shapes
   that belong to one page or one family of pages, in the same language: flat
   surfaces, hairline borders, one saturated element per row.

   Loaded after r6-ui.css on every page in the redesign scope.
   ========================================================================== */

/* ==========================================================================
   HOME — hero
   ========================================================================== */
.home-page { display: block; }

/* Full-bleed strip for the admin alert, above everything.

   The home page drops the container's top padding rather than pulling the
   banner up with a negative margin: the banner is site chrome and belongs
   flush against the navbar, and a negative margin here collapsed through
   `#content` at the breakpoints where that padding is smaller, tucking the
   first line of the banner behind the navbar. The hero brings its own 92px of
   top padding, so nothing else needs the space. */
.page-content:has(.home-page) { padding-top: 0; }
.home-alert-slot {
  margin: 0 calc(50% - 50vw); position: relative; z-index: 20;
}
.home-alert-slot:empty { display: none; }
/* Opaque, not a translucent tint: the hero photo starts right underneath and
   would otherwise show through the bar. */
.home-alert-banner {
  width: 100%;
  background: #2a2214;
  border-bottom: 1px solid rgba(245, 166, 35, .22);
  color: var(--primary-color);
}
.home-alert-inner {
  min-height: 46px; max-width: var(--maxw); margin: 0 auto;
  padding: 9px 52px 9px 20px;
  display: flex; align-items: center; justify-content: center; gap: 12px;
  position: relative; text-align: center;
}
.home-alert-text { font-size: .88rem; font-weight: 600; line-height: 1.4; min-width: 0; color: var(--primary-color); }
.home-alert-action {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: var(--radius-sm);
  border: 1px solid rgba(245, 166, 35, .35); background: transparent;
  color: var(--primary-color); font-size: .8rem; font-weight: 700; white-space: nowrap;
  transition: background-color .16s ease, border-color .16s ease;
}
.home-alert-action:hover { background: rgba(245, 166, 35, .12); border-color: var(--primary-color); color: var(--primary-color); }
.home-alert-action .material-icons { font-size: 16px; }
.home-alert-close {
  position: absolute; right: 14px; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center; width: 30px; height: 30px;
  border: 0; border-radius: 8px; background: transparent;
  color: var(--primary-color); cursor: pointer; opacity: .7;
}
.home-alert-close:hover { opacity: 1; background: rgba(245, 166, 35, .12); }
.home-alert-close .material-icons { font-size: 18px; }

/* ---- hero backdrop --------------------------------------------------------
   The Siege concept art is back, but as a full-bleed backdrop rather than a
   photo inside a rounded card: it starts flush under the navbar, runs edge to
   edge, and is masked away towards the bottom so it dissolves into the page
   instead of ending on a hard edge. `::before` carries the image, `::after` the
   colour wash that keeps the headline legible over it. */
.hero {
  position: relative; padding-block: 92px 52px; text-align: center;
  background: none; border: 0; border-radius: 0; box-shadow: none; overflow: visible;
  margin-bottom: 0;
}
/* The bleed uses the same `calc(50% - 50vw)` trick as .home-alert-slot. */
.hero::before,
.hero::after {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  left: calc(50% - 50vw); right: calc(50% - 50vw);
  top: calc(-1 * (var(--nav-height) + 22px)); bottom: -60px;
}
/* The photo reads as a photo: full opacity, and only the bottom third is masked
   away so it dissolves into the page. It was at .3 under a heavy dark wash,
   which buried it. */
.hero::before {
  background-image:
    url('https://staticctf.ubisoft.com/J3yJr34U2pZ2Ieem48Dwy9uqj5PNUQTn/2vuUMp7f7nVNtkgOmbMFJ8/af5a3c42d9e232414b194592b4bd8c93/r6s-concept.jpg'),
    url('/assets/img/maps/wallpaper.jpg');
  background-size: cover; background-position: center 30%; background-repeat: no-repeat;
  opacity: 1;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 58%, rgba(0, 0, 0, .45) 82%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 58%, rgba(0, 0, 0, .45) 82%, transparent 100%);
}
/* Sits over the photo. Just enough to keep the headline and the search box
   legible — a light scrim at the top, the page colour only at the very bottom
   where the mask has already taken the image away. */
.hero::after {
  background:
    /* A soft pool behind the copy block only, so the headline and the lead stay
       readable over the bright snow without dulling the whole photograph. */
    radial-gradient(ellipse 880px 260px at 50% 46%, rgba(9, 9, 11, .78), transparent 72%),
    radial-gradient(ellipse 820px 420px at 50% 34%, rgba(245, 166, 35, .08), transparent 70%),
    linear-gradient(to bottom, rgba(9, 9, 11, .42) 0%, rgba(9, 9, 11, .22) 34%, rgba(13, 13, 15, .5) 74%, var(--background-color) 100%);
}
.hero > * { position: relative; z-index: 1; }
/* The two backdrop pseudos are positioned, so at the default z-index they paint
   over the static sections that follow — the first tool cards were half-covered
   by the wash. Lifting the sections into their own layer settles the order. */
.home-page > .section { position: relative; z-index: 1; }
.hero h1 {
  font-size: clamp(2.1rem, 5.2vw, 3.4rem); font-weight: 800;
  letter-spacing: -0.04em; line-height: 1.05; font-style: normal;
}
.hero h1 mark { background: none; color: var(--primary-color); padding: 0; }
.hero .lead {
  color: var(--text-secondary); font-size: 1.05rem; max-width: 660px;
  margin: 16px auto 30px; line-height: 1.6;
}
.hero-hint { display: inline-flex; align-items: center; gap: 6px; margin-top: 16px; color: var(--text-muted); }
.hero-hint .material-icons { font-size: 17px; }

/* ---- hero search: platform picker, field and submit are ONE control --------
   The platform is part of the query, so it lives inside the box that takes the
   query rather than floating above it as a separate widget. */
.search-wrap { position: relative; width: 100%; max-width: 700px; margin: 0 auto; z-index: 40; }
.hero-search {
  display: flex; align-items: center; gap: 8px;
  padding: 7px; border-radius: 16px;
  background: var(--surface-color); border: 1px solid var(--line-strong);
  transition: border-color .16s ease, box-shadow .16s ease;
}
.hero-search:hover { border-color: #454550; }
.hero-search:focus-within { border-color: var(--primary-color); box-shadow: 0 0 0 4px var(--primary-soft); }

/* Segmented control — the ACTIVE segment is the only saturated thing on the
   row, and it takes the platform's own colour. */
.hero-platforms { display: inline-flex; gap: 2px; flex: none; }
.platform-tab {
  display: inline-flex; align-items: center; gap: 6px;
  height: 42px; padding: 0 12px; border: 0; border-radius: 11px; background: transparent;
  color: var(--text-muted); font-family: inherit; font-weight: 600; font-size: .82rem;
  cursor: pointer; transition: background-color .14s ease, color .14s ease;
  -webkit-tap-highlight-color: transparent;
}
.platform-tab svg { width: 17px; height: 17px; display: block; flex: none; }
.platform-tab:hover { background: var(--surface-2); color: var(--text-primary); }
.platform-tab.active { color: #fff; }
.platform-tab.active[data-platform="uplay"] { background: #ff6600; }
.platform-tab.active[data-platform="xbl"]   { background: #107c10; }
.platform-tab.active[data-platform="psn"]   { background: #0f4bb5; }

/* Hairline between the picker and the field, so the box reads as two parts of
   one control rather than as a button glued to an input. */
.hs-sep { flex: none; width: 1px; align-self: stretch; margin: 6px 2px; background: var(--line); }

.hero-search input {
  flex: 1; min-width: 0; padding: 13px 4px; border: 0; border-radius: 0;
  background: none; color: var(--text-primary); font: inherit; font-size: 1rem; text-align: left;
}
.hero-search input:hover, .hero-search input:focus { border: 0; outline: none; box-shadow: none; }
.hero-search input::placeholder { color: var(--text-muted); }
.hs-go { flex: none; min-height: 42px; padding: 0 20px; border-radius: 11px; }
.hs-go .material-icons { font-size: 19px; margin-left: -3px; }

/* ---- typeahead / recent players ---- */
.search-results {
  position: absolute; top: calc(100% + 8px); left: 0; right: 0; z-index: 900;
  background: var(--surface-color); border: 1px solid var(--line-strong); border-radius: 14px;
  box-shadow: var(--shadow-lg); max-height: 380px;
  overflow-y: auto; overscroll-behavior: contain;
  text-align: left; padding: 5px;
}
.search-results { scrollbar-width: thin; scrollbar-color: var(--primary-color) var(--bg-2); }
.search-results::-webkit-scrollbar { width: 10px; }
.search-results::-webkit-scrollbar-track { background: var(--bg-2); }
.search-results::-webkit-scrollbar-thumb { background: var(--primary-color); border-radius: 999px; border: 3px solid var(--bg-2); }
.search-results-head {
  display: flex; align-items: center; gap: 7px; padding: 10px 12px 6px;
  font-size: .64rem; font-weight: 700; text-transform: uppercase; letter-spacing: .12em;
  color: var(--text-muted);
}
.search-results-head .material-icons { font-size: 15px; }
.search-item {
  display: flex; align-items: center; gap: 12px; padding: 9px 11px;
  cursor: pointer; border-radius: var(--radius);
  transition: background-color .12s ease;
}
.search-item:hover, .search-item.active { background: var(--surface-2); }
.s-av {
  width: 34px; height: 34px; border-radius: 10px; flex-shrink: 0;
  display: grid; place-items: center; overflow: hidden;
  background: var(--surface-3); color: var(--text-secondary);
}
.s-av img { width: 100%; height: 100%; object-fit: cover; }
.s-av .material-icons { font-size: 18px; }
.s-av-uplay { background: rgba(255, 255, 255, .08); color: #fff; }
.s-av-xbl { background: rgba(16, 124, 16, .16); color: #4fbe4f; }
.s-av-psn { background: rgba(15, 75, 181, .18); color: #6ba3ff; }
.search-item .s-main { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.search-item .s-name {
  display: flex; align-items: center; gap: 7px; min-width: 0;
  font-weight: 600; font-size: .94rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.s-plat { flex: none; display: inline-grid; place-items: center; width: 14px; height: 14px; }
.s-plat svg { width: 100%; height: 100%; display: block; }
/* The Ubisoft Connect mark is a white glyph; tinting it orange made it read
   as a different brand. Xbox and PlayStation keep their own colours. */
.s-plat-uplay { color: #fff; }
.s-plat-xbl { color: #4fbe4f; }
.s-plat-psn { color: #6ba3ff; }
.search-item .s-sub { color: var(--text-muted); font-size: .78rem; margin-top: -1px; }
.s-del {
  flex: none; display: grid; place-items: center; width: 28px; height: 28px;
  border: 0; border-radius: 8px; background: transparent; color: var(--text-muted);
  cursor: pointer; opacity: .6; transition: opacity .14s ease, background-color .14s ease, color .14s ease;
}
.s-del:hover { opacity: 1; background: rgba(255, 92, 122, .12); color: var(--error-color); }
.s-del .material-icons { font-size: 16px; }

/* ==========================================================================
   HOME — section headings and tool cards

   Each tool opens with its own heading and a rule that runs to the right edge,
   the way the previous design named them. One tool per section, so the name
   above the card says what it is before the card has to.
   ========================================================================== */
/* Each tool section holds a single card, so the default 28px section rhythm put
   ~90px of air between one card and the next heading. */
.home-page .section { padding-block: 16px; }
.home-page .section:first-of-type { padding-top: 10px; }

.rule-head { display: flex; align-items: center; gap: 16px; margin-bottom: 16px; }
.rule-head h2 { flex: none; margin: 0; font-size: 1.25rem; font-weight: 700; letter-spacing: -0.02em; }
.rule-line { flex: 1; height: 1px; background: var(--line); }
.rule-link {
  flex: none; display: inline-flex; align-items: center; gap: 4px;
  font-size: .86rem; font-weight: 600; color: var(--primary-color); white-space: nowrap;
}
.rule-link:hover { color: var(--primary-light); }
.rule-link .material-icons { font-size: 17px; }

.tool-card { --tool-accent: var(--primary-color); }
.tool-card .card-content { padding: 24px 26px; }
.tool-head { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; margin-bottom: 10px; }
.tool-ic {
  flex: none; width: 36px; height: 36px; border-radius: 10px; display: grid; place-items: center;
  background: color-mix(in srgb, var(--tool-accent) 14%, transparent); color: var(--tool-accent);
}
.tool-ic .material-icons { font-size: 20px; }
.tool-head h3 { margin: 0; font-size: 1.2rem; font-weight: 700; letter-spacing: -0.02em; }
.tool-card p { margin: 0; color: var(--text-secondary); font-size: .94rem; line-height: 1.6; max-width: 780px; }
.tool-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
/* The globe's button carries its own colour, so it needs its own ink too. */
.tool-card[style*="--tool-accent"] .btn-primary {
  background: var(--tool-accent); border-color: var(--tool-accent); color: #041013;
}
.tool-card[style*="--tool-accent"] .btn-primary:hover { filter: brightness(1.08); }

/* ==========================================================================
   HOME — statistics

   Grouped counters, not one box per number: a card is a subject (Steam, Twitch
   watch time…) and holds the one or two figures that belong to it.
   ========================================================================== */
.stat-grid { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); align-items: stretch; }
.stat-group-card .card-content { display: flex; flex-direction: column; height: 100%; padding: 20px 22px; }
.sgc-head { display: flex; align-items: center; gap: 9px; margin-bottom: 16px; }
.sgc-head .material-icons { font-size: 20px; color: var(--primary-color); }
.sgc-head h3 { margin: 0; font-size: 1rem; font-weight: 600; }
.is-twitch-card .sgc-head .material-icons { color: #a970ff; }

.stat-group-card .stat-item {
  background: none; border: 0; border-radius: 0; padding: 0;
  display: flex; flex-direction: column; gap: 2px;
}
.stat-group-card .stat-item + .stat-item { margin-top: 14px; }
.stat-group-card .stat-item:hover { border: 0; }
.stat-group-card .stat-value {
  font-family: var(--font-display); font-weight: 700; font-size: 1.5rem;
  letter-spacing: -0.03em; line-height: 1.1; font-variant-numeric: tabular-nums;
  margin-bottom: 0; transition: opacity .3s ease;
}
.stat-group-card .stat-value.is-accent { color: var(--primary-color); }
.stat-group-card .stat-value.is-good { color: var(--success-color); }
.stat-group-card .stat-value.is-twitch { color: #a970ff; }

/* Platform split — a row per platform, name left, count right. */
.split-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid var(--line);
}
.split-row:last-child { border-bottom: 0; padding-bottom: 0; }
.split-row:first-child { padding-top: 0; }
.split-name { display: inline-flex; align-items: center; gap: 8px; font-size: .9rem; color: var(--text-secondary); }
.split-name .material-icons { font-size: 18px; color: var(--text-muted); }
.split-val { font-weight: 700; font-size: 1rem; font-variant-numeric: tabular-nums; transition: opacity .3s ease; }

/* Freshness line the loaders append after each stat grid. */
.update-indicator, .twitch-update-indicator {
  margin-top: 14px; text-align: center;
  font-size: .76rem; color: var(--text-muted); font-variant-numeric: tabular-nums;
}

/* ---- Developer access ------------------------------------------------------
   The one panel on the site that is allowed a wash of colour: it is the single
   commercial call to action, and it sat on a tinted background before. The wash
   is a flat gold gradient over the surface rather than the old slate→gold one,
   so it still belongs to this palette. */
/* Cool slate on the left running to a warm gold hint on the right — the wash
   the panel had before, re-cut against the new surfaces. A single gold ramp
   read as a flat gold block; the temperature shift is what gave it depth. */
.cta-panel {
  display: flex; align-items: center; justify-content: space-between;
  gap: 22px; flex-wrap: wrap; padding: 30px 32px;
  background:
    linear-gradient(135deg, rgba(34, 44, 64, .82) 0%, rgba(28, 30, 38, .5) 46%, rgba(245, 166, 35, .12) 100%),
    var(--surface-color);
  border: 1px solid rgba(245, 166, 35, .3);
}
.cta-panel:hover { border-color: rgba(245, 166, 35, .42); }
.cta-main { display: flex; align-items: center; gap: 18px; min-width: 300px; flex: 1; }
.cta-panel h2 { margin: 0 0 5px; font-size: 1.4rem; font-weight: 800; letter-spacing: -0.02em; }
.cta-panel p { color: var(--text-secondary); margin: 0; font-size: .96rem; max-width: 580px; line-height: 1.55; }
.cta-ic {
  flex: none; width: 48px; height: 48px; border-radius: 13px; display: grid; place-items: center;
  background: var(--primary-soft); border: 1px solid rgba(245, 166, 35, .28); color: var(--primary-color);
}
.cta-ic .material-icons { font-size: 25px; }
.cta-btn { flex: none; min-height: 46px; padding: 0 26px; font-size: .98rem; }

/* ==========================================================================
   CATALOG PAGES — operators, maps, weapons, gadgets, attachments, skins, charms

   One card shape across all of them, so the database section reads as one
   thing rather than seven differently-built galleries.
   ========================================================================== */
.page-controls {
  display: flex; flex-direction: column; gap: 14px; margin-bottom: 22px;
}
.page-controls .tabs { margin: 0; align-self: flex-start; }
.page-controls .search-bar { margin: 0; }
.page-controls-row { flex-direction: row; align-items: center; flex-wrap: wrap; }

/* Cards stretch to their row so every row reads as one band; the chips row is
   pushed to the bottom so it lines up across the row even when one card's name
   wraps to two lines. */
.entity-grid .card-content { display: flex; flex-direction: column; height: 100%; }
.entity-grid .ent-chips { margin-top: auto; padding-top: 14px; }
/* A map with no playlists, an attachment with no rarity: without this the empty
   row still claimed the bottom of the card and left a hole under the copy. */
.ent-chips:empty { display: none; }

/* No accent spine on the left edge. It used to carry the category colour
   (attacker/defender, weapon class, rarity), but on a card that already states
   the same thing in a chip it read as a stray line. The chips are the cue. */
.entity-card {
  cursor: pointer;
  border-left: 1px solid var(--line);
  position: relative;
}
.entity-card::before { display: none; }
.entity-card:hover { border-color: var(--line-strong); background: var(--surface-2); }

.ent-head { display: flex; align-items: center; gap: 14px; min-width: 0; }
.ent-ic {
  width: 48px; height: 48px; flex: none; border-radius: 12px;
  object-fit: cover; background: var(--surface-3); display: block;
}
.ent-ic-ph { display: grid; place-items: center; color: var(--text-muted); }
.ent-ic-ph .material-icons { font-size: 22px; }
.ent-ic-lg { width: 60px; height: 60px; border-radius: 14px; }
.ent-id { min-width: 0; }
.ent-name {
  margin: 0; font-family: var(--font-display); font-weight: 700; font-size: 1.05rem;
  letter-spacing: -0.02em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ent-sub { margin: 1px 0 0; color: var(--text-muted); font-size: .82rem; }
.ent-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 14px; }
/* A universal skin covers ~200 weapons; the dialog scrolls that list rather
   than growing to hold it. */
.skin-weapons {
  max-height: 220px; overflow-y: auto; overscroll-behavior: contain;
  padding-right: 4px;
  scrollbar-width: thin; scrollbar-color: var(--primary-color) var(--bg-2);
}

/* The API returns "attacker"/"defender" lowercase; capitalising in CSS keeps
   the data untouched and the label in the site's sentence case. */
.chip-attacker, .chip-defender { text-transform: capitalize; }
.chip-attacker { background: var(--accent-soft); border-color: rgba(255, 107, 53, .3); color: var(--accent-color); }
.chip-defender { background: rgba(74, 155, 255, .12); border-color: rgba(74, 155, 255, .3); color: #6fb0ff; }

.chip-warning { background: rgba(255, 181, 69, .12); border-color: rgba(255, 181, 69, .3); color: var(--warning-color); }
.chip-rarity { border-color: currentColor; background: transparent; }

/* ---- maps: a photo card, so the image is the card's top edge ----
   No side spine here: on a card whose top half is a photograph the 3px bar
   reads as a stray line rather than a category cue. */
.map-grid { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.map-card .map-image-container {
  height: 168px; overflow: hidden; background: var(--surface-3);
  border-bottom: 1px solid var(--line);
}
.map-card .map-image-container img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .3s ease;
}
.map-card:hover .map-image-container img { transform: scale(1.04); }
.map-card .ent-name { font-size: 1.15rem; margin-bottom: 8px; }
.map-meta {
  display: flex; align-items: center; gap: 7px; margin: 0 0 5px;
  color: var(--text-secondary); font-size: .86rem;
}
.map-meta .material-icons { font-size: 16px; color: var(--text-muted); }

/* A charm name is often long enough to need two lines; the catalog's other
   entities never wrap, so wrapping is opt-in. */
.ent-name-wrap {
  white-space: normal; overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow-wrap: anywhere; font-size: .98rem;
}

/* ---- charms: search on the left, rarity picker on the right ---- */
.charms-filter { align-items: flex-end; gap: 12px; }
.charms-filter .cf-search { flex: 1 1 260px; min-width: 0; }
.charms-filter .cf-rarity { flex: 0 0 200px; }
.charms-filter .cf-rarity label { margin-bottom: 6px; font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: var(--text-muted); }
.pager-note { margin: 12px 0 24px; }

/* ---- weapons: the render sits on its own plate above the name ---- */
.weapon-grid { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.wpn-shot {
  display: grid; place-items: center; height: 84px; margin-bottom: 12px;
  padding: 8px 12px; border-radius: var(--radius);
  background: var(--surface-2); border: 1px solid var(--line);
  overflow: hidden;
}
/* `max-width` alone does not contain a grid item: the image's intrinsic width
   sets the track, so a wide render pushed the track past the plate and spilled
   out of the card. `min-width: 0` lets the track shrink; `width/height: 100%`
   plus `object-fit: contain` then scales the render down to fit. */
.wpn-shot img {
  min-width: 0; min-height: 0;
  width: 100%; height: 100%;
  max-width: 100%; max-height: 100%;
  object-fit: contain;
}
.dialog-title .wpn-shot { height: 120px; margin-bottom: 14px; }

/* ---- ranks: tier icon, then the point range as a two-cell footer ---- */
.rank-grid { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
.rank-card .rank-ic { width: 52px; height: 52px; flex: none; object-fit: contain; display: block; }
.rank-range {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  margin-top: auto; padding-top: 14px;
}
.rank-range > span { display: flex; flex-direction: column; gap: 2px; }
.rank-range .rr-max { text-align: right; }
.rank-range .rr-l {
  font-size: .64rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .1em; color: var(--text-muted);
}
.rank-range b { font-size: 1.05rem; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }

/* ---- the rank-version picker + its floating list ---- */
.rank-version { max-width: 560px; }
.rank-version > label {
  font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .1em; color: var(--text-muted); margin-bottom: 8px;
}
.rank-version .custom-select { position: relative; }
.version-select {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  border-radius: var(--radius); cursor: pointer;
  background: var(--surface-color); border: 1px solid var(--line-strong);
  transition: border-color .16s ease, background-color .16s ease;
}
.version-select:hover { border-color: #454550; background: var(--surface-2); }
.version-select .vs-ic { color: var(--primary-color); font-size: 21px; flex: none; }
.vs-body { flex: 1; min-width: 0; }
.vs-label { font-weight: 600; font-size: .94rem; }
.vs-desc { font-size: .8rem; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; }
.version-select .dropdown-arrow { color: var(--text-muted); transition: transform .2s ease; flex: none; }

.rank-dropdown {
  position: absolute; z-index: 950; max-height: 340px;
  overflow-y: auto; overscroll-behavior: contain;
  padding: 5px; border-radius: 14px;
  background: var(--surface-color); border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-lg);
  opacity: 0; transform: translateY(8px);
  transition: opacity .16s ease, transform .16s ease;
  scrollbar-width: thin; scrollbar-color: var(--primary-color) var(--bg-2);
}
.rank-dropdown.visible { opacity: 1; transform: translateY(0); }
.rank-dropdown::-webkit-scrollbar { width: 8px; }
.rank-dropdown::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 4px; }
.rank-dropdown-option {
  display: flex; align-items: center; gap: 11px; padding: 10px 12px;
  border-radius: var(--radius-sm); cursor: pointer;
  transition: background-color .14s ease;
}
.rank-dropdown-option:hover { background: var(--surface-2); }
.rank-dropdown-option.selected { background: var(--primary-soft); }
.rank-dropdown-option.selected .vs-label { color: var(--primary-color); }
.rank-dropdown-option .material-icons { color: var(--text-muted); font-size: 19px; flex: none; }
.rank-dropdown-option.selected .material-icons { color: var(--primary-color); }

/* ==========================================================================
   GAME SUMMARY (quiz result share page)
   ========================================================================== */
.summary-container {
  background: var(--surface-color); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: none;
}
.summary-title {
  background: none;
  -webkit-background-clip: border-box; background-clip: border-box;
  -webkit-text-fill-color: currentColor;
  color: var(--text-primary); font-style: italic; font-weight: 800; letter-spacing: -0.03em;
}
.summary-container .btn-primary {
  background: var(--primary-color); color: var(--primary-ink);
  border: 1px solid var(--primary-color); border-radius: var(--radius);
}
.summary-container .btn-primary:hover {
  transform: none; background: var(--primary-light);
  border-color: var(--primary-light); color: var(--primary-ink);
}

/* ==========================================================================
   PLAYER COUNT

   The hero laid a darkened map wallpaper behind the headline number and gave
   the number a glow. Same treatment as the home hero instead: a flat surface
   with one lit patch, and the number carries the colour on its own.
   ========================================================================== */
.pc-hero {
  position: relative; overflow: hidden;
  background: var(--surface-color); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 60px 32px 54px;
}
/* The map wallpaper is back behind the headline number, dimmed enough that the
   figure stays the loudest thing in the box. */
.pc-hero::after {
  background-image: url('/assets/img/maps/wallpaper.jpg');
  background-size: cover; background-position: center 35%; background-repeat: no-repeat;
  opacity: .8;
}
.pc-hero::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(ellipse 780px 240px at 50% 58%, rgba(9, 9, 11, .7), transparent 74%),
    radial-gradient(ellipse at center top, rgba(245, 166, 35, .10), transparent 62%),
    linear-gradient(to bottom, rgba(13, 13, 15, .5) 0%, rgba(13, 13, 15, .62) 100%);
}
.pc-hero > * { position: relative; z-index: 2; }
.pc-bignum { text-shadow: none; color: var(--primary-color); letter-spacing: -0.04em; }
.pc-card:hover { transform: none; box-shadow: none; border-color: var(--line-strong); }
.pc-cta:hover { transform: none; border-color: var(--line-strong); }

/* ==========================================================================
   R6 GAME (quiz)

   r6data-game.html's own <style> paints the title and the two call-to-action
   buttons with a gold→orange gradient and lifts every interactive element by
   2px on hover. One flat saturated fill and a border change replace both.
   ========================================================================== */
.game-title {
  background: none;
  -webkit-background-clip: border-box; background-clip: border-box;
  -webkit-text-fill-color: currentColor;
  color: var(--text-primary);
  font-style: italic; font-weight: 800; letter-spacing: -0.03em;
}
.game-subtitle { color: var(--text-secondary); }
.setup-screen, .game-screen, .results-screen {
  background: var(--surface-color); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: none;
}
.start-btn, .play-again-btn {
  background: var(--primary-color); color: var(--primary-ink);
  border: 1px solid var(--primary-color); border-radius: var(--radius);
  font-weight: 700;
}
.start-btn:hover, .play-again-btn:hover {
  transform: none; box-shadow: none;
  background: var(--primary-light); border-color: var(--primary-light);
}
.answer-btn:hover {
  transform: none; border-color: var(--primary-color); background: var(--primary-soft);
}
.toggle-btn-top {
  background: var(--surface-color); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--text-secondary);
}
.toggle-btn-top:hover { transform: none; border-color: var(--line-strong); color: var(--text-primary); }
.filter-input-container { box-shadow: var(--shadow-lg); border: 1px solid var(--line-strong); border-radius: var(--radius); }

/* ==========================================================================
   PRODUCT LANDING PAGES — r6-data-js, r6-replay-viewer, r6-streaming-widget

   These three already sit close to the system. What is left is the hero title
   (painted with a clipped gradient) and the buttons that lift and glow on
   hover — the reference never moves an element on hover and never glows.
   Their own <style> blocks sit in <head> above this file, so equal specificity
   is enough.
   ========================================================================== */
.npm-hero h1, .replay-hero h1, .overlay-hero h1 {
  background: none;
  -webkit-background-clip: border-box; background-clip: border-box;
  -webkit-text-fill-color: currentColor;
  color: var(--text-primary);
  font-style: italic;
}
.npm-hero h1 mark, .replay-hero h1 mark, .overlay-hero h1 mark { background: none; color: var(--primary-color); }

.npm-hero-actions .btn-primary,
.overlay-hero-actions .btn-primary {
  border-radius: var(--radius); border: 1px solid var(--primary-color);
}
.npm-hero-actions .btn-primary:hover,
.overlay-hero-actions .btn-primary:hover {
  transform: none; box-shadow: none;
  background-color: var(--primary-light); border-color: var(--primary-light);
}

.code-block-container, .replay-image, .feature-image {
  border-color: var(--line); border-radius: var(--radius-lg); box-shadow: none;
}

/* ==========================================================================
   DISCORD — the rest of the page's look is in the module's own <style>
   ========================================================================== */
.bot-hub-container.card { padding: 40px 24px; margin-bottom: 40px; }
.bot-cta {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 30px; margin-bottom: 40px;
}
.bot-cta h3 { font-size: 1.35rem; font-weight: 800; letter-spacing: -0.02em; margin-bottom: 10px; }
.bot-cta-copy { color: var(--text-secondary); max-width: 580px; margin-bottom: 22px; }
.bot-cta-btn { min-height: 46px; padding: 0 32px; font-size: 1rem; }

.bot-doc { margin-bottom: 40px; }
.bot-doc-title {
  font-size: 1.4rem; font-weight: 800; letter-spacing: -0.02em;
  padding-bottom: 14px; margin-bottom: 18px; border-bottom: 1px solid var(--line);
}
.bot-doc-lead { color: var(--text-secondary); line-height: 1.7; margin-bottom: 22px; }
.cmd-list { display: flex; flex-direction: column; gap: 10px; }
.cmd-item {
  padding: 14px 16px; border-radius: var(--radius);
  background: var(--surface-2); border: 1px solid var(--line);
}
.cmd-name { display: block; margin-bottom: 4px; color: var(--primary-color); font-family: var(--font-mono); font-size: .9rem; }
.cmd-name code { background: none; border: 0; padding: 0; color: inherit; }
.cmd-desc { color: var(--text-secondary); font-size: .88rem; line-height: 1.55; }

/* ==========================================================================
   PRICING

   The page shipped its own indigo/emerald accents (#6366f1, #10b981) for the
   recommended and yearly plans — two colours that exist nowhere else on the
   site. The highlight is the primary gold instead, and the badge row goes back
   to the standard chip.
   ========================================================================== */
.plans-page { padding-block: 8px 36px; }
body:has(.plans-page) .site-footer { margin-top: 28px; }
.plans-header h1 { font-style: italic; font-weight: 800; letter-spacing: -0.03em; }
.plans-header p { color: var(--text-secondary); }

.billing-toggle {
  gap: 3px; padding: 4px; border-radius: 12px;
  border: 1px solid var(--line); background: var(--surface-color);
}
.billing-toggle button { border-radius: 8px; padding: 8px 15px; font-size: .88rem; }
.billing-toggle button:hover { background: var(--surface-2); color: var(--text-primary); }
.billing-toggle button.active,
.billing-toggle button.active:hover { background: var(--primary-color); color: var(--primary-ink); }

.plan-card {
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: var(--surface-color);
}
.plan-card.pro, .plan-card.yearly { background: var(--surface-color); }
.plan-card.pro { border-color: rgba(245, 166, 35, .38); }
.plan-card.yearly { border-color: rgba(61, 220, 151, .35); }
.plan-head { border-bottom: 1px solid var(--line); padding: 18px 20px 14px; }
.plan-title { font-size: 1.15rem; }
.plan-badge {
  font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .1em;
  padding: 3px 9px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--line); color: var(--text-muted);
}
/* ---- tier ladder ----------------------------------------------------------
   Pro, Ultra and Mega all shipped with the same `pro` class, so three of the
   four monthly cards were pixel-identical and the tiers read as one block.
   Each card now carries its own `tier-*` class, and the badge is what tells
   them apart — a small chip is already a coloured element here, so tinting it
   costs nothing, whereas four differently-coloured surfaces would put four
   saturated things in one row. Surfaces and prices stay identical. */
.plan-badge.tier-free { background: var(--surface-2); border-color: var(--line); color: var(--text-muted); }
.plan-badge.tier-pro { background: var(--primary-soft); border-color: rgba(245, 166, 35, .34); color: var(--primary-color); }
.plan-badge.tier-ultra { background: rgba(74, 155, 255, .13); border-color: rgba(74, 155, 255, .34); color: #6fb0ff; }
.plan-badge.tier-mega { background: rgba(169, 112, 255, .13); border-color: rgba(169, 112, 255, .34); color: #b98cff; }
.plan-badge.tier-enterprise { background: rgba(61, 220, 151, .12); border-color: rgba(61, 220, 151, .3); color: var(--success-color); }
/* Yearly cards keep the "you save" green on the badge whatever tier they are. */
.plan-badge.yearly { background: rgba(61, 220, 151, .12); border-color: rgba(61, 220, 151, .3); color: var(--success-color); }

/* The border picks up a trace of the same hue — enough to follow the column
   down, not enough to compete with the badge. */
.plan-card.tier-pro { border-color: rgba(245, 166, 35, .38); }
.plan-card.tier-ultra { border-color: rgba(74, 155, 255, .26); }
.plan-card.tier-mega { border-color: rgba(169, 112, 255, .26); }
.plan-card.yearly { border-color: rgba(61, 220, 151, .3); }
.plan-price { font-weight: 800; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
.plan-sub { color: var(--text-secondary); }
.compare-cell, .compare-row { border-color: var(--line); }
.compare-head { color: var(--text-muted); }
/* Below 760px the page's own stylesheet widens every compare row to 860px so it
   can be scrolled sideways — but the wrapper is `overflow: hidden`, so the plan
   columns past the first were simply cut off with no way to reach them. */
@media (max-width: 760px) {
  .compare-grid {
    overflow-x: auto; overscroll-behavior-x: contain;
    scrollbar-width: thin; scrollbar-color: var(--primary-color) var(--bg-2);
  }
}
.compare-icon.yes { color: var(--success-color); }
.compare-icon.no { color: var(--text-muted); }

/* ==========================================================================
   NOTIFICATIONS POPOVER

   css/notifications.css draws this with its own hexes and an underlined tab
   row. Here it becomes the same object as every other popover on the site: a
   surface panel with a hairline border, a segmented tab group that hugs its
   two tabs, and the standard empty state.
   ========================================================================== */
/* Anchored under the bell rather than pinned to the viewport edge, and placed
   with `right` rather than a translate: `transform` is left free to carry the
   open/close animation on its own, so the panel drops straight down from the
   bar instead of sliding in sideways. */
.notification-modal {
  top: calc(var(--nav-height) + 8px);
  left: auto;
  right: calc(max(0px, (100vw - min(var(--maxw), 100vw)) / 2) + 40px);
  transform: translateY(-14px);
  transform-origin: top center;
  width: 380px; max-height: 520px;
  padding: 6px;
  background: var(--surface-color);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  transition: transform .18s ease, opacity .18s ease;
}

/* Open: slide down into place. Closing runs the same transition backwards, so
   the panel lifts back up as it fades. */
.notification-modal-overlay.active .notification-modal {
  transform: translateY(0);
}

.notification-header {
  padding: 12px 12px 10px; border-bottom: 0;
}
.notification-header h3 { font-size: 1rem; font-weight: 700; letter-spacing: -0.01em; }
.notification-header .material-icons {
  display: grid; place-items: center; width: 30px; height: 30px;
  border-radius: 8px; color: var(--text-muted); font-size: 19px !important; padding: 0 !important;
  transition: background-color .14s ease, color .14s ease;
}
.notification-header .material-icons:hover { background: var(--surface-2); color: var(--text-primary); }

/* Hugs its two tabs instead of spanning the panel: the modal is a flex column,
   which stretches an inline-flex child to the full width. */
.notification-tabs {
  display: inline-flex; align-self: flex-start; width: auto;
  gap: 3px; padding: 4px; margin: 0 8px 8px;
  border: 1px solid var(--line); border-bottom: 1px solid var(--line);
  border-radius: 12px; background: var(--bg-2);
}
.notification-tab {
  padding: 6px 14px; border-radius: 8px;
  font-size: .85rem; font-weight: 600; color: var(--text-secondary);
  transition: background-color .14s ease, color .14s ease;
}
.notification-tab:hover { background: var(--surface-2); color: var(--text-primary); }
.notification-tab.active { background: var(--primary-color); color: var(--primary-ink); }
.notification-tab.active::after { display: none; }

.notification-content { padding: 0 6px 4px; min-height: 140px; }
.notification-content::-webkit-scrollbar { width: 8px; }
.notification-content::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 4px; }

.notification-item {
  gap: 11px; padding: 11px; border-bottom: 0; border-radius: var(--radius);
}
.notification-item:hover { background: var(--surface-2); }
.notification-icon {
  width: 32px; height: 32px; flex: none; border-radius: 10px;
  background: var(--primary-soft); color: var(--primary-color);
}
.notification-title { font-size: .9rem; font-weight: 600; }
.notification-message { font-size: .84rem; color: var(--text-secondary); }
.notification-time { font-size: .72rem; color: var(--text-muted); }

/* The popover's empty state is a line of text, not the full bordered card the
   page-level `.empty-state` draws. */
.notification-content .empty-state {
  display: block; padding: 44px 20px; min-height: 0;
  background: none; border: 0; border-radius: 0;
  color: var(--text-muted); font-size: .9rem;
}

.notification-footer { padding: 8px; border-top: 1px solid var(--line); }
.archive-all-btn {
  width: 100%; min-height: 34px; padding: 0 12px; border-radius: var(--radius-sm);
  background: transparent; border: 1px solid transparent; color: var(--text-secondary);
  font-family: inherit; font-size: .85rem; font-weight: 600; cursor: pointer;
  transition: background-color .14s ease, color .14s ease, border-color .14s ease;
}
.archive-all-btn:hover { background: var(--surface-2); border-color: var(--line); color: var(--text-primary); }

@media (max-width: 768px) {
  /* Full-screen sheet on a phone. The desktop rule fixes a 380px width and
     anchors the panel under the navbar; both have to go here or the sheet ends
     up a narrow column floating below the bar instead of covering the screen. */
  .notification-modal,
  .notification-modal-overlay.active .notification-modal {
    top: 0; left: 0; right: 0; bottom: 0;
    width: 100%; max-width: none; height: 100%; max-height: none;
    transform: none; border-radius: 0; border: 0; padding: 0;
  }
  .notification-header { padding: 16px; border-bottom: 1px solid var(--line); }
  /* Comfortable touch target for the close control. */
  .notification-header .material-icons { width: 40px; height: 40px; font-size: 22px !important; }
  .notification-tabs { margin: 12px 16px 10px; }
  .notification-content { flex: 1; padding: 0 10px; }
  .notification-footer { padding: 10px 16px; padding-bottom: max(10px, env(safe-area-inset-bottom)); }
}

/* ==========================================================================
   SETTINGS DIALOG
   ========================================================================== */
.settings-modal-overlay { background: rgba(4, 4, 6, .74); backdrop-filter: blur(4px); }
.settings-modal {
  background: var(--surface-color);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
}
.settings-header { padding: 18px 22px; border-bottom: 1px solid var(--line); }
.settings-header h2 { font-size: 1.15rem; font-weight: 700; letter-spacing: -0.02em; color: var(--text-primary); }
.settings-close-btn {
  width: 32px; height: 32px; border-radius: 8px; color: var(--text-muted);
}
.settings-close-btn:hover { background: var(--surface-2); color: var(--text-primary); }

.settings-sidebar { width: 196px; border-right: 1px solid var(--line); padding: 10px; gap: 2px; }
/* A rounded pill like the nav and the dropdowns, not a left accent bar. */
.settings-sidebar-item {
  gap: 11px; padding: 9px 12px; border-radius: var(--radius);
  color: var(--text-secondary); font-size: .9rem; font-weight: 500;
}
.settings-sidebar-item:hover { background: var(--surface-2); color: var(--text-primary); }
.settings-sidebar-item.active {
  background: var(--surface-2); color: var(--text-primary); font-weight: 600;
  border-left: 0; padding-left: 12px;
}
.settings-sidebar-item .material-icons { font-size: 19px; color: var(--text-muted); }
.settings-sidebar-item.active .material-icons { color: var(--primary-color); }

.settings-content { padding: 22px 24px; }
.settings-content::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 4px; }
.settings-section-title { color: var(--text-primary); font-size: 1.1rem; font-weight: 700; letter-spacing: -0.01em; }
/* Category markers are micro-labels like every other one on the site; they were
   the only ones painted gold. */
.settings-category {
  color: var(--text-muted); font-size: .68rem; letter-spacing: .1em; font-weight: 700;
  border-bottom: 1px solid var(--line);
}
.settings-row { border-color: var(--line); }
/* The label is swept into the shared micro-label rule in r6-ui, which paints
   every one of them --text-muted. Here that put the row's title and its
   explanation in exactly the same grey, so the pair read as one block of text.
   The title steps up; the description keeps the muted tone. */
.settings-row-label { color: var(--text-secondary); }
.settings-row-description { color: var(--text-muted); }
.settings-toggle input:checked + .settings-toggle-slider { background: var(--primary-color); }
.settings-action-btn {
  min-height: 36px; border-radius: var(--radius);
  background: var(--surface-color); border: 1px solid var(--line-strong); color: var(--text-primary);
  font-weight: 600;
}
.settings-action-btn:hover { background: var(--surface-2); }
.settings-action-btn.danger { border-color: rgba(255, 92, 122, .34); color: var(--error-color); background: transparent; }
.settings-action-btn.danger:hover { background: rgba(255, 92, 122, .1); }

/* ---- the settings dialog on a phone ---------------------------------------
   settings-modal.css already turns the sidebar into a tab strip below 640px,
   but the block above lands later in the cascade and was written without a
   media query — so `width: 196px` and the right border survived onto mobile and
   clipped the strip at "Privacy". Everything here restores the row layout and
   finishes it in the current form language. */
@media (max-width: 640px) {
  .settings-modal { border: 0; border-radius: 0; box-shadow: none; }
  .settings-header { padding: 16px; }

  .settings-sidebar {
    width: 100%; padding: 6px 8px 0; gap: 4px;
    border-right: 0; border-bottom: 1px solid var(--line);
    /* The three tabs fit at 390px, but a longer label or a bigger font must
       scroll rather than disappear off the edge. */
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .settings-sidebar::-webkit-scrollbar { display: none; }

  /* Underlined tabs, matching the profile tabs on the stats page — a row of
     pills inside a bordered strip reads as a box in a box. */
  .settings-sidebar-item {
    flex: 1 1 0; justify-content: center; min-width: 0;
    gap: 7px; padding: 10px 8px; border-radius: 0;
    background: none; border-bottom: 2px solid transparent;
    font-size: .82rem; white-space: nowrap;
  }
  .settings-sidebar-item .material-icons { font-size: 17px; }
  .settings-sidebar-item:hover { background: none; }
  .settings-sidebar-item.active {
    background: none; padding-left: 8px;
    border-bottom-color: var(--primary-color);
  }

  .settings-content { padding: 16px; }
  /* The toggle keeps its place on the right: the row is 340px wide here, which
     is room enough, and stacking it under the text made every row 120px tall. */
  .settings-row {
    flex-direction: row; align-items: center; gap: 14px;
  }
  .settings-row-info { margin-right: 0; min-width: 0; }
  .settings-row-description { font-size: .74rem; }
  .settings-toggle { flex: none; }
  /* Buttons are the one thing that cannot share the line — "Download" next to
     its own explanation leaves neither enough room. */
  .settings-row:has(.settings-action-btn) { flex-direction: column; align-items: stretch; }
  .settings-row:has(.settings-action-btn) .settings-action-btn { width: 100%; justify-content: center; }
}

/* ==========================================================================
   CONTACT
   ========================================================================== */
.contact-wrap { max-width: 680px; }
.contact-card { padding: 24px 26px 26px; }
.contact-card .form-group { margin-bottom: 18px; }
.contact-status { margin-bottom: 18px; }
.contact-status[hidden] { display: none; }
.notice-success { background: rgba(61, 220, 151, .1); border-color: rgba(61, 220, 151, .3); color: var(--success-color); }
.notice-success .material-icons { color: var(--success-color); }
.notice-error { background: rgba(255, 92, 122, .1); border-color: rgba(255, 92, 122, .3); color: var(--error-color); }
.notice-error .material-icons { color: var(--error-color); }
.spin { animation: spin .9s linear infinite; }

/* ==========================================================================
   AUTH PAGES — login, register, forgot / reset password, verify, change name

   css/auth.css ships its own `:root` (a lighter #1e1e1e surface, a bluish
   radial backdrop) and its own token names; r6-ui.css already wins the shared
   ones by load order, so what is left is the handful auth.css owns outright.
   ========================================================================== */
:root { --bg-color: var(--background-color); --surface-hover: var(--surface-2); }

.auth-header { top: 18px; left: 18px; }
.auth-header .btn-secondary {
  min-height: 36px; padding: 0 14px; border-radius: var(--radius);
  background: var(--surface-color); backdrop-filter: none;
  border: 1px solid var(--line); color: var(--text-secondary);
  font-size: .88rem; font-weight: 600; gap: 6px;
}
.auth-header .btn-secondary:hover { background: var(--surface-2); border-color: var(--line-strong); color: var(--text-primary); }

/* Flat page, one lit patch behind the card — the same cue the home hero uses.
   Scoped with :has(): `.app-background` is on <main id="app"> of EVERY SPA page,
   so an unscoped `padding: 48px 20px` here put 48px of dead space above every
   page header on the site and a second gutter inside the container's. */
.app-background:has(.auth-container) {
  background: none; position: relative; padding: 48px 20px;
}
.app-background:has(.auth-container)::before {
  content: ''; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 760px; height: 420px; max-width: 100%;
  background: radial-gradient(ellipse at center, rgba(245, 166, 35, .10), transparent 70%);
  pointer-events: none;
}
.auth-container { position: relative; max-width: 420px; }
.auth-card {
  background: var(--surface-color); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: none; padding: 30px 28px;
}
.auth-title { font-size: 1.6rem; font-weight: 800; letter-spacing: -0.03em; margin-bottom: 22px; }
.auth-card .form-input, .auth-card input {
  background: var(--input-bg); border: 1px solid var(--line-strong);
  border-radius: var(--radius); padding: 11px 14px;
}
.auth-card .btn-primary {
  width: 100%; min-height: 42px; border-radius: var(--radius);
  background: var(--primary-color); color: var(--primary-ink);
  border: 1px solid var(--primary-color); font-weight: 700;
}
.auth-card .btn-primary:hover { background: var(--primary-light); border-color: var(--primary-light); }
.alert { border-radius: var(--radius); border: 1px solid var(--line); }
.alert-error { background: rgba(255, 92, 122, .1); border-color: rgba(255, 92, 122, .3); color: var(--error-color); }
.alert-success { background: rgba(61, 220, 151, .1); border-color: rgba(61, 220, 151, .3); color: var(--success-color); }

/* ==========================================================================
   PLAYER STATS

   css/stats.css carries the page's structure (sidebar + main, the seasons and
   operators grids, the matches list) and that stays. What changes here is the
   finish: it was the one page still using gradients, coloured glows and drop
   shadows, which is exactly what this system does not do. Selectors are
   prefixed with `.stats-page` where stats.css prefixes, so these win on
   specificity rather than on order alone.
   ========================================================================== */
.stats-page .player-hero-card,
.stats-page .stats-card,
.stats-page .chart-card,
.stats-page .matches-card,
.stats-page .platforms-card,
.stats-page .operators-card,
.stats-page .seasons-grid-card,
.stats-page .season-stats-card,
.stats-page .season-peaks-card,
.stats-page .current-season-card {
  background: var(--surface-color);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: none;
}
.stats-page .card:hover { box-shadow: none; transform: none; border-color: var(--line-strong); }

/* The stats page is the one wide layout on the site (sidebar + main + a chart);
   `#main-content` was capping it at the 1200px measure everything else uses and
   squeezing all three columns. css/stats.css already asks for 1500px on its own
   `.page-container`; the outer wrapper has to allow it. */
body.stats-page #main-content { max-width: 1500px; }

/* ---- regressions from the shared vocabulary, undone on this page ----------
   These three generic rules are right everywhere else and wrong here:
   `.stat-item` boxes each counter, `.card-header` justifies its contents apart,
   and `.card-header-hint` is in the micro-label group. On the stats page the
   headline figures are plain columns, the card title sits next to its icon, and
   the hint is a sentence. */
.stats-page .hstat,
.stats-page .cs-stat,
.stats-page .peak-stat,
.stats-page .platform-stat,
.stats-page .stat-item {
  background: none; border: 0; border-radius: 0; padding: 0;
}
.stats-page .card-header { justify-content: flex-start; }
.stats-page .card-header-hint {
  margin-left: auto; text-transform: none; letter-spacing: normal;
  font-size: .8rem; font-weight: 400; color: var(--text-secondary);
}
.stats-page .card-header-hint strong { color: var(--primary-color); font-weight: 700; }
/* The headline label keeps the site's micro-label size but not its tracking —
   "TIME PLAYED" at .1em ran into the next column. */
.stats-page .hstat-label { letter-spacing: .06em; }
.stats-page .hstat-value { font-size: 1.3rem; font-weight: 700; color: var(--text-primary); }

.stats-page .player-hero-card .player-avatar,
.stats-page .player-avatar-placeholder {
  border: 1px solid var(--line-strong);
  border-radius: 16px;
  box-shadow: none;
}
.stats-page .player-level-badge {
  background: var(--primary-color); color: var(--primary-ink);
  border: 2px solid var(--surface-color); box-shadow: none;
}
.stats-page .player-username { letter-spacing: -0.03em; }

/* ---- profile tabs: Home / Matches / Seasons / Operators -------------------
   These sit INSIDE the player card, so a pill group inside it drew a second
   bordered row within a bordered row. They are a plain tab bar now, riding the
   hairline that separates them from the header above and marking the active tab
   with an underline — the shape a profile header wants. */
.stats-page .player-tabs-inline {
  width: 100%; margin: 18px 0 0; padding: 0 4px;
  border-top: 1px solid var(--line);
}
/* The 20px bottom margin stats.css gives the tab group made sense when the
   group was a floating pill; inside the hero card it just left a dead strip
   between the active underline and the card's bottom edge. The row ends where
   the card ends. */
.stats-page .stats-top-tabs .main-tabs,
.stats-page .main-tabs {
  width: 100%; background: none; border: 0; border-radius: 0;
  padding: 0; margin-bottom: 0; gap: 2px; box-shadow: none;
  justify-content: flex-start;
}
.stats-page .main-tabs-row { justify-content: flex-start; }
.stats-page .main-tab {
  flex: 0 1 auto; display: inline-flex; align-items: center; gap: 8px;
  padding: 14px 18px 12px; border: 0; border-radius: 0; background: transparent;
  border-bottom: 2px solid transparent; margin-bottom: 0;
  color: var(--text-muted); font-weight: 600; font-size: .95rem;
  transition: color .14s ease, border-color .14s ease;
}
.stats-page .main-tab .material-icons { font-size: 19px; }
.stats-page .main-tab:hover { background: none; color: var(--text-secondary); }
.stats-page .main-tab.active {
  background: none; box-shadow: none;
  color: var(--text-primary); border-bottom-color: var(--primary-color);
}
.stats-page .main-tab.active .material-icons { color: var(--primary-color); }

/* ---- mode tabs under the chart: Ranked / Casual / Unranked / … ------------
   `.tabs-container` was picking up the pill-group box from r6-ui as well as the
   `.tabs` inside it — a box in a box, and neither filled the column. The
   container is a plain full-width wrapper; the group inside it spans the same
   measure as the chart above and shares the row out between the modes. */
.stats-page .tabs-container {
  width: 100%; background: none; border: 0; border-radius: 0;
  padding: 0; margin: 0 0 20px; overflow: visible;
}
.stats-page .tabs-container > .tabs {
  display: flex; width: 100%; max-width: none;
  padding: 4px; gap: 2px;
  background: var(--surface-color); border: 1px solid var(--line); border-radius: 12px;
  overflow-x: auto; scrollbar-width: none;
}
.stats-page .tabs-container > .tabs > .tab {
  flex: 1 1 0; min-width: 0; justify-content: center; text-align: center;
  padding: 9px 10px; border-radius: 8px; font-size: .88rem;
  white-space: nowrap;
}

.stats-page .chart-container, .stats-page #rank-chart-container {
  background: var(--surface-color); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: none;
}
.stats-page .chart-container:hover { box-shadow: none; border-color: var(--line-strong); }
.stats-page #rank-chart-container::before { display: none; }

.stats-page .kd-peak, .stats-page .rank-placeholder.small { box-shadow: none; }
.stats-page .expand-btn, .stats-page .expand-btn:hover { box-shadow: none; }
.stats-page .expand-btn {
  background: var(--surface-color); border: 1px solid var(--line-strong);
  color: var(--text-primary); border-radius: var(--radius-sm); font-weight: 600;
}
.stats-page .expand-btn:hover { background: var(--surface-2); }

/* The full-page splash that covers the stats page while it boots. */
.overlay-content { box-shadow: none; background: none; }
.page-loading-overlay { background: var(--background-color); }

/* ---- the stats page on a phone -------------------------------------------
   Everything here is built for a 1500px three-column layout. At 390px the
   pieces that break are the ones that assume horizontal room: rows of equal
   flex columns squeeze until their labels collide, and the two-line blocks
   (season name over its sub-line, rank name over its timestamp) get clipped by
   whatever sits to their right. */
@media (max-width: 720px) {
  /* Four nested gutters — page, shell, layout, card — stacked up to 66px a side
     on a 360px phone, leaving the match rows about 220px to work with. The cards
     already draw their own edge, so the inner ones go and the content keeps the
     width. */
  .stats-page .page-container { padding-left: 0; padding-right: 0; }
  .stats-page .stats-layout { padding-left: 0; padding-right: 0; gap: 16px; }
  .stats-page .card-content { padding: 16px; }

  /* Mode tabs: scroll the row instead of squeezing seven labels into 356px,
     which is what made them overlap. */
  .stats-page .tabs-container > .tabs {
    gap: 3px; padding: 4px;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .stats-page .tabs-container > .tabs::-webkit-scrollbar { display: none; }
  .stats-page .tabs-container > .tabs > .tab {
    flex: 0 0 auto; padding: 9px 14px; font-size: .85rem;
  }

  /* Profile tabs: four across the card, evenly spread. stats.css hides the
     labels on a phone, which leaves four anonymous glyphs — Seasons and
     Operators are indistinguishable. The label comes back under the icon at
     micro-label size, which fits even at 360px. */
  .stats-page .player-tabs-inline { padding: 0; }
  .stats-page .main-tab {
    flex: 1 1 0; flex-direction: column; justify-content: center; gap: 3px;
    padding: 10px 2px 8px; min-width: 0;
  }
  .stats-page .main-tab .material-icons { font-size: 20px; }
  .stats-page .main-tab > span:not(.material-icons) {
    display: block; font-size: .66rem; letter-spacing: .04em;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
  }

  /* Headline figures: 2×2 instead of four columns, so "Time Played" keeps its
     label on one line. */
  .stats-page .player-headline-stats {
    display: grid !important; grid-template-columns: 1fr 1fr; gap: 0;
  }
  .stats-page .hstat {
    align-items: flex-start; padding: 11px 14px;
    border-right: 1px solid var(--line); border-bottom: 1px solid var(--line);
  }
  .stats-page .hstat:nth-child(2n) { border-right: none; }
  .stats-page .hstat:nth-last-child(-n+2) { border-bottom: none; }
  .stats-page .hstat-label { font-size: .6rem; letter-spacing: .06em; white-space: nowrap; }
  .stats-page .hstat-value { font-size: 1.15rem; }

  /* Peak ranks keep the desktop shape — icon, season, then KD/WR on the right,
     one row per season. Stacking the stats under the name (the first attempt at
     making the name fit) turned every season into a three-line block and the
     list into a wall. Instead the row is tightened: smaller icon, tighter gaps,
     narrower stat pair. That leaves the name column ~170px at 360px, which is
     more than "System Override" and its RP line need. */
  .stats-page .ps-row {
    grid-template-columns: 34px minmax(0, 1fr) auto;
    gap: 10px; padding: 11px 2px;
  }
  .stats-page .ps-rank { width: 34px; height: 34px; }
  .stats-page .ps-rank-icon, .stats-page .ps-rank-ph { width: 32px; height: 32px; }
  .stats-page .ps-season { font-size: .88rem; }
  .stats-page .ps-sub { font-size: .7rem; }
  .stats-page .ps-stats { gap: 12px; }
  .stats-page .ps-stat span { font-size: .56rem; }

  /* Match rows: the rank name and its RP were fighting for the same line and
     both wrapped. Name over timestamp on the left, RP over delta on the right. */
  .stats-page .matches-card .match-item {
    gap: 8px; padding: 11px 12px; align-items: center;
  }
  /* responsive.css adds a 12px right margin to the icon on top of the row gap;
     between that and the wide result tag the name column was left with about
     90px, one pixel short of "Platinum 1". Both go, and the name gets the slack. */
  .stats-page .matches-card .match-rank { margin-right: 0; flex: none; }
  .stats-page .matches-card .match-result-tag {
    width: 26px; height: 26px; min-width: 0; flex: none; font-size: .78rem;
  }
  .stats-page .match-info { flex: 1 1 auto; min-width: 0; }
  .stats-page .match-rank-name {
    font-size: .88rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .stats-page .match-timestamp { font-size: .72rem; white-space: nowrap; }
  .stats-page .match-mmr { text-align: right; flex: none; }
  .stats-page .match-mmr-value { font-size: .85rem; white-space: nowrap; }
  .stats-page .match-mmr-change { font-size: .75rem; }
  .stats-page .match-rank-icon, .stats-page .rank-placeholder { width: 30px; height: 30px; }

  /* Seasons and Operators are nine- and ten-column tables; on a phone they
     scroll inside their card. Without a visible bar there is nothing to say so,
     and the columns past "Max Rank" look like they simply do not exist — so the
     same gold bar the ban list uses. */
  .stats-page .seasons-grid,
  .stats-page .operators-grid {
    scrollbar-width: thin; scrollbar-color: var(--primary-color) transparent;
    padding-bottom: 6px;
  }
  .stats-page .seasons-grid::-webkit-scrollbar,
  .stats-page .operators-grid::-webkit-scrollbar { height: 6px; display: block; }
  .stats-page .seasons-grid::-webkit-scrollbar-track,
  .stats-page .operators-grid::-webkit-scrollbar-track {
    background: var(--surface-2); border-radius: 999px;
  }
  .stats-page .seasons-grid::-webkit-scrollbar-thumb,
  .stats-page .operators-grid::-webkit-scrollbar-thumb {
    background: var(--primary-color); border-radius: 999px;
  }

  /* Filter rows: full-width stacked controls beat three squeezed columns. */
  .stats-page .operators-filters,
  .stats-page .seasons-controls { display: grid; grid-template-columns: 1fr; gap: 12px; }
  .stats-page .operators-filters .filter,
  .stats-page .seasons-controls .filter { min-width: 0; width: 100%; }

  /* Card headers: the hint is a full sentence and belongs on its own line. */
  .stats-page .card-header { flex-wrap: wrap; }
  .stats-page .card-header-hint { margin-left: 0; flex-basis: 100%; margin-top: 4px; }
}

/* ==========================================================================
   SEARCH — one control, then tabbed result cards
   ========================================================================== */
.gs-searchwrap { position: relative; max-width: 760px; margin: 0 0 26px; }
/* The clear button only earns its space once there is something to clear. */
.gs-clear {
  flex: none; display: none; place-items: center; width: 32px; height: 32px;
  border: 0; border-radius: 8px; background: transparent; color: var(--text-muted); cursor: pointer;
}
.gs-clear:hover { background: var(--surface-2); color: var(--text-primary); }
.gs-clear .material-icons { font-size: 18px; }

.gs-resulthead { align-items: baseline; margin-bottom: 14px; }
.gs-card .ent-id { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.ent-ic-bare { background: none; object-fit: contain; }
.gs-details { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
/* Weapons and skins have no extra lines to show, so the block would render as a
   rule with nothing under it. */
.gs-details:empty { display: none; }
.gs-line { margin: 3px 0; color: var(--text-secondary); font-size: .86rem; }
.gs-details :first-child { margin-top: 0; }

.gs-explore { margin: 40px 0 24px; text-align: center; }
.gs-explore-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 14px; }

/* ==========================================================================
   BANS — a div-grid "table" plus a history chart
   ========================================================================== */
.controls { margin-bottom: 16px; }
.filters { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; }
.filters-split { justify-content: space-between; align-items: flex-end; }
.filter { display: flex; flex-direction: column; gap: 6px; min-width: 168px; }
.filter > label { margin: 0; }
.filter-action { justify-content: flex-end; min-width: 0; }

/* public/style.css scopes its own bans rules with `#bans-content`, which
   outranks the plain class selectors above. Two of its values were fighting
   this layout: `align-items: center` on the group left the label-less Refresh
   button floating mid-height instead of sitting on the same baseline as the
   three controls, and the same property on each filter centred the label over
   its control. Both read left-aligned and bottom-aligned now. */
#bans-content .filters { align-items: flex-end; }
#bans-content .filter {
  align-items: flex-start; padding: 0; border-radius: 0;
}
#bans-content .filter > label { margin-right: 0; }
/* The button carries no label above it, so it aligns by its own bottom edge. */
#bans-content .filter-action .btn { min-height: 40px; }

/* The picker that opens .filter-dropdown — same skin as any other control. */
.filter-select-display {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  min-height: 40px; padding: 0 8px 0 13px; border-radius: var(--radius);
  background: var(--surface-color); border: 1px solid var(--line-strong); color: var(--text-primary);
  font-size: .92rem; font-weight: 600; cursor: pointer;
  transition: border-color .16s ease, background-color .16s ease;
}
.filter-select-display:hover { background: var(--surface-2); border-color: #454550; }
.filter-select-display.active { border-color: var(--primary-color); box-shadow: 0 0 0 3px var(--primary-soft); }
.filter-select-display .value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filter-select-display .dropdown-arrow { color: var(--text-muted); font-size: 20px; transition: transform .2s ease; flex: none; }

/* `overscroll-behavior: contain` is what makes the list actually scrollable:
   the option lists are long (the rank filter has 38 entries) and without it the
   wheel event chained straight through to the page, so the popover looked
   frozen while the page moved underneath. */
.filter-dropdown {
  position: absolute; z-index: 950; max-height: 320px;
  overflow-y: auto; overscroll-behavior: contain;
  padding: 5px; border-radius: 12px;
  background: var(--surface-color); border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-lg);
  scrollbar-width: thin; scrollbar-color: var(--primary-color) var(--bg-2);
}
.filter-dropdown::-webkit-scrollbar { width: 10px; }
.filter-dropdown::-webkit-scrollbar-track { background: var(--bg-2); }
.filter-dropdown::-webkit-scrollbar-thumb {
  background: var(--primary-color); border-radius: 999px; border: 3px solid var(--bg-2);
}
.filter-dropdown-option {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 11px; border-radius: var(--radius-sm); cursor: pointer;
  font-size: .9rem; font-weight: 600; color: var(--text-secondary); white-space: nowrap;
}
.filter-dropdown-option:hover { background: var(--surface-2); color: var(--text-primary); }
.filter-dropdown-option.selected { color: var(--primary-color); background: var(--primary-soft); }
.filter-dropdown-option .material-icons { font-size: 17px; }

/* Timeframe picker — the reference's segmented group. */
.timeframes {
  display: inline-flex; gap: 3px; padding: 4px; border-radius: 12px;
  background: var(--surface-color); border: 1px solid var(--line); flex-wrap: wrap;
}
.timeframe {
  padding: 7px 14px; border: 0; border-radius: 8px; background: transparent;
  color: var(--text-secondary); font-family: inherit; font-weight: 600; font-size: .85rem;
  cursor: pointer; transition: background-color .14s ease, color .14s ease;
}
.timeframe:hover { background: var(--surface-2); color: var(--text-primary); }
.timeframe.active, .timeframe.active:hover { background: var(--primary-color); color: var(--primary-ink); }

/* The "table" is a stack of CSS-grid rows, not a <table>; each row carries its
   own column template in `--cols` so the header and body always agree. */
.data-table {
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: var(--surface-color); overflow: hidden; margin-bottom: 24px;
}
.data-table:last-child { margin-bottom: 0; }
.data-table .grid { display: grid; grid-template-columns: var(--cols, 1fr); gap: 12px; margin: 0; }
.table-header {
  padding: 14px 16px 11px; border-bottom: 1px solid var(--line);
  background: var(--surface-color);
}
.table-row {
  padding: 12px 16px; border-bottom: 1px solid var(--line);
  align-items: center; transition: background-color .12s ease;
}
.table-row:last-child { border-bottom: 0; }
.table-row:hover { background: var(--surface-2); }
.table-row.is-clickable { cursor: pointer; }
.cell {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  font-size: .9rem; font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cell.is-up { color: var(--success-color); font-weight: 700; }
.cell.is-down { color: var(--error-color); font-weight: 700; }
.cell.is-flat { color: var(--text-muted); }
/* A year row is a heading for the months it opens, so it carries the weight;
   the months sit inset and quieter underneath it. */
.table-row.is-year .cell:first-child { font-weight: 700; }
.table-row.is-year.is-open { background: var(--surface-2); }
.table-row.is-month { background: rgba(255, 255, 255, .012); }
.table-row.is-month .cell:first-child { padding-left: 27px; color: var(--text-secondary); }
.table-body[hidden] { display: none; }
.cell .avatar { width: 30px; height: 30px; border-radius: 8px; object-fit: cover; flex: none; }
.cell .rank-ic { width: 30px; height: 30px; object-fit: contain; flex: none; }
.cell .platform-icon { width: 16px; height: 16px; flex: none; opacity: .7; }
.row-caret { font-size: 19px; color: var(--text-muted); flex: none; }

.chart-box { position: relative; width: 100%; height: 320px; }
.chart-note { margin-top: 10px; font-size: .78rem; color: var(--text-muted); }

/* The bans page stacks two sections; without this the chart card, the month
   grid and the recent list all carried their own bottom margin and the page
   drifted a long way from the footer. */
#historySection { margin-bottom: 34px; }
#historySection .card { margin-bottom: 18px; }
#recentSection .data-table { margin-bottom: 0; }
#recentSection { margin-bottom: 8px; }

/* css/stats.css ships a blanket `.table-body { max-height: 350px; overflow-y:
   auto }` for its own season table, and index.html loads that sheet for every
   SPA route. The month grid must not inherit it — a year opens into its months
   in place and needs to grow. */
#bans-content .table-body { max-height: none; overflow: visible; }

/* ---- bans on a phone -----------------------------------------------------
   Both grids were built for a desktop column. At 390px the month grid squeezed
   four numeric columns into the width and the latest-bans list turned into a
   580px-wide horizontal scroller, so Date and Rank sat off-screen. Each drops
   the columns that carry the least on a phone and fits the viewport instead.
   `!important` is needed for the second one: css/responsive.css pins those
   column widths that way. */
@media (max-width: 640px) {
  /* Month grid: the absolute change goes, the percentage stays — it is the one
     that reads without a reference figure next to it. */
  #bansHistoryGrid .table-header > :nth-child(3),
  #bansHistoryGrid .cell:nth-child(3) { display: none; }
  #bansHistoryGrid .grid { --cols: 1.1fr 1fr 1fr !important; gap: 8px; }
  #bansHistoryGrid .table-header,
  #bansHistoryGrid .table-row { padding: 11px 12px; }
  #bansHistoryGrid .cell { font-size: .82rem; }
  .table-row.is-month .cell:first-child { padding-left: 22px; }

  /* Latest bans: level and rank go, the row fits and nothing scrolls sideways.
     The 30px avatar goes too — it is a generic placeholder for most records and
     it was eating the room the name needs; the platform glyph stays, since that
     is the part of the cell that actually says something. */
  #recentSection .data-table { overflow-x: hidden !important; }
  #recentSection .table-body { width: 100% !important; min-width: 0 !important; }
  #recentSection .table-header,
  #recentSection .table-row {
    grid-template-columns: minmax(0, 1.45fr) minmax(0, 1.2fr) minmax(0, .9fr) !important;
    width: auto !important; min-width: 0 !important; gap: 6px !important;
    padding-left: 10px !important; padding-right: 10px !important;
  }
  #recentSection .cell { padding-left: 4px !important; padding-right: 4px !important; }
  #recentSection .table-header > :nth-child(2),
  #recentSection .table-header > :nth-child(5),
  #recentSection .cell:nth-child(2),
  #recentSection .cell:nth-child(5) { display: none !important; }
  #recentSection .cell { font-size: .78rem; }
  /* `!important` because css/responsive.css forces every image in these cells
     to `display: block` at this breakpoint. */
  #recentSection .cell .avatar { display: none !important; }
  #recentSection .avatar-name { min-width: 0; gap: 6px; }
  #recentSection .avatar-name .name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
}

/* The latest-bans list keeps a fixed frame and scrolls inside it, so 100 rows
   don't push the rest of the page miles down. Roughly twice the old 350px cap.
   Above the mobile breakpoint only: below it css/responsive.css turns the same
   element into a `width: max-content` horizontal scroller, and a second scroll
   axis inside that is unusable. */
@media (min-width: 769px) {
  #recentSection .table-body {
    max-height: 620px;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    /* `stable` keeps the channel reserved, so the rows do not jump sideways
       when the bar appears and the last column never sits under it. */
    scrollbar-gutter: stable;
    scrollbar-width: thin;
    scrollbar-color: var(--primary-color) var(--bg-2);
  }
  /* Chrome honours the two standard properties above and ignores this block;
     it is here for Safari, which has no `scrollbar-color`. */
  #recentSection .table-body::-webkit-scrollbar { width: 10px; }
  #recentSection .table-body::-webkit-scrollbar-track { background: var(--bg-2); }
  #recentSection .table-body::-webkit-scrollbar-thumb {
    background: var(--primary-color);
    border-radius: 999px;
    border: 3px solid var(--bg-2);
  }
  #recentSection .table-body::-webkit-scrollbar-thumb:hover { background: var(--primary-light); }
}

/* ==========================================================================
   OPERATOR DETAIL — server-rendered at /operators/:slug

   This page is built by lib/views/operators-detail.js, not by the SPA, so it
   has no `.page-content`; `.opd` is its container.
   ========================================================================== */
.opd { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 24px 20px 8px; }

.opd-crumbs {
  display: flex; align-items: center; gap: 6px;
  margin-bottom: 12px; color: var(--text-secondary); font-size: .86rem;
}
.opd-crumbs a { color: var(--primary-color); font-weight: 600; text-decoration: none; }
.opd-crumbs a:hover { color: var(--primary-light); }
.opd-crumbs .material-icons { font-size: 18px; color: var(--text-muted); }

/* No accent spine here either. The system dropped it from the catalog cards on
   the grounds that a card already naming its side in a chip does not need a
   coloured bar as well, and the same reasoning applies to the hero. --side is
   kept because the stat pips read it. */
.opd-hero {
  --side: var(--line-strong);
  position: relative; display: flex; gap: 26px; flex-wrap: wrap;
  align-items: center; padding: 26px; margin-bottom: 32px;
}
.opd-figure {
  flex: none; display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.opd-icon {
  display: block; width: 116px; height: 116px;
  border-radius: var(--radius-lg); object-fit: cover;
  background: var(--surface-2); border: 1px solid var(--line);
}
.opd-icon-ph { display: grid; place-items: center; color: var(--text-muted); }
.opd-icon-ph .material-icons { font-size: 40px; }
.opd-side { width: 100%; justify-content: center; text-transform: capitalize; }

/* min-width: 0 is what keeps a long operator or unit name from forcing the
   flex row wider than the card on a phone. */
.opd-id { flex: 1 1 260px; min-width: 0; }
.opd-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 12px; }
.opd-id h1 {
  margin: 0 0 6px; font-size: clamp(1.9rem, 4vw, 2.6rem);
  font-style: italic; font-weight: 800; letter-spacing: -0.03em; line-height: 1.05;
}
.opd-real {
  margin: 0; font-size: 1rem; color: var(--text-secondary);
  overflow-wrap: anywhere;
}
.opd-chips { margin: 14px 0 0; }
.opd-chips .chip { display: inline-flex; align-items: center; gap: 5px; }
.opd-chips .material-icons { font-size: 14px; }

/* Roles sit in the hero rather than buried in a card further down: they are
   how players actually pick an operator, so they belong next to the name. */
.opd-roles { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 16px; }

/* ---- speed / armour ------------------------------------------------------
   Siege rates both 1-3, and every player reads them as three pips. Printing
   "3 / 1" as text — which is what this page used to do — throws away the one
   comparison the numbers exist for. */
/* The meters are their own column of the hero on a wide screen and a full-width
   row underneath once the hero wraps. `min(150px, 100%)` is what lets the two
   tracks collapse instead of forcing the grid wider than the phone. */
.opd-meters {
  flex: 0 1 260px; min-width: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr)); gap: 10px;
}
.opd-meter {
  min-width: 0; padding: 13px 15px; border-radius: var(--radius);
  background: var(--surface-2); border: 1px solid var(--line);
}
.opd-meter-label {
  color: var(--text-muted); font-size: .68rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
}
.opd-meter-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.opd-meter-value { font-size: 1.05rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.opd-meter-pips { display: flex; gap: 4px; margin-top: 9px; }
.opd-pip { flex: 1; height: 5px; border-radius: 999px; background: var(--surface-3); }
.opd-pip.is-on { background: var(--side, var(--primary-color)); }

/* ---- body: loadout on the left, dossier on the right ---------------------
   The old page ran the weapons full width and then dropped into a two-column
   split, so the eye had to reset halfway down. One stable column pair holds
   from the hero to the end of the loadout instead. */
/* ---- body: loadout on the left, dossier on the right ---------------------
   The old page ran the weapons full width and then dropped into a two-column
   split, so the eye had to reset halfway down. One stable column pair holds
   from the hero to the end of the loadout instead. */
.opd-body { display: grid; grid-template-columns: 1fr; gap: 40px; }
.opd-layout { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 28px; align-items: start; }
.opd-main { min-width: 0; display: grid; gap: 28px; }
.opd-aside { min-width: 0; display: grid; gap: 16px; position: sticky; top: 84px; }

.opd-section-head {
  display: flex; align-items: center; gap: 12px; margin-bottom: 24px;
}
.opd-section-head > .material-icons {
  width: 40px; height: 40px; flex: none; display: grid; place-items: center;
  color: var(--primary-color); background: var(--primary-soft);
  border: 1px solid rgba(245, 166, 35, .25); border-radius: var(--radius);
  font-size: 21px;
}
.opd-section-head h2 {
  margin: 0; color: var(--text-primary); font-size: 1.35rem;
  font-weight: 700; letter-spacing: -.025em;
}
.opd-section-head p {
  margin: 3px 0 0; color: var(--text-muted); font-size: .82rem;
}

.opd-h3 {
  margin: 0 0 12px; font-size: .68rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .1em; color: var(--text-muted);
}
.opd-h3-gap { margin-top: 26px; }
.opd-note { padding: 24px; text-align: center; color: var(--text-secondary); }
.opd-lead { margin: 0; font-size: .92rem; line-height: 1.65; color: var(--text-secondary); }

.opd-weapon-grid { margin: 0; }
.opd-weapon { min-width: 0; cursor: default; }
.opd-weapon .card-content { padding: 18px; }
.opd-weapon .wpn-shot { position: relative; height: 92px; }
.opd-weapon-placeholder { display: none; color: var(--text-muted); font-size: 30px; }
.opd-weapon .wpn-shot.is-empty .opd-weapon-placeholder { display: block; }
.opd-weapon-stats {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px; margin: 16px 0 0; padding: 0;
  border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
  background: var(--line);
}
.opd-weapon-stats > div {
  min-width: 0; padding: 10px 8px; background: var(--surface-2); text-align: center;
}
.opd-weapon-stats dt {
  color: var(--text-muted); font-size: .58rem; font-weight: 700;
  letter-spacing: .08em; line-height: 1.2; text-transform: uppercase;
}
.opd-weapon-stats dd {
  margin: 4px 0 0; color: var(--text-primary); font-size: .82rem;
  font-weight: 700; line-height: 1.2; font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* The section head's trailing link is a back-link pointing the other way. */
.opd-see-all { margin-bottom: 0; }

/* ---- aside: the dossier --------------------------------------------------
   Reuses .spec-grid / .spec-row, the same spec sheet the operator dialog on
   /operators uses, so clicking through from the catalog lands on a layout the
   player already knows. One column here, not two. */
.opd-aside-card { padding: 20px; }
.opd-aside-card .spec-grid { grid-template-columns: 1fr; }
.opd-aside-head {
  display: block; margin-bottom: 12px; padding-bottom: 10px;
  border-bottom: 1px solid var(--line); color: var(--text-primary);
  font-size: .7rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
}
.opd-aside-card .spec-row:last-child { border-bottom: 0; padding-bottom: 0; }

/* Related operators reuse the catalogue-card vocabulary but keep a strict
   vertical rhythm: the identity block gets a two-line allowance and the badge
   row is anchored to the bottom, so every card has exactly the same height. */
.opd-related-title {
  display: flex; align-items: center; justify-content: space-between;
  gap: 18px; margin-bottom: 16px;
}
.opd-related-title h2 {
  margin: 0; font-size: 1.25rem; font-weight: 700; letter-spacing: -.02em;
}
.opd-see-all {
  display: inline-flex; align-items: center; gap: 3px; flex: none;
  color: var(--text-secondary); font-size: .84rem; font-weight: 600;
}
.opd-see-all:hover { color: var(--text-primary); }
.opd-see-all .material-icons { font-size: 17px; }

.opd-related {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  grid-auto-rows: 166px; gap: 14px;
}
.operator-card-ssr {
  color: inherit; text-decoration: none; display: flex;
  min-width: 0; height: 166px;
}
.operator-card-ssr:hover { color: inherit; }
.operator-card-ssr .opd-rel-body {
  display: flex; flex-direction: column; width: 100%; height: 100%;
  min-width: 0; padding: 20px;
}
.opd-rel-head { align-items: flex-start; }
.opd-rel-ic { width: 48px; height: 48px; }
.opd-rel-name { line-height: 1.25; }
.opd-rel-sub {
  min-height: 2.7em; margin-top: 2px; line-height: 1.35;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; overflow-wrap: anywhere;
}
.opd-rel-chips {
  margin-top: auto; padding-top: 12px; flex-wrap: nowrap;
  align-items: center; overflow: hidden;
}
.opd-rel-chips .chip { min-width: 0; white-space: nowrap; }
.opd-rel-country .material-icons { flex: none; font-size: 14px; }

@media (max-width: 1100px) {
  .opd-related { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (max-width: 860px) {
  .opd-related { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
  .opd-related { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .operator-card-ssr .opd-rel-body { padding: 16px; }
  .opd-rel-head { gap: 11px; }
}

@media (max-width: 390px) {
  .opd-related { grid-template-columns: 1fr; }
}

@media (max-width: 1040px) {
  /* Below this the dossier column is too narrow to hold a label and a value on
     one line, so it goes under the loadout and spreads out again. */
  .opd-layout { grid-template-columns: 1fr; }
  .opd-aside {
    position: static;
    grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  }
  .opd-aside-card .spec-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---- phones --------------------------------------------------------------
   Every track floor on this page is wrapped in min(Npx, 100%). A bare
   `minmax(240px, 1fr)` never shrinks below 240px, so on a 320-360px screen —
   once the page and card padding are taken out — the grid was wider than its
   container and the right-hand edge of the cards ran off the display. */
@media (max-width: 720px) {
  .opd { padding: 18px 16px 8px; }
  .opd-hero { padding: 20px; gap: 20px; }
  .opd-icon { width: 88px; height: 88px; }
  .opd-meters { flex-basis: 100%; }
  .opd-aside-card .spec-grid { grid-template-columns: 1fr; }

  /* Scoped to .opd on purpose: .weapon-grid and .entity-grid belong to the
     catalog pages too, and loosening their floors globally would shrink the
     cards on /weapons and /operators as a side effect. */
  .opd .weapon-grid,
  .opd .entity-grid {
    grid-template-columns: repeat(auto-fill, minmax(min(158px, 100%), 1fr));
  }
}

@media (max-width: 420px) {
  /* One column, and the identity block goes under the portrait rather than
     beside it — at this width an 88px icon plus a name leaves nothing for
     either. */
  .opd-hero { flex-direction: column; align-items: flex-start; }
  .opd-id { flex-basis: auto; width: 100%; }
  .opd-meters { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .opd .weapon-grid,
  .opd .entity-grid { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .opd-hero { padding: 22px; gap: 20px; }
  .opd-icon { width: 96px; height: 96px; }
  .opd-id { min-width: 0; }
  .opd-figure { flex-direction: row; align-items: center; gap: 16px; }
  .opd-side { width: auto; }
  .opd-aside-card .spec-grid { grid-template-columns: 1fr; }
}

/* ---- detail dialog: a two-column spec sheet ---- */
.dialog-backdrop {
  position: fixed; inset: 0; z-index: 1200; display: grid; place-items: center; padding: 20px;
  background: rgba(4, 4, 6, .74); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
}
.dialog-backdrop .dialog { width: 100%; max-width: 640px; max-height: 90vh; overflow: auto; }
.dialog-title { display: block; }

/* A dialog that opens with a photograph: the image is the panel's top edge, so
   the panel drops its own top padding and the image bleeds to the corners. */
.dialog-with-figure { padding-top: 0; overflow: hidden; }
.dialog-figure {
  margin: 0 -22px 18px; height: 200px; overflow: hidden;
  background: var(--surface-2); border-bottom: 1px solid var(--line);
}
.dialog-figure img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 640px) {
  .dialog-figure { height: 150px; }
}

.spec-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px 18px; }
.spec-row {
  display: flex; align-items: center; gap: 10px; padding: 9px 0;
  border-bottom: 1px solid var(--line); font-size: .9rem; min-width: 0;
}
.spec-row .material-icons { font-size: 17px; color: var(--text-muted); flex: none; }
.spec-l {
  flex: none; font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .1em; color: var(--text-muted); min-width: 84px;
}
.spec-v {
  margin-left: auto; text-align: right; font-weight: 600; color: var(--text-primary);
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
.spec-v small { color: var(--text-muted); font-weight: 500; }
.spec-block { margin-top: 20px; }
.spec-block-l {
  display: block; margin-bottom: 8px;
  font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: var(--text-muted);
}

@media (max-width: 640px) {
  .spec-grid { grid-template-columns: 1fr; }
  .hero { padding-block: 44px 32px; }
  /* Everything in the search box shrinks to its icon so the field itself keeps
     the room: platform labels go, and so does the button's word. */
  .hero-search { gap: 4px; padding: 6px; }
  .platform-tab { padding: 0 9px; gap: 0; }
  .platform-tab span { display: none; }
  .hs-sep { margin: 6px 0; }
  .hero-search input { font-size: .95rem; }
  .hs-go { padding: 0 13px; }
  .hs-go .hs-go-label { display: none; }
  .hs-go .material-icons { margin-left: 0; }
  /* Comfortable touch target: 30px is below what a thumb reliably hits. */
  .home-alert-close { width: 38px; height: 38px; right: 8px; }
  .home-alert-inner { padding-right: 52px; }
  .rule-head { gap: 12px; flex-wrap: wrap; }
  .rule-head h2 { font-size: 1.1rem; }
  .tool-card .card-content { padding: 20px; }
  .cta-panel { padding: 22px; }
  .cta-panel .cta-btn { width: 100%; }
}

/* ==========================================================================
   R6 SERVER STATUS — status.css builds this page out of glassy translucent
   panels with drop shadows and a cyan gradient CTA. Everything below re-cuts
   the same markup in the site's form language: flat surfaces, hairline
   borders, one saturated thing per group. The class names are all namespaced
   r6-status-*, so nothing here can leak onto another page.
   ========================================================================== */
.r6-status-page {
  padding: 0 0 8px;
  min-height: 0;
  --r6-surface: var(--surface-color);
  --r6-border: var(--line);
  --r6-text: var(--text-primary);
  --r6-muted: var(--text-secondary);
  --r6-accent: var(--primary-color);
}
.r6-status-section-inner { max-width: none; margin: 0; }
/* The hero — the question, the verdict and the report button — stays the
   centred column it has always been. It is the one thing people come here for,
   so it reads as a statement rather than as the first row of a dashboard; the
   sections below it are full-width like every other page. */
.r6-status-hero-inner { max-width: 720px; margin: 0 auto; }

.r6-status-title {
  text-align: center;
  font-style: italic; font-weight: 800;
  font-size: clamp(1.75rem, 3.6vw, 2.3rem);
  letter-spacing: -0.03em;
  margin: 8px 0 22px;
}

/* ---- the headline state card ---- */
.r6-status-summary {
  margin: 0 auto 16px; max-width: 720px;
  background: var(--surface-color); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: none;
}
.r6-status-summary-main { padding: 22px; }
/* Round chip, round refresh, pill button — the shapes the card had before. The
   palette is the only thing that changes: flat surfaces and a hairline rule
   instead of the translucent white washes. */
.r6-status-summary-icon {
  width: 36px; height: 36px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--line);
  color: var(--text-secondary); font-size: 21px;
}
.r6-status-summary-title { font-size: 1.35rem; font-weight: 800; letter-spacing: -0.02em; }
.r6-status-summary-subtitle { font-size: .88rem; color: var(--text-muted); }
.r6-status-summary-refresh {
  width: 36px; height: 36px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--line-strong);
  color: var(--text-secondary);
  transition: background-color .16s ease, color .16s ease;
}
.r6-status-summary-refresh:hover { background: var(--surface-3); color: var(--text-primary); }

/* The actions row lives inside the card's own padding, so its rule lines up
   with the title above it — splitting the inset in two (card padding plus a
   second horizontal padding here) is what left the divider and the button
   floating short of everything else. */
.r6-status-summary-actions {
  margin-top: 18px; padding: 16px 0 0;
  border-top: 1px solid var(--line);
}
.r6-status-summary-ask { font-size: .88rem; color: var(--text-secondary); }
.r6-status-report-btn {
  min-height: 38px; padding: 0 20px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--line-strong);
  backdrop-filter: none; color: var(--text-primary);
  font-family: inherit; font-weight: 600; font-size: .9rem;
  transition: background-color .16s ease, border-color .16s ease;
}
.r6-status-report-btn:hover { background: var(--surface-3); border-color: var(--text-muted); }

.r6-status-disclaimer {
  max-width: 640px; margin: 0 auto; text-align: center;
  font-size: .8rem; line-height: 1.65;
  color: var(--text-muted);
}

/* ---- section rhythm ---- */
.r6-status-chart-section { margin-top: 38px; }
.r6-status-platforms { margin-top: 38px; }
.r6-status-section-title {
  margin: 0 0 14px; font-size: 1.15rem; font-weight: 700; letter-spacing: -0.02em;
  color: var(--text-primary);
}

/* ---- range picker: one segmented group, the active segment is the only
   saturated thing in it ---- */
.r6-status-range-selector {
  display: inline-flex; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
  gap: 2px; margin-bottom: 14px; max-width: 100%;
  padding: 4px; background: var(--surface-color);
  border: 1px solid var(--line); border-radius: 12px;
}
.r6-status-range-selector::-webkit-scrollbar { display: none; }
.r6-status-range-btn {
  flex: 0 0 auto;
  border: 0; background: transparent; color: var(--text-muted);
  border-radius: 8px; padding: 8px 14px;
  font-family: inherit; font-weight: 600; font-size: .88rem; white-space: nowrap;
  transition: background-color .14s ease, color .14s ease;
}
.r6-status-range-btn:hover { background: var(--surface-2); color: var(--text-primary); }
.r6-status-range-btn.active {
  background: var(--primary-color); border-color: transparent; color: var(--primary-ink);
}

.r6-status-chart-card {
  background: var(--surface-color); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: none; padding: 18px;
}
.r6-status-chart-note { font-size: .82rem; color: var(--text-muted); }
.r6-status-tooltip {
  background: var(--surface-2); border: 1px solid var(--line-strong);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
}
.r6-status-tooltip-title { font-weight: 700; font-size: .82rem; }
.r6-status-tooltip-line { font-weight: 600; font-size: .76rem; color: var(--text-muted); }
.r6-status-tooltip-body { font-size: .76rem; color: var(--text-secondary); }

/* ---- the globe hand-off ---- */
.r6-status-globe-cta {
  margin-top: 24px; padding: 22px;
  background: var(--surface-color); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: none;
}
.r6-status-globe-cta-text h3 {
  font-size: 1.05rem; font-weight: 700; letter-spacing: -0.02em; margin: 0 0 6px;
}
.r6-status-globe-cta-text p { font-size: .88rem; color: var(--text-secondary); }
.r6-status-globe-btn {
  min-height: 42px; padding: 0 20px; border-radius: var(--radius);
  background: var(--primary-color); color: var(--primary-ink);
  font-weight: 600; font-size: .92rem; box-shadow: none;
  transition: background-color .16s ease;
}
.r6-status-globe-btn:hover {
  transform: none; box-shadow: none;
  background: var(--primary-light); color: var(--primary-ink);
}
.r6-status-globe-btn .material-icons { font-size: 19px; }

/* ---- per-platform cards ---- */
.r6-status-grid { gap: 16px; }
.r6-status-card {
  background: var(--surface-color); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: none; padding: 18px;
}
.r6-status-card-title { font-size: .98rem; font-weight: 700; letter-spacing: -0.01em; }
.r6-status-card-title .material-icons { color: var(--primary-color); font-size: 20px; }
.r6-status-chip {
  padding: 5px 10px; border-radius: 999px;
  font-weight: 600; font-size: .72rem; letter-spacing: .02em;
  background: var(--surface-2); border: 1px solid var(--line-strong); color: var(--text-secondary);
}
.r6-status-chip.ok {
  background: rgba(61, 220, 151, .12); border-color: rgba(61, 220, 151, .3); color: var(--success-color);
}
.r6-status-chip.warn {
  background: var(--primary-soft); border-color: rgba(245, 166, 35, .32); color: var(--primary-color);
}
.r6-status-chip.down {
  background: rgba(255, 92, 122, .12); border-color: rgba(255, 92, 122, .3); color: var(--error-color);
}
.r6-status-services { gap: 6px; }
.r6-status-service-row {
  padding: 10px 12px; border-radius: var(--radius-sm);
  background: var(--surface-2); border: 1px solid var(--line);
}
.r6-status-service-name { font-size: .85rem; font-weight: 500; color: var(--text-secondary); }
.r6-status-service-value { font-size: .85rem; font-weight: 600; color: var(--text-muted); }
.r6-status-service-status { font-size: .82rem; font-weight: 600; }
.r6-status-service-status.ok { color: var(--success-color); }
.r6-status-service-status.warn { color: var(--primary-color); }
.r6-status-service-status.down { color: var(--error-color); }

/* ---- report dialog: same shell as the settings dialog ---- */
.r6-status-modal-backdrop { background: rgba(0, 0, 0, .62); backdrop-filter: blur(2px); }
.r6-status-modal-card {
  background: var(--surface-color); border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: 22px;
}
.r6-status-modal-title { font-size: 1.05rem; font-weight: 700; letter-spacing: -0.02em; }
.r6-status-modal-close {
  width: 32px; height: 32px; border-radius: var(--radius-sm); padding: 0;
  display: grid; place-items: center; font-size: 20px;
  color: var(--text-muted); transition: background-color .14s ease, color .14s ease;
}
.r6-status-modal-close:hover { background: var(--surface-2); color: var(--text-primary); }
.r6-status-modal-text { font-size: .88rem; color: var(--text-secondary); }
.r6-status-modal-consent {
  border-radius: var(--radius); background: var(--surface-2); border: 1px solid var(--line);
  font-size: .8rem; line-height: 1.55; padding: 12px 14px;
}
.r6-status-modal-btn {
  min-height: 40px; padding: 0 18px; border-radius: var(--radius);
  background: var(--surface-2); border: 1px solid var(--line-strong); color: var(--text-primary);
  font-family: inherit; font-weight: 600; font-size: .9rem;
  transition: background-color .16s ease;
}
.r6-status-modal-btn:hover { background: var(--surface-3); }
.r6-status-modal-btn.primary {
  background: var(--primary-color); border-color: transparent; color: var(--primary-ink);
}
.r6-status-modal-btn.primary:hover:not(:disabled) { background: var(--primary-light); }

@media (max-width: 720px) {
  .r6-status-title { margin: 4px 0 18px; }
  .r6-status-summary-main { padding: 18px; }
  /* Stacked and centred: at this width the ask and the button cannot share a
     line without one of them looking stranded. */
  .r6-status-summary-actions {
    margin-top: 16px; padding: 14px 0 0;
    flex-direction: column; align-items: stretch; gap: 10px;
  }
  .r6-status-summary-ask { text-align: center; }
  .r6-status-report-btn { width: 100%; }
  .r6-status-chart-card { padding: 14px; }
  .r6-status-chart-canvas-wrap { height: 240px; }
  .r6-status-globe-cta { padding: 18px; }
  .r6-status-globe-btn { width: 100%; }
  .r6-status-card { padding: 16px; }
  .r6-status-chart-section, .r6-status-platforms { margin-top: 28px; }
}
