/* WARDOGS theme, layered on Pico CSS v2 (amber build).
   Load order: pico.amber.min.css → theme.css → page <style>.
   Pico owns typography, forms, tables, buttons and cards. This file sets the brand tokens
   (fonts, square corners, near-black palette) and the handful of components Pico doesn't ship. */

:root{
  --pico-font-family-sans-serif:'Rajdhani',system-ui,sans-serif;
  --pico-font-family-monospace:'JetBrains Mono',ui-monospace,monospace;
  --pico-font-family:var(--pico-font-family-sans-serif);
  --pico-font-weight:500;
  --pico-border-radius:0;
  --pico-form-element-spacing-vertical:.55rem;
  --pico-form-element-spacing-horizontal:.8rem;

  /* brand + status colours (Pico only has primary/secondary/contrast) */
  --amber:#d7a24a; --green:#7bb661; --red:#cf5b43; --blue:#8ab4f8; --faint:#5f5f63;
  --tint:rgba(215,162,74,.08); --tint2:rgba(215,162,74,.15);
  /* short aliases, used by inline styles in page scripts and by dropdown.js */
  --sans:var(--pico-font-family-sans-serif); --mono:var(--pico-font-family-monospace);
  --line:rgba(255,255,255,.08); --line2:rgba(255,255,255,.16);
}
:root[data-theme="dark"]{
  --pico-background-color:#0a0a0b;
  --pico-color:#e6e6e6;
  --pico-muted-color:#9a9a9d;
  --pico-muted-border-color:rgba(255,255,255,.08);
  --pico-card-background-color:#121213;
  --pico-card-sectioning-background-color:#171718;
  --pico-card-box-shadow:none;
  --pico-form-element-background-color:#0e0e0f;
  --pico-form-element-border-color:rgba(255,255,255,.16);
  --pico-table-border-color:rgba(255,255,255,.07);
  --pico-dropdown-background-color:#101013;
  --pico-dropdown-border-color:rgba(255,255,255,.16);
  --pico-dropdown-hover-background-color:rgba(215,162,74,.15);
  --pico-primary:#d7a24a; --pico-primary-background:#d7a24a; --pico-primary-border:#d7a24a;
  --pico-primary-underline:rgba(215,162,74,.5);
  --pico-primary-hover:#e5b566; --pico-primary-hover-background:#e5b566; --pico-primary-hover-border:#e5b566;
  --pico-primary-focus:rgba(215,162,74,.35);
  --pico-primary-inverse:#0a0a0b;
  --fg:var(--pico-color); --dim:var(--pico-muted-color);
}

/* Always keep room for the scrollbar: short pages (no scrollbar) and long ones otherwise lay out at different
   widths, and every page switch between them slides the header and tabs sideways. */
html{scrollbar-gutter:stable;}
body{min-height:100vh;background:radial-gradient(1200px 600px at 70% -10%,rgba(215,162,74,.05),transparent 60%) fixed;}
[hidden]{display:none !important;}

/* Page switches: the header stays put and only the page below it crossfades (Chrome/Edge 126+, Safari 18.2+;
   other browsers just load the page as before). */
@media (prefers-reduced-motion:no-preference){
  @view-transition{navigation:auto;}
  .site-head{view-transition-name:site-head;}
  ::view-transition-old(root),::view-transition-new(root){animation-duration:.16s;}
  ::view-transition-group(site-head){animation-duration:0s;}
}

/* ---------- header + tab bar ---------- */
.site-head{padding-bottom:0;}
.head-row{display:flex;justify-content:space-between;align-items:center;gap:1rem 2rem;flex-wrap:wrap;}
.brand{display:flex;align-items:center;gap:.9rem;}
/* header emblem = the favicon badge, so the site mark matches the browser tab */
.emblem{width:2.2rem;height:2.2rem;flex:none;background:url("/favicon.svg") center/contain no-repeat;}
.brand hgroup{margin:0;}
.brand h1,.brand .brandline{margin:0;font-size:1.2rem;letter-spacing:.2em;text-transform:uppercase;}
/* /server's brand line is a <p>: that page's <h1> is the server's name, which is what it is about */
.brand .brandline{font-weight:700;line-height:1.125;} /* Pico's h1 line height, so this header is as tall as the others */
.brand h1 span,.brand .brandline span{color:var(--pico-primary);}
/* "// Page" after the site name. Phones drop it (the highlighted tab already says which page this is), so every
   header is one line and the tabs sit at the same height on every page. */
.brand h1 .pg,.brand .brandline .pg{color:inherit;}
@media (max-width:640px){
  .brand h1 .pg,.brand .brandline .pg{display:none;}
  /* /api's openapi.json button (Scalar's own download link covers phones); !important beats /api's scoped Pico build */
  .head-row>[role="button"]{display:none !important;}
  /* The status line under the title changes as data loads ("LOADING…" → "FEED LIVE · 13 SECTORS · SYNCED…"): keep
     it to one line so the header can't grow and push the tabs down mid-load. */
  .brand{min-width:0;} .brand hgroup{min-width:0;}
  .brand hgroup>.sub{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
}
.brand hgroup>.sub,.sub{margin:0;font-family:var(--mono);font-size:.66rem;font-weight:500;letter-spacing:.2em;text-transform:uppercase;color:var(--faint);}

nav.tabs{justify-content:flex-start;gap:.15rem;margin-top:1rem;border-bottom:1px solid var(--line);overflow-x:auto;scrollbar-width:none;}
nav.tabs a{flex:none;display:inline-flex;align-items:center;gap:.4rem;margin:0 0 -1px;padding:.75rem 1rem;font:600 .72rem var(--mono);letter-spacing:.14em;text-transform:uppercase;text-decoration:none;color:var(--pico-muted-color);border-bottom:2px solid transparent;}
nav.tabs a:hover{color:var(--pico-color);border-bottom-color:var(--line2);}
nav.tabs a.active,nav.tabs a[aria-current="page"]{color:var(--pico-primary);border-bottom-color:var(--pico-primary);background:var(--tint);}

/* ---------- text helpers ---------- */
.label{font-family:var(--mono);font-size:.66rem;font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:var(--pico-muted-color);}
.mono{font-family:var(--mono);}
.muted{color:var(--pico-muted-color);} .faint{color:var(--faint);}
.o{color:var(--amber);} .c{color:var(--green);} .stale{color:var(--red);}
.sec{display:flex;align-items:center;gap:.6rem;margin:2rem 0 .75rem;font:600 .7rem var(--mono);letter-spacing:.24em;text-transform:uppercase;color:var(--faint);}
.sec::before{content:"";width:.9rem;height:1px;background:var(--pico-primary);}
.sec b{color:var(--pico-primary);}

/* ---------- stat tiles ---------- */
/* A card in a neutral hairline frame (the 2px coloured left edge went on 2026-10-12). A clickable tile's frame turns
   amber and the tile tints on hover, so colour only appears where it means something. Either order works inside:
   value then label (the home page, server pages) or label then value (the stats page's hero). */
.tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(9.5rem,1fr));gap:.75rem;}
article.tile{display:flex;flex-direction:column;margin:0;padding:.8rem 1rem;border:1px solid var(--line);transition:border-color .15s,background-color .15s;container-type:inline-size;}
.tile b{display:block;font:700 clamp(1.05rem,1.8vw,1.45rem)/1.15 var(--mono);white-space:nowrap;}
.tile .k{display:block;margin-top:.3rem;font:600 .64rem var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--pico-muted-color);}
.tile .m{display:block;margin-top:.2rem;font:400 .66rem var(--mono);color:var(--faint);}
.tile.live b{color:var(--green);}
.tile.clickable{cursor:pointer;}
.tile.clickable:hover{border-color:var(--pico-primary);background-color:var(--tint);}
.tile.clickable:hover .k{color:var(--pico-primary);}
/* The home page's shape: an icon block beside the value and its label, a meter under them, and a caption that names
   what the meter measures. Nothing in it may overflow the tile: the value's hour change wraps under the value when
   the tile is narrow, the caption cuts with an ellipsis. */
/* the meter and caption sit at the bottom of the tile, so a row stays level when one label wraps to two lines */
.tile .top{display:flex;align-items:center;gap:.7rem;min-width:0;padding-bottom:.6rem;}
.tile .top+.cap{margin-top:auto;}
.tile .top>.tv{min-width:0;flex:1;}
.tile .top b{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:.4rem;font-size:clamp(1.05rem,1.5vw,1.3rem);line-height:1.1;}
.tile .top .k{margin-top:.15rem;overflow:hidden;text-overflow:ellipsis;}
.tile .ic{flex:none;display:grid;place-items:center;width:2.1rem;height:2.1rem;background:var(--tint2);color:var(--pico-primary);}
.tile .ic svg{width:1.05rem;height:1.05rem;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round;}
.tile .ic.g{background:rgba(123,182,97,.15);color:var(--green);}
.tile .ic.n{background:rgba(255,255,255,.06);color:var(--pico-muted-color);}
.tile .d{font:600 .66rem var(--mono);letter-spacing:.04em;color:var(--pico-muted-color);}
.tile .d.up{color:var(--green);} .tile .d.down{color:var(--red);}
.tile .d:empty{display:none;}
.tile .mt{display:flex;gap:2px;height:4px;margin:auto 0 .4rem;background:var(--line);}
/* a single fill is sized by width (style="width:41%"), a pair's two fills by flex-grow (style="flex:973") */
.tile .mt i{display:block;flex:none;width:0;background:var(--pico-primary);transition:flex-grow .3s,width .3s;}
.tile .mt.g i{background:var(--green);} .tile .mt.b i{background:var(--blue);} .tile .mt.n i{background:var(--pico-muted-color);}
.tile .mt.pair{background:none;} .tile .mt.pair i+i{background:var(--green);}
/* a tile with nothing to measure keeps the meter's room, so its caption lines up with its neighbours' */
.tile .mt.none{visibility:hidden;}
.tile .ic.b{background:rgba(138,180,248,.15);color:var(--blue);}
/* two lines are always reserved: a caption that wraps (the official/community pair in a narrow tile) then takes the
   second, and the meters above stay on one line across the row */
.tile .cap{display:flex;flex-wrap:wrap;justify-content:space-between;column-gap:.6rem;min-height:2lh;font:400 .62rem var(--mono);color:var(--faint);white-space:nowrap;}
.tile .cap>span{min-width:0;overflow:hidden;text-overflow:ellipsis;}
.tile .cap .o,.tile .cap .c{font-weight:600;}
.tile .cap .pc{color:var(--pico-muted-color);}
/* The hour change goes on its own line under the value once a tile is too narrow for an estimate ("~139,753 +10,204")
   beside it, so a row wraps all of its changes or none. In px: Pico scales the root font up on wide screens, so a rem
   threshold would fire on a desktop too. */
@container (max-width:245px){ .tile .top .d{flex-basis:100%;} }

/* ---------- cards ---------- */
.site-main article>header{display:flex;justify-content:space-between;align-items:baseline;gap:.4rem 1rem;flex-wrap:wrap;}
.card-t{font:700 .76rem var(--mono);letter-spacing:.14em;text-transform:uppercase;}
.card-d{font-size:.8rem;color:var(--faint);}
article.flush{padding:0;}
article.flush>header,article.flush>footer{margin:0;padding:.8rem 1.1rem;}

/* ---------- filter bars ---------- */
.filters{display:grid;grid-template-columns:repeat(auto-fit,minmax(10rem,1fr));gap:.75rem 1rem;align-items:end;}
.filters label{margin:0;}
.filters .label{display:block;margin-bottom:.3rem;}
.filters input,.filters select{margin:0;}
.site-main input[type=search]{border-radius:0;}

/* ---------- segmented controls + chips ---------- */
.seg{display:inline-flex;margin:0;}
.seg button,.chip{width:auto;margin:0;padding:.4rem .85rem;font:600 .68rem var(--mono);letter-spacing:.1em;text-transform:uppercase;background:transparent;color:var(--pico-muted-color);border:1px solid var(--line2);box-shadow:none;}
.seg button+button{margin-left:-1px;}
.seg button:hover,.chip:hover{background:transparent;color:var(--pico-color);border-color:var(--line2);}
.seg button.on,.chip.on{position:relative;background:var(--tint2);color:var(--pico-primary);border-color:var(--pico-primary);}
/* chips are toggles: "+" when off, "✓ … ✕" when on so it's clear a second click clears them */
.chip::before{content:"+ ";opacity:.6;}
.chip.on::before{content:"✓ ";opacity:1;}
.chip.on::after{content:"  ✕";opacity:.7;}

/* ---------- notices ---------- */
/* The gap goes under a notice, as with Pico's own blocks: the banners at the top of a page (site-banner.js and
   queue-banner.js in the frontend worker, poll.js's delay notice) start where the page does and keep the usual gap
   above what follows, which on / and /leaderboard is the tiles. */
.notice{display:flex;align-items:center;gap:.8rem;margin:0 0 1rem;padding:.7rem 1rem;line-height:1.5;background:var(--tint);border:1px solid rgba(215,162,74,.3);border-left:2px solid var(--pico-primary);}
.notice b{color:var(--pico-primary);}
/* a smaller line under a notice's text: the site banner's own (set with it), poll.js's "this notice is automatic" */
.notice small{display:block;margin-top:.2rem;color:var(--pico-muted-color);font-size:.8em;}
.notice .nx{flex:none;width:auto;margin:0 0 0 auto;padding:.1rem .45rem;background:none;border:none;color:var(--pico-muted-color);}
.notice .nx:hover{background:none;color:var(--pico-primary);}

/* ---------- tables ---------- */
/* element rules are scoped to .site-main (our own <main>), not bare <main>: Scalar on /api renders <main> elements of its own */
.site-main table{margin:0;}
.site-main :is(th,td){background-color:transparent;}
.site-main th{font:600 .64rem var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--pico-muted-color);white-space:nowrap;}
th[data-k]{cursor:pointer;user-select:none;}
th[data-k]:hover{color:var(--pico-primary);}
th .arw{color:var(--pico-primary);}
th.num,td.num{text-align:right;font-family:var(--mono);white-space:nowrap;}
tr.clickrow{cursor:pointer;}
tr.clickrow:hover>td,tr.clickrow.open>td{background-color:var(--tint);}
tr.clickrow.open>td:first-child{box-shadow:inset 2px 0 0 var(--pico-primary);}
tr.detail>td{padding:0;background-color:var(--pico-card-sectioning-background-color);}
.empty{padding:2.5rem 1rem;text-align:center;color:var(--faint);font:500 .78rem var(--mono);letter-spacing:.06em;line-height:1.7;}
/* A list's first "Loading…" row holds roughly the space the list will fill, so the footer doesn't flash up and then
   get pushed off-screen when the rows arrive. */
.empty.loading{height:70vh;vertical-align:middle;}

/* ---------- small status bits ---------- */
.dot{display:inline-block;padding:0;width:.45rem;height:.45rem;border-radius:50%;vertical-align:middle;background:var(--green);box-shadow:0 0 6px var(--green);}
.dot.full{background:var(--red);box-shadow:0 0 6px var(--red);}
.dot.empty{background:var(--faint);box-shadow:none;}
progress.mini{width:4.5rem;height:.3rem;margin:0;}
.site-main .badge{display:inline-block;padding:.05rem .4rem;font:700 .6rem var(--mono);letter-spacing:.12em;text-transform:uppercase;vertical-align:middle;color:var(--pico-primary);border:1px solid var(--pico-primary);}
.tag{display:inline-block;margin:.1rem .25rem .1rem 0;padding:.05rem .35rem;font:500 .6rem var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--pico-muted-color);border:1px solid var(--line2);}
button.copy{width:auto;margin:0 0 0 .4rem;padding:.12rem .5rem;font:600 .62rem var(--mono);letter-spacing:.1em;text-transform:uppercase;background:transparent;color:var(--pico-muted-color);border:1px solid var(--line2);box-shadow:none;}
button.copy:hover{background:transparent;color:var(--pico-primary);border-color:var(--pico-primary);}

/* ---------- charts ---------- */
.legend{display:flex;gap:.9rem;flex-wrap:wrap;margin-top:.6rem;font:500 .75rem var(--mono);color:var(--pico-muted-color);}
.legend b{color:var(--pico-color);}
.lg{display:inline-block;width:.55rem;height:.55rem;margin-right:.35rem;vertical-align:middle;}
/* Chart tooltips follow the pointer. Pages move them with transform (translate), never left/top: a box moved with
   left/top counts as a layout shift on every mousemove (pointer moves aren't input to CLS), and hovering a chart
   added up to real-user CLS on /leaderboard. */
.tip{position:fixed;left:0;top:0;z-index:100;pointer-events:none;padding:.55rem .75rem;white-space:nowrap;font-size:.85rem;background:#101013;border:1px solid var(--line2);border-left:2px solid var(--pico-primary);box-shadow:0 10px 28px rgba(0,0,0,.7);}
.tip .tt{margin-bottom:.4rem;font:600 .62rem var(--mono);letter-spacing:.14em;text-transform:uppercase;color:#d9b988;}
.tip .row{display:flex;align-items:center;gap:.5rem;}
.tip .row+.row{margin-top:.2rem;}
.tip .row b{margin-left:auto;padding-left:1.1rem;font-family:var(--mono);color:#fff;}

/* ---------- new community server cards (server list's New section; markup in newcards.js) ---------- */
.ngrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(15rem,1fr));gap:.6rem;padding:.9rem 1.1rem;}
.ncard{display:flex;flex-direction:column;gap:.4rem;min-width:0;padding:.6rem .8rem;border:1px solid var(--line2);border-left:2px solid var(--blue);cursor:pointer;}
.ncard:hover{background:var(--tint2);}
.ncard a.nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600;color:var(--pico-color);text-decoration:none;}
.ncard .meta{display:flex;align-items:center;gap:.5rem;min-width:0;white-space:nowrap;}
.ncard .region,.ncard .map{font:500 .74rem var(--mono);color:var(--pico-muted-color);letter-spacing:.05em;text-transform:uppercase;}
.ncard .meta .map{min-width:0;overflow:hidden;text-overflow:ellipsis;}
.ncard .row{display:flex;align-items:center;justify-content:space-between;gap:.5rem;min-width:0;}
.ncard .occ{display:inline-flex;align-items:center;gap:.55rem;}
.ncard .count{font:500 .8rem var(--mono);}
.ncard .lock{color:var(--dim);margin-right:.3rem;}
.ncard button.jcode{max-width:9rem;margin:0;padding:.1rem .35rem;font:700 .75rem var(--mono);letter-spacing:.1em;color:var(--amber);border-color:transparent;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;}
.ncard button.jcode:hover{color:var(--amber);border-color:var(--line2);}
.newtag{flex:none;padding:0 .35rem;font:700 .56rem/1.5 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--blue);border:1px solid rgba(138,180,248,.5);}

/* ---------- favourite server cards (Favourites tab's grid view; markup in favcards.js) ---------- */
.fbar{display:flex;justify-content:space-between;align-items:center;gap:.6rem 1rem;flex-wrap:wrap;margin-top:1rem;padding:.7rem 1.1rem;}
.fbar .fsum{font:500 .8rem var(--mono);letter-spacing:.04em;color:var(--pico-muted-color);min-width:0;}
.fbar .fsum b{color:var(--pico-color);}
.fbar .facts{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;}
/* matches the .seg buttons it sits beside, so the two line up */
.fbar .facts>button{width:auto;margin:0;padding:.4rem .85rem;font:600 .68rem var(--mono);letter-spacing:.1em;text-transform:uppercase;}

.fgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(17rem,1fr));gap:.7rem;}
.fcard{display:flex;flex-direction:column;gap:.45rem;min-width:0;margin:0;padding:.7rem .85rem;background:var(--pico-card-background-color);border:1px solid var(--line2);border-left:2px solid var(--pico-primary);cursor:pointer;}
.fcard:hover{background:var(--tint);}
.fcard>header{display:flex;align-items:center;gap:.45rem;min-width:0;margin:0;padding:0;background:none;border:0;}
/* the card star is a real control (role=button, focusable), which Pico would otherwise paint as a button */
.fcard .fav{padding:0;background:none;border:0;box-shadow:none;font:1rem/1 var(--sans);}
.fcard .fav:focus-visible{outline:1px solid var(--pico-primary);outline-offset:2px;}
.fcard a.nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600;color:var(--pico-color);text-decoration:none;}
.fcard a.nm:hover{color:var(--pico-primary);}
.fcard .lock{color:var(--dim);margin-right:.3rem;}
.fcard .rankbadge{flex:none;padding:0 .35rem;font:700 .62rem/1.5 var(--mono);letter-spacing:.06em;color:var(--pico-primary);border:1px solid var(--pico-primary);text-decoration:none;}
/* wraps rather than overprinting: "Offline · seen 3 hours ago" and "24h peak … · avg …" don't fit side by side on a
   narrow card, so the stats drop to their own line, still right-aligned */
.fcard .row{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.25rem .5rem;min-width:0;}
.fcard .row>.stat{margin-left:auto;}
.fcard .occ{display:inline-flex;align-items:center;gap:.5rem;min-width:0;}
.fcard .occ.off .dot{background:var(--faint);box-shadow:none;}
.fcard .count{font:500 .78rem var(--mono);white-space:nowrap;}
.fcard progress.mini{width:3rem;}
.fcard .stat{font:500 .68rem var(--mono);letter-spacing:.04em;color:var(--pico-muted-color);white-space:nowrap;}
.fcard .stat b{color:var(--pico-color);}
.fcard .stat.dim{color:var(--faint);white-space:normal;text-align:right;}
.fcard .meta .region{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:500 .68rem var(--mono);letter-spacing:.05em;text-transform:uppercase;color:var(--faint);}
.fcard button.jcode{flex:none;max-width:8rem;margin:0;padding:.1rem .35rem;font:700 .7rem var(--mono);letter-spacing:.08em;color:var(--amber);border-color:transparent;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.fcard button.jcode:hover{color:var(--amber);border-color:var(--line2);}

/* the sparkline stretches to the card's width (preserveAspectRatio="none"), so stroke width is set in the
   viewBox's units and would be scaled with it: vector-effect keeps the line 1.4px whatever the card's width */
.fcard .sl{display:block;width:100%;height:3.1rem;cursor:crosshair;}
.fcard .sl .bl{stroke:var(--line2);stroke-width:1;vector-effect:non-scaling-stroke;}
.fcard .sl .bl.dash{stroke-dasharray:4 4;}
/* six-hourly marks: the card's time axis, readable without hovering */
.fcard .sl .gl{stroke:rgba(255,255,255,.1);stroke-width:1;vector-effect:non-scaling-stroke;}
.fcard .sl .hl{stroke:rgba(255,255,255,.35);stroke-width:1;stroke-dasharray:3 3;vector-effect:non-scaling-stroke;}
.fcard .sl .hd{fill:var(--pico-primary);stroke:var(--pico-background-color);stroke-width:1.5;vector-effect:non-scaling-stroke;}
.fcard .sl .hv[hidden],.fcard .sl .hd[hidden]{display:none;}
.fcard .sl .ln{fill:none;stroke:var(--pico-primary);stroke-width:1.4;stroke-linejoin:round;vector-effect:non-scaling-stroke;}
.fcard .sl .ar{fill:var(--pico-primary);opacity:.16;stroke:none;}
.fcard .sl .pt{fill:var(--pico-primary);}
/* a favourite that isn't in the live list: still shown (that IS the answer to "is my server up?"), just muted */
.fcard.off{border-left-color:var(--faint);}
.fcard.off a.nm{color:var(--pico-muted-color);}
.fcard.off .sl{opacity:.5;}
/* a favourite saved before this browser kept any details: nothing to open until the server is next online */
.fcard.nolink{cursor:default;}
.fcard.nolink .nm{color:var(--pico-muted-color);}

/* ---------- issues / feedback (every page, directly above the site footer) ---------- */
.feedback h2{margin:0 0 .4rem;font:600 .7rem var(--mono);letter-spacing:.24em;text-transform:uppercase;color:var(--faint);}
.feedback p{margin:0;color:var(--pico-muted-color);}

/* ---------- footer ---------- */
.foot{margin-top:1.5rem;padding-top:1rem;border-top:1px solid var(--line);font:500 .72rem var(--mono);color:var(--faint);line-height:1.8;}
.foot a{color:var(--pico-muted-color);}
/* the site footer directly under a page's own footnote (leaderboard) shares its rule */
.foot+.foot{margin-top:.25rem;padding-top:0;border-top:0;}

/* Server-rendered page summary (frontend-worker/src/page-summary.js). Hidden until the worker fills it. */
.summary[hidden]{display:none;}
.summary h2{margin:0 0 .5rem;font-size:1rem;letter-spacing:.14em;text-transform:uppercase;}
.summary h3{margin:1.1rem 0 .5rem;font:600 .68rem var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--pico-muted-color);}
.summary p{margin:0;max-width:64ch;color:var(--pico-muted-color);}
.summary ul{margin:0;padding:0;list-style:none;display:grid;gap:.3rem .9rem;}
.sregions{grid-template-columns:repeat(auto-fill,minmax(11rem,1fr));}
.sregions li{display:flex;justify-content:space-between;gap:.6rem;border-bottom:1px solid var(--line2);padding:.2rem 0;}
.sregions .rz{font:500 .74rem var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--pico-muted-color);}
.sregions b{font-family:var(--mono);}
/* Two fixed columns, not auto-fill: server names run long (sort-hack prefixes, Discord invites), and
   auto-fill kept adding columns on wide screens until every name was ellipsed. The count is what needs
   capping, not the minimum width. Rank and name share a line; the players/region line sits under them. */
.stop{grid-template-columns:1fr;}
@media(min-width:720px){.stop{grid-template-columns:1fr 1fr;}}
.stop li{display:grid;grid-template-columns:auto 1fr;column-gap:.45rem;align-items:baseline;padding:.3rem 0;min-width:0;}
.stop .tr{grid-column:1;font:700 .66rem var(--mono);color:var(--amber);}
.stop a{grid-column:2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.stop .tm{grid-column:2;font:500 .68rem var(--mono);letter-spacing:.04em;text-transform:uppercase;color:var(--faint);}
.smore{margin:.9rem 0 0;font:600 .7rem var(--mono);letter-spacing:.1em;text-transform:uppercase;}

/* ---- analytics notice (public/analytics.js) ----
   Here rather than injected by analytics.js: the worker draws the notice into the HTML for visitors in its region
   (frontend-worker/src/consent-notice.js), so it has to be styled at first paint. [hidden] must win over display:flex. */
#wdl-consent{position:fixed;left:1rem;right:1rem;bottom:1rem;z-index:100000;max-width:42rem;margin:0 auto;padding:.9rem 1rem;display:flex;flex-wrap:wrap;align-items:center;gap:.75rem 1rem;
  background:var(--pico-card-background-color,#141416);border:1px solid var(--line2,rgba(255,255,255,.18));box-shadow:0 12px 30px rgba(0,0,0,.6);
  color:var(--pico-color,#dcdcdc);font:500 .85rem/1.5 var(--pico-font-family,system-ui,sans-serif);}
#wdl-consent[hidden]{display:none;}
#wdl-consent p{flex:1 1 18rem;margin:0;}
#wdl-consent a{color:var(--amber,#d7a24a);}
#wdl-consent .btns{display:flex;gap:.5rem;}
#wdl-consent button{width:auto;margin:0;padding:.4rem .9rem;background:transparent;color:inherit;border:1px solid var(--line2,rgba(255,255,255,.25));
  font:600 .7rem var(--mono,monospace);letter-spacing:.08em;text-transform:uppercase;cursor:pointer;}
#wdl-consent button.ok{background:var(--amber,#d7a24a);border-color:var(--amber,#d7a24a);color:#0a0a0b;}
.wdl-analytics{margin:1.5rem auto 2rem;text-align:center;font:500 .72rem var(--mono,monospace);color:var(--faint,#7a7a7e);}
.wdl-analytics button{all:unset;cursor:pointer;color:var(--amber,#d7a24a);text-decoration:underline;}
