/* ============================================================================
   IRANRUST V2 — global stylesheet
   Ported verbatim from the approved homepage (IranRust-V2/public/index.html).
   Only change from the source: the @font-face url is now root-absolute, because
   this file lives at /css/app.css and a relative path would resolve to
   /css/assets/brand/... instead of /assets/brand/...
   ========================================================================== */

@font-face{font-family:'Booster';src:url('/assets/brand/BoosterPolygonCP-Bold.otf') format('opentype');font-weight:700;font-display:swap}

/* The hand-lettered accents from the mockups — "STRONGER TOGETHER",
   "See you in Rust", "NO SAFE ZONE ONLY PROGRESS". Caveat (OFL), Latin
   subset only: every one of these accents is English by design, so the
   Cyrillic and Greek subsets would be 40KB of nothing.

   SELF-HOSTED, not fonts.gstatic.com. Google Fonts is unreliable from
   Iran, and a decorative face that arrives late or never is exactly the
   thing that should not block a page for the audience this site has. */
@font-face{font-family:'Caveat';src:url('/assets/fonts/caveat-700.woff2') format('woff2');
  font-weight:700;font-style:normal;font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+2000-206F,U+2122,U+2191,U+2193,U+2212}

:root{
  /* --------------------------------------------------------------------
     BLACK / WHITE / GOLD

     Gold is an ACCENT, not a surface. Roughly 90% black-and-white, 10% gold:
     gold marks the one thing in a view that matters — the primary action, the
     rank you hold, a reward you have not collected — and everything else is
     black, white and grey. Spend more than that and it stops reading as
     premium and starts reading as yellow.

     --rust / --rust-hot are kept as names because ~60 rules in this sheet
     reference them; they now resolve to gold. Renaming them would be a large
     diff that changes nothing on screen, and a half-finished rename is how a
     stylesheet ends up with two accent colours at once.
     ------------------------------------------------------------------ */

  /* black — five steps, so a panel can sit on a panel without a border */
  --ink:#050505; --black-deep:#080808; --panel:#0D0D0D; --panel2:#111111;
  --card-hover:#171717; --elevated:#1A1A1A;
  --line:#1D1D1D; --line2:#292929;

  /* gold */
  --gold:#D9A52E; --gold-bright:#F2C75C; --gold-light:#E8C878;
  --gold-highlight:#FFD978; --gold-dark:#8A641B; --gold-deep:#5C4315;
  --rust:#D9A52E; --rust-hot:#F2C75C;

  /* white */
  --white:#FFFFFF; --bone:#F5F5F2; --mute:#C8C8C4; --dim:#858585; --off:#555555;

  /* Semantic, and deliberately NOT gold: a green "delivered" and a gold
     "claim your reward" must never be confusable, so status keeps its own
     hues and they do not count against the 10%. */
  --live:#3FCF7F; --danger:#E5544B; --danger-text:#FF9A8A;

  /* medals — gold / silver / bronze is the one place three metals belong */
  --silver:#C6CEDA; --bronze:#C77B45;

  --disp:'Booster',Impact,sans-serif;
  --ui:'Vazirmatn',system-ui,Tahoma,sans-serif;
  --script:'Caveat',cursive;
  --max:1200px;
  --s1:8px; --s2:16px; --s3:24px; --s4:40px; --s5:64px; --s6:104px;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:var(--ink);color:var(--bone);font-family:var(--ui);font-size:15px;
  font-weight:400;line-height:1.85;overflow-x:hidden;-webkit-font-smoothing:antialiased}

/*
 * STICKY FOOTER. Without this, a short page - a single LFG ad, an empty
 * board, a 404 - leaves the footer stranded halfway up the window with a
 * band of dead black beneath it, which reads as a page that failed to load
 * rather than a page with little on it.
 *
 * flex on the BODY rather than a min-height on the content, because the
 * body's children are nav, main and footer: `flex:1` on main hands it every
 * pixel the other two do not want, whatever their height turns out to be.
 */
body{min-height:100vh;display:flex;flex-direction:column}
/* 1 0 auto, not `1`: the shorthand would set flex-basis:0 and let a long
   page's content shrink below its own height. */
.page{flex:1 0 auto;min-width:0}
img{max-width:100%;display:block}

/* The browser's own [hidden]{display:none} is a NORMAL declaration in the UA
   stylesheet, so ANY author `display` on the same element beats it — specificity
   never enters into it. Every component here that sets display and is toggled
   with el.hidden was therefore permanently visible: the achievement dialog
   painted over the whole page, filtered-out cards stayed on screen, and the
   cases result panel (.cs-result{display:flex}) never hid either.
   One author-origin rule fixes all of them. Do not remove it. */
[hidden]{display:none!important}

a{color:inherit;text-decoration:none}
:focus-visible{outline:2px solid var(--rust-hot);outline-offset:3px}
.num{font-variant-numeric:tabular-nums;direction:ltr;display:inline-block}

/* Sprite icons. Sized in em so an icon tracks the text beside it, and
   coloured by currentColor so one symbol serves every context. */
.ico{width:1em;height:1em;flex:none;display:inline-block;vertical-align:-.125em}

.wrap{max-width:var(--max);margin:0 auto;padding:0 var(--s3)}
section{padding:var(--s6) 0}
.band{background:var(--panel)}

.eyebrow{font-size:11px;font-weight:700;letter-spacing:.2em;color:var(--gold);text-transform:uppercase;margin:0 0 var(--s2)}
h2{font-family:var(--ui);font-weight:900;font-size:clamp(28px,3.6vw,42px);line-height:1.25;margin:0 0 var(--s2);letter-spacing:-.01em;text-wrap:balance}
.lede{color:var(--mute);max-width:52ch;font-size:15px;font-weight:300;margin:0}
.sec-head{position:relative;margin-bottom:var(--s4);max-width:640px;
  padding-inline-start:18px}
/* A short gold rule at the start of every section head. It is the page's only
   repeating ornament, so it reads as punctuation between bands rather than as
   decoration — and it is 3px of gold, which keeps the 90/10 budget intact. */
.sec-head::before{content:"";position:absolute;top:2px;height:calc(100% - 12px);
  inset-inline-start:0;width:3px;border-radius:2px;
  background:linear-gradient(180deg,var(--gold) 0%,transparent 100%)}

/* ===================================================================
   PODIUM

   The old treatment was a 3px edge and a 3px type bump, which is why
   five rows read as five identical rows. First place now differs in
   SIZE — the only difference the eye registers before it reads.
   =================================================================== */
.row.medal-1{padding-block:22px;
  background:linear-gradient(to left,transparent 42%,rgba(217,165,46,.13))}
.row.medal-1::before{width:4px;box-shadow:0 0 18px 1px rgba(217,165,46,.55)}
.row.medal-1 .av-wrap{width:58px;height:58px}
.row.medal-1 .av{box-shadow:0 0 0 1px rgba(217,165,46,.5),0 6px 22px rgba(217,165,46,.25)}
.row.medal-1 .who b{font-size:16px}
.row.medal-1 .rank{font-size:26px;text-shadow:0 0 22px rgba(217,165,46,.55)}
.row.medal-1 .val{font-size:25px;text-shadow:0 0 26px rgba(217,165,46,.4)}

/* A slow sheen across first place only. One moving highlight on the one row
   that matters, rather than motion sprayed across the whole board. */
.row.medal-1::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(105deg,transparent 38%,rgba(255,236,190,.11) 48%,transparent 58%);
  background-size:280% 100%;animation:podium-sheen 5.5s ease-in-out infinite}
@keyframes podium-sheen{0%,62%{background-position:180% 0}100%{background-position:-80% 0}}

.row.medal-2{background:linear-gradient(to left,transparent 62%,rgba(200,200,196,.055))}
.row.medal-2 .av-wrap{width:50px;height:50px}
.row.medal-2 .rank,.row.medal-3 .rank{font-size:21px}
.row.medal-3{background:linear-gradient(to left,transparent 68%,rgba(199,123,69,.05))}

/* The crown sat at the avatar's top edge and read as a smudge at 44px. */
.row.medal-1 .row-crown{top:-15px;font-size:17px;
  filter:drop-shadow(0 2px 6px rgba(217,165,46,.7))}

@media(max-width:640px){
  .row.medal-1{padding-block:16px}
  .row.medal-1 .av-wrap{width:48px;height:48px}
  .row.medal-1 .rank{font-size:20px}
  .row.medal-1 .val{font-size:19px}
}

/* ------------------------------------------------------- server cards */
/* The art was a flat 132px strip. A gradient floor lets the card's own panel
   colour rise through the bottom of the photo, so the image reads as part of
   the card instead of pasted on top of it. */
.srv-art::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,var(--panel2) 2%,rgba(17,17,17,.45) 38%,transparent 78%)}
.srv:hover .srv-art img{transform:scale(1.07)}
/* A hairline of the server's own accent along the top of the card, lit on
   hover. Each server already carries a --srv colour; nothing used it here. */
.srv::after{content:"";position:absolute;inset:0 0 auto 0;height:2px;z-index:2;
  background:linear-gradient(90deg,transparent,var(--srv),transparent);
  opacity:.35;transition:opacity .25s}
.srv:hover::after{opacity:1}

@media(prefers-reduced-motion:reduce){
  .row.medal-1::after{animation:none}
  .srv:hover .srv-art img{transform:none}
}


.btn{display:inline-flex;align-items:center;gap:var(--s1);padding:12px 22px;border-radius:8px;
  font-family:var(--ui);font-weight:700;font-size:14px;border:1px solid transparent;cursor:pointer;
  transition:background .18s,border-color .18s,transform .18s}
.btn:hover{transform:translateY(-2px)}
.btn-p{background:linear-gradient(180deg,var(--gold-bright),var(--gold));color:#050505;font-weight:800;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.28)}
.btn-p:hover{background:linear-gradient(180deg,var(--gold-highlight),var(--gold-bright));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.4),0 6px 22px rgba(217,165,46,.28)}
.btn-g{background:transparent;border-color:var(--line2);color:var(--bone)}
.btn-g:hover{border-color:var(--rust);background:rgba(217,165,46,.07)}

/* ---------- NAV ---------- */
/* Scoped to the id on purpose. As a bare element selector this pinned EVERY
   <nav> on the site to the top of the viewport - it caught the profile tab bar
   and the installer's step list. app.js finds this element by id, so nothing
   depended on the loose match. */
#nav{position:fixed;inset:0 0 auto 0;z-index:50;border-bottom:1px solid transparent;transition:background .3s,border-color .3s}
#nav.stuck{background:rgba(5,5,5,.92);backdrop-filter:blur(16px);border-bottom-color:var(--line)}
.nav-in{max-width:var(--max);margin:0 auto;padding:14px var(--s3);display:flex;align-items:center;gap:var(--s4)}
.logo{display:flex;align-items:center;gap:10px;font-family:var(--disp);font-size:20px;letter-spacing:.02em}
.logo img{width:28px;height:28px;border-radius:6px}
.navlinks{display:flex;gap:var(--s3);font-size:14px;font-weight:500}
.navlinks a{position:relative;padding:6px 0;color:var(--mute);transition:color .18s}
.navlinks a:hover{color:var(--bone)}
/* The active page gets the nav's single gold mark, as in the mockup. Colouring
   every link gold would spend the accent on navigation, which is the one place
   nothing needs emphasising. */
.navlinks a.on{color:var(--white)}
.navlinks a.on::after{content:"";position:absolute;inset-inline:0;bottom:-3px;height:2px;
  border-radius:2px;background:var(--gold)}
.nav-r{margin-inline-start:auto;display:flex;align-items:center;gap:10px}

/* --- nav dropdown (the Community group) --------------------------------- */

.nav-drop{position:relative}
.nav-drop>button{display:inline-flex;align-items:center;gap:5px;padding:6px 0;
  background:transparent;border:0;font-family:inherit;font-size:14px;font-weight:500;
  color:var(--mute);cursor:pointer;transition:color .18s}
.nav-drop>button:hover,.nav-drop.open>button{color:var(--bone)}
.nav-drop>button.on{color:var(--white)}
.nav-drop-caret{font-size:13px;transition:transform .2s}
.nav-drop.open .nav-drop-caret{transform:rotate(180deg)}

.nav-drop-menu{position:absolute;top:calc(100% + 12px);inset-inline-start:0;z-index:60;
  min-width:190px;display:flex;flex-direction:column;padding:7px;
  background:rgba(5,5,5,.97);backdrop-filter:blur(16px);
  border:1px solid var(--line2);border-radius:13px;
  box-shadow:0 18px 40px rgba(0,0,0,.55)}
.nav-drop-menu a{padding:9px 11px;border-radius:9px;font-size:13px;font-weight:500;
  color:var(--mute);transition:background .16s,color .16s}
.nav-drop-menu a:hover{background:var(--panel2);color:var(--bone)}
.nav-drop-menu a.on{background:rgba(217,165,46,.12);color:var(--gold-light);font-weight:700}

/* --- mobile menu -------------------------------------------------------- */

/* Hidden by default and shown only where .navlinks is not: the two are exact
   complements, so there is never a screen with both and never one with
   neither. Also hidden when JS is dead — see the <noscript> block. */
.nav-burger{display:none;width:38px;height:38px;flex:none;padding:0;
  flex-direction:column;align-items:center;justify-content:center;gap:4px;
  background:transparent;border:1px solid transparent;border-radius:11px;cursor:pointer;
  transition:background .16s,border-color .16s}
.nav-burger span{display:block;width:17px;height:2px;border-radius:2px;background:var(--mute);
  transition:transform .2s,opacity .2s,background .16s}
.nav-burger:hover{background:var(--panel2);border-color:var(--line2)}
.nav-burger:hover span{background:var(--bone)}
.nav-burger.open span{background:var(--gold)}
.nav-burger.open span:nth-child(1){transform:translateY(6px) rotate(45deg)}
.nav-burger.open span:nth-child(2){opacity:0}
.nav-burger.open span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}

.nav-panel{position:absolute;inset-inline:0;top:100%;z-index:55;
  display:flex;flex-direction:column;padding:8px;
  background:rgba(5,5,5,.97);backdrop-filter:blur(16px);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  box-shadow:0 18px 40px rgba(0,0,0,.5)}
.nav-panel a{padding:12px 14px;border-radius:10px;font-size:14px;font-weight:500;
  color:var(--mute);transition:background .16s,color .16s}
.nav-panel a:hover{background:var(--panel2);color:var(--bone)}
.nav-panel a.on{background:rgba(217,165,46,.12);color:var(--gold-light);font-weight:700}

@media (max-width:820px){
  .nav-burger{display:flex}
}

/* --- nav right cluster, per the mockups -------------------------------- */

/* A bare icon button. 38px square is the smallest that still clears the
   44px touch guidance once the 10px gap either side is counted. */
.nav-icon{position:relative;width:38px;height:38px;flex:none;display:grid;
  place-items:center;border-radius:11px;font-size:17px;color:var(--mute);
  border:1px solid transparent;transition:color .16s,background .16s,border-color .16s}
.nav-icon:hover{color:var(--bone);background:var(--panel2);border-color:var(--line2)}

/* The unread badge. Sits on the inline-END corner so it mirrors correctly in
   RTL instead of hanging off the wrong side of the bell. */
.nav-dot{position:absolute;top:4px;inset-inline-end:3px;min-width:16px;height:16px;
  padding:0 4px;border-radius:99px;background:var(--gold);color:var(--ink);
  font-size:10px;font-weight:800;line-height:16px;text-align:center;
  border:2px solid var(--ink)}

/* Currency chip: value and a "+" that goes to the shop. */
.nav-coin{display:flex;align-items:center;gap:8px;padding:6px 8px 6px 12px;
  border-radius:99px;background:var(--panel2);border:1px solid var(--line2)}
.nav-coin img{width:18px;height:18px;object-fit:contain;flex:none}
.nav-coin>b{font-size:13px;font-weight:700;color:var(--gold-light)}
.nav-coin-add{width:24px;height:24px;flex:none;display:grid;place-items:center;
  border-radius:8px;background:var(--gold);color:var(--ink);font-size:13px;
  transition:background .16s}
.nav-coin-add:hover{background:var(--gold-bright)}

/* Touch targets. 24px and 21px are below what a thumb can reliably hit -
   Apple asks for 44, Android for 48. Desktop keeps the compact sizing because
   a mouse is precise; only touch screens get the bigger hit area. */
@media (pointer:coarse){
  .nav-coin-add{width:34px;height:34px}
  .sh-support-go{padding:8px 4px}
}

/* Name + presence, stacked, as in every mockup. */
.nav-me-t{display:flex;flex-direction:column;align-items:flex-start;line-height:1.15;min-width:0}
.nav-me-t b{font-size:13px}
.nav-me-t small{font-size:10.5px;color:#5FBF7F;font-weight:600}

.btn .ico{font-size:15px;margin-inline-end:6px;vertical-align:-.18em}

@media (max-width:900px){
  .nav-me-t small{display:none}
}

/* The right cluster has to fit a 375px bar on its own, because .navlinks is
   already display:none by then and body has overflow-x:hidden — so anything
   that does not fit is CLIPPED and unreachable rather than scrollable.
   Measured budget at 375: logo ~115 + coin ~90 + bell 34 + avatar 42 + gaps.
   The search icon goes (the leaderboard is one tap away in the menu) and the
   account chip drops to avatar + caret. The BALANCE stays: it is the number a
   player opens the site to check. */
@media (max-width:560px){
  .nav-icon{width:34px;height:34px;font-size:15px}
  /* `.nav-r>.nav-icon:first-child{display:none}` used to live here to drop the
     SEARCH icon on phones. It selected by POSITION, not by what it was — and
     the search icon has now been removed from the markup, which would have made
     this rule hide the player's MESSAGES inbox instead. Deleted rather than
     re-pointed: there is nothing left in that row worth dropping. */
  .nav-coin{padding:4px 5px 4px 9px;gap:6px}
  .nav-coin>b{font-size:12px}
  .nav-me-t{display:none}
  .nav-me{padding:6px 8px}

  /* The wordmark goes; the R mark stays. font-size:0 collapses the bare text
     node next to the <img> without needing a wrapper element that the footer
     logo would also inherit. Worth ~85px, which is what the bar was short by. */
  #nav .logo{font-size:0;gap:0}
}

/* --- footer, per the mockups ------------------------------------------- */

.f-brand{display:flex;flex-direction:column;gap:5px}
.f-tag{margin:0;font-size:11px;color:var(--dim);letter-spacing:.02em}

.f-social{display:flex;gap:8px}
.f-social a{width:34px;height:34px;display:grid;place-items:center;border-radius:10px;
  font-size:15px;color:var(--dim);background:var(--panel2);border:1px solid var(--line2);
  transition:color .16s,border-color .16s,transform .16s}
.f-social a:hover{color:var(--gold);border-color:var(--gold);transform:translateY(-2px)}

/* The sign-off. Decorative, English, and removed rather than shrunk on small
   screens — a scrawl small enough to fit a phone is just noise. */
.f-scrawl{margin:0;font-family:var(--script);font-size:26px;line-height:.98;
  color:var(--gold-light);transform:rotate(-6deg);text-align:center}
.f-scrawl span{display:block}
.f-scrawl-crown{display:block;margin:0 auto 2px;font-size:16px;color:var(--gold)}
@media (max-width:900px){.f-scrawl{display:none}}

.f-legal{padding-top:14px;margin-top:18px;border-top:1px solid var(--line);text-align:center}
.f-legal small{color:var(--off);font-size:11.5px}

/* ---------- HERO ---------- */
/* Sized to the viewport rather than a fixed 600px, but capped so it never eats
   a tall monitor whole — the servers below have to stay findable. */
.hero{position:relative;min-height:min(90vh,880px);display:flex;align-items:flex-end;
  padding:210px 0 var(--s5);overflow:hidden}
.hero-bg{position:absolute;inset:0}
.hero-bg img{width:100%;height:100%;object-fit:cover;object-position:center 30%;
  transform:scale(1.04);animation:hero-drift 26s ease-in-out infinite alternate}
@keyframes hero-drift{to{transform:scale(1.12) translate3d(1.5%,-1%,0)}}
.hero-bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,var(--ink) 1%,rgba(5,5,5,.72) 40%,rgba(5,5,5,.34) 72%,rgba(5,5,5,.8) 100%),
             linear-gradient(to left,transparent 40%,rgba(5,5,5,.9) 100%),
             radial-gradient(60% 70% at 78% 42%,rgba(217,165,46,.16),transparent 70%)}
/* A hairline of gold where the hero meets the page — the only edge on the site
   that gets one, so it reads as the top of the brand rather than decoration. */
.hero::after{content:"";position:absolute;inset:auto 0 0 0;height:1px;z-index:3;
  background:linear-gradient(90deg,transparent,rgba(217,165,46,.55),transparent)}
#embers{position:absolute;inset:0;z-index:1;pointer-events:none}
.hero-in{position:relative;z-index:2;width:100%}

/* The wordmark is the single loudest thing on the site, so it gets the one
   genuinely expensive treatment: brushed gold rather than flat white.

   Two layers doing different jobs — a gradient clipped to the glyphs for the
   metal, and a blurred copy behind it for the light it throws. The glow is a
   pseudo-element rather than a text-shadow because a shadow large enough to
   read as light also smears the letterforms. */
.hero h1{position:relative;color:var(--white);
  background:linear-gradient(176deg,#FFF6E2 4%,var(--gold-bright) 26%,var(--gold) 54%,#8A641B 88%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  filter:drop-shadow(0 2px 1px rgba(0,0,0,.55))}
.hero h1::before{content:attr(data-glow);position:absolute;inset:0;z-index:-1;
  color:var(--gold);filter:blur(26px);opacity:.4;pointer-events:none}

/* The wordmark rises as the page loads, then stays put. One movement, on the
   thing the eye lands on first — more than that and the hero fidgets. */
@keyframes hero-rise{from{opacity:0;transform:translateY(26px)}to{opacity:1;transform:none}}
.hero h1,.hero .eyebrow,.hero-sub,.hero p,.hero-cta{animation:hero-rise .9s cubic-bezier(.2,.8,.2,1) both}
.hero .eyebrow{animation-delay:.05s}
.hero h1{animation-delay:.14s}
.hero-sub{animation-delay:.24s}
.hero p{animation-delay:.32s}
.hero-cta{animation-delay:.4s}

/* The live dot is the page's proof of life, so it gets a real pulse rather than
   a static circle — the one thing on the hero that keeps moving after landing. */
/* --- buy scrap (the + in the nav) --------------------------------------- */

body.tu-locked{overflow:hidden}
.tu{position:fixed;inset:0;z-index:240;display:grid;place-items:center;padding:20px}
.tu-bg{position:absolute;inset:0;background:rgba(5,5,5,.86);backdrop-filter:blur(6px)}
.tu-box{position:relative;z-index:1;width:min(430px,100%);max-height:90vh;overflow-y:auto;
  padding:26px 24px 20px;background:var(--panel);border:1px solid var(--line2);
  border-radius:20px;box-shadow:0 28px 70px rgba(0,0,0,.65)}
.tu-box::before{content:"";position:absolute;inset-inline:0;top:0;height:2px;
  background:var(--gold);border-radius:20px 20px 0 0}
.tu-x{position:absolute;top:12px;inset-inline-end:14px;width:28px;height:28px;
  background:transparent;border:0;color:var(--dim);font-size:24px;line-height:1;cursor:pointer}
.tu-x:hover{color:var(--bone)}

.tu-t{margin:0 0 4px;font-family:var(--disp);font-size:19px;text-align:center}
.tu-sub{margin:0 0 18px;text-align:center;color:var(--dim);font-size:12px;font-weight:300}

.tu-presets{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:16px}
.tu-preset{padding:12px 6px;border-radius:12px;background:var(--panel2);
  border:1px solid var(--line2);color:var(--mute);font-family:inherit;cursor:pointer;
  transition:border-color .16s,background .16s,color .16s}
.tu-preset b{display:block;font-family:var(--disp);font-size:17px}
.tu-preset span{font-size:10.5px;color:var(--dim)}
.tu-preset:hover{border-color:var(--off);color:var(--bone)}
.tu-preset.on{background:rgba(217,165,46,.13);border-color:var(--gold);color:var(--gold-light)}
.tu-preset.on span{color:var(--gold-dark)}

.tu-field{display:block;margin-bottom:12px}
.tu-field>span{display:block;margin-bottom:5px;font-size:11.5px;color:var(--dim)}
.tu-field input{width:100%;padding:11px 13px;background:var(--panel2);
  border:1px solid var(--line2);border-radius:11px;color:var(--bone);
  font-family:inherit;font-size:13.5px}
.tu-field input:focus{outline:0;border-color:var(--gold)}

.tu-code-msg{margin:-6px 0 12px;font-size:11.5px;color:#E5544B}
.tu-code-msg.is-ok{color:#5FBF7F}

.tu-gift{display:flex;align-items:center;gap:8px;margin-bottom:12px;
  font-size:12.5px;color:var(--mute);cursor:pointer}
.tu-gift input{width:15px;height:15px;accent-color:var(--gold);flex:none}

/* Every line the player is charged, itemised. */
.tu-sum{margin:16px 0 0;padding:13px 15px;background:var(--panel2);
  border:1px solid var(--line);border-radius:12px;display:flex;
  flex-direction:column;gap:7px}
.tu-sum div{display:flex;align-items:center;justify-content:space-between;gap:10px}
.tu-sum dt{font-size:11.5px;color:var(--dim);margin:0}
.tu-sum dd{margin:0;font-size:12.5px;font-weight:600}
.tu-minus{color:#5FBF7F}
.tu-total{padding-top:8px;border-top:1px solid var(--line)}
.tu-total dt{color:var(--bone);font-weight:700;font-size:12.5px}
.tu-total dd{color:var(--gold);font-family:var(--disp);font-size:17px}

.tu-err{margin:12px 0 0;padding:9px 12px;border-radius:10px;font-size:12px;
  background:rgba(229,84,75,.1);border:1px solid rgba(229,84,75,.35);color:#E5544B}

.tu-go{width:100%;margin-top:14px;padding:13px;border-radius:12px;
  background:var(--gold);border:1px solid var(--gold);color:var(--ink);
  font-family:inherit;font-size:14px;font-weight:800;cursor:pointer;
  transition:background .16s}
.tu-go:hover{background:var(--gold-bright)}
.tu-go[disabled]{opacity:.5;cursor:default}

.tu-note{margin:10px 0 0;text-align:center;font-size:10.5px;color:var(--off)}

/* --- home: hero rotation + pillars section ------------------------------ */

/* Cross-fade, in CSS. Each layer is opaque for one slot of the cycle and
   transparent for the rest; --i shifts its start. No JavaScript, so the
   rotation cannot break the page, and a visitor who never scrolls still only
   downloads the first image eagerly. */
/* THE ROTATION IS DRIVEN BY JS, AND THE REASON IS ARITHMETIC.
   It used to be a keyframe animation whose percentages were of the WHOLE
   cycle, so they only lined up for one particular number of images. With
   three the cycle is 21s and each photo faded in by 0.84s and back out by
   4.2s - while the next one did not begin until 7s. That left 2.8 seconds of
   black between every image, longer than the picture was even up for. CSS
   cannot compute keyframe percentages from --hero-n, so no set of fixed
   percentages can be right for two images AND five.
   A class toggle plus a transition crossfades correctly for any count: the
   outgoing image fades out over exactly the same period the incoming one
   fades in, so there is never a moment with nothing on screen. */
.hero-bg img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity var(--hero-fade,1.6s) ease-in-out}

/* No JavaScript, or reduced motion: the first photograph simply stays up. A
   still hero is a fine hero; a black box is not. */
.hero-bg img:first-child{opacity:1}

/* Once the rotator is running it owns visibility. Declared AFTER the
   first-child rule on purpose - same specificity, so source order decides. */
.hero-bg.is-rotating img{opacity:0}
.hero-bg.is-rotating img.on{opacity:1}

/* One image never rotates: a lone picture fading out and back is a flicker. */
.hero-bg[style*="--hero-n:1"] img{opacity:1}

@media (prefers-reduced-motion:reduce){
  .hero-bg img{transition:none}
}

.pillars-sec{position:relative;overflow:hidden;padding-block:var(--s5,64px)}
.pillars-sec.has-art::before{content:"";position:absolute;inset:0;
  background-image:var(--art);background-size:cover;background-position:center;
  opacity:.24}
.pillars-sec.has-art::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to bottom,var(--ink),rgba(5,5,5,.72) 40%,var(--ink))}
.pillars-sec>*{position:relative;z-index:2}

.pillars-more{display:inline-flex;align-items:center;gap:7px;margin-top:22px;
  font-size:13px;font-weight:700;color:var(--gold)}
.pillars-more:hover{color:var(--gold-bright)}
.pillars-more .ico{font-size:14px;transform:scaleX(-1)}

/* The scrawl now sits ON the section, not in a card below it. */
.pillars-scrawl{position:absolute;z-index:3;top:14%;inset-inline-start:4%;margin:0;
  font-family:var(--script);font-size:clamp(18px,2vw,30px);line-height:1.04;
  color:var(--gold-light);transform:rotate(-7deg);text-align:center;
  text-shadow:0 2px 18px rgba(0,0,0,.7);pointer-events:none}
.pillars-scrawl span{display:block}
.pillars-scrawl .ico{display:block;margin:4px auto 0;font-size:18px;color:var(--gold)}
@media (max-width:1200px){.pillars-scrawl{display:none}}

/* --- home: hero stat row, pillars (mockup pass) ------------------------- */

.hero-sub{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:10px;font-size:13px;font-weight:600;letter-spacing:.16em;color:var(--mute)}
.hero-sub i{font-style:normal;font-size:8px;color:var(--gold)}
.hero-body{max-width:52ch;margin-inline:auto}

.hero-stats{display:flex;flex-wrap:wrap;justify-content:center;gap:16px 38px;
  margin-top:30px}
.hero-stat{display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto auto;
  column-gap:11px;align-items:center;text-align:start}
.hero-stat .ico{grid-row:1/3;font-size:19px;width:40px;height:40px;display:grid;
  place-items:center;border-radius:12px;color:var(--gold);
  background:rgba(217,165,46,.1);border:1px solid rgba(217,165,46,.28)}
.hero-stat b{font-family:var(--disp);font-size:21px;line-height:1.1}
.hero-stat span{font-size:11px;color:var(--dim)}
.hero-stat-live .ico{color:#5FBF7F;background:rgba(95,191,127,.1);
  border-color:rgba(95,191,127,.3)}
.hero-stat-live:hover b{color:var(--gold-light)}

.hero-scrawl{position:absolute;z-index:3;bottom:16%;inset-inline-end:5%;margin:0;
  font-family:var(--script);font-size:clamp(20px,2.2vw,34px);line-height:1.02;
  color:var(--gold-light);transform:rotate(-8deg);text-align:center;
  text-shadow:0 2px 20px rgba(0,0,0,.65);pointer-events:none}
.hero-scrawl span{display:block}
.hero-scrawl-crown{display:block;margin:5px auto 0;font-size:20px;color:var(--gold)}
@media (max-width:1100px){.hero-scrawl{display:none}}

/* The four pillars. auto-FIT so a filtered or shortened list never leaves an
   empty track beside it. */
.pillars{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:14px}
.pillar{position:relative;display:flex;flex-direction:column;align-items:center;
  text-align:center;gap:9px;padding:24px 18px;background:var(--panel);
  border:1px solid var(--line);border-radius:16px;
  transition:border-color .2s,transform .2s,background .2s}
.pillar:hover{border-color:var(--line2);transform:translateY(-3px);background:var(--panel2)}
.pillar h3{margin:2px 0 0;font-family:var(--disp);font-size:16px;letter-spacing:.02em}
.pillar p{margin:0;color:var(--dim);font-size:12px;font-weight:300;line-height:1.85}

/* Hexagon mark, same clip-path family as the achievement badges so the two
   pages read as one system. */
.pillar-hex{position:relative;width:64px;height:72px;flex:none}
.pillar-hex::before{content:"";position:absolute;inset:0;
  background:linear-gradient(160deg,var(--gold-highlight),var(--gold-dark));
  clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%)}
.pillar-hex-in{position:absolute;inset:2px;background:var(--panel);
  clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);
  display:grid;place-items:center}
.pillar-hex-in .ico{font-size:26px;color:var(--gold)}

/* The wide art card. It spans two tracks where there is room and simply behaves
   as one more card where there is not. */
.pillar-wide{grid-column:span 2;padding:0;overflow:hidden;justify-content:center;
  min-height:190px}
.pillar-wide img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.5}
.pillar-wide::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,rgba(5,5,5,.9),rgba(5,5,5,.35))}
.pillar-scrawl{position:relative;z-index:2;font-family:var(--script);
  font-size:clamp(20px,2vw,30px);line-height:1.04;color:var(--gold-light);
  transform:rotate(-6deg);text-align:center}
.pillar-scrawl span{display:block}
.pillar-scrawl .ico{display:block;margin:5px auto 0;font-size:19px;color:var(--gold)}
@media (max-width:760px){.pillar-wide{grid-column:span 1;min-height:150px}}

.hero-live-dot{position:relative}
.hero-live-dot::after{content:"";position:absolute;inset:-5px;border-radius:50%;
  border:1px solid var(--live);opacity:0;animation:live-ping 2.4s ease-out infinite}
@keyframes live-ping{0%{transform:scale(.6);opacity:.7}70%{transform:scale(1.9);opacity:0}100%{opacity:0}}

@media(prefers-reduced-motion:reduce){
  .hero h1,.hero .eyebrow,.hero-sub,.hero p,.hero-cta{animation:none}
  .hero-live-dot::after{animation:none}
  .hero-bg img{animation:none}
}
h1{font-family:var(--disp);font-size:clamp(54px,9vw,116px);line-height:.86;margin:0 0 var(--s2);text-transform:uppercase}
.hero-sub{font-weight:900;font-size:clamp(19px,2.6vw,30px);color:var(--bone);
  line-height:1.3;margin:0 0 var(--s2);letter-spacing:.01em}
.hero p{color:#C8C8C4;max-width:44ch;font-weight:300;margin:0 0 var(--s3);font-size:15.5px}
.hero-cta{display:flex;gap:10px;flex-wrap:wrap;align-items:center}

/* The live count, moved out of the old strip and into the headline block. Same
   figure, but read next to the pitch instead of as a band between sections. */
.hero-live{display:inline-flex;align-items:center;gap:9px;padding:9px 16px;border-radius:99px;
  font-size:12.5px;color:var(--mute);background:rgba(5,5,5,.55);
  border:1px solid var(--line2);backdrop-filter:blur(8px);
  transition:border-color .2s,background .2s}
.hero-live:hover{border-color:rgba(217,165,46,.5);background:rgba(5,5,5,.75)}
.hero-live b{font-family:var(--disp);font-size:20px;line-height:1;color:var(--white)}
.hero-live-dot{width:8px;height:8px;border-radius:50%;background:var(--live);flex:none;
  box-shadow:0 0 0 0 rgba(63,207,127,.55);animation:pulse 2s infinite}
@media(max-width:560px){.hero-live{width:100%;justify-content:center}}

/* ---------- LIVE POPULATION (centrepiece) ---------- */
.pop-strip{background:var(--panel);border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:var(--s3) 0}
.pop-in{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);flex-wrap:wrap}
.pop-total{display:flex;align-items:baseline;gap:10px}
.pop-total b{font-family:var(--disp);font-size:46px;line-height:1;color:var(--rust)}
.pop-total span{font-size:13px;color:var(--mute);font-weight:500}
.live-tag{display:inline-flex;align-items:center;gap:7px;font-size:11px;font-weight:700;letter-spacing:.14em;
  color:var(--live);text-transform:uppercase}
.live-tag i{width:7px;height:7px;border-radius:50%;background:var(--live);animation:pulse 2s infinite}
@keyframes pulse{0%,100%{opacity:1;box-shadow:0 0 0 0 rgba(63,207,127,.5)}50%{opacity:.7;box-shadow:0 0 0 6px rgba(63,207,127,0)}}
.spark{display:flex;align-items:flex-end;gap:3px;height:44px}
.spark i{width:6px;background:var(--line2);border-radius:2px;transition:background .18s}
.spark i.hi{background:var(--rust)}

/* ---------- SERVER CARDS ----------
   Three cards, each with its own artwork and its own accent (--srv). This is the
   one deliberate exception to the gold-only accent rule: a server is a PLACE, and
   telling 2X from PVE at a glance is worth more here than palette purity. The
   accent is confined to the badge, the bar, the live dot and the hover edge. */
/* THE ROW CENTRES ITSELF, WHATEVER THE FLEET SIZE.
   This was repeat(3,1fr), which only ever looked right because a third card
   existed — and one of those three was a PVE server the community does not
   own. With two real servers the cards packed into two of three fixed tracks
   and left a dead gutter beside them (on the LEFT here, the page being RTL).
   auto-fit collapses the empty tracks and justify-content centres what is
   left, so two, three or five servers all sit centred. The 380px cap stops a
   lone card stretching the width of the page. */
/* FLEX, NOT GRID, SO THE LAST ROW CENTRES TOO.
   Grid auto-fit sizes tracks from the MINIMUM, so a 280px floor needed
   3x280+2gap = 872px before it would place three cards on one line; below that
   RTG dropped to a second row and sat hard against the edge, because a grid's
   final row is aligned, never centred. Flex wraps by the same rule but
   justify-content centres every row including the last, and a 240px basis lets
   three cards share a narrower viewport (or a zoomed browser) before wrapping.
   max-width keeps a lone card from stretching the width of the page. */
.srv-list{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--s2)}
.srv-list > .srv{flex:1 1 240px;max-width:380px}
@media(max-width:680px){.srv-list > .srv{flex-basis:100%;max-width:none}}

.srv{--srv:var(--gold);position:relative;display:flex;flex-direction:column;overflow:hidden;
  background:var(--panel2);border:1px solid var(--line2);border-radius:16px;
  transition:border-color .25s,transform .25s,box-shadow .25s}
.srv:hover{transform:translateY(-4px);border-color:color-mix(in srgb,var(--srv) 55%,transparent);
  box-shadow:0 18px 46px rgba(0,0,0,.6)}

.srv-art{position:relative;height:132px;overflow:hidden;flex:none}
.srv-art img{width:100%;height:100%;object-fit:cover;
  transition:transform .5s cubic-bezier(.2,.7,.3,1)}
.srv:hover .srv-art img{transform:scale(1.07)}
/* The scrim carries the server's accent, which is what makes three cards built
   from the same few banner photos read as three different places. */
.srv-art::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,var(--panel2) 2%,rgba(17,17,17,.55) 55%,transparent),
             linear-gradient(120deg,color-mix(in srgb,var(--srv) 26%,transparent),transparent 62%)}

.srv-live{position:absolute;z-index:2;top:12px;inset-inline-end:12px;
  display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:99px;
  font-size:10px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;
  background:rgba(5,5,5,.72);border:1px solid var(--line2);
  border-color:color-mix(in srgb,var(--srv) 45%,transparent);
  color:var(--srv);backdrop-filter:blur(6px)}
.srv-live i{width:6px;height:6px;border-radius:50%;background:currentColor;
  animation:srv-pulse 2s infinite}
@keyframes srv-pulse{0%,100%{opacity:1}50%{opacity:.35}}
.srv.off .srv-live{color:var(--dim);border-color:var(--line2)}
.srv.off .srv-live i{animation:none;background:var(--dim)}

.srv-body{padding:0 var(--s3) var(--s3);display:flex;flex-direction:column;gap:14px;flex:1}
.srv-top{display:flex;align-items:center;gap:13px;margin-top:-26px;position:relative;z-index:2}
.srv-badge{width:54px;height:54px;border-radius:14px;flex:none;display:grid;place-items:center;
  font-family:var(--disp);font-size:18px;color:var(--srv);
  background:linear-gradient(140deg,color-mix(in srgb,var(--srv) 20%,transparent),rgba(5,5,5,.92));
  border:1px solid var(--line2);
  border-color:color-mix(in srgb,var(--srv) 45%,transparent);
  box-shadow:0 8px 22px rgba(0,0,0,.55)}
.srv-titles{min-width:0}
.srv-name{font-weight:800;font-size:15px;margin:0 0 2px;line-height:1.3;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.srv-ip{font-size:11.5px;color:var(--dim);font-weight:400}

.srv-gauge{margin-top:auto}
.gauge-top{display:flex;justify-content:space-between;align-items:baseline;font-size:12.5px;margin-bottom:8px}
.gauge-top b{font-weight:800}
.gauge-top span{color:var(--dim);font-size:11px}
.bar{position:relative;height:6px;background:rgba(255,255,255,.06);border-radius:99px;overflow:hidden}
.bar i{display:block;height:100%;border-radius:99px;
  background:var(--srv);
  background:linear-gradient(90deg,color-mix(in srgb,var(--srv) 65%,#000),var(--srv));
  transform-origin:right center;transform:scaleX(0);transition:transform 1.1s cubic-bezier(.2,.7,.3,1)}
/* A slow sheen along the filled part, so a busy server looks alive rather than
   like a static rule. Stopped for reduced-motion by the guard at the file end. */
.bar i::after{content:"";position:absolute;inset:0;border-radius:99px;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.45),transparent);
  transform:translateX(-100%);animation:bar-sheen 3.2s ease-in-out infinite}
@keyframes bar-sheen{0%{transform:translateX(-100%)}55%,100%{transform:translateX(100%)}}

.srv-foot{display:flex;align-items:center;justify-content:space-between;gap:var(--s2);
  padding-top:14px;border-top:1px solid var(--line)}
.srv-wipe b{display:block;font-family:var(--disp);font-size:19px;color:var(--bone);line-height:1}
.srv-wipe span{font-size:10.5px;color:var(--dim);letter-spacing:.08em}
.srv-foot .btn{padding:9px 20px;font-size:13px}

/* ---------- STAT ROW ---------- */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--line);
  border:1px solid var(--line2);border-radius:16px;overflow:hidden}
@media(max-width:720px){.stats{grid-template-columns:repeat(2,1fr)}}
.stats>div{position:relative;background:var(--panel2);padding:var(--s3) var(--s3) var(--s3);
  transition:background .2s}
.stats>div:hover{background:var(--card-hover)}
/* One gold tick per cell, top-aligned: enough to tie the row to the brand
   without four gold numbers shouting at each other. */
.stats>div::before{content:"";position:absolute;top:0;inset-inline-start:var(--s3);
  width:26px;height:2px;background:var(--gold);border-radius:0 0 2px 2px}
.stats b{font-family:var(--disp);font-size:clamp(30px,3.4vw,42px);line-height:1;display:block;
  color:var(--white)}
.stats span{color:var(--mute);font-size:12px;font-weight:500;margin-top:8px;display:block}

/* ---------- SPLIT ---------- */
.split{display:grid;grid-template-columns:1fr 1fr;gap:var(--s5);align-items:center}
@media(max-width:900px){.split{grid-template-columns:1fr;gap:var(--s4)}}
.split-img{border-radius:14px;overflow:hidden;aspect-ratio:4/3}
.split-img img{width:100%;height:100%;object-fit:cover}
.pts{display:grid;grid-template-columns:1fr 1fr;gap:var(--s3) var(--s2);margin:var(--s3) 0}
@media(max-width:560px){.pts{grid-template-columns:1fr}}
.pt{border-inline-start:2px solid var(--rust);padding-inline-start:14px}
.pt b{display:block;font-size:14.5px;font-weight:700;margin-bottom:2px}
.pt span{font-size:13.5px;color:var(--mute);font-weight:300;line-height:1.7}

/* ---------- LEADERBOARD ---------- */
.lb{background:var(--panel2);border:1px solid var(--line2);border-radius:14px;overflow:hidden}
.lb-tabs{display:flex;gap:2px;padding:var(--s1);border-bottom:1px solid var(--line);overflow-x:auto}
.lb-tabs button{flex:none;background:none;border:0;color:var(--mute);font-family:var(--ui);font-size:13px;
  font-weight:500;padding:8px 16px;border-radius:7px;cursor:pointer;white-space:nowrap;transition:background .18s,color .18s}
.lb-tabs button:hover{color:var(--bone)}
.lb-tabs button.on{background:var(--rust);color:#050505;font-weight:700}
/* --- board rows -----------------------------------------------------------
   The top three carry a metal (--m); everyone below is plain grey. Three metals
   is the entire hierarchy, so fourth place gets none — that is what keeps a
   podium finish worth looking at. */
.row{--m:var(--dim);position:relative;display:grid;
  grid-template-columns:44px 44px minmax(0,1fr) minmax(112px,auto);gap:14px;align-items:center;
  padding:14px var(--s3);border-bottom:1px solid var(--line);
  animation:row-in .45s cubic-bezier(.2,.7,.3,1) both;animation-delay:calc(var(--i,0) * 60ms)}
@keyframes row-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.row:last-child{border-bottom:0}
.row.medal-1{--m:var(--gold)}
.row.medal-2{--m:var(--silver)}
.row.medal-3{--m:var(--bronze)}
/* A metal edge on the leading side, and only for the podium. */
.row.medal-1::before,.row.medal-2::before,.row.medal-3::before{content:"";position:absolute;
  inset-block:0;inset-inline-start:0;width:3px;background:var(--m)}
.row.medal-1{background:linear-gradient(to left,transparent 55%,rgba(217,165,46,.08))}
.row:hover{background:rgba(255,255,255,.035)}

.rank{font-family:var(--disp);font-size:17px;color:var(--m);opacity:.9}
.row.medal-1 .rank{font-size:20px;opacity:1}

.av-wrap{position:relative;width:44px;height:44px}
.av{width:44px;height:44px;border-radius:11px;object-fit:cover;background:var(--line);
  border:1px solid var(--line2)}
.row.medal-1 .av,.row.medal-2 .av,.row.medal-3 .av{border-color:color-mix(in srgb,var(--m) 60%,transparent)}
.row-crown{position:absolute;top:-11px;inset-inline-start:50%;transform:translateX(-50%);
  font-size:15px;font-style:normal;color:var(--gold);text-shadow:0 2px 8px rgba(217,165,46,.7)}

.who{min-width:0}
.who b{display:block;font-size:14px;font-weight:700;line-height:1.4;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.who span{display:block;color:var(--dim);font-size:11.5px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.row-val{text-align:end}
.val{font-family:var(--disp);font-size:18px;color:var(--bone);line-height:1}
.row.medal-1 .val{color:var(--gold);font-size:21px}
/* Length is the row's share of the leader's figure, so the gap between first
   and fifth is legible without reading a single number. */
.row-bar{display:block;height:3px;margin-top:7px;border-radius:99px;
  background:rgba(255,255,255,.07);overflow:hidden}
.row-bar i{display:block;height:100%;border-radius:99px;background:var(--m);
  transform-origin:right center;transform:scaleX(0);
  transition:transform .9s cubic-bezier(.2,.7,.3,1)}
.row:not(.medal-1):not(.medal-2):not(.medal-3) .row-bar i{background:var(--line2)}

@media(max-width:560px){
  .row{grid-template-columns:32px 40px minmax(0,1fr);gap:11px;padding:12px var(--s2)}
  .row-val{grid-column:2 / -1;text-align:start}
  .av-wrap,.av{width:40px;height:40px}
}

/* ---------- EVENTS ---------- */
.ev-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s2)}
@media(max-width:860px){.ev-grid{grid-template-columns:1fr}}
.ev{background:var(--panel2);border:1px solid var(--line2);border-radius:12px;overflow:hidden;
  transition:border-color .2s,transform .2s}
.ev:hover{border-color:var(--line2);transform:translateY(-3px)}
.ev-i{aspect-ratio:16/9;overflow:hidden;position:relative}
.ev-i img{width:100%;height:100%;object-fit:cover;transition:transform .6s}
.ev:hover .ev-i img{transform:scale(1.05)}
.tag{position:absolute;top:12px;inset-inline-start:12px;background:var(--rust);color:#050505;font-size:10px;
  font-weight:700;letter-spacing:.1em;padding:4px 9px;border-radius:5px}
.tag.news{background:#8A641B;color:#F5F5F2}
.ev-b{padding:var(--s2)}
.ev-b h3{font-size:15px;font-weight:700;margin:0 0 6px;line-height:1.5}
.ev-b span{color:var(--dim);font-size:12.5px}

/* ---------- GALLERY ---------- */
.gal{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}
@media(max-width:860px){.gal{grid-template-columns:repeat(2,1fr)}}
.gal a{border-radius:10px;overflow:hidden;aspect-ratio:1;display:block}
.gal img{width:100%;height:100%;object-fit:cover;transition:transform .6s}
.gal a:hover img{transform:scale(1.06)}

/* ---------- FAQ ---------- */
.faq-split{display:grid;grid-template-columns:320px 1fr;gap:var(--s5);align-items:start}
@media(max-width:900px){.faq-split{grid-template-columns:1fr;gap:var(--s3)}}
.faq-aside{position:sticky;top:100px}
@media(max-width:900px){.faq-aside{position:static}}
.faq-aside .sec-head{margin-bottom:var(--s2)}
.faq{display:flex;flex-direction:column;gap:6px}
/* Rows are cards that sit flat until touched, rather than a stack of
   hairlines. An open row gets a gold edge on its leading side, so the page
   shows WHICH question is open from across the screen instead of only by the
   rotated plus sign. */
.q{position:relative;border:1px solid transparent;border-radius:11px;
  background:transparent;transition:background .2s,border-color .2s}
.q::before{content:"";position:absolute;inset-block:10px;inset-inline-start:0;
  width:2px;border-radius:2px;background:var(--gold);opacity:0;transition:opacity .2s}
.q:hover{background:rgba(255,255,255,.022)}
.q[open]{background:rgba(255,255,255,.035);border-color:var(--line2)}
.q[open]::before{opacity:1}
.q summary{padding:17px 18px;cursor:pointer;font-weight:700;font-size:15px;line-height:1.6;
  display:flex;align-items:baseline;gap:14px;list-style:none;transition:color .18s}
.q summary::-webkit-details-marker{display:none}
.q summary:hover{color:var(--white)}
.q summary::before{content:"+";font-family:var(--disp);font-size:17px;color:var(--rust);flex:none;
  width:14px;transition:transform .25s;transform-origin:center}
.q[open] summary::before{transform:rotate(45deg)}
.q[open] summary{color:var(--white)}
.q .a{padding:0 46px 20px 18px;color:var(--mute);font-size:14.5px;font-weight:300;
  margin:0;max-width:62ch;line-height:1.9}
.q .a b{color:var(--bone);font-weight:700}

/* ---------- CTA + FOOTER ---------- */
.cta{position:relative;padding:var(--s6) 0;text-align:center;overflow:hidden}
.cta>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
/* A gold bloom behind the headline instead of a flat scrim, so the last
   thing on the page has the same warmth as the first. The vertical stops still
   bury the photo's edges in the page colour. */
.cta::after{content:"";position:absolute;inset:0;
  background:radial-gradient(58% 62% at 50% 46%,rgba(217,165,46,.17),transparent 68%),
             linear-gradient(to top,var(--ink) 4%,rgba(5,5,5,.88) 55%,rgba(5,5,5,.8) 100%)}
/* The same hairline that closes the hero, mirrored at the top of the CTA — the
   page opens and closes on the one edge that is allowed to be gold. */
.cta::before{content:"";position:absolute;inset:0 0 auto 0;height:1px;z-index:3;
  background:linear-gradient(90deg,transparent,rgba(217,165,46,.5),transparent)}
.cta-in{position:relative;z-index:2}
.cta h2{margin-bottom:10px}
.cta p{color:var(--mute);font-weight:300;margin:0 0 var(--s3)}
.cta-row{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}

/* The CTA image was static while the hero's drifts; matching them makes the
   page feel like one piece rather than two treatments. */
.cta>img{transform:scale(1.06);animation:cta-drift 34s ease-in-out infinite alternate}
@keyframes cta-drift{to{transform:scale(1.14) translate3d(-1.2%,1%,0)}}
@media(prefers-reduced-motion:reduce){.cta>img{animation:none}}

footer{background:var(--panel);border-top:1px solid var(--line);padding:var(--s4) 0}
.f-in{display:flex;justify-content:space-between;align-items:center;gap:var(--s3);flex-wrap:wrap}
.f-links{display:flex;gap:var(--s3);font-size:13.5px;color:var(--mute);flex-wrap:wrap}
.f-links a:hover{color:var(--rust)}
.f-in small{color:var(--dim);font-size:12.5px}

/* ---------- PRELOADER ---------- */
#load{position:fixed;inset:0;z-index:999;background:var(--ink);display:grid;place-items:center;
  transition:opacity .6s ease,visibility .6s}
#load.done{opacity:0;visibility:hidden}
.load-in{text-align:center;width:min(300px,78vw)}
.load-mark{font-family:var(--disp);font-size:40px;line-height:1;margin-bottom:4px;
  background:linear-gradient(100deg,var(--bone) 25%,var(--rust) 50%,var(--bone) 75%);
  background-size:220% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;
  animation:sheen 2s linear infinite}
@keyframes sheen{to{background-position:-220% 0}}
.load-sub{font-size:10.5px;letter-spacing:.28em;color:var(--dim);text-transform:uppercase;margin-bottom:22px}
.load-bar{height:2px;background:var(--line);border-radius:99px;overflow:hidden}
.load-bar i{display:block;height:100%;width:100%;border-radius:99px;transform:scaleX(0);transform-origin:right center;
  background:linear-gradient(90deg,var(--rust),var(--rust-hot));transition:transform .3s ease;will-change:transform}
.load-pct{margin-top:10px;font-family:var(--disp);font-size:12px;color:var(--dim)}

#prog{position:fixed;top:0;inset-inline:0;height:2px;z-index:60;transform-origin:right center;
  background:linear-gradient(90deg,var(--rust),var(--rust-hot));transform:scaleX(0)}
.rv{opacity:0;transform:translateY(20px);transition:opacity .65s cubic-bezier(.2,.7,.3,1),transform .65s cubic-bezier(.2,.7,.3,1)}
.rv.in{opacity:1;transform:none}

@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important;scroll-behavior:auto}
  .rv{opacity:1!important;transform:none!important}
  #embers{display:none}
}
@media(max-width:820px){
  .navlinks{display:none}
  .ev-grid{grid-template-columns:1fr}
  .hero{min-height:auto;padding-top:130px}
}

/* ============================================================================
   ADDITIONS — states the static mockup never had to show, in the same idiom.
   Nothing above this line differs from the approved design.
   ========================================================================== */

/* Empty states, for when a table has no rows yet. */
.empty{padding:var(--s4) var(--s3);text-align:center;color:var(--mute);font-size:14px;font-weight:300}
.empty b{display:block;color:var(--bone);font-weight:700;font-size:15px;margin-bottom:6px}

/* The main content region needs to clear the fixed nav on pages without a hero. */
.page-top{padding-top:calc(var(--s6) + 40px)}

/* Offline server: the gauge and the connect button stay, the badge goes grey. */
.srv.off .srv-badge{background:rgba(129,140,156,.08);border-color:var(--line2);color:var(--dim)}
.srv.off .srv-wipe b{color:var(--dim)}

/* ---- auth + owner panel ------------------------------------------------- */
.notice{padding:13px 17px;border-radius:10px;margin-bottom:var(--s2);font-size:14px;border:1px solid}
.notice-ok{background:rgba(63,207,127,.09);border-color:rgba(63,207,127,.35);color:#8FE9B8}
.notice-err{background:rgba(229,84,75,.09);border-color:rgba(229,84,75,.35);color:#FF9A8A}
.notice-warn{background:rgba(217,165,46,.09);border-color:rgba(217,165,46,.35);color:#E8C878}
.notice a{color:inherit;text-decoration:underline}

.login-methods{display:flex;flex-direction:column;gap:10px}
.login-methods .btn{justify-content:center;padding:15px}

.owner-group{background:var(--panel2);border:1px solid var(--line2);border-radius:14px;
  padding:var(--s3);margin-bottom:var(--s2)}
.owner-group-title{font-size:15px;font-weight:800;margin:0 0 var(--s2);color:var(--bone)}
.owner-field{margin-bottom:var(--s3)}
.owner-field:last-child{margin-bottom:0}
.owner-field label{display:flex;align-items:center;gap:9px;flex-wrap:wrap;
  font-size:13.5px;font-weight:700;margin-bottom:7px}
.owner-input{width:100%;background:rgba(255,255,255,.04);border:1px solid var(--line2);
  border-radius:9px;padding:11px 13px;color:var(--bone);font-family:var(--ui);font-size:14px;
  direction:ltr;text-align:left}
.owner-input:focus{outline:none;border-color:var(--rust)}
.owner-input:disabled{opacity:.5}
.owner-secret{display:flex;gap:8px}
.owner-secret .owner-input{flex:1}
.owner-help{display:block;color:var(--dim);font-size:11.5px;margin-top:6px;line-height:1.8}
.pill-ok,.pill-off,.pill-env{font-size:10px;font-weight:700;padding:3px 8px;border-radius:99px;letter-spacing:.04em}
.pill-ok{background:rgba(63,207,127,.14);color:var(--live)}
.pill-off{background:rgba(133,133,133,.18);color:var(--dim)}
.pill-env{background:rgba(217,165,46,.14);color:#D9A52E}

/* ---- phase 3: leaderboard, profile, dashboard --------------------------- */
.lb-tabs{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:var(--s2)}
.lb-tab{padding:8px 15px;border-radius:8px;font-size:13px;font-weight:500;
  color:var(--mute);background:var(--panel2);border:1px solid var(--line2);transition:all .18s}
.lb-tab:hover{color:var(--bone);border-color:var(--line2)}
.lb-tab.on{background:var(--gold);border-color:var(--gold);color:#050505;font-weight:800}
.lb-search{display:flex;gap:8px;margin-bottom:var(--s2)}
.lb-search .owner-input{flex:1;direction:rtl;text-align:right}
.lb-panel{background:var(--panel2);border:1px solid var(--line2);border-radius:14px;overflow:hidden}
.lb-panel .row{display:grid;grid-template-columns:44px 36px 1fr auto;gap:14px;align-items:center;
  padding:13px var(--s3);border-bottom:1px solid var(--line);transition:background .16s}
.lb-panel .row:last-child{border-bottom:0}
.lb-panel .row:hover{background:rgba(217,165,46,.06)}
.dot-live{display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--live);
  vertical-align:middle;margin-inline-end:4px}
.pager{display:flex;align-items:center;justify-content:center;gap:12px;margin-top:var(--s3)}
.pager-info{color:var(--mute);font-size:13px}

.profile-head{display:flex;align-items:center;gap:var(--s3);margin-bottom:var(--s4);flex-wrap:wrap}
.profile-av{width:84px;height:84px;border-radius:16px;object-fit:cover;background:var(--line);flex:none;display:block}
.profile-points{margin-inline-start:auto;text-align:center}
.profile-points b{display:block;font-family:var(--disp);font-size:34px;color:var(--rust);line-height:1}
.profile-points span{font-size:11.5px;color:var(--dim)}
.stat-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}
.stat-cell{background:rgba(255,255,255,.02);border:1px solid var(--line2);border-radius:11px;padding:14px}
.stat-cell b{display:block;font-family:var(--disp);font-size:22px;line-height:1;margin-bottom:5px}
.stat-cell span{font-size:12.5px;color:var(--mute)}
.stat-rank{display:block;font-size:11px;color:var(--dim);margin-top:5px}

.dash-top{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-bottom:var(--s2)}
.dash-card{background:var(--panel2);border:1px solid var(--line2);border-radius:14px;padding:var(--s3)}
.dash-card span{display:block;font-size:12.5px;color:var(--mute);margin-bottom:7px}
.dash-card b{font-family:var(--disp);font-size:32px;line-height:1;display:block}
.dash-card small{display:block;font-size:11px;color:var(--dim);margin-top:8px}
.link-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:12px 0;border-bottom:1px solid var(--line)}
.link-row:last-child{border-bottom:0}
.link-row>span:first-child{min-width:70px;color:var(--mute);font-size:13px}
.link-row form,.link-row .btn,.link-row .pill-ok{margin-inline-start:auto}
.muted{color:var(--dim);font-weight:400}
.tbl-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:11px 0;
  border-bottom:1px solid var(--line);font-size:13.5px}
.tbl-row:last-child{border-bottom:0}
.tbl-row b{min-width:150px}
.tbl-row .pill-ok,.tbl-row .pill-off,.tbl-row .pill-err{margin-inline-start:auto}
.pill-err{font-size:10px;font-weight:700;padding:3px 8px;border-radius:99px;
  background:rgba(229,84,75,.14);color:#FF9A8A}
.nav-user{display:inline-flex;align-items:center;gap:9px;padding:5px 12px 5px 5px;
  background:var(--panel2);border:1px solid var(--line2);border-radius:99px;font-size:13px}
.nav-user:hover{border-color:var(--rust)}
.nav-user img{width:26px;height:26px;border-radius:50%;object-fit:cover}
.nav-user-coin{color:var(--rust);font-weight:700}
@media(max-width:640px){.nav-user-name{display:none}}

/* ---- shop --------------------------------------------------------------- */
.shop-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:12px}
.shop-card{position:relative;background:rgba(255,255,255,.02);border:1px solid var(--line2);
  border-radius:13px;padding:18px 14px;text-align:center;transition:border-color .2s,transform .2s}
.shop-card:hover{border-color:var(--rust);transform:translateY(-3px)}
.shop-card.best{border-color:var(--rust);background:linear-gradient(180deg,rgba(217,165,46,.10),transparent)}
.shop-tag{position:absolute;top:-9px;inset-inline-start:50%;transform:translateX(50%);
  background:var(--rust);color:#050505;font-size:9.5px;font-weight:700;padding:3px 10px;
  border-radius:99px;white-space:nowrap}
.shop-card h4{font-family:var(--disp);font-size:19px;margin:0 0 9px}
.shop-price{margin-bottom:13px}
.shop-price span{font-family:var(--disp);font-size:26px;color:var(--rust);line-height:1}
.shop-price small{display:block;font-size:10.5px;color:var(--dim);letter-spacing:.1em;margin-top:4px}
.shop-card .btn{width:100%;justify-content:center;font-size:13px;padding:10px}
.veh-img{height:46px;width:auto;margin:0 auto 10px;object-fit:contain;display:block}

/* ---- leaderboard v2 ----------------------------------------------------- */
.lb-hero{position:relative;padding:170px 0 var(--s5);overflow:hidden;text-align:center;
  border-bottom:1px solid var(--line)}
.lb-hero-bg{position:absolute;inset:0}
.lb-hero-bg img{width:100%;height:100%;object-fit:cover;object-position:center 30%}
.lb-hero-bg::after{content:"";position:absolute;inset:0;
  background:radial-gradient(120% 90% at 50% 40%,rgba(5,5,5,.35),rgba(5,5,5,.88) 70%),
             linear-gradient(to top,var(--ink),transparent 55%)}
.lb-hero-in{position:relative;z-index:2}
.lb-kicker{font-size:11px;font-weight:700;letter-spacing:.26em;color:var(--rust);
  text-transform:uppercase;margin:0 0 14px}
.lb-title{font-family:var(--disp);font-size:clamp(48px,8vw,104px);line-height:.88;margin:0;
  text-transform:uppercase;text-shadow:0 4px 40px rgba(0,0,0,.5)}
.lb-sub{color:#C8C8C4;font-weight:300;margin:16px auto 0;font-size:15px;max-width:48ch}

.lb-stats{display:flex;justify-content:center;gap:1px;margin:var(--s4) auto 0;max-width:620px;
  background:var(--line);border:1px solid var(--line2);border-radius:14px;overflow:hidden}
.lb-stats>div{flex:1;background:rgba(14,20,29,.88);backdrop-filter:blur(8px);padding:16px 10px}
.lb-stats b{display:block;font-family:var(--disp);font-size:26px;line-height:1}
.lb-stats span{font-size:10.5px;color:var(--mute);margin-top:5px;display:block}

.lb-body{padding:var(--s5) 0 var(--s6)}
/* Two columns since the categories moved to the top row. The rail that used
   to hold them is gone; what is left is the board and the widgets. */
.lb-layout{display:grid;grid-template-columns:minmax(0,1fr) 250px;gap:var(--s3);align-items:start}
@media(max-width:1180px){
  .lb-layout{grid-template-columns:minmax(0,1fr) 250px}
  /* The category nav must not vanish here: below this width it was the ONLY way
     to change board, and hiding it left the page stuck on overall points. It
     becomes a scrollable chip row above the table instead of disappearing. */
  .lb-side{position:static;grid-column:1/-1;display:flex;gap:6px;overflow-x:auto;
    padding-bottom:6px;scrollbar-width:none}
  .lb-side::-webkit-scrollbar{display:none}
  .lb-side-title{display:none}
  .lb-side-link{flex:none;margin:0;white-space:nowrap;border:1px solid var(--line2)}
}
@media(max-width:880px){.lb-layout{grid-template-columns:minmax(0,1fr)}.lb-rail{display:none}}

.lb-side{position:sticky;top:92px}
.lb-side-title,.lb-widget-title{font-size:10px;font-weight:700;letter-spacing:.18em;
  color:var(--dim);text-transform:uppercase;margin:0 0 12px}
.lb-side-link{display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:9px;
  font-size:13.5px;color:var(--mute);margin-bottom:2px;transition:color .16s,background .16s}
.lb-side-dot{width:5px;height:5px;border-radius:50%;background:var(--line2);flex:none;transition:background .16s}
.lb-side-link:hover{color:var(--bone);background:rgba(255,255,255,.03)}
.lb-side-link:hover .lb-side-dot{background:var(--mute)}
.lb-side-link.on{color:var(--bone);background:rgba(217,165,46,.10);font-weight:700}
.lb-side-link.on .lb-side-dot{background:var(--rust);box-shadow:0 0 0 3px rgba(217,165,46,.18)}

.lb-main{background:var(--panel2);border:1px solid var(--line2);border-radius:16px;
  padding:var(--s3) var(--s3) var(--s2);min-width:0}
.lb-main-head{display:flex;align-items:center;justify-content:space-between;gap:var(--s2);
  flex-wrap:wrap;margin-bottom:var(--s3)}
.lb-main-title{display:flex;align-items:baseline;gap:11px;flex-wrap:wrap}
.lb-main-title h2{font-size:21px;margin:0}
.lb-count{font-size:12px;color:var(--dim)}
.lb-search{position:relative;flex:0 1 260px;margin:0}
.lb-input{width:100%;background:rgba(255,255,255,.03);border:1px solid var(--line2);
  border-radius:10px;padding:10px 14px;color:var(--bone);font-family:var(--ui);font-size:13px}
.lb-input:focus{outline:none;border-color:var(--rust);background:rgba(255,255,255,.05)}
.lb-input::placeholder{color:var(--dim)}
.lb-clear{position:absolute;inset-inline-start:10px;top:50%;transform:translateY(-50%);
  color:var(--dim);font-size:17px;line-height:1}
.lb-clear:hover{color:var(--rust)}

/* --- player profile --- */
.pf-hero{position:relative;padding:150px 0 var(--s4);overflow:hidden;border-bottom:1px solid var(--line)}
.pf-hero-bg{position:absolute;inset:0}
.pf-hero-bg img{width:100%;height:100%;object-fit:cover;object-position:center 35%}
.pf-hero-bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,var(--ink),rgba(5,5,5,.7) 55%,rgba(5,5,5,.45))}
/* Two blocks, pushed apart. A single right-aligned block left the whole banner
   empty on one side, which is what made the page read as unfinished. */
.pf-hero-in{position:relative;z-index:2;display:flex;align-items:center;
  justify-content:space-between;gap:var(--s3);flex-wrap:wrap}
.pf-idblock{display:flex;align-items:center;gap:var(--s3);min-width:0;flex:1}

.pf-av-wrap{position:relative;flex:none}
.pf-av{width:116px;height:116px;border-radius:22px;object-fit:cover;display:block;
  border:1px solid var(--line2);box-shadow:0 16px 48px rgba(0,0,0,.6)}
/* The letter is the accent, the tile is near-black — not the other way round.
   White on a light accent (champagne, silver) measured 2.2:1; this way the
   contrast holds for every value --a can take, and it matches the mockup's
   dark tiles with gold glyphs. */
.pf-av-init{display:grid;place-items:center;font-weight:900;font-size:46px;color:var(--a);
  background:linear-gradient(140deg,rgba(255,255,255,.06),rgba(5,5,5,.9));
  border:1px solid var(--line2)}
/* Only the #1 player gets the crown, so it stays worth something. */
.pf-crown{position:absolute;top:-15px;inset-inline-start:50%;transform:translateX(-50%);
  font-size:24px;color:#D9A52E;text-shadow:0 2px 12px rgba(217,165,46,.65)}

.pf-id{min-width:0}
.pf-name{font-family:var(--ui);font-weight:900;font-size:clamp(26px,4vw,42px);line-height:1.15;
  margin:0 0 10px;letter-spacing:-.01em;word-break:break-word}
.pf-clan{font-weight:700;color:var(--rust);font-size:.6em;vertical-align:middle}
.pf-meta{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin:0 0 10px;
  font-size:12px;color:var(--mute)}
.pf-meta b{color:var(--bone)}
.pf-steam{margin:9px 0 0;font-size:11px;color:var(--dim)}
.pf-tags{display:flex;gap:6px;flex-wrap:wrap;margin:0}
.pf-tag{font-size:11px;font-weight:700;padding:5px 11px;border-radius:99px;
  border:1px solid var(--line2);background:rgba(5,5,5,.5);color:var(--mute)}
.pf-tag-raider{color:#FF9A8A;border-color:rgba(217,165,46,.45)}
.pf-tag-pvp{color:#E8C878;border-color:rgba(217,165,46,.45)}
.pf-tag-builder{color:#8FE9B8;border-color:rgba(63,207,127,.4)}
.pf-tag-farmer{color:#F5F5F2;border-color:rgba(245,245,242,.4)}
.pf-tag-veteran{color:#E8C878;border-color:rgba(167,139,250,.45)}

/* career panel: fills the other half of the banner */
.pf-career{display:flex;align-items:center;gap:var(--s2);flex:none;
  background:rgba(13,13,13,.82);border:1px solid var(--line2);border-radius:16px;
  padding:16px 20px;backdrop-filter:blur(10px)}
.pf-ring{--p:0;position:relative;width:84px;height:84px;border-radius:50%;flex:none;
  display:grid;place-items:center;text-align:center;
  background:conic-gradient(var(--rust) calc(var(--p)*1%),rgba(255,255,255,.08) 0)}
.pf-ring::after{content:"";position:absolute;inset:6px;border-radius:50%;background:var(--panel2)}
.pf-ring b,.pf-ring span{position:relative;z-index:1;display:block}
.pf-ring b{font-family:var(--disp);font-size:26px;line-height:1}
.pf-ring span{font-size:9px;letter-spacing:.14em;color:var(--dim);text-transform:uppercase;margin-top:3px}
/* Wide enough for its own labels. Measured at 52px before this, which wrapped
   "امتیاز کل" onto two lines and made the block look broken. */
.pf-career-x{min-width:104px}
.pf-career-x>div{margin-bottom:12px}
.pf-career-x>div:last-child{margin-bottom:0}
.pf-career-x span{display:block;font-size:9.5px;letter-spacing:.12em;color:var(--dim);
  text-transform:uppercase;margin-bottom:4px;white-space:nowrap}
.pf-career-x b{font-family:var(--disp);font-size:21px;line-height:1}
@media(max-width:760px){.pf-career{width:100%;justify-content:center}}

/* stat bar */
.pf-bar{background:var(--panel);border-bottom:1px solid var(--line);padding:0}
.pf-kpis{display:grid;grid-template-columns:1.5fr repeat(5,1fr);gap:1px;background:var(--line)}
@media(max-width:1000px){.pf-kpis{grid-template-columns:repeat(3,1fr)}}
@media(max-width:560px){.pf-kpis{grid-template-columns:repeat(2,1fr)}}
.pf-kpi{background:var(--panel);padding:20px 14px;text-align:center;min-width:0}
.pf-kpi span{display:block;font-size:9.5px;letter-spacing:.14em;color:var(--dim);
  text-transform:uppercase;margin-bottom:8px}
.pf-kpi b{font-family:var(--disp);font-size:27px;line-height:1;display:block}
.pf-kpi i{font-style:normal;font-size:14px;color:var(--dim)}
.pf-kpi small{display:block;font-size:10px;color:var(--mute);margin-top:7px}
.pf-kpi-hero b{color:#D9A52E;font-size:32px}

/* tabs + cards */
.pf-body{padding:var(--s3) 0 var(--s6)}
/* One control row: content tabs on one side, filters on the other. The border
   sits on the ROW so the rule runs the full width and the tabs sit on it,
   instead of a second stacked bar with an underline trailing into empty space. */
.pf-bar-row{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s2);
  flex-wrap:wrap;margin:0 0 var(--s3);border-bottom:1px solid var(--line)}
.pf-filters{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding-bottom:8px}
.pf-filters .lb-tab{padding:6px 12px;font-size:11.5px}
.pf-filters .lb-scope a{padding:5px 11px;font-size:11.5px}
.pf-tabs{display:flex;gap:4px;flex-wrap:wrap;margin:0}
.pf-tabl{padding:11px 16px;font-size:13px;font-weight:700;color:var(--mute);
  border-bottom:2px solid transparent;margin-bottom:-1px;white-space:nowrap}
.pf-tabl:hover{color:var(--bone)}
.pf-tabl.on{color:var(--bone);border-bottom-color:var(--rust)}

/* dense: a card spanning two columns otherwise leaves a hole beside it that
   nothing backfills - that was most of the dead space on the profile. */
.pf-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s2);
  align-items:start;grid-auto-flow:dense}
@media(max-width:1000px){.pf-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:680px){.pf-grid{grid-template-columns:minmax(0,1fr)}}
.card{background:var(--panel2);border:1px solid var(--line2);border-radius:14px;padding:var(--s2) 18px;
  transition:background .18s,border-color .18s}
.card:hover{background:var(--card-hover);border-color:#333}
.card-wide{grid-column:span 2}
@media(max-width:680px){.card-wide{grid-column:span 1}}
.card-t{font-size:12px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  color:var(--bone);margin:0 0 var(--s2);display:flex;align-items:center;gap:9px}
/* The gold marker carries the accent so the heading itself can stay white.
   Every card title in gold was most of the "whole site is yellow" problem. */
.card-t::before{content:"";width:3px;height:13px;border-radius:2px;background:var(--gold);flex:none}
.card-sub{font-size:11px;font-weight:700;color:var(--dim);margin:var(--s3) 0 10px;
  letter-spacing:.1em;text-transform:uppercase}
.card-empty{font-size:12.5px;line-height:1.9;color:var(--dim);margin:0}
.card-note{font-size:11px;line-height:1.8;color:var(--dim);margin:12px 0 0}
.card-note b{color:var(--mute)}
.card-more{display:inline-block;margin-top:14px;font-size:12px;font-weight:700;color:var(--mute)}
.card-more:hover{color:var(--rust-hot)}

.pf-facts{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.pf-facts>div{background:rgba(255,255,255,.03);border-radius:10px;padding:12px 10px;text-align:center;min-width:0}
.pf-facts span{display:block;font-size:9.5px;letter-spacing:.1em;color:var(--dim);
  text-transform:uppercase;margin-bottom:6px}
.pf-facts b{font-size:14px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* radar */
.pf-radar{width:100%;max-width:230px;margin:0 auto;display:block;aspect-ratio:1}
.pf-radar-k{display:flex;flex-wrap:wrap;gap:6px 14px;justify-content:center;margin-top:12px;font-size:11px}
.pf-radar-k b{color:var(--mute);font-weight:600}
.pf-radar-k i{font-style:normal;color:var(--bone);font-weight:700}

/* comparison */
.pf-cmp{display:flex;align-items:center;gap:10px;font-size:12.5px;margin-top:14px}
.pf-cmp b{flex:1;min-width:0}
.pf-cmp-x{font-weight:800}
.pf-cmp-x.up{color:var(--live)}
.pf-cmp-x.down{color:var(--mute)}

.pf-splitbar{position:relative;height:6px;border-radius:99px;background:rgba(255,255,255,.06);
  overflow:hidden;margin-top:7px}
.pf-splitbar-l{height:9px}
.pf-splitbar i{display:block;height:100%;border-radius:99px;background:var(--rust)}
/* The tick marks the average, so a bar can be read without the number. */
.pf-splitbar u{position:absolute;top:0;bottom:0;inset-inline-start:50%;width:1px;
  background:rgba(255,255,255,.35)}

.pf-tierrow{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:6px}
.pf-tierrow .tier.off{opacity:.4}
.pf-arrow{color:var(--dim)}

/* per-wipe bars */
.pf-bars{display:flex;align-items:flex-end;gap:10px;height:150px;overflow-x:auto;padding-top:6px}
.pf-bar-col{flex:1;min-width:46px;display:flex;flex-direction:column;justify-content:flex-end;
  align-items:center;height:100%;text-align:center}
.pf-bar-col i{display:block;width:100%;max-width:52px;border-radius:6px 6px 0 0;
  background:linear-gradient(to top,var(--rust),#F2C75C);min-height:2px}
.pf-bar-col span{font-size:11px;font-weight:700;margin-top:7px}
.pf-bar-col small{font-size:9.5px;color:var(--dim);margin-top:2px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;max-width:100%}

/* category standing */
.pf-cats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s2) var(--s3)}
@media(max-width:560px){.pf-cats{grid-template-columns:minmax(0,1fr)}}
.pf-cat-h{display:flex;align-items:baseline;gap:10px;font-size:12.5px}
.pf-cat-h b{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pf-cat small{display:block;font-size:10.5px;margin-top:6px}

.pf-weap,.pf-rival{display:flex;align-items:center;gap:10px;font-size:12.5px;margin-top:13px}
.pf-weap b,.pf-rival b{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pf-rival{padding-bottom:9px;border-bottom:1px solid rgba(41,41,41,.6);margin-top:9px}
.pf-rival:last-of-type{border-bottom:0}

.pf-badges{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.pf-badges-all{grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
.pf-badge{background:rgba(255,255,255,.03);border:1px solid var(--line2);border-radius:12px;
  padding:14px 10px;text-align:center;opacity:.5}
.pf-badge.got{opacity:1;border-color:rgba(217,165,46,.4);background:rgba(217,165,46,.08)}
.pf-badge-i{display:block;font-size:20px;color:var(--dim);margin-bottom:7px}
.pf-badge.got .pf-badge-i{color:#D9A52E}
.pf-badge b{display:block;font-size:12px}
.pf-badge small{display:block;font-size:10px;color:var(--dim);margin-top:5px;line-height:1.6}

.pf-split{display:flex;align-items:center;gap:9px;font-size:12.5px;margin-top:12px}
.pf-split b{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pf-dot{width:9px;height:9px;border-radius:3px;background:var(--a);flex:none}

.pf-hist{overflow-x:auto}
.pf-hist-h,.pf-hist-r{display:grid;grid-template-columns:minmax(150px,1.6fr) repeat(5,minmax(56px,1fr));
  gap:10px;align-items:center;min-width:520px}
.pf-hist-h{padding-bottom:10px;border-bottom:1px solid var(--line);font-size:10px;
  font-weight:700;letter-spacing:.12em;color:var(--dim);text-transform:uppercase}
.pf-hist-r{padding:12px 0;border-bottom:1px solid rgba(41,41,41,.6);font-size:13px}
.pf-hist-r:last-child{border-bottom:0}
.pf-hist-r small{display:block;font-size:10px;margin-top:3px}

.pf-server-row{display:flex;align-items:center;gap:10px;padding:11px 0;
  border-bottom:1px solid rgba(41,41,41,.6);font-size:13px}
.pf-server-row:last-of-type{border-bottom:0}
.pf-server-row b{flex:1;min-width:0}
.pf-server-row:hover b{color:var(--rust)}
.pf-actions{margin-top:var(--s3)}

/* --- owner: wipe management --- */
.owner-nav{display:flex;gap:6px;flex-wrap:wrap;margin:0 0 var(--s3);font-size:13px}
.owner-nav a,.owner-nav .on{padding:7px 14px;border-radius:9px;border:1px solid var(--line2);
  color:var(--mute);font-weight:700}
.owner-nav a:hover{color:var(--bone);border-color:var(--mute)}
.owner-nav .on{color:#fff;background:rgba(217,165,46,.13);border-color:rgba(217,165,46,.55)}
.owner-tabs{margin-bottom:var(--s3)}

.wipe-row{padding:var(--s2) 0;border-bottom:1px solid var(--line)}
.wipe-row:last-child{border-bottom:0;padding-bottom:0}
.wipe-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:12px}
.wipe-head b{font-size:14.5px}
.wipe-meta{font-size:11.5px;color:var(--dim)}
.wipe-meta b{font-size:12.5px;color:var(--mute)}
.wipe-actions{display:grid;grid-template-columns:1fr 1fr;gap:var(--s2)}
@media(max-width:700px){.wipe-actions{grid-template-columns:1fr}}
.wipe-form{display:flex;gap:8px;align-items:center}
.wipe-form .owner-input{flex:1;min-width:0;font-size:12.5px;padding:9px 12px}
.wipe-form .btn,.wipe-form .btn-danger{flex:none;white-space:nowrap}

/* Destructive controls look destructive. They are one click from deleting a
   season of player history, so they do not share the neutral button style. */
.btn-danger{background:transparent;border:1px solid rgba(229,84,75,.55);color:#FF9A8A;
  padding:10px 16px;border-radius:8px;font-family:var(--ui);font-weight:700;font-size:13px;
  cursor:pointer;transition:background .16s,color .16s,border-color .16s}
.btn-danger:hover:not(:disabled){background:var(--danger);color:#fff;border-color:var(--danger)}
.btn-danger:disabled{opacity:.45;cursor:not-allowed}
.owner-danger{border-color:rgba(217,165,46,.3)}
.owner-danger .owner-group-title{color:#FF9A8A}

/* --- dashboard: tabs, clan, achievements, history -------------------------- */
.db-tabs{margin-bottom:var(--s2)}
.db-tabdot{display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--rust);
  margin-inline-start:6px;vertical-align:middle}

/* Unclaimed XP is money already earned and not yet handed over, so it gets the
   one interrupting element on the page. */
.db-claimbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:var(--s2);
  padding:13px 18px;border-radius:12px;font-size:12.5px;
  background:linear-gradient(90deg,rgba(217,165,46,.16),rgba(217,165,46,.05));
  border:1px solid rgba(217,165,46,.4);color:#E8C878}
.db-claimbar b{font-family:var(--disp);font-size:20px;line-height:1;color:#D9A52E}
.db-claimbar span{flex:1;min-width:0}
.db-claimbar i{font-style:normal;font-weight:700;color:#D9A52E}
.db-claimbar:hover{border-color:#D9A52E;
  background:linear-gradient(90deg,rgba(217,165,46,.24),rgba(217,165,46,.08))}

/* clan */
.db-clanhead{display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  padding-bottom:var(--s2);border-bottom:1px solid rgba(41,41,41,.6);margin-bottom:6px}
.db-clanbadge{width:52px;height:52px;border-radius:14px;flex:none;display:grid;place-items:center;
  font-family:var(--disp);font-size:19px;color:var(--gold);letter-spacing:.02em;
  background:linear-gradient(140deg,rgba(217,165,46,.14),rgba(5,5,5,.9));
  border:1px solid rgba(217,165,46,.4)}
.db-claninfo{flex:1;min-width:140px}
.db-claninfo b{display:block;font-family:var(--disp);font-size:20px;line-height:1.2;margin-bottom:5px}
.db-claninfo span{font-size:11.5px;color:var(--mute)}
.db-on{color:var(--live)}
.db-clantag{font-weight:800;color:var(--rust);letter-spacing:.02em}
.db-clantag:hover{color:var(--rust-hot)}

.db-roster{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 var(--s2)}
@media(max-width:640px){.db-roster{grid-template-columns:minmax(0,1fr)}}
.db-member{display:flex;align-items:center;gap:9px;padding:9px 0;font-size:12.5px;
  border-bottom:1px solid rgba(41,41,41,.5)}
.db-member b{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-weight:600}
.db-member:hover b{color:var(--rust)}
.db-member.me b{color:#E8C878}
.db-member-dot{width:7px;height:7px;border-radius:50%;background:var(--line2);flex:none}
.db-member-dot.on{background:var(--live);box-shadow:0 0 0 3px rgba(63,207,127,.16)}
.db-role{font-size:10px;font-weight:700;padding:2px 7px;border-radius:99px;
  border:1px solid var(--line2);color:var(--dim);white-space:nowrap}

/* achievements */
.db-ach{display:flex;flex-direction:column;gap:7px;padding:16px 13px}
.db-ach.ready{border-color:rgba(217,165,46,.55);background:rgba(217,165,46,.1)}
.db-ach small{color:var(--dim);line-height:1.7}
.db-achbar{height:5px;border-radius:99px;background:rgba(255,255,255,.07);overflow:hidden;
  margin-top:3px}
.db-achbar i{display:block;height:100%;border-radius:99px;background:var(--rust)}
.db-achstate{font-size:10.5px;font-weight:700;color:var(--dim);margin-top:3px}
.db-achstate.done{color:var(--live)}
.db-achclaim{width:100%;margin-top:4px;padding:8px 10px;font-size:11.5px}

/* --- staff panel ----------------------------------------------------------- */
.sf-shell{padding:150px 0 var(--s6)}
.sf-tools{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;margin-bottom:var(--s2)}
.sf-search{display:flex;gap:8px;margin-inline-start:auto}
.sf-search .lb-input{min-width:230px}
.sf-unread{font-size:12.5px;color:var(--gold-light);margin:0 0 var(--s2)}
.sf-unread b{font-family:var(--disp);font-size:17px;color:var(--gold)}

.sf-row{display:flex;align-items:center;gap:12px;padding:13px 0;font-size:12.5px;
  border-bottom:1px solid var(--line)}
.sf-row:last-child{border-bottom:0}
/* Unanswered work is the only thing that gets emphasis in this list. */
.sf-row.unread{background:rgba(217,165,46,.05)}
.sf-main{flex:1;min-width:0}
.sf-main b{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sf-main span{display:block;font-size:11.5px;color:var(--dim);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sf-row:hover .sf-main b{color:var(--gold)}
.sf-who{min-width:150px;text-align:end}
.sf-who b{display:block;font-size:12.5px}
.sf-who span{font-size:10.5px}
.sf-badge{flex:none;min-width:22px;padding:2px 7px;border-radius:99px;text-align:center;
  font-size:11px;font-weight:800;background:var(--gold);color:#050505}

.sf-head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s2);
  flex-wrap:wrap}
.sf-subject{font-size:20px;margin:0 0 8px;line-height:1.35}
.sf-meta{display:flex;gap:12px;flex-wrap:wrap;font-size:12px;color:var(--mute);margin:0}
.sf-meta a{color:var(--gold)}

.sf-msg{padding:14px 0;border-bottom:1px solid rgba(41,41,41,.6)}
.sf-msg:last-child{border-bottom:0}
.sf-msg-who{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap;font-size:11.5px;
  margin-bottom:7px}
.sf-msg-who b{font-size:12.5px}
.sf-msg.staff .sf-msg-who b{color:var(--gold)}
.sf-msg-body{margin:0;font-size:13.5px;line-height:2;color:var(--mute);white-space:pre-wrap}
.sf-msg.staff .sf-msg-body{color:var(--bone)}
.sf-states{display:flex;gap:8px;flex-wrap:wrap}
.sf-states .btn{padding:8px 15px;font-size:12.5px}
.sf-states .btn.on{border-color:var(--gold);color:var(--gold)}

.os-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:13px 0;
  border-bottom:1px solid var(--line)}
.os-row:last-of-type{border-bottom:0}
.os-main{flex:1;min-width:160px}
.os-main b{display:block;font-size:13.5px}
.os-main span{font-size:11px}

/* Discord role states. A row of quiet tiles: these numbers are for scanning,
   not for celebrating, so none of them wears the brand colour — the only gold
   on this page is the primary button. */
.os-counts{display:grid;grid-template-columns:repeat(auto-fit,minmax(96px,1fr));
  gap:10px;margin-bottom:var(--s2)}
.os-count{background:var(--panel);border:1px solid var(--line2);border-radius:11px;
  padding:12px 10px;text-align:center}
.os-count b{display:block;font-size:19px;font-weight:800;color:var(--bone);line-height:1.25}
.os-count span{font-size:10.5px;color:var(--dim)}

/* ===================================================================
   PERMANENT SITE CLANS

   Gold appears in exactly three places on a clan page: the emblem ring,
   the level chip, and the single primary action. A clan page that wears
   gold everywhere stops reading as status and starts reading as a
   warning banner.
   =================================================================== */

.cp-hero{position:relative;border-bottom:1px solid var(--line2);
  background:linear-gradient(180deg,var(--panel) 0%,var(--ink) 100%);overflow:hidden}
/* The banner sits in a pseudo-element so the overlay gradient can sit on top
   of it without also dimming the text, which is a child of the hero. */
.cp-hero.has-banner::before{content:"";position:absolute;inset:0;
  background-image:var(--banner);background-size:cover;background-position:center;
  opacity:.42}
.cp-hero.has-banner::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(5,5,5,.35) 0%,rgba(5,5,5,.92) 100%)}
.cp-hero-in{position:relative;z-index:1;display:flex;align-items:center;
  gap:var(--s3);padding:var(--s4) var(--s2);flex-wrap:wrap}

.cp-emblem{width:104px;height:104px;flex:none;border-radius:20px;
  border:2px solid var(--accent);background:var(--ink);
  display:grid;place-items:center;overflow:hidden;
  box-shadow:0 0 0 6px rgba(0,0,0,.45)}
.cp-emblem img{width:100%;height:100%;object-fit:cover}
.cp-emblem span{font-size:40px;font-weight:800;color:var(--accent)}

/* flex-basis with a min-width guard: without it this column collapses to a few
   pixels beside the CTA at narrow widths and a clan name breaks one letter per
   line. The dashboard hero had exactly this bug. */
.cp-id{flex:1 1 260px;min-width:min(260px,100%);max-width:640px}
.cp-name{font-size:clamp(28px,5vw,46px);font-weight:800;line-height:1.1;margin:0;
  color:var(--white);letter-spacing:-.01em;
  /* Headings on this site are uppercased by the base style. A clan name is a
     name its owner chose and typed, so it renders exactly as entered — a
     player who wrote "ShadowLegion" did not ask for "SHADOWLEGION". */
  text-transform:none}
.cp-motto{margin:8px 0 0;font-size:14px;color:var(--mute);font-weight:300}

.cp-chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.cp-chip{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;
  border-radius:999px;font-size:11.5px;font-weight:600;color:var(--mute);
  background:rgba(255,255,255,.05);border:1px solid var(--line2)}
.cp-chip-lv{color:#050505;background:var(--gold);border-color:var(--gold)}
.cp-chip-open{color:var(--live);border-color:rgba(90,200,120,.35)}

.cp-cta{flex:none;display:flex;align-items:center;gap:10px}
.cp-note{font-size:12px;color:var(--dim)}

.cp-grid{display:grid;grid-template-columns:1.15fr 1fr 1fr;gap:var(--s2);
  align-items:start;margin:var(--s3) 0 var(--s4)}
@media(max-width:980px){.cp-grid{grid-template-columns:1fr 1fr}}
@media(max-width:680px){.cp-grid{grid-template-columns:1fr}}
.cp-col{display:flex;flex-direction:column;gap:var(--s2);min-width:0}

.cp-about{margin:0;font-size:13.5px;line-height:2;color:var(--mute);
  white-space:pre-line}
.cp-locked{margin-top:var(--s3)}

.cp-stat{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:11px 0;border-bottom:1px solid var(--line);font-size:12.5px;color:var(--dim)}
.cp-stat:last-of-type{border-bottom:0}
.cp-stat b{color:var(--bone);font-size:14px}
.cp-next{display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-top:12px;padding:11px 13px;border-radius:10px;font-size:12px;
  background:rgba(217,165,46,.07);border:1px solid rgba(217,165,46,.22);color:var(--gold-light)}

.cp-hist{display:flex;align-items:center;gap:10px;padding:11px 0;
  border-bottom:1px solid var(--line);font-size:12.5px}
.cp-hist:last-of-type{border-bottom:0}
.cp-hist b{color:var(--bone)}
.cp-hist small{margin-inline-start:auto}

.cp-member{display:flex;align-items:center;gap:10px;padding:9px 0;
  border-bottom:1px solid var(--line);min-width:0}
.cp-member:last-of-type{border-bottom:0}
.cp-member img,.cp-member-init{width:32px;height:32px;border-radius:9px;flex:none;
  object-fit:cover}
.cp-member-init{display:grid;place-items:center;background:var(--ink);
  color:var(--gold);font-weight:800;font-size:13px;border:1px solid var(--line2)}
.cp-member-id{flex:1;min-width:0}
.cp-member-id b{display:block;font-size:13px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.cp-member-id small{font-size:10.5px}
.cp-donated{flex:none;font-size:11px;color:var(--gold-light)}

.cp-donate{display:flex;gap:10px;align-items:center;margin-top:12px}
.cp-donate input{flex:1;min-width:0}

/* Preset pickers. A radio whose label wraps the image, so the whole tile is the
   hit target and the checked state can be styled without JavaScript. */
.cp-picker{display:grid;grid-template-columns:repeat(auto-fill,minmax(72px,1fr));gap:10px}
.cp-picker-wide{grid-template-columns:repeat(auto-fill,minmax(160px,1fr))}
.cp-pick{position:relative;cursor:pointer;border-radius:11px;overflow:hidden;
  border:2px solid var(--line2);aspect-ratio:1;display:block}
.cp-picker-wide .cp-pick{aspect-ratio:16/6}
.cp-pick img{width:100%;height:100%;object-fit:cover;display:block}
.cp-pick input{position:absolute;opacity:0;pointer-events:none}
.cp-pick:has(input:checked){border-color:var(--gold)}
.cp-pick:has(input:focus-visible){outline:2px solid var(--gold);outline-offset:2px}

/* clan directory row */
.cb-row{display:flex;align-items:center;gap:12px;padding:12px 0;
  border-bottom:1px solid var(--line)}
.cb-row:last-of-type{border-bottom:0}
.cb-emblem{width:38px;height:38px;border-radius:11px;flex:none;display:grid;
  place-items:center;overflow:hidden;background:var(--ink);border:1px solid var(--line2);
  color:var(--gold);font-weight:800}
.cb-emblem img{width:100%;height:100%;object-fit:cover}
.cb-id{flex:1;min-width:0}
.cb-id b{display:block;font-size:13.5px}
.cb-id small{font-size:11px}

/* clan shop row */
.cu-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:13px 0;
  border-bottom:1px solid var(--line)}
.cu-row:last-of-type{border-bottom:0}
.cu-row.owned{opacity:.75}
.cu-row.soon{opacity:.5}
.cu-id{flex:1;min-width:170px}
.cu-id b{display:block;font-size:13.5px}
.cu-id small{display:block;font-size:11px;line-height:1.7;margin-top:3px}
.cu-price{flex:none;font-size:12.5px;color:var(--gold-light);font-weight:700}

/* shared form bits for the clan forms */
.cf-form{display:flex;flex-direction:column;gap:12px;align-items:flex-start;margin-top:14px}
.cf-form .owner-input,.cf-form select{width:100%}
.cf-field{display:block;margin-bottom:14px}
.cf-field>span{display:block;font-size:12px;color:var(--mute);margin-bottom:7px}
.cf-check{display:flex;align-items:center;gap:9px;font-size:12.5px;
  color:var(--mute);margin:4px 0 16px;cursor:pointer}

/* Clan history on a player profile. A past clan is dimmed rather than hidden —
   the point of the list is that it remembers, so the old rows have to be
   visible enough to read while still ranking below the current one. */
.ch-row{display:flex;align-items:center;gap:11px;padding:11px 0;
  border-bottom:1px solid var(--line);min-width:0}
.ch-row:last-of-type{border-bottom:0}
.ch-row.past{opacity:.62}
.ch-mark{--accent:var(--gold);width:34px;height:34px;flex:none;border-radius:10px;
  display:grid;place-items:center;background:var(--ink);color:var(--accent);
  border:1px solid var(--line2);font-weight:800;font-size:14px}
.ch-id{flex:1;min-width:0}
.ch-id b{display:block;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ch-id small{font-size:10.5px}

/* The scrap balance in the account menu. The icon is the live site's own, so
   the currency reads the same here as it does in game. */
.nav-menu-coin{display:inline-flex;align-items:center;gap:6px}
.nav-menu-coin img{width:16px;height:16px;object-fit:contain;flex:none}
.nav-menu-coin b{font-size:12.5px;font-weight:700;color:var(--gold)}

/* ===================================================================
   IN-GAME CLAN: activity shape + contribution board

   One hue per activity group, reused by both the summary bars and the
   per-member cells, so a colour means the same thing everywhere on the
   page. Gold stays reserved for combat — the thing the server is
   actually about — and the rest are desaturated so four bars side by
   side read as one chart rather than as a paint chart.
   =================================================================== */
:root{
  --cl-combat:#D9A52E; --cl-raid:#E5544B; --cl-gather:#4FA88B;
  --cl-build:#5B8DEF;  --cl-life:#A05BEF;
}

.cl-shape{margin-bottom:var(--s2)}
.cl-bars{display:flex;flex-direction:column;gap:12px;margin-top:4px}
.cl-bar{display:grid;grid-template-columns:96px minmax(0,1fr) auto;gap:12px;align-items:center}
.cl-bar-l{font-size:12.5px;color:var(--mute)}
.cl-bar-t{height:12px;border-radius:999px;background:rgba(255,255,255,.05);overflow:hidden}
.cl-bar-t i{display:block;height:100%;border-radius:999px;background:var(--g);
  box-shadow:0 0 16px color-mix(in srgb,var(--g) 45%,transparent);
  transition:width .6s cubic-bezier(.2,.8,.2,1)}
.cl-bar>b{font-size:13px;color:var(--bone);min-width:64px;text-align:start}

.cl-board{margin-bottom:var(--s2)}
.cl-board .card-t{display:flex;align-items:center;gap:8px}
.cl-board-head,.cl-board-row{display:grid;
  grid-template-columns:minmax(0,1.5fr) repeat(4,minmax(0,1fr)) 60px;
  gap:10px;align-items:center}
.cl-board-head{font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--off);padding-bottom:8px;border-bottom:1px solid var(--line)}
.cl-board-row{padding:11px 0;border-bottom:1px solid var(--line)}
.cl-board-row:last-of-type{border-bottom:0}
.cl-board-row:hover{background:rgba(255,255,255,.02)}
.cl-b-name{min-width:0}
.cl-b-name b{display:block;font-size:12.5px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.cl-b-name small{font-size:10px}

/* MEMBER TITLES — "your farmer", "your pvp god".
   Each one is a claim about a real person on a public page, so they get their
   own hue rather than the brand gold: gold is the site's own voice, and these
   are statements about the player. Kept to a tinted outline instead of a filled
   badge so a member holding three titles still reads as one name, not a row of
   buttons. */
/* The text import control sits in a row of buttons, so the file input has to
   line up with them rather than stack like a form field. */
.txt-import{display:inline-flex;align-items:center;gap:var(--s1);flex-wrap:wrap}
.txt-import input[type=file]{font-size:11px;color:var(--dim);max-width:230px}

/* CombatAnalyzer figures on a profile. Auto-fit rather than a fixed column
   count because each figure is printed only when it was actually measured —
   a player the analyzer has barely sampled shows two, not six with four blanks. */
.pp-combat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));
  gap:var(--s2);margin-bottom:var(--s2)}
.pp-cstat{display:flex;flex-direction:column;gap:3px}
.pp-cstat b{font-size:22px;line-height:1}
.pp-cstat small{font-size:10.5px;color:var(--dim)}
.pp-cstat small i{font-style:normal;opacity:.6}

/* The clan's written summary. Reads as prose, so it gets prose measure and
   line-height rather than the tighter rhythm the stat cards use. */
.cl-summary p.cl-sum-line{margin:0 0 8px;max-width:68ch;line-height:1.85;color:var(--txt)}
.cl-summary p.cl-sum-line:last-of-type{margin-bottom:0}
.cl-sum-facts{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s2);
  padding-top:var(--s2);border-top:1px solid var(--line2)}
.cl-sum-facts span{display:flex;flex-direction:column;gap:2px}
.cl-sum-facts small{font-size:10px;color:var(--dim)}
.cl-sum-facts b{font-size:15px}

.cl-b-titles{display:flex;flex-wrap:wrap;gap:4px;margin-top:3px}
.cl-title{font-style:normal;font-size:9.5px;line-height:1;padding:3px 6px;border-radius:999px;
  border:1px solid color-mix(in srgb,var(--t) 45%,transparent);
  background:color-mix(in srgb,var(--t) 12%,transparent);
  color:color-mix(in srgb,var(--t) 88%,#fff);white-space:nowrap}
.cl-title-pvp{--t:#FF6B5A}
.cl-title-raider{--t:#FF9F43}
.cl-title-farmer{--t:#3FCF7F}
.cl-title-builder{--t:#4FA8FF}
/* Deliberately the dimmest of the five. It is the one title nobody chose. */
.cl-title-feeder{--t:#8C93A3}

/* Contribution share. `solid` is intentionally unstyled-looking — most members
   are ordinary, and colouring every row would make "carry" mean nothing. */
.cl-b-share{display:block;margin-top:3px;font-size:9.5px;color:var(--dim)}
.cl-b-share .num{opacity:.75}
.cl-b-share-carry{color:#FBD380}
.cl-b-share-light{color:var(--dim)}

/* The bar is the row's background and the number sits on it, so a glance
   reads the ranking and a second look reads the value. */
.cl-b-cell{position:relative;display:flex;align-items:center;height:26px;
  border-radius:7px;background:rgba(255,255,255,.04);overflow:hidden;padding:0 8px}
.cl-b-cell i{position:absolute;inset-inline-start:0;top:0;bottom:0;
  background:color-mix(in srgb,var(--g) 30%,transparent);
  border-inline-end:2px solid var(--g)}
.cl-b-cell b{position:relative;font-size:11.5px;color:var(--bone)}
.cl-b-h{font-size:11.5px;color:var(--dim);text-align:start}

@media(max-width:820px){
  .cl-board-head{display:none}
  .cl-board-row{grid-template-columns:minmax(0,1fr) repeat(2,minmax(0,1fr));
    row-gap:6px}
  .cl-b-h{grid-column:1 / -1;color:var(--off)}
  .cl-bar{grid-template-columns:80px minmax(0,1fr);row-gap:4px}
  .cl-bar>b{grid-column:2;text-align:end}
}

/* ===================================================================
   CASES

   Rarity is the whole visual language here: grey -> white -> blue ->
   purple -> gold, the convention every case site shares, so it needs
   no legend. Gold is the TOP TIER ONLY, which is also what keeps this
   page inside the 90/10 rule -- the rarest line is the one thing
   wearing the brand colour.
   =================================================================== */

/* The old page had a flat 150px top pad. This one opens on a full-bleed hero
   that runs up behind the transparent fixed nav, so the offset moves inside
   the hero instead. */
.cs-shell{padding:0 0 var(--s6)}

.cs-hero{position:relative;overflow:hidden;border-bottom:1px solid var(--line2);
  background:linear-gradient(180deg,var(--panel) 0%,var(--ink) 100%)}

/* The art is its own layer so the fade can sit BETWEEN it and the text. As a
   background on the hero itself, any overlay dark enough to make the headline
   readable also flattened the picture into a grey rectangle.

   It covers the far half and dissolves toward the copy, so the headline always
   lands on near-black no matter what the owner uploads — the one thing a
   swappable hero image must not be able to break is the text on top of it. */
.cs-hero-art{position:absolute;inset:0;background-image:var(--art);
  background-size:cover;background-position:center;opacity:.55;
  -webkit-mask-image:linear-gradient(to right,#000 0%,rgba(0,0,0,.5) 44%,transparent 78%);
  mask-image:linear-gradient(to right,#000 0%,rgba(0,0,0,.5) 44%,transparent 78%)}
.cs-hero.has-art::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(5,5,5,.55) 0%,rgba(5,5,5,.15) 45%,var(--ink) 100%)}

.cs-hero-in{position:relative;z-index:1;padding:128px var(--s2) var(--s4)}
/* Half-width so the art is never fully covered, with a floor so the headline
   cannot collapse into a column one word wide on a laptop. */
.cs-hero-copy{max-width:min(560px,58%)}
@media(max-width:820px){
  .cs-hero-copy{max-width:100%}
  .cs-hero-art{opacity:.3}
  .cs-hero-in{padding-top:118px}
}
.cs-eyebrow{margin:0 0 10px;font-size:11px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--gold);font-weight:700}
.cs-hero-t{margin:0;font-family:var(--disp);line-height:1;
  font-size:clamp(30px,4.4vw,52px);color:var(--white)}
/* The one place the page shouts: a gradient on the second line only, so the eye
   lands on the promise rather than on both halves at once. */
.cs-hero-t em{display:block;font-style:normal;
  background:linear-gradient(180deg,var(--gold-bright) 0%,var(--gold) 62%,#8A641B 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent}
.cs-hero-p{margin:14px 0 0;max-width:46ch;font-size:13.5px;font-weight:300;
  line-height:1.9;color:var(--mute)}

.cs-hero-bal{display:flex;align-items:center;gap:13px;flex-wrap:wrap;margin-top:22px;
  padding:12px 16px;border-radius:13px;width:max-content;max-width:100%;
  background:rgba(0,0,0,.55);border:1px solid var(--line2);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.cs-hero-bal span{font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim)}
.cs-hero-bal b{font-family:var(--disp);font-size:28px;line-height:1;color:var(--gold)}

/* ------------------------------------------------------------ case rail */
.cs-rail{display:flex;gap:12px;overflow-x:auto;padding:var(--s3) 2px var(--s2);
  justify-content:center;scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch}
/* Once the rail actually overflows, centring would hide the first card behind
   the scroll origin, so it reverts to packing from the start. */
@media(max-width:720px){.cs-rail{justify-content:flex-start}}
.cs-card{flex:0 0 148px;scroll-snap-align:start;cursor:pointer;text-align:center;
  padding:14px 10px 12px;border-radius:14px;background:var(--panel2);
  border:1px solid var(--line2);color:inherit;font:inherit;
  transition:border-color .18s,transform .18s,background .18s}
.cs-card:hover{transform:translateY(-2px);background:var(--card-hover)}
.cs-card.on{border-color:var(--gold);background:rgba(217,165,46,.07);
  box-shadow:0 0 0 1px var(--gold),0 10px 30px rgba(217,165,46,.14)}
.cs-card-art{display:grid;place-items:center;width:64px;height:52px;margin:0 auto 10px;
  border-radius:10px;background:linear-gradient(180deg,var(--elevated) 0%,var(--ink) 100%);
  border:1px solid var(--line2)}
.cs-card-art i{font-style:normal;font-family:var(--disp);font-size:24px;color:var(--gold)}
.cs-card-n{display:block;font-size:12.5px;line-height:1.4;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.cs-card-p{display:block;margin-top:5px;font-size:11px;color:var(--gold-light)}

/* ------------------------------------------------------------ main grid */
.cs-main{display:grid;grid-template-columns:250px minmax(0,1fr) 250px;gap:var(--s2);
  align-items:start;margin-bottom:var(--s3)}
@media(max-width:1080px){.cs-main{grid-template-columns:minmax(0,1fr)}}

.cs-info-head{display:flex;align-items:center;gap:11px;padding-bottom:13px;
  border-bottom:1px solid var(--line)}
.cs-info-art{display:grid;place-items:center;width:44px;height:44px;flex:none;
  border-radius:11px;background:var(--ink);border:1px solid var(--line2)}
.cs-info-art i{font-style:normal;font-family:var(--disp);font-size:19px;color:var(--gold)}
.cs-info-head b{display:block;font-size:14px}
.cs-info-head small{font-size:11px}

.cs-odds{margin-top:6px}
.cs-odd{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:10px 0;border-bottom:1px solid var(--line);font-size:12px;color:var(--dim)}
.cs-odd:last-of-type{border-bottom:0}
.cs-odd b{color:var(--bone);font-size:13.5px}
.cs-odd-gold{color:var(--gold)}

/* ---------------------------------------------------------------- stage */
.cs-stage{background:var(--panel2);border:1px solid var(--line2);border-radius:16px;
  padding:var(--s2);min-width:0}
.cs-stage-top{display:flex;align-items:center;justify-content:space-between;gap:12px;
  flex-wrap:wrap;margin-bottom:14px}
.cs-stage-state{font-size:12px;color:var(--mute);font-weight:600}
.cs-toggles{display:flex;align-items:center;gap:12px}
.cs-toggle{display:flex;align-items:center;gap:7px;font-size:11.5px;color:var(--dim);cursor:pointer}
.cs-mute{background:none;border:1px solid var(--line2);border-radius:9px;cursor:pointer;
  padding:5px 9px;font-size:13px;line-height:1;color:var(--mute)}
.cs-mute:hover{border-color:var(--gold);color:var(--gold)}

/* The reel. direction:ltr so the transform maths is plain left-to-right even
   though the page is RTL -- a right-to-left reel would need every sign flipped
   for no gain, and the classic case reel reads the same either way. */
.cs-reel{position:relative;overflow:hidden;direction:ltr;
  border-radius:12px;background:linear-gradient(180deg,var(--ink) 0%,var(--black-deep) 100%);
  border:1px solid var(--line2);padding:16px 0;
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 12%,#000 88%,transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 12%,#000 88%,transparent 100%)}
.cs-reel-strip{display:flex;gap:10px;will-change:transform}
.cs-reel-mark{position:absolute;top:0;bottom:0;left:50%;width:2px;z-index:2;
  transform:translateX(-50%);background:var(--gold);
  box-shadow:0 0 14px 2px rgba(217,165,46,.55)}
.cs-reel-mark::before,.cs-reel-mark::after{content:"";position:absolute;left:50%;
  transform:translateX(-50%);border:6px solid transparent}
.cs-reel-mark::before{top:-1px;border-top-color:var(--gold)}
.cs-reel-mark::after{bottom:-1px;border-bottom-color:var(--gold)}

.cs-tile{flex:0 0 116px;height:104px;border-radius:10px;display:flex;
  flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:8px;
  background:linear-gradient(180deg,color-mix(in srgb,var(--t) 16%,transparent) 0%,rgba(0,0,0,.32) 68%);
  border:1px solid color-mix(in srgb,var(--t) 34%,var(--line2));
  border-top:3px solid var(--t)}
.cs-tile-art{font-size:26px;line-height:1;display:grid;place-items:center;
  width:40px;height:40px;color:var(--t)}
.cs-tile-art img{width:100%;height:100%;object-fit:contain}
.cs-tile b{font-size:10.5px;font-weight:600;color:var(--mute);text-align:center;
  line-height:1.3;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.cs-result{position:absolute;inset:0;z-index:3;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:8px;direction:rtl;
  background:rgba(5,5,5,.9);animation:csPop .38s cubic-bezier(.2,1.4,.4,1)}
.cs-result-art{display:grid;place-items:center;width:66px;height:66px;border-radius:14px;
  font-size:32px;color:var(--t);border:2px solid var(--t);
  background:color-mix(in srgb,var(--t) 12%,transparent);
  box-shadow:0 0 34px color-mix(in srgb,var(--t) 40%,transparent)}
.cs-result-art img{width:76%;height:76%;object-fit:contain}
.cs-result b{font-size:19px;font-family:var(--disp)}
.cs-result small{font-size:11px;color:var(--dim);letter-spacing:.1em;text-transform:uppercase}
@keyframes csPop{from{opacity:0;transform:scale(.86)}to{opacity:1;transform:scale(1)}}

.cs-open{margin-top:16px}
.cs-open-btn{width:100%;justify-content:center;gap:10px;font-size:15px;padding:15px 22px}
.cs-open-btn b{color:inherit;opacity:.72}
.cs-open-btn:disabled{opacity:.55;cursor:not-allowed}
/* --- cases: hero CTAs, scrawl, step rail (per the mockup) --------------- */

.cs-hero-cta{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:18px}
.cs-hero-cta .btn{display:inline-flex;align-items:center;gap:7px}
.cs-hero-cta .ico{font-size:15px}
.cs-hero-cta .btn-gold .ico{transform:scaleX(-1)}
.cs-hero-earn{font-size:12px;font-weight:700;color:var(--gold);text-decoration:underline;
  text-underline-offset:3px}
.cs-hero-earn:hover{color:var(--gold-bright)}

/* Opposite the copy: RTL puts the copy on the right, so this is inline-END. */
.cs-scrawl{position:absolute;z-index:3;top:34%;inset-inline-end:5%;margin:0;
  font-family:var(--script);font-size:clamp(20px,2.2vw,34px);line-height:1.05;
  color:var(--gold-light);transform:rotate(-7deg);text-align:center;
  text-shadow:0 2px 18px rgba(0,0,0,.6);pointer-events:none}
.cs-scrawl span{display:block}
.cs-scrawl-crown{display:block;margin:4px auto 0;font-size:20px;color:var(--gold)}
@media (max-width:1100px){.cs-scrawl{display:none}}

.cs-steps{list-style:none;display:flex;gap:8px;margin:16px 0 0;padding:0}
.cs-steps li{flex:1;display:flex;align-items:center;gap:8px;padding:9px 11px;
  background:var(--panel2);border:1px solid var(--line);border-radius:11px;
  font-size:11.5px;color:var(--dim);transition:border-color .2s,color .2s}
.cs-steps li b{font-family:var(--disp);font-size:12px;color:var(--off)}
.cs-steps li span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cs-steps li .ico{font-size:14px;opacity:.35}
.cs-steps li.is-done{color:var(--mute);border-color:var(--line2)}
.cs-steps li.is-done b{color:var(--mute)}
.cs-steps li.is-done .ico{opacity:1;color:#5FBF7F}
.cs-steps li.is-now{border-color:var(--gold);color:var(--gold-light);
  background:rgba(217,165,46,.08)}
.cs-steps li.is-now b{color:var(--gold)}
.cs-steps li.is-now .ico{opacity:1;color:var(--gold);animation:cs-spin 1.4s linear infinite}
@keyframes cs-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.cs-steps li.is-now .ico{animation:none}}
@media (max-width:560px){.cs-steps li span{display:none}}

.cs-fair{margin:12px 0 0;font-size:10.5px;line-height:1.9;color:var(--off);text-align:center}

/* ----------------------------------------------------------- live feed */
.cs-feed .card-t{display:flex;align-items:center;justify-content:space-between;gap:8px}
.cs-live{display:inline-flex;align-items:center;gap:6px;font-size:10px;color:var(--live);
  letter-spacing:.08em;text-transform:uppercase}
.cs-live i{width:6px;height:6px;border-radius:50%;background:var(--live);
  animation:csBlink 1.6s ease-in-out infinite}
@keyframes csBlink{0%,100%{opacity:1}50%{opacity:.28}}
.cs-feed-row{display:flex;align-items:center;gap:10px;padding:8px 0;
  border-bottom:1px solid var(--line);min-width:0}
.cs-feed-row:last-of-type{border-bottom:0}
.cs-feed-art{display:grid;place-items:center;width:30px;height:30px;flex:none;
  border-radius:8px;font-size:14px;color:var(--t);
  background:color-mix(in srgb,var(--t) 12%,transparent);
  border:1px solid color-mix(in srgb,var(--t) 30%,var(--line2))}
.cs-feed-art img{width:78%;height:78%;object-fit:contain}
.cs-feed-id{flex:1;min-width:0}
.cs-feed-id b{display:block;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cs-feed-id small{display:block;font-size:10.5px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}

/* --------------------------------------------------------- drop table */
.cs-drops-head{display:flex;align-items:baseline;gap:10px;margin:var(--s2) 0 12px}
.cs-drops-head h3{margin:0;font-size:15px;font-weight:800}
/* auto-FIT, not auto-fill. auto-fill keeps the empty tracks it cannot fill,
   so a four-item case in an eight-column grid rendered four items and four
   dead columns, pushed to one side. auto-fit collapses them. */
.cs-drops{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;
  max-width:1000px;margin-inline:auto}
.cs-drop{position:relative;padding:14px 10px 12px;border-radius:12px;text-align:center;
  background:linear-gradient(180deg,color-mix(in srgb,var(--t) 13%,transparent) 0%,rgba(0,0,0,.3) 70%);
  border:1px solid color-mix(in srgb,var(--t) 30%,var(--line2));
  border-top:3px solid var(--t);transition:transform .16s}
.cs-drop:hover{transform:translateY(-2px)}
.cs-drop-art{display:grid;place-items:center;width:44px;height:44px;margin:0 auto 9px;
  font-size:26px;color:var(--t)}
.cs-drop-art img{width:100%;height:100%;object-fit:contain}
.cs-drop b{display:block;font-size:11.5px;line-height:1.4;color:var(--bone)}
.cs-drop small{display:block;margin-top:3px;font-size:10px;color:var(--t)}
.cs-drop-p{display:block;margin-top:7px;font-size:11.5px;font-weight:700;color:var(--mute)}

.cs-hist{margin-top:var(--s3)}

/* A global reduced-motion guard already exists, but the reel is the most
   aggressive thing on the site so it is stopped explicitly here too. The JS
   checks the same query and skips straight to the result. */
@media(prefers-reduced-motion:reduce){
  .cs-reel-strip{transition:none}
  .cs-result{animation:none}
  .cs-live i{animation:none}
}

/* The bot contract, verbatim. Scrolls inside itself so a long URL can never
   widen the page — the panel is already narrow on a phone. */
.owner-pre{background:var(--panel);border:1px solid var(--line2);border-radius:11px;
  padding:14px;margin:0 0 var(--s2);overflow-x:auto;font-size:11.5px;line-height:1.85;
  color:var(--mute);white-space:pre;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
.os-grant{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.os-grant .owner-input{width:auto;min-width:190px;padding:8px 11px;font-size:12.5px}

/* --- owner: site text ------------------------------------------------------ */
.ot-bar{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:var(--s2);
  padding:14px 18px;border-radius:12px;background:var(--panel2);border:1px solid var(--line2);
  font-size:12.5px;color:var(--mute)}
.ot-bar b{color:var(--gold);font-family:var(--disp);font-size:19px;line-height:1}
.ot-bar .btn{margin-inline-start:auto;padding:8px 14px;font-size:12.5px}

/* Collapsed by default: ~400 strings on one open page is unusable, and the
   group a person came to edit is almost never the first one. */
.ot-group{padding:0}
.ot-group > summary{display:flex;align-items:center;gap:10px;cursor:pointer;
  padding:16px var(--s3);font-size:14px;list-style:none}
.ot-group > summary::-webkit-details-marker{display:none}
.ot-group > summary::before{content:"+";font-family:var(--disp);color:var(--gold);
  font-size:16px;width:14px}
.ot-group[open] > summary::before{content:"–"}
.ot-group > summary:hover{background:var(--card-hover)}
.ot-group > form{padding:0 var(--s3) var(--s3)}

.ot-row{padding:12px 0;border-bottom:1px solid rgba(41,41,41,.6)}
.ot-row:last-of-type{border-bottom:0}
.ot-key{display:flex;align-items:center;gap:8px;font-size:11px;color:var(--dim);
  margin-bottom:6px;cursor:pointer}
.ot-row.changed .ot-key{color:var(--gold-light)}
.ot-dot{width:6px;height:6px;border-radius:50%;background:var(--gold);flex:none}
.ot-default{display:block;margin-top:6px;font-size:11px;color:var(--off);line-height:1.8}

/* --- owner: cases ---------------------------------------------------------- */
/* .owner-input is LTR by default because it was built for API keys and URLs;
   Persian-text fields opt back in. */
.owner-input.rtl{direction:rtl;text-align:right}
.owner-field > span{display:block;font-size:13.5px;font-weight:700;margin-bottom:7px}
.owner-field small{display:block;font-size:11.5px;color:var(--dim);margin-top:6px;line-height:1.8}
.owner-check{display:flex;align-items:center;gap:9px;font-size:13.5px;cursor:pointer}
.owner-check input{width:16px;height:16px;accent-color:var(--gold);flex:none}
.owner-danger{border-color:rgba(229,84,75,.35)}

.oc-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:14px 0;
  border-bottom:1px solid var(--line)}
.oc-row:last-child{border-bottom:0}
.oc-main{min-width:170px}
.oc-main b{display:block;font-size:14px}
.oc-main span{font-size:11.5px}
.oc-meta{display:flex;gap:14px;flex-wrap:wrap;font-size:12px;color:var(--dim);flex:1}
.oc-meta b{color:var(--bone)}
.oc-actions{display:flex;gap:8px;flex-wrap:wrap}
.oc-actions .btn{padding:7px 14px;font-size:12.5px}

/* Five columns on desktop, stacked on narrow screens: an owner editing odds on a
   phone needs the labels, which the header row cannot supply once it wraps. */
.oc-items{display:flex;flex-direction:column;gap:8px}
.oc-head,.oc-item{display:grid;
  grid-template-columns:minmax(0,2fr) 84px minmax(0,1fr) minmax(0,1fr) 108px minmax(0,1.1fr);
  gap:8px;align-items:center}
.oc-head{font-size:11px;letter-spacing:.1em;color:var(--dim);text-transform:uppercase;
  padding-bottom:4px}
.oc-item .owner-input{padding:9px 11px;font-size:13px}
@media(max-width:820px){
  .oc-head{display:none}
  .oc-item{grid-template-columns:minmax(0,1fr) 90px;gap:8px}
  .oc-item select,.oc-item input[name$="[key]"],.oc-item input[name$="[icon]"]{grid-column:1 / -1}
}

/* --- phone verification ---------------------------------------------------- */
.ph-shell{padding:150px 0 var(--s6)}
.ph-form{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.ph-form .owner-input{flex:1;min-width:190px}
.ph-form .btn{flex:none}
/* Wide tracking on the code box so six digits read as six separate characters
   rather than one number — this field is transcribed from a phone screen. */
.ph-code{letter-spacing:.5em;text-align:center;font-size:19px;padding-inline-start:.5em}
.ph-done{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.ph-done b{display:block;font-size:14px;margin-bottom:2px}
.ph-done span{font-size:12.5px;color:var(--mute)}
.ph-done .btn{margin-inline-start:auto}
.ph-check{width:38px;height:38px;border-radius:50%;flex:none;display:grid;place-items:center;
  font-size:18px;color:var(--live);background:rgba(63,207,127,.14);
  border:1px solid rgba(63,207,127,.4)}

/* --- XP cases -------------------------------------------------------------- */
.cs-shell{padding:150px 0 var(--s6)}
.cs-bal{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:var(--s3);
  padding:16px 20px;border-radius:14px;background:var(--panel2);border:1px solid var(--line2)}
.cs-bal span{font-size:11px;letter-spacing:.14em;color:var(--dim);text-transform:uppercase}
.cs-bal b{font-family:var(--disp);font-size:30px;line-height:1;color:var(--gold)}
.cs-bal .card-more{margin:0 0 0 auto;margin-inline-start:auto}

.cs-case{margin-bottom:var(--s2)}
.cs-head{display:flex;align-items:center;justify-content:space-between;gap:var(--s2);
  flex-wrap:wrap;padding-bottom:var(--s2);border-bottom:1px solid var(--line);margin-bottom:var(--s2)}
.cs-name{font-family:var(--disp);font-size:22px;margin:0 0 4px;line-height:1.2}
.cs-cost{font-size:12.5px;color:var(--mute)}

.cs-items{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:10px}
/* The tier tint is a left edge and the label colour only — a fully tinted tile
   per item would put five accent colours on one card. */
.cs-item{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:12px 14px;border-radius:11px;font-size:12.5px;
  background:rgba(255,255,255,.03);border:1px solid var(--line);
  border-inline-start:3px solid var(--t)}
.cs-item b{color:var(--t);font-weight:700;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.cs-item span{color:var(--dim);flex:none}

.cs-roll.just-now{background:rgba(217,165,46,.08);border-radius:8px}
.cs-proof{grid-column:1 / -1;margin-top:6px}
.cs-proof summary{font-size:11px;color:var(--dim);cursor:pointer;width:max-content}
.cs-proof summary:hover{color:var(--gold)}
.cs-proof p{margin:8px 0 4px;font-size:10.5px;line-height:2;color:var(--dim)}
.cs-proof code{color:var(--mute);word-break:break-all}
.cs-proof span{display:inline-block;min-width:44px;color:var(--off)}
.cs-proof small{font-size:10px;color:var(--off)}

/* --- local dev sign-in (routes/dev.php; never served in production) -------- */
.dev-shell{padding:150px 0 var(--s6)}
.dev-warn{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;font-size:12.5px;
  line-height:1.9;color:#E8C878;background:rgba(217,165,46,.09);
  border:1px solid rgba(217,165,46,.35);border-radius:12px;padding:13px 17px;
  margin-bottom:var(--s3)}
.dev-warn b{font-size:11px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  color:#D9A52E;flex:none}
.dev-row{display:flex;align-items:center;gap:12px;padding:12px 0;font-size:13px;
  border-bottom:1px solid rgba(41,41,41,.6)}
.dev-row:last-of-type{border-bottom:0}
.dev-row img,.dev-init{width:34px;height:34px;border-radius:10px;flex:none;object-fit:cover}
.dev-init{display:grid;place-items:center;font-weight:800;color:#050505;background:var(--rust)}
.dev-row b{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dev-row:hover b{color:var(--rust)}
.dev-row .btn{flex:none;padding:6px 14px;font-size:11.5px}
.dev-links{display:flex;gap:10px;flex-wrap:wrap}
.dev-cmd{margin:12px 0 0;padding:11px 14px;border-radius:9px;font-size:12.5px;
  background:rgba(5,5,5,.6);border:1px solid var(--line2);color:var(--bone);overflow-x:auto}

/* --- nav: signed-in account button ----------------------------------------- */
.nav-acct{position:relative}
/* Matched to .btn's box so the chip and the Discord button read as a pair
   instead of two controls of different heights sitting next to each other. */
/* 12px block padding + a 26px avatar + 1px borders = 52px, the same box .btn
   produces, so the chip and the Discord button line up exactly. */
.nav-me{display:flex;align-items:center;gap:9px;padding:12px 18px 12px 12px;border-radius:99px;
  border:1px solid var(--line2);background:rgba(255,255,255,.04);max-width:210px;
  font-family:var(--ui);font-size:14px;line-height:26px;color:var(--bone);cursor:pointer;
  transition:border-color .18s,background .18s}
.nav-me:hover,.nav-acct.open .nav-me{border-color:var(--gold);background:rgba(217,165,46,.1)}
.nav-me-caret{width:0;height:0;flex:none;margin-inline-start:2px;
  border-inline:4px solid transparent;border-top:5px solid var(--dim);
  transition:transform .18s}
.nav-acct.open .nav-me-caret{transform:rotate(180deg)}

.nav-menu{position:absolute;top:calc(100% + 10px);inset-inline-end:0;z-index:60;min-width:230px;
  background:var(--panel2);border:1px solid var(--line2);border-radius:14px;padding:6px;
  box-shadow:0 22px 60px rgba(0,0,0,.7);
  animation:nav-menu-in .16s cubic-bezier(.2,.7,.3,1) both}
@keyframes nav-menu-in{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
.nav-menu-head{padding:11px 13px 12px;border-bottom:1px solid var(--line);margin-bottom:6px}
.nav-menu-head b{display:block;font-size:13.5px;margin-bottom:3px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav-menu-head span{font-size:11.5px;color:var(--gold)}
.nav-menu-item{display:block;width:100%;text-align:start;padding:9px 13px;border-radius:9px;
  font-family:var(--ui);font-size:13px;font-weight:500;color:var(--mute);
  background:none;border:0;cursor:pointer;transition:background .14s,color .14s}
.nav-menu-item:hover{background:rgba(255,255,255,.06);color:var(--bone)}
.nav-menu-out{color:var(--danger-text);margin-top:4px;border-top:1px solid var(--line);
  border-radius:0 0 9px 9px}
.nav-menu-out:hover{background:rgba(229,84,75,.12);color:#fff}
.nav-me img,.nav-me-init{width:26px;height:26px;border-radius:50%;flex:none;object-fit:cover}
.nav-me-init{display:grid;place-items:center;font-size:12px;font-weight:800;color:#050505;
  background:var(--rust)}
.nav-me b{font-size:12.5px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav-out{display:contents}
@media(max-width:760px){.nav-me b,.nav-out{display:none}}

/* --- player dashboard ------------------------------------------------------ */
.db-shell{padding:120px 0 var(--s6)}
.db-wrap{display:grid;grid-template-columns:212px minmax(0,1fr);gap:var(--s3);align-items:start}
@media(max-width:960px){.db-wrap{grid-template-columns:minmax(0,1fr)}}
.db-side{position:sticky;top:92px}
@media(max-width:960px){.db-side{position:static;display:flex;gap:8px;overflow-x:auto;
  padding-bottom:10px;margin-bottom:var(--s2)}}
.db-badge{margin-inline-start:auto;font-style:normal;font-size:10px;font-weight:700;
  padding:2px 7px;border-radius:99px;background:var(--rust);color:#050505}
.db-wallet{margin-top:var(--s3);display:grid;gap:1px;background:var(--line);
  border:1px solid var(--line2);border-radius:12px;overflow:hidden}
@media(max-width:960px){.db-wallet{display:none}}
.db-wallet>div{background:var(--panel2);padding:13px 14px}
.db-wallet span{display:block;font-size:9.5px;letter-spacing:.12em;color:var(--dim);
  text-transform:uppercase;margin-bottom:5px}
.db-wallet b{font-family:var(--disp);font-size:20px;line-height:1}

.db-hero{position:relative;border-radius:16px;overflow:hidden;border:1px solid var(--line2);
  margin-bottom:var(--s2)}
.db-hero-bg{position:absolute;inset:0}
.db-hero-bg img{width:100%;height:100%;object-fit:cover;object-position:center 35%}
.db-hero-bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,rgba(5,5,5,.96),rgba(5,5,5,.68) 60%,rgba(5,5,5,.42))}
.db-hero-in{position:relative;z-index:2;display:flex;align-items:center;gap:var(--s3);
  flex-wrap:wrap;padding:var(--s4) var(--s3)}
.db-av-wrap{position:relative;flex:none}
.db-av{width:96px;height:96px;border-radius:20px;object-fit:cover;display:block;
  border:1px solid var(--line2);box-shadow:0 12px 40px rgba(0,0,0,.55)}
.db-av.pf-av-init{font-size:38px}
/* flex:1 with min-width:0 let this collapse to 16px between ~470 and 620px:
   the CTA is flex:none, so the browser squeezed the name column instead of
   wrapping, and a player name broke into one letter per line. A real basis
   forces the wrap; min() keeps it from overflowing narrower than that. */
.db-id{flex:1 1 240px;min-width:min(240px,100%)}
.db-name{font-family:var(--ui);font-weight:900;font-size:clamp(22px,3vw,34px);line-height:1.2;
  margin:0 0 9px;word-break:break-word}
.db-meta{display:flex;gap:14px;flex-wrap:wrap;margin:0 0 10px;font-size:12px;color:var(--mute)}
.db-meta b{color:var(--bone)}
.db-hero-cta{flex:none;display:flex;gap:10px;flex-wrap:wrap}

.db-strip{display:grid;grid-template-columns:minmax(150px,1fr) minmax(170px,1.1fr) minmax(0,2.2fr);
  gap:1px;background:var(--line);border:1px solid var(--line2);border-radius:14px;
  overflow:hidden;margin-bottom:var(--s2)}
@media(max-width:860px){.db-strip{grid-template-columns:1fr}}
.db-rank,.db-level{background:var(--panel2);padding:16px 18px}
.db-rank span,.db-level span{display:block;font-size:9.5px;letter-spacing:.14em;color:var(--dim);
  text-transform:uppercase;margin-bottom:6px}
.db-rank b{display:block;font-family:var(--disp);font-size:30px;line-height:1;color:#D9A52E}
.db-rank small{display:block;font-size:10.5px;color:var(--mute);margin-top:6px}
.db-level b{display:block;font-family:var(--disp);font-size:24px;line-height:1;margin-bottom:9px}
.db-level small{display:block;font-size:10.5px;color:var(--dim);margin-top:7px}
.db-xpbar{height:6px;border-radius:99px;background:rgba(255,255,255,.07);overflow:hidden}
.db-xpbar i{display:block;height:100%;border-radius:99px;
  background:linear-gradient(90deg,var(--rust),#F2C75C)}
.db-kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--line)}
@media(max-width:560px){.db-kpis{grid-template-columns:repeat(2,1fr)}}
.db-kpis>div{background:var(--panel2);padding:16px 12px;text-align:center}
.db-kpis span{display:block;font-size:9.5px;letter-spacing:.14em;color:var(--dim);
  text-transform:uppercase;margin-bottom:7px}
.db-kpis b{font-family:var(--disp);font-size:23px;line-height:1}
.db-kpis i{font-style:normal;font-size:13px;color:var(--dim)}

.db-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s2);
  align-items:start;grid-auto-flow:dense}
@media(max-width:1100px){.db-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:700px){.db-grid{grid-template-columns:minmax(0,1fr)}}

.db-stat{display:flex;align-items:center;gap:10px;font-size:12.5px;padding:9px 0;
  border-bottom:1px solid rgba(41,41,41,.6)}
.db-stat:last-of-type{border-bottom:0}
.db-stat b{flex:1;min-width:0;font-weight:600;color:var(--mute)}
.db-stat>span{font-weight:700}
.db-chg{font-style:normal;font-size:11px;font-weight:700;min-width:54px;text-align:end}
.db-chg.up{color:var(--live)}
.db-chg.down{color:#FF9A8A}
.db-chg.none{color:var(--dim)}

.db-ticket{display:flex;align-items:center;gap:10px;padding:10px 0;font-size:12.5px;
  border-bottom:1px solid rgba(41,41,41,.6)}
.db-ticket:last-of-type{border-bottom:0}
.db-ticket b{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.db-ticket:hover b{color:var(--rust)}

.db-server{display:flex;align-items:center;gap:10px;padding:11px 0;font-size:12.5px;
  border-bottom:1px solid rgba(41,41,41,.6)}
.db-server:last-of-type{border-bottom:0}
.db-server b{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.db-server .btn{flex:none;padding:6px 12px;font-size:11.5px}

/* Purchases and payments, two lines deep so they fit a single grid column.
   Nine one-column cards fill three rows exactly; a card spanning two columns
   left a hole in the last row with nothing able to backfill it. */
.db-line{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;
  gap:3px 10px;padding:11px 0;border-bottom:1px solid rgba(41,41,41,.6);font-size:12.5px}
.db-line:last-of-type{border-bottom:0}
.db-line b{grid-column:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.db-line small{grid-column:1;font-size:11px;color:var(--dim)}
.db-line .pill-ok,.db-line .pill-off,.db-line .pill-err{grid-column:2;grid-row:1/3;justify-self:end}

/* A failed delivery has always carried this class; nothing ever defined it, so
   it rendered as plain text between two styled pills. */
/* Danger stays red. The retheme swept the old rust-red into gold everywhere it
   was BRAND; here it was STATUS, and a failed delivery that highlights gold
   would read as a reward. */
.pill-err{font-size:10px;font-weight:700;padding:3px 8px;border-radius:99px;letter-spacing:.04em;
  background:rgba(229,84,75,.14);color:var(--danger-text)}
a.pill-err:hover{background:rgba(229,84,75,.26);color:#fff}

/* --- support tickets ------------------------------------------------------- */
.tk-hero{position:relative;padding:150px 0 var(--s4);overflow:hidden;text-align:center;
  border-bottom:1px solid var(--line)}
.tk-hero-bg{position:absolute;inset:0}
.tk-hero-bg img{width:100%;height:100%;object-fit:cover;object-position:center 35%}
.tk-hero-bg::after{content:"";position:absolute;inset:0;
  background:radial-gradient(120% 90% at 50% 40%,rgba(5,5,5,.4),rgba(5,5,5,.9) 70%),
             linear-gradient(to top,var(--ink),transparent 55%)}
.tk-hero-in{position:relative;z-index:2}
.tk-promises{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--line);
  border:1px solid var(--line2);border-radius:14px;overflow:hidden;
  max-width:760px;margin:var(--s4) auto 0}
@media(max-width:700px){.tk-promises{grid-template-columns:repeat(2,1fr)}}
.tk-promises>div{background:rgba(14,20,29,.9);padding:15px 12px;backdrop-filter:blur(8px)}
.tk-promises b{display:block;font-size:12.5px}
.tk-promises span{display:block;font-size:10.5px;color:var(--mute);margin-top:4px}

.tk-layout{display:grid;grid-template-columns:230px minmax(0,1fr);gap:var(--s3);align-items:start}
@media(max-width:900px){.tk-layout{grid-template-columns:minmax(0,1fr)}}
.tk-side{position:sticky;top:92px}
@media(max-width:900px){.tk-side{position:static}}
.tk-urgent{margin-top:var(--s3);padding:16px;border-radius:12px;
  background:rgba(217,165,46,.08);border:1px solid rgba(217,165,46,.28)}
.tk-urgent b{display:block;font-size:13px;color:#FF9A8A;margin-bottom:6px}
.tk-urgent span{display:block;font-size:11.5px;color:var(--mute);line-height:1.8;margin-bottom:12px}

.tk-filters{margin-bottom:var(--s3)}
.tk-filters .lb-tab i{font-style:normal;color:var(--dim);font-size:11px}
.tk-filters .lb-tab.on i{color:#fff}

.tk-list{display:flex;flex-direction:column}
.tk-row{display:grid;grid-template-columns:64px minmax(0,1fr) auto auto;gap:14px;align-items:center;
  padding:14px 4px;border-bottom:1px solid rgba(41,41,41,.6);
  animation:lb-slide .4s ease both;animation-delay:var(--d,0ms);transition:background .16s}
.tk-row:last-child{border-bottom:0}
.tk-row:hover{background:rgba(255,255,255,.025)}
@media(max-width:640px){
  .tk-row{grid-template-columns:52px minmax(0,1fr);row-gap:8px}
  .tk-row .tk-state,.tk-row .tk-when{grid-column:2}
}
.tk-id{font-family:var(--disp);font-size:13px;color:var(--dim)}
.tk-main{min-width:0}
.tk-main b{display:block;font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tk-main small{display:block;font-size:11.5px;color:var(--dim);margin-top:3px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tk-row:hover .tk-main b{color:var(--rust-hot)}
/* An unread staff reply is the one thing a player is looking for in this list. */
.tk-dot{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--rust);
  margin-inline-start:7px;vertical-align:middle}
.tk-when{font-size:11px;color:var(--dim);white-space:nowrap}

.tk-state{font-size:10.5px;font-weight:700;padding:5px 11px;border-radius:99px;white-space:nowrap;
  border:1px solid transparent}
.tk-state-open{background:rgba(217,165,46,.12);color:#E8C878;border-color:rgba(217,165,46,.4)}
.tk-state-in_progress{background:rgba(245,245,242,.12);color:#F5F5F2;border-color:rgba(245,245,242,.35)}
.tk-state-waiting{background:rgba(217,165,46,.12);color:#E8C878;border-color:rgba(217,165,46,.35)}
.tk-state-resolved{background:rgba(63,207,127,.12);color:#8FE9B8;border-color:rgba(63,207,127,.35)}
.tk-state-closed{background:rgba(133,133,133,.16);color:var(--mute);border-color:var(--line2)}

.tk-thread-page{padding-top:140px}
.tk-head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s2);
  flex-wrap:wrap;padding-bottom:var(--s2);border-bottom:1px solid var(--line);margin-bottom:var(--s3)}
.tk-h1{font-family:var(--ui);font-weight:900;font-size:clamp(19px,2.6vw,28px);line-height:1.4;margin:0 0 8px}
.tk-h1 .num{color:var(--dim)}
.tk-head-meta{display:flex;gap:14px;flex-wrap:wrap;margin:0;font-size:11.5px;color:var(--dim)}

.tk-thread{display:flex;flex-direction:column;gap:var(--s2)}
.tk-msg{padding:15px 18px;border-radius:14px;border:1px solid var(--line2);background:var(--panel2);
  max-width:88%}
/* Staff sit on one side, the player on the other, so a thread can be skimmed
   without reading a single name. */
.tk-msg.me{align-self:flex-start}
.tk-msg.staff{align-self:flex-end;background:rgba(245,245,242,.06);border-color:rgba(245,245,242,.22)}
@media(max-width:640px){.tk-msg{max-width:100%}}
.tk-msg-h{display:flex;align-items:center;gap:9px;margin-bottom:9px;font-size:12px}
.tk-badge{font-size:9.5px;font-weight:700;padding:3px 8px;border-radius:99px;
  background:rgba(245,245,242,.16);color:#F5F5F2}
.tk-msg-h .tk-when{margin-inline-start:auto}
.tk-msg-b{font-size:13.5px;line-height:2;color:#C8C8C4}
.tk-file{display:flex;align-items:center;gap:9px;margin-top:12px;padding:10px 12px;
  border-radius:10px;background:rgba(255,255,255,.03);border:1px solid var(--line2);font-size:12px}
.tk-file span{color:var(--dim);font-size:10.5px}

.tk-reply{margin-top:var(--s3);display:flex;flex-direction:column;gap:12px;align-items:flex-start}
.tk-reply textarea{width:100%}
.tk-form .owner-field{margin-bottom:var(--s3)}

/* --- news ------------------------------------------------------------------ */
.nw-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s2)}
@media(max-width:900px){.nw-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:600px){.nw-grid{grid-template-columns:minmax(0,1fr)}}
.nw-card{display:flex;flex-direction:column;background:var(--panel2);border:1px solid var(--line2);
  border-radius:14px;overflow:hidden;animation:lb-rise .45s cubic-bezier(.2,.7,.3,1) both;
  animation-delay:var(--d,0ms);transition:transform .18s,border-color .18s}
/* This used to set border-color to var(--line2) — the resting value — so
   the hover did nothing at all to the border. */
.nw-card:hover{transform:translateY(-6px);border-color:rgba(217,165,46,.42);
  box-shadow:0 20px 46px rgba(0,0,0,.55)}
/* The stock banners are night scenes, so at card size they read as flat dark
   rectangles. A modest lift plus a gradient floor gives the art some shape
   without turning a screenshot into something it is not. */
.nw-art{display:block;position:relative;aspect-ratio:16/9;overflow:hidden;background:var(--panel)}
.nw-art::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,rgba(5,5,5,.55),transparent 55%)}
.nw-art img{width:100%;height:100%;object-fit:cover;transition:transform .4s;
  filter:brightness(1.22) saturate(1.08)}
.nw-card:hover .nw-art img{transform:scale(1.05)}
.nw-body{display:flex;flex-direction:column;padding:16px 18px 18px;flex:1}
.nw-tags{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:10px;
  font-size:11px;color:var(--dim)}
.nw-cat{font-style:normal;font-size:10px;font-weight:700;letter-spacing:.08em;padding:4px 10px;
  border-radius:99px;background:rgba(217,165,46,.14);color:#FF9A8A;text-transform:uppercase}
.nw-cat-event{background:rgba(63,207,127,.14);color:#8FE9B8}
.nw-cat-update{background:rgba(245,245,242,.14);color:#F5F5F2}
.nw-cat-wipe{background:rgba(217,165,46,.14);color:#E8C878}
.nw-pin{font-style:normal;font-size:10px;color:#D9A52E}
.nw-title{font-size:15px;line-height:1.6;margin-bottom:8px}
.nw-ex{font-size:12.5px;line-height:1.9;color:var(--mute);flex:1}
.nw-meta{display:flex;justify-content:space-between;gap:10px;margin-top:14px;
  padding-top:12px;border-top:1px solid var(--line);font-size:11px;color:var(--dim)}

.nw-hero{position:relative;padding:170px 0 var(--s4);overflow:hidden;
  border-bottom:1px solid var(--line)}
.nw-hero-bg{position:absolute;inset:0}
.nw-hero-bg img{width:100%;height:100%;object-fit:cover;object-position:center 35%}
.nw-hero-bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,var(--ink),rgba(5,5,5,.78) 60%,rgba(5,5,5,.5))}
.nw-hero-in{position:relative;z-index:2;max-width:820px}
.nw-h1{font-family:var(--ui);font-weight:900;font-size:clamp(26px,4vw,44px);line-height:1.25;
  margin:0 0 14px;text-wrap:balance}
.nw-lede{color:#C8C8C4;font-weight:300;font-size:15px;margin:0;max-width:62ch;line-height:1.9}

.nw-article{font-size:15px;line-height:2.1;color:#C8C8C4}
.nw-foot{display:flex;align-items:center;justify-content:space-between;gap:var(--s2);
  margin-top:var(--s4);padding-top:var(--s3);border-top:1px solid var(--line);
  font-size:12px;color:var(--dim)}

/* --- leaderboard: pulse + category champions --- */
.lb-pulse{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--line);
  border:1px solid var(--line2);border-radius:14px;overflow:hidden;margin-bottom:var(--s2)}
@media(max-width:640px){.lb-pulse{grid-template-columns:repeat(2,1fr)}}
.lb-pulse>div{background:var(--panel2);padding:16px 12px;text-align:center}
.lb-pulse b{display:block;font-family:var(--disp);font-size:24px;line-height:1}
.lb-pulse span{display:block;font-size:10px;letter-spacing:.14em;color:var(--dim);
  text-transform:uppercase;margin-top:7px}

.lb-champs{margin-bottom:var(--s3)}
.lb-champs-t{font-size:10px;font-weight:700;letter-spacing:.18em;color:var(--dim);
  text-transform:uppercase;margin:0 0 10px}
.lb-champs-row{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:10px}
@media(max-width:1000px){.lb-champs-row{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(max-width:560px){.lb-champs-row{grid-template-columns:repeat(2,minmax(0,1fr))}}
.lb-champ{display:flex;align-items:center;gap:10px;min-width:0;padding:11px 12px;
  background:var(--panel2);border:1px solid var(--line2);border-radius:12px;
  transition:border-color .16s,transform .16s}
.lb-champ:hover{border-color:rgba(217,165,46,.5);transform:translateY(-2px)}
.lb-champ-av{width:34px;height:34px;border-radius:9px;object-fit:cover;flex:none;display:block}
.lb-champ-txt{min-width:0}
.lb-champ-txt small{display:block;font-size:9.5px;letter-spacing:.1em;color:#D9A52E;
  text-transform:uppercase}
.lb-champ-txt b{display:block;font-size:12.5px;margin-top:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lb-champ-txt i{font-style:normal;font-size:11px;color:var(--dim)}

/* --- clan board ------------------------------------------------------------
   Clans carry no points, so the board is ranked on a category and each row has
   one fewer column than the player table. */
.cl-metrics{margin:calc(var(--s2) * -1) 0 var(--s3)}
.cl-head,.cl-row{grid-template-columns:46px minmax(150px,1fr) 90px 76px 76px}
.cl-kpis{grid-template-columns:repeat(4,1fr)}
@media(max-width:560px){.cl-kpis{grid-template-columns:repeat(2,1fr)}}

/* --- leaderboard: podium + motion ------------------------------------------
   The board is the busiest page on the site - this is where players come to look
   each other up. Rank has to be legible at a glance, so the top three get real
   estate and everyone else gets a bar showing the gap. */

@keyframes lb-rise{from{opacity:0;transform:translateY(18px) scale(.97)}to{opacity:1;transform:none}}
@keyframes lb-slide{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes lb-grow{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes lb-glow{0%,100%{box-shadow:0 0 0 0 rgba(217,165,46,0)}50%{box-shadow:0 0 26px 0 rgba(217,165,46,.35)}}

.lb-podium{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s2);
  align-items:end;margin-bottom:var(--s3)}
@media(max-width:760px){.lb-podium{grid-template-columns:1fr;align-items:stretch}}

.lb-pod{position:relative;display:flex;flex-direction:column;align-items:center;text-align:center;
  padding:26px 16px 20px;border-radius:16px;border:1px solid var(--line2);
  background:linear-gradient(180deg,var(--panel2),rgba(13,13,13,.9));
  animation:lb-rise .5s cubic-bezier(.2,.7,.3,1) both;animation-delay:var(--d,0ms);
  transition:transform .18s ease,border-color .18s ease,box-shadow .18s ease}
.lb-pod:hover{transform:translateY(-4px);border-color:var(--mute)}
/* The winner is physically taller - the shape says who won before you read it. */
.lb-pod-first{padding-top:34px;padding-bottom:28px}

.lb-pod-gold{border-color:rgba(217,165,46,.5);
  background:linear-gradient(180deg,rgba(217,165,46,.12),rgba(13,13,13,.92))}
.lb-pod-gold.lb-pod-first{animation:lb-rise .5s cubic-bezier(.2,.7,.3,1) both,lb-glow 3.2s ease-in-out 1s infinite}
.lb-pod-silver{border-color:rgba(198,206,218,.38);
  background:linear-gradient(180deg,rgba(198,206,218,.08),rgba(13,13,13,.92))}
.lb-pod-bronze{border-color:rgba(199,123,69,.4);
  background:linear-gradient(180deg,rgba(199,123,69,.1),rgba(13,13,13,.92))}

.lb-pod-place{position:absolute;top:-14px;inset-inline-start:50%;transform:translateX(-50%);
  width:30px;height:30px;border-radius:50%;display:grid;place-items:center;
  font-family:var(--disp);font-size:15px;color:var(--ink);background:var(--mute)}
.lb-pod-gold .lb-pod-place{background:#D9A52E}
.lb-pod-silver .lb-pod-place{background:#C6CEDA}
.lb-pod-bronze .lb-pod-place{background:#C77B45}

.lb-pod-avwrap{position:relative;margin-bottom:12px}
.lb-pod-av{width:72px;height:72px;border-radius:18px;object-fit:cover;display:block;
  border:1px solid var(--line2)}
.lb-pod-first .lb-pod-av{width:88px;height:88px;border-radius:22px}
.lb-pod-crown{position:absolute;top:-16px;inset-inline-start:50%;transform:translateX(-50%);
  font-size:19px;color:#D9A52E;text-shadow:0 2px 10px rgba(217,165,46,.7)}

.lb-pod-name{font-size:15px;margin-bottom:7px;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lb-pod-first .lb-pod-name{font-size:18px}
.lb-pod-score{display:block;font-family:var(--disp);font-size:30px;line-height:1;margin-top:14px}
.lb-pod-first .lb-pod-score{font-size:38px;color:#D9A52E}
.lb-pod-metric{font-size:10px;letter-spacing:.14em;color:var(--dim);text-transform:uppercase;margin-top:5px}

/* --- leaderboard: mockup pass ------------------------------------------ */

.lb-lede{margin:14px auto 0;max-width:56ch;color:var(--dim);font-size:13.5px;
  font-weight:300;line-height:1.9}

.lb-scrawl{position:absolute;z-index:3;top:26%;inset-inline-end:4%;margin:0;
  font-family:var(--script);font-size:clamp(19px,2vw,31px);line-height:1.04;
  color:var(--gold-light);transform:rotate(-7deg);text-align:center;
  text-shadow:0 2px 18px rgba(0,0,0,.6);pointer-events:none}
.lb-scrawl span{display:block}
.lb-scrawl-crown{display:block;margin:4px auto 0;font-size:19px;color:var(--gold)}
@media (max-width:1100px){.lb-scrawl{display:none}}

/* The category row. Scrolls rather than wraps: eight tabs wrapping to three
   lines pushes the podium off the first screen. */
.lb-cats{display:flex;gap:7px;margin:0 0 var(--s3);overflow-x:auto;
  scrollbar-width:none;-webkit-overflow-scrolling:touch}
.lb-cats::-webkit-scrollbar{display:none}
.lb-cat{flex:none;display:inline-flex;align-items:center;gap:7px;padding:9px 15px;
  border-radius:999px;background:var(--panel2);border:1px solid var(--line2);
  color:var(--mute);font-size:12.5px;font-weight:500;white-space:nowrap;
  transition:border-color .16s,color .16s,background .16s}
.lb-cat .ico{font-size:14px;color:var(--dim)}
.lb-cat:hover{border-color:var(--off);color:var(--bone)}
.lb-cat.on{background:rgba(217,165,46,.14);border-color:var(--gold);
  color:var(--gold-light);font-weight:700}
.lb-cat.on .ico{color:var(--gold)}

/* Four stats per podium card, as the mockup shows. */
.lb-pod-stats{display:grid;grid-template-columns:1fr 1fr;gap:6px 10px;
  width:100%;margin-top:12px;padding-top:11px;border-top:1px solid var(--line)}
.lb-pod-stats>span{display:flex;align-items:center;justify-content:center;gap:5px}
.lb-pod-stats .ico{font-size:12px;color:var(--dim)}
.lb-pod-stats b{font-size:12px;font-weight:700}

/* A K/D at or above 1 is the one number on the row worth colouring. */
.lb-kd-up{color:var(--gold-light);font-weight:700}

.lb-totals{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  gap:12px;margin:34px 0 8px}
.lb-total{display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto auto;
  column-gap:13px;align-items:center;padding:16px 18px;
  background:var(--panel);border:1px solid var(--line);border-radius:14px}
.lb-total .ico{grid-row:1/3;font-size:20px;width:42px;height:42px;display:grid;
  place-items:center;border-radius:12px;color:var(--gold);
  background:rgba(217,165,46,.1);border:1px solid rgba(217,165,46,.28)}
.lb-total b{font-family:var(--disp);font-size:23px;line-height:1.1}
.lb-total span{font-size:11px;color:var(--dim)}

.lb-seen{display:flex;align-items:center;justify-content:center}
.lb-live{display:inline-flex;align-items:center;gap:5px;font-size:10.5px;
  font-weight:700;color:#5FBF7F}
.lb-live i{width:6px;height:6px;border-radius:50%;background:#5FBF7F;flex:none;
  box-shadow:0 0 0 3px rgba(95,191,127,.18)}

/* Below this the eight-column table stops being a table. The metric, kills and
   playtime are what a player came to compare; deaths and K/D are detail that
   belongs on the profile. */
.lb-pod-sub{display:flex;gap:14px;margin-top:14px;padding-top:13px;
  border-top:1px solid var(--line);width:100%;justify-content:center}
.lb-pod-sub i{font-style:normal;font-size:11px;color:var(--dim)}
.lb-pod-sub b{color:var(--bone);font-size:12.5px}

/* Rows: a bar behind each one shows the gap to the top of the page. */
.lb-tr{position:relative;isolation:isolate;animation:lb-slide .42s ease both;animation-delay:var(--d,0ms)}
.lb-tr-fill{position:absolute;inset-block:4px;inset-inline-start:0;z-index:-1;border-radius:8px;
  background:linear-gradient(to left,rgba(217,165,46,.16),rgba(217,165,46,.03));
  transform-origin:right center;animation:lb-grow .6s cubic-bezier(.2,.7,.3,1) both;
  animation-delay:calc(var(--d,0ms) + 120ms)}
.lb-tr:hover{background:rgba(255,255,255,.03)}
.lb-tr:hover .lb-metric{color:var(--rust-hot)}
.lb-metric{transition:color .16s}

/* Motion is decoration here. With reduced motion everything must still be
   readable at its final state, never stuck at opacity 0. */
@media(prefers-reduced-motion:reduce){
  .lb-pod,.lb-tr,.lb-tr-fill{animation:none!important;opacity:1;transform:none}
  .lb-pod:hover{transform:none}
}

/* --- leaderboard: server tabs, wipe scope, and the narrow-screen category row --- */
.lb-toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--s2);
  flex-wrap:wrap;margin:0 0 var(--s3)}
.lb-tabs{display:flex;gap:6px;flex-wrap:wrap;min-width:0}
.lb-tab{display:inline-flex;align-items:center;gap:8px;padding:8px 15px;border-radius:10px;
  border:1px solid var(--line2);background:rgba(255,255,255,.02);color:var(--mute);
  font-size:12.5px;font-weight:700;letter-spacing:.06em;white-space:nowrap;
  transition:color .16s,border-color .16s,background .16s}
.lb-tab:hover{color:var(--bone);border-color:var(--mute)}
.lb-tab.on{color:#fff;background:rgba(217,165,46,.13);border-color:rgba(217,165,46,.55)}
.lb-tab-dot{width:6px;height:6px;border-radius:50%;background:var(--line2);flex:none;transition:background .16s}
.lb-tab.on .lb-tab-dot{background:var(--rust);box-shadow:0 0 0 3px rgba(217,165,46,.18)}

/* A two-state switch, not two more tabs — the shape says "same data, other view". */
.lb-scope{display:inline-flex;gap:2px;padding:3px;border-radius:11px;
  background:rgba(255,255,255,.03);border:1px solid var(--line2)}
.lb-scope a{padding:7px 14px;border-radius:8px;font-size:12px;font-weight:700;
  color:var(--mute);white-space:nowrap;transition:color .16s,background .16s}
.lb-scope a:hover{color:var(--bone)}
.lb-scope a.on{background:var(--rust);color:#050505}

.lb-note{margin:0 0 var(--s2);padding:11px 14px;border-radius:10px;font-size:12.5px;
  line-height:1.75;color:#E8C878;background:rgba(217,165,46,.07);
  border:1px solid rgba(217,165,46,.22)}
.lb-note-quiet{color:var(--mute);background:rgba(255,255,255,.025);border-color:var(--line)}
.lb-note b{color:var(--bone)}

.lb-table{overflow-x:auto;margin:0 calc(var(--s3) * -1)}
.lb-thead,.lb-tr{display:grid;grid-template-columns:44px minmax(130px,1fr) 74px 62px 62px 58px 66px 92px;
  gap:12px;align-items:center;min-width:560px;padding-inline:var(--s3)}

/* Columns are dropped BY NAME, never by nth-child: .lb-tr-fill is the row's
   first child, so index N means a different column in the row than in the
   header — hiding by index put playtime under the "points" heading.

   These MUST come after the base rule above. They were written before it and
   lost the cascade at equal specificity, so the row kept all eight tracks on a
   phone and min-width:560px pinned it 235px wider than its container. Because
   body carries overflow-x:hidden, that overflow was CLIPPED, not scrollable —
   the status column simply vanished off the edge. */
@media (max-width:900px){
  .lb-thead,.lb-tr{grid-template-columns:38px minmax(110px,1fr) 72px 62px 66px 86px;
    min-width:0}
  .lb-c-deaths,.lb-c-kd{display:none}
}

@media (max-width:620px){
  .lb-thead,.lb-tr{grid-template-columns:30px minmax(0,1fr) 62px 70px;gap:6px;min-width:0}
  .lb-c-kills,.lb-c-time{display:none}
  .lb-player-txt small{display:none}
}
.lb-thead{padding-bottom:10px;font-size:10px;font-weight:700;letter-spacing:.14em;
  color:var(--dim);text-transform:uppercase;border-bottom:1px solid var(--line)}
.lb-tr{padding-block:12px;border-bottom:1px solid rgba(41,41,41,.6);position:relative;
  transition:background .16s}
.lb-tr:last-child{border-bottom:0}
.lb-tr:hover{background:rgba(255,255,255,.025)}
.lb-pos b{font-family:var(--disp);font-size:16px;color:var(--dim)}
/* Medals read as rank without needing an icon or a coloured row. */
.lb-tr.medal-gold   .lb-pos b{color:#D9A52E}
.lb-tr.medal-silver .lb-pos b{color:#C6CEDA}
.lb-tr.medal-bronze .lb-pos b{color:#C77B45}
.lb-tr.medal-gold::before,.lb-tr.medal-silver::before,.lb-tr.medal-bronze::before{
  content:"";position:absolute;inset-inline-start:0;top:8px;bottom:8px;width:2px;border-radius:2px}
.lb-tr.medal-gold::before{background:#D9A52E}
.lb-tr.medal-silver::before{background:#C6CEDA}
.lb-tr.medal-bronze::before{background:#C77B45}

.lb-player{display:flex;align-items:center;gap:11px;min-width:0}
.lb-av{width:34px;height:34px;border-radius:10px;object-fit:cover;flex:none;display:block}
/* A missing avatar becomes a coloured initial. An empty grey box reads as broken. */
/* Same inversion as .pf-av-init: the letter carries the accent, the tile is
   near-black. White on a champagne or silver --a measured 2.2:1. */
.lb-av-init{display:grid;place-items:center;font-weight:800;font-size:14px;color:var(--a);
  background:linear-gradient(140deg,rgba(255,255,255,.06),rgba(5,5,5,.9));
  border:1px solid var(--line2)}
.lb-player-txt{min-width:0}
.lb-player b{display:block;font-size:13.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lb-player small{color:var(--dim);font-size:10.5px;letter-spacing:.04em}
.ta-c{text-align:center}
.ta-e{text-align:end}
.strong{font-weight:700}
.dim{color:var(--dim)}
.lb-tr i{font-style:normal;color:var(--dim);font-size:11px;margin-inline-start:1px}

.tier{display:inline-block;font-size:9px;font-weight:800;letter-spacing:.1em;
  padding:4px 9px;border-radius:5px;border:1px solid;white-space:nowrap}
.tier-legend{color:#D9A52E;background:rgba(217,165,46,.10);border-color:rgba(217,165,46,.35)}
.tier-veteran{color:#E8C878;background:rgba(232,200,120,.10);border-color:rgba(232,200,120,.35)}
.tier-elite{color:#FFD978;background:rgba(255,217,120,.10);border-color:rgba(255,217,120,.35)}
.tier-raider{color:var(--live);background:rgba(63,207,127,.10);border-color:rgba(63,207,127,.3)}
.tier-rookie{color:var(--dim);background:rgba(133,133,133,.12);border-color:var(--line2)}

.pager{display:flex;align-items:center;justify-content:center;gap:6px;margin-top:var(--s3);
  padding-top:var(--s2);border-top:1px solid var(--line)}
.pg{display:grid;place-items:center;min-width:32px;height:32px;border-radius:8px;
  border:1px solid var(--line2);color:var(--mute);font-size:12.5px;transition:all .16s}
.pg:hover{border-color:var(--line2);color:var(--bone)}
.pg.on{background:var(--rust);border-color:var(--rust);color:#050505;font-weight:700}

.lb-empty{text-align:center;padding:var(--s5) var(--s3)}
.lb-empty b{display:block;font-size:15px;margin-bottom:6px}
.lb-empty span{color:var(--dim);font-size:13px}

.lb-rail{position:sticky;top:92px}
.lb-widget{background:var(--panel2);border:1px solid var(--line2);border-radius:14px;
  padding:var(--s2) var(--s2) 6px;margin-bottom:12px}
.lb-widget-row{display:flex;align-items:center;gap:10px;padding:9px 0;
  border-bottom:1px solid rgba(41,41,41,.6);font-size:13px}
.lb-widget-row:last-child{border-bottom:0}
.lb-widget-pos{font-family:var(--disp);font-size:13px;color:var(--dim);min-width:14px}
.lb-widget-row b{flex:1;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lb-widget-av{width:29px;height:29px;border-radius:8px;object-fit:cover;flex:none;font-size:12px}
.lb-widget-txt{display:flex;flex-direction:column;min-width:0;flex:1;gap:1px}
.lb-widget-txt small{color:var(--dim);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lb-mini-empty{padding:4px 0 12px}
.lb-mini-empty b{display:block;font-size:12.5px;margin-bottom:4px}
.lb-mini-empty span{color:var(--dim);font-size:11.5px;line-height:1.8}
.lb-mini-empty code{background:rgba(255,255,255,.05);padding:1px 5px;border-radius:4px;font-size:11px}

.lb-promo{position:relative;display:block;border-radius:13px;overflow:hidden;aspect-ratio:4/5}
.lb-promo img{width:100%;height:100%;object-fit:cover;transition:transform .5s}
.lb-promo:hover img{transform:scale(1.05)}
.lb-promo::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,rgba(5,5,5,.96),transparent 60%)}
.lb-promo-txt{position:absolute;inset-inline:0;bottom:0;z-index:2;padding:14px;text-align:center}
.lb-promo-txt b{display:block;font-size:12.5px;margin-bottom:3px}
.lb-promo-txt small{color:var(--rust);font-size:11px;font-weight:700}

/* ===================================================================
/* ===================================================================
   ACHIEVEMENTS: the wall

   Rarity carries the colour and nothing else does. A card at rest is
   neutral panel + hairline; the rarity hue appears on the hexagon ring
   and the rarity label, and gold is reserved for the top tier and for
   the one thing the player can ACT on — the claim button. On a wall of
   52 cards that is what keeps the page inside the 90/10 rule.

   Locked is expressed by restraint, not a grey filter: the hexagon
   loses opacity and its ring stays dark. A saturate(0) over the whole
   card would also kill the text contrast, which on an OLED phone in
   daylight is the difference between readable and not.
   =================================================================== */

.vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

.ah-shell{padding-top:var(--nav-h,64px)}

/* ------------------------------------------------------------- hero */

.ah-hero{position:relative;overflow:hidden;padding:52px 0 34px;
  border-bottom:1px solid var(--line)}

/* The art is its own layer so the gradient can sit BETWEEN it and the
   copy, instead of dimming the headline along with the photo. RTL: the
   text sits on the right, so the mask keeps the RIGHT edge readable and
   lets the picture breathe on the left. */
.ah-hero-art{position:absolute;inset:0;background-image:var(--art);
  background-size:cover;background-position:center 32%;opacity:.5;
  -webkit-mask-image:linear-gradient(to right,#000 0%,rgba(0,0,0,.75) 34%,transparent 78%);
  mask-image:linear-gradient(to right,#000 0%,rgba(0,0,0,.75) 34%,transparent 78%)}
.ah-hero::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,var(--ink) 2%,rgba(5,5,5,.55) 46%,rgba(5,5,5,.28) 100%)}
.ah-hero-in{position:relative;z-index:2}

.ah-eyebrow{margin:0 0 6px;font-size:11px;letter-spacing:.34em;color:var(--gold);
  font-weight:700}
.ah-h1{margin:0 0 10px;font-family:var(--disp);line-height:1.02;text-wrap:balance}
.ah-h1 span{display:block;font-size:clamp(34px,6vw,62px);letter-spacing:-.01em}
.ah-h1 em{display:block;font-style:normal;font-size:clamp(20px,3.2vw,32px);color:var(--gold)}
.ah-sub{margin:0 0 26px;color:var(--mute);font-size:14px;font-weight:300;max-width:52ch}

.ah-stats{display:flex;flex-wrap:wrap;gap:14px 40px}
.ah-stat{display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto auto;
  column-gap:11px;align-items:center}
.ah-stat-i{grid-row:1/3;font-size:19px;width:38px;height:38px;
  display:grid;place-items:center;border-radius:11px;background:rgba(217,165,46,.1);
  border:1px solid rgba(217,165,46,.28);color:var(--gold)}

/* The hand-lettered accent, sitting where the mockup puts it: hard against
   the far edge of the hero, rotated off-axis, never over the copy. It is
   decoration — below the art breakpoint it is removed rather than shrunk,
   because a scrawl small enough to fit a phone is just noise. */
.ah-scrawl{position:absolute;z-index:3;top:36%;inset-inline-end:5%;margin:0;
  font-family:var(--script);font-size:clamp(20px,2.2vw,34px);line-height:1.05;
  color:var(--gold-light);transform:rotate(-7deg);text-align:center;
  text-shadow:0 2px 18px rgba(0,0,0,.6);pointer-events:none}
.ah-scrawl span{display:block}
.ah-scrawl-crown{display:block;margin:4px auto 0;font-size:20px;color:var(--gold)}
@media (max-width:1100px){.ah-scrawl{display:none}}
.ah-stat b{font-family:var(--disp);font-size:20px;line-height:1.1}
.ah-stat span{font-size:11px;color:var(--dim);letter-spacing:.03em}

@media (max-width:640px){
  .ah-hero{padding:34px 0 26px}
  .ah-stats{gap:12px 22px}
  .ah-stat-i{width:32px;height:32px;font-size:16px}
  .ah-stat b{font-size:17px}
}

/* ------------------------------------------------------------- body */

/* align-items:start, and it is load-bearing: without it the rail
   stretches to the height of a 52-card grid and its promo card floats
   above several hundred pixels of nothing. */
.ah-body{display:grid;grid-template-columns:250px minmax(0,1fr);align-items:start;
  gap:24px;padding:26px 0 70px;max-width:1480px}
.ah-hero-in{max-width:1480px}
@media (max-width:980px){.ah-body{grid-template-columns:minmax(0,1fr)}}

/* ------------------------------------------------------------- rail */

.ah-rail{display:flex;flex-direction:column;gap:14px;
  position:sticky;top:calc(var(--nav-h,64px) + 16px)}
@media (max-width:980px){.ah-rail{position:static}}

.ah-cats{display:flex;flex-direction:column;gap:2px;padding:7px;
  background:var(--panel);border:1px solid var(--line);border-radius:14px}

/* On a phone the rail becomes a scrolling strip rather than 13 stacked
   rows that push the grid a screen and a half down the page. */
@media (max-width:980px){
  .ah-cats{flex-direction:row;overflow-x:auto;gap:6px;
    scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .ah-cats::-webkit-scrollbar{display:none}
  .ah-cat{flex:none}
  .ah-cat span{white-space:nowrap}
  .ah-cat b{display:none}
}

.ah-cat{display:flex;align-items:center;gap:9px;width:100%;padding:9px 11px;
  background:transparent;border:0;border-radius:10px;color:var(--mute);
  font-family:inherit;font-size:13px;font-weight:500;text-align:start;cursor:pointer;
  transition:background .16s,color .16s}
.ah-cat .ico{font-size:15px;color:var(--dim)}
.ah-cat.on .ico{color:var(--gold)}
.ah-cat span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ah-cat b{font-size:11px;color:var(--off);font-weight:600}
.ah-cat:hover{background:var(--panel2);color:var(--bone)}
.ah-cat.on{background:rgba(217,165,46,.12);color:var(--gold-light);font-weight:700}
.ah-cat.on i,.ah-cat.on b{color:var(--gold)}
.ah-cat:focus-visible{outline:2px solid var(--gold);outline-offset:-2px}

.ah-promo{display:block;padding:16px;border-radius:14px;text-align:center;
  background:linear-gradient(160deg,rgba(217,165,46,.14),rgba(217,165,46,.03));
  border:1px solid rgba(217,165,46,.3)}
.ah-promo b{display:block;font-family:var(--disp);font-size:14px;margin-bottom:5px}
.ah-promo p{margin:0 0 12px;color:var(--mute);font-size:11.5px;font-weight:300;line-height:1.75}
.ah-promo-n{display:flex;align-items:baseline;justify-content:center;gap:5px;margin-bottom:12px}
.ah-promo-n b{font-family:var(--disp);font-size:26px;color:var(--gold);margin:0}
.ah-promo-n span{font-size:11px;color:var(--gold-dark);font-weight:700}
.ah-claim-all{width:100%}
.ah-promo-bal{margin:11px 0 0;font-size:11px;color:var(--gold-dark);font-weight:600}
.ah-promo-bal b{color:var(--gold);font-size:12.5px;margin-inline-start:5px}
.ah-promo-link:hover{border-color:var(--gold)}
.ah-promo-go{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;
  font-weight:700;color:var(--gold)}
.ah-promo-go .ico{font-size:13px;transform:scaleX(-1)}

.btn-gold{background:var(--gold);border:1px solid var(--gold);color:var(--ink);
  font-weight:800;font-family:inherit;font-size:12.5px;padding:9px 14px;
  border-radius:9px;cursor:pointer;transition:background .16s,border-color .16s}
.btn-gold:hover{background:var(--gold-bright);border-color:var(--gold-bright)}
.btn-gold[disabled]{opacity:.5;cursor:default}

/* -------------------------------------------------------- filter bar */

.ah-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:12px;margin-bottom:18px}
.ah-pills{display:flex;gap:7px;flex-wrap:wrap}
.ah-pill{padding:7px 15px;background:var(--panel2);border:1px solid var(--line2);
  border-radius:999px;color:var(--mute);font-family:inherit;font-size:12.5px;
  font-weight:500;cursor:pointer;transition:border-color .16s,color .16s,background .16s}
.ah-pill:hover{border-color:var(--off);color:var(--bone)}
.ah-pill.on{background:rgba(217,165,46,.14);border-color:var(--gold);color:var(--gold-light);font-weight:700}

.ah-tools{display:flex;gap:8px;flex-wrap:wrap}
.ah-search input,.ah-sort select{background:var(--panel2);border:1px solid var(--line2);
  border-radius:9px;color:var(--bone);font-family:inherit;font-size:12.5px;
  padding:8px 12px;min-width:0}
.ah-search{position:relative;display:flex;align-items:center}
.ah-search .ico{position:absolute;inset-inline-start:11px;font-size:14px;color:var(--off);
  pointer-events:none}
.ah-search input{width:210px;padding-inline-start:32px}
.ah-search input::placeholder{color:var(--off)}
.ah-search input:focus,.ah-sort select:focus{outline:0;border-color:var(--gold)}
.ah-sort select{cursor:pointer}
@media (max-width:560px){
  .ah-tools{width:100%}
  .ah-search{flex:1}
  .ah-search input{width:100%}
}

/* ------------------------------------------------------------ grid */

/* auto-FIT, never auto-fill: auto-fill creates the empty tracks it
   cannot fill, so a search matching 3 cards would strand them in a
   5-column grid beside two columns of void. */
.ah-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(178px,1fr));gap:12px}

/* Phones get two-up. Without this the 178px track the desktop needs for six
   columns forces a single column on a 375px screen, and an achievement wall
   one card wide is a very long list. */
@media (max-width:640px){
  .ah-grid{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
}

.ah-card{position:relative;display:flex;flex-direction:column;align-items:center;
  text-align:center;gap:7px;padding:18px 14px 14px;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;
  overflow:hidden;cursor:pointer;
  transition:border-color .18s,transform .18s,background .18s}

/* The card's own quiet glow, drawn rather than downloaded: one photo per
   card would be 52 image requests on a 3G connection. */
.ah-card::before{content:"";position:absolute;inset-inline:0;top:0;height:96px;
  background:radial-gradient(120% 100% at 50% 0,rgba(217,165,46,.09),transparent 70%);
  pointer-events:none}
.ah-card:hover{border-color:var(--line2);transform:translateY(-2px);background:var(--panel2)}
.ah-card:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.ah-card.is-done{border-color:rgba(255,255,255,.09)}
.ah-card.is-claimable{border-color:rgba(217,165,46,.45)}
.ah-card.is-secret{border-style:dashed;cursor:default}
.ah-card.is-secret:hover{transform:none;background:var(--panel)}

/* hexagon badge: a ring of rarity colour with the panel punched out */
.ah-hex{position:relative;width:62px;height:70px;flex:none}
.ah-hex::before{content:"";position:absolute;inset:0;background:var(--rc,var(--line2));
  clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%)}
.ah-hex-in{position:absolute;inset:2px;background:var(--panel2);
  clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);
  display:grid;place-items:center;font-size:26px;color:var(--rc,var(--dim));line-height:1}
.ah-card:not(.is-done) .ah-hex-in{color:var(--dim)}
.ah-hex-in img{width:34px;height:34px;object-fit:contain}
.ah-card:not(.is-done) .ah-hex{opacity:.5}
.ah-card:not(.is-done) .ah-hex::before{background:var(--line2)}
.ah-lock{font-size:22px;color:var(--off)}

.ah-name{margin:2px 0 0;font-size:13.5px;font-weight:700;line-height:1.4}
.ah-card:not(.is-done) .ah-name{color:var(--mute)}
.ah-desc{margin:0;color:var(--dim);font-size:11.5px;font-weight:300;line-height:1.7}

.ah-meter{display:flex;align-items:center;justify-content:space-between;gap:8px;
  width:100%;margin-top:auto;padding-top:8px}
.ah-count{font-size:11px;color:var(--dim)}
.ah-xp{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:700;
  color:var(--gold)}
.ah-xp .ico{font-size:12px}

.ah-bar-track{width:100%;height:4px;background:var(--line);border-radius:99px;overflow:hidden}
.ah-bar-track i{display:block;height:100%;background:var(--gold);border-radius:99px}

.ah-claim{width:100%;margin-top:8px;padding:8px 10px;border-radius:9px;
  background:var(--gold);border:1px solid var(--gold);color:var(--ink);
  font-family:inherit;font-size:12px;font-weight:800;cursor:pointer;
  transition:background .16s}
.ah-claim:hover{background:var(--gold-bright)}
.ah-claim[disabled]{opacity:.55;cursor:default}

.ah-got{margin:8px 0 0;font-size:11px;color:var(--dim);display:flex;gap:6px;
  align-items:center;justify-content:center}
.ah-got b{color:var(--off);font-weight:400;font-size:10.5px}

.ah-rar{position:absolute;top:9px;inset-inline-start:11px;font-size:9.5px;
  letter-spacing:.06em;font-weight:700;color:var(--rc)}
.ah-card:not(.is-done) .ah-rar{color:var(--off)}

.ah-none{margin:34px 0;text-align:center;color:var(--dim);font-size:13px}

.ah-empty{margin:34px 0 70px;padding:44px 24px;text-align:center;background:var(--panel);
  border:1px dashed var(--line2);border-radius:16px}
.ah-empty b{display:block;font-family:var(--disp);font-size:18px;margin-bottom:8px}
.ah-empty p{margin:0;color:var(--dim);font-size:13px;font-weight:300;line-height:1.9}

/* ------------------------------------------------------------ side */

.ah-side{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));
  gap:14px;margin-top:26px}
.ah-panel{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:16px}
.ah-panel h2{margin:0 0 12px;font-family:var(--disp);font-size:14px}

.ah-rare{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:9px}
.ah-rare li{display:flex;align-items:center;gap:9px;font-size:12.5px}
.ah-rare li::before{content:"";width:3px;height:15px;border-radius:2px;background:var(--rc);flex:none}
.ah-rare span{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ah-rare b{color:var(--gold);font-size:11.5px;font-weight:700}

.ah-lead{list-style:none;margin:0;padding:0}
.ah-lead li{display:flex;align-items:center;gap:9px;padding:7px 0;
  border-bottom:1px solid rgba(41,41,41,.6);font-size:12.5px}
.ah-lead li:last-child{border-bottom:0}
.ah-lead li.is-me{background:rgba(217,165,46,.06);
  margin-inline:-16px;padding-inline:16px;border-radius:6px}
.ah-lead-n{font-family:var(--disp);font-size:12px;color:var(--dim);min-width:15px}
.ah-lead a{flex:1;min-width:0;display:flex;align-items:center;gap:7px;color:var(--bone)}
.ah-lead a:hover{color:var(--gold)}
.ah-lead a img{width:24px;height:24px;border-radius:7px;object-fit:cover;flex:none}
.ah-lead a span{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ah-lead li>b:last-child{font-size:11.5px;color:var(--mute);font-weight:600}

.ah-sync{margin:22px 0 0;text-align:center;font-size:11px;color:var(--off);font-weight:300}
.ah-sync b{color:var(--dim);font-weight:400;margin-inline-start:4px}

/* ----------------------------------------------------------- modal */

body.ah-locked{overflow:hidden}
.ah-modal{position:fixed;inset:0;z-index:200;display:grid;place-items:center;padding:20px}
.ah-modal-bg{position:absolute;inset:0;background:rgba(5,5,5,.82);backdrop-filter:blur(5px)}
.ah-modal-box{position:relative;z-index:1;width:min(400px,100%);padding:26px 24px 20px;
  background:var(--panel);border:1px solid var(--line2);border-radius:18px;text-align:center;
  box-shadow:0 24px 60px rgba(0,0,0,.6)}
.ah-modal-box::before{content:"";position:absolute;inset-inline:0;top:0;height:2px;
  background:var(--rc,var(--gold));border-radius:18px 18px 0 0}
.ah-modal-x{position:absolute;top:10px;inset-inline-end:12px;width:28px;height:28px;
  background:transparent;border:0;color:var(--dim);font-size:22px;line-height:1;cursor:pointer}
.ah-modal-x:hover{color:var(--bone)}
.ah-hex-lg{width:78px;height:88px;margin:0 auto 12px}
.ah-hex-lg .ah-hex-in{font-size:28px}
.ah-hex-lg .ah-hex-in img{width:44px;height:44px}
.ah-modal-rar{display:inline-block;margin-bottom:7px;font-size:10.5px;font-weight:700;
  letter-spacing:.08em;color:var(--rc,var(--gold))}
.ah-modal-box h3{margin:0 0 8px;font-family:var(--disp);font-size:19px}
.ah-modal-box>p{margin:0 0 18px;color:var(--mute);font-size:13px;font-weight:300;line-height:1.9}
.ah-modal-rows{display:flex;flex-direction:column;gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:11px;overflow:hidden}
.ah-modal-rows div{display:flex;align-items:center;justify-content:space-between;
  gap:10px;padding:9px 13px;background:var(--panel2)}
.ah-modal-rows span{font-size:11.5px;color:var(--dim)}
.ah-modal-rows b{font-size:12.5px;font-weight:700}

/* ----------------------------------------------------------- toast */

.ah-toast{position:fixed;z-index:210;bottom:22px;inset-inline-start:50%;
  transform:translateX(50%);padding:11px 18px;border-radius:11px;
  background:var(--panel2);border:1px solid var(--gold);color:var(--bone);
  font-size:13px;font-weight:600;box-shadow:0 12px 34px rgba(0,0,0,.55)}
.ah-toast.is-bad{border-color:var(--line2);color:var(--mute)}

@media (prefers-reduced-motion:reduce){
  .ah-card,.ah-card:hover{transition:none;transform:none}
}

/* ===================================================================
   SHOP

   This page takes real money, so restraint is a feature here. Gold
   marks exactly three things: the price, the buy button, and the
   SPONSOR rank. Everything else is panel and hairline. A shop where
   every card shouts is a shop players stop trusting.
   =================================================================== */

.sh-shell{padding-top:var(--nav-h,64px)}

/* ------------------------------------------------------------- hero */

.sh-hero{position:relative;overflow:hidden;padding:54px 0 34px;
  border-bottom:1px solid var(--line)}
.sh-hero-art{position:absolute;inset:0;background-image:var(--art);
  background-size:cover;background-position:center 38%;opacity:.42;
  -webkit-mask-image:linear-gradient(to right,#000 0%,rgba(0,0,0,.7) 36%,transparent 80%);
  mask-image:linear-gradient(to right,#000 0%,rgba(0,0,0,.7) 36%,transparent 80%)}
.sh-hero::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,var(--ink) 2%,rgba(5,5,5,.5) 46%,rgba(5,5,5,.25) 100%)}
.sh-hero-in{position:relative;z-index:2}

.sh-eyebrow{margin:0 0 4px;font-size:11px;letter-spacing:.34em;color:var(--gold);font-weight:700}
.sh-h1{margin:0 0 8px;font-family:var(--disp);font-size:clamp(40px,7vw,76px);
  line-height:.98;letter-spacing:-.01em;
  background:linear-gradient(180deg,var(--gold-highlight),var(--gold-dark));
  -webkit-background-clip:text;background-clip:text;color:transparent}
.sh-sub{margin:0 0 24px;color:var(--mute);font-size:13px;font-weight:500;
  letter-spacing:.12em}

.sh-trust{display:flex;flex-wrap:wrap;gap:12px 34px}
.sh-trust-i{display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto auto;
  column-gap:11px;align-items:center}
.sh-trust-i .ico{grid-row:1/3;font-size:19px;width:38px;height:38px;display:grid;
  place-items:center;border-radius:11px;color:var(--gold);
  background:rgba(217,165,46,.1);border:1px solid rgba(217,165,46,.28)}
.sh-trust-i b{font-size:13px}
.sh-trust-i span{font-size:11px;color:var(--dim)}

.sh-scrawl{position:absolute;z-index:3;top:30%;inset-inline-end:5%;margin:0;
  font-family:var(--script);font-size:clamp(20px,2.1vw,32px);line-height:1.04;
  color:var(--gold-light);transform:rotate(-7deg);text-align:center;
  text-shadow:0 2px 18px rgba(0,0,0,.6);pointer-events:none}
.sh-scrawl span{display:block}
.sh-scrawl-crown{display:block;margin:4px auto 0;font-size:19px;color:var(--gold)}
@media (max-width:1100px){.sh-scrawl{display:none}}
@media (max-width:640px){
  .sh-hero{padding:34px 0 26px}
  .sh-trust{gap:10px 18px}
  .sh-trust-i .ico{width:32px;height:32px;font-size:16px}
}

/* ------------------------------------------------------ server tabs */

.sh-servers{display:flex;gap:8px;flex-wrap:wrap;padding-top:22px}
.sh-server{padding:8px 18px;border-radius:999px;background:var(--panel2);
  border:1px solid var(--line2);color:var(--mute);font-size:13px;font-weight:600;
  transition:border-color .16s,color .16s,background .16s}
.sh-server:hover{border-color:var(--off);color:var(--bone)}
.sh-server.on{background:rgba(217,165,46,.14);border-color:var(--gold);
  color:var(--gold-light);font-weight:700}

/* ------------------------------------------------------------- body */

/* align-items:start, or the rail stretches to the height of the grid and
   its support card floats above a column of nothing. */
.sh-body{display:grid;grid-template-columns:236px minmax(0,1fr);align-items:start;
  gap:24px;padding:20px 0 60px}
@media (max-width:980px){.sh-body{grid-template-columns:minmax(0,1fr)}}

.sh-rail{display:flex;flex-direction:column;gap:14px;
  position:sticky;top:calc(var(--nav-h,64px) + 16px)}
@media (max-width:980px){.sh-rail{position:static}}

.sh-cats{display:flex;flex-direction:column;gap:2px;padding:7px;
  background:var(--panel);border:1px solid var(--line);border-radius:14px}
.sh-cats-t{margin:5px 8px 6px;font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--off);font-weight:700}
.sh-cat{display:flex;align-items:center;gap:9px;width:100%;padding:9px 11px;
  background:transparent;border:0;border-radius:10px;color:var(--mute);
  font-family:inherit;font-size:13px;font-weight:500;text-align:start;cursor:pointer;
  transition:background .16s,color .16s}
.sh-cat .ico{font-size:14px;color:var(--dim);flex:none}
.sh-cat span{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sh-cat b{font-size:11px;color:var(--off);font-weight:600}
.sh-cat:hover{background:var(--panel2);color:var(--bone)}
.sh-cat.on{background:rgba(217,165,46,.12);color:var(--gold-light);font-weight:700}
.sh-cat.on .ico,.sh-cat.on b{color:var(--gold)}
.sh-cat:focus-visible{outline:2px solid var(--gold);outline-offset:-2px}

/* AFTER the .sh-cat rules, not before.
   This block used to sit above them, so at equal specificity the base
   `.sh-cat{width:100%}` won and `flex:none` never applied - every category
   became a 374px slab on a 390px phone and only one fitted on screen at a
   time. Overriding the width is the other half: flex:none does not undo an
   explicit width. */
@media (max-width:980px){
  .sh-cats{flex-direction:row;overflow-x:auto;gap:6px;
    scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .sh-cats::-webkit-scrollbar{display:none}
  .sh-cats-t{display:none}
  .sh-cat{flex:none;width:auto}
  /* The count is noise once the chips are compact. */
  .sh-cat b{display:none}
}

.sh-support{padding:16px;border-radius:14px;text-align:center;
  background:linear-gradient(160deg,rgba(217,165,46,.13),rgba(217,165,46,.03));
  border:1px solid rgba(217,165,46,.3)}
.sh-support-mark{font-size:24px;color:var(--gold);margin-bottom:7px}
.sh-support b{display:block;font-family:var(--disp);font-size:14px;margin-bottom:5px}
.sh-support p{margin:0 0 12px;color:var(--mute);font-size:11.5px;font-weight:300;line-height:1.75}
.sh-support-go{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;
  font-weight:700;color:var(--gold)}
.sh-support-go:hover{color:var(--gold-bright)}

/* --------------------------------------------------------- controls */

.sh-bar{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:14px}
.sh-search{position:relative;flex:1;min-width:200px;display:flex;align-items:center}
.sh-search .ico{position:absolute;inset-inline-start:12px;font-size:15px;
  color:var(--off);pointer-events:none}
.sh-search input{width:100%;padding:10px 14px;padding-inline-start:36px;
  background:var(--panel2);border:1px solid var(--line2);border-radius:10px;
  color:var(--bone);font-family:inherit;font-size:13px}
.sh-search input::placeholder{color:var(--off)}
.sh-sort select{padding:10px 12px;background:var(--panel2);border:1px solid var(--line2);
  border-radius:10px;color:var(--bone);font-family:inherit;font-size:13px;cursor:pointer}
.sh-search input:focus,.sh-sort select:focus{outline:0;border-color:var(--gold)}

.sh-bal{margin:0 0 18px;font-size:12px;color:var(--dim)}
.sh-bal b{color:var(--gold);font-size:14px;margin-inline-start:6px}

.sh-sec-head{display:flex;align-items:baseline;justify-content:space-between;
  gap:12px;margin:26px 0 12px}
.sh-sec-head h2{display:flex;align-items:center;gap:8px;margin:0;
  font-family:var(--disp);font-size:16px}
.sh-sec-head h2 .ico{font-size:16px;color:var(--gold)}
.sh-sec-head small{font-size:11.5px}

/* ------------------------------------------------------------ cards */

/* auto-FIT, never auto-fill: auto-fill leaves empty tracks it cannot
   fill, so a filter down to two cards would strand them beside a
   column of void. */
.sh-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(158px,1fr));gap:12px}

.sh-card{position:relative;display:flex;flex-direction:column;align-items:center;
  text-align:center;gap:6px;padding:18px 14px 14px;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;
  transition:border-color .18s,transform .18s,background .18s}
.sh-card:hover{border-color:var(--line2);transform:translateY(-2px);background:var(--panel2)}
.sh-card.is-tagged{border-color:color-mix(in srgb,var(--rc) 45%,transparent)}

.sh-tag{position:absolute;top:-1px;inset-inline-start:14px;padding:3px 9px 4px;
  border-radius:0 0 8px 8px;background:var(--rc);color:var(--ink);
  font-size:9.5px;font-weight:800;letter-spacing:.04em}

.sh-art{width:74px;height:74px;flex:none;display:grid;place-items:center;
  border-radius:14px;background:var(--panel2);border:1px solid var(--line2);
  margin-bottom:2px}
.sh-art img{width:56px;height:56px;object-fit:contain}
.sh-art .ico{font-size:26px;color:var(--dim)}
.sh-art-rank{border-color:color-mix(in srgb,var(--rc) 45%,transparent)}
.sh-art-rank .ico{color:var(--rc);font-size:30px}

.sh-name{margin:2px 0 0;font-size:14px;font-weight:700;line-height:1.35}
.sh-meta{margin:0;font-size:10.5px;color:var(--off);letter-spacing:.05em}

.sh-price{display:flex;align-items:center;justify-content:center;gap:6px;margin:8px 0 2px}
.sh-price img{width:17px;height:17px;object-fit:contain;flex:none}
.sh-price b{font-family:var(--disp);font-size:19px;color:var(--gold)}

.sh-buy{width:100%;margin-top:auto;padding-top:10px}
.sh-btn{display:block;width:100%;padding:9px 12px;border-radius:10px;
  background:var(--gold);border:1px solid var(--gold);color:var(--ink);
  font-family:inherit;font-size:12.5px;font-weight:800;text-align:center;
  cursor:pointer;transition:background .16s,border-color .16s}
.sh-btn:hover{background:var(--gold-bright);border-color:var(--gold-bright)}

/* Not affordable, not signed in, shop off: three states, one shape, and
   none of them gold — gold on this page means "you can press this". */
.sh-btn.is-short,.sh-btn-ghost,.sh-btn-off{background:transparent;color:var(--mute);
  border-color:var(--line2);font-weight:600;cursor:default}
.sh-btn.is-short{opacity:.7}
.sh-btn-ghost{margin-top:auto;cursor:pointer}
.sh-btn-ghost:hover{background:var(--panel2);border-color:var(--off);color:var(--bone)}

.sh-none{margin:34px 0;text-align:center;color:var(--dim);font-size:13px}

/* -------------------------------------------------------- bottom cta */

.sh-cta{border-top:1px solid var(--line);
  background:linear-gradient(180deg,rgba(217,165,46,.05),transparent 70%)}
.sh-cta-in{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:22px;padding:34px 0 40px}
.sh-cta-copy{max-width:44ch}
.sh-cta-eyebrow{margin:0 0 3px;font-size:11px;letter-spacing:.2em;color:var(--gold);
  font-weight:700}
.sh-cta-t{margin:0 0 8px;font-family:var(--disp);font-size:clamp(22px,3vw,32px);line-height:1.1}
.sh-cta-p{margin:0;color:var(--mute);font-size:13px;font-weight:300;line-height:1.85}

.sh-cta-stats{display:flex;gap:34px}
.sh-cta-stats b{display:block;font-family:var(--disp);font-size:26px;color:var(--gold);line-height:1}
.sh-cta-stats span{font-size:11px;color:var(--dim)}

.sh-cta .btn-gold{display:inline-flex;align-items:center;gap:7px}
.sh-cta .btn-gold .ico{font-size:15px}

/* --- shared page bits: the key-figures table, the owner-only note, and
       the footer legal row. The rest of the old standing-page layout went
       when terms and privacy moved to the .lg-* design. ------------------ */
/* A clause that carries a number the player will be charged gets lifted out
   of the prose, because those are the sentences people come back to check. */
.pg-key{border:1px solid var(--line2);border-radius:12px;background:var(--panel);
  padding:16px 18px;margin:0 0 14px;max-width:70ch}
.pg-key dl{margin:0;display:grid;grid-template-columns:auto 1fr;gap:8px 18px;
  font-size:14px;align-items:baseline}
.pg-key dt{color:var(--dim);font-weight:400}
.pg-key dd{margin:0;color:var(--bone);font-weight:700}
/* OWNER-ONLY. Never rendered for a player — see pages/partials/owner-note.
   It marks a clause whose wording is a business decision the code cannot
   make, so the person who can decide it is reminded every time they read
   their own terms page. */
.pg-todo{border:1px solid var(--gold-dark);border-radius:12px;
  background:linear-gradient(180deg,rgba(217,165,46,.10),rgba(217,165,46,.03));
  padding:14px 16px;margin:0 0 16px;max-width:70ch;font-size:13.5px;
  color:var(--gold-light);line-height:1.8}
.pg-todo b{display:block;color:var(--gold-bright);font-weight:700;
  font-size:11px;letter-spacing:.16em;text-transform:uppercase;margin-bottom:6px}
/* The footer's legal row. Separated from the nav links above it because these
   are destinations someone seeks out, and a payment provider expects to find
   them from any page. */
.f-legal{display:flex;align-items:center;justify-content:space-between;
  gap:var(--s2);flex-wrap:wrap;text-align:start}
.f-legal-links{display:flex;gap:var(--s2);flex-wrap:wrap;font-size:11.5px}
.f-legal-links a{color:var(--dim);transition:color .18s}
.f-legal-links a:hover{color:var(--bone)}
@media(max-width:560px){.f-legal{justify-content:center;text-align:center}}

/* ===================================================================
   FAQ PAGE — to the supplied mockup

   Banner with a search field, an icon rail of categories on the leading
   side, one panel at a time beside it, and three cards underneath.

   The rail is BUTTONS, not links, and every panel is visible until app.js
   takes over — with no JavaScript the page is a plain list of every
   question rather than nine empty tabs. Progressive, in that order.
   =================================================================== */

.fq-hero{position:relative;padding:150px 0 var(--s5);overflow:hidden;
  border-bottom:1px solid var(--line)}
.fq-hero-bg{position:absolute;inset:0}
.fq-hero-bg img{width:100%;height:100%;object-fit:cover;object-position:center 42%}
/* Darker on the leading side, where the type sits, and left clearer on the
   trailing side so the artwork still reads. */
.fq-hero-bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to left,rgba(5,5,5,.10),rgba(5,5,5,.72) 62%,var(--ink)),
             linear-gradient(to top,var(--ink) 2%,transparent 42%)}
.fq-hero-in{position:relative;z-index:2;max-width:620px}
.fq-hero h1{font-family:var(--ui);font-weight:900;letter-spacing:-.015em;
  font-size:clamp(32px,5vw,52px);line-height:1.12;margin:0 0 14px;text-wrap:balance}
.fq-hero .lede{max-width:46ch;margin-bottom:var(--s3)}

.fq-search{position:relative;display:flex;align-items:center;gap:10px;
  max-width:520px;padding:0 14px;height:52px;border-radius:12px;
  border:1px solid var(--line2);background:rgba(8,8,8,.78);
  backdrop-filter:blur(8px);transition:border-color .18s,box-shadow .18s}
.fq-search:focus-within{border-color:var(--gold-dark);
  box-shadow:0 0 0 3px rgba(217,165,46,.13)}
.fq-search>.ico{color:var(--dim);font-size:17px;flex:none}
.fq-search input{flex:1;min-width:0;background:none;border:0;outline:0;
  color:var(--bone);font-family:var(--ui);font-size:14.5px;font-weight:300}
.fq-search input::placeholder{color:var(--off)}
/* The native clear button is a light X on a dark field, so it is invisible. */
.fq-search input::-webkit-search-cancel-button{-webkit-appearance:none}
.fq-kbd{flex:none;font-family:var(--ui);font-size:10px;font-weight:700;
  letter-spacing:.06em;color:var(--dim);background:var(--panel2);
  border:1px solid var(--line2);border-radius:5px;padding:3px 6px;line-height:1}
@media(max-width:560px){.fq-kbd{display:none}}

.fq-body{padding:var(--s5) 0 var(--s6)}
.fq-split{display:grid;grid-template-columns:280px 1fr;gap:var(--s4);
  align-items:start;margin-bottom:var(--s5)}
@media(max-width:960px){.fq-split{grid-template-columns:1fr;gap:var(--s3)}}

.fq-rail{display:flex;flex-direction:column;gap:8px;position:sticky;top:100px}
@media(max-width:960px){
  /* A horizontal strip on a phone: nine stacked cards would fill the whole
     screen before the first answer. */
  .fq-rail{position:static;flex-direction:row;overflow-x:auto;
    padding-bottom:6px;scrollbar-width:thin}
  .fq-cat{flex:none}
  .fq-cat-n{display:none}
}
.fq-cat{display:flex;align-items:center;gap:12px;width:100%;text-align:start;
  padding:14px 16px;border-radius:12px;cursor:pointer;
  border:1px solid var(--line);background:var(--panel);
  color:var(--mute);font-family:var(--ui);font-size:14px;font-weight:500;
  transition:background .18s,border-color .18s,color .18s}
.fq-cat:hover{background:var(--card-hover);color:var(--bone)}
.fq-cat.on{color:var(--white);border-color:var(--gold-dark);
  background:linear-gradient(180deg,rgba(217,165,46,.16),rgba(217,165,46,.05))}
.fq-cat-ico{flex:none;width:34px;height:34px;border-radius:9px;
  display:grid;place-items:center;font-size:16px;
  background:var(--elevated);color:var(--mute);transition:background .18s,color .18s}
.fq-cat.on .fq-cat-ico{background:rgba(217,165,46,.18);color:var(--gold-bright)}
.fq-cat-l{flex:1;min-width:0}
.fq-cat-n{flex:none;font-size:12px;color:var(--off)}
.fq-cat.on .fq-cat-n{color:var(--gold-light)}

.fq-main{position:relative;min-width:0}
.fq-panel h2{font-family:var(--ui);font-weight:900;letter-spacing:-.01em;
  font-size:clamp(20px,2.6vw,26px);margin:0 0 6px}
.fq-sub{color:var(--dim);font-size:13.5px;font-weight:300;margin:0 0 var(--s3);max-width:60ch}
.fq-none{color:var(--mute);font-size:14px;font-weight:300;
  padding:var(--s4) 0;margin:0;max-width:52ch}

/* The hand-lettered note from the mockup. Decorative and English by design,
   so it is aria-hidden and carries nothing a reader needs. Absolutely
   positioned so it cannot push the heading around, and gone on narrow
   screens where there is no room beside the title. */
.fq-scrawl{position:absolute;top:-6px;inset-inline-end:0;margin:0;
  display:flex;flex-direction:column;align-items:flex-end;
  font-family:var(--script);font-size:22px;line-height:1.05;
  color:var(--gold-light);opacity:.85;pointer-events:none;transform:rotate(-3deg)}
@media(max-width:900px){.fq-scrawl{display:none}}

/* ---------- the three cards ---------- */
.fq-cards{display:grid;grid-template-columns:1fr 1fr 1fr;gap:var(--s3);align-items:stretch}
@media(max-width:1000px){.fq-cards{grid-template-columns:1fr 1fr}}
@media(max-width:700px){.fq-cards{grid-template-columns:1fr}}

.fq-card{position:relative;border:1px solid var(--line);border-radius:14px;
  background:var(--panel);padding:20px;overflow:hidden;
  display:flex;flex-direction:column}
.fq-card-t{font-size:11px;font-weight:700;letter-spacing:.18em;color:var(--gold);
  text-transform:uppercase;margin:0 0 16px}

.fq-card-cta{padding:0;min-height:230px;justify-content:flex-end;border-color:var(--line2)}
.fq-card-cta>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.fq-card-cta::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,var(--ink) 12%,rgba(5,5,5,.72) 58%,rgba(5,5,5,.28))}
.fq-card-in{position:relative;z-index:2;padding:20px}
.fq-card-in h2{font-family:var(--ui);font-weight:800;font-size:19px;
  line-height:1.4;margin:0 0 6px}
.fq-card-in p{color:var(--mute);font-size:13.5px;font-weight:300;margin:0 0 16px;max-width:34ch}

.fq-links{display:flex;flex-direction:column;gap:4px}
.fq-links a{display:flex;align-items:center;gap:12px;padding:11px 10px;
  border-radius:10px;transition:background .18s}
.fq-links a:hover{background:rgba(255,255,255,.035)}
.fq-link-ico{flex:none;width:36px;height:36px;border-radius:10px;display:grid;
  place-items:center;font-size:17px;background:var(--elevated);color:var(--mute)}
.fq-links a:hover .fq-link-ico{color:var(--bone)}
.fq-link-txt{flex:1;min-width:0;display:flex;flex-direction:column;line-height:1.4}
.fq-link-txt b{font-size:13.5px;font-weight:700;color:var(--bone)}
.fq-link-txt em{font-style:normal;font-size:11.5px;font-weight:300;color:var(--dim)}
/* The page is RTL, so the arrow is mirrored and "forward" is leftward. */
.fq-link-go{flex:none;font-size:15px;color:var(--off);transform:scaleX(-1);
  transition:transform .18s,color .18s}
.fq-links a:hover .fq-link-go{color:var(--gold);transform:scaleX(-1) translateX(3px)}

.fq-status-line{display:flex;align-items:center;gap:9px;margin:0 0 16px;
  font-size:14px;font-weight:700;color:var(--bone)}
.fq-dot{width:9px;height:9px;border-radius:50%;flex:none;background:var(--off)}
.fq-dot.on{background:var(--live);box-shadow:0 0 0 3px rgba(63,207,127,.16)}
.fq-pop{border:1px solid var(--line2);border-radius:11px;background:var(--panel2);
  padding:14px 16px;margin-bottom:14px;display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.fq-pop-n{font-family:var(--ui);font-weight:900;font-size:26px;color:var(--white);line-height:1}
.fq-pop-s{font-size:12px;color:var(--dim);font-weight:300}
.fq-srv{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
.fq-srv li{display:flex;align-items:center;gap:9px;font-size:13px;color:var(--mute)}
.fq-srv b{font-weight:700;color:var(--bone);min-width:38px}
.fq-srv .num{margin-inline-start:auto;color:var(--dim);font-size:12.5px}

/* ===================================================================
   LEGAL PAGES — terms of service, privacy policy

   To the supplied mockup: banner, breadcrumb strip, a rail of the legal
   pages with an art panel under it, and numbered cards down the main
   column, each led by a gold icon tile.

   The numbers in the headings are TEXT, not a CSS counter. A counter
   renumbers itself when a clause is reordered, which sounds like a
   feature until somebody cites "clause 7" in a support ticket and the
   next deploy makes clause 7 a different rule.
   =================================================================== */

.lg-hero{position:relative;padding:150px 0 var(--s5);overflow:hidden;
  border-bottom:1px solid var(--line)}
.lg-hero-bg{position:absolute;inset:0}
.lg-hero-bg img{width:100%;height:100%;object-fit:cover;object-position:center 38%}
.lg-hero-bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to left,rgba(5,5,5,.12),rgba(5,5,5,.74) 60%,var(--ink)),
             linear-gradient(to top,var(--ink) 2%,transparent 46%)}
.lg-hero-in{position:relative;z-index:2;max-width:640px}
.lg-hero h1{font-family:var(--ui);font-weight:900;letter-spacing:-.015em;
  font-size:clamp(32px,5.2vw,54px);line-height:1.1;margin:0 0 10px;text-wrap:balance}
/* The letter-spaced line under the title in the mockup. Spacing this wide
   needs the extra line-height or the ascenders collide with the lede. */
.lg-tag{font-size:12.5px;font-weight:700;letter-spacing:.26em;color:var(--gold-light);
  margin:0 0 18px;line-height:1.9}
.lg-hero .lede{max-width:52ch}

.lg-hero-scrawl{position:absolute;z-index:2;top:34%;inset-inline-end:6%;margin:0;
  display:flex;flex-direction:column;align-items:flex-end;
  font-family:var(--script);font-size:clamp(20px,2.6vw,34px);line-height:1.02;
  color:var(--gold-light);opacity:.9;pointer-events:none;transform:rotate(-4deg);
  text-shadow:0 2px 18px rgba(0,0,0,.55)}
@media(max-width:900px){.lg-hero-scrawl{display:none}}

/* ---------- breadcrumb strip ---------- */
.lg-crumbs{border-bottom:1px solid var(--line);background:var(--black-deep)}
.lg-crumbs-in{display:flex;align-items:center;justify-content:space-between;
  gap:var(--s2);flex-wrap:wrap;padding-block:12px;font-size:12.5px;color:var(--dim)}
.lg-crumbs nav{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.lg-crumbs a{color:var(--dim);transition:color .18s}
.lg-crumbs a:hover{color:var(--bone)}
.lg-crumbs b{color:var(--bone);font-weight:700}
.lg-crumbs span[aria-hidden]{color:var(--off)}
.lg-updated{color:var(--off)}

.lg-body{padding:var(--s5) 0 var(--s6)}
.lg-split{display:grid;grid-template-columns:270px 1fr;gap:var(--s4);align-items:start}
@media(max-width:960px){.lg-split{grid-template-columns:1fr;gap:var(--s3)}}

/* ---------- the rail and the art panel ---------- */
.lg-side{position:sticky;top:100px;display:flex;flex-direction:column;gap:var(--s3)}
.lg-rail{display:flex;flex-direction:column;gap:6px;padding:8px;
  border:1px solid var(--line);border-radius:14px;background:var(--panel)}
.lg-rail-i{display:flex;align-items:center;gap:11px;padding:11px 12px;
  border-radius:10px;font-size:13.5px;font-weight:500;color:var(--mute);
  border:1px solid transparent;transition:background .18s,color .18s,border-color .18s}
.lg-rail-i:hover{background:rgba(255,255,255,.035);color:var(--bone)}
.lg-rail-i.on{color:var(--white);border-color:var(--gold-dark);
  background:linear-gradient(180deg,rgba(217,165,46,.16),rgba(217,165,46,.04))}
.lg-rail-ico{flex:none;width:30px;height:30px;border-radius:8px;display:grid;
  place-items:center;font-size:15px;background:var(--elevated);color:var(--mute);
  transition:background .18s,color .18s}
.lg-rail-i.on .lg-rail-ico{background:rgba(217,165,46,.18);color:var(--gold-bright)}

.lg-art{position:relative;border:1px solid var(--line);border-radius:14px;
  overflow:hidden;min-height:420px;display:flex;align-items:flex-end}
.lg-art>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.lg-art::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,var(--ink) 16%,rgba(5,5,5,.66) 58%,rgba(5,5,5,.18))}
.lg-art-in{position:relative;z-index:2;padding:20px}
.lg-art-scrawl{display:flex;flex-direction:column;margin:0 0 18px;
  font-family:var(--script);font-size:26px;line-height:1.04;color:var(--gold-light)}
.lg-art-in h2{font-family:var(--ui);font-weight:900;font-size:16px;line-height:1.5;
  letter-spacing:.02em;margin:0 0 8px}
.lg-art-in p{color:var(--mute);font-size:13px;font-weight:300;line-height:1.85;margin:0}

/* AFTER the rules it overrides, not before. .lg-rail and .lg-art set
   flex-direction and display at the same specificity, so a media query
   placed above them loses the cascade and the mobile layout silently
   never applies — which is exactly what happened the first time. */
@media(max-width:960px){
  .lg-side{position:static}
  /* The art panel is atmosphere. On a phone it would push the first clause
     a full screen down, so the rail travels and the panel does not. */
  .lg-art{display:none}
  .lg-rail{flex-direction:row;overflow-x:auto;padding-bottom:6px;scrollbar-width:thin}
  .lg-rail-i{flex:none}
}

/* ---------- the numbered cards ---------- */
.lg-secs{display:flex;flex-direction:column;gap:14px;min-width:0}
/* scroll-margin, not a spacer: the nav is fixed, so an anchor jump would
   otherwise land the heading underneath it. */
.lg-sec{display:flex;gap:16px;padding:22px;scroll-margin-top:110px;
  border:1px solid var(--line);border-radius:14px;background:var(--panel)}
@media(max-width:600px){.lg-sec{padding:18px;gap:12px}}
.lg-ico{flex:none;width:38px;height:38px;border-radius:10px;display:grid;
  place-items:center;font-size:18px;
  background:rgba(217,165,46,.14);color:var(--gold-bright)}
.lg-sec-in{flex:1;min-width:0}
.lg-sec h2{font-family:var(--ui);font-weight:800;letter-spacing:-.005em;
  font-size:clamp(16.5px,1.9vw,19px);line-height:1.5;margin:0 0 12px;
  color:var(--gold-light);text-wrap:balance}
.lg-sec p{color:var(--mute);font-size:14px;font-weight:300;line-height:1.95;
  max-width:72ch;margin:0 0 12px}
.lg-sec p:last-child{margin-bottom:0}
.lg-sec strong,.lg-sec b{color:var(--bone);font-weight:700}
.lg-sec ul{margin:0 0 12px;padding-inline-start:18px;color:var(--mute);
  font-size:14px;font-weight:300;line-height:1.95;max-width:72ch}
.lg-sec ul:last-child{margin-bottom:0}
.lg-sec li{margin-bottom:5px}
.lg-sec li::marker{color:var(--gold-dark)}

/* The key figures, lifted out of the prose because those are the lines
   people come back to check. */
.lg-key{border:1px solid var(--line2);border-radius:11px;background:var(--panel2);
  padding:15px 17px;margin:0 0 14px;max-width:72ch}
.lg-key dl{margin:0;display:grid;grid-template-columns:auto 1fr;gap:8px 18px;
  font-size:13.5px;align-items:baseline}
.lg-key dt{color:var(--dim);font-weight:400}
.lg-key dd{margin:0;color:var(--bone);font-weight:700}

/* The two-column inventory in privacy section 1. */
.lg-two{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:0 0 14px}
@media(max-width:700px){.lg-two{grid-template-columns:1fr}}
.lg-two-box{border:1px solid var(--line2);border-radius:11px;background:var(--panel2);
  padding:15px 17px}
.lg-two-t{font-size:12.5px;font-weight:700;color:var(--gold-light);margin:0 0 10px}
.lg-two-box ul{margin:0;padding-inline-start:17px;font-size:13px;line-height:1.85;max-width:none}
.lg-two-box li{margin-bottom:4px}

.lg-contact{display:inline-flex;align-items:center;gap:11px;margin-top:6px;
  padding:11px 16px;border-radius:11px;font-size:13.5px;font-weight:700;
  border:1px solid var(--gold-dark);color:var(--gold-light);
  background:linear-gradient(180deg,rgba(217,165,46,.14),rgba(217,165,46,.04));
  transition:background .18s,color .18s}
.lg-contact:hover{color:var(--ink);background:var(--gold);border-color:var(--gold)}
.lg-contact-ico{font-size:15px;flex:none}
/* The page is RTL, so the arrow is mirrored and "forward" is leftward. */
.lg-contact-go{flex:none;font-size:15px;transform:scaleX(-1);transition:transform .18s}
.lg-contact:hover .lg-contact-go{transform:scaleX(-1) translateX(3px)}

/* ===================================================================
   OWNER PANEL — dashboard, players, payments, delivery

   Deliberately plainer than the public site. This is a workbench: the
   owner is reading numbers and pressing things that move money, so the
   gold budget goes on the ONE tile that needs attention rather than on
   decoration. A panel that looks as exciting as the landing page makes
   the alarming tile look like everything else.
   =================================================================== */

/* A size modifier, not a new variant — .btn-g, .btn-gold and .btn-danger
   already exist and carry the meaning. */
.btn-sm{padding:8px 14px;font-size:12.5px;border-radius:7px}
.btn-sm:hover{transform:none}
.btn:disabled{opacity:.45;cursor:not-allowed;transform:none}

/* PENDING is neither an error nor "off": a payment mid-flight is a normal
   state that becomes a problem only with age, and colouring it red makes
   every healthy checkout look like a failure. */
.pill-warn{display:inline-block;padding:3px 9px;border-radius:6px;font-size:11.5px;
  font-weight:700;background:rgba(217,165,46,.14);color:var(--gold-light);
  border:1px solid rgba(217,165,46,.35)}

/* ---------- attention list ---------- */
.od-attn{display:flex;flex-direction:column;gap:8px;margin-bottom:var(--s3)}
.od-attn-row{display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  padding:14px 16px;border-radius:12px;border:1px solid var(--line2);
  background:var(--panel)}
.od-attn-n{flex:none;min-width:44px;font-size:20px;font-weight:900;text-align:center}
.od-attn-t{flex:1;min-width:220px;font-size:13.5px;color:var(--mute);line-height:1.75}
.od-attn-row.od-bad{border-color:rgba(229,84,75,.45);background:rgba(229,84,75,.06)}
.od-attn-row.od-bad .od-attn-n{color:var(--danger-text)}
.od-attn-row.od-warn{border-color:rgba(217,165,46,.42);background:rgba(217,165,46,.05)}
.od-attn-row.od-warn .od-attn-n{color:var(--gold-bright)}
.od-attn-row.od-info .od-attn-n{color:var(--mute)}

/* ---------- number tiles ---------- */
.od-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));gap:10px}
.od-tile{border:1px solid var(--line2);border-radius:11px;background:var(--panel);
  padding:14px 15px;display:flex;flex-direction:column;gap:4px;min-width:0}
.od-k{font-size:11.5px;color:var(--dim);line-height:1.5}
.od-v{font-family:var(--ui);font-weight:900;font-size:22px;color:var(--white);
  line-height:1.2;overflow-wrap:anywhere}
.od-u{font-size:11px;color:var(--off)}
.od-tile.od-hl{border-color:rgba(217,165,46,.42)}
.od-tile.od-hl .od-v{color:var(--gold-bright)}
.od-tile.od-bad{border-color:rgba(229,84,75,.45)}
.od-tile.od-bad .od-v{color:var(--danger-text)}

/* ---------- action rows (delivery) ---------- */
.od-row{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding:13px 0;
  border-top:1px solid var(--line)}
.od-row:first-of-type{border-top:0}
.od-row-main{flex:1;min-width:200px;display:flex;flex-direction:column;gap:3px}
.od-row-main b{font-size:13.5px;color:var(--bone)}
/* Why a delivery failed. Wraps rather than truncates - a reason cut off at the
   edge of the row is the same as no reason at all. */
.od-row-why{font-size:11.5px;line-height:1.6;max-width:60ch}
.od-row-acts{display:flex;gap:8px;flex-wrap:wrap}

/* ---------- player rows ---------- */
.op-row{display:flex;align-items:center;gap:13px;padding:11px 12px;border-radius:10px;
  border:1px solid transparent;transition:background .18s,border-color .18s}
.op-row:hover{background:rgba(255,255,255,.035);border-color:var(--line2)}
.op-av{width:38px;height:38px;border-radius:9px;object-fit:cover;flex:none;
  border:1px solid var(--line2)}
.op-av-blank{background:var(--elevated)}
.op-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.op-main b{font-size:13.5px;color:var(--bone)}
.op-meta{font-size:12px;color:var(--dim);flex:none}

/* ---------- forms and tables ---------- */
.op-form{max-width:520px}
.op-actions{display:flex;gap:10px;flex-wrap:wrap}
.op-details{margin-top:14px}
.op-details summary{cursor:pointer;font-size:13px;color:var(--mute);padding:6px 0}
.op-details summary:hover{color:var(--bone)}

/* Tables carry SteamIDs and order ids, which do not wrap and must not
   push the page sideways — so the table scrolls inside its own box. */
.op-table{width:100%;border-collapse:collapse;font-size:12.5px;display:block;
  overflow-x:auto;white-space:nowrap}
.op-table th{text-align:start;font-weight:700;color:var(--dim);font-size:11.5px;
  padding:9px 10px;border-bottom:1px solid var(--line2)}
.op-table td{padding:10px;border-bottom:1px solid var(--line);color:var(--mute);
  vertical-align:top}
.op-table tr:last-child td{border-bottom:0}
.op-table a{color:var(--gold-light)}
.op-table a:hover{color:var(--gold-bright)}

/* ===================================================================
   OWNER CONSOLE — sidebar shell and dashboard grid

   From the supplied mockup. A fixed rail on the leading side, a scrolling
   main column, a banner, a KPI strip and a card grid.

   The rail is sticky rather than scrolling with the page because the main
   column is long, and an owner jumping between players, payments and
   delivery should never have to scroll back up to change screen.
   =================================================================== */

.ow-shell{display:grid;grid-template-columns:248px 1fr;min-height:100vh;
  background:var(--ink)}
@media(max-width:1000px){.ow-shell{grid-template-columns:1fr}}

/* ---------- sidebar ---------- */
.ow-side{position:sticky;top:0;align-self:start;height:100vh;overflow-y:auto;
  background:var(--black-deep);border-inline-start:1px solid var(--line);
  padding:18px 14px;display:flex;flex-direction:column;gap:22px}

.ow-brand{display:flex;align-items:center;gap:11px;padding:6px 8px 0}
.ow-brand img{border-radius:8px;flex:none}
.ow-brand span{display:flex;flex-direction:column;line-height:1.3;min-width:0}
.ow-brand b{font-family:var(--disp);font-size:16px;letter-spacing:.02em;color:var(--white)}
.ow-brand em{font-style:normal;font-size:11px;color:var(--dim)}

.ow-nav{display:flex;flex-direction:column;gap:14px}
.ow-nav-g{display:flex;flex-direction:column;gap:3px;padding-top:14px;
  border-top:1px solid var(--line)}
.ow-nav-g:first-child{border-top:0;padding-top:0}
.ow-nav-i{display:flex;align-items:center;gap:11px;padding:9px 11px;border-radius:9px;
  font-size:13px;font-weight:500;color:var(--dim);
  border:1px solid transparent;transition:background .16s,color .16s,border-color .16s}
.ow-nav-i .ico{font-size:16px;flex:none}
.ow-nav-i:hover{background:rgba(255,255,255,.04);color:var(--bone)}
.ow-nav-i.on{color:var(--white);border-color:var(--gold-dark);
  background:linear-gradient(180deg,rgba(217,165,46,.16),rgba(217,165,46,.04))}
.ow-nav-i.on .ico{color:var(--gold-bright)}

/* ---------- main column ---------- */
.ow-main{min-width:0;padding:22px 24px 64px;display:flex;flex-direction:column;gap:18px}

.ow-hero{position:relative;border-radius:16px;overflow:hidden;
  border:1px solid var(--line2);min-height:150px;display:flex;align-items:center}
.ow-hero-bg{position:absolute;inset:0}
.ow-hero-bg img{width:100%;height:100%;object-fit:cover;object-position:center 35%}
.ow-hero-bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to left,rgba(5,5,5,.35),rgba(5,5,5,.85) 70%,var(--ink))}
.ow-hero-in{position:relative;z-index:2;display:flex;align-items:center;
  justify-content:space-between;gap:var(--s3);flex-wrap:wrap;padding:24px;width:100%}
.ow-hero h1{font-family:var(--ui);font-weight:900;font-size:clamp(21px,2.6vw,29px);
  line-height:1.25;margin:0 0 7px}
.ow-hero p{color:var(--mute);font-size:13px;font-weight:300;margin:0;max-width:56ch;line-height:1.8}
.ow-hero-card{flex:none;border:1px solid var(--line2);border-radius:11px;
  background:rgba(8,8,8,.72);backdrop-filter:blur(6px);padding:12px 15px;
  display:flex;flex-direction:column;gap:7px;font-size:12.5px;color:var(--mute)}
.ow-hero-ok{display:flex;align-items:center;gap:8px}

/* ---------- kpi strip ---------- */
.ow-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(158px,1fr));gap:10px}
.ow-kpi{border:1px solid var(--line2);border-radius:13px;background:var(--panel);
  padding:15px;display:flex;flex-direction:column;gap:6px;min-width:0}
.ow-kpi-i{width:32px;height:32px;border-radius:9px;display:grid;place-items:center;
  background:var(--elevated);color:var(--mute);font-size:15px;margin-bottom:2px}
.ow-kpi-k{font-size:11.5px;color:var(--dim);line-height:1.5}
.ow-kpi-v{font-family:var(--ui);font-weight:900;font-size:21px;color:var(--white);
  line-height:1.2;overflow-wrap:anywhere}
.ow-kpi-hl{border-color:rgba(217,165,46,.42)}
.ow-kpi-hl .ow-kpi-i{background:rgba(217,165,46,.16);color:var(--gold-bright)}
.ow-kpi-hl .ow-kpi-v{color:var(--gold-bright)}

/* ---------- card grid ---------- */
.ow-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(330px,1fr));gap:14px;
  align-items:start}
.ow-card{border:1px solid var(--line);border-radius:14px;background:var(--panel);
  padding:18px;min-width:0}
.ow-card-wide{grid-column:1 / -1}
.ow-card-h{display:flex;align-items:center;justify-content:space-between;gap:12px;
  flex-wrap:wrap;margin-bottom:14px}
.ow-card-h h2{font-family:var(--ui);font-weight:800;font-size:15px;margin:0;color:var(--bone)}

.ow-big{font-family:var(--ui);font-weight:900;font-size:26px;color:var(--white);
  margin:0 0 16px;line-height:1.2}
.ow-big em{font-style:normal;font-size:13px;font-weight:400;color:var(--dim)}

/* Bars are a flex row of columns; the height is a percentage of the week's
   peak, written inline because it is data, not style. */
.ow-bars{display:flex;align-items:flex-end;gap:8px;height:132px}
.ow-bar{flex:1;min-width:0;display:flex;flex-direction:column;
  align-items:center;justify-content:flex-end;gap:7px;height:100%}
.ow-bar i{display:block;width:100%;border-radius:5px 5px 0 0;
  background:linear-gradient(180deg,var(--gold-bright),var(--gold-dark));
  transition:filter .18s}
.ow-bar:hover i{filter:brightness(1.25)}
.ow-bar span{font-size:10.5px;color:var(--off);flex:none}

.ow-srv{display:flex;align-items:center;gap:12px;padding:11px 0;
  border-top:1px solid var(--line)}
.ow-srv:first-of-type{border-top:0}
.ow-srv-b{flex:none;font-family:var(--disp);font-size:13px;color:var(--gold-bright);
  background:rgba(217,165,46,.13);border-radius:7px;padding:5px 9px}
.ow-srv-m{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.ow-srv-m b{font-size:13px;color:var(--bone)}
.ow-srv-m span{font-size:11px}
.ow-srv-p{flex:none;display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--mute)}

.ow-quick{display:grid;grid-template-columns:1fr 1fr;gap:7px}
.ow-quick a{display:flex;align-items:center;gap:10px;padding:11px 12px;border-radius:10px;
  font-size:12.5px;color:var(--mute);border:1px solid var(--line2);
  background:var(--panel2);transition:background .16s,color .16s,border-color .16s}
.ow-quick a:hover{background:var(--card-hover);color:var(--bone);border-color:var(--mute)}
.ow-quick .ico{font-size:15px;flex:none;color:var(--gold)}

.ow-act{display:flex;align-items:flex-start;gap:11px;padding:10px 0;
  border-top:1px solid var(--line)}
.ow-act:first-of-type{border-top:0}
.ow-act-i{flex:none;width:30px;height:30px;border-radius:8px;display:grid;
  place-items:center;font-size:14px;background:var(--elevated);color:var(--mute)}
.ow-act-pay .ow-act-i{color:var(--live)}
.ow-act-case .ow-act-i{color:var(--gold-bright)}
.ow-act-t{flex:1;min-width:0;font-size:12.5px;color:var(--mute);line-height:1.7;
  overflow-wrap:anywhere}
.ow-act-w{flex:none;font-size:10.5px;color:var(--off)}

/* ---------- narrow screens ----------
   AFTER the rules they override, not before: .ow-side and .ow-nav-g set
   flex-direction and border at the same specificity, so a media query placed
   above them loses the cascade and the mobile layout silently never applies. */
@media(max-width:1000px){
  /* A 248px rail on a phone leaves no room for a table, so it becomes a
     horizontal strip above the content. */
  .ow-side{position:static;height:auto;flex-direction:row;align-items:center;
    gap:14px;overflow-x:auto;border-inline-start:0;border-bottom:1px solid var(--line)}
  .ow-nav{flex-direction:row;gap:6px}
  .ow-nav-g{flex-direction:row;gap:6px;border-top:0;padding-top:0}
  .ow-nav-i{flex:none;white-space:nowrap}
  .ow-brand em{display:none}
}
@media(min-width:1200px){.ow-card-wide{grid-column:span 2}}
@media(max-width:600px){.ow-main{padding:16px 14px 48px}}
@media(max-width:520px){.ow-quick{grid-template-columns:1fr}}

/* Taller bars for the 24-hour activity chart: 24 columns need more height
   than 7 to stay readable at the same width. */
.ow-bars-tall{height:184px;gap:4px}
.ow-bars-tall .ow-bar span{font-size:9.5px}

/* Per-staff section grants on the staff screen. */
.os-sections{margin:0 0 var(--s3);padding:14px 16px;border:1px solid var(--line2);
  border-radius:12px;background:var(--panel2)}
.os-sec-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
  gap:9px;margin-bottom:14px}
.os-sections .owner-check{font-size:12.5px}

/* ---------- whitelist queue (owner) ----------
   One application per row: who, what they wrote, and the two decisions. The
   reason is the widest thing on the row because it is the only thing an owner
   actually reads before deciding. */
.owl-row{display:grid;gap:10px;padding:14px 0;border-bottom:1px solid var(--line)}
.owl-row:last-of-type{border-bottom:0}
.owl-who{display:flex;flex-direction:column;gap:3px}
.owl-who b{font-size:15px}
.owl-reason{margin:0;padding:10px 12px;border-radius:10px;line-height:1.9;
  white-space:pre-line;border:1px solid var(--line);background:var(--panel2)}
.owl-self{margin:0;color:var(--dim);font-size:12px}
.owl-acts{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-start}
.owl-reject{display:flex;gap:8px;flex:1 1 320px}
.owl-reject .owner-input{flex:1 1 auto;min-width:0}

/* ---------- whitelist status card (player) ---------- */
.wl-state{display:grid;gap:14px;padding:18px;border-radius:14px;
  border:1px solid var(--line);background:var(--panel2)}
.wl-state h3{margin:0;font-size:18px}
.wl-state p{margin:0;line-height:2}
.wl-days{font-size:34px;line-height:1;color:var(--gold)}
.wl-page{display:grid;gap:18px;max-width:820px;margin-inline:auto}
.wl-form{display:grid;gap:14px}
.wl-two{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.wl-why{margin:0;color:var(--dim);font-size:12.5px;line-height:1.9}

/* AFTER the rules above, never before: a media query placed over the rules it
   overrides loses the cascade and the mobile layout silently never applies. */
@media(max-width:720px){
  .owl-reject{flex:1 1 100%}
  .wl-two{grid-template-columns:1fr}
}

/* ---------- map polls (owner) ----------
   One row per candidate: thumbnail, name, a share bar, the count, and the
   remove button. The bar is the point — an owner wants to see the gap. */
.om-two{display:grid;grid-template-columns:1fr 1fr;gap:var(--s2)}
.om-row{display:flex;align-items:center;gap:14px;padding:12px 0;
  border-bottom:1px solid var(--line)}
.om-row:last-of-type{border-bottom:0}
.om-thumb{width:84px;height:84px;flex:none;object-fit:cover;border-radius:10px;
  border:1px solid var(--line);background:var(--panel2)}
.om-thumb-none{display:grid;place-items:center;color:var(--dim)}
.om-thumb-none .ico{width:26px;height:26px}
.om-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:5px}
.om-main b{font-size:14.5px}
.om-bar{height:6px;border-radius:10px;overflow:hidden;background:rgba(255,255,255,.06)}
.om-bar>span{display:block;height:100%;background:var(--gold);border-radius:10px}
.om-score{flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:3px;min-width:74px}
.om-score b{font-size:19px;line-height:1;color:var(--gold)}

/* ---------- map vote (player) ---------- */
.mv-total{margin:0 0 var(--s3);color:var(--dim);font-size:13px}
.mv-total b{color:var(--gold);font-size:16px}
.mv-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(310px,1fr));
  gap:var(--s3);margin-bottom:var(--s5,48px)}
.mv-card{display:flex;flex-direction:column;gap:12px;padding:16px;border-radius:16px;
  border:1px solid var(--line);background:var(--panel2)}
.mv-card.on{border-color:var(--gold)}
.mv-card.mine{border-color:var(--gold);box-shadow:0 0 0 1px var(--gold) inset}
.mv-shot{position:relative;border-radius:12px;overflow:hidden;background:var(--panel);
  aspect-ratio:1/1}
.mv-shot img{width:100%;height:100%;object-fit:cover;display:block}
.mv-shot-none{position:absolute;inset:0;display:grid;place-items:center;color:var(--dim)}
.mv-shot-none .ico{width:40px;height:40px}
.mv-count{position:absolute;top:10px;inset-inline-end:10px;padding:5px 11px;border-radius:50px;
  background:rgba(0,0,0,.72);border:1px solid var(--gold);font-size:10.5px;color:#fff}
.mv-count b{color:var(--gold);font-size:13.5px;margin-inline-end:4px}
.mv-badge{position:absolute;top:10px;inset-inline-start:10px;padding:4px 10px;border-radius:50px;
  background:var(--gold);color:#050505;font-size:10.5px;font-weight:700}
.mv-name{margin:0;font-size:16px}
.mv-share{display:flex;justify-content:space-between;font-size:11px;color:var(--dim)}
.mv-bar{height:6px;border-radius:10px;overflow:hidden;background:rgba(255,255,255,.06)}
.mv-bar>span{display:block;height:100%;background:var(--gold);border-radius:10px}
.mv-mon{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:1fr 1fr;gap:3px 10px;
  font-size:10.5px}
.mv-mon li{display:flex;align-items:center;gap:6px}
.mv-mon li.no{opacity:.35}
.mv-mon li.yes span:first-child{color:var(--live,#5dc922)}
.mv-mon li.no span:first-child{color:var(--danger,#e5544b)}
.mv-meta{display:flex;gap:14px;margin:0;font-size:11.5px;color:var(--dim)}
.mv-yours{margin:0;padding:9px 12px;border-radius:10px;text-align:center;font-size:12.5px;
  color:var(--gold);border:1px dashed var(--gold)}

/* AFTER the rules above, never before: a media query placed over the rules it
   overrides loses the cascade and the mobile layout silently never applies. */
@media(max-width:720px){
  .om-two{grid-template-columns:1fr}
  .om-row{flex-wrap:wrap}
  .om-main{flex:1 1 100%;order:3}
  .mv-grid{grid-template-columns:1fr}
}

/* =========================================================================
   SIGN-IN
   Built to the supplied mockup: a full-bleed photo, a centred crest, and three
   method cards each carrying its own service's accent.

   The page's own chrome stays in the site's gold/black system; the blue,
   blurple and green belong to Steam, Discord and the game and are used only on
   their own cards, which is what makes them readable as service marks rather
   than as decoration.
   ========================================================================= */
.auth-body{min-height:100dvh;display:flex;flex-direction:column;
  background:var(--black-deep,#070709)}

/* The art. Two layers on purpose: login-background.png is the intended piece,
   and the .jpg under it is what shows if that file has not been uploaded yet —
   a missing layer simply does not paint, so the page is never a black void. */
.auth-bg{position:fixed;inset:0;z-index:0;pointer-events:none;
  background-image:url('/assets/banner/login-background.png'),
                   url('/assets/banner/iranrustbackground.jpg');
  background-size:cover,cover;background-position:center,center}
/* Two scrims, because one cannot do both jobs. The linear one holds the type
   at the top of the page; the radial one sinks the edges so the cards sit on a
   quiet ground. Tuned against the darkest art we ship, so a brighter
   login-background.png still reads. */
.auth-bg::after{content:'';position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(6,6,8,.86) 0%,rgba(6,6,8,.6) 26%,rgba(6,6,8,.72) 60%,rgba(6,6,8,.93) 100%),
             radial-gradient(115% 85% at 50% 8%,transparent 0%,rgba(6,6,8,.5) 62%,rgba(6,6,8,.9) 100%)}

.auth-bar,.auth-main,.auth-foot{position:relative;z-index:1}

.auth-bar{display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:18px clamp(16px,4vw,44px)}
.auth-brand{display:flex;align-items:center;gap:10px;text-decoration:none;color:var(--bone,#eee)}
.auth-brand span{font-weight:800;letter-spacing:.14em;font-size:13px}
.auth-bar-tag{font-size:11px;letter-spacing:.22em;color:var(--dim);text-transform:uppercase}

.auth-main{flex:1 1 auto;width:100%;max-width:1180px;margin-inline:auto;
  padding:clamp(10px,2.4vh,26px) clamp(16px,4vw,44px) clamp(20px,4vh,38px);text-align:center}
.auth-main-narrow{max-width:640px}

.auth-crest{display:flex;flex-direction:column;align-items:center;gap:5px;
  margin-bottom:clamp(10px,2.2vh,20px)}
.auth-crown{width:34px;height:34px;color:var(--gold)}
.auth-word{margin:0;font-size:clamp(28px,5vw,46px);font-weight:900;letter-spacing:.06em;
  line-height:1;color:#fff;text-shadow:0 2px 24px rgba(0,0,0,.6)}
.auth-tag{display:flex;gap:16px;margin:2px 0 0;font-size:11px;letter-spacing:.2em;color:var(--mute)}
.auth-tag span+span{position:relative}
.auth-tag span+span::before{content:'•';position:absolute;inset-inline-end:calc(100% + 8px);color:var(--gold)}

.auth-h1{margin:0;font-size:clamp(24px,4vw,38px);font-weight:800;color:#fff;text-wrap:balance}
.auth-sub{margin:8px 0 0;color:var(--mute);font-size:14.5px}
.auth-notice{max-width:620px;margin:18px auto 0;text-align:start}

.auth-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(268px,1fr));
  gap:clamp(14px,2vw,22px);margin:clamp(16px,3vh,28px) auto 0;max-width:1080px}

/* Each card owns --a, its service's accent. Everything tinted below reads from
   it, so a new method is one class and one colour rather than a block of rules. */
.auth-card{--a:var(--gold);
  display:flex;flex-direction:column;gap:9px;padding:12px 12px 15px;
  border-radius:18px;border:1px solid color-mix(in srgb,var(--a) 42%,transparent);
  background:linear-gradient(180deg,rgba(18,20,26,.86),rgba(10,11,14,.94));
  box-shadow:0 0 0 1px rgba(255,255,255,.03) inset,0 18px 46px rgba(0,0,0,.5);
  backdrop-filter:blur(6px);text-align:center;
  transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease}
.auth-card:hover{transform:translateY(-3px);border-color:var(--a);
  box-shadow:0 0 0 1px rgba(255,255,255,.05) inset,0 22px 54px rgba(0,0,0,.6),
             0 0 32px color-mix(in srgb,var(--a) 26%,transparent)}
/* Each service's own colour, not an approximation of it: Steam's light blue
   from its client chrome, Discord's blurple, and a green for the game that is
   bright enough to survive being mixed down to 22% behind the button label. */
.auth-steam{--a:#66c0f4}
.auth-discord{--a:#5865f2}
.auth-ingame{--a:#3ddc84}

/* TWO ELEMENTS, AND THE SPLIT IS THE WHOLE POINT. Rounding the photo's corners
   needs overflow:hidden, and overflow:hidden clips ANY descendant — so while
   the badge lived in here, the half of it that hangs below the photo was cut
   off. .auth-shot does the clipping; .auth-art clips nothing and is only the
   positioning context the badge hangs from. */
.auth-art{position:relative;margin-bottom:36px}
.auth-shot{display:block;position:relative;border-radius:13px;overflow:hidden;
  aspect-ratio:16/10;background:#0c0d11}
.auth-shot img{width:100%;height:100%;object-fit:cover;display:block}
/* Only the bottom third is darkened — enough for the badge to sit on something
   solid, without turning the photograph into a black rectangle. */
.auth-shot::after{content:'';position:absolute;inset:0;
  background:linear-gradient(180deg,transparent 52%,rgba(10,11,14,.9) 100%)}

.auth-icon{position:absolute;z-index:3;left:50%;bottom:-28px;transform:translateX(-50%);
  width:62px;height:62px;border-radius:50%;display:grid;place-items:center;
  background:radial-gradient(circle at 50% 34%,#fff 0%,#e9edf3 100%);
  /* A ring in the service's colour and a glow beneath it, so the badge reads as
     lifted off the photo rather than pasted onto it. */
  box-shadow:0 0 0 3px color-mix(in srgb,var(--a) 34%,transparent),
             0 0 22px color-mix(in srgb,var(--a) 40%,transparent),
             0 10px 26px rgba(0,0,0,.6)}
/* The glyph takes the brand hue, darkened enough to hold contrast on white. */
.auth-icon .ico{width:30px;height:30px;color:color-mix(in srgb,var(--a) 62%,#0a0d12)}
.auth-card:hover .auth-icon{box-shadow:0 0 0 3px color-mix(in srgb,var(--a) 60%,transparent),
             0 0 30px color-mix(in srgb,var(--a) 55%,transparent),
             0 10px 26px rgba(0,0,0,.6)}

.auth-eyebrow{margin:4px 0 0;font-size:10.5px;letter-spacing:.2em;color:var(--dim)}
.auth-name{margin:0;font-size:23px;font-weight:800;color:#fff;letter-spacing:.02em}
/* RENAMED FROM .auth-body, WHICH IS ALSO THE <body> CLASS ON layouts/auth.
   Two unrelated things shared the name and this rule is the later one, so it
   won: the sign-in page's <body> was getting min-height:44px instead of
   100dvh, a 12.5px font-size and a 2px/6px margin. The footer stopped being
   pushed to the bottom of the screen and sat in the middle of a black band.
   The page shell keeps .auth-body; this is the card's description text. */
.auth-card-body{margin:2px 0 6px;font-size:12.5px;line-height:2;color:var(--mute);min-height:44px}

.auth-go{display:flex;align-items:center;justify-content:center;gap:8px;
  padding:12px 14px;border-radius:11px;text-decoration:none;font-size:14px;font-weight:700;
  color:#fff;border:1px solid color-mix(in srgb,var(--a) 60%,transparent);
  background:color-mix(in srgb,var(--a) 22%,transparent);
  transition:background .16s ease,border-color .16s ease}
.auth-go:hover{background:color-mix(in srgb,var(--a) 40%,transparent);border-color:var(--a)}
.auth-go .ico{width:17px;height:17px}

.auth-chips{list-style:none;display:flex;justify-content:center;gap:14px;
  margin:2px 0 0;padding:0;font-size:10.5px;color:var(--dim)}
.auth-chips li+li{position:relative}
.auth-chips li+li::before{content:'•';position:absolute;inset-inline-end:calc(100% + 6px)}

.auth-or{display:flex;align-items:center;gap:16px;max-width:520px;margin:clamp(16px,3vh,28px) auto 0;
  color:var(--dim);font-size:11px;letter-spacing:.2em}
.auth-or::before,.auth-or::after{content:'';flex:1 1 auto;height:1px;background:var(--line)}

.auth-help{margin:14px 0 0;font-size:12.5px;color:var(--mute)}
.auth-help a{color:var(--gold)}

/* The in-game instructions. */
.auth-steps{display:grid;gap:10px;margin:24px auto 0;max-width:520px;text-align:start}
.auth-step{display:flex;align-items:flex-start;gap:12px;padding:13px 15px;border-radius:13px;
  border:1px solid var(--line);background:rgba(14,15,19,.8)}
.auth-step b{flex:none;width:26px;height:26px;border-radius:50%;display:grid;place-items:center;
  font-size:13px;color:#050505;background:var(--gold)}
.auth-step p{margin:0;font-size:13px;line-height:1.95;color:var(--mute)}
.auth-step code{padding:1px 7px;border-radius:6px;background:rgba(255,255,255,.07);color:var(--gold)}

.auth-foot{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;
  padding:16px clamp(16px,4vw,44px);border-top:1px solid rgba(255,255,255,.06);
  font-size:11.5px;color:var(--dim)}
.auth-foot-links{display:flex;gap:18px}
.auth-foot-links a{color:var(--dim);text-decoration:none}
.auth-foot-links a:hover{color:var(--gold)}

/* AFTER the rules above, never before: a media query placed over the rules it
   overrides loses the cascade and the mobile layout silently never applies. */
@media(max-width:860px){
  .auth-cards{grid-template-columns:1fr;max-width:420px}
  .auth-card-body{min-height:0}
  .auth-bar-tag{display:none}
}

/* ---------- audit trail (owner) ----------
   Severity is a LEFT EDGE, not a background wash: the rows still read as one
   list, and the eye can still run down the margin looking for money and access.
   Gold is this site's "look here", so the high band gets it. */
.osec-counts{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
  gap:9px;margin-top:var(--s3)}
.osec-count{display:flex;flex-direction:column;gap:2px;padding:11px 13px;border-radius:11px;
  text-decoration:none;border:1px solid var(--line);background:var(--panel2);
  border-inline-start:3px solid var(--line)}
.osec-count b{font-size:18px;line-height:1;color:var(--bone,#eee)}
.osec-count span{font-size:11.5px;color:var(--dim)}
.osec-count:hover{border-color:var(--gold)}

.osec-row{display:flex;align-items:flex-start;gap:14px;padding:12px 0 12px 0;
  border-bottom:1px solid var(--line);border-inline-start:3px solid transparent;
  padding-inline-start:11px}
.osec-row:last-of-type{border-bottom:0}
.osec-when{flex:none;width:96px;display:flex;flex-direction:column;gap:2px;font-size:11.5px}
.osec-what{flex:1 1 auto;min-width:0}
.osec-line{margin:0;font-size:13.5px;line-height:1.9;display:flex;flex-wrap:wrap;
  align-items:center;gap:7px}
.osec-act{color:var(--gold)}
.osec-meta{list-style:none;display:flex;flex-wrap:wrap;gap:4px 14px;margin:5px 0 0;padding:0;
  font-size:11.5px}
.osec-meta li{display:flex;align-items:baseline;gap:5px}
.osec-meta b{font-weight:600;color:var(--mute)}
.osec-ip{flex:none;font-size:11px;padding-top:3px}

.sev-high{border-inline-start-color:var(--gold)}
.sev-normal{border-inline-start-color:var(--line2,#2a2a2a)}
.sev-low{border-inline-start-color:transparent}

/* AFTER the rules above, never before: a media query placed over the rules it
   overrides loses the cascade and the mobile layout silently never applies. */
@media(max-width:720px){
  .osec-row{flex-wrap:wrap}
  .osec-when{width:auto;flex-direction:row;gap:8px}
  .osec-ip{order:4}
}

/* ---------- shop: two ways to pay ----------
   Stacked, not side by side: the card is already narrow and two half-width
   buttons would each be too small to read a price in. */
.sh-pay{display:flex;flex-direction:column;gap:7px}
.sh-pay .sh-buy{margin:0}
.sh-note{display:block;text-align:center;font-size:11px;color:var(--dim)}

/* ---------- shop: term picker, two pay buttons, fine print ----------
   Stacked, not side by side: the card is already narrow and two half-width
   buttons would each be too small to read a price in. */
.sh-pay{display:flex;flex-direction:column;gap:7px}
.sh-note{display:block;text-align:center;font-size:11px;color:var(--dim)}
.sh-fine{margin:0 0 2px;font-size:11px;line-height:1.8;color:var(--dim);min-height:32px}
.sh-term{display:block}
.sh-term-sel{width:100%;padding:9px 11px;border-radius:9px;font:inherit;font-size:12.5px;
  color:var(--bone,#eee);background:var(--panel2);border:1px solid var(--line);
  appearance:none;text-align:center}
.sh-term-sel:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ==========================================================================
   PLAYER STORY - the written summary at the top of a profile
   ==========================================================================
   Appended at the end of the file ON PURPOSE. Several rules here override
   earlier profile rules, and in this stylesheet later wins at equal
   specificity - putting them above would have made them silently dead, which
   has already happened three times on this project.
*/

.pf-story{position:relative;margin:0 0 var(--s2);padding:26px 26px 22px;
  border:1px solid var(--line2);border-radius:16px;overflow:hidden;
  background:
    radial-gradient(120% 140% at 100% 0%,rgba(217,165,46,.10),transparent 55%),
    linear-gradient(180deg,rgba(255,255,255,.035),rgba(255,255,255,.012));
}
/* One gold edge, not a gold panel. The accent is the frame, the words are the
   content - the other way round is how the whole site went yellow before. */
.pf-story::before{content:"";position:absolute;inset-inline-start:0;top:0;bottom:0;width:3px;
  background:linear-gradient(180deg,var(--gold),transparent)}

.pf-story-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:16px}
.pf-story-kicker{font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--dim)}
.pf-story-title{font-family:var(--disp);font-size:clamp(26px,4.4vw,42px);line-height:1.05;
  margin:0;color:var(--bone);text-wrap:balance}

.pf-story-body{max-width:66ch}
.pf-story-line{margin:0 0 10px;font-size:14.5px;line-height:2.05;color:var(--mute)}
.pf-story-line:last-child{margin-bottom:0}
/* The figures are the payload; everything around them is scaffolding. */
.pf-story-line b{color:var(--bone);font-weight:800}
/* The opening sentence carries the claim, so it gets the weight. */
.pf-story-line:first-child{font-size:16.5px;color:var(--bone)}
.pf-story-line:first-child b{color:var(--gold)}

.pf-story-facts{display:flex;flex-wrap:wrap;gap:10px;margin-top:20px;
  padding-top:18px;border-top:1px solid var(--line)}
.pf-fact{display:flex;align-items:baseline;gap:8px;padding:9px 14px;border-radius:99px;
  background:rgba(255,255,255,.04);border:1px solid var(--line2)}
.pf-fact b{font-family:var(--disp);font-size:17px;line-height:1;color:var(--bone)}
.pf-fact span{font-size:10.5px;letter-spacing:.08em;color:var(--dim)}

/* Lines arrive one after another, left to right in reading order. They start
   VISIBLE and animate from a visible resting state, so a screenshot, a
   printout or a browser that skips the animation still shows the whole
   summary. */
@media(prefers-reduced-motion:no-preference){
  .pf-story-line,.pf-fact{animation:pf-rise .5s cubic-bezier(.2,.7,.3,1) both;
    animation-delay:calc(var(--i,0) * 70ms + 60ms)}
  .pf-story-title{animation:pf-rise .55s cubic-bezier(.2,.7,.3,1) both}
}
@keyframes pf-rise{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:none}}

/* An axis nobody on the server scores on: shown, but visibly not a number. */
.pf-radar-k span.off{opacity:.45}
.pf-radar-k span.off i{font-style:normal;color:var(--dim);font-weight:600}

/* Two wipes in a full-width chart left most of the card empty. Bars now keep a
   readable width and sit at the start of the rail instead of stretching to
   fill it. */
.pf-bars{justify-content:flex-start}
.pf-bar-col{flex:0 0 auto;width:clamp(46px,9vw,78px)}

/* The six KPI numbers must share one baseline.

   Centring each cell did NOT achieve that: the rank cell carries an extra
   "top N%" line, so centring pushed its number 41px above the other five and
   the strip read as misaligned. Stacking from the TOP instead means the
   caption row and the number row start at the same y in every cell, and the
   extra line simply hangs below where it belongs. */
.pf-kpi{display:grid;grid-template-rows:auto auto 1fr;justify-items:center;
  align-content:start;gap:6px}
.pf-kpi span,.pf-kpi small{margin:0}

@media(max-width:680px){
  .pf-story{padding:20px 18px 18px}
  .pf-story-line{font-size:13.5px;line-height:1.95}
  .pf-story-line:first-child{font-size:15px}
}

/* ==========================================================================
   PROFILE CARDS: MASONRY, NOT A GRID  (opt in with .pf-grid-flow)
   ==========================================================================
   OPT-IN, because .pf-grid is SHARED. The clan page uses the same class with
   four cards of near-equal height, and columns balanced those into two of the
   three tracks and left the third empty - reintroducing on that page exactly
   the hole this was written to remove from the profile. Masonry earns its keep
   where card heights vary a lot (the profile runs 198px to 568px); a plain
   grid is better where they do not.

   Measured on a real profile at 1440px, the three-column grid left 390px of
   dead space and, in the last row, a 406px-wide empty column beside the
   achievements card. That was most of what "the layout is a mess" pointed at.

   A grid cannot fix it, and the reason is rows. Every card in a row is pinned
   to that row's top edge, so a 366px card beside a 240px card leaves 126px of
   nothing, and `grid-auto-flow: dense` only backfills sideways - it can never
   pull a later card UP into that space. Stretching cards to equal heights
   would only hide the gaps inside padded boxes rather than remove them, and
   would not have touched the empty column at all.

   CSS columns have no rows, so there is nothing to leave a hole in. Cards flow
   down one column and continue at the top of the next, each taking exactly the
   height it needs.

   THE COST, STATED PLAINLY: reading order becomes column-major - down the
   first column, then down the second - rather than left-to-right. These are
   independent panels people scan, not prose read in sequence, so that is the
   right trade here. It would be the wrong one for an article.

   `break-inside: avoid` keeps a card whole. The `inline-block` + `width:100%`
   pair is not decoration: without it WebKit still splits cards across a column
   boundary despite break-inside.
*/
.pf-grid-flow{
  display:block;
  column-count:3;
  column-gap:var(--s2);
}
.pf-grid-flow>.card{
  break-inside:avoid;
  -webkit-column-break-inside:avoid;
  page-break-inside:avoid;
  display:inline-block;
  width:100%;
  margin:0 0 var(--s2);
  vertical-align:top;
}
/* Spanning is a grid idea and silently does nothing here. Neutralised so the
   class stays harmless wherever the Blade still sets it. */
.pf-grid-flow>.card-wide{width:100%}

@media(max-width:1000px){.pf-grid-flow{column-count:2}}
@media(max-width:680px){.pf-grid-flow{column-count:1}}

/* The category card's own two-up grid suited a full-width row, not a column. */
.pf-grid-flow .pf-cats{grid-template-columns:minmax(0,1fr)}

/* The favourite weapon, called out above the per-weapon bars.
   It is the one line in the card that is a CLAIM rather than a number, so it
   gets the gold; the bars underneath stay quiet and let it lead. */
.pf-signature{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  margin:0 0 14px;padding:11px 13px;border-radius:10px;
  background:rgba(217,165,46,.08);border:1px solid rgba(217,165,46,.22)}
.pf-signature span{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim)}
.pf-signature b{font-size:15px;font-weight:800;color:var(--gold);text-align:end}

/* ==========================================================================
   PROFILE STAT BAR - two fixes
   ==========================================================================

   1. THE RANK CELL WAS BREAKING INTO FOUR LINES.

   The base rule `.pf-kpi span{display:block}` was written for the caption
   above each number. But the rank cell's sub-line is

       <small>بالاترین <span class="num">3.1٪</span> از <span class="num">32</span></small>

   and those nested `.num` spans are spans too, so they became blocks and
   stacked. Measured: the <small> collapsed to 29px wide and rendered on four
   lines while every neighbour was single-line, which is what made the whole
   strip look broken.

   Scoping the rule to the DIRECT child fixes it without touching the caption.

   2. THE STRIP LOOKED LIKE IT WAS FLOATING.

   `.pf-bar` and `.pf-kpi` are both #0d0d0d, so the only thing marking the
   strip's edges was where its 1px separators stopped - at 1200px inside a
   1736px band. It read as content adrift in an empty bar. A border and a
   radius make it a deliberate object instead of an accident.
*/
.pf-kpi>span{display:block}
.pf-kpi small span{display:inline}
.pf-kpi small{line-height:1.7}

.pf-kpis{border:1px solid var(--line2);border-radius:14px;overflow:hidden}

/* ==========================================================================
   THE STANDING CURVE - the whole server, and where this player sits in it
   ==========================================================================
   A rank is a number people read. A distribution is a picture people feel -
   and this one is honest: every bar is a real count of real players.
*/
.pf-curve-band{border-block:1px solid var(--line);
  background:linear-gradient(180deg,rgba(255,255,255,.02),transparent);
  padding:26px 0 22px}

.pf-curve-head{display:flex;align-items:flex-end;justify-content:space-between;
  gap:18px;flex-wrap:wrap;margin-bottom:18px}
.pf-curve-kicker{margin:0 0 6px;font-size:9.5px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--dim)}
.pf-curve-title{margin:0;font-family:var(--disp);font-size:clamp(20px,2.6vw,30px);
  line-height:1.15;color:var(--bone)}
.pf-curve-title b{color:var(--gold)}
.pf-curve-sub{margin:0;max-width:46ch;font-size:11.5px;line-height:1.9;color:var(--dim)}
.pf-curve-sub b{color:var(--mute)}

.pf-curve{display:flex;align-items:flex-end;gap:3px;height:124px;
  /* The flag is ~24px tall and floats 8px clear of a full-height bar, so it
     needs 32px of headroom. At 26px it overhung the chart and collided with
     the heading above. Height grows with the padding so the bars keep their
     86px of drawing room. */
  padding-top:38px}
.pf-curve-col{position:relative;flex:1 1 0;min-width:0;height:100%;
  display:flex;align-items:flex-end}
.pf-curve-col i{display:block;width:100%;height:var(--h);border-radius:3px 3px 0 0;
  background:linear-gradient(180deg,#3a3a3a,#242424);
  transform-origin:bottom;transition:background .18s}
.pf-curve-col:hover i{background:linear-gradient(180deg,#4d4d4d,#2e2e2e)}

/* The one bar that is this player. Gold, and glowing - the only place on the
   whole band where the accent gets spent. */
.pf-curve-col.mine i{background:linear-gradient(180deg,var(--gold),#8A641B);
  box-shadow:0 0 18px rgba(217,165,46,.45)}

.pf-curve-you{position:absolute;bottom:calc(var(--h) + 8px);inset-inline-start:50%;
  transform:translateX(50%);white-space:nowrap;font-size:10px;font-weight:800;
  letter-spacing:.06em;color:#0d0d0d;background:var(--gold);
  padding:3px 8px;border-radius:99px}
.pf-curve-you::after{content:"";position:absolute;top:100%;inset-inline-start:50%;
  transform:translateX(50%);border:4px solid transparent;border-top-color:var(--gold)}

.pf-curve-axis{display:flex;justify-content:space-between;align-items:center;
  margin-top:10px;font-size:10px;color:var(--dim);letter-spacing:.1em}

/* Bars grow from the floor, left to right, and the flag drops in once they
   have arrived. The animation ENDS at the real height, so a browser that skips
   it still shows the true chart rather than an empty one. */
@media(prefers-reduced-motion:no-preference){
  .pf-curve-col i{animation:pf-grow .5s cubic-bezier(.2,.8,.3,1) both;
    animation-delay:calc(var(--i,0) * 22ms)}
  .pf-curve-you{animation:pf-drop .45s cubic-bezier(.2,.8,.3,1) both;
    animation-delay:calc(var(--i,0) * 22ms + 260ms)}
}
@keyframes pf-grow{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes pf-drop{from{opacity:0;transform:translateX(50%) translateY(-8px)}
  to{opacity:1;transform:translateX(50%)}}

@media(max-width:680px){
  .pf-curve{height:84px;gap:2px}
  .pf-curve-head{margin-bottom:14px}
}

/* ==========================================================================
   HEAT MAP
   ==========================================================================
   The overlay is ONE svg sized in grid units with preserveAspectRatio:none,
   stretched over the image by absolute positioning. That is what keeps every
   cell glued to the same patch of terrain at any width - a pixel-positioned
   overlay would drift the moment the image was scaled, and would need
   JavaScript on every resize to stay honest.
*/
.hm-meta{display:flex;flex-wrap:wrap;gap:8px 20px;align-items:baseline;
  margin:0 0 14px;font-size:12px;color:var(--mute)}
.hm-meta b{color:var(--bone);font-weight:800}
.hm-meta .dim{color:var(--dim)}

/* The layer switch: radios drive it, so it works before any script runs. */
.hm-switch{position:relative}
.hm-switch>input{position:absolute;opacity:0;width:0;height:0}
.hm-switch>label{display:inline-block;margin:0 0 12px 8px;padding:7px 14px;
  border:1px solid var(--line2);border-radius:99px;font-size:12px;font-weight:700;
  color:var(--dim);cursor:pointer;transition:color .15s,border-color .15s,background .15s}
.hm-switch>label:hover{color:var(--bone)}
.hm-switch>input:checked+label{color:#0d0d0d;background:var(--gold);border-color:var(--gold)}
.hm-switch>input:focus-visible+label{outline:2px solid var(--gold);outline-offset:2px}

/* Capped, because the map is SQUARE: at full container width it came out
   1152px tall in a 900px viewport, so the picture alone was taller than the
   screen and everything under it fell off the page. */
.hm-stage{position:relative;width:100%;max-width:min(100%,720px);margin-inline:auto;
  aspect-ratio:1;border-radius:14px;
  overflow:hidden;border:1px solid var(--line2);background:#0b0b0b}
/* THE MAP IS DARKENED, and the overlay depends on it.

   `mix-blend-mode: screen` on the heat layer ADDS light. Over a dark ground
   that reads beautifully; over a bright one it saturates toward white and the
   heat disappears. Checked against a real photograph rather than the striped
   placeholder: gold cells over the light areas were invisible, and a genuine
   RustMaps image is full of bright terrain - snow, desert, beaches.

   Dimming the basemap gives `screen` a consistently dark ground to work
   against everywhere on the map. The terrain stays perfectly readable - you
   can still make out coastline, roads and monuments - it is simply no longer
   competing with the data drawn on top of it. */
.hm-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;
  filter:brightness(.42) saturate(.75) contrast(1.05)}
.hm-noimg{position:absolute;inset:0;display:grid;place-items:center;
  background:repeating-linear-gradient(45deg,#101010,#101010 12px,#0c0c0c 12px,#0c0c0c 24px)}
.hm-noimg span{font-size:12px;color:var(--dim)}

.hm-heat{position:absolute;inset:0;width:100%;height:100%;display:block;
  /* `screen` makes overlapping heat build up like light instead of painting
     flat blocks over the terrain, so the map underneath stays readable. */
  mix-blend-mode:screen;pointer-events:none}
.hm-l-kill rect{fill:#F2C75C}
.hm-l-raid rect{fill:#C7452F}

/* Which layers are drawn. Sibling selectors from the checked radio - the
   groups sit inside .hm-stage, which follows the inputs. */
#hm-kill:checked~.hm-stage .hm-l-raid,
#hm-raid:checked~.hm-stage .hm-l-kill{display:none}

.hm-legend{display:flex;flex-wrap:wrap;gap:8px 18px;align-items:center;
  margin-top:14px;font-size:11.5px;color:var(--mute)}
.hm-key{display:inline-flex;align-items:center;gap:7px}
.hm-key::before{content:"";width:11px;height:11px;border-radius:3px}
.hm-key-kill::before{background:#F2C75C}
.hm-key-raid::before{background:#C7452F}
.hm-legend .dim{color:var(--dim);flex:1 1 22ch;min-width:0}

@media(max-width:680px){
  .hm-meta{gap:6px 14px;font-size:11.5px}
  .hm-switch>label{padding:6px 12px}
}

/* An undelivered purchase, waiting on the dashboard.
   Two lines: what happened, then what was done about it. The bold opener
   carries the fact a player most needs — for a paid order, that their money
   did go through. */
.db-undelivered{display:flex;flex-direction:column;gap:5px;line-height:1.85}
.db-undelivered b:first-child{font-size:13.5px}
.db-undelivered span{font-size:12.5px;opacity:.9}
.db-undelivered .num{font-weight:800}


/* ============================================================================
   LFG — the team-finding board, and the private messages that come out of it

   Accent is GOLD throughout (--gold and friends, declared at the top of this
   file). The design this follows was drawn in red; red on this site already
   means "destructive" on every owner screen, and a board full of it would read
   as a page full of warnings.
   ==========================================================================*/

/* ------------------------------------------ the board, on the home -- */

.home-lfg{display:grid; gap:12px; grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}

.home-lfg-card{
  display:flex; flex-direction:column; gap:8px; min-width:0;
  padding:16px 18px; border-radius:14px; text-decoration:none; color:inherit;
  background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.07);
  transition:background .15s, border-color .15s;
}
.home-lfg-card:hover{background:rgba(255,255,255,.055); border-color:rgba(217,165,46,.4)}
.home-lfg-card.is-lfp{border-inline-start:3px solid var(--gold,#D9A52E)}
.home-lfg-card.is-lft{border-inline-start:3px solid rgba(255,255,255,.22)}

.home-lfg-top{display:flex; align-items:center; gap:8px}
.home-lfg-slots{margin-inline-start:auto; font-size:.74rem; color:var(--muted)}

/* Titles are player-written and vary wildly. Two lines, then clipped, so a
   long one cannot make its card twice the height of the two beside it. */
.home-lfg-title{
  font-size:.95rem; line-height:1.55;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
  overflow:hidden;
}
.home-lfg-who{font-size:.78rem; color:var(--muted)}

.home-lfg-more{margin:18px 0 0; text-align:center}
.home-lfg-more .btn{display:inline-flex; align-items:center; gap:8px}

/* --------------------------------------------- the ad, on a profile -- */

.pf-lfg-wrap{padding:14px 0 0}
.pf-lfg{display:flex; flex-wrap:wrap; gap:10px}

.pf-lfg-card{
  display:flex; align-items:center; gap:12px; flex:1 1 320px; min-width:0;
  padding:12px 16px; border-radius:14px; text-decoration:none; color:inherit;
  background:rgba(217,165,46,.07);
  border:1px solid rgba(217,165,46,.26);
  transition:background .15s, border-color .15s;
}
.pf-lfg-card:hover{background:rgba(217,165,46,.12); border-color:var(--gold,#D9A52E)}
.pf-lfg-card.is-lft{background:rgba(255,255,255,.035); border-color:rgba(255,255,255,.12)}
.pf-lfg-card.is-lft:hover{background:rgba(255,255,255,.06)}

.pf-lfg-txt{display:flex; flex-direction:column; gap:2px; min-width:0; flex:1}
/* The title is the poster's own text and can be any length; it gets one
   line and an ellipsis rather than pushing the button off the card. */
.pf-lfg-txt b{font-size:.92rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.pf-lfg-txt small{font-size:.74rem; color:var(--muted)}
.pf-lfg-txt i{font-style:normal}

.pf-lfg-go{
  flex:none; font-size:.76rem; padding:6px 14px; border-radius:999px;
  background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.10);
}

/* ------------------------------------------------------------------ hero -- */

.lfg-hero{
  position:relative; isolation:isolate;
  padding:64px 0 52px; margin-bottom:26px;
  border-bottom:1px solid rgba(255,255,255,.07);
  text-align:center; overflow:hidden;
}

.lfg-hero-bg{position:absolute; inset:0; z-index:-1}
.lfg-hero-bg img{width:100%; height:100%; object-fit:cover; opacity:.30}

/* The image is a texture, not a picture: without this the type sits on a busy
   photograph and the whole header stops being readable. */
.lfg-hero::after{
  content:''; position:absolute; inset:0; z-index:-1;
  background:linear-gradient(180deg, rgba(8,11,16,.55) 0%, rgba(8,11,16,.92) 100%);
}

.lfg-hero-kicker{
  margin:0 0 6px; font-size:.78rem; letter-spacing:.18em;
  text-transform:uppercase; color:var(--gold-light,#E8C878);
}

.lfg-hero-title{
  margin:0; font-size:clamp(3.2rem, 11vw, 6.5rem); line-height:.92;
  font-weight:900; letter-spacing:.06em; color:#fff;
  text-shadow:0 6px 40px rgba(0,0,0,.6);
}

.lfg-hero-sub{
  margin:12px 0 0; font-size:.95rem; letter-spacing:.02em; color:#dfe3ea;
}

.lfg-hero-script{
  margin:6px 0 0; font-size:1.05rem; color:var(--gold-bright,#F2C75C);
  font-style:italic;
}

/* --------------------------------------------------------------- layout -- */

.lfg-shell{
  display:grid; gap:22px;
  grid-template-columns:minmax(0,1fr) 320px;
  align-items:start;
}

.lfg-main{min-width:0}

.lfg-side{display:flex; flex-direction:column; gap:16px; position:sticky; top:88px}

/* ---------------------------------------------------------- LFT / LFP --- */

.lfg-switch{
  display:grid; gap:12px; margin-bottom:16px;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto;
  align-items:stretch;
}

.lfg-side-card{
  display:flex; align-items:center; gap:12px;
  padding:14px 16px; border-radius:14px; text-decoration:none; color:inherit;
  background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.08);
  transition:border-color .15s, background .15s;
}
.lfg-side-card:hover{background:rgba(255,255,255,.05)}

/* The selected side is the one loud thing on the page. */
.lfg-side-card.on{
  border-color:var(--gold,#D9A52E);
  background:linear-gradient(180deg, rgba(217,165,46,.16), rgba(217,165,46,.06));
}

.lfg-side-ico{
  width:40px; height:40px; flex:none; border-radius:11px;
  display:grid; place-items:center;
  background:rgba(217,165,46,.12); color:var(--gold-bright,#F2C75C);
}
.lfg-side-ico .ico{width:20px; height:20px}

.lfg-side-txt{display:flex; flex-direction:column; gap:2px; min-width:0}
.lfg-side-txt b{font-size:.95rem; display:flex; align-items:center; gap:8px}
.lfg-side-txt b i{
  font-style:normal; font-size:.65rem; letter-spacing:.08em;
  padding:2px 6px; border-radius:5px;
  background:rgba(255,255,255,.07); color:var(--gold-light,#E8C878);
}
.lfg-side-txt small{color:var(--muted); font-size:.78rem}

.lfg-create{
  display:inline-flex; align-items:center; gap:8px; white-space:nowrap;
  align-self:stretch;
}
.lfg-create .ico{width:16px; height:16px}

/* -------------------------------------------------------------- filters -- */

.lfg-filters{
  display:flex; flex-wrap:wrap; gap:10px; align-items:center;
  padding:12px; border-radius:14px; margin-bottom:12px;
  background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.07);
}

.lfg-search{
  display:flex; align-items:center; gap:8px; flex:1 1 220px; min-width:0;
  padding:0 12px; border-radius:10px;
  background:rgba(0,0,0,.28); border:1px solid rgba(255,255,255,.08);
}
.lfg-search .ico{width:16px; height:16px; flex:none; color:var(--muted)}
.lfg-search input{
  flex:1; min-width:0; padding:10px 0; border:0; outline:0;
  background:transparent; color:inherit; font:inherit;
}

.lfg-select{
  padding:10px 12px; border-radius:10px; font:inherit; color:inherit;
  background:rgba(0,0,0,.28); border:1px solid rgba(255,255,255,.08);
}
.lfg-select:focus{outline:2px solid var(--gold-dark,#8A641B); outline-offset:1px}

.lfg-servers{margin-bottom:14px}

/* ----------------------------------------------------------- the board -- */

.lfg-list{display:flex; flex-direction:column; gap:10px}

.lfg-row{
  display:grid; gap:14px; align-items:center;
  grid-template-columns:48px minmax(0,1fr) auto auto;
  padding:14px 16px; border-radius:14px;
  background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.07);
  transition:border-color .15s, background .15s;
}
.lfg-row:hover{background:rgba(255,255,255,.05); border-color:rgba(217,165,46,.35)}

/* One hairline is the whole difference between the two kinds. Two card
   designs would say they are different things; they are two sides of one. */
.lfg-row.is-lfp{border-inline-start:3px solid var(--gold,#D9A52E)}
.lfg-row.is-lft{border-inline-start:3px solid rgba(255,255,255,.22)}

.lfg-av{
  width:48px; height:48px; border-radius:50%; overflow:hidden; flex:none;
  display:grid; place-items:center; text-decoration:none;
  background:rgba(255,255,255,.07); color:var(--gold-light,#E8C878);
}
.lfg-av img{width:100%; height:100%; object-fit:cover}


/* ------------------------------------------------- live and verified --
   Two marks the site can make that a poster cannot: who is in the server
   right now, and which numbers came from the game rather than from a text
   box. Green is used for exactly one thing here - alive - so it never
   competes with the gold accent.                                        */

.lfg-av.is-online{position:relative; box-shadow:0 0 0 2px rgba(64,200,120,.65)}

.lfg-live{
  width:8px; height:8px; border-radius:50%; flex:none;
  background:#40C878; box-shadow:0 0 0 3px rgba(64,200,120,.22);
}
/* On the avatar it is a dot pinned to the corner; inline it is just a dot. */
.lfg-av .lfg-live{
  position:absolute; inset-inline-end:-1px; bottom:-1px;
  border:2px solid var(--ink,#080B10); width:12px; height:12px; box-shadow:none;
}

.lfg-online{
  display:inline-flex; align-items:center; gap:6px;
  font-size:.68rem; padding:3px 8px; border-radius:999px;
  color:#9BE7BC; background:rgba(64,200,120,.12);
  border:1px solid rgba(64,200,120,.28);
}

/* A recorded figure is gold; a typed one stays grey. The difference has to
   be visible at a glance or the tick is decoration. */
.lfg-row-meta span.is-verified{color:var(--gold-light,#E8C878)}
.lfg-row-meta span.is-verified .ico{opacity:1; color:var(--gold,#D9A52E)}
.lfg-row-meta span.is-verified b{color:var(--gold-bright,#F2C75C)}

.lfg-fact.is-verified b{color:var(--gold-bright,#F2C75C)}
.lfg-fact.is-verified small{color:var(--gold-light,#E8C878); opacity:.8}

/* prefers-reduced-motion is respected by there being no motion at all: the
   dot does not pulse. A blinking element beside every online player would
   make a busy board unreadable. */

.lfg-row-body{min-width:0; display:flex; flex-direction:column; gap:6px}

.lfg-row-title{
  margin:0; font-size:1rem; line-height:1.5;
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
}
.lfg-row-title a{color:inherit; text-decoration:none}
.lfg-row-title a:hover{text-decoration:underline}

.lfg-badge{
  font-size:.62rem; font-weight:800; letter-spacing:.09em;
  padding:3px 7px; border-radius:5px; flex:none;
  background:rgba(255,255,255,.08); color:#cfd5de;
}
.is-lfp .lfg-badge{background:rgba(217,165,46,.18); color:var(--gold-bright,#F2C75C)}

.lfg-row-desc{
  margin:0; font-size:.84rem; line-height:1.8; color:var(--muted);
  overflow-wrap:anywhere;
}

.lfg-chips{display:flex; flex-wrap:wrap; gap:6px}

.lfg-chip{
  font-size:.7rem; padding:3px 9px; border-radius:999px;
  background:rgba(255,255,255,.05); border:1px solid rgba(255,255,255,.08);
}
.lfg-chip-quiet{opacity:.6}

.lfg-row-meta{
  display:flex; flex-direction:column; gap:4px; flex:none;
  font-size:.76rem; color:var(--muted);
}
.lfg-row-meta span{display:flex; align-items:center; gap:6px; white-space:nowrap}
.lfg-row-meta .ico{width:14px; height:14px; flex:none; opacity:.75}
.lfg-row-meta b{color:#e6e9ee}
.lfg-row-meta small{font-size:.7rem}

.lfg-row-side{
  display:flex; flex-direction:column; align-items:flex-end; gap:8px; flex:none;
}
.lfg-when{font-size:.72rem; color:var(--muted); white-space:nowrap}
.lfg-join{padding:8px 20px}

.lfg-state{font-size:.74rem; color:var(--muted); white-space:nowrap}
.lfg-state-ok{color:var(--gold-bright,#F2C75C)}

/* --------------------------------------------------------------- aside -- */

.lfg-card{
  padding:16px 18px; border-radius:16px;
  background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.07);
}

.lfg-card-head{
  margin:0 0 14px; font-size:.85rem; letter-spacing:.02em;
  display:flex; align-items:center; gap:8px; color:#e6e9ee;
}
.lfg-card-head .ico{width:16px; height:16px; color:var(--gold,#D9A52E)}

.lfg-stats{display:grid; grid-template-columns:repeat(3,1fr); gap:10px; text-align:center}
.lfg-stats div{display:flex; flex-direction:column; gap:2px}
.lfg-stats b{font-size:1.5rem; line-height:1.1; color:var(--gold-bright,#F2C75C)}
.lfg-stats span{font-size:.68rem; color:var(--muted); line-height:1.4}

.lfg-cloud{display:flex; flex-wrap:wrap; gap:6px}

.lfg-cloud-tag{
  display:inline-flex; align-items:center; gap:6px;
  font-size:.72rem; padding:5px 10px; border-radius:999px;
  text-decoration:none; color:inherit;
  background:rgba(255,255,255,.04); border:1px solid rgba(255,255,255,.08);
}
.lfg-cloud-tag:hover{background:rgba(255,255,255,.07)}
.lfg-cloud-tag.on{
  border-color:var(--gold,#D9A52E); background:rgba(217,165,46,.14);
  color:var(--gold-bright,#F2C75C);
}
.lfg-cloud-tag i{font-style:normal; font-size:.66rem; opacity:.65}

.lfg-promo p{margin:0 0 12px; font-size:.82rem; line-height:1.9; color:var(--muted)}
.lfg-promo .btn{display:inline-flex; align-items:center; gap:8px}
.lfg-promo .ico{width:16px; height:16px}

.lfg-promise{
  margin:0; padding:12px 14px; border-radius:12px;
  font-size:.78rem; line-height:1.9; color:var(--muted);
  background:rgba(217,165,46,.06);
  border:1px solid rgba(217,165,46,.20);
}

/* ------------------------------------------------------------ one post -- */

.lfg-single,.lfg-mine,.dm-wrap{max-width:860px}

.lfg-back{margin:0 0 16px; font-size:.85rem}
.lfg-back a{display:inline-flex; align-items:center; gap:6px; color:var(--muted); text-decoration:none}
.lfg-back a:hover{color:var(--bone)}
/* The chevron points back along the reading direction, so in RTL it flips. */
.lfg-back .ico{width:14px; height:14px; transform:scaleX(-1)}

.lfg-full{
  padding:0; border-radius:18px; overflow:hidden;
  background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.07);
}
.lfg-full.is-lfp{border-top:3px solid var(--gold,#D9A52E)}
.lfg-full.is-lft{border-top:3px solid rgba(255,255,255,.22)}

.lfg-full-head{
  display:flex; align-items:flex-start; gap:16px;
  padding:22px 24px 18px;
  background:linear-gradient(180deg, rgba(255,255,255,.035), transparent);
}

.lfg-full-av{
  width:64px; height:64px; flex:none; border-radius:16px; overflow:hidden;
  display:grid; place-items:center; text-decoration:none;
  background:rgba(255,255,255,.07); color:var(--gold-light,#E8C878);
  border:1px solid rgba(255,255,255,.08);
}
.lfg-full-av img{width:100%; height:100%; object-fit:cover}

.lfg-full-id{min-width:0; flex:1}

.lfg-full-kicker{
  margin:0 0 8px; display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  font-size:.74rem; color:var(--muted);
}
.lfg-dot{opacity:.4}

.lfg-full-title{
  margin:0 0 6px; font-size:1.6rem; line-height:1.4; text-wrap:balance;
}

.lfg-who{
  margin:0; font-size:.86rem; color:var(--muted);
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
}
.lfg-who a{color:var(--gold-light,#E8C878); text-decoration:none}
.lfg-who a:hover{text-decoration:underline}

/* The facts strip. These all existed on the board row and had nowhere to go
   on the page with the most room for them, which is what made this page read
   as emptier than the list it came from. */
.lfg-facts{
  display:grid; gap:1px; margin:0;
  grid-template-columns:repeat(auto-fit,minmax(110px,1fr));
  background:rgba(255,255,255,.07);
  border-block:1px solid rgba(255,255,255,.07);
}

.lfg-fact{
  display:flex; flex-direction:column; align-items:center; gap:2px;
  padding:14px 10px; background:var(--ink,#080B10);
}
.lfg-fact .ico{width:16px; height:16px; color:var(--gold,#D9A52E); opacity:.85}
.lfg-fact b{font-size:.95rem; line-height:1.3}
.lfg-fact small{font-size:.68rem; color:var(--muted); text-align:center}

.lfg-full-body{
  margin:0; padding:20px 24px; line-height:2.05; color:#d7dbe2;
  overflow-wrap:anywhere;
}

.lfg-full-tags{padding:0 24px 20px}

.lfg-full-foot{
  display:flex; flex-wrap:wrap; align-items:center; gap:12px;
  padding:14px 24px; font-size:.78rem; color:var(--muted);
  border-top:1px solid rgba(255,255,255,.06);
  background:rgba(0,0,0,.18);
}

/* ------------------------------------------------------- apply / cta --- */

.lfg-apply{
  margin-top:18px; padding:20px 24px; border-radius:18px;
  background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.07);
}
.lfg-apply-head{margin:0 0 12px; font-size:1rem}
.lfg-apply textarea{width:100%; box-sizing:border-box}

.lfg-apply-foot{
  display:flex; align-items:flex-end; justify-content:space-between;
  gap:16px; margin-top:12px;
}
.lfg-apply-foot .lfg-note{margin:0; flex:1}
.lfg-apply-foot .btn{flex:none}

.lfg-cta{
  margin-top:18px; padding:22px 24px; border-radius:18px; text-align:center;
  background:rgba(217,165,46,.06);
  border:1px solid rgba(217,165,46,.22);
}
.lfg-cta p{margin:0 0 12px}

.lfg-more{margin:20px 0 0; text-align:center; font-size:.85rem}
.lfg-more a{color:var(--muted)}

.lfg-note{margin:10px 0 0; font-size:.8rem; line-height:1.9; color:var(--muted)}
/* -------------------------------------------------------- my own ads --- */

.lfg-block{
  margin-top:22px; padding:20px 22px; border-radius:16px;
  background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.07);
}

.lfg-block-title{
  margin:0 0 14px; font-size:1rem;
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
}

.lfg-form-row{display:grid; gap:12px; grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}

/* The tag picker: real checkboxes, so it works with no JavaScript at all. */
.lfg-tagpick{display:flex; flex-wrap:wrap; gap:8px}
.lfg-tagpick-one{position:relative; cursor:pointer}
.lfg-tagpick-one input{position:absolute; opacity:0; width:0; height:0}
.lfg-tagpick-one span{
  display:inline-block; font-size:.76rem; padding:7px 13px; border-radius:999px;
  background:rgba(255,255,255,.04); border:1px solid rgba(255,255,255,.10);
  transition:background .12s, border-color .12s, color .12s;
}
.lfg-tagpick-one input:checked + span{
  background:rgba(217,165,46,.16); border-color:var(--gold,#D9A52E);
  color:var(--gold-bright,#F2C75C);
}
/* Keyboard users have to be able to see where they are. */
.lfg-tagpick-one input:focus-visible + span{outline:2px solid var(--gold-bright,#F2C75C); outline-offset:2px}

.lfg-owned{display:block}
.lfg-owned-top{display:flex; justify-content:space-between; align-items:center; gap:10px}
.lfg-owned-top h4{margin:0; font-size:1.05rem}
.lfg-owned-top a{color:inherit; text-decoration:none}

.lfg-owned-actions{display:flex; gap:8px; margin:14px 0}
.lfg-owned-actions form{display:inline}

.lfg-applicants-title{
  margin:18px 0 10px; font-size:.95rem;
  display:flex; align-items:center; gap:8px;
}
.lfg-applicants-title i{
  font-style:normal; font-size:.75rem; padding:2px 8px; border-radius:999px;
  background:rgba(255,255,255,.06);
}

.lfg-rows{display:flex; flex-direction:column; gap:8px}

/* A plain two-column row — deliberately NOT .lfg-row, which is the board's
   four-column grid and would squash these. */
.lfg-row-flat{
  display:flex; align-items:center; justify-content:space-between; gap:14px;
  padding:12px 14px; border-radius:12px;
  background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.06);
}

.lfg-row-main{display:flex; flex-direction:column; gap:4px; min-width:0}
.lfg-row-main a{color:inherit}
.lfg-row-main small{color:var(--muted); line-height:1.8; overflow-wrap:anywhere}

.lfg-sent-end{display:flex; align-items:center; gap:10px; flex-shrink:0}
/* Quieter than the accept/decline pair: taking your own application back is
   a correction, not a decision about somebody else. */
/* stylelint-disable-next-line */
.lfg-withdraw{padding:5px 12px; font-size:.74rem; opacity:.8}
.lfg-withdraw:hover{opacity:1}

.lfg-decide{display:flex; gap:8px; flex-shrink:0}
.lfg-decide form{display:inline}

/* ============================================================================
   Private messages
   ==========================================================================*/

.dm-notice{margin-bottom:18px}

.dm-list{display:flex; flex-direction:column; gap:8px; margin-top:16px}

.dm-item{
  display:flex; align-items:center; gap:12px;
  padding:12px 14px; border-radius:12px; text-decoration:none; color:inherit;
  background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.06);
}
.dm-item:hover{background:rgba(255,255,255,.05)}
.dm-unread{border-color:rgba(217,165,46,.45)}

.dm-av{
  width:38px; height:38px; border-radius:50%; flex-shrink:0;
  object-fit:cover; display:grid; place-items:center;
  background:rgba(255,255,255,.07);
}

.dm-item-main{display:flex; flex-direction:column; gap:3px; min-width:0; flex:1}
.dm-item-main small{color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}

.dm-item-meta{display:flex; align-items:center; gap:8px; flex-shrink:0}
.dm-item-meta small{color:var(--muted); font-size:.72rem}

.dm-badge{
  font-style:normal; font-size:.7rem; min-width:20px; text-align:center;
  padding:2px 6px; border-radius:999px;
  background:var(--gold,#D9A52E); color:#111;
}

.dm-blocked{margin-top:30px}

.dm-head{display:flex; align-items:center; gap:12px; margin-bottom:16px}
.dm-head-id h2{margin:0; font-size:1.2rem}
.dm-head-id h2 a{color:inherit; text-decoration:none}
.dm-head-id small{color:var(--muted)}

.dm-thread{display:flex; flex-direction:column; gap:10px; margin:18px 0}

.dm-msg{
  max-width:78%; padding:10px 14px; border-radius:14px;
  background:rgba(255,255,255,.04);
  border:1px solid rgba(255,255,255,.06);
}
.dm-msg p{margin:0; line-height:1.9; overflow-wrap:anywhere}
.dm-msg small{display:block; margin-top:4px; font-size:.7rem; color:var(--muted)}

/* Logical properties, so the sides follow the RTL document rather than being
   hard-coded left and right. */
.dm-mine{margin-inline-start:auto; background:rgba(217,165,46,.10); border-color:rgba(217,165,46,.28)}
.dm-theirs{margin-inline-end:auto}

.dm-sender{display:block; font-size:.75rem; color:var(--gold-bright,#F2C75C); margin-bottom:4px}

/* The staff view is a transcript, not a conversation: both sides are shown the
   same way so nobody's messages look like "ours". */
.dm-staff .dm-msg{max-width:100%; margin:0}

.dm-reply{display:flex; gap:10px; align-items:flex-end; margin-top:8px}
.dm-reply textarea{flex:1}

.dm-tools{display:flex; flex-wrap:wrap; gap:10px; align-items:flex-start; margin-top:22px}
.dm-tools form{display:inline}

.dm-report{
  flex:1; min-width:260px; padding:10px 14px; border-radius:12px;
  background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.06);
}
.dm-report summary{cursor:pointer; font-size:.85rem}
.dm-report textarea{margin-top:10px}

.nav-dm i{
  font-style:normal; margin-inline-start:6px; font-size:.7rem;
  padding:1px 6px; border-radius:999px;
  background:var(--gold,#D9A52E); color:#111;
}

/* Base rules above, overrides below — the order this stylesheet depends on. */

@media (max-width:1080px){
  /* The sidebar stops being a sidebar before the rows start to crush. */
  .lfg-shell{grid-template-columns:minmax(0,1fr)}
  .lfg-side{position:static; flex-direction:row; flex-wrap:wrap}
  .lfg-side > *{flex:1 1 260px}
}

@media (max-width:820px){
  .lfg-switch{grid-template-columns:minmax(0,1fr)}
  .lfg-create{justify-content:center}
}

@media (max-width:640px){
  .lfg-hero{padding:44px 0 36px}

  /* The board row goes from four columns to two: avatar plus everything else,
     with the meta and the button dropping underneath. Kept as a grid rather
     than a stack so the avatar stays beside the title. */
  .lfg-row{grid-template-columns:44px minmax(0,1fr); gap:10px}
  .lfg-row-meta{grid-column:1 / -1; flex-direction:row; flex-wrap:wrap; gap:12px}
  .lfg-row-side{grid-column:1 / -1; flex-direction:row; align-items:center;
    justify-content:space-between; width:100%}

  .lfg-filters{padding:10px}
  .lfg-select{flex:1 1 140px}

  /* The accept/decline pair would otherwise squeeze the applicant's message
     into a two-character column. */
  .lfg-row-flat{flex-direction:column; align-items:stretch}
  .lfg-decide{justify-content:flex-start}

  .dm-msg{max-width:92%}
  .dm-reply{flex-direction:column; align-items:stretch}

  .lfg-full-head{padding:18px 16px 14px; gap:12px}
  .lfg-full-av{width:52px; height:52px; border-radius:14px}
  .lfg-full-title{font-size:1.25rem}
  .lfg-full-body,.lfg-full-tags,.lfg-full-foot{padding-inline:16px}
  .lfg-facts{grid-template-columns:repeat(2,1fr)}
  .lfg-apply{padding:16px}
  /* The button drops under the warning rather than squeezing it. */
  .lfg-apply-foot{flex-direction:column; align-items:stretch}
}
/* ---------------------------------------------------------------- bell page
   Gold, not red. The list is one object: the same rail, the same baseline and
   the same inner padding on every row, so an unread row differs from a read
   one by weight and a tint - not by becoming a different shape. */

.nt-wrap{padding-block:0}  /* .lb-body owns the vertical rhythm and the fixed-nav clearance */

.nt-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;
         flex-wrap:wrap;margin-bottom:20px}
.nt-title{font-size:clamp(24px,4vw,34px);line-height:1.15;margin:0}
.nt-sub{margin:6px 0 0;opacity:.62;font-size:14px}

.nt-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}

.nt-row{border:1px solid rgba(255,255,255,.08);border-radius:12px;
        background:rgba(255,255,255,.02);overflow:hidden;transition:border-color .15s}
.nt-row:hover{border-color:rgba(217,165,46,.35)}

.nt-row.is-new{border-color:rgba(217,165,46,.30);background:rgba(217,165,46,.05)}
.nt-row.is-new .nt-h{font-weight:800}

.nt-link{display:grid;grid-template-columns:auto 1fr auto;align-items:center;
         gap:14px;padding:14px 16px;color:inherit;text-decoration:none;min-width:0}

.nt-kind{font-size:11px;letter-spacing:.04em;padding:4px 9px;border-radius:999px;
         border:1px solid rgba(217,165,46,.30);color:var(--gold-bright);white-space:nowrap}

.nt-main{display:flex;flex-direction:column;gap:3px;min-width:0}
.nt-h{font-size:15px;line-height:1.35;overflow-wrap:anywhere}
.nt-b{font-size:13px;opacity:.6;line-height:1.45;
      display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

.nt-when{font-size:12px;opacity:.45;white-space:nowrap}

.nt-empty{text-align:center;padding:64px 20px;border:1px dashed rgba(255,255,255,.10);
          border-radius:16px}
.nt-empty .ico{width:34px;height:34px;opacity:.30;margin-bottom:12px}
.nt-empty p{margin:0 0 6px;font-size:17px}
.nt-empty span{font-size:13px;opacity:.55}

/* The date is the first thing worth losing on a phone - the rest of the row
   still says what happened and links where it happened. */
@media (max-width:560px){
  .nt-link{grid-template-columns:auto 1fr;gap:10px;padding:12px 13px}
  .nt-when{grid-column:2;justify-self:start;margin-top:2px}
}

/* ============================================================================
   GAME UI PASS
   ----------------------------------------------------------------------------
   The site and the in-game CUI are the same product and were not reading like
   it. The language below is taken from the real panel rather than invented:

     - NO rounded corners anywhere. Everything is a hard rectangle.
     - L-shaped corner BRACKETS on panels instead of borders that meet.
     - Diamonds: a square rotated 45deg, 1px outline, label counter-rotated.
     - A different ACCENT PER ITEM - gold, rose, orange, green, magenta -
       rather than one gold used for everything.
     - A tiny wide-tracked eyebrow over a heavy display heading.
     - Text buttons that are a word with a hairline rule under it.
     - Square bullets, never discs.
     - A faint diagonal lattice behind things, and a radial glow under focal
       elements.

   This block is deliberately LAST in the file so it wins the cascade without
   touching the 309 border-radius declarations above it one at a time.
   ========================================================================= */

:root{
  --acc-gold:#FBD380;
  --acc-rose:#E8546E;
  --acc-orange:#E8862E;
  --acc-green:#3FBF6F;
  --acc-magenta:#C74BD6;
  --acc-blue:#5AA9E6;

  --gx-line:rgba(251,211,128,.30);
  --gx-line-soft:rgba(251,211,128,.10);
  --gx-glow:rgba(251,211,128,.18);
}

/* --------------------------------------------------------------- 1. FLATTEN
   The only !important pair in the file, and it earns it: this is one global
   design decision, not a patch on a component. Reverting the look is deleting
   two rules rather than hunting 309 of them. */
*{border-radius:0 !important}

/* The few things that really are round in the game too. */
/* .nav-coin was here and has been removed: the game has no pills, its
   player-count bar has ANGLED ends, so the scrap counter is chamfered in
   wave 5 instead. */
[class*="avatar"],.nav-avatar,.nav-dot,
.cp-emblem,.dot,.live-dot,.gx-round{border-radius:999px !important}

/* ------------------------------------------------------- 2. CORNER BRACKETS */
.gx-frame{position:relative}
.gx-frame::before,.gx-frame::after{
  content:"";position:absolute;width:16px;height:16px;pointer-events:none;z-index:2}
.gx-frame::before{top:-1px;right:-1px;
  border-top:1px solid var(--gx-line);border-right:1px solid var(--gx-line)}
.gx-frame::after{bottom:-1px;left:-1px;
  border-bottom:1px solid var(--gx-line);border-left:1px solid var(--gx-line)}

/* ------------------------------------------------------------- 3. LATTICE
   Two crossed 45deg repeating gradients make the diamond grid behind the game
   panel. Very low alpha on purpose: it must read as texture, never content. */
.gx-lattice{position:relative;isolation:isolate}
.gx-lattice::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:
    repeating-linear-gradient(45deg,var(--gx-line-soft) 0 1px,transparent 1px 72px),
    repeating-linear-gradient(-45deg,var(--gx-line-soft) 0 1px,transparent 1px 72px);
  -webkit-mask-image:radial-gradient(ellipse at 50% 0%,#000 0%,transparent 78%);
  mask-image:radial-gradient(ellipse at 50% 0%,#000 0%,transparent 78%)}

/* -------------------------------------------------- 4. EYEBROW + DISPLAY */
.gx-eyebrow{
  font-size:10px;font-weight:700;letter-spacing:.34em;text-transform:uppercase;
  color:var(--mute);margin:0 0 8px;line-height:1}
.gx-display{
  font-size:clamp(26px,4vw,44px);font-weight:900;line-height:1.06;
  letter-spacing:-.02em;margin:0;text-wrap:balance}

/* ------------------------------------------------- 5. HAIRLINE TEXT BUTTON */
.gx-rule{
  display:inline-block;padding:7px 16px 9px;background:none;border:0;
  border-bottom:1px solid var(--gx-line);color:var(--gold-bright);
  font-family:inherit;font-size:12px;font-weight:800;letter-spacing:.16em;
  cursor:pointer;transition:border-color .15s,text-shadow .15s}
.gx-rule:hover{
  border-bottom-color:var(--gold-bright);text-shadow:0 0 14px var(--gx-glow)}

/* ------------------------------------------------------------- 6. DIAMOND
   A rotated square. The label is counter-rotated so the text stays level,
   which is the same trick the CUI uses and the reason the inner span exists. */
.gx-dia{
  --acc:var(--acc-gold);
  display:grid;place-items:center;width:104px;height:104px;
  border:1px solid var(--acc);transform:rotate(45deg);
  background:rgba(0,0,0,.35);transition:box-shadow .18s,background .18s}
.gx-dia:hover{box-shadow:0 0 26px -4px var(--acc);background:rgba(0,0,0,.15)}
.gx-dia > *{transform:rotate(-45deg);text-align:center;line-height:1.25}
.gx-dia b{display:block;color:var(--acc);font-size:14px;font-weight:800;letter-spacing:.06em}
.gx-dia small{display:block;color:var(--mute);font-size:10px;letter-spacing:.14em}

/* --------------------------------------------------------- 7. ACCENT CARD
   The VIP tier card from the game: a coloured bar across the top and a
   coloured bracket biting the bottom corner. */
.gx-card{
  --acc:var(--acc-gold);
  position:relative;background:var(--panel);border:1px solid var(--line);
  padding:20px 18px}
.gx-card::before{
  content:"";position:absolute;top:-1px;left:-1px;right:-1px;height:2px;background:var(--acc)}
.gx-card::after{
  content:"";position:absolute;right:-1px;bottom:-1px;width:14px;height:14px;
  border-right:2px solid var(--acc);border-bottom:2px solid var(--acc)}
.gx-card h3{color:var(--acc);margin:0 0 2px;font-size:20px;font-weight:900}

/* ------------------------------------------------------- 8. SQUARE BULLETS */
.gx-bullets{list-style:none;margin:0;padding:0}
.gx-bullets li{position:relative;padding-inline-start:18px;margin-bottom:7px}
.gx-bullets li::before{
  content:"";position:absolute;inset-inline-start:0;top:.72em;
  width:5px;height:5px;background:var(--acc,var(--acc-gold))}

/* ---------------------------------------------------------------- 9. GLOW */
.gx-halo{position:relative}
.gx-halo::before{
  content:"";position:absolute;inset:-40% -20%;z-index:-1;pointer-events:none;
  background:radial-gradient(ellipse at center,var(--gx-glow) 0%,transparent 62%)}

/* ====================================================================
   APPLYING IT TO WHAT ALREADY EXISTS
   Restyling, never restructuring. No control is removed and nothing moves.
   ================================================================= */

/* Buttons take the tracking and the squared edge. The gold primary keeps its
   fill because it is the one loud control in the CUI too. */
.btn{letter-spacing:.08em;font-weight:800}
.btn-g{border:1px solid var(--gx-line);background:transparent}
.btn-g:hover{border-color:var(--gold-bright);box-shadow:0 0 18px -6px var(--gx-glow)}

/* Notices become a coloured rail rather than a tinted box. */
.notice{position:relative;border-inline-start:2px solid var(--acc-gold)}
.notice-ok{border-inline-start-color:var(--acc-green)}
.notice-err{border-inline-start-color:var(--acc-rose)}
.notice-warn{border-inline-start-color:var(--acc-orange)}

/* The bell list as game panels: hard edges, a coloured rail per category, and
   the kind chip as a squared tag rather than a pill. */
.nt-row{position:relative;border-color:var(--line)}
.nt-row::before{
  content:"";position:absolute;inset-block:0;inset-inline-start:0;width:2px;
  background:var(--acc,transparent)}
.nt-row.is-new{background:rgba(251,211,128,.045)}
.nt-kind{
  border:1px solid var(--acc,var(--gx-line));color:var(--acc,var(--gold-bright));
  letter-spacing:.14em;font-size:10px;font-weight:800}

/* Per-category accents, straight from the five colours in the CUI. */
[data-kind="dm_message"]{--acc:var(--acc-magenta)}
[data-kind="lfg_application"]{--acc:var(--acc-green)}
[data-kind="lfg_answered"]{--acc:var(--acc-green)}
[data-kind="ticket_reply"]{--acc:var(--acc-blue)}
[data-kind="delivery_failed"]{--acc:var(--acc-rose)}
[data-kind="rank_expiring"]{--acc:var(--acc-orange)}
[data-kind="wipe"]{--acc:var(--acc-gold)}
[data-kind="event"]{--acc:var(--acc-orange)}
[data-kind="clan"]{--acc:var(--acc-magenta)}
[data-kind="achievement"]{--acc:var(--acc-gold)}

/* Page headers take the display treatment. */
.nt-title{font-size:clamp(26px,4vw,42px);font-weight:900;letter-spacing:-.02em;line-height:1.06}
.nt-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap}

/* The settings screen, as a stack of game panels. */
.ns-form{display:flex;flex-direction:column;gap:14px;margin-top:18px}
.ns-block{position:relative;background:var(--panel);border:1px solid var(--line);padding:18px 18px 14px}
.ns-block::before{
  content:"";position:absolute;top:-1px;left:-1px;right:-1px;height:2px;background:var(--acc-gold)}
.ns-h{margin:0 0 4px;font-size:12px;font-weight:800;letter-spacing:.2em;
  text-transform:uppercase;color:var(--gold-bright)}
.ns-note{margin:0 0 12px;font-size:12.5px;color:var(--mute);line-height:1.7}
.ns-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.ns-row{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:9px 0;border-top:1px solid rgba(255,255,255,.05)}
.ns-row:first-child{border-top:0}
.ns-label{display:flex;align-items:center;gap:10px;cursor:pointer;min-width:0}
.ns-label input{width:15px;height:15px;accent-color:#D9A52E;flex:none;cursor:pointer}
.ns-name{font-size:14px}
.ns-state{font-size:11px;letter-spacing:.12em;color:var(--gold-bright);white-space:nowrap}
.ns-state.dim{color:var(--dim)}
.ns-actions{display:flex;justify-content:flex-start;padding-top:4px}

@media (max-width:560px){
  .ns-row{align-items:flex-start;flex-direction:column;gap:4px}
  .ns-state{padding-inline-start:25px}
}

/* ============================================================================
   GAME UI PASS - WAVE 2
   Harder. The first wave squared the edges; this one gives the site the game
   panel's actual shapes: cut corners, brackets, the diamond lattice, and a
   different accent for each card in a row the way the VIP tiers do it.
   ========================================================================= */

/* ------------------------------------------------------------ 1. CHAMFERS
   The angled cut the CUI puts on its bars and cards. Applied to CARDS only -
   never to list rows, whose coloured rail runs to the edge, and never to
   anything containing a dropdown, because clip-path clips children too. */
.card,.dash-card,.lb-panel,.lb-widget,.sh-card,.sh-server,.nw-card,.ow-card,
.ah-card,.pf-kpi,.db-wallet,.db-rank,.ns-block,.gx-card,.ev,.pillar,.od-tile,
.tu-preset,.lg-two-box,.mv-shot{
  clip-path:polygon(
    16px 0, 100% 0,
    100% calc(100% - 16px), calc(100% - 16px) 100%,
    0 100%, 0 16px)}

/* ------------------------------------------------- 2. BRACKETS ON PANELS
   Hairline L marks at a corner, the way the game frames its window. Only on
   the big surfaces - a bracket on a small control is noise. */
.lb-panel,.lb-widget,.dash-card,.sh-server,.ow-card,.ah-panel,.ns-block,
.db-wallet,.pillar,.nw-art{position:relative}
.lb-panel::after,.lb-widget::after,.dash-card::after,.sh-server::after,
.ow-card::after,.ah-panel::after,.db-wallet::after,.pillar::after{
  content:"";position:absolute;top:6px;left:6px;width:14px;height:14px;
  border-top:1px solid var(--gx-line);border-left:1px solid var(--gx-line);
  pointer-events:none;z-index:2}

/* ------------------------------------------------------ 3. SECTION LATTICE
   The faint diamond grid behind the panel. Sections only, and masked so it
   fades out rather than tiling flatly to the edge. */
section{position:relative;isolation:isolate}
section::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;opacity:.55;
  background-image:
    repeating-linear-gradient(45deg,var(--gx-line-soft) 0 1px,transparent 1px 78px),
    repeating-linear-gradient(-45deg,var(--gx-line-soft) 0 1px,transparent 1px 78px);
  -webkit-mask-image:radial-gradient(ellipse at 50% 40%,#000 0%,transparent 75%);
  mask-image:radial-gradient(ellipse at 50% 40%,#000 0%,transparent 75%)}
/* The hero paints its own art; a lattice on top of a photograph is mud. */
.hero::before,.lfg-hero::before,.cs-hero::before{display:none}

/* --------------------------------------------------- 4. DISPLAY HEADINGS
   Heavier and tighter, the way "Read this" and "VIP" sit in the panel. */
h1,h2{letter-spacing:-.025em;font-weight:900;line-height:1.05}
.eyebrow{letter-spacing:.34em;font-size:10px;color:var(--mute)}

/* ------------------------------------------- 5. A COLOUR PER CARD IN A ROW
   Straight off the VIP tier row: Bronze green, Silver orange, Gold rose,
   Elite magenta. Any row of cards now reads as a set of distinct things
   rather than four copies of one gold thing. */
.sh-card,.pillar,.ow-card,.ev,.nw-card{--acc:var(--acc-gold);position:relative}
.sh-card:nth-child(4n+1),.pillar:nth-child(4n+1),.ev:nth-child(4n+1){--acc:var(--acc-green)}
.sh-card:nth-child(4n+2),.pillar:nth-child(4n+2),.ev:nth-child(4n+2){--acc:var(--acc-orange)}
.sh-card:nth-child(4n+3),.pillar:nth-child(4n+3),.ev:nth-child(4n+3){--acc:var(--acc-rose)}
.sh-card:nth-child(4n+4),.pillar:nth-child(4n+4),.ev:nth-child(4n+4){--acc:var(--acc-magenta)}

/* The coloured top edge that makes them tier cards. */
.sh-card::before,.pillar::before,.ev::before{
  content:"";position:absolute;top:0;left:0;right:0;height:2px;
  background:var(--acc);z-index:3;pointer-events:none}

/* ---------------------------------------------------- 6. HERO STAT TILES
   The ICON BADGE becomes the diamond, and the stat keeps its own two-column
   grid untouched. Overriding that grid with aspect-ratio collapsed the whole
   row - the tiles are icon-beside-number, not centred squares.

   The diamond is a clip-path on the badge rather than a rotated pseudo
   element, because .ico is an <svg> and SVG elements do not render ::before
   or ::after at all. */
.hero-stat{--acc:var(--acc-gold)}
.hero-stat .ico{
  clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%);
  background:color-mix(in srgb,var(--acc) 26%,transparent);
  color:var(--acc);transition:background .18s}
.hero-stat:hover .ico{background:color-mix(in srgb,var(--acc) 46%,transparent)}
.hero-stats > *:nth-child(4n+1){--acc:var(--acc-gold)}
.hero-stats > *:nth-child(4n+2){--acc:var(--acc-green)}
.hero-stats > *:nth-child(4n+3){--acc:var(--acc-orange)}
.hero-stats > *:nth-child(4n+4){--acc:var(--acc-magenta)}

/* ------------------------------------------------------- 7. SQUARE BULLETS
   Every list in the product, not just the ones that opt in. */
.sh-card ul,.pillar ul{list-style:none;padding-inline-start:0}
.sh-card ul li,.pillar ul li{position:relative;padding-inline-start:16px}
.sh-card ul li::before,.pillar ul li::before{
  content:"";position:absolute;inset-inline-start:0;top:.7em;
  width:5px;height:5px;background:var(--acc,var(--acc-gold))}

/* ------------------------------------------------------------- 8. TAB RAILS
   Tabs become the underlined words from the panel footer. */
.lb-tabs a,.lb-tabs button,.sh-cat,.ah-cat{
  letter-spacing:.14em;font-weight:800;border-bottom:1px solid transparent}
.lb-tabs .is-on,.sh-cat.is-on,.ah-cat.is-on{
  border-bottom-color:var(--gold-bright);
  text-shadow:0 0 14px var(--gx-glow)}

/* ============================================================================
   GAME UI PASS - WAVE 3
   The pages that matched none of wave 2, because they carry their own class
   names: the team-finding board, the dashboard and the leaderboard. Found by
   reading the views rather than guessing, after the hero taught me not to.
   ========================================================================= */

/* ------------------------------------------------------ TEAM FINDING BOARD */
.lfg-card{
  --acc:var(--acc-gold);
  position:relative;
  clip-path:polygon(16px 0,100% 0,100% calc(100% - 16px),
                    calc(100% - 16px) 100%,0 100%,0 16px)}
.lfg-card::before{
  content:"";position:absolute;top:0;left:0;right:0;height:2px;
  background:var(--acc);z-index:3;pointer-events:none}

/* These are the sidebar PANELS, not the ads - checked the view rather than
   assuming, after a data-kind rule that matched nothing. Rotating accents,
   the same way the VIP tier row does it. */
.lfg-card:nth-of-type(3n+1){--acc:var(--acc-gold)}
.lfg-card:nth-of-type(3n+2){--acc:var(--acc-green)}
.lfg-card:nth-of-type(3n+3){--acc:var(--acc-magenta)}

/* Tags become the squared, wide-tracked chips from the panel. */
.lfg-chip,.lfg-state{
  letter-spacing:.12em;font-size:10px;font-weight:800;
  border:1px solid var(--gx-line)}

/* ----------------------------------------------------------- DASHBOARD */
.db-grid > *,.db-line,.db-undelivered,.pf-facts{
  clip-path:polygon(14px 0,100% 0,100% calc(100% - 14px),
                    calc(100% - 14px) 100%,0 100%,0 14px)}
.db-grid > *{position:relative}
.db-grid > *::after{
  content:"";position:absolute;top:6px;left:6px;width:12px;height:12px;
  border-top:1px solid var(--gx-line);border-left:1px solid var(--gx-line);
  pointer-events:none;z-index:2}

/* The account card rows read as the game panel list. */
.link-row{border-top:1px solid rgba(255,255,255,.05)}
.link-row:first-child{border-top:0}

/* --------------------------------------------------------- LEADERBOARD */
.lb-widget-title{
  letter-spacing:.2em;text-transform:uppercase;font-size:11px;
  color:var(--gold-bright);font-weight:800}
.lb-total{letter-spacing:.06em;font-weight:900}

/* The top three keep their metals; everyone else gets the hairline row. */
.lb-widget-row{border-top:1px solid rgba(255,255,255,.05)}
.lb-widget-row:first-child{border-top:0}

/* --------------------------------------------------------------- GLOBAL
   The footer and nav take the panel's hairline seam rather than a solid
   block edge, which is what separates the two halves of the game window. */
footer{border-top:1px solid var(--gx-line-soft)}
nav{border-bottom:1px solid var(--gx-line-soft)}

/* Anything still round that should not be: the search field, selects and
   inputs are hard rectangles in the CUI. */
input,select,textarea,button{letter-spacing:.02em}
input:focus-visible,select:focus-visible,textarea:focus-visible{
  outline:1px solid var(--gold-bright);outline-offset:1px}

/* ============================================================================
   GAME UI PASS - WAVE 4
   The loading curtain, and the pages wave 3 did not reach.
   ========================================================================= */

/* ==========================================================================
   THE LOADER - a gold neon diamond
   The count sits inside the shape, the way the game panel puts a value inside
   a rhombus. Two counter-pulsing rings do the neon; the wordmark below picks
   up the same glow.

   #load, #loadbar and #loadpct are app.js hooks and are never renamed.
   ======================================================================= */
#load{background:#050505}

/* The lattice, so the very first thing anyone sees is already the game. */
#load::before{
  content:"";position:absolute;inset:0;pointer-events:none;opacity:.5;
  background-image:
    repeating-linear-gradient(45deg,var(--gx-line-soft) 0 1px,transparent 1px 68px),
    repeating-linear-gradient(-45deg,var(--gx-line-soft) 0 1px,transparent 1px 68px);
  -webkit-mask-image:radial-gradient(ellipse at center,#000 0%,transparent 70%);
  mask-image:radial-gradient(ellipse at center,#000 0%,transparent 70%)}

.load-in{position:relative}

.load-dia{position:relative;width:132px;height:132px;margin:0 auto 30px;
  display:grid;place-items:center}

.load-ring{
  position:absolute;inset:0;border:1px solid var(--acc-gold);
  box-shadow:
    0 0 14px rgba(251,211,128,.55),
    0 0 40px rgba(251,211,128,.22),
    inset 0 0 18px rgba(251,211,128,.18);
  animation:load-dia 2.1s cubic-bezier(.4,0,.2,1) infinite}
.load-ring-2{inset:22px;opacity:.6;animation-delay:.42s}

@keyframes load-dia{
  0%,100%{transform:rotate(45deg) scale(.82);opacity:.45}
  50%    {transform:rotate(45deg) scale(1);opacity:1}}

/* The number rides above the rings and does not rotate with them. */
.load-pct{
  position:relative;z-index:2;font-family:var(--disp);font-size:26px;
  color:var(--acc-gold);letter-spacing:.02em;margin:0;
  text-shadow:0 0 10px rgba(251,211,128,.8),0 0 30px rgba(251,211,128,.35)}

/* The wordmark drops the old sheen for neon. The sheen relied on
   background-clip:text with a transparent colour, so both have to be undone
   or the text stays invisible. */
.load-mark{
  animation:load-neon 3.4s ease-in-out infinite;
  background:none;-webkit-background-clip:border-box;background-clip:border-box;
  color:var(--acc-gold);letter-spacing:.04em;
  text-shadow:
    0 0 8px rgba(251,211,128,.9),
    0 0 26px rgba(251,211,128,.45),
    0 0 54px rgba(251,211,128,.2)}

@keyframes load-neon{
  0%,100%{opacity:1}
  47%    {opacity:.82}
  50%    {opacity:.55}
  53%    {opacity:.86}}

.load-sub{color:var(--acc-gold);opacity:.55;letter-spacing:.42em}

/* The bar takes the angled ends of the game's player-count bar. */
.load-bar{
  height:3px;background:rgba(251,211,128,.10);
  clip-path:polygon(5px 0,100% 0,calc(100% - 5px) 100%,0 100%)}
.load-bar i{
  background:linear-gradient(90deg,var(--gold),var(--acc-gold));
  box-shadow:0 0 14px rgba(251,211,128,.85)}

/* The top-of-page progress sliver matches. */
#prog{background:linear-gradient(90deg,var(--gold),var(--acc-gold));
  box-shadow:0 0 12px rgba(251,211,128,.7)}

/* Somebody who asked for less motion gets the shape without the pulsing. */
@media (prefers-reduced-motion:reduce){
  .load-ring,.load-mark{animation:none}
  .load-ring{transform:rotate(45deg);opacity:.9}
  .load-ring-2{transform:rotate(45deg)}
}

/* ==========================================================================
   THE REMAINING PAGES
   ======================================================================= */

/* ------------------------------------------------------------- SERVERS
   The card is .srv, and the view ALREADY hands each server its own colour on
   a --srv custom property. My first pass invented .sv-card/.srv-card, which
   matched nothing - read the markup, found the real thing, used it. */
.srv{--acc:var(--srv,var(--acc-gold));position:relative;
  clip-path:polygon(18px 0,100% 0,100% calc(100% - 18px),
                    calc(100% - 18px) 100%,0 100%,0 18px)}
.srv::after{
  content:"";position:absolute;top:0;left:0;right:0;height:2px;
  background:var(--acc);z-index:4;pointer-events:none}
.srv-live{letter-spacing:.14em;font-size:10px;font-weight:800}
.srv-badge{border:1px solid var(--acc);color:var(--acc);
  letter-spacing:.12em;font-size:10px;font-weight:800}

/* ------------------------------------------------------------- PROFILE */
.pf-card,.pf-panel,.pf-block,.pf-facts,.pf-ring{
  clip-path:polygon(14px 0,100% 0,100% calc(100% - 14px),
                    calc(100% - 14px) 100%,0 100%,0 14px)}
.pf-facts{position:relative}

/* --------------------------------------------------------------- CASES */
.cs-card,.cs-item,.cs-panel,.cs-result{
  clip-path:polygon(14px 0,100% 0,100% calc(100% - 14px),
                    calc(100% - 14px) 100%,0 100%,0 14px)}
/* The reel itself is never clipped - the strip has to slide past the frame. */
.cs-reel,.cs-strip,.cs-track{clip-path:none}

/* ---------------------------------------------------------------- NEWS */
.nw-item,.nw-post,.nw-body{
  clip-path:polygon(14px 0,100% 0,100% calc(100% - 14px),
                    calc(100% - 14px) 100%,0 100%,0 14px)}

/* --------------------------------------------------------- OWNER PANEL */
.owner-group,.owner-pre,.ow-kpi,.os-count{
  clip-path:polygon(12px 0,100% 0,100% calc(100% - 12px),
                    calc(100% - 12px) 100%,0 100%,0 12px)}

/* ------------------------------------------------------------- TICKETS */
.tk-msg{position:relative;
  clip-path:polygon(12px 0,100% 0,100% calc(100% - 12px),
                    calc(100% - 12px) 100%,0 100%,0 12px)}

/* ============================================================================
   GAME UI PASS - WAVE 5: THE NAV
   It is on every page and was the plainest thing left. The panel footer in the
   game reads "Discord  Website  Store  Enter" - wide-tracked words, each with a
   hairline rule under it - and that is exactly what a nav is.
   ========================================================================= */

/* The bar itself: a framed strip rather than a floating row. */
.nav-in{position:relative}
.nav-in::before,.nav-in::after{
  content:"";position:absolute;top:8px;bottom:8px;width:12px;
  pointer-events:none;opacity:.7}
.nav-in::before{
  inset-inline-start:6px;
  border-top:1px solid var(--gx-line);border-inline-start:1px solid var(--gx-line)}
.nav-in::after{
  inset-inline-end:6px;
  border-bottom:1px solid var(--gx-line);border-inline-end:1px solid var(--gx-line)}

/* ------------------------------------------------------------- THE LINKS
   The panel-footer treatment: tracked out, with the rule under the active one
   turned into the neon underline the game uses. */
.navlinks{gap:var(--s3)}
.navlinks a{
  letter-spacing:.1em;font-weight:700;font-size:13px;
  border-bottom:1px solid transparent;padding-bottom:5px}
.navlinks a:hover{border-bottom-color:var(--gx-line)}
.navlinks a.on{border-bottom-color:transparent}
.navlinks a.on::after{
  height:1px;bottom:-1px;
  background:var(--acc-gold);
  box-shadow:0 0 10px rgba(251,211,128,.85),0 0 22px rgba(251,211,128,.4)}

/* --------------------------------------------------------- ICON BUTTONS
   Diamonds. The frame is a ROTATED PSEUDO-ELEMENT rather than a clip-path,
   because clipping the button would cut off the unread badge that sits in its
   corner - and the badge is the whole point of the bell. */
.nav-icon{--acc:var(--gx-line);overflow:visible;border:0;background:transparent}
.nav-icon::before{
  content:"";position:absolute;inset:5px;z-index:-1;
  border:1px solid var(--acc);background:rgba(0,0,0,.35);
  transform:rotate(45deg);transition:border-color .18s,box-shadow .18s}
.nav-icon:hover{--acc:var(--acc-gold)}
.nav-icon:hover::before{box-shadow:0 0 18px -3px var(--acc-gold)}

/* A bell with something in it lights up, the way an active item does in the
   panel. */
.nav-icon.has-dot{--acc:var(--acc-gold)}
.nav-icon.has-dot::before{box-shadow:0 0 16px -4px var(--acc-gold)}

/* The badge rides above the diamond and stays a hard little block. */
.nav-dot{
  z-index:3;border:1px solid #050505;
  font-size:10px;font-weight:800;letter-spacing:0}

/* ----------------------------------------------------------- SCRAP PILL
   Correcting an earlier call of mine: I put .nav-coin in the round allowlist,
   but the game has no pills. Its player-count bar has ANGLED ends, so this
   takes the same cut. */
.nav-coin{
  border:1px solid var(--gx-line);background:rgba(0,0,0,.35);
  clip-path:polygon(9px 0,100% 0,calc(100% - 9px) 100%,0 100%)}
.nav-coin b{letter-spacing:.04em}

/* ------------------------------------------------------------ USER CHIP */
.nav-me,.nav-user{
  border:1px solid var(--gx-line);background:rgba(0,0,0,.35);
  clip-path:polygon(10px 0,100% 0,100% calc(100% - 10px),
                    calc(100% - 10px) 100%,0 100%,0 10px)}
.nav-me-t b,.nav-me-t strong{letter-spacing:.03em}

/* ------------------------------------------------------------- DROPDOWN
   A panel, with the same bracket as every other surface. */
/* NO position here. Both of these are ALREADY positioned - .nav-drop-menu is
   absolute and .nav-panel is absolute - so they can host an absolute child as
   they are. Setting position:relative overrode the menu back into normal flow,
   which made .nav-drop 362px tall instead of 34px, inflated the whole navbar
   and dropped the menu hundreds of pixels down the page. */
.nav-drop-menu,.nav-panel{
  border:1px solid var(--gx-line);
  box-shadow:0 18px 50px -12px rgba(0,0,0,.8)}
.nav-drop-menu::after{
  content:"";position:absolute;top:6px;left:6px;width:12px;height:12px;
  border-top:1px solid var(--gx-line);border-left:1px solid var(--gx-line);
  pointer-events:none}
.nav-menu-item{letter-spacing:.04em}

/* --------------------------------------------------------------- BURGER */
.nav-burger{border:1px solid var(--gx-line);background:rgba(0,0,0,.35)}
.nav-burger:hover{border-color:var(--acc-gold)}

/* The diamond frame is a lot at phone size, where the icons sit shoulder to
   shoulder. Below 560 they go back to a plain hairline square. */
@media (max-width:560px){
  .nav-icon::before{transform:none;inset:2px}
  .nav-in::before,.nav-in::after{display:none}
}

/* ============================================================================
   GAME UI PASS - WAVE 6: THE DASHBOARD KPIs AS DIAMONDS
   ----------------------------------------------------------------------------
   The panel puts a value inside a rhombus - "1 / Online", "VIP / 4 tiers" -
   and the four dashboard stats are exactly that shape of content.

   Read the markup first this time. It is:
       .db-kpis > div > (span label, b number)
   laid out as a 4-column grid using the gap:1px + background:var(--line)
   hairline trick. THAT TRICK HAS TO GO: it draws its dividers by letting the
   parent background show through a 1px gap, and diamonds cannot share an edge.
   ========================================================================= */

.db-kpis{
  grid-template-columns:repeat(4,1fr);
  gap:12px;
  background:transparent;   /* was var(--line), which drew the hairline grid */
  padding:4px 0}

.db-kpis > div{
  --acc:var(--acc-gold);
  position:relative;
  aspect-ratio:1;
  background:transparent;   /* the fill moves to ::before, which is clipped */
  padding:0;
  display:grid;
  place-items:center;
  align-content:center;
  gap:2px;
  /* A grid item defaults to min-width:auto, so it refuses to shrink below its
     content and 1fr never really constrains it - the tiles rendered 127px wide
     in a 107px column and .db-strip (overflow:hidden) sliced the last one. */
  min-width:0;min-height:0}

.db-kpis > div::before{
  content:"";position:absolute;inset:0;z-index:0;
  background:rgba(0,0,0,.42);
  border:1px solid var(--acc);
  clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%);
  transition:box-shadow .18s,background .18s}

.db-kpis > div:hover::before{
  background:rgba(0,0,0,.2);
  box-shadow:0 0 28px -6px var(--acc)}

/* A DIAMOND'S SAFE AREA IS ITS MIDDLE. Anything wider than roughly two thirds
   of the box pokes out through the points, so the text is capped and allowed
   to wrap rather than being left to overflow. */
.db-kpis > div > *{
  position:relative;z-index:1;max-width:68%;
  overflow-wrap:anywhere;line-height:1.2}

.db-kpis span{
  font-size:8.5px;letter-spacing:.16em;color:var(--mute);margin:0}
.db-kpis b{
  font-size:clamp(15px,1.5vw,21px);color:var(--acc)}
.db-kpis i{font-size:11px;color:var(--mute)}

/* One colour each, the way every item in the game panel carries its own. */
.db-kpis > div:nth-child(1){--acc:var(--acc-gold)}
.db-kpis > div:nth-child(2){--acc:var(--acc-rose)}
.db-kpis > div:nth-child(3){--acc:var(--acc-green)}
.db-kpis > div:nth-child(4){--acc:var(--acc-blue)}

/* Four diamonds across a phone would be thumbnails. Two up, two down. */
@media (max-width:640px){
  .db-kpis{grid-template-columns:repeat(2,1fr);gap:10px}
}

/* ============================================================================
   GAME UI PASS - WAVE 7: MORE BLOOM
   ----------------------------------------------------------------------------
   The shapes are right; this is the light. The in-game panel glows - the centre
   diamond has real bloom behind it and the active item burns brighter than the
   rest. Flat gold on flat black reads as a mockup; lit gold reads as a screen.

   Three moves, in order of how much they change the feel:
     1. Focal numbers glow. The big figure is the point of every tile.
     2. Bars take the angled ends and a lit fill, like the player-count bar.
     3. Everything answers the cursor - accent, glow, and the corner brackets.

   .sh-bar is NOT in the bar list: it is a flex toolbar, not a meter. Read
   before styling.
   ========================================================================= */

/* ---------------------------------------------------------- 1. LIT NUMBERS
   Two shadows, not one: a tight bright core and a wide soft halo. A single
   large blur just looks blurry. */
.db-kpis b,
.hero-stat b,
.lb-pod-score,
.gx-dia b{
  text-shadow:
    0 0 8px  color-mix(in srgb,var(--acc,var(--acc-gold)) 55%,transparent),
    0 0 26px color-mix(in srgb,var(--acc,var(--acc-gold)) 30%,transparent)}

/* The wordmark carries the most light on the page, because it is the name. */
.hero h1,.hero-title{
  text-shadow:
    0 0 14px rgba(251,211,128,.35),
    0 0 60px rgba(251,211,128,.18)}

/* ------------------------------------------------------------- 2. THE BARS
   The game's player-count bar has ANGLED ENDS and a fill that glows. Every
   meter on the site now reads the same way.

   The fills keep whatever colour they already had - most carry it on --m or
   inherit it - so this lights them without repainting them. */
.row-bar,.pf-bar,.ah-bar,.ah-bar-track,.cl-bar,.ow-bar,
.mv-bar,.om-bar,.ot-bar,.auth-bar,.ah-meter{
  clip-path:polygon(4px 0,100% 0,calc(100% - 4px) 100%,0 100%);
  background:rgba(255,255,255,.06)}

.pf-bar > i,.ah-bar > i,.cl-bar > i,.ow-bar > i,
.mv-bar > i,.om-bar > i,.ot-bar > i,.auth-bar > i,.lb-tr-fill{
  box-shadow:0 0 12px -2px currentColor;
  filter:saturate(1.15)}

/* The capacity fills carry their colour on --m, so light that specifically or
   the glow would default to gold under a green bar. */
.row-bar > i{box-shadow:0 0 12px -2px var(--m,var(--acc-gold));filter:saturate(1.15)}

/* ------------------------------------------------------- 3. ANSWER THE CURSOR
   Every card was static. Now the accent it already owns lights up when you
   point at it - which is what makes a panel feel like software rather than a
   picture of software. */
.srv,.sh-card,.pillar,.lfg-card,.nw-card,.ow-card,.ev,.gx-card{
  transition:border-color .18s,box-shadow .18s}
.srv:hover,.sh-card:hover,.pillar:hover,.lfg-card:hover,
.nw-card:hover,.ow-card:hover,.ev:hover,.gx-card:hover{
  border-color:color-mix(in srgb,var(--acc,var(--acc-gold)) 55%,transparent);
  box-shadow:0 0 34px -16px var(--acc,var(--acc-gold))}

/* The bracket on a panel brightens with it. */
.lb-panel:hover::after,.lb-widget:hover::after,.dash-card:hover::after,
.sh-server:hover::after,.ow-card:hover::after,.pillar:hover::after,
.db-wallet:hover::after{border-color:var(--gold-bright)}

/* Notification rows light their own category colour. */
.nt-row{transition:border-color .18s,box-shadow .18s}
.nt-row:hover{box-shadow:0 0 26px -16px var(--acc,var(--acc-gold))}

/* ------------------------------------------------------------ 4. THE PODIUM
   First place should look like first place. The metals are already tokens on
   this site, so they light rather than get replaced. */
.lb-pod-first{position:relative}
.lb-pod-gold{--acc:var(--gold-bright)}
.lb-pod-silver{--acc:var(--silver)}
.lb-pod-bronze{--acc:var(--bronze)}

.lb-pod-gold,.lb-pod-silver,.lb-pod-bronze{
  border-color:color-mix(in srgb,var(--acc) 45%,transparent)}
.lb-pod-gold{box-shadow:0 0 60px -26px var(--gold-bright)}

.lb-pod-crown{filter:drop-shadow(0 0 10px rgba(251,211,128,.75))}

.lb-pod-place{
  border:1px solid color-mix(in srgb,var(--acc,var(--acc-gold)) 55%,transparent);
  letter-spacing:.06em;font-weight:900}

/* ----------------------------------------------------- 5. THE LATTICE DRIFTS
   Barely. Two crossed gradients sliding one tile over a minute reads as depth
   rather than as animation - you notice it only if you look for it.

   background-position only, never transform, so it cannot promote a layer or
   fight the scroll. */
@keyframes gx-drift{to{background-position:78px 78px,-78px 78px}}
section::before{animation:gx-drift 60s linear infinite}

/* Somebody who asked for less motion gets a still lattice. */
@media (prefers-reduced-motion:reduce){
  section::before{animation:none}
}

/* ------------------------------------------------------ 6. SECTION HEADINGS
   The eyebrow gets the hairline the panel puts under its labels, so a heading
   reads as a titled section rather than loose text. */
.sec-head .eyebrow,.lb-kicker{
  display:inline-block;padding-bottom:6px;
  border-bottom:1px solid var(--gx-line)}

/* -------------------------------------------------------- 7. PRIMARY BUTTON
   The one loud control in the panel, and it should look switched on. */
.btn-p{box-shadow:0 0 22px -10px var(--gold-bright)}
.btn-p:hover{box-shadow:0 0 30px -8px var(--gold-bright)}

/* ============================================================================
   GAME UI PASS - WAVE 8: THE REVEAL
   ----------------------------------------------------------------------------
   Two effects, both riding the reveal machinery that already exists. app.js
   adds `.in` to any `.rv` element as it enters view, with a 2500ms failsafe
   that reveals everything regardless - so nothing here can leave content stuck
   invisible, which is the only real risk in an animated reveal.

   WHY NOT A clip-path WIPE ON .rv. Half the cards on this site already carry a
   clip-path for their cut corners - .srv, .sh-card, .dash-card and the rest.
   clip-path is one property: a wipe would REPLACE the chamfer and the card
   would keep the wipe shape for ever. And a mask-image wipe clips box-shadow
   to the border box, which would kill every hover glow added in wave 7.

   So the diamond wipe animates the DIAMOND PSEUDO-ELEMENT this stylesheet
   already owns. Nothing to collide with.
   ========================================================================= */

/* ------------------------------------------------- 1. THE DIAMOND GROWS IN
   A CSS ANIMATION, not a .rv reveal.

   I first hung this on .rv and measured the result: the tiles ended up with
   class "rv in" and opacity 0 anyway - the reveal does not land on this page,
   and every KPI was invisible. An effect must never be able to hide content,
   so it no longer depends on JavaScript at all.

   `both` holds the final frame, and the global reduced-motion rule
   (*{animation:none!important}) drops the whole thing to the natural state,
   which is the finished one because the base rule sets no transform. */
/* NO fill-mode, deliberately. `both` holds the invisible FIRST frame, and a
   suspended compositor - a background tab, a minimised window - never advances
   it, so the numbers stay at zero opacity indefinitely. Exactly the hazard the
   header of app.js documents for rAF. Without a fill mode the base style is the
   FINISHED one: the animation is decoration that plays when it can, and content
   is visible whether it runs or not. */
@keyframes gx-dia-in{
  from{transform:scale(.15);opacity:0}
  to  {transform:scale(1);opacity:1}}
@keyframes gx-dia-txt{
  from{opacity:0;transform:translateY(6px)}
  to  {opacity:1;transform:none}}

.db-kpis > div::before{animation:gx-dia-in .55s cubic-bezier(.2,.8,.2,1)}
.db-kpis > div > *{animation:gx-dia-txt .45s ease}

/* Four landing at once is a flash; in sequence it is an animation. */
.db-kpis > div:nth-child(2)::before{animation-delay:.07s}
.db-kpis > div:nth-child(3)::before{animation-delay:.14s}
.db-kpis > div:nth-child(4)::before{animation-delay:.21s}
.db-kpis > div:nth-child(2) > *{animation-delay:.25s}
.db-kpis > div:nth-child(3) > *{animation-delay:.32s}
.db-kpis > div:nth-child(4) > *{animation-delay:.39s}

/* ------------------------------------------------- 2. A DIAGONAL RISE
   The existing reveal lifts straight up. On a layout built out of diamonds and
   a 45-degree lattice, arriving ALONG that diagonal reads as the same object.

   Only the transform changes - opacity, timing and the .in hook are all the
   original, so the failsafe still works exactly as before. */
.rv{transform:translate3d(6px,20px,0)}
.rv.in{transform:none}

/* Cards in a row arrive one after another rather than as a block. */
.srv-list > .rv:nth-child(2),.pillars > .rv:nth-child(2){transition-delay:.08s}
.srv-list > .rv:nth-child(3),.pillars > .rv:nth-child(3){transition-delay:.16s}
.srv-list > .rv:nth-child(4),.pillars > .rv:nth-child(4){transition-delay:.24s}

/* ------------------------------------------------------- 3. REDUCED MOTION
   Everything final, immediately. The site already honours this for embers,
   reveals and counters; these must not become the exception. */
@media (prefers-reduced-motion:reduce){
  .rv,.rv.in{transform:none}
  .db-kpis > div.rv::before,
  .db-kpis > div.rv.in::before{transform:scale(1);opacity:1;transition:none}
  .db-kpis > div.rv > *,
  .db-kpis > div.rv.in > *{opacity:1;transform:none;transition:none}
  .srv-list > .rv,.pillars > .rv{transition-delay:0s}
}

/* -------------------------------------------------- CASES: the fairness log
   Collapsed by default. It is the provable-fairness record, so it stays
   reachable - it just stops being the tallest thing on the page. */
.cs-hist{padding:0;overflow:hidden}
.cs-hist-sum{
  display:flex;align-items:center;gap:10px;cursor:pointer;list-style:none;
  padding:14px 18px;font-weight:800;letter-spacing:.06em;font-size:13px;
  color:var(--gold-bright);transition:background .15s}
.cs-hist-sum::-webkit-details-marker{display:none}
.cs-hist-sum:hover{background:rgba(251,211,128,.05)}
.cs-hist-sum b{
  border:1px solid var(--gx-line);padding:1px 8px;font-size:11px;color:var(--bone)}
.cs-hist-sum i{
  font-style:normal;font-size:11px;color:var(--dim);letter-spacing:.1em;
  margin-inline-start:auto}
/* A long history scrolls inside the panel rather than stretching the page. */
.cs-hist-list{max-height:340px;overflow-y:auto;padding:0 18px 14px;
  border-top:1px solid rgba(255,255,255,.05)}
.cs-hist[open] .cs-hist-sum{border-bottom:1px solid rgba(255,255,255,.05)}

/* A teammate the game has not confirmed lately: not online, not proven
   offline. A hollow ring says "no answer" where grey would claim they left. */
.db-member-dot.unk{background:transparent;border:1px solid var(--line2);box-shadow:none}

/* ---------------------------------------------------------------- bases
   Your cupboards. The grid sits in its own block because it is the thing a
   player scans for - "which base is this" - and the countdown is what they
   read second. .low tints the row against THAT PLAYER'S OWN threshold, so two
   people authorised on one cupboard can honestly see different urgency. */
.db-bases{display:flex;flex-direction:column;gap:6px}
.db-base{display:flex;align-items:center;gap:10px;padding:9px 11px;
  border:1px solid var(--line2);background:rgba(255,255,255,.02)}
.db-base.low{border-color:rgba(232,134,46,.5);background:rgba(232,134,46,.08)}
.db-base-grid{flex:none;min-width:44px;text-align:center;font-weight:900;
  font-size:13px;padding:4px 6px;border:1px solid var(--line2);color:var(--gold-bright)}
.db-base.low .db-base-grid{border-color:rgba(232,134,46,.55);color:var(--acc-orange)}
.db-base-mid{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.db-base-mid b{font-size:13px}
.db-base-sub{font-size:10px;color:var(--dim)}
.db-base-flag{flex:none;font-size:10px;font-weight:800;letter-spacing:.04em;
  padding:3px 8px;border:1px solid rgba(232,134,46,.55);color:var(--acc-orange)}

/* the upkeep threshold select, in the notification settings list */
.ns-select{background:var(--bg2);color:var(--fg);border:1px solid var(--line2);
  padding:6px 10px;font:inherit;font-size:12px}
.ns-note{font-size:11px;color:var(--dim);line-height:1.9;margin-top:8px}

/* ------------------------------------------------------------- step 9 logs
   Three histories, all read at a glance rather than studied: the verb comes
   first on a death row, the thing destroyed first on a raid row. */
.db-deaths,.db-raidlog{display:flex;flex-direction:column;gap:5px}
.db-death,.db-raidrow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  padding:7px 10px;border:1px solid var(--line2);font-size:12px}
.db-death-verb{flex:none;font-weight:800;font-size:10px;letter-spacing:.04em;
  padding:2px 7px;border:1px solid rgba(232,84,110,.5);color:var(--acc-rose)}
.db-death.win .db-death-verb{border-color:rgba(63,191,111,.5);color:var(--acc-green)}
.db-death-who{flex:1;min-width:0}
.db-death-weap{font-size:10px;color:var(--dim);border:1px solid var(--line2);padding:2px 6px}
.db-raidrow-what{flex:none;font-weight:800;color:var(--acc-orange)}
.db-raidrow-by{flex:1;min-width:0;color:var(--dim)}
.db-tlog{display:flex;flex-direction:column;gap:3px;margin-top:9px}
.db-tlog-row{display:flex;align-items:center;gap:7px;font-size:11px;color:var(--dim)}
.db-tlog-dot{width:5px;height:5px;border-radius:50%;background:var(--live);flex:none}
.db-tlog-dot.out{background:var(--line2)}

/* the LFG edit fold: closed by default so the applicant queue stays visible */
.lfg-edit{margin:12px 0 4px}
.lfg-edit-sum{cursor:pointer;font-size:12px;font-weight:700;color:var(--dim);
  padding:7px 11px;border:1px solid var(--line2);list-style:none}
.lfg-edit-sum::-webkit-details-marker{display:none}
.lfg-edit-sum:hover{color:var(--fg);border-color:var(--gold-bright)}
.lfg-edit[open] .lfg-edit-sum{margin-bottom:10px;color:var(--fg)}

/* ---------------------------------------------------- discount codes
   A code is a row you scan, not a form you read: the code and its percent
   come first, the badge says whether it would actually work right now, and
   the eight settings live behind a fold. */
.oc-badge{flex:none;font-size:10px;font-weight:800;letter-spacing:.04em;
  padding:2px 8px;border:1px solid var(--line2);color:var(--dim)}
.oc-badge.on{border-color:rgba(63,191,111,.55);color:var(--acc-green)}
.oc-edit{margin:0 0 10px}
.oc-edit-sum{cursor:pointer;font-size:11px;color:var(--dim);padding:6px 10px;
  border:1px solid var(--line2);list-style:none}
.oc-edit-sum::-webkit-details-marker{display:none}
.oc-edit-sum:hover{color:var(--fg);border-color:var(--gold-bright)}
.oc-edit[open] .oc-edit-sum{margin-bottom:10px;color:var(--fg)}

/* the clan chat box: one line in, one button beside it */
.cp-chat{display:flex;gap:8px;align-items:center}
.cp-chat .owner-input{flex:1;min-width:0}

/* ============================================================================
   GAME UI PASS - WAVE 9: THE OWNER PANEL
   ----------------------------------------------------------------------------
   The player side got the whole treatment in waves 1-8. The owner panel got the
   FLATTENING and nothing else: `*{border-radius:0 !important}` stripped every
   14px/11px/10px radius its CSS still asks for, and put nothing in their place.
   The result is what the owner described - flat grey rectangles.

   Wave 5 chamfered exactly four owner selectors (.owner-group, .owner-pre,
   .ow-kpi, .os-count). Every sub-page is actually built from .ow-card, .od-tile,
   .od-row, .op-row, .ow-nav-i and .owner-input, none of which were touched.
   This is that omission fixed.

   NOTHING NEW IS INVENTED HERE. Same chamfer geometry, same --acc-* accents and
   the same hairline rules the player pages already use, so the panel reads as
   the same product rather than as a second design.

   ONE DELIBERATE DIFFERENCE. The lattice, the big display type and the diamonds
   stay on the player side. This is a workbench: it is read for ten minutes at a
   time by somebody looking for a number, and texture behind a table of payments
   is noise. What it takes from the game is the SHAPE and the accent, not the
   decoration.
   ========================================================================= */

/* --------------------------------------------------------- 1. THE PANEL
   .ow-card is the box every sub-page is made of, so this one rule is most of
   the difference. Chamfer plus a hairline accent along the top, which is what
   the game's panels do and what .srv already does on the servers page. */
.ow-card{
  --acc:var(--acc-gold);
  position:relative;
  background:var(--panel);
  border:1px solid var(--line2);
  clip-path:polygon(14px 0,100% 0,100% calc(100% - 14px),
                    calc(100% - 14px) 100%,0 100%,0 14px);
  transition:border-color .18s,box-shadow .18s}

.ow-card::before{
  content:"";position:absolute;top:0;left:0;right:0;height:1px;
  background:linear-gradient(90deg,transparent,var(--acc),transparent);
  opacity:.5;z-index:3;pointer-events:none;transition:opacity .18s}

.ow-card:hover{border-color:rgba(251,211,128,.28)}
.ow-card:hover::before{opacity:1}

/* The card header becomes a labelled edge rather than a floating heading. */
.ow-card-h{
  border-bottom:1px solid var(--line2);
  padding-bottom:11px;margin-bottom:14px}
.ow-card-h h2{
  font-size:11px;font-weight:800;letter-spacing:.22em;text-transform:uppercase;
  color:var(--mute)}

/* A card carrying something wrong is orange, not red - red is the site's
   "money failed" colour and a staff warning is not that. */
.ow-card.owner-danger,.owner-group.owner-danger{--acc:var(--acc-orange)}
.ow-card.owner-danger{border-color:rgba(232,134,46,.42)}

/* ------------------------------------------------------------ 2. THE HERO */
.ow-hero{
  position:relative;
  clip-path:polygon(20px 0,100% 0,100% calc(100% - 20px),
                    calc(100% - 20px) 100%,0 100%,0 20px)}
.ow-hero-in{position:relative;z-index:2}
.ow-hero h1{letter-spacing:-.01em}

/* The eyebrow above a page title, matching .gx-eyebrow on the player side. */
.ow-main .eyebrow{
  font-size:10px;font-weight:700;letter-spacing:.34em;text-transform:uppercase;
  color:var(--dim)}
.ow-main .sec-head h2{
  font-family:var(--ui);font-weight:900;letter-spacing:-.01em}
.ow-main .lede{color:var(--mute);line-height:1.85;max-width:70ch}

/* --------------------------------------------------------- 3. THE SIDEBAR
   The nav item picks up the angled selected state from the game's menus: a
   solid accent edge on the leading side rather than a filled pill. */
.ow-side{
  border-inline-end:1px solid var(--line2);
  background:linear-gradient(180deg,rgba(251,211,128,.03),transparent 220px)}

.ow-nav-i{
  position:relative;
  border-inline-start:2px solid transparent;
  transition:background .16s,color .16s,border-color .16s}

.ow-nav-i:hover{border-inline-start-color:rgba(251,211,128,.35)}

.ow-nav-i.on{
  border-inline-start-color:var(--acc-gold);
  background:linear-gradient(90deg,rgba(251,211,128,.10),transparent 70%)}

.ow-nav-g{border-top-color:var(--line)}

/* ------------------------------------------------------------- 4. TILES */
.od-tile{
  position:relative;
  clip-path:polygon(10px 0,100% 0,100% calc(100% - 10px),
                    calc(100% - 10px) 100%,0 100%,0 10px);
  transition:border-color .18s,background .18s}
.od-tile:hover{border-color:rgba(251,211,128,.3)}
.od-k{letter-spacing:.1em;text-transform:uppercase;font-weight:700}
.od-tile.od-hl{background:rgba(251,211,128,.05)}

/* The attention rows read as severity, so they keep their own colours and
   only gain the shape. */
.od-attn-row{
  clip-path:polygon(10px 0,100% 0,100% calc(100% - 10px),
                    calc(100% - 10px) 100%,0 100%,0 10px)}

/* -------------------------------------------------------------- 5. ROWS
   A list row gets a leading accent bar on hover instead of a background wash.
   It marks the row being pointed at without repainting half the panel, which
   is what keeps a long table readable. */
.od-row{
  position:relative;padding-inline-start:12px;
  border-bottom:1px solid var(--line);
  transition:background .14s}
.od-row::before{
  content:"";position:absolute;inset-block:0;inset-inline-start:0;width:2px;
  background:var(--acc-gold);opacity:0;transition:opacity .14s}
.od-row:hover{background:rgba(255,255,255,.02)}
.od-row:hover::before{opacity:.85}
.od-row:last-child{border-bottom:0}
.od-row-main b{color:var(--bone)}

.op-row{
  position:relative;
  border:1px solid transparent;
  clip-path:polygon(9px 0,100% 0,100% calc(100% - 9px),
                    calc(100% - 9px) 100%,0 100%,0 9px);
  transition:background .14s,border-color .14s}
.op-row:hover{border-color:rgba(251,211,128,.26)}

/* ------------------------------------------------------------ 6. TABLES
   Owner tables are read in columns, so the header is what needs the work. */
.op-table{width:100%;border-collapse:collapse;font-size:12.5px}
.op-table th{
  text-align:start;padding:9px 10px;
  font-size:10px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;
  color:var(--dim);border-bottom:1px solid var(--line2);white-space:nowrap}
.op-table td{padding:10px;border-bottom:1px solid var(--line);color:var(--mute)}
.op-table tr:last-child td{border-bottom:0}
.op-table tbody tr{transition:background .14s}
.op-table tbody tr:hover{background:rgba(255,255,255,.02)}

/* ------------------------------------------------------------- 7. FORMS
   Inputs are chamfered on the leading corner only. A four-corner cut on a
   40px-tall field eats the text; one corner is enough to say "same family". */
.owner-input,.ow-main select,.ow-main textarea{
  clip-path:polygon(8px 0,100% 0,100% 100%,0 100%,0 8px);
  border-color:var(--line2);
  transition:border-color .16s,box-shadow .16s,background .16s}

.owner-input:focus,.ow-main select:focus,.ow-main textarea:focus{
  border-color:var(--acc-gold);
  box-shadow:0 0 0 1px rgba(251,211,128,.16),0 0 22px -10px var(--acc-gold);
  background:rgba(255,255,255,.05)}

.owner-field > span,.owner-field label{
  font-size:11px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;
  color:var(--mute)}
.owner-field small,.owner-help{color:var(--dim);text-transform:none;letter-spacing:normal}

/* A disabled control here means "your login is too old", which is a state
   worth looking deliberate rather than broken. */
.owner-input:disabled,.ow-main button:disabled{
  opacity:.4;cursor:not-allowed;filter:grayscale(.4)}

/* --------------------------------------------------------- 8. THE EMPTIES
   Every owner page has at least one, and on a quiet day they are the panel's
   most common state. They were the plainest thing on it. */
.ow-main .empty{
  border:1px dashed var(--line2);
  color:var(--dim);font-size:12.5px;letter-spacing:.02em;
  padding:22px 16px}

/* --------------------------------------------------------- 9. THE NOTICES */
.ow-main .notice{
  clip-path:polygon(10px 0,100% 0,100% calc(100% - 10px),
                    calc(100% - 10px) 100%,0 100%,0 10px)}

/* -------------------------------------------------------- 10. SMALL PRINT
   Figures line up in a column of money. */
.ow-main .num{font-variant-numeric:tabular-nums}

/* ============================================================================
   WAVE 9b: THE OWNER PANEL - LAYOUT, NOT DECORATION
   ----------------------------------------------------------------------------
   Wave 9a styled the panel. Looking at it rendered showed the real complaint was
   never colour: the pages are enormous. Three structural causes, measured in the
   browser rather than guessed:

   1. THE 260px SEARCH BOX. Both the players and payments pages borrow
      `.lb-search` from the leaderboard. That rule is `flex:0 1 260px`, written
      for a horizontal toolbar where 260px is a WIDTH. `.ow-main` is
      `flex-direction:column`, so the basis lands on the HEIGHT instead and the
      field grows to a 260px-tall slab. Measured: 1008x260.

   2. NOTHING IS WIDTH-CONSTRAINED. A settings form stretched across a 1600px
      monitor puts its label at one edge and its input at the other. That is the
      "so big" - not the type size, the measure.

   3. `.ow-main` IS A FULL-HEIGHT COLUMN, so any child carrying a flex-grow or a
      basis from another context stretches down the page.

   Fixing the geometry first; the decoration in 9a only reads correctly once the
   boxes are the right size.
   ========================================================================= */

/* ------------------------------------------------- 1. STOP THE STRETCHING
   Nothing in this column grows. A child that wants to is a child borrowing a
   rule from a row somewhere else, which is exactly how the search box happened. */
.ow-main > *{flex:none}

/* The borrowed leaderboard search, put back to a normal field. Scoped to the
   panel so the leaderboard's own toolbar is untouched. */
.ow-main .lb-search{flex:none;max-width:520px;margin-bottom:0}
.ow-main .lb-search .owner-input{flex:1 1 auto;min-width:0}

/* ------------------------------------------------------- 2. A READING WIDTH
   The panel is a workbench, but a workbench still has a measure. Wide things -
   tables, rosters, the KPI strip - keep the full width; everything else stops
   where it stays readable. */
.ow-main{max-width:1280px;width:100%}
.ow-main .sec-head,.ow-main .notice{max-width:960px}
.ow-main .op-form,.ow-main form.op-form{max-width:100%}

/* ------------------------------------------------------------- 3. THE FORMS
   Fields go in a grid rather than one per line. Eight stacked full-width inputs
   is what made the discount screen a mile long. */
.op-form{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
  gap:14px 18px;
  align-items:start}

/* A field is label + control + hint, stacked, and it owns its own column. */
.op-form .owner-field{margin:0;display:flex;flex-direction:column;gap:6px}
.op-form .owner-field > span{margin:0}
.op-form .owner-field small{margin:0}

/* The wide ones - a body of text, a full-width note - take the whole row. */
.op-form textarea,.op-form .owner-field.is-wide{grid-column:1 / -1}
.op-form .owner-field:has(textarea){grid-column:1 / -1}

/* The submit sits on its own line, at the start, not floating mid-grid. */
.op-form > button,.op-form > p:last-child{grid-column:1 / -1;justify-self:start;margin:0}

/* A field outside a form grid still should not span a monitor. */
.ow-main .owner-field{max-width:520px}
.op-form .owner-field{max-width:none}

/* --------------------------------------------------------- 4. THE CONTROLS
   40px is a control; 60px is a slab. The panel had no height rule at all, so
   every input inherited whatever its container felt like. */
.owner-input,.ow-main select{min-height:38px;height:38px;padding:0 12px;font-size:13px}
.ow-main textarea.owner-input{height:auto;min-height:120px;padding:10px 12px;line-height:1.8}
.ow-main input[type="search"].owner-input{height:38px}

/* ------------------------------------------------------------ 5. THE TABLE
   Long tables are the panel's real content. They scroll inside their own box
   rather than pushing the page sideways, and the rows are tightened. */
.ow-main .owner-group:has(> .op-table),.ow-main .ow-card:has(> .op-table){overflow-x:auto}
.op-table{min-width:640px}
.op-table th,.op-table td{padding:8px 10px;white-space:nowrap}
.op-table td:first-child,.op-table th:first-child{padding-inline-start:2px}
/* The trailing actions column should not claim a share of the width. */
.op-table th:last-child,.op-table td:last-child{width:1%;white-space:nowrap}

/* --------------------------------------------------------- 6. THE KPI STRIP
   Tighter, and it stops being four enormous squares on a wide screen. */
.ow-kpis,.od-grid{grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:10px}
.ow-kpi,.od-tile{padding:12px 13px}
.od-v,.ow-kpi-v{font-size:19px;line-height:1.15}

/* --------------------------------------------------------------- 7. GAPS
   18px between every block on a page with ten blocks is 180px of nothing. */
.ow-main{gap:14px;padding:20px 22px 56px}
.ow-card,.owner-group{padding:15px 16px}

/* ============================================================================
   WAVE 9c: ONE OWNER PANEL, NOT TWO
   ----------------------------------------------------------------------------
   Two things were still wrong after 9b fixed the geometry.

   1. THE PANEL IS BUILT FROM TWO DIFFERENT BOXES. `.ow-card` on 9 pages,
      `.owner-group` on 13, and they are not the same object: different border
      colour, different padding, different heading, one chamfered at 12px and
      one at 14px, only one of them carrying the accent hairline 9a added.
      Walking from payments to codes changed design system halfway. They are
      the same thing and from here they render the same.

   2. LATIN TYPOGRAPHY ON PERSIAN TEXT. Wave 9a set `text-transform:uppercase`
      and `letter-spacing:.22em` on card headings, table headers and field
      labels. That is the right treatment for an English micro-label and the
      wrong one here: uppercase does nothing in Persian, and tracking pulls
      joined letterforms apart. That is the "lazy" look - a template applied
      without looking at what was inside it. Headings get a gold tick instead,
      which says the same thing without touching the letterforms.

   Everything else here is compaction. A workbench page is read for ten minutes
   by somebody looking for one number; the job is to fit more of it on screen.
   ========================================================================= */

/* ------------------------------------------------------- 1. ONE PANEL BOX
   .owner-group inherits everything .ow-card got in wave 9a. */
.ow-card,.owner-group{
  --acc:var(--acc-gold);
  position:relative;
  background:var(--panel);
  border:1px solid var(--line2);
  padding:15px 16px;
  clip-path:polygon(14px 0,100% 0,100% calc(100% - 14px),
                    calc(100% - 14px) 100%,0 100%,0 14px);
  transition:border-color .18s,box-shadow .18s}

.ow-card::before,.owner-group::before{
  content:"";position:absolute;top:0;left:0;right:0;height:1px;
  background:linear-gradient(90deg,transparent,var(--acc),transparent);
  opacity:.5;z-index:3;pointer-events:none;transition:opacity .18s}

.ow-card:hover,.owner-group:hover{border-color:rgba(251,211,128,.28)}
.ow-card:hover::before,.owner-group:hover::before{opacity:1}

/* The corner bracket .ow-card already had, so the two read as one object. */
.owner-group::after{
  content:"";position:absolute;top:6px;left:6px;width:14px;height:14px;
  border-top:1px solid var(--gx-line);border-left:1px solid var(--gx-line);
  pointer-events:none;z-index:2}

/* Trouble is orange here, not red: red is what a failed payment looks like on
   this site, and a staff warning is not that. */
.owner-group.owner-danger{border-color:rgba(232,134,46,.42)}
.owner-danger .owner-group-title{color:var(--acc-orange)}
.owner-danger .owner-group-title::before{background:var(--acc-orange)}

/* --------------------------------------------------- 2. ONE PANEL HEADING
   Persian takes its weight from size and colour, not from being tracked
   apart. The gold tick is what carries "this is a section label". */
.ow-card-h,.owner-group-title{
  display:flex;align-items:center;gap:10px;
  border-bottom:1px solid var(--line2);
  padding-bottom:10px;margin:0 0 13px}

.ow-card-h{justify-content:flex-start}

.ow-card-h h2,.owner-group-title{
  font-family:var(--ui);font-size:13.5px;font-weight:800;
  letter-spacing:0;text-transform:none;color:var(--bone)}
.ow-card-h h2{margin:0;display:flex;align-items:center}

.ow-card-h h2::before,.owner-group-title::before{
  content:"";flex:none;width:3px;height:14px;background:var(--acc-gold);
  margin-inline-end:9px;display:inline-block;vertical-align:-2px}

/* Whatever sits after the heading - a count, a link out - goes to the far end. */
.ow-card-h > :not(h2):last-child,
.owner-group-title > span:last-child{margin-inline-start:auto}
.ow-card-h .dim,.owner-group-title .dim{font-size:11.5px;font-weight:600}

/* ---------------------------------------------- 3. UNDO 9a's LATIN LABELS */
.op-table th,.owner-field > span,.owner-field label,.od-k,.ow-kpi-k{
  letter-spacing:0;text-transform:none}
.op-table th{font-size:11.5px;font-weight:700;color:var(--dim)}
.owner-field > span,.owner-field label{font-size:12.5px;font-weight:700;color:var(--mute)}

/* ------------------------------------------------------ 4. THE PAGE TITLE
   Every sub-page opened with a hero-sized heading over a three-line
   paragraph, which is a quarter of the screen before the first control. It
   becomes a title bar: it still says what the page is and stops pretending to
   be a landing page. The vertical accent rule belongs to the player pages. */
.ow-main .sec-head{
  max-width:none;margin:0;padding:0 0 13px;
  border-bottom:1px solid var(--line2)}
.ow-main .sec-head::before{display:none}
.ow-main .sec-head .eyebrow{margin:0 0 5px}
.ow-main .sec-head h2{font-size:21px;line-height:1.2;margin:0}
.ow-main .sec-head .lede{
  font-size:12.5px;line-height:1.8;color:var(--dim);
  margin:7px 0 0;max-width:90ch}

/* ---------------------------------------------------------- 5. LIST ROWS
   Five row classes across the panel (.od-row .op-row .os-row .oc-row .om-row)
   with five paddings and no hover between them. One row from here. */
.ow-main .od-row,.ow-main .os-row,.ow-main .oc-row,.ow-main .om-row{
  position:relative;
  padding:11px 12px;margin:0;gap:12px;
  border-bottom:1px solid var(--line);border-top:0;
  transition:background .14s}
.ow-main .od-row:last-of-type,.ow-main .os-row:last-of-type,
.ow-main .oc-row:last-of-type,.ow-main .om-row:last-of-type{border-bottom:0}

.ow-main .od-row::before,.ow-main .os-row::before,
.ow-main .oc-row::before,.ow-main .om-row::before{
  content:"";position:absolute;inset-block:0;inset-inline-start:0;width:2px;
  background:var(--acc-gold);opacity:0;transition:opacity .14s}
.ow-main .od-row:hover,.ow-main .os-row:hover,
.ow-main .oc-row:hover,.ow-main .om-row:hover{background:rgba(255,255,255,.022)}
.ow-main .od-row:hover::before,.ow-main .os-row:hover::before,
.ow-main .oc-row:hover::before,.ow-main .om-row:hover::before{opacity:.85}

/* Rows run to the panel edge rather than floating inside its padding, which
   is what makes a list read as a list. */
.ow-card > .od-row,.owner-group > .od-row,
.ow-card > .os-row,.owner-group > .os-row,
.ow-card > .oc-row,.owner-group > .oc-row,
.ow-card > .om-row,.owner-group > .om-row{margin-inline:-16px;padding-inline:16px}

.os-main,.od-row-main,.op-main{flex:1;min-width:170px}
.os-main b,.od-row-main b,.oc-main b{font-size:13px;color:var(--bone)}
.od-row-acts,.oc-actions{display:flex;gap:7px;flex-wrap:wrap;flex:none}

/* -------------------------------------------------------- 6. THE CONTROLS
   A button in the panel is a control, not a call to action. */
.ow-main .btn-sm{padding:0 13px;height:32px;line-height:30px;font-size:12px}
.ow-main .btn{
  clip-path:polygon(7px 0,100% 0,100% calc(100% - 7px),
                    calc(100% - 7px) 100%,0 100%,0 7px)}

/* Filter strips - the payment statuses, the maps server tabs. A segmented
   row, not seven floating chips. */
.ow-main .owner-nav,.ow-main .lb-tabs{
  display:flex;gap:0;flex-wrap:wrap;margin:0;padding:0;
  border:1px solid var(--line2);width:max-content;max-width:100%;
  clip-path:polygon(9px 0,100% 0,100% calc(100% - 9px),
                    calc(100% - 9px) 100%,0 100%,0 9px)}
.ow-main .owner-nav a,.ow-main .owner-nav .on,.ow-main .lb-tab{
  padding:0 15px;height:34px;line-height:34px;
  border:0;border-inline-end:1px solid var(--line);
  font-size:12.5px;color:var(--mute);background:none;
  clip-path:none;border-radius:0}
.ow-main .owner-nav a:last-child,.ow-main .owner-nav .on:last-child,
.ow-main .lb-tab:last-child{border-inline-end:0}
.ow-main .owner-nav a:hover,.ow-main .lb-tab:hover{
  color:var(--bone);background:rgba(255,255,255,.03)}
.ow-main .owner-nav .on,.ow-main .lb-tab.on{
  color:#050505;background:var(--acc-gold);font-weight:800}
.ow-main .lb-tab.on .lb-tab-dot{background:#050505;box-shadow:none}

/* --------------------------------------------------------- 7. THE STATUS
   Pills stopped being pills when the site was flattened and had been left as
   grey rectangles. Same chamfer as everything else, and a size that does not
   compete with the value they are labelling. */
.ow-main .pill-ok,.ow-main .pill-off,.ow-main .pill-err,
.ow-main .pill-warn,.ow-main .pill-env,.ow-main .oc-badge{
  flex:none;font-size:10.5px;font-weight:800;letter-spacing:0;
  padding:3px 9px;line-height:1.6;border-radius:0;
  clip-path:polygon(5px 0,100% 0,100% calc(100% - 5px),
                    calc(100% - 5px) 100%,0 100%,0 5px)}

/* ------------------------------------------------------------ 8. THE KEYS
   The counts strip on discord, the KPI strip on maps and the dashboard: the
   same object rendered at three sizes. */
.os-counts{grid-template-columns:repeat(auto-fit,minmax(104px,1fr));gap:9px}
.os-count,.ow-kpi{padding:11px 12px}
.os-count b{font-size:19px;color:var(--white)}
.os-count span,.ow-kpi-k{font-size:11px;color:var(--dim)}

/* --------------------------------------------------------- 9. THE COLUMNS
   Two cards side by side start at 300, not 330: on a 1280 panel 330 gave one
   column of card and one column of nothing. */
.ow-grid{grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:12px;margin:0}

/* ----------------------------------------------------------- 10. THE MAPS
   An 84px square next to a 13px name is a picture with a caption underneath.
   The map is the subject here, so it keeps a real thumbnail - just one shaped
   like a map rather than an avatar. */
.om-thumb{width:84px;height:60px}
.om-main b{font-size:13.5px}
.om-bar{height:5px}
.om-score b{font-size:18px;color:var(--acc-gold)}
.om-two{grid-template-columns:1fr 1fr;gap:12px}
.op-form .om-two{grid-column:1 / -1;display:grid}

/* ---------------------------------------------------- 11. THE CODE FOLDER
   The per-code edit form sits under its row. It was a bare summary line with
   no relationship to the row it belongs to. */
.oc-edit{margin:0;border-bottom:1px solid var(--line)}
.oc-edit:last-of-type{border-bottom:0}
.oc-edit-sum{
  display:inline-flex;align-items:center;gap:7px;
  padding:5px 11px;margin:0 0 0 4px;font-size:11px;
  border:1px solid var(--line2);color:var(--dim);
  clip-path:polygon(6px 0,100% 0,100% calc(100% - 6px),
                    calc(100% - 6px) 100%,0 100%,0 6px)}
.oc-edit[open]{padding-bottom:14px}
.oc-edit[open] .oc-edit-sum{margin-bottom:12px;border-color:var(--acc-gold);color:var(--bone)}

/* --------------------------------------------------------- 12. THE PROSE
   Help under a heading, the note at the foot of a card, the API block for
   whoever writes the Discord bot. */
.ow-main .owner-help,.ow-main .card-note,.ow-main .card-empty{
  font-size:11.5px;line-height:1.85;color:var(--dim);max-width:80ch}
.ow-main .owner-group-title + .owner-help{margin:-4px 0 12px}
.owner-pre{
  font-size:11px;line-height:1.75;padding:12px 14px;overflow-x:auto;
  background:#0A0A0A;border-color:var(--line)}

/* ---------------------------------------------------------- 13. THE EMPTY
   On a quiet day this is most of the panel. */
.ow-main .empty,.ow-main .card-empty{
  border:1px dashed var(--line2);
  padding:18px 16px;text-align:start;
  font-size:12.5px;font-weight:400;color:var(--dim)}

/* -------------------------------------------------------- 14. THE TOOLBAR
   Search and its filters belong on one line. Two stacked full-width blocks
   above a table is the most repeated piece of wasted height in the panel. */
.ow-toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0}
.ow-toolbar .lb-search{flex:0 1 360px;margin:0}
.ow-toolbar-end{margin-inline-start:auto}

/* ============================================================================
   WAVE 9d: THE NEWS EDITOR, AND WHAT IT WRITES
   ----------------------------------------------------------------------------
   Two halves of one feature.

   The EDITOR is a toolbar over a contenteditable box shadowing the textarea
   that was always there. It has to look like a field on this panel rather than
   like a browser default, because a raw contenteditable div is a borderless
   rectangle with no focus ring and an owner cannot tell whether they are
   typing into it.

   The ARTICLE is the other half, and it is the half that was missing entirely.
   `.nw-article` was one line - a size, a leading and a colour - because a post
   body was plain text and had no headings, lists or images in it to style. Now
   it does, and an <h2> with no rule of its own inherits the site's display
   heading: 900 weight, tight tracking, sized for a hero. In the middle of a
   paragraph of news that reads as shouting.
   ========================================================================= */

/* ------------------------------------------------------------ 1. THE FRAME */
.rt{display:block}
.rt .rt-src{display:block}
/* Once the editor is live the textarea is still the field that submits, but it
   is not the field anyone looks at. Kept in the layout, out of the way: a
   display:none textarea is skipped by some browsers' form restore. */
.rt.is-live .rt-src{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}

/* ---------------------------------------------------------- 2. THE TOOLBAR */
.rt-bar{
  display:flex;flex-wrap:wrap;align-items:center;gap:4px;
  padding:7px 8px;
  background:var(--elevated);border:1px solid var(--line2);border-bottom:0;
  clip-path:polygon(9px 0,100% 0,100% 100%,0 100%,0 9px)}

.rt-g{display:flex;gap:2px;align-items:center}
/* A hairline between groups says "these do related things" without a label. */
.rt-g + .rt-g{
  margin-inline-start:5px;padding-inline-start:7px;
  border-inline-start:1px solid var(--line)}

.rt-b{
  min-width:30px;height:28px;padding:0 8px;
  background:none;border:1px solid transparent;
  color:var(--mute);font-family:var(--ui);font-size:11.5px;font-weight:700;
  line-height:1;cursor:pointer;
  transition:background .14s,color .14s,border-color .14s}
.rt-b:hover{background:rgba(255,255,255,.05);color:var(--bone);
  border-color:rgba(251,211,128,.3)}
.rt-b:active{background:rgba(251,211,128,.12)}
.rt-b:focus-visible{outline:1px solid var(--acc-gold);outline-offset:1px}

/* The four character buttons are the only Latin on the bar and should read as
   what they do rather than as text. */
.rt-g:first-child .rt-b{font-family:Georgia,'Times New Roman',serif;font-size:14px}
.rt-g:first-child .rt-b:nth-child(2){font-style:italic}
.rt-g:first-child .rt-b:nth-child(3){text-decoration:underline}
.rt-g:first-child .rt-b:nth-child(4){text-decoration:line-through}

.rt-bar.is-off{opacity:.45;pointer-events:none}

/* -------------------------------------------------------- 3. THE WRITING */
.rt-area{
  min-height:320px;max-height:62vh;overflow-y:auto;
  padding:16px 18px;
  background:rgba(255,255,255,.03);
  border:1px solid var(--line2);
  font-size:14.5px;line-height:2;color:var(--bone);
  clip-path:polygon(0 0,100% 0,100% calc(100% - 9px),
                    calc(100% - 9px) 100%,0 100%)}
.rt-area:focus{
  outline:none;border-color:var(--acc-gold);
  background:rgba(255,255,255,.045);
  box-shadow:0 0 0 1px rgba(251,211,128,.16),0 0 26px -12px var(--acc-gold)}

/* What the owner types has to look like what a reader will get, or the
   toolbar is guesswork. Same shapes as .nw-article below. */
.rt-area > :first-child{margin-top:0}
.rt-area p{margin:0 0 1em}
.rt-area h2{font-size:20px;font-weight:800;letter-spacing:0;line-height:1.45;
  margin:1.3em 0 .5em;color:var(--white)}
.rt-area h3{font-size:16px;font-weight:800;letter-spacing:0;line-height:1.5;
  margin:1.2em 0 .45em;color:var(--bone)}
.rt-area ul,.rt-area ol{margin:0 0 1em;padding-inline-start:1.6em}
.rt-area li{margin-bottom:.35em}
.rt-area blockquote{
  margin:1em 0;padding:2px 14px;
  border-inline-start:2px solid var(--acc-gold);color:var(--mute)}
.rt-area a{color:var(--gold-light);text-decoration:underline}
.rt-area img{max-width:100%;height:auto;margin:10px 0;display:block}
.rt-area hr{border:0;border-top:1px solid var(--line2);margin:1.4em 0}

/* ------------------------------------------------------------ 4. THE NOTE
   "uploading", "too big", "that is not an image". One line, under the thing
   it is talking about, gone again when the next action succeeds. */
.rt-note{
  margin:7px 0 0;min-height:16px;
  font-size:11.5px;line-height:1.6;color:var(--dim)}
.rt-note-bad{color:var(--danger-text,#FF9A8A)}

/* ------------------------------------------------------- 5. THE TWO COLUMNS
   Writing on the left, everything describing the post on the right. Below
   1100 the rail goes back under the body, where a narrow screen wants it. */
.nw-edit{
  display:grid;grid-template-columns:minmax(0,1fr) 320px;
  gap:14px;align-items:start}
@media(max-width:1100px){.nw-edit{grid-template-columns:1fr}}

.nw-edit-main,.nw-edit-side{display:flex;flex-direction:column;gap:12px;min-width:0}

/* The title is the one field on this page worth making big: it is the thing
   the post is, and it is read at that size on the card. */
.nw-title{height:46px;min-height:46px;font-size:17px;font-weight:700}

.nw-body-field{max-width:none}
.nw-edit .owner-field{max-width:none;margin-bottom:14px}
.nw-edit .owner-field:last-child{margin-bottom:0}

.nw-edit-acts{display:flex;gap:8px;margin:14px 0 0}

/* --------------------------------------------------------- 6. THE COVER */
.nw-cover{display:flex;flex-direction:column;gap:8px}
.nw-cover-shot{
  width:100%;aspect-ratio:16/9;object-fit:cover;
  border:1px solid var(--line2);background:var(--elevated);
  clip-path:polygon(10px 0,100% 0,100% calc(100% - 10px),
                    calc(100% - 10px) 100%,0 100%,0 10px)}
.nw-cover .btn{align-self:flex-start}
.nw-cover .rt-note{margin:0}

/* ---------------------------------------------------------- 7. THE FOLD
   A block that is read once on day one and then never again - the Discord bot
   contract, anything an owner sets up and forgets. */
.ow-fold > .ow-fold-sum{
  display:flex;align-items:center;gap:9px;
  cursor:pointer;list-style:none;
  font-family:var(--ui);font-size:13.5px;font-weight:800;color:var(--bone)}
.ow-fold > .ow-fold-sum::-webkit-details-marker{display:none}
.ow-fold > .ow-fold-sum::before{
  content:"";flex:none;width:3px;height:14px;background:var(--acc-gold)}
.ow-fold > .ow-fold-sum::after{
  content:"+";margin-inline-start:auto;color:var(--dim);font-weight:700}
.ow-fold[open] > .ow-fold-sum{
  border-bottom:1px solid var(--line2);padding-bottom:10px;margin-bottom:13px}
.ow-fold[open] > .ow-fold-sum::after{content:"\2212"}
.ow-fold > .ow-fold-sum:hover{color:var(--white)}

/* ======================================================= 8. THE POST BODY
   The reader's half. Until now a body was plain text with line breaks, so one
   declaration covered it. It can now contain headings, lists, quotes, rules
   and images, none of which had a rule of their own. */
.nw-article > :first-child{margin-top:0}
.nw-article > :last-child{margin-bottom:0}
.nw-article p{margin:0 0 1.15em}

.nw-article h2{
  font-family:var(--ui);font-size:22px;font-weight:800;
  letter-spacing:0;line-height:1.45;
  margin:1.7em 0 .55em;color:var(--white)}
.nw-article h3{
  font-family:var(--ui);font-size:17px;font-weight:800;
  letter-spacing:0;line-height:1.55;
  margin:1.5em 0 .45em;color:var(--bone)}

.nw-article ul,.nw-article ol{margin:0 0 1.15em;padding-inline-start:1.7em}
.nw-article li{margin-bottom:.4em}
.nw-article li::marker{color:var(--acc-gold)}

.nw-article blockquote{
  margin:1.4em 0;padding:10px 16px;
  background:rgba(255,255,255,.025);
  border-inline-start:2px solid var(--acc-gold);
  color:var(--mute);font-size:14.5px}
.nw-article blockquote p:last-child{margin-bottom:0}

.nw-article a{color:var(--gold-light);text-decoration:underline;
  text-underline-offset:3px}
.nw-article a:hover{color:var(--gold-bright)}

.nw-article hr{
  border:0;height:1px;margin:2em 0;
  background:linear-gradient(90deg,transparent,var(--line2) 20%,
                             var(--line2) 80%,transparent)}

/* An image in a post is the width of the column, chamfered like every other
   surface on the site, and never taller than a screen - a portrait photo at
   full width otherwise pushes the rest of the post off the page. */
.nw-article img{
  display:block;max-width:100%;height:auto;max-height:76vh;object-fit:contain;
  margin:1.5em auto;
  border:1px solid var(--line2);
  clip-path:polygon(14px 0,100% 0,100% calc(100% - 14px),
                    calc(100% - 14px) 100%,0 100%,0 14px)}

.nw-article figure{margin:1.5em 0}
.nw-article figcaption{
  margin-top:8px;font-size:12px;color:var(--dim);text-align:center}

.nw-article code{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:.88em;padding:2px 6px;background:rgba(255,255,255,.06)}
.nw-article pre{
  margin:1.3em 0;padding:13px 15px;overflow-x:auto;
  background:#0A0A0A;border:1px solid var(--line);
  font-size:12.5px;line-height:1.75;direction:ltr;text-align:left}
.nw-article pre code{background:none;padding:0}

/* ============================================================================
   WAVE 9e: WHAT LOOKING AT IT FOUND
   ----------------------------------------------------------------------------
   Three things the rendered pages showed that reading the CSS did not.
   ========================================================================= */

/* -------------------------------------------------- 1. THE STRETCHED PILL
   On the codes page the "فعال" badge rendered as a full-width green bar
   across the row. `.od-row-main` is a COLUMN flex container - written for
   delivery, where it stacks an item name over a SteamID - and in a column
   every child stretches to the full cross-axis width. A badge is not a bar. */
.od-row-main > .oc-badge,.od-row-main > .pill-ok,.od-row-main > .pill-off,
.od-row-main > .pill-err,.od-row-main > .pill-warn,
.os-main > .oc-badge,.os-main > .pill-ok,.os-main > .pill-off,
.os-main > .pill-err,.os-main > .pill-warn{align-self:flex-start}

/* A discount code is a line of facts - code, percent, state, usage - not a
   stack of them. It was only stacking because it borrowed delivery's row. */
.oc-row > .od-row-main{
  flex-direction:row;align-items:center;flex-wrap:wrap;gap:6px 11px}
.oc-row > .od-row-main > b{margin-inline-end:2px}

/* --------------------------------------------------- 2. THE STANDINGS ROW
   The score column was sized for two digits and holds a count, a percentage
   and sometimes a "leading" badge. */
.om-score{min-width:92px;gap:5px}
.om-score .pill-ok{align-self:flex-end}

/* ----------------------------------------------------------- 3. THE TABLE
   A payment row prints a full timestamp, a SteamID and an order number, so it
   is a table of long figures. A point smaller, and every column of digits in
   the same rhythm, fits the ones that matter without a sideways scroll. */
.op-table{font-size:12px}
.op-table td.num,.op-table th{font-variant-numeric:tabular-nums}

/* ============================================================================
   WAVE 9f: THE DEAD GUTTER
   ----------------------------------------------------------------------------
   Wave 9b put `max-width:1280px` on `.ow-main` to stop a settings form
   stretching across a wide monitor. Wrong lever. `.ow-main` is the whole page,
   and the page is laid out from the start edge - so on a 1900px screen the
   panel stopped 400px short and left a black strip down the left side of every
   owner page. The dashboard is a GRID OF CARDS: it wants every pixel.

   The measure belongs to the things that actually read badly when they are too
   wide - a form, a paragraph - not to the container holding them.
   ========================================================================= */
.ow-main{max-width:none}

/* A form is the thing that needed the limit. Four columns of field is already
   more than anyone fills in; past that it stops being a form and becomes a
   spreadsheet. */
.op-form{max-width:1120px}

/* Prose has a measure for the same reason a book does. Wide enough not to look
   like a column against a full-width dashboard, narrow enough to read. */
.ow-main .sec-head,.ow-main .notice{max-width:1100px}

/* Wave 9b's `.ow-main .op-form{max-width:100%}` outranks a bare `.op-form`, so
   the cap has to be written at the same specificity or the form keeps taking
   the full width - six columns of field on a 1900px screen, with the seventh
   orphaned on a row of its own. Four is the most a form should ever be. */
.ow-main .op-form,.ow-main form.op-form{max-width:1120px}

/* ============================================================================
   WAVE 11: THE DROPDOWNS
   ----------------------------------------------------------------------------
   Every <select> on the site opened a white panel of near-invisible text.

   THE OPTION LIST IS NOT DRAWN BY THE PAGE. It is an OS-level popup, and the
   only thing the page had told the browser was `select { background: dark;
   color: light }`. The browser painted the popup on its own default - a LIGHT
   surface, because nothing had said otherwise - and then let the options
   inherit the page's light text colour. White on white.

   `color-scheme` is the property that actually answers this. It tells the
   browser which set of system colours to build native UI from, and it is what
   repaints the option list, the scrollbars, the date and colour pickers, the
   autofill background and the spinner arrows. Painting `option` by hand as
   well is belt and braces: it covers the engines that honour author colours in
   the list, and it costs nothing on the ones that do not.

   This was never a dark-mode toggle - the site has exactly one theme, and this
   is how you declare it to the browser rather than only to the reader.
   ========================================================================= */
:root{color-scheme:dark}

/* Some engines only take the hint from the control itself. */
select,input,textarea,button{color-scheme:dark}

/* The list, painted explicitly. Slightly lighter than the page so the popup
   reads as sitting ON the page rather than as a hole cut through it. */
option,optgroup{
  background-color:#101010;
  color:var(--bone,#E8E6E1);
  font-family:inherit}

optgroup{color:var(--dim,#8A8A85);font-weight:700;font-style:normal}
option{padding:6px 10px;font-weight:400}

/* The current choice takes the site's gold rather than the OS blue that was
   the one legible thing in the broken popup. */
option:checked,option[selected]{
  background:linear-gradient(rgba(251,211,128,.22),rgba(251,211,128,.22));
  color:#FFF;font-weight:700}

option:disabled{color:var(--off,#5A5A56)}

/* A disabled select was reading as an empty box rather than as a control that
   is switched off. */
select:disabled{opacity:.5;cursor:not-allowed}

/* ============================================================================
   GAME UI PASS - WAVE 10: THE PLAYER'S OWN PAGE
   ----------------------------------------------------------------------------
   The same audit that found the owner panel, run against the dashboard. Same
   shape of result: the pass reached the CONTENT ROWS - bases, deaths, the raid
   log, the team log, the wallet, the rank tile - and never reached the TOP
   HALF. Verified by listing the classes the markup uses against the ones the
   pass region actually touches:

       reached   db-strip db-rank db-wallet db-grid db-line db-bases db-deaths
                 db-raidlog db-tlog db-kpis db-undelivered
       missed    db-hero db-hero-bg db-hero-in db-hero-cta db-av db-av-wrap
                 db-id db-name db-meta db-clantag db-tabs db-level db-xpbar
                 db-claimbar db-clanhead db-clanbadge db-roster db-member
                 db-role db-side db-shell

   That second list is the page a player actually looks at. And because the
   flatten (`*{border-radius:0 !important}`) ran afterwards, three of them are
   worse than untouched: `.db-hero` asks for 16px, `.db-av` for 20px and
   `.db-xpbar` for 99px, and all three were stripped to hard rectangles with
   nothing put back. A 96px square avatar with a grey hairline round it does
   not read as a neutral default, it reads as a broken image.

   THE HOME PAGE IS MOSTLY LEFT ALONE, on purpose. Its hero, server cards,
   pillars and events all went through the pass, and the FAQ has a considered
   treatment of its own. The one plain block left there is the gallery.
   ========================================================================= */

/* ============================================================== 1. THE HERO
   The banner behind a player's own name gets the full card treatment -
   chamfer, accent hairline, corner bracket - plus the one thing an ordinary
   card never needs: a scrim that guarantees the name reads over whatever
   screenshot happens to be behind it. */
.db-hero{
  --acc:var(--acc-gold);
  min-height:184px;
  border-color:var(--line2);
  clip-path:polygon(22px 0,100% 0,100% calc(100% - 22px),
                    calc(100% - 22px) 100%,0 100%,0 22px);
  transition:border-color .25s}
.db-hero:hover{border-color:rgba(251,211,128,.26)}

.db-hero::before{
  content:"";position:absolute;top:0;left:0;right:0;height:1px;z-index:3;
  background:linear-gradient(90deg,transparent,var(--acc-gold),transparent);
  opacity:.75;pointer-events:none}

.db-hero::after{
  content:"";position:absolute;top:10px;left:10px;width:16px;height:16px;z-index:3;
  border-top:1px solid var(--gx-line);border-left:1px solid var(--gx-line);
  pointer-events:none}

/* A DIRECTIONAL scrim, not only a bottom fade. The identity sits on the start
   edge, so that is the side that has to stay dark whichever banner the player
   picked - the old bottom-to-top fade left a name sitting on bright sky. */
.db-hero-bg::after{
  background:
    linear-gradient(to top,rgba(5,5,5,.97),rgba(5,5,5,.70) 55%,rgba(5,5,5,.40)),
    linear-gradient(to left,transparent 45%,rgba(5,5,5,.72))}
[dir="rtl"] .db-hero-bg::after{
  background:
    linear-gradient(to top,rgba(5,5,5,.97),rgba(5,5,5,.70) 55%,rgba(5,5,5,.40)),
    linear-gradient(to right,transparent 45%,rgba(5,5,5,.72))}

/* The banner drifts. Very slowly - this is a page somebody leaves open. */
.db-hero-bg img{
  transform:scale(1.04);
  animation:db-drift 42s ease-in-out infinite alternate}
@keyframes db-drift{
  from{transform:scale(1.04) translate3d(0,0,0)}
  to{transform:scale(1.10) translate3d(0,-1.5%,0)}}

.db-hero-in{padding:var(--s4) var(--s3) calc(var(--s3) + 4px);align-items:flex-end}

/* ============================================================== 2. THE FACE
   The frame carries the shape and the ring and the image sits inside it. It
   has to be built this way round: clip-path clips a box-shadow, so a ring
   drawn on the avatar itself would be sliced off at the chamfer. */
.db-av-wrap{
  padding:3px;
  background:linear-gradient(150deg,rgba(251,211,128,.55),rgba(251,211,128,.10) 55%,transparent);
  clip-path:polygon(16px 0,100% 0,100% calc(100% - 16px),
                    calc(100% - 16px) 100%,0 100%,0 16px);
  box-shadow:0 14px 44px rgba(0,0,0,.6)}

.db-av{
  width:104px;height:104px;border:0;box-shadow:none;
  clip-path:polygon(14px 0,100% 0,100% calc(100% - 14px),
                    calc(100% - 14px) 100%,0 100%,0 14px)}
.db-av.pf-av-init{
  font-family:var(--disp);font-size:42px;display:grid;place-items:center;line-height:1}
@media(max-width:560px){.db-av{width:84px;height:84px}}

/* ========================================================== 3. THE IDENTITY
   The biggest word on the player's own page, sitting on photographic art - so
   it earns legibility with a shadow rather than with more weight. */
.db-name{
  font-size:clamp(26px,3.6vw,42px);
  letter-spacing:-.02em;line-height:1.08;
  margin:0 0 10px;color:var(--white);
  text-shadow:0 2px 18px rgba(0,0,0,.85),0 1px 2px rgba(0,0,0,.9)}

.db-meta{gap:8px 14px;align-items:center;font-size:12px}
.db-meta > *{display:inline-flex;align-items:center;gap:6px}

/* The clan tag is a badge, not a link inside a sentence. */
.db-clantag{
  padding:3px 10px;font-weight:800;font-size:11.5px;
  color:var(--acc-gold);border:1px solid rgba(251,211,128,.42);
  background:rgba(251,211,128,.08);
  clip-path:polygon(6px 0,100% 0,100% calc(100% - 6px),
                    calc(100% - 6px) 100%,0 100%,0 6px);
  transition:background .16s,border-color .16s}
.db-clantag:hover{background:rgba(251,211,128,.16);border-color:var(--acc-gold)}

.db-hero-cta{align-self:flex-end}

/* ============================================================= 4. THE STRIP */
.db-strip{
  clip-path:polygon(16px 0,100% 0,100% calc(100% - 16px),
                    calc(100% - 16px) 100%,0 100%,0 16px)}
.db-rank b{color:var(--acc-gold);font-size:32px;letter-spacing:-.02em}
.db-level b{font-size:26px;letter-spacing:-.02em;color:var(--white)}

/* Wave 9c's rule, carried here: these labels are Persian, and uppercase does
   nothing to Persian while tracking pulls its joined letterforms apart. */
.db-rank span,.db-level span,.db-kpis span,.db-wallet span{
  text-transform:none;letter-spacing:0;font-size:11px}

/* ========================================================== 5. THE XP RAIL
   The one bar the whole level system hangs on, and it was a 6px grey pill with
   its radius stripped off. Thicker, chamfered, and the leading end glows, so
   progress reads without going to the numbers underneath. */
.db-xpbar{
  position:relative;height:9px;
  background:rgba(255,255,255,.055);
  border:1px solid var(--line);
  clip-path:polygon(4px 0,100% 0,100% calc(100% - 4px),
                    calc(100% - 4px) 100%,0 100%,0 4px)}
/* No width transition. The fill is rendered server-side as an inline style and
   nothing ever changes it, so a transition on width could not fire even once -
   it would only be a layout-animating rule sitting there waiting to be copied
   somewhere it does fire. The sheen below moves on transform instead. */
.db-xpbar i{
  position:relative;border-radius:0;
  background:linear-gradient(90deg,rgba(217,165,46,.75),var(--acc-gold));
  box-shadow:0 0 14px -2px rgba(251,211,128,.7)}
.db-xpbar i::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.38),transparent);
  transform:translateX(-100%);
  animation:db-sheen 2.8s ease-in-out infinite}
@keyframes db-sheen{
  0%{transform:translateX(-100%)}
  60%,100%{transform:translateX(220%)}}

/* ============================================================== 6. THE TABS
   Shared with the profile page, so this lands on both. The underline stays -
   it is the right pattern for a row of views over one subject - but it now
   sits on a rail, which is what stops four words floating in space. */
.pf-tabs{
  position:relative;gap:2px;
  border-bottom:1px solid var(--line2);
  margin-bottom:var(--s2)}
.pf-tabl{
  position:relative;padding:12px 17px;
  border-bottom:2px solid transparent;
  transition:color .16s,background .16s}
.pf-tabl:hover{background:rgba(255,255,255,.03)}
.pf-tabl.on{
  color:var(--white);border-bottom-color:var(--acc-gold);
  background:linear-gradient(to top,rgba(251,211,128,.10),transparent 70%)}
.db-tabdot{
  width:6px;height:6px;background:var(--acc-gold);
  box-shadow:0 0 0 3px rgba(251,211,128,.18)}

/* ========================================================== 7. THE CLAIM BAR
   Unclaimed XP is the one interrupting element on the page - its own rule says
   so. It should look like something waiting to be pressed, not like a notice. */
.db-claimbar{
  position:relative;overflow:hidden;
  border-color:rgba(251,211,128,.45);
  clip-path:polygon(12px 0,100% 0,100% calc(100% - 12px),
                    calc(100% - 12px) 100%,0 100%,0 12px);
  transition:border-color .18s,background .18s}
.db-claimbar b,.db-claimbar i{color:var(--acc-gold)}
.db-claimbar:hover{border-color:var(--acc-gold)}
.db-claimbar::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(100deg,transparent 35%,rgba(251,211,128,.13) 50%,transparent 65%);
  transform:translateX(-60%);
  animation:db-claim 5.5s ease-in-out infinite}
@keyframes db-claim{
  0%,15%{transform:translateX(-60%)}
  55%,100%{transform:translateX(160%)}}

/* =============================================================== 8. THE CLAN */
.db-clanbadge{
  font-family:var(--disp);
  border:1px solid rgba(251,211,128,.30);
  clip-path:polygon(12px 0,100% 0,100% calc(100% - 12px),
                    calc(100% - 12px) 100%,0 100%,0 12px);
  transition:border-color .18s}
.db-clanbadge:hover{border-color:var(--acc-gold)}
.db-clanhead{border-bottom-color:var(--line2)}

/* A roster row gets the leading accent every other list row on the site got in
   wave 9c. No negative margin: .db-roster is a two-column grid and pulling the
   rows outward would let the two columns touch across the gap. */
.db-member{position:relative;padding-inline-start:10px;transition:background .14s}
.db-member::before{
  content:"";position:absolute;inset-block:2px;inset-inline-start:0;width:2px;
  background:var(--acc-gold);opacity:0;transition:opacity .14s}
.db-member:hover{background:rgba(255,255,255,.025)}
.db-member:hover::before{opacity:.8}
.db-member:hover b,.db-member.me b{color:var(--acc-gold)}
.db-role{
  border-radius:0;
  clip-path:polygon(4px 0,100% 0,100% calc(100% - 4px),
                    calc(100% - 4px) 100%,0 100%,0 4px)}

/* ============================================================ 9. THE SIDEBAR
   The account rail was a list of words. It becomes a list of destinations,
   with the same selected state the owner panel uses. */
.db-side a{
  position:relative;
  border-inline-start:2px solid transparent;
  transition:background .16s,color .16s,border-color .16s}
.db-side a:hover{border-inline-start-color:rgba(251,211,128,.35)}
.db-side a.on{
  border-inline-start-color:var(--acc-gold);
  background:linear-gradient(90deg,rgba(251,211,128,.10),transparent 72%)}
.db-badge{
  border-radius:0;background:var(--acc-gold);color:#050505;font-weight:800;
  clip-path:polygon(4px 0,100% 0,100% calc(100% - 4px),
                    calc(100% - 4px) 100%,0 100%,0 4px)}
.db-wallet{
  clip-path:polygon(13px 0,100% 0,100% calc(100% - 13px),
                    calc(100% - 13px) 100%,0 100%,0 13px)}
.db-wallet b{color:var(--white)}
.db-wallet>div:first-child b{color:var(--acc-gold)}

/* =========================================================== 10. THE BAD NEWS
   A failed delivery is real money, so it stays at the top where a player sees
   it. It does not have to be two slabs tall to say so. */
.db-undelivered{line-height:1.7;gap:3px}
.db-undelivered b:first-child{font-size:13px}
.db-undelivered span{font-size:12px}
.db-main .notice{
  padding:12px 16px;
  clip-path:polygon(11px 0,100% 0,100% calc(100% - 11px),
                    calc(100% - 11px) 100%,0 100%,0 11px)}

/* ============================================================ 11. THE GALLERY
   The last plain block on the home page: four equal squares with the radius
   stripped, no frame, no hover beyond a slow zoom.

   ONE SHOT LEADS. A grid of identical squares claims every picture is equally
   worth looking at, which is never true of a screenshot wall. The first takes
   four cells - but only when there are enough pictures left to fill the row
   beside it, which `:has` makes a property of the content rather than
   something somebody has to remember when the gallery changes. */
.gal{grid-auto-flow:dense}
.gal:has(> a:nth-child(5)) > a:first-child{grid-column:span 2;grid-row:span 2}
@media(max-width:700px){.gal{grid-template-columns:repeat(2,1fr)}}

.gal a{
  position:relative;
  border:1px solid var(--line);
  clip-path:polygon(14px 0,100% 0,100% calc(100% - 14px),
                    calc(100% - 14px) 100%,0 100%,0 14px);
  transition:border-color .22s}
.gal a:hover{border-color:rgba(251,211,128,.42)}

/* The wall sits back until you point at one, so it reads as a single texture
   and the one under the cursor lifts out of it. */
.gal img{filter:saturate(.85) brightness(.82);transition:transform .6s,filter .4s}
.gal a:hover img{transform:scale(1.07);filter:saturate(1.05) brightness(1)}

.gal:has(> a:nth-child(5)) > a:first-child::after{
  content:"";position:absolute;top:10px;left:10px;width:18px;height:18px;z-index:2;
  border-top:1px solid rgba(251,211,128,.55);border-left:1px solid rgba(251,211,128,.55);
  pointer-events:none}

/* Nothing above moves for somebody who asked the system not to move things. */
@media(prefers-reduced-motion:reduce){
  .db-hero-bg img{animation:none;transform:none}
  .db-xpbar i::after,.db-claimbar::after{animation:none;opacity:0}
  .gal img,.gal a:hover img{transition:none}}

/* ============================================================================
   WAVE 12: THE GALLERY SUBMISSION PAGE
   ----------------------------------------------------------------------------
   The player half of the community gallery. It borrows the notification
   settings shell (.ns-block, .ns-h, .ns-note) because it is the same kind of
   page - a short form plus a list of your own things - and a second set of
   panel classes for one screen would be two designs to keep in step.

   THE THUMBNAIL HAS A PLACEHOLDER STATE AND THAT IS LOAD BEARING. A pending
   submission has no image to show, because the file is in quarantine with no
   URL. An empty frame says "waiting" better than a broken-image icon does.
   ========================================================================= */
.gs-wrap{max-width:860px}

.gs-form .owner-field{max-width:none;margin-bottom:14px}
.gs-form .owner-field:last-of-type{margin-bottom:0}

/* A file input is the one control the browser draws itself, so it gets room
   rather than the 38px the text fields use. */
.gs-file .owner-input[type="file"]{
  height:auto;min-height:44px;padding:11px 12px;
  font-size:12.5px;cursor:pointer;line-height:1.6}

.gs-row{
  position:relative;
  display:flex;align-items:center;gap:13px;
  padding:11px 0;border-bottom:1px solid var(--line);
  transition:background .14s}
.gs-row:last-of-type{border-bottom:0}
.gs-row:hover{background:rgba(255,255,255,.022)}

.gs-thumb{
  width:74px;height:52px;flex:none;display:block;overflow:hidden;
  border:1px solid var(--line2);background:var(--elevated);
  clip-path:polygon(10px 0,100% 0,100% calc(100% - 10px),
                    calc(100% - 10px) 100%,0 100%,0 10px)}
.gs-thumb img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .5s}
.gs-thumb:hover img{transform:scale(1.06)}

/* Nothing to show yet: a hatched frame, not a broken picture. */
.gs-thumb-none{
  background-image:repeating-linear-gradient(45deg,
    rgba(255,255,255,.045) 0 1px,transparent 1px 9px)}

.gs-row-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.gs-row-main b{font-size:13px;color:var(--bone);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gs-row-main .num{font-size:11px}

.gs-row > .pill-ok,.gs-row > .pill-err,.gs-row > .pill-warn{
  flex:none;align-self:center}

/* ============================================================================
   WAVE 13: CLAN EVENTS
   ----------------------------------------------------------------------------
   The raid board. It lives inside a .card on the clan page, so it inherits that
   surface and only adds the row.

   THE TALLY IS THE POINT, so it is the loudest thing in the row after the time.
   A leader is deciding whether the raid is on; they read the green number and
   the clock and nothing else. Everything below that is detail for the people
   who have already decided.
   ========================================================================= */
.ce-form{display:flex;flex-direction:column;gap:9px;margin-bottom:16px;
  padding-bottom:16px;border-bottom:1px solid var(--line)}
.ce-form-row{display:grid;grid-template-columns:140px 1fr;gap:9px}
@media(max-width:560px){.ce-form-row{grid-template-columns:1fr}}
.ce-form .btn{align-self:flex-start}

/* A datetime-local draws its own picker, so it gets room rather than the
   38px a text field takes. */
.ce-form input[type="datetime-local"]{min-height:40px;height:40px}

.ce-row{
  position:relative;padding:13px 0;
  border-bottom:1px solid var(--line)}
.ce-row:last-of-type{border-bottom:0}

.ce-head{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap}

/* raid / farm / meet - which kind of evening this is, at a glance. */
.ce-kind{
  flex:none;font-size:10.5px;font-weight:800;padding:3px 9px;
  color:var(--acc-gold);border:1px solid rgba(251,211,128,.38);
  clip-path:polygon(5px 0,100% 0,100% calc(100% - 5px),
                    calc(100% - 5px) 100%,0 100%,0 5px)}

.ce-title{font-size:14px;color:var(--bone);flex:1;min-width:0}
.ce-when{font-size:12px;color:var(--white);font-variant-numeric:tabular-nums}
.ce-note{margin:7px 0 0;font-size:12.5px;line-height:1.8;color:var(--dim)}

.ce-tally{display:flex;gap:7px;flex-wrap:wrap;margin-top:10px}

/* Who is coming, by name. The count says whether it is happening; the names
   say whether you have a rocket guy. */
.ce-going{display:flex;gap:6px;flex-wrap:wrap;margin:9px 0 0}
.ce-going span{
  font-size:11px;color:var(--mute);padding:2px 8px;
  background:rgba(255,255,255,.04);border:1px solid var(--line)}

.ce-acts{display:flex;gap:6px;flex-wrap:wrap;margin-top:11px}
.ce-acts form{margin:0}

/* The answer you already gave, so three buttons are not three identical
   choices. */
.ce-acts .btn.on{
  background:rgba(251,211,128,.16);border-color:var(--acc-gold);
  color:var(--acc-gold);font-weight:800}

/* ------------------------------------------------------------ the history */
.ce-past{margin-top:14px;border-top:1px solid var(--line);padding-top:12px}
.ce-past > summary{
  cursor:pointer;list-style:none;font-size:12px;color:var(--dim);
  display:inline-flex;align-items:center;gap:7px}
.ce-past > summary::-webkit-details-marker{display:none}
.ce-past > summary::before{content:"+";font-family:var(--disp);color:var(--acc-gold)}
.ce-past[open] > summary::before{content:"\2212"}
.ce-past > summary:hover{color:var(--bone)}

.ce-past-row{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:8px 0;border-bottom:1px solid var(--line);font-size:12px}
.ce-past-row:last-child{border-bottom:0}
.ce-past-row b{color:var(--mute);font-size:12.5px;flex:1;min-width:0}

/* ============================================================================
   WAVE 14: THE IN-GAME CODE FORM
   ----------------------------------------------------------------------------
   Six digits read off a chat line and typed back. It is the only thing this
   page is for, so it is the biggest thing on it after the wordmark.

   THE DIGITS ARE THE CONTROL. Wide tracking and a large monospace-ish size
   make a six-figure code easy to check against the one still on screen behind
   the game, which is the actual task: not "enter a password" but "copy this
   without getting a digit wrong".
   ========================================================================= */
.auth-code{
  display:flex;align-items:flex-end;gap:10px;flex-wrap:wrap;
  justify-content:center;margin:22px auto 0;max-width:460px}

.auth-code label{
  flex:1 1 100%;text-align:center;margin-bottom:2px;
  font-size:12px;color:var(--dim)}

.auth-code-in{
  flex:1 1 220px;min-width:0;height:52px;
  padding:0 16px;
  background:rgba(255,255,255,.05);
  border:1px solid var(--line2);
  color:var(--white);
  font-family:var(--disp,inherit);
  font-size:26px;font-weight:800;letter-spacing:.28em;
  text-align:center;font-variant-numeric:tabular-nums;
  clip-path:polygon(10px 0,100% 0,100% calc(100% - 10px),
                    calc(100% - 10px) 100%,0 100%,0 10px);
  transition:border-color .16s,background .16s,box-shadow .16s}

.auth-code-in::placeholder{
  color:var(--off);letter-spacing:.28em;font-weight:400}

.auth-code-in:focus{
  outline:none;border-color:var(--gold);
  background:rgba(255,255,255,.07);
  box-shadow:0 0 0 1px rgba(217,165,46,.2),0 0 28px -12px var(--gold)}

.auth-code .btn{flex:0 0 auto;height:52px;padding:0 26px;font-size:15px}

@media(max-width:520px){
  .auth-code{flex-direction:column;align-items:stretch}
  .auth-code .btn{width:100%}
}

/* ============================================================================
   WAVE 15: THE NOTIFICATION SCREENS
   ----------------------------------------------------------------------------
   Two complaints, and they pull against each other: "use more colours" and
   "do not make it hurt to look at". The way to have both is to spend colour
   on MEANING and nowhere else.

   So: no coloured backgrounds, no coloured body text, nothing saturated
   covering any real area. Colour appears on three small things only - a 2px
   rail at the start of a row, a chip, and a switch - and every one of them is
   encoding a fact the reader is actually looking for:

       the row's rail    WHICH KIND of notification this is. It is the same
                         data-kind attribute the notifications list already
                         used, so a raid alarm is the same colour on both
                         screens and the colour starts meaning something.
       the chip          WHETHER IT INTERRUPTS. Warm = buzzes your phone now,
                         cool = waits for the digest, grey = bell only.
       the switch        on or off, and nothing else.

   Body text stays --mute on --panel. Nothing here is white on black, which is
   the pairing that actually tires eyes on a dark page.
   ========================================================================= */

/* ------------------------------------------------------ 1. THE MISSING MAP
   The per-kind accents existed but stopped at ten, and the four missing ones
   are most of what the settings page shows. An uncoloured row next to nine
   coloured ones reads as a bug. */
[data-kind="team_on"]{--acc:var(--acc-green)}
[data-kind="team_off"]{--acc:var(--acc-blue)}
[data-kind="upkeep_low"]{--acc:var(--acc-orange)}
/* The loudest thing the site can say gets the loudest colour it has. */
[data-kind="raid"]{--acc:var(--acc-rose)}

/* The two channels take their own brand hues rather than the site gold, so
   "which service is this" is answered before the word is read. */
[data-channel="discord"]{--acc:#7A8CF0}
[data-channel="telegram"]{--acc:var(--acc-blue)}

/* --------------------------------------------------------- 2. THE PANELS
   One tinted hairline along the top, and a heading in the same hue. That is
   the entire group treatment - three panels that read apart without three
   coloured surfaces fighting each other. */
.ns-block[data-tier="personal"]{--acc:var(--acc-gold)}
.ns-block[data-tier="money"]{--acc:var(--acc-green)}
.ns-block[data-tier="news"]{--acc:var(--acc-blue)}

.ns-block::before{background:linear-gradient(90deg,transparent,var(--acc,var(--acc-gold)),transparent)}
.ns-h{color:var(--acc,var(--gold-bright))}

/* ------------------------------------------------------------ 3. THE ROWS */
.ns-row{
  position:relative;
  padding-inline-start:14px;
  border-bottom:1px solid var(--line);
  transition:background .14s}
.ns-row:last-child{border-bottom:0}

/* The rail. 2px, and only at full strength on hover - at rest it is a hint of
   which family the row belongs to, not a stripe demanding attention. */
.ns-row::before{
  content:"";position:absolute;inset-block:9px;inset-inline-start:0;width:2px;
  background:var(--acc,var(--gx-line));opacity:.45;transition:opacity .14s}
.ns-row:hover{background:rgba(255,255,255,.022)}
.ns-row:hover::before{opacity:1}

.ns-label{gap:12px;flex:1;min-width:0;padding-block:3px}
.ns-name{font-size:13.5px;color:var(--bone)}

/* --------------------------------------------------------- 4. THE SWITCH
   A 15px native checkbox was the single thing making this page look unfinished
   - it is the one control on the site the browser was still drawing. */
.ns-sw{position:relative;flex:none;width:38px;height:21px;display:block}

.ns-sw input{
  position:absolute;inset:0;width:100%;height:100%;margin:0;
  opacity:0;cursor:pointer;z-index:2}

.ns-sw-t{
  position:absolute;inset:0;display:block;pointer-events:none;
  background:rgba(255,255,255,.07);
  border:1px solid var(--line2);
  border-radius:99px;
  transition:background .18s,border-color .18s}

/* The knob. Travels 17px, which is the track minus its own width and padding. */
.ns-sw-t::after{
  content:"";position:absolute;top:3px;inset-inline-start:3px;
  width:13px;height:13px;border-radius:50%;
  background:var(--off);
  transition:transform .18s cubic-bezier(.2,.8,.2,1),background .18s}

.ns-sw input:checked + .ns-sw-t{
  background:color-mix(in srgb,var(--acc,var(--acc-gold)) 26%,transparent);
  border-color:var(--acc,var(--acc-gold))}
.ns-sw input:checked + .ns-sw-t::after{
  background:var(--acc,var(--acc-gold));
  transform:translateX(17px)}
[dir="rtl"] .ns-sw input:checked + .ns-sw-t::after{transform:translateX(-17px)}

/* Keyboard users get the same ring every other control here has. */
.ns-sw input:focus-visible + .ns-sw-t{
  outline:2px solid var(--acc,var(--acc-gold));outline-offset:2px}

@media(prefers-reduced-motion:reduce){
  .ns-sw-t,.ns-sw-t::after{transition:none}
}

/* ----------------------------------------------------------- 5. THE CHIPS
   Outline only. A filled chip at the end of seventeen rows is seventeen
   coloured blocks, which is exactly the "fights your eyes" failure. */
.ns-chip{
  flex:none;font-size:10.5px;font-weight:700;letter-spacing:0;
  padding:3px 9px;white-space:nowrap;
  color:var(--dim);border:1px solid var(--line2);
  clip-path:polygon(5px 0,100% 0,100% calc(100% - 5px),
                    calc(100% - 5px) 100%,0 100%,0 5px)}

/* Delivery, which is the question being asked. */
.ns-chip-d[data-delivery="now"]{color:var(--acc-orange);border-color:rgba(232,134,46,.42)}
.ns-chip-d[data-delivery="digest"]{color:var(--acc-blue);border-color:rgba(90,169,230,.38)}
.ns-chip-d[data-delivery="bell"]{color:var(--dim);border-color:var(--line2)}

/* A linked channel is fine and needs no colour; an unlinked one is the only
   thing on this page with something to DO about it. */
.ns-chip-on{color:var(--acc-green);border-color:rgba(63,191,111,.40)}
.ns-chip-off{color:var(--acc-orange);border-color:rgba(232,134,46,.42)}

/* ---------------------------------------------------------- 6. THE REST */
.ns-select{min-height:36px;padding:0 12px;font-size:13px}
.ns-actions{padding-top:12px;border-top:1px solid var(--line);margin-top:4px}

/* A settings row is a short label and a short chip. At the full 1180px page
   width those two sit at opposite ends of an empty field and the eye has to
   travel the whole way to pair them up. This is a reading measure, not a
   layout: the scannable column of chips survives, the journey to it does not. */
.ns-wrap{max-width:820px}

/* ============================================================================
   WAVE 16: THE PROFILE - STATS, HISTORY, AND THE LFP CHIPS
   ========================================================================= */

/* ------------------------------------------------------- 1. THE STAT TABS
   Four cards, five figures between them, each card full width: the tab was
   mostly empty floor with a number pinned to one edge. Cards side by side,
   and cells that stretch to fill the card they are in. */
.pf-groups{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(268px,1fr));
  gap:14px;align-items:start}

.pf-group{margin:0}

/* auto-FIT, not auto-fill. auto-fill keeps the empty tracks it created, which
   is precisely how one number ended up sitting in a 900px card. */
.stat-grid{grid-template-columns:repeat(auto-fit,minmax(112px,1fr));gap:9px}

.stat-cell{
  position:relative;padding:13px 14px;
  background:rgba(255,255,255,.025);
  border:1px solid var(--line2);border-radius:0;
  clip-path:polygon(11px 0,100% 0,100% calc(100% - 11px),
                    calc(100% - 11px) 100%,0 100%,0 11px);
  transition:border-color .18s,background .18s}
.stat-cell:hover{border-color:rgba(251,211,128,.3);background:rgba(255,255,255,.04)}

.stat-cell b{font-size:25px;color:var(--white);letter-spacing:-.02em}
.stat-cell span{display:block;font-size:12px;color:var(--mute);line-height:1.5}

/* The rank reads as a standing, not as a second statistic. */
.stat-rank{
  display:inline-flex;align-items:baseline;gap:4px;margin-top:8px;
  font-size:10.5px;color:var(--dim)}
.stat-rank b{font-size:12px;color:var(--acc-gold);font-family:var(--ui)}

/* ---------------------------------------------------------- 2. THE HISTORY
   A table of wipes is read down one column at a time, so the columns need to
   line up and the rows need to be separable. */
.pf-hist-h{letter-spacing:0;font-size:11px;color:var(--dim)}
.pf-hist-r{align-items:center;transition:background .14s}
.pf-hist-r:hover{background:rgba(255,255,255,.022)}

/* The wipe still running is the one row worth finding at a glance. */
.pf-hist-r.is-open{background:rgba(251,211,128,.05)}

.pf-hist-name{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;min-width:0}
.pf-hist-name b{font-size:13.5px;color:var(--bone)}
.pf-hist-name small{margin:0;font-size:11px}
.pf-hist-r .num.strong{color:var(--acc-gold);font-size:14px}
.pf-hist-r .pill-ok{font-size:9.5px;padding:2px 7px}

/* ------------------------------------------------------- 3. THE LFP CHIPS
   These were two full-width banners sitting between the hero and the stat bar,
   which made a footnote look like the headline. Now they are chips: they take
   their own width, wrap, and stop growing. */
.pf-lfg{gap:8px}

.pf-lfg-card{
  flex:0 1 auto;max-width:100%;
  gap:9px;padding:7px 10px 7px 8px;
  border-radius:0;
  background:rgba(251,211,128,.06);
  border:1px solid rgba(251,211,128,.22);
  clip-path:polygon(9px 0,100% 0,100% calc(100% - 9px),
                    calc(100% - 9px) 100%,0 100%,0 9px)}

.pf-lfg-card.is-lft{background:rgba(255,255,255,.03);border-color:var(--line2)}

.pf-lfg-txt{gap:0}
.pf-lfg-txt b{font-size:12.5px;font-weight:700;max-width:34ch}
.pf-lfg-txt small{font-size:10.5px;color:var(--dim)}

/* The badge carries the kind, so the sentence under the title no longer has
   to repeat it - that line is now just where and how many. */
.pf-lfg-card .lfg-badge{
  flex:none;font-size:9px;font-weight:800;letter-spacing:.04em;
  padding:2px 6px;border-radius:0}

/* A chevron, not a button. The card is already the link. */
.pf-lfg-go{
  flex:none;width:auto;padding:0 2px;border:0;background:none;border-radius:0;
  font-size:15px;line-height:1;color:var(--dim);transition:color .16s,transform .16s}
.pf-lfg-card:hover .pf-lfg-go{color:var(--acc-gold);transform:translateX(-2px)}

@media(prefers-reduced-motion:reduce){
  .pf-lfg-card:hover .pf-lfg-go{transform:none}
}

/* ============================================================================
   WAVE 17: COLOUR ON THE LFG BOARD
   ----------------------------------------------------------------------------
   The board is a wall of near-identical cards, and every chip on them was the
   same grey pill. Reading it meant reading every word: eight chips a card,
   fifteen cards a page.

   Same rule as the notification screens - colour encodes a FACT, never a mood,
   and it lands on small outline elements so fifteen cards do not become
   fifteen colour fields. Three things carry it:

       the kind rail   LFP or LFT, the board's primary axis
       the chip        WHICH QUESTION it answers (doing / with whom / how long
                       / who they are), not which answer it gives
       the slots       one place left, which is the most perishable fact here

   The chips stay OUTLINE. A filled chip is a block of colour, and eight of
   them on a card is a paint chart.
   ========================================================================= */

/* ------------------------------------------------------------- 1. THE KIND
   The two ad kinds are opposite offers - a team with room, a player with time
   - and they were a gold rail against a grey one. Now they read apart at the
   edge of the card, before the badge is read. */
.lfg-row.is-lfp{--kind:var(--acc-gold);border-inline-start-color:var(--acc-gold)}
.lfg-row.is-lft{--kind:var(--acc-blue);border-inline-start-color:rgba(90,169,230,.65)}

.lfg-badge{
  border:1px solid color-mix(in srgb,var(--kind,var(--gx-line)) 45%,transparent);
  background:color-mix(in srgb,var(--kind,#fff) 13%,transparent);
  color:var(--kind,#cfd5de);
  border-radius:0;
  clip-path:polygon(4px 0,100% 0,100% calc(100% - 4px),
                    calc(100% - 4px) 100%,0 100%,0 4px)}
.is-lfp .lfg-badge{color:var(--acc-gold)}

/* A card lifts toward its own kind rather than everything glowing gold. */
.lfg-row{transition:border-color .18s,background .18s}
.lfg-row:hover{background:rgba(255,255,255,.022)}

/* ----------------------------------------------------------- 2. THE CHIPS
   Four families. The hue answers "which question is this chip about", so a
   reader looking for a language stops scanning the rose ones entirely. */
.lfg-chip{
  border-radius:0;
  clip-path:polygon(5px 0,100% 0,100% calc(100% - 5px),
                    calc(100% - 5px) 100%,0 100%,0 5px);
  background:transparent;
  border-color:var(--line2);
  color:var(--mute);
  transition:border-color .14s,color .14s}

/* what you will be DOING together */
.lfg-chip[data-fam="play"]{color:#F08CA0;border-color:rgba(232,84,110,.34)}
/* who you will be doing it WITH */
.lfg-chip[data-fam="vibe"]{color:#7FD9A2;border-color:rgba(63,191,111,.34)}
/* how long, and on what */
.lfg-chip[data-fam="term"]{color:var(--acc-gold);border-color:rgba(251,211,128,.34)}
/* where they are, what they speak, how old */
.lfg-chip[data-fam="who"]{color:#8FC6F0;border-color:rgba(90,169,230,.34)}

.lfg-chip:hover{border-color:currentColor}

/* "با هماهنگی" is a caveat, not a category - it stays out of the colour
   system so it does not read as a fifth family. */
.lfg-chip-quiet{opacity:.55;color:var(--dim);border-color:var(--line)}

/* ---------------------------------------------------------- 3. THE SLOTS
   A group with one place left is the ad worth answering now. */
.lfg-slots.is-last{color:var(--acc-gold)}
.lfg-slots.is-last .ico{opacity:1;color:var(--acc-gold)}
.lfg-slots.is-last b{color:var(--acc-gold)}
.lfg-slots.is-last small{
  font-size:9.5px;font-weight:700;padding:1px 6px;
  border:1px solid rgba(251,211,128,.4)}

/* Full is the opposite signal: still listed, no longer an invitation. */
.lfg-slots.is-full{opacity:.55}
.lfg-slots.is-full small{font-size:9.5px;color:var(--dim)}

/* ===========================================================================
   WAVE 18 — CLAN ANNOUNCEMENTS  (.cn-*)
   ---------------------------------------------------------------------------
   The `news` unlock, in two places that must not look like two features: the
   clan page card and the dashboard strip share every .cn-* rule below, and
   only the two .cn-strip-* wrappers differ.

   A LEFT RAIL, NOT A CARD PER NOTICE. Announcements are a list of things one
   person said, so they read as a stack against a single gold edge — boxing
   each one would say "separate object" about paragraphs of the same voice and
   flatten the page into yet another grid of tiles.

   In RTL the rail is the RIGHT edge, which is why every offset here is written
   with border-inline-start / padding-inline-start rather than -left. Get that
   wrong and the rail lands on the far side of the text from where the eye
   starts reading.
   ======================================================================== */

.cn-card .card-t{margin-bottom:var(--s2)}

/* ------------------------------------------------------------ compose form */
.cn-form{
  display:flex; flex-direction:column; gap:10px;
  padding:14px; margin-bottom:var(--s3);
  background:linear-gradient(180deg,rgba(251,211,128,.045),transparent 70%);
  border:1px solid var(--gx-line-soft);
  border-inline-start:2px solid var(--acc-gold);
  border-radius:4px;
}
.cn-body-in{resize:vertical; min-height:64px; line-height:1.75; font-family:var(--ui)}
.cn-form-foot{
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--s2); flex-wrap:wrap;
}
.cn-form-foot .card-note{margin:0; font-size:11.5px; flex:1 1 220px}

/* ------------------------------------------------------------- one notice */
.cn-row{
  position:relative;
  padding:2px 0 var(--s2) 0;
  padding-inline-start:16px;
  margin-bottom:var(--s2);
  border-inline-start:2px solid var(--gx-line);
}
/* Newest notice is the one being announced; the rest are context. */
.cn-row:first-of-type{border-inline-start-color:var(--acc-gold)}
.cn-row:last-of-type{margin-bottom:0; padding-bottom:0}

/* The dot that ties the notice to the rail. Inset rather than centred so it
   sits ON the line in both directions without a transform. */
.cn-row::before{
  content:''; position:absolute; top:7px; inset-inline-start:-5px;
  width:8px; height:8px; border-radius:50%;
  background:var(--panel); border:2px solid var(--gx-line);
}
.cn-row:first-of-type::before{
  border-color:var(--acc-gold);
  box-shadow:0 0 0 3px rgba(251,211,128,.12);
}

.cn-head{display:flex; align-items:baseline; gap:10px; flex-wrap:wrap}
.cn-title{font-size:14.5px; color:var(--bone); line-height:1.5}
.cn-when{margin-inline-start:auto; font-size:11px; color:var(--dim); white-space:nowrap}

/* --dim, not --off: who said this is information, and --off on the panel
   ground measures about 2.6:1, which is a name you cannot read. */
.cn-by{margin:3px 0 0; font-size:11px; color:var(--dim)}
.cn-edited{
  margin-inline-start:6px; padding:1px 6px; border-radius:3px;
  font-size:10px; color:var(--acc-orange);
  background:rgba(232,134,46,.10); border:1px solid rgba(232,134,46,.22);
}

.cn-body{
  margin-top:8px; font-size:13px; line-height:1.95; color:var(--mute);
  overflow-wrap:anywhere;
}
.cn-body p{margin:0 0 8px}
.cn-body p:last-child{margin-bottom:0}
.cn-body a{color:var(--acc-gold)}
.cn-body ul,.cn-body ol{margin:0 0 8px; padding-inline-start:20px}
.cn-body img{max-width:100%; height:auto; border-radius:3px}

/* ----------------------------------------------------------- manage tools */
.cn-acts{display:flex; align-items:flex-start; gap:8px; margin-top:10px; flex-wrap:wrap}
.cn-edit{flex:1 1 100%}
.cn-edit>summary{
  display:inline-block; cursor:pointer; list-style:none;
  padding:3px 10px; border-radius:3px;
  font-size:11px; color:var(--dim);
  border:1px solid var(--line2); background:var(--panel2);
}
.cn-edit>summary::-webkit-details-marker{display:none}
.cn-edit>summary:hover{color:var(--gold-light); border-color:var(--gx-line)}
.cn-edit[open]>summary{color:var(--acc-gold); border-color:var(--acc-gold)}
.cn-edit form{display:flex; flex-direction:column; gap:8px; margin-top:10px}

/* --------------------------------------------------------------- archived */
.cn-past{margin-top:var(--s3); border-top:1px solid var(--line); padding-top:var(--s2)}
.cn-past>summary{
  cursor:pointer; list-style:none;
  font-size:12px; color:var(--dim);
}
.cn-past>summary::-webkit-details-marker{display:none}
.cn-past>summary::before{content:'▾ '; color:var(--gold-dark)}
.cn-past>summary:hover{color:var(--mute)}
.cn-past-row{
  display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;
  padding:7px 0; border-bottom:1px solid var(--line);
  font-size:12px; color:var(--off);
}
.cn-past-row:last-child{border-bottom:0}
.cn-past-row b{font-weight:400; color:var(--dim)}
.cn-past-row .num{margin-inline-start:auto}

/* ===================================================== the dashboard strip
   Same notices, on somebody else's screen. It carries a gold wash across the
   whole card rather than a per-row rail, because on the dashboard the card
   itself is the thing that has to be noticed among a dozen stat tiles — once
   the player is looking at it, the rows can be quiet.
   ===================================================================== */
.cn-strip{
  background:
    radial-gradient(120% 100% at 100% 0,rgba(251,211,128,.07),transparent 62%),
    var(--panel);
  border-color:var(--gx-line);
}
.cn-strip .card-t::after{
  content:''; display:inline-block; width:5px; height:5px; border-radius:50%;
  margin-inline-start:8px; vertical-align:middle;
  background:var(--acc-gold); box-shadow:0 0 8px rgba(251,211,128,.6);
}
.cn-strip-row{
  padding:12px 0; border-bottom:1px solid var(--line);
}
.cn-strip-row:last-of-type{border-bottom:0}
.cn-strip-row .cn-title{font-size:14px}
/* Two notices at most reach here, so a body can run long without burying the
   cards under it. Clamped rather than truncated server-side: the full text is
   one click away on the clan page and the clamp is only about this screen. */
.cn-strip-row .cn-body{
  display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical;
  overflow:hidden;
}

.cn-strip-ev{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  margin-top:10px; padding:9px 12px; border-radius:4px;
  background:var(--panel2); border:1px solid var(--line);
  border-inline-start:2px solid var(--acc-blue);
}
.cn-strip-ev .cn-when{margin-inline-start:auto}
.cn-strip .card-more{margin-top:var(--s2)}

@media (max-width:640px){
  .cn-when{margin-inline-start:0; width:100%}
  .cn-strip-ev .cn-when{margin-inline-start:0}
  .cn-past-row .num{margin-inline-start:0}
}

/* Archiving is not deleting — nothing leaves the table, the notice just stops
   being current. `btn-danger` said otherwise in red, on a page whose whole
   palette is gold, so this is the quiet version: a warm outline that reads as
   "put away" rather than "destroy". */
.cn-arch{
  color:var(--gold-light); border-color:var(--gx-line);
  background:rgba(251,211,128,.04);
}
.cn-arch:hover{
  color:var(--acc-gold); border-color:var(--acc-gold);
  background:rgba(251,211,128,.10);
}

/* ===========================================================================
   WAVE 19 — THE CLAN ALBUM  (.cg-*)
   ---------------------------------------------------------------------------
   Deliberately NOT the community gallery's `.gal`. That grid is a showcase:
   square crops, a hero tile, hover zoom, everything tuned to make a stranger
   stop scrolling. This one is a reference album a clan looks things up in —
   "what did we build last wipe" — so the tiles stay even, the caption is part
   of the tile rather than an overlay you have to hover to read, and nothing
   moves when the pointer crosses it.

   The privacy note is styled to be read, not skipped. It is the one line that
   tells a member their base photo is not going anywhere public, and it is the
   reason they will actually upload one.
   ======================================================================== */

.cg-card .card-t{margin-bottom:var(--s2)}

/* ---------------------------------------------------------------- the form */
.cg-form{
  display:flex; flex-direction:column; gap:10px;
  padding:14px; margin-bottom:var(--s3);
  background:linear-gradient(180deg,rgba(90,169,230,.05),transparent 70%);
  border:1px solid rgba(90,169,230,.16);
  border-inline-start:2px solid var(--acc-blue);
  border-radius:4px;
}
.cg-form-row{display:flex; gap:10px; flex-wrap:wrap; align-items:center}
.cg-form-row .owner-input{flex:1 1 180px; min-width:0}
.cg-form-row .btn{flex:0 0 auto}

/* The native file button is unstyleable from outside; ::file-selector-button
   is the one hook, and without it the control renders as a light-grey system
   chip on a black card. */
.cg-file{padding:6px 8px; font-size:12px; cursor:pointer}
.cg-file::file-selector-button{
  margin-inline-end:10px; padding:5px 12px;
  font-family:var(--ui); font-size:12px; cursor:pointer;
  color:var(--bone); background:var(--panel2);
  border:1px solid var(--line2); border-radius:3px;
}
.cg-file::file-selector-button:hover{
  color:var(--acc-blue); border-color:rgba(90,169,230,.45);
}

.cg-note{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  margin:0; font-size:11.5px; color:var(--mute);
}
/* A small key icon, drawn rather than loaded, so the privacy line reads as a
   statement about access and not as one more grey caption. */
.cg-note::before{
  content:''; flex:0 0 auto; width:6px; height:6px; border-radius:50%;
  background:var(--acc-blue); box-shadow:0 0 7px rgba(90,169,230,.55);
}
.cg-note .num{margin-inline-start:auto; color:var(--dim)}

/* ---------------------------------------------------------------- the grid */
.cg-grid{
  display:grid; gap:12px;
  /* auto-fit, NOT auto-fill: auto-fill keeps empty tracks, so a clan with two
     pictures would get two tiles and three gaps. The stats grid was fixed the
     same way after it shipped with a hole in it. */
  grid-template-columns:repeat(auto-fit,minmax(170px,1fr));
}

.cg-item{
  position:relative; margin:0;
  background:var(--panel2); border:1px solid var(--line);
  border-radius:5px; overflow:hidden;
}
.cg-item:hover{border-color:rgba(90,169,230,.35)}

.cg-item > a{display:block; aspect-ratio:4/3; background:var(--ink)}
.cg-item img{
  width:100%; height:100%; object-fit:cover; display:block;
  /* No hover zoom. This is a reference album — a tile that jumps when the
     pointer crosses it makes a grid harder to read, not livelier. */
  filter:saturate(.92) brightness(.92); transition:filter .3s;
}
.cg-item:hover img{filter:none}

.cg-cap{
  display:flex; flex-direction:column; gap:3px;
  padding:8px 10px; font-size:11.5px;
}
.cg-cap b{
  font-weight:400; color:var(--bone); line-height:1.6;
  overflow-wrap:anywhere;
}
.cg-meta{display:flex; align-items:baseline; gap:8px; color:var(--dim); font-size:10.5px}
.cg-meta .num{margin-inline-start:auto}

/* Remove sits ON the tile, at the inline-END so it lands top-left in RTL and
   never covers the corner the eye starts reading from. */
.cg-rm{position:absolute; top:6px; inset-inline-end:6px}
.cg-rm button{
  width:22px; height:22px; line-height:1; cursor:pointer;
  font-size:15px; color:var(--mute);
  background:rgba(5,5,5,.72); border:1px solid var(--line2);
  border-radius:3px; backdrop-filter:blur(2px);
}
.cg-rm button:hover{color:var(--white); background:rgba(229,84,75,.85); border-color:transparent}

@media (max-width:640px){
  .cg-grid{grid-template-columns:repeat(auto-fit,minmax(140px,1fr)); gap:8px}
  .cg-form-row .owner-input{flex:1 1 100%}
  .cg-note .num{margin-inline-start:0}
}

/* ===========================================================================
   WAVE 20 — THE ANIMATED BANNER  (.cp-hero.anim-*)
   ---------------------------------------------------------------------------
   The `banner_anim` unlock, and the last item in the clan catalogue. 40,000 XP
   and level 5, so at most a handful of clans on the server will ever wear one —
   which is the point, and also why each motion gets to be distinctive rather
   than one tasteful shared fade.

   WHAT MOVES IS THE IMAGE, NOT THE TEXT. The banner lives in ::before and the
   dimming gradient in ::after; the clan name and chips are real children of the
   hero sitting at z-index 1 above both. So every animation below touches only
   the pseudo-elements, and the name never drifts, shimmers or pulses. A moving
   headline is unreadable, and the point of a banner is what is written on it.

   EVERYTHING HERE IS TRANSFORM AND OPACITY. Those are the two properties the
   compositor can animate without re-laying-out the page; animating
   background-position on a full-bleed hero costs a repaint every frame, and
   this audience is on mid-range Android phones.

   ALL OF IT STOPS FOR prefers-reduced-motion. One block at the end, no
   exceptions — see the note there for why it is written that way.
   ======================================================================== */

/* A touch more room to move into. The banner is already `cover`, so starting
   slightly scaled means a pan never exposes an edge. */
.cp-hero[class*="anim-"].has-banner::before{
  will-change:transform,opacity;
  transform:scale(1.06);
}

/* The inner wrapper is what the extra layers hang off, and it must not trap
   the text above them. */
.cp-hero[class*="anim-"] .cp-hero-in{position:relative; isolation:isolate}

/* ------------------------------------------------------ 1. حرکت آرام (drift)
   Ken Burns. The slowest and the most expensive-looking: a 40 second round
   trip, longer than anybody spends on the page, so it never visibly repeats. */
@keyframes cp-drift{
  0%  {transform:scale(1.06) translate3d(0,0,0)}
  50% {transform:scale(1.13) translate3d(-1.6%,-1.2%,0)}
  100%{transform:scale(1.06) translate3d(0,0,0)}
}
.cp-hero.anim-drift.has-banner::before{
  animation:cp-drift 40s ease-in-out infinite;
}

/* ------------------------------------------------------- 2. برق فلزی (sheen)
   A light sweep carried as a second background layer on the dimming gradient,
   so it costs no extra element. It crosses for a fifth of the cycle and rests
   for the rest — a sheen that sweeps constantly reads as a loading bar. */
@keyframes cp-sheen{
  0%,70%{background-position:-120% 0, 0 0}
  100%  {background-position:220% 0, 0 0}
}
.cp-hero.anim-sheen.has-banner::after{
  background:
    linear-gradient(105deg,transparent 42%,rgba(255,237,200,.20) 50%,transparent 58%),
    linear-gradient(180deg,rgba(5,5,5,.35) 0%,rgba(5,5,5,.92) 100%);
  background-size:220% 100%, 100% 100%;
  background-repeat:no-repeat;
  animation:cp-sheen 9s ease-in-out infinite;
}

/* ------------------------------------------------------- 3. نفس آتش (ember)
   A slow warm breath. Rust is a game about fire and this is the gold the whole
   site already uses, so it is the one motion that looks like it belongs to
   this server rather than to any banner anywhere. */
@keyframes cp-ember{
  0%,100%{opacity:.42}
  50%    {opacity:.58}
}
.cp-hero.anim-ember.has-banner::before{
  animation:cp-ember 7s ease-in-out infinite;
}
/* A warm wash over the top. Same 7s period so the two stay in step rather than
   drifting into a beat pattern that would read as flicker. */
@keyframes cp-ember-glow{
  0%,100%{opacity:.10}
  50%    {opacity:.45}
}
.cp-hero.anim-ember.has-banner .cp-hero-in::before{
  content:""; position:absolute; inset:-50% -10% auto -10%; height:190%;
  z-index:-1; pointer-events:none;
  background:radial-gradient(58% 68% at 50% 0,rgba(251,211,128,.30),transparent 72%);
  animation:cp-ember-glow 7s ease-in-out infinite;
}

/* ----------------------------------------------------------- 4. اسکن (scan)
   A soft band travelling down, over faint static lines. Kept low-contrast on
   purpose: a bright scanline across a photograph is a 1990s screensaver, and
   this has to sit underneath a clan name. */
@keyframes cp-scan{
  0%  {transform:translate3d(0,-120%,0)}
  100%{transform:translate3d(0,320%,0)}
}
.cp-hero.anim-scan.has-banner .cp-hero-in::after{
  content:""; position:absolute; inset:-60% 0 auto 0; height:55%;
  z-index:-1; pointer-events:none;
  background:linear-gradient(180deg,
    transparent 0%,
    rgba(90,169,230,.10) 45%,
    rgba(200,230,255,.16) 50%,
    rgba(90,169,230,.10) 55%,
    transparent 100%);
  animation:cp-scan 6s linear infinite;
}
.cp-hero.anim-scan.has-banner::before{
  /* Static lines under the moving band: two layers, no animation, no cost. */
  background-image:
    repeating-linear-gradient(180deg,rgba(0,0,0,.16) 0 1px, transparent 1px 3px),
    var(--banner);
  background-size:auto, cover;
}

/* ===========================================================================
   THE STOP SWITCH
   ---------------------------------------------------------------------------
   Written as `animation:none` on the rendered classes rather than by having
   Blade leave the class off, because the media query is a LIVE preference: a
   reader who turns motion down while the page is open gets a still banner on
   the next frame, with no reload and no server round trip. Blade cannot do
   that — it decided what to print before the browser knew.

   What is kept still reads as designed rather than broken: scan keeps its
   lines, drift keeps its slight scale. What is dropped is only the two layers
   that exist solely to move.
   ======================================================================== */
@media (prefers-reduced-motion: reduce){
  .cp-hero[class*="anim-"].has-banner::before,
  .cp-hero[class*="anim-"].has-banner::after,
  .cp-hero[class*="anim-"].has-banner .cp-hero-in::before,
  .cp-hero[class*="anim-"].has-banner .cp-hero-in::after{
    animation:none !important;
  }
  .cp-hero.anim-sheen.has-banner::after{background-position:-120% 0, 0 0}
  .cp-hero.anim-ember.has-banner::before{opacity:.42}
  .cp-hero.anim-scan.has-banner .cp-hero-in::after,
  .cp-hero.anim-ember.has-banner .cp-hero-in::before{display:none}
}

/* ------------------------------------------------- the picker in settings */
.cp-motion{display:flex; gap:8px; flex-wrap:wrap; margin-top:8px}
.cp-motion-pick{position:relative; cursor:pointer}
.cp-motion-pick input{position:absolute; opacity:0; width:0; height:0}
.cp-motion-pick span{
  display:block; padding:7px 14px; border-radius:4px;
  font-size:12px; color:var(--mute);
  background:var(--panel2); border:1px solid var(--line2);
  transition:color .2s, border-color .2s, background .2s;
}
.cp-motion-pick:hover span{color:var(--bone); border-color:var(--gx-line)}
.cp-motion-pick input:checked + span{
  color:var(--ink); background:var(--acc-gold); border-color:var(--acc-gold);
  font-weight:600;
}
/* Keyboard focus has to be visible: the real radio is off-screen, so without
   this the only way to know where you are is to already know. */
.cp-motion-pick input:focus-visible + span{
  outline:2px solid var(--acc-gold); outline-offset:2px;
}
.cp-motion-note{margin:8px 0 0; font-size:11px; color:var(--dim)}

/* ===========================================================================
   WAVE 21 — THE 16px FLOOR ON PHONES
   ---------------------------------------------------------------------------
   iOS Safari AUTO-ZOOMS into any form control whose font-size is under 16px,
   and it does not zoom back out afterwards. The reader is left on a page that
   is suddenly too wide, pinching to recover, having done nothing wrong.

   That was happening on the WORST possible control: the custom-amount field in
   the top-up modal, at 13.5px. A player typing how much to pay got the page
   zoomed in mid-payment. The VIP duration select and the shop search did the
   same thing.

   WHY ONE BLANKET RULE AND NOT SIX EDITS. The sizes are set in at least six
   scattered places - .owner-input, .ow-main select, .wipe-form .owner-input,
   .os-grant .owner-input, .oc-item .owner-input, .ns-select, .tu-field input -
   written months apart at different specificities. Editing each one means
   finding all of them today AND every one added later; a single one missed is
   a control that still zooms. A floor applied at the end of the stylesheet
   cannot be missed and cannot be out-specified by a rule written tomorrow.

   `!important` IS DELIBERATE HERE. It is the only thing that beats
   `.wipe-form .owner-input` (0,2,0) without this block having to guess and
   out-climb every future selector. The property is font-size on phones only -
   the narrowest possible blast radius for the bluntest possible tool.

   DESKTOP IS UNTOUCHED. Everything below 768px only.
   ======================================================================== */
@media (max-width: 768px){
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="hidden"]),
  select,
  textarea{
    font-size:16px !important;
  }

  /* 16px text does not fit a box built around 13px. These heights were set as
     a fixed `height`, so without this the taller text is clipped rather than
     the box growing. min-height lets the control grow, and 44px is the touch
     target it should have had anyway. */
  .owner-input,
  .ow-main select,
  .ns-select{
    height:auto;
    min-height:44px;
    padding-top:10px;
    padding-bottom:10px;
  }

  .ow-main textarea.owner-input{min-height:120px}

  /* The top-up modal is the money path, so it gets the same floor and a real
     touch target rather than the 45px it happened to land on. */
  .tu-field input{min-height:46px}

  /* The file input in the clan album renders its own button, and that button
     inherits the control font, so it needs the same room. */
  .cg-file{height:auto; min-height:44px}
  .cg-file::file-selector-button{font-size:14px; padding:8px 14px}
}

/* ===========================================================================
   WAVE 22 — TWO MOBILE NAV FIXES
   ======================================================================== */

/* ------------------------------------------ 1. the account chip, un-clipped
   A REAL RULE THAT HAS BEEN DEAD SINCE IT WAS WRITTEN.

   Line 322 already says `.nav-me{padding:6px 8px}` inside
   @media (max-width:560px). Line 2030 then says
   `.nav-me{...padding:12px 18px 12px 12px...}` with no media query at all.

   Both are specificity (0,1,0). A MEDIA QUERY DOES NOT RAISE SPECIFICITY, so
   the tie is broken by source order and the later, unconditional rule wins -
   on phones too. The mobile padding has never once applied.

   What that looked like: on a 375px screen the chip is 77px wide but its text
   children are display:none, so it is mostly empty padding - and it hangs 25px
   off the left edge of the viewport with its gold border cut in half. It does
   not widen the document (in RTL, overflow past the inline-end edge does not
   grow scrollWidth), which is exactly why an overflow check never caught it.

   Restated here, at the end of the file, where nothing written later at the
   same specificity can quietly undo it again. */
@media (max-width:560px){
  .nav-me{padding:6px 8px}
}

/* --------------------------------------------- 2. bigger targets, same look
   The nav icons measure 34px and the burger 38px. Apple's guideline and
   WCAG 2.5.5 both want 44px; these are tappable but mean, and they are the
   controls a player on a phone uses most - the bell, the messages, and the
   button that opens the top-up modal.

   The hit area is grown with a pseudo-element instead of by resizing the
   control, so NOTHING MOVES. Making the icons visually bigger would reflow a
   nav row that already has only 158px of slack at 375px; this adds the touch
   margin browsers ask for and changes not one pixel of what is drawn. */
@media (max-width:768px){
  .nav-icon,
  .nav-coin-add,
  .nav-burger{position:relative}

  .nav-icon::after,
  .nav-coin-add::after,
  .nav-burger::after{
    content:"";
    position:absolute;
    /* -5px on a 34px control gives 44px; the burger lands at 48px. */
    inset:-5px;
    /* Purely a touch target: it must never paint. It sits INSIDE its own
       control, so the click it receives belongs to that control anyway. */
    background:transparent;
  }
}

/* The last 11px.
   With .nav-me finally taking its mobile padding, the right-hand cluster still
   measures 322px against a 375px screen once the logo has taken its 64px — so
   the account chip, which is the flex item that gives, was still hanging its
   gold border off the edge.

   The row has four 10px gaps in it. Taking them to 6px returns 16px, which
   covers the 11px shortfall with room to spare, and costs nothing anybody will
   notice: these are 34px icons, not text that needs separating. Shrinking a
   control instead would have meant a smaller tap target, which is the opposite
   of what the rule above just bought. */
@media (max-width:560px){
  .nav-r{gap:6px}
}

/* ===========================================================================
   WAVE 23 — THE SCRAP CHIP AND ITS BUTTON
   ---------------------------------------------------------------------------
   The "+" was the only ROUNDED, SOLID-FILLED thing in a row of chamfered
   outlines and 45-degree diamonds: an 8px-radius gold square sitting inside a
   clipped parallelogram, next to icons drawn as hairline lozenges. It read as
   bolted on, because it was — styled on its own terms rather than the bar's.

   It is now the END of the chip rather than an object inside it. The pill
   already carries `clip-path: polygon(9px 0, 100% 0, calc(100% - 9px) 100%,
   0 100%)`, and clip-path clips DESCENDANTS — so a button flush against the
   inline-end edge is cut to the chip's own angle for free, with no second
   clip-path to keep in sync. One object: a dark chip holding a number, with a
   gold slab at the end you press to add more.

   THE GOLD STAYS. This is the button that takes money, and the only commerce
   action in the bar; making it another hairline outline would hide the one
   control the site actually wants found. What changes is its shape.
   ======================================================================== */

.nav-coin{
  /* Padding only on the side the scrap icon sits on. The end belongs to the
     button now, which supplies its own. Logical, because in RTL the button is
     at the LEFT and a physical `padding-left:0` would be right in Persian and
     wrong the moment anything renders LTR. */
  padding-block: 0;
  padding-inline: 11px 0;
  gap: 8px;

  /* Matching .nav-icon's 38px so the whole cluster sits on one baseline; the
     row was previously three different heights pretending to be aligned. */
  height: 38px;

  /* stretch, so the button fills the chip's full height and is cut by the
     parent's clip-path at both corners. */
  align-items: stretch;
}

/* Those two are content, not structure, so they re-centre themselves. */
.nav-coin > img,
.nav-coin > b{align-self:center}

.nav-coin-add{
  /* Was 24x24 with an 8px radius. Now a full-height slab with no radius at
     all — the chip's clip-path draws its angled edge. */
  width: 38px;
  height: auto;
  border: 0;
  border-radius: 0;
  flex: none;
  display: grid;
  place-items: center;
  cursor: pointer;

  /* A little depth, so it reads as a pressable face rather than a flat gold
     rectangle. Top-lit, like everything else on the site. */
  background: linear-gradient(180deg, var(--gold-bright) 0%, var(--gold) 62%, var(--gold-dark) 100%);
  color: var(--ink);

  /* The seam between the number and the button. Without it the gold runs
     straight into the dark fill and the chip looks torn rather than joined. */
  box-shadow: inset 1px 0 0 rgba(0,0,0,.38);

  transition: filter .16s ease, box-shadow .16s ease;
}

.nav-coin-add .ico{width:14px;height:14px;stroke-width:2.6}

.nav-coin-add:hover{
  filter: brightness(1.1);
  box-shadow: inset 1px 0 0 rgba(0,0,0,.38), 0 0 16px -4px var(--gold-bright);
}

/* Pressed state. The bar had none: every other control here answers a click and
   this one did nothing until the modal appeared. */
.nav-coin-add:active{filter:brightness(.94)}

/* The real button is what receives focus, and it had no visible ring. Inset,
   because the chip's clip-path would cut an outset one clean off. */
.nav-coin-add:focus-visible{
  outline: 0;
  box-shadow: inset 0 0 0 2px var(--ink), inset 1px 0 0 rgba(0,0,0,.38);
}

/* The chip itself answers when the button inside it is hovered, so the whole
   thing behaves as the single object it now looks like. */
.nav-coin:has(.nav-coin-add:hover){border-color:var(--acc-gold)}

@media (max-width:560px){
  /* Overrides the older `.nav-coin{padding:4px 5px 4px 9px}` in the 560px block
     further up, which assumed the button had its own inset. */
  .nav-coin{height:34px; padding-inline:9px 0; gap:6px}
  .nav-coin-add{width:34px}
  .nav-coin-add .ico{width:13px;height:13px}
}

/* ===========================================================================
   WAVE 24 — CORRECTING WAVE 22's HIT AREAS
   ---------------------------------------------------------------------------
   Wave 22 grew each nav icon's touch target with `::after{inset:-5px}` and, in
   the same wave, tightened `.nav-r{gap:6px}` to win back 11px of row. Those two
   numbers fight: 5px of expansion on each side of a 6px gap means the two areas
   OVERLAP BY 4px, and the later sibling wins the raycast. Measured, not
   guessed — a hit test 3px to the left of the inbox returned the notifications
   icon.

   So a player tapping just beside the bell opened their messages. That is worse
   than the small target it replaced: a target that is hard to hit is a nuisance,
   one that reliably opens the wrong page is a bug.

   The horizontal expansion is now HALF THE GAP, so the two areas meet exactly
   at the midpoint and never overlap. Vertical stays generous because nothing
   sits above or below in that row. 34px becomes 40x44, which is honest: there
   is no room for more — the right-hand cluster is 306px of a 375px screen once
   the logo has taken its share.
   ======================================================================== */
@media (max-width:768px){
  .nav-icon::after,
  .nav-burger::after{inset:-5px -3px}
}

/* The "+" no longer needs one at all.
   Its ::after was being clipped away in any case: .nav-coin carries a
   clip-path, and clip-path clips DESCENDANTS, so anything reaching past the
   chip's edge was cut off and never received a single tap. It is removed rather
   than left as decoration.

   The button did not lose anything by it. It used to be a 24x24 square floating
   inside the chip; as the chip's end it is now 38x36 on desktop and 34x32 on a
   phone, which is the larger target the expansion was trying to fake. */
@media (max-width:768px){
  .nav-coin-add::after{content:none}
}

/* ===========================================================================
   WAVE 25 — THE STAT BREAKDOWN  (.sb-*)
   ---------------------------------------------------------------------------
   The first screen in this project built on leaderboard.stats_json — a column
   written on every sync since the board went up and read by nothing until now.

   THE BAR IS THE NUMBER. Every row here is a share of its category, and the
   share is drawn as a fill behind the text rather than printed beside it. A
   reader should see that one weapon is four times another without reading a
   single digit; the percentage is there for the person who wants to check, not
   for the person skimming.

   The fill sits in a ::before at z-index -1 under an isolated row, rather than
   as a background-size trick on the row itself, because the row has three
   separate children and a background behind all of them has to be its own
   layer to stay crisp at the edge.

   RTL: the fill grows from the INLINE-START edge, which is the right in
   Persian. `inset-inline-start:0` does that; `left:0` would have every bar
   growing away from the side the eye starts on.
   ======================================================================== */

/* ------------------------------------------------------------ the headline */
.sb-head{
  display:flex; align-items:center; gap:var(--s2); flex-wrap:wrap;
  margin-bottom:var(--s3); padding:14px 16px;
  background:
    radial-gradient(120% 140% at 100% 0,rgba(251,211,128,.07),transparent 60%),
    var(--panel);
  border:1px solid var(--line);
  border-inline-start:2px solid var(--acc-gold);
}

/* The one word for how somebody plays. Loudest thing on the page on purpose —
   it is the line players will screenshot at each other. */
.sb-arch{
  font-family:var(--disp); font-size:19px; line-height:1;
  color:var(--ink); background:var(--acc-gold);
  padding:9px 16px;
  clip-path:polygon(8px 0,100% 0,calc(100% - 8px) 100%,0 100%);
}

.sb-fact{
  display:flex; align-items:baseline; gap:7px;
  font-size:11.5px; color:var(--dim);
}
.sb-fact b{font-size:16px; color:var(--bone); font-weight:700}
.sb-fact .num{font-family:var(--disp); color:var(--gold-light)}

/* -------------------------------------------------------------- the panels */
.sb-grid{
  display:grid; gap:var(--s2); margin-bottom:var(--s3);
  /* auto-fit, not auto-fill: a player with three panels gets three columns,
     not three panels and two holes. */
  grid-template-columns:repeat(auto-fit,minmax(260px,1fr));
}

.sb-card .card-t{margin-bottom:12px}

/* ---------------------------------------------------------------- the rows */
.sb-row{
  position:relative; isolation:isolate;
  display:flex; align-items:center; gap:10px;
  padding:7px 10px; margin-bottom:4px;
  font-size:12.5px;
  background:var(--panel2);
}
.sb-row:last-of-type{margin-bottom:0}

/* The share, drawn. --share is set inline per row because it is DATA, not
   style: it is the one number here that genuinely differs every time. It is
   unitless 0..1, because the bar is drawn with scaleX rather than width.

   SCALEX, NOT WIDTH. Wave 20 states the rule for this codebase — only
   transform and opacity animate, because they are the two the compositor can
   do without laying the page out again — and an animated `width` here would
   have broken it on the very next screen. The element is full width and
   squashed to its share instead.

   The origin is the INLINE-START edge so the bar grows from the side the eye
   starts on. transform-origin takes no logical keyword, so the document
   direction is named explicitly rather than assumed. */
.sb-row::before{
  content:""; position:absolute; z-index:-1;
  inset:0;
  transform:scaleX(var(--share,0));
  transform-origin:right center;
  background:linear-gradient(90deg,rgba(251,211,128,.26),rgba(251,211,128,.10));
  transition:transform .5s cubic-bezier(.2,.7,.3,1);
}
[dir="ltr"] .sb-row::before{transform-origin:left center}

.sb-name{flex:1 1 auto; min-width:0; color:var(--bone); overflow-wrap:anywhere}
.sb-val{flex:0 0 auto; color:var(--mute); font-weight:700}
.sb-share{flex:0 0 auto; width:42px; text-align:end; color:var(--dim); font-size:11px}

/* A headshot is the one row worth colouring differently — it is the stat
   players actually compete over. */
.sb-row.is-head .sb-name{color:var(--acc-gold)}
.sb-row.is-head::before{
  background:linear-gradient(90deg,rgba(251,211,128,.44),rgba(251,211,128,.16));
}

.sb-note{margin:10px 0 0; font-size:11.5px}
.sb-note .num{color:var(--gold-light); font-weight:700}

@media (max-width:640px){
  .sb-grid{grid-template-columns:1fr}
  .sb-arch{font-size:17px; padding:8px 14px}
  .sb-head{gap:12px; padding:12px}
}

/* Somebody who asked their device for less motion does not want a bar sliding
   in behind text they are trying to read. */
@media (prefers-reduced-motion: reduce){
  .sb-row::before{transition:none}
}

/* ===========================================================================
   WAVE 26 — EVERY BOARD, GROUPED  (.lb-boards)
   ---------------------------------------------------------------------------
   Nineteen leaderboards existed, were queried, ranked and paginated, and could
   only be reached by typing ?m= into the address bar. This is the menu that
   admits they are there.

   IT SITS UNDER THE FEATURED ROW AND LOOKS QUIETER THAN IT. The eight boards
   above are the ones people came for; these are the long tail. Making them
   equally loud would bury the popular ones among twenty-three neighbours, so
   the panel reads as a drawer: hairline, low contrast, open on the group you
   are already in.

   The <summary> marker is removed and redrawn, because the native triangle is
   an LTR shape that sits on the wrong side of a Persian heading and cannot be
   moved with any standard property.
   ======================================================================== */

.lb-boards{
  display:grid; gap:6px;
  margin:calc(var(--s2) * -1) 0 var(--s3);
}

.lb-bgroup{
  border:1px solid var(--line);
  background:rgba(0,0,0,.25);
}
.lb-bgroup[open]{border-color:var(--gx-line-soft)}

.lb-bgroup > summary{
  display:flex; align-items:center; gap:10px;
  padding:9px 14px; cursor:pointer;
  font-size:12.5px; color:var(--mute);
  list-style:none;
  transition:color .16s, background .16s;
}
.lb-bgroup > summary::-webkit-details-marker{display:none}
.lb-bgroup > summary:hover{color:var(--bone); background:rgba(251,211,128,.04)}

/* The disclosure arrow, drawn rather than inherited. A CSS triangle rotates
   predictably in both directions; the native marker does not. */
.lb-bgroup > summary::before{
  content:""; flex:none;
  width:0; height:0;
  border-inline-start:5px solid var(--gold-dark);
  border-block:4px solid transparent;
  transition:transform .18s ease;
}
.lb-bgroup[open] > summary::before{transform:rotate(-90deg)}
.lb-bgroup[open] > summary{color:var(--bone)}

.lb-bgroup-t{flex:1 1 auto}
.lb-bgroup-n{
  flex:none; font-size:10.5px; color:var(--off);
  padding:1px 7px; border:1px solid var(--line2);
}

/* -------------------------------------------------------------- the chips */
.lb-bchips{
  display:flex; flex-wrap:wrap; gap:6px;
  padding:0 14px 12px;
}

.lb-bchip{
  padding:6px 12px;
  font-size:12px; color:var(--dim); text-decoration:none;
  background:var(--panel2); border:1px solid var(--line2);
  transition:color .16s, border-color .16s, background .16s;
}
.lb-bchip:hover{color:var(--bone); border-color:var(--gx-line)}

/* The board being read. Gold fill rather than a gold outline, because there is
   exactly one of these on the page and it has to be findable among thirty. */
.lb-bchip.on{
  color:var(--ink); background:var(--acc-gold); border-color:var(--acc-gold);
  font-weight:700;
}

@media (max-width:640px){
  .lb-bchips{padding:0 10px 10px; gap:5px}
  .lb-bchip{padding:7px 11px}
  .lb-bgroup > summary{padding:10px 12px}
}

/* The chips must be HIDDEN when the group is closed, and `display:flex` on a
   direct child of a closed <details> is enough to defeat the browser's own
   hiding of it. Measured on the page rather than assumed: a closed group box
   was 43px tall while the chip wrapper inside it still reported 1150x48, and a
   hit test at a chip's centre returned the site logo — laid out and clipped
   rather than not laid out at all.

   Same family as the [hidden] trap already documented on this project: an
   author `display` silently beats a user-agent rule, and only geometry or
   hit-testing catches it. So the open state drives the display explicitly,
   instead of leaning on the element's default. */
.lb-bchips{display:none}
.lb-bgroup[open] > .lb-bchips{display:flex}

/* ===========================================================================
   WAVE 27 — THE BOARD, REBUILT  (.ir-*)
   ---------------------------------------------------------------------------
   The owner brought two reference screens and asked for exactly that layout in
   this project's colours. This is it: a rail + banner + one wide ranked table
   + a right column of context.

   THREE THINGS THIS SHEET DELIBERATELY DOES NOT DO.

   1. It invents no colours. Every value resolves to a token that already
      existed in :root — including --silver and --bronze, which were already in
      the sheet for exactly this purpose. The reference used red as its accent;
      red is --danger here and means something else, so everywhere the
      reference went red, this goes gold.

   2. It does not touch .lb-*. Twenty-six waves carry that prefix. A new
      namespace costs a few hundred bytes; a half-finished rename costs an
      afternoon and leaves two accent systems live at once.

   3. It sets no max-width on the shell. This is an application screen, not an
      article — the rail pins to the inline-start edge and the table takes the
      rest. A max-width here would leave the dead RTL gutter this project has
      already been caught by once.
   ======================================================================== */

.ir{
  --rail:214px;

  /* 88px, and it is not a guess.
     The site nav is position:fixed with a TRANSPARENT background, so it floats
     over whatever the page puts at the top — which on the homepage is the point
     and here was not: the banner started at y=14 and its kicker rendered behind
     the bar. Measured, the nav is 81px tall when somebody is signed in (the
     account chip is taller than the logged-out links) and about 64px when they
     are not. 88 clears the taller case with a little air; the shorter case just
     gets more air, which costs nothing. */
  --ir-navh:88px;

  display:grid;
  grid-template-columns:var(--rail) minmax(0,1fr);
  align-items:start;
  padding-top:var(--ir-navh);
}

/* ---------------------------------------------------------------------------
   BOARD COLOURS — one per family, the same set the in-game panels use.

   Thirty-one boards is too many to tell apart by name alone, so the family
   carries a colour and the rail, the group headings, the column marks and the
   sorted bar all take it from the same token. Gold stays with combat because
   combat is the headline board and gold is the house accent; the rest are the
   --cl-* values that were already in this sheet for the category charts, so
   the site does not end up with two disagreeing palettes for the same idea.

   The medals are NOT part of this. Gold, silver and bronze mark the rank, not
   the board, and they stay the three metals whichever board you are reading.
   --------------------------------------------------------------------------- */
.ir{--bc:var(--gold)}
.ir-g-overall{--bc:#E0893C}
.ir-g-combat {--bc:var(--gold)}
.ir-g-raid   {--bc:var(--cl-raid)}
.ir-g-gather {--bc:var(--cl-gather)}
.ir-g-build  {--bc:var(--cl-build)}
.ir-g-life   {--bc:var(--cl-life)}

/* --------------------------------------------------------------- the rail */
.ir-side{
  position:sticky; top:var(--ir-navh);
  align-self:start;
  max-height:calc(100vh - var(--ir-navh));
  display:flex; flex-direction:column;
  background:var(--black-deep);
  border-inline-start:1px solid var(--line2);
  overflow:hidden;
}
.ir-side-scroll{overflow-y:auto; padding:10px 0; flex:1; scrollbar-width:thin}
.ir-side-scroll::-webkit-scrollbar{width:3px}
.ir-side-scroll::-webkit-scrollbar-thumb{background:var(--line2)}

.ir-sh{padding:12px 18px 6px; font-size:10.5px; color:var(--off)}
.ir-side a{
  display:flex; align-items:center; gap:11px;
  padding:9px 18px; font-size:13px; color:var(--dim); text-decoration:none;
  border-inline-start:2px solid transparent;
  transition:color .16s, background .16s, border-color .16s;
}
.ir-side a:hover{color:var(--bone); background:rgba(245,245,242,.035)}
.ir-side a.on{
  color:var(--gold-bright); font-weight:700;
  background:linear-gradient(270deg, rgba(217,165,46,.15), transparent 88%);
  border-inline-start-color:var(--gold);
}
.ir-side a .ico{width:15px; height:15px; flex:none}

/* The motto. Persian stays Vazirmatn 900 — letter-spaced caps are Latin
   typography and wrong on this script. */
.ir-side-foot{
  padding:16px 18px; border-top:1px solid var(--line);
  font-weight:900; font-size:14.5px; line-height:1.75; color:var(--gold-dark);
}
.ir-side-foot span{display:block}

.ir-main{min-width:0; padding:14px}

/* ------------------------------------------------------------- the banner */
.ir-hero{
  position:relative; overflow:hidden;
  border:1px solid var(--line2);
  min-height:210px; display:flex; align-items:center;
  background:var(--black-deep);
}
.ir-hero img{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; object-position:50% 42%;
  filter:grayscale(.35) contrast(1.06) brightness(.62);
}
/* Two scrims, not one. A flat overlay dims the photograph evenly and kills it;
   a directional wash keeps the picture legible where there is no type and
   sinks it to near-black where the words sit. */
.ir-hero::after{
  content:""; position:absolute; inset:0;
  background:
    linear-gradient(270deg, rgba(5,5,5,.94) 6%, rgba(5,5,5,.55) 46%, rgba(5,5,5,.2) 100%),
    linear-gradient(0deg, rgba(5,5,5,.88), transparent 58%);
}
.ir-hero-in{position:relative; z-index:1; padding:26px 30px 64px; max-width:620px}
.ir-hero-k{
  font-family:var(--disp); font-size:12px; letter-spacing:.22em;
  color:var(--gold-dark); margin:0 0 8px; direction:ltr;
}
.ir-hero-t{
  margin:0; font-weight:900; font-size:clamp(26px,3.4vw,44px);
  line-height:1.14; letter-spacing:-.02em; color:var(--white);
  text-shadow:0 4px 28px rgba(0,0,0,.9);
}
.ir-hero-t em{font-style:normal; color:var(--gold-bright)}
.ir-hero-s{
  margin:10px 0 0; font-family:var(--script); font-size:clamp(19px,2.3vw,29px);
  line-height:1.3; color:var(--gold-light); transform:rotate(-2.2deg);
  transform-origin:right center;
  text-shadow:0 3px 20px rgba(0,0,0,.95);
}
.ir-hero-b{
  position:absolute; inset-block-end:0; inset-inline:0;
  display:flex; z-index:1; border-top:1px solid rgba(245,245,242,.1);
  background:rgba(5,5,5,.6);
}
.ir-hero-b div{
  flex:1 1 0; padding:9px 14px; min-width:0;
  border-inline-end:1px solid rgba(245,245,242,.08);
}
.ir-hero-b div:last-child{border-inline-end:0}
.ir-hero-b b{display:block; font-size:16px; color:var(--bone); line-height:1.2}
.ir-hero-b span{font-size:10.5px; color:var(--dim)}

/* -------------------------------------------------------------- title row */
.ir-head{display:flex; align-items:flex-end; gap:18px; flex-wrap:wrap; padding:20px 2px 14px}
.ir-h1{margin:0; font-size:clamp(24px,3vw,34px); font-weight:900; letter-spacing:-.02em; line-height:1.16}
.ir-h1 em{font-style:normal; color:var(--gold-bright)}
.ir-lede{margin:6px 0 0; font-size:12.5px; color:var(--off)}
.ir-ctl{margin-inline-start:auto; display:flex; gap:8px; flex-wrap:wrap; align-items:center}
.ir-seg{display:flex; border:1px solid var(--line2)}
.ir-seg a{
  padding:7px 15px; font-size:12.5px; color:var(--dim); text-decoration:none;
  border-inline-start:1px solid var(--line2); transition:color .16s, background .16s;
}
.ir-seg a:first-child{border-inline-start:0}
.ir-seg a:hover{color:var(--bone)}
.ir-seg a.on{background:var(--gold); color:var(--ink); font-weight:700}
.ir-find{
  display:flex; align-items:center; gap:8px;
  background:var(--panel2); border:1px solid var(--line2); padding:6px 11px;
}
.ir-find input{
  background:transparent; border:0; outline:none; color:var(--bone);
  font-family:var(--ui); font-size:12.5px; width:150px; min-width:0;
}
.ir-find input::placeholder{color:var(--off)}
.ir-find .ico{width:14px; height:14px; color:var(--off); flex:none}

/* ------------------------------------------------------------ the columns */
.ir-cols{display:grid; grid-template-columns:minmax(0,1fr) 304px; gap:14px; align-items:start}

/* -------------------------------------------------------------- the table */
.ir-tw{overflow-x:auto; border:1px solid var(--line2); background:var(--panel)}
.ir-tbl{width:100%; border-collapse:collapse; min-width:1000px}
/* top:0, NOT the nav height.
   .ir-tw sets overflow-x:auto so a wide table can scroll sideways — and an
   element with overflow on one axis is a scroll container on BOTH. That makes
   .ir-tw the containing block for this sticky header, so `top: 60px` did not
   mean "60px below the site nav", it meant "60px below the top of the table" —
   which parked the header squarely on top of the first row and hid whoever was
   in first place. Measured, not guessed: the gold medal row was rendering
   behind the header. */
.ir-tbl thead th{
  position:sticky; top:0; z-index:3;
  background:var(--black-deep);
  padding:12px 10px; font-size:11px; font-weight:600; color:var(--off);
  border-bottom:1px solid var(--line2); white-space:nowrap; text-align:center;
}
.ir-tbl thead th.l{text-align:right}
.ir-tbl thead th .ico{width:13px; height:13px; margin-inline-end:4px; vertical-align:-2px}
.ir-tbl thead th a{color:inherit; text-decoration:none; display:inline-block}
.ir-tbl thead th a:hover{color:var(--gold-bright)}
.ir-tbl thead th.sorted{color:var(--gold-bright)}
.ir-tbl td{
  padding:0 10px; height:48px; border-bottom:1px solid var(--line);
  text-align:center; white-space:nowrap;
}
.ir-tbl td.l{text-align:right}
.ir-tbl tbody tr{transition:background .16s}
.ir-tbl tbody tr:hover td{background:rgba(217,165,46,.05)}
.ir-tbl a.ir-cell{display:flex; align-items:center; gap:10px; color:inherit; text-decoration:none; min-width:0}

/* ---- gold, silver, bronze --------------------------------------------- */
.ir-tbl tr.m1 td{background:rgba(217,165,46,.08)}
.ir-tbl tr.m2 td{background:rgba(198,206,218,.05)}
.ir-tbl tr.m3 td{background:rgba(199,123,69,.05)}
.ir-tbl tr.m1 td:first-child{box-shadow:inset 3px 0 0 var(--gold)}
.ir-tbl tr.m2 td:first-child{box-shadow:inset 3px 0 0 var(--silver)}
.ir-tbl tr.m3 td:first-child{box-shadow:inset 3px 0 0 var(--bronze)}

/* Struck, not printed: a hexagon with a lit top-left edge so it reads as
   metal rather than as a coloured chip. */
.ir-medal{
  display:inline-grid; place-items:center; width:27px; height:27px;
  font-family:var(--disp); font-size:13px; color:var(--ink);
  clip-path:polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  direction:ltr;
}
.m1 .ir-medal{background:linear-gradient(150deg,var(--gold-highlight),var(--gold),var(--gold-dark))}
.m2 .ir-medal{background:linear-gradient(150deg,#F2F5F9,var(--silver),#5B606B)}
.m3 .ir-medal{background:linear-gradient(150deg,#E8A878,var(--bronze),#5E4025)}
.ir-rk{font-family:var(--disp); font-size:15px; color:var(--off); direction:ltr}

.ir-av{
  width:28px; height:28px; flex:none; border-radius:50%;
  background:var(--elevated); border:1px solid var(--line2);
  display:grid; place-items:center; object-fit:cover;
  font-family:var(--disp); font-size:12px; color:var(--off);
}
.m1 .ir-av{border-color:var(--gold); box-shadow:0 0 0 2px rgba(217,165,46,.16)}
.m2 .ir-av{border-color:var(--silver)}
.m3 .ir-av{border-color:var(--bronze)}
.ir-nm{font-size:14px; color:var(--bone); overflow:hidden; text-overflow:ellipsis; max-width:200px}
.m1 .ir-nm{color:var(--gold-bright); font-weight:700}
.ir-tier{
  font-family:var(--disp); font-size:9.5px; letter-spacing:.1em;
  color:var(--gold-dark); direction:ltr; display:block; margin-top:1px;
}
.ir-tag{font-family:var(--disp); font-size:12px; color:var(--gold-dark); direction:ltr}
.ir-v{font-family:var(--disp); font-size:15px; color:var(--bone); direction:ltr}
.m1 .ir-v{color:var(--gold-bright)}
.ir-vm{font-size:13px; color:var(--dim)}
.ir-kd{color:var(--gold-light)}

/* The sorted metric gets a bar behind it, drawn from the inline-end edge so it
   grows the way the column reads. */
.ir-bar{position:relative; display:inline-block; min-width:84px; padding:4px 9px}
.ir-bar i{
  position:absolute; inset-block:0; inset-inline-end:0; display:block;
  background:linear-gradient(270deg, rgba(217,165,46,.3), rgba(217,165,46,.04));
  border-inline-start:1px solid rgba(217,165,46,.4);
}
.m1 .ir-bar i{background:linear-gradient(270deg, rgba(242,199,92,.42), rgba(242,199,92,.06))}
.ir-bar b{position:relative; font-family:var(--disp); font-size:15px; direction:ltr}

.ir-pager{display:flex; align-items:center; gap:14px; flex-wrap:wrap; padding:12px 14px; border-top:1px solid var(--line)}
.ir-pgs{display:flex; gap:4px; flex-wrap:wrap}
.ir-pg{
  min-width:31px; height:31px; display:grid; place-items:center;
  background:var(--panel2); border:1px solid var(--line2); color:var(--dim);
  font-family:var(--disp); font-size:13px; text-decoration:none; direction:ltr;
  padding:0 8px; transition:color .16s, border-color .16s;
}
.ir-pg:hover{color:var(--bone); border-color:var(--gold-deep)}
.ir-pg.on{background:var(--gold); border-color:var(--gold); color:var(--ink); font-weight:700}
.ir-pg.off{opacity:.3; pointer-events:none}
.ir-pgn{margin-inline-start:auto; font-size:12px; color:var(--off)}

/* ------------------------------------------------------------- right rail */
.ir-rail{display:grid; gap:14px}
.ir-card{background:var(--panel); border:1px solid var(--line2)}
.ir-ch{display:flex; align-items:center; gap:9px; padding:11px 14px; border-bottom:1px solid var(--line)}
.ir-ch .ico{width:15px; height:15px; color:var(--gold-dark); flex:none}
.ir-ct{font-size:12.5px; font-weight:800; color:var(--bone)}
.ir-cx{margin-inline-start:auto; font-size:11.5px; color:var(--gold-dark); text-decoration:none}
.ir-cx:hover{color:var(--gold-bright)}

.ir-cl{
  display:grid; grid-template-columns:24px minmax(0,1fr) auto; gap:10px;
  align-items:center; padding:9px 14px; border-bottom:1px solid var(--line);
  color:inherit; text-decoration:none;
}
.ir-cl:last-child{border-bottom:0}
.ir-cl:hover{background:rgba(217,165,46,.05)}
.ir-cl.top{background:rgba(217,165,46,.07); box-shadow:inset 3px 0 0 var(--gold)}
.ir-cl-n{font-size:13px; color:var(--bone); overflow:hidden; text-overflow:ellipsis}

.ir-champs{display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:var(--line)}
.ir-champ{background:var(--panel); padding:12px 6px; text-align:center; color:inherit; text-decoration:none}
.ir-champ:hover{background:var(--card-hover)}
.ir-champ .ico{width:16px; height:16px; color:var(--gold-dark); margin-bottom:6px}
.ir-champ small{display:block; font-size:10px; color:var(--off); margin-bottom:5px}
.ir-champ b{display:block; font-size:12px; color:var(--bone); overflow:hidden; text-overflow:ellipsis}
.ir-champ i{font-style:normal; font-family:var(--disp); font-size:12px; color:var(--gold-dark); direction:ltr}

.ir-quote{padding:16px 14px; border-top:1px solid var(--line)}
.ir-quote p{
  margin:0; font-family:var(--script); font-size:19px; line-height:1.55;
  color:var(--gold-light); transform:rotate(-1.4deg); transform-origin:right center;
}
.ir-quote span{display:block; margin-top:10px; font-size:11px; color:var(--off)}

.ir-ms{display:flex; align-items:flex-start; gap:10px; padding:10px 14px; border-bottom:1px solid var(--line); font-size:12px; color:var(--dim); line-height:1.7; color:inherit; text-decoration:none}
.ir-ms:last-child{border-bottom:0}
.ir-ms:hover{background:rgba(217,165,46,.05)}
.ir-ms .ico{width:14px; height:14px; color:var(--gold-dark); margin-top:3px; flex:none}
.ir-ms span{color:var(--dim); font-size:12px}
.ir-ms b{color:var(--bone); font-weight:700}
.ir-ms em{font-style:normal; margin-inline-start:auto; font-size:10.5px; color:var(--off); white-space:nowrap}

.ir-empty{padding:44px 20px; text-align:center; color:var(--off); font-size:13px}

/* ------------------------------------------------------------- responsive */
/* 1440, not 1240. Measured at a 1340px laptop: rail 214 + context column 304 +
   padding left the table 765px against its own 1000px minimum, so eleven
   columns scrolled sideways inside the box on the commonest desktop width
   there is. Dropping the context column one breakpoint earlier gives the table
   ~1098px and it fits whole. */
@media (max-width:1439px){
  .ir-cols{grid-template-columns:1fr}
}
@media (max-width:1024px){
  .ir{grid-template-columns:1fr}
  /* The rail becomes a scrolling strip above the board rather than vanishing.
     A hidden nav is a nav nobody can use, and these are the only links to
     nineteen of the boards. */
  .ir-side{
    position:static; max-height:none; flex-direction:row;
    border-inline-start:0; border-bottom:1px solid var(--line2);
  }
  .ir-side-scroll{display:flex; overflow-x:auto; overflow-y:hidden; padding:0}
  .ir-side a{
    border-inline-start:0; border-bottom:2px solid transparent;
    white-space:nowrap; padding:11px 14px;
  }
  .ir-side a.on{
    border-inline-start:0; border-bottom-color:var(--gold);
    background:linear-gradient(0deg, rgba(217,165,46,.15), transparent 88%);
  }
  .ir-sh, .ir-side-foot{display:none}
  .ir-tbl thead th{top:0}
}
@media (max-width:640px){
  .ir-main{padding:8px}
  .ir-hero{min-height:180px}
  .ir-hero-in{padding:18px 16px 60px}
  .ir-hero-b b{font-size:14px}
  .ir-ctl{width:100%}
  .ir-find input{width:100%}
}

/* --- wave 27b: the catalogue groups inside the rail ---------------------
   Twenty-three boards that are not in the featured eight. They live in the
   rail rather than in a drawer at the bottom of the page, because that is
   where somebody looks for a board — and because the reachability test
   asserts a link exists for every single category, not just the popular ones.

   `display` on a closed <details> child defeats the browser's own hiding, so
   the list is driven from [open] explicitly rather than left to the default.
   This project has already been caught by that once. */
.ir-cat{border-bottom:1px solid var(--line)}
.ir-cat > summary{
  display:flex; align-items:center; gap:8px;
  padding:9px 18px; cursor:pointer; list-style:none;
  font-size:12.5px; color:var(--dim);
  transition:color .16s, background .16s;
}
.ir-cat > summary::-webkit-details-marker{display:none}
.ir-cat > summary:hover{color:var(--bone); background:rgba(245,245,242,.035)}
.ir-cat[open] > summary{color:var(--bone)}
/* Drawn, not inherited: the native marker is an LTR shape that sits on the
   wrong side of a Persian heading and cannot be moved with any property. */
.ir-cat > summary::before{
  content:""; flex:none; width:0; height:0;
  border-inline-start:5px solid var(--gold-dark);
  border-block:4px solid transparent;
  transition:transform .18s ease;
}
.ir-cat[open] > summary::before{transform:rotate(-90deg)}
.ir-cat > summary i{
  margin-inline-start:auto; font-style:normal; font-size:10.5px;
  color:var(--off); border:1px solid var(--line2); padding:0 6px;
}
.ir-cat-a{display:none}
.ir-cat[open] .ir-cat-a{
  display:block; padding:7px 18px 7px 34px;
  font-size:12px; color:var(--off); text-decoration:none;
  border-inline-start:2px solid transparent;
}
.ir-cat[open] .ir-cat-a:hover{color:var(--bone); background:rgba(245,245,242,.03)}
.ir-cat[open] .ir-cat-a.on{color:var(--gold-bright); border-inline-start-color:var(--gold); font-weight:700}
@media (max-width:1024px){
  /* In the horizontal strip a disclosure box makes no sense. The first version
     of this rule hid the groups outright — which would have left twenty-three
     boards with no link at all on a phone, the exact failure this project has
     already been caught by once. So the groups FLATTEN instead: the heading
     goes and every board becomes a chip in the same strip. */
  .ir-cat{display:flex; align-items:center; border-bottom:0}
  .ir-cat > summary{display:none}
  .ir-cat .ir-cat-a,
  .ir-cat[open] .ir-cat-a{
    display:block; white-space:nowrap;
    padding:11px 13px; border-inline-start:0; border-bottom:2px solid transparent;
  }
  .ir-cat[open] .ir-cat-a.on{border-inline-start:0; border-bottom-color:var(--gold)}
}

/* ===========================================================================
   WAVE 28 — FAMILY COLOUR, AND THE CLEAN-UP PASS
   ---------------------------------------------------------------------------
   Everything here reads --bc, the board-family colour set in wave 27. The page
   root carries the ACTIVE board's family, so the sorted column, its bar and the
   rail's current item all tint together; each rail link also carries its own
   family, so the list reads as six groups at a glance instead of thirty-one
   identical rows.
   ======================================================================== */

/* the rail ---------------------------------------------------------------- */
.ir-side a .ico{color:var(--bc); opacity:.5; transition:opacity .16s}
.ir-side a:hover .ico{opacity:.85}
.ir-side a.on{
  color:var(--bc); font-weight:700;
  background:linear-gradient(270deg, color-mix(in srgb, var(--bc) 18%, transparent), transparent 88%);
  border-inline-start-color:var(--bc);
}
.ir-side a.on .ico{opacity:1}

.ir-cat > summary::before{border-inline-start-color:var(--bc)}
.ir-cat[open] > summary{color:var(--bc)}
.ir-cat[open] .ir-cat-a.on{color:var(--bc); border-inline-start-color:var(--bc)}

/* the table --------------------------------------------------------------- */
.ir-tbl thead th.sorted{color:var(--bc)}
.ir-bar i{
  background:linear-gradient(270deg,
    color-mix(in srgb, var(--bc) 32%, transparent),
    color-mix(in srgb, var(--bc) 5%, transparent));
  border-inline-start-color:color-mix(in srgb, var(--bc) 62%, transparent);
}
.m1 .ir-bar i{
  background:linear-gradient(270deg,
    color-mix(in srgb, var(--bc) 46%, transparent),
    color-mix(in srgb, var(--bc) 8%, transparent));
}
.ir-bar b{color:var(--bc)}

/* The hero's kicker and the banner border take the family too, so the top of
   the page agrees with the rest of it rather than being gold on every board. */
.ir-hero-k{color:var(--bc)}
.ir-hero-t em{color:var(--bc)}
.ir-hero{border-block-end:2px solid color-mix(in srgb, var(--bc) 55%, transparent)}
.ir-h1 em{color:var(--bc)}

/* --------------------------------------------------------------- clean-up */

/* The rank tier was as loud as the player's name and repeated fifteen times.
   It is a footnote, so it is sized and coloured like one. */
.ir-tier{font-size:9px; color:var(--off); letter-spacing:.08em}
.m1 .ir-tier,.m2 .ir-tier,.m3 .ir-tier{color:var(--gold-dark)}

/* An em dash at full text colour reads as a value. An absent clan is absent. */
.ir-vm{color:var(--off)}
.ir-tbl td .ir-vm:only-child{color:#3A3A3A}

/* Unsorted figures step back so the column you actually chose is the one the
   eye lands on. Before this, eleven columns shouted equally. */
.ir-tbl td .num{font-size:12.5px}
.ir-tbl td .ir-v{font-size:14px}
.ir-tbl td .ir-bar b{font-size:15.5px}

/* Rows breathe: fifteen of them at 48px was a wall. */
.ir-tbl td{height:44px}
.ir-nm{font-size:13.5px}

/* The context column's cards were three different rhythms; one now. */
.ir-card + .ir-card{margin-top:0}
.ir-champ small{min-height:24px; display:flex; align-items:center; justify-content:center}

@media (max-width:1024px){
  /* The rail is a strip here, so the family colour moves to the underline. */
  .ir-side a.on{
    background:linear-gradient(0deg, color-mix(in srgb, var(--bc) 18%, transparent), transparent 88%);
    border-bottom-color:var(--bc);
  }
}

/* ===========================================================================
   WAVE 29 — THE PLAYER PAGE  (.pp-*)
   ---------------------------------------------------------------------------
   Shares the board shell: .ir grid, .ir-side rail, .ir-hero banner, .ir-card.
   Only what is genuinely new to a profile lives here.

   The page takes its family colour from the ARCHETYPE, so a raider profile
   reads red the way the raid board does. --bc comes from wave 27.
   ======================================================================== */

.pgrid{display:grid; grid-template-columns:repeat(12,minmax(0,1fr)); gap:14px; align-items:start; padding-bottom:10px}
.c2{grid-column:span 2}.c3{grid-column:span 3}.c4{grid-column:span 4}

/* ------------------------------------------------------------- identity */
.pp-hero{min-height:0; display:block}
.pp-id{
  position:relative; z-index:1;
  display:flex; align-items:center; gap:20px; flex-wrap:wrap;
  padding:24px 26px 70px;
}
.pp-av{
  width:98px; height:98px; flex:none; object-fit:cover;
  background:var(--black-deep); border:2px solid var(--bc);
  box-shadow:0 0 0 5px rgba(0,0,0,.45);
}
.pp-av-i{
  display:grid; place-items:center;
  font-family:var(--disp); font-size:40px; color:var(--bc);
}
.pp-who{min-width:210px}
.pp-name{display:flex; align-items:center; gap:12px; flex-wrap:wrap}
.pp-name h1{
  margin:0; font-family:var(--disp); font-size:clamp(28px,3.6vw,46px);
  line-height:1; color:var(--white); direction:ltr;
  text-shadow:0 3px 22px rgba(0,0,0,.9);
}
.pp-on{display:inline-flex; align-items:center; gap:6px; font-size:11.5px; color:var(--live)}
.pp-on i{width:7px; height:7px; border-radius:50%; background:var(--live); animation:pp-pulse 2.4s ease-in-out infinite}
@keyframes pp-pulse{0%,100%{box-shadow:0 0 0 0 rgba(63,207,127,.5)}50%{box-shadow:0 0 0 6px rgba(63,207,127,0)}}
@media (prefers-reduced-motion:reduce){.pp-on i{animation:none}}
.pp-sid{margin:8px 0 0; font-size:11.5px; color:var(--dim)}
.pp-arch{
  display:inline-block; margin:9px 0 0; padding:4px 13px;
  font-size:12px; color:var(--bc); border:1px solid var(--bc);
  background:rgba(0,0,0,.45);
}
.pp-ranks{margin-inline-start:auto; display:flex; gap:10px; flex-wrap:wrap}
.pp-rank{
  display:flex; align-items:center; gap:11px; padding:11px 17px;
  background:rgba(5,5,5,.7); border:1px solid color-mix(in srgb, var(--bc) 45%, transparent);
}
.pp-rank .ico{width:21px; height:21px; color:var(--bc)}
.pp-rank b{display:block; font-family:var(--disp); font-size:20px; color:var(--bc); line-height:1}
.pp-rank span{display:block; font-size:10.5px; color:var(--dim); margin-top:3px}

/* The written summary sits between the banner and the grid. It is the one
   thing on the page that says what the numbers MEAN. */
.pp-summary{
  margin:0 0 14px; padding:14px 18px;
  background:var(--panel); border:1px solid var(--line);
  border-inline-start:2px solid var(--bc);
  font-size:13.5px; line-height:2.05; color:var(--mute);
}

/* ------------------------------------------------------------- the tiles */
.pp-ov{display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:var(--line)}
.pp-t{background:var(--panel); padding:13px 14px; display:flex; gap:11px; align-items:flex-start}
.pp-t .ico{width:18px; height:18px; color:var(--bc); opacity:.75; margin-top:2px; flex:none}
.pp-t small{display:block; font-size:10.5px; color:var(--off); margin-bottom:3px}
.pp-t b{font-family:var(--disp); font-size:20px; color:var(--bone); line-height:1}

/* ------------------------------------------------------------ the level */
.pp-lvl{display:flex; align-items:baseline; gap:10px}
.pp-lvl b{font-size:20px; font-weight:800}
.pp-lvl span{margin-inline-start:auto; font-family:var(--disp); font-size:13px; color:var(--bc)}
.pp-xp{height:9px; background:var(--elevated); margin:10px 0 6px; position:relative; display:block}
.pp-xp i{
  position:absolute; inset-block:0; inset-inline-end:0; display:block;
  background:linear-gradient(270deg, var(--bc), color-mix(in srgb, var(--bc) 45%, transparent));
}
.pp-xpn{font-family:var(--disp); font-size:11.5px; color:var(--off); margin:0}
.pp-sub{font-size:11px; color:var(--off); margin:16px 0 6px}

.pp-mil{display:flex; align-items:center; gap:11px; padding:8px 0; border-bottom:1px solid var(--line)}
.pp-mil:last-of-type{border-bottom:0}
.pp-mb{
  min-width:42px; padding:3px 0; flex:none; text-align:center;
  border:1px solid color-mix(in srgb, var(--bc) 40%, transparent);
  font-family:var(--disp); font-size:13px; color:var(--bc);
}
.pp-mil b{display:block; font-size:12.5px; color:var(--bone); font-weight:700}
.pp-mil span{display:block; font-size:10.5px; color:var(--off)}
.pp-now{
  margin-inline-start:auto; font-style:normal; font-size:10px;
  color:var(--ink); background:var(--bc); padding:1px 7px;
}

/* ------------------------------------------------------------ the chart */
.pp-chart{
  display:flex; align-items:flex-end; gap:6px;
  height:126px; padding-bottom:2px; border-bottom:1px solid var(--line2);
}
.pp-cb{
  flex:1 1 0; min-width:8px; display:block;
  background:linear-gradient(0deg, color-mix(in srgb, var(--bc) 22%, transparent), color-mix(in srgb, var(--bc) 58%, transparent));
  border-top:2px solid var(--bc);
  transition:filter .16s;
}
.pp-cb:hover{filter:brightness(1.35)}
.pp-cb.now{background:linear-gradient(0deg, color-mix(in srgb, var(--bc) 40%, transparent), var(--bc))}
.pp-cx{display:flex; justify-content:space-between; margin-top:8px; font-size:10.5px; color:var(--off)}

/* ----------------------------------------------------------- bar lists */
.pp-list{display:grid; gap:0}
.pp-row{
  display:grid; grid-template-columns:minmax(84px,auto) minmax(0,1fr) auto;
  gap:12px; align-items:center; padding:9px 0; border-bottom:1px solid var(--line);
}
.pp-row:last-child{border-bottom:0}
.pp-row-ic{grid-template-columns:34px minmax(76px,auto) minmax(0,1fr) auto}
.pp-ic{width:34px; height:22px; object-fit:contain; flex:none}
.pp-ic-x{display:grid; place-items:center; color:var(--off)}
.pp-rn{font-size:12.5px; color:var(--mute); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.pp-rb{height:5px; background:var(--elevated); position:relative; display:block}
.pp-rb i{
  position:absolute; inset-block:0; inset-inline-end:0; display:block;
  background:var(--bc); opacity:.8;
}
.pp-rv{font-family:var(--disp); font-size:13.5px; color:var(--bone); direction:ltr}

/* -------------------------------------------------------- picture tiles */
.pp-tiles{display:grid; grid-template-columns:repeat(3,1fr); gap:6px}
.pp-tile{background:var(--panel2); border:1px solid var(--line); padding:11px 6px; text-align:center}
.pp-tile img{width:34px; height:34px; object-fit:contain; margin-bottom:6px}
.pp-tile b{display:block; font-family:var(--disp); font-size:16px; color:var(--bone)}
.pp-tile small{display:block; font-size:10px; color:var(--off); margin-top:2px; line-height:1.4}

/* --------------------------------------------------------------- badges */
.pp-bdg{display:grid; grid-template-columns:repeat(4,1fr); gap:6px}
.pp-bd{background:var(--panel2); border:1px solid var(--line); padding:11px 6px; text-align:center}
/* An unearned badge is shown, not hidden — knowing what is left is the point —
   but it is drained of colour so the earned ones still read as earned. */
.pp-bd img{width:36px; height:36px; object-fit:contain; filter:grayscale(1) opacity(.35)}
.pp-bd.got{border-color:color-mix(in srgb, var(--bc) 45%, transparent); background:color-mix(in srgb, var(--bc) 7%, var(--panel2))}
.pp-bd.got img{filter:none}
.pp-bd b{display:block; font-size:10.5px; color:var(--dim); font-weight:700; margin-top:6px; line-height:1.35}
.pp-bd.got b{color:var(--bone)}
.pp-got{display:block; font-size:9.5px; color:var(--bc); margin-top:4px}
.pp-bdp{display:block; height:3px; background:var(--elevated); position:relative; margin-top:7px}
.pp-bdp i{position:absolute; inset-block:0; inset-inline-end:0; display:block; background:var(--off)}

/* --------------------------------------------------------------- fights */
.pp-fight{
  display:grid; grid-template-columns:64px minmax(0,1fr) auto auto;
  gap:12px; align-items:center; padding:9px 0; border-bottom:1px solid var(--line);
  font-size:12.5px;
}
.pp-fight:last-child{border-bottom:0}
.pp-fv{font-size:11px; font-weight:700}
.pp-fight.win .pp-fv{color:var(--live)}
.pp-fight.loss .pp-fv{color:var(--danger-text)}
.pp-fo{font-family:var(--disp); font-size:13.5px; color:var(--bone); text-decoration:none; direction:ltr}
.pp-fo:hover{color:var(--bc)}
.pp-fw{font-size:11.5px; color:var(--off); direction:ltr}
.pp-fd{font-family:var(--disp); font-size:12.5px; color:var(--dim)}

.pp-clan{
  display:flex; align-items:center; gap:10px; padding:10px 12px;
  background:var(--panel2); border:1px solid var(--line); text-decoration:none;
}
.pp-clan:hover{border-color:color-mix(in srgb, var(--bc) 45%, transparent)}
.pp-clan span:last-child{font-size:11.5px; color:var(--off)}

/* ----------------------------------------------------------- responsive */
@media (max-width:1500px){
  .c4{grid-column:span 6}.c3{grid-column:span 6}.c2{grid-column:span 4}
}
@media (max-width:900px){
  .pp-ranks{margin-inline-start:0; width:100%}
  .pp-rank{flex:1 1 130px}
}
@media (max-width:760px){
  .c4,.c3,.c2{grid-column:span 12}
  .pp-ov{grid-template-columns:repeat(2,1fr)}
  .pp-bdg{grid-template-columns:repeat(2,1fr)}
  .pp-id{padding:18px 16px 66px}
  .pp-av{width:72px; height:72px}
  .pp-fight{grid-template-columns:56px minmax(0,1fr) auto; row-gap:4px}
  .pp-fw{grid-column:2/4}
}

/* wave 29b — the written summary, which is a title, lines and facts. */
.pp-st{display:block; font-size:14px; color:var(--bone); margin-bottom:8px}
.pp-summary p{margin:0 0 6px; font-size:13px; line-height:2.05}
.pp-summary p:last-of-type{margin-bottom:0}
.pp-facts{
  display:flex; flex-wrap:wrap; gap:0 26px;
  margin-top:12px; padding-top:11px; border-top:1px solid var(--line);
}
.pp-facts span{display:block}
.pp-facts small{display:block; font-size:10.5px; color:var(--off)}
.pp-facts b{font-family:var(--disp); font-size:16px; color:var(--bc); direction:ltr; display:inline-block}

/* ===========================================================================
   WAVE 30 — THE STATS THE PLUGIN WAS ALREADY COLLECTING
   ---------------------------------------------------------------------------
   A gun-by-gun accuracy table, a body silhouette lit by where the hits land,
   and a kill-mix ring. All three take the same --bc family colour as the rest
   of the profile.
   ======================================================================== */

.c6{grid-column:span 6}

/* ---------------------------------------------------------- the gun table */
.pp-guns{display:grid}
.pp-gh, .pp-g{
  display:grid;
  grid-template-columns:minmax(0,1fr) 74px 88px minmax(110px,1.1fr) 76px;
  gap:12px; align-items:center; padding:9px 14px;
}
.pp-gh{
  font-size:10.5px; color:var(--off);
  border-bottom:1px solid var(--line2); background:var(--black-deep);
}
.pp-gh span:not(:first-child), .pp-g > *:not(:first-child){text-align:center}
.pp-g{border-bottom:1px solid var(--line); transition:background .16s}
.pp-g:last-child{border-bottom:0}
.pp-g:hover{background:rgba(255,255,255,.02)}
.pp-gn{display:flex; align-items:center; gap:10px; min-width:0}
.pp-gn img{width:38px; height:24px; object-fit:contain; flex:none}
.pp-gn b{
  font-size:12.5px; color:var(--bone); font-weight:500;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.pp-gv{font-family:var(--disp); font-size:14px; color:var(--bone); direction:ltr}
.pp-gd{color:var(--off)}

/* Accuracy is a bar AND a figure. The bar is for comparing rows at a glance;
   the figure is because 28.4% and 31.2% look identical as bars. */
.pp-gacc{position:relative; display:flex; align-items:center; justify-content:center; height:22px}
.pp-gacc i{
  position:absolute; inset-block:0; inset-inline-end:0; display:block;
  background:linear-gradient(270deg,
    color-mix(in srgb, var(--bc) 34%, transparent),
    color-mix(in srgb, var(--bc) 6%, transparent));
  border-inline-start:1px solid color-mix(in srgb, var(--bc) 60%, transparent);
}
.pp-gacc b{position:relative; font-family:var(--disp); font-size:13.5px; color:var(--bc); direction:ltr}

/* ------------------------------------------------------- the body diagram */
.pp-body{display:grid; grid-template-columns:auto minmax(0,1fr); gap:18px; align-items:center}
.pp-fig{width:104px; height:auto; flex:none}
/* --s is the share of hits that landed on this part, 0..1. The fill carries it
   directly, so the silhouette IS the chart — no legend needed to read it. */
.pp-part{
  fill:var(--bc);
  fill-opacity:calc(.09 + var(--s) * .85);
  stroke:color-mix(in srgb, var(--bc) 45%, transparent);
  stroke-width:1;
}
.pp-parts{display:grid; gap:1px; background:var(--line)}
.pp-pt{
  display:grid; grid-template-columns:minmax(0,1fr) auto auto; gap:10px;
  align-items:baseline; padding:8px 10px; background:var(--panel);
  font-size:12px; color:var(--mute);
}
.pp-pt b{font-family:var(--disp); font-size:14px; color:var(--bc); direction:ltr}
.pp-pt i{font-style:normal; font-family:var(--disp); font-size:12px; color:var(--off); direction:ltr; min-width:46px; text-align:left}

/* ------------------------------------------------------------- the donut */
.pp-donutwrap{display:grid; grid-template-columns:auto minmax(0,1fr); gap:18px; align-items:center}
.pp-donut{width:108px; height:108px; flex:none; transform:rotate(-90deg)}
.pp-dring{fill:none; stroke:var(--elevated); stroke-width:5.5}
.pp-dseg{fill:none; stroke-width:5.5; transition:stroke-width .16s}
.pp-dseg:hover{stroke-width:7}
.pp-dlegend{display:grid; gap:7px; min-width:0}
.pp-dl{display:grid; grid-template-columns:9px minmax(0,1fr) auto auto; gap:9px; align-items:baseline; font-size:12px; color:var(--mute)}
.pp-dl i{width:9px; height:9px; display:block; align-self:center}
.pp-dl span{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.pp-dl b{font-family:var(--disp); font-size:13px; color:var(--bone); direction:ltr}
.pp-dl em{font-style:normal; font-family:var(--disp); font-size:11.5px; color:var(--off); direction:ltr; min-width:34px; text-align:left}

/* ----------------------------------------------------------- responsive */
@media (max-width:1500px){
  .c6{grid-column:span 12}
}
@media (max-width:760px){
  .pp-gh, .pp-g{grid-template-columns:minmax(0,1fr) 58px 78px 76px; gap:8px; padding:9px 10px}
  /* Shots is the column to lose first on a phone: accuracy already carries it,
     and the gun name must not be crushed to fit a raw count. */
  .pp-gh span:nth-child(3), .pp-g > *:nth-child(3){display:none}
  .pp-gn img{width:30px; height:20px}
  .pp-body, .pp-donutwrap{grid-template-columns:1fr; justify-items:center}
  .pp-parts, .pp-dlegend{width:100%}
}

/* ===========================================================================
   WAVE 31 — THE CARD WALL, MADE TO LINE UP
   ---------------------------------------------------------------------------
   Three measured faults, three fixes.

   1. RAGGED CARD HEIGHTS. .pgrid had align-items:start, so a card never grew
      to its row. Measured on one profile the spread inside a row was 168, 248,
      115 and 51 pixels — a 445px card beside a 197px one leaves 248px of black
      that reads as a rendering fault. Cards stretch now, and their bodies
      stretch with them, so a row has one bottom edge.

   2. DEAD COLUMNS. A fixed twelve-column grid with hand-assigned spans meant
      the last row used five columns of twelve and left seven empty. The grid
      is auto-filled now: the browser fits as many equal cards as the width
      allows, so there is no arithmetic left to get wrong, and it reflows at
      every width instead of at three hand-picked breakpoints.

   3. ORPHAN TILES. .pp-tiles was a hard three columns holding four resources,
      so the fourth sat alone under two empty cells. auto-fit gives four items
      four columns and three items three.
   ======================================================================== */

.pgrid{
  grid-template-columns:repeat(auto-fill, minmax(330px, 1fr));
  align-items:stretch;
  /* Backfills a gap with the next card that fits it, so a wide card pushed to
     the following row does not leave a hole behind it. */
  grid-auto-flow:row dense;
}

/* Spans are "one cell" or "two" now, not a twelfth of a fixed row. Only the gun
   table asks for two: it carries five columns of its own. */
.c2, .c3, .c4{grid-column:auto}
.c6{grid-column:span 2}

/* A stretched card has to pass that height down, or the card grows and the
   panel inside it does not — the same ragged edge one level in. */
.pgrid > .ir-card{display:flex; flex-direction:column}
.pgrid > .ir-card > .ir-cb,
.pgrid > .ir-card > .pp-ov,
.pgrid > .ir-card > .pp-guns{flex:1 1 auto}

/* Lists inside a stretched card spread to fill it rather than bunching at the
   top over a pool of empty panel. */
.pgrid > .ir-card > .ir-cb.pp-list{display:flex; flex-direction:column; justify-content:space-around}

/* Twelve tiles in three columns is four even rows; they should share any extra
   height rather than leave it under the last one. */
.pp-ov{grid-auto-rows:1fr}
.pp-guns{align-content:start}

/* ------------------------------------------------------------ tile grids */
.pp-tiles{grid-template-columns:repeat(auto-fit, minmax(86px, 1fr))}
.pp-bdg{grid-template-columns:repeat(auto-fit, minmax(92px, 1fr))}

/* ------------------------------------------------------------- the chart */
/* Two wipes were drawn as two half-card-wide slabs, because every bar was
   flex:1. A bar has a sensible maximum now and the row centres, so a new server
   with one wipe looks like a chart with one bar rather than a solid block of
   colour. */
.pp-chart{justify-content:center}
.pp-cb{flex:1 1 0; max-width:54px}

/* --------------------------------------------------------- sparse cards */
/* Content that genuinely cannot fill a tall row centres in it instead of being
   pinned to the top with a void underneath. */
.pp-clan, .pp-body, .pp-donutwrap{align-self:center}
.ir-card > .ir-cb > .ir-empty{margin:auto}

@media (max-width:700px){
  /* One card per row below this: minmax would otherwise keep two 330px tracks
     on a 375px phone and push the page sideways. */
  .pgrid{grid-template-columns:1fr}
  .c6{grid-column:auto}
}


/* wave 31c — the machine tiles.
   Two of these at most, and each is a bigger moment than anything else on the
   page, so they are sized as a statement rather than as another list row. */
.pp-tile.pp-big{padding:16px 8px}
.pp-tile.pp-big .ico{width:26px; height:26px; color:var(--bc)}
.pp-tile.pp-big b{font-size:24px; color:var(--bc); margin-top:6px}
.pp-tile.pp-big small{font-size:11px; color:var(--mute)}

/* ===========================================================================
   WAVE 32 — MOTION
   ---------------------------------------------------------------------------
   Every bar, ring and badge on this page is a number drawn as a length. Growing
   them from nothing on load is the one animation that says something true: you
   watch the figure arrive rather than find it already there.

   THE RULES THIS FOLLOWS.
   - Nothing starts at opacity 0 waiting on a scroll observer. The page at rest,
     before any script runs, is the finished page; motion only replays it.
   - Only transform and opacity are animated. Width would relayout every row.
   - prefers-reduced-motion turns the whole thing off in one block.
   ======================================================================== */

@keyframes ir-grow{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes ir-rise{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes ir-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes ir-ring{from{stroke-dasharray:0 100}}

/* Bars grow from the inline-end edge, which is the edge they are anchored to,
   so they unroll the way the eye reads them. */
.pp-rb i, .pp-gacc i, .pp-xp i, .pp-bdp i, .ir-bar i{
  transform-origin:right center;
  animation:ir-grow .62s cubic-bezier(.2,.8,.25,1) both;
}
.pp-chart .pp-cb{transform-origin:bottom; animation:ir-rise .55s cubic-bezier(.2,.8,.25,1) both}

/* A stagger, computed from the row index by nth-child rather than by a style
   attribute per element — the markup stays clean and the cascade does the work. */
.pp-list .pp-row:nth-child(1) i{animation-delay:.02s}
.pp-list .pp-row:nth-child(2) i{animation-delay:.07s}
.pp-list .pp-row:nth-child(3) i{animation-delay:.12s}
.pp-list .pp-row:nth-child(4) i{animation-delay:.17s}
.pp-list .pp-row:nth-child(5) i{animation-delay:.22s}
.pp-list .pp-row:nth-child(6) i{animation-delay:.27s}
.pp-g:nth-child(2) .pp-gacc i{animation-delay:.04s}
.pp-g:nth-child(3) .pp-gacc i{animation-delay:.09s}
.pp-g:nth-child(4) .pp-gacc i{animation-delay:.14s}
.pp-g:nth-child(5) .pp-gacc i{animation-delay:.19s}
.pp-chart .pp-cb:nth-child(2){animation-delay:.05s}
.pp-chart .pp-cb:nth-child(3){animation-delay:.1s}
.pp-chart .pp-cb:nth-child(4){animation-delay:.15s}
.pp-chart .pp-cb:nth-child(5){animation-delay:.2s}
.pp-chart .pp-cb:nth-child(6){animation-delay:.25s}

/* The donut draws itself round. The dasharray each segment carries is its own
   share, so animating FROM zero lands exactly on the value already in the
   markup — the ring cannot end up disagreeing with the legend beside it. */
.pp-dseg{animation:ir-ring .9s cubic-bezier(.2,.8,.25,1) both}
.pp-dseg:nth-child(3){animation-delay:.08s}
.pp-dseg:nth-child(4){animation-delay:.16s}
.pp-dseg:nth-child(5){animation-delay:.24s}
.pp-dseg:nth-child(6){animation-delay:.32s}

/* The body silhouette fades its fill up rather than popping in lit. */
@keyframes ir-lit{from{fill-opacity:.06}}
.pp-part{animation:ir-lit .8s ease both}
.pp-part:nth-child(2){animation-delay:.06s}
.pp-part:nth-child(3){animation-delay:.12s}
.pp-part:nth-child(4){animation-delay:.18s}
.pp-part:nth-child(6){animation-delay:.24s}

/* Cards arrive in a short wave. Six steps, then every later card uses the last
   one — a fortieth card must not wait two seconds to exist. */
.pgrid > .ir-card{animation:ir-in .45s ease both}
.pgrid > .ir-card:nth-child(2){animation-delay:.04s}
.pgrid > .ir-card:nth-child(3){animation-delay:.08s}
.pgrid > .ir-card:nth-child(4){animation-delay:.12s}
.pgrid > .ir-card:nth-child(5){animation-delay:.16s}
.pgrid > .ir-card:nth-child(n+6){animation-delay:.2s}

/* -------------------------------------------------------------- hover life */
.pp-tile, .pp-bd{transition:transform .18s cubic-bezier(.2,.8,.25,1), border-color .18s}
.pp-tile:hover, .pp-bd.got:hover{transform:translateY(-3px); border-color:var(--gold-deep)}
.pp-gn img{transition:transform .2s cubic-bezier(.2,.8,.25,1)}
.pp-g:hover .pp-gn img{transform:scale(1.12)}
.pp-rank{transition:border-color .2s, transform .2s}
.pp-rank:hover{transform:translateY(-2px); border-color:var(--gold)}

/* The champion avatar keeps a slow breath so the top of the page is not dead. */
@keyframes ir-halo{
  0%,100%{box-shadow:0 0 0 5px rgba(0,0,0,.45), 0 0 22px -6px var(--gold)}
  50%{box-shadow:0 0 0 5px rgba(0,0,0,.45), 0 0 34px -2px var(--gold)}
}
.pp-av{animation:ir-halo 4.5s ease-in-out infinite}

@media (prefers-reduced-motion:reduce){
  .pp-rb i, .pp-gacc i, .pp-xp i, .pp-bdp i, .ir-bar i,
  .pp-chart .pp-cb, .pp-dseg, .pp-part, .pgrid > .ir-card, .pp-av{
    animation:none;
  }
  .pp-tile, .pp-bd, .pp-gn img, .pp-rank{transition:none}
}

/* ===========================================================================
   WAVE 33 — THE ACHIEVEMENTS PANEL  (.ach-*)
   ---------------------------------------------------------------------------
   Fifty rows an owner scans down a column of number inputs. The row exists to
   get the eye to that input, so everything else steps back: the English name
   carries, the Persian name and the condition are support, and the input is the
   only lit thing in the row.
   ======================================================================== */

.ach-rows{display:grid}
.ach-head, .ach-row{
  display:grid;
  grid-template-columns:minmax(150px,1.1fr) minmax(0,1.6fr) 88px 128px;
  gap:14px; align-items:center; padding:10px 14px;
}
.ach-head{
  font-size:10.5px; color:var(--off);
  border-bottom:1px solid var(--line2); background:var(--black-deep);
}
.ach-head span:nth-child(n+3), .ach-row > span:nth-child(n+3){text-align:center}
.ach-row{border-bottom:1px solid var(--line)}
.ach-row:last-child{border-bottom:0}
.ach-row:hover{background:rgba(255,255,255,.02)}

.ach-name b{display:block; font-size:13px; color:var(--bone); font-weight:700}
.ach-name small{display:block; font-size:11px; color:var(--off); margin-top:1px}
.ach-hint{font-size:12px; color:var(--mute); line-height:1.7}
.ach-target{font-family:var(--disp); font-size:14px; color:var(--dim); direction:ltr}

/* Untracked rows are dimmed but NOT disabled — the XP is still editable,
   because setting it before the plugin event exists is a reasonable thing to
   want to do. The chip is what says it will not fire yet. */
.ach-row.is-blocked .ach-name b,
.ach-row.is-blocked .ach-hint,
.ach-row.is-blocked .ach-target{color:var(--off)}
.ach-chip{
  display:inline-block; margin-top:5px; padding:2px 8px;
  font-size:9.5px; color:var(--gold-dark);
  border:1px dashed var(--gold-deep); background:rgba(251,211,128,.05);
}

.ach-xp{display:flex; align-items:center; gap:7px; justify-content:center}
.ach-xp input{
  width:84px; padding:7px 9px; text-align:center;
  font-family:var(--disp); font-size:14px; color:var(--gold);
  background:var(--black-deep); border:1px solid var(--line2);
  direction:ltr;
}
.ach-xp input:focus{outline:none; border-color:var(--gold); background:#0B0B0D}
.ach-xp i{font-style:normal; font-size:10px; color:var(--off)}

.ach-save{
  position:sticky; bottom:0; z-index:5;
  display:flex; align-items:center; gap:16px; flex-wrap:wrap;
  margin-top:16px; padding:14px 16px;
  background:rgba(10,10,12,.94); backdrop-filter:blur(8px);
  border:1px solid var(--gold-deep);
}
/* Sticky because the form is fifty rows long: a save button at the bottom of
   that is a scroll away from every change somebody just made. */
.ach-save span{font-size:11.5px; color:var(--off); line-height:1.8}

@media (max-width:860px){
  .ach-head{display:none}
  .ach-row{grid-template-columns:minmax(0,1fr) 118px; gap:8px 12px; padding:12px 12px}
  .ach-hint{grid-column:1; font-size:11.5px}
  .ach-target{display:none}
  .ach-xp{grid-row:1 / span 2; grid-column:2}
}

/* ===========================================================================
   WAVE 34 — THE FIFTY  (.ach-b, .ach-wall)
   ---------------------------------------------------------------------------
   Fifty badges is a wall unless it is grouped, so this is six short rows rather
   than one long grid, with a single summary bar above them all.

   THREE STATES, AND THEY HAVE TO LOOK DIFFERENT AT A GLANCE:
     got   full colour, gold edge, the XP it paid
     open  drained art, a progress bar AND the figure
     off   dashed edge, no bar at all — nothing is counting it, and a bar at
           0% would read as "you have not done this" instead of "this is not
           being measured"
   ======================================================================== */

.ach-card{grid-column:span 2}

.ach-sum{padding:12px 14px; border-bottom:1px solid var(--line)}
.ach-sumbar{display:block; height:7px; background:var(--elevated); position:relative}
.ach-sumbar i{
  position:absolute; inset-block:0; inset-inline-end:0; display:block;
  background:linear-gradient(270deg, var(--bc), color-mix(in srgb, var(--bc) 40%, transparent));
  transform-origin:right center; animation:ir-grow .7s cubic-bezier(.2,.8,.25,1) both;
}
.ach-sum small{display:block; margin-top:7px; font-size:11px; color:var(--off)}

.ach-group{padding:12px 14px; border-bottom:1px solid var(--line)}
.ach-group:last-child{border-bottom:0}
.ach-gh{
  display:flex; align-items:baseline; gap:10px;
  margin:0 0 10px; font-size:12px; color:var(--dim); font-weight:700;
}
.ach-gh i{font-style:normal; font-size:11px; color:var(--off); margin-inline-start:auto}

.ach-wall{display:grid; grid-template-columns:repeat(auto-fill,minmax(126px,1fr)); gap:7px}

.ach-b{
  position:relative; padding:12px 8px 10px; text-align:center;
  background:var(--panel2); border:1px solid var(--line);
  transition:transform .18s cubic-bezier(.2,.8,.25,1), border-color .18s, background .18s;
}
.ach-b:hover{transform:translateY(-3px)}
.ach-b img{
  width:40px; height:40px; object-fit:contain; display:block; margin:0 auto 7px;
  filter:grayscale(1) opacity(.32);
  transition:filter .2s;
}
.ach-b b{display:block; font-size:11px; color:var(--dim); font-weight:700; line-height:1.3; direction:ltr}
.ach-b small{display:block; font-size:10px; color:var(--off); margin-top:2px; line-height:1.4}

/* earned ------------------------------------------------------------------ */
.ach-b.got{
  border-color:color-mix(in srgb, var(--bc) 48%, transparent);
  background:color-mix(in srgb, var(--bc) 8%, var(--panel2));
}
.ach-b.got img{filter:none}
.ach-b.got b{color:var(--bone)}
.ach-b.got:hover{border-color:var(--bc)}
.ach-got{
  display:block; margin-top:7px; padding:2px 0;
  font-size:10px; color:var(--ink); background:var(--bc); font-weight:700;
}

/* in progress ------------------------------------------------------------- */
.ach-bar{display:block; height:3px; background:var(--elevated); position:relative; margin-top:8px}
.ach-bar i{
  position:absolute; inset-block:0; inset-inline-end:0; display:block;
  background:color-mix(in srgb, var(--bc) 70%, transparent);
  transform-origin:right center; animation:ir-grow .6s cubic-bezier(.2,.8,.25,1) both;
}
.ach-prog{display:block; margin-top:5px; font-size:10px; color:var(--off); direction:ltr}

/* not measured yet -------------------------------------------------------- */
/* Dashed, and deliberately WITHOUT a progress bar. A bar sitting at zero is
   read as failure; the absence of one plus a label is read as "not counted". */
.ach-b.off{border-style:dashed; border-color:var(--line2); background:transparent}
.ach-b.off img{filter:grayscale(1) opacity(.14)}
.ach-b.off b, .ach-b.off small{color:var(--off)}
.ach-b.off:hover{transform:none; border-color:var(--gold-deep)}
.ach-off{
  display:block; margin-top:8px; font-size:9px; color:var(--gold-dark);
  border:1px dashed var(--gold-deep); padding:2px 4px; line-height:1.5;
}

@media (max-width:1500px){.ach-card{grid-column:span 2}}
@media (max-width:760px){
  .ach-card{grid-column:auto}
  .ach-wall{grid-template-columns:repeat(auto-fill,minmax(104px,1fr)); gap:6px}
  .ach-b{padding:10px 6px 8px}
  .ach-b img{width:32px; height:32px}
}

/* wave 34b — badge art in the owner panel, and the dashboard claim button. */

/* The owner row now leads with the badge, so the name column is a flex pair
   rather than a stack of text. */
.ach-name{display:flex; align-items:center; gap:11px; min-width:0}
.ach-art{width:32px; height:32px; object-fit:contain; flex:none}
.ach-row.is-blocked .ach-art{filter:grayscale(1) opacity(.35)}
.ach-names{min-width:0}

/* Claiming is the one action on the dashboard wall, so it is the one thing
   that looks like a control. */
.ach-claim{
  display:block; width:100%; margin-top:8px; padding:5px 6px; cursor:pointer;
  font-family:var(--fa); font-size:10px; font-weight:700;
  color:var(--ink); background:var(--gold); border:0;
  transition:background .15s, transform .15s;
}
.ach-claim:hover{background:var(--gold-hot); transform:translateY(-1px)}
.ach-claim:focus-visible{outline:2px solid var(--white); outline-offset:1px}
.ach-prize{display:block; margin-top:8px; font-size:9.5px; color:var(--off)}

/* A badge with XP waiting on it has to pull the eye across fifty others. */
.ach-b.ready{
  border-color:var(--gold);
  background:color-mix(in srgb, var(--gold) 12%, var(--panel2));
  animation:ach-wait 2.6s ease-in-out infinite;
}
@keyframes ach-wait{
  0%,100%{box-shadow:0 0 0 0 rgba(251,211,128,.34)}
  50%{box-shadow:0 0 0 6px rgba(251,211,128,0)}
}
@media (prefers-reduced-motion:reduce){.ach-b.ready{animation:none}}

@media (max-width:860px){
  .ach-art{width:26px; height:26px}
}

/* wave 34c — FIVE columns, not auto-fill.
   ---------------------------------------------------------------------------
   auto-fill picked 6 against category counts of 10, 10, 10, 10, 5 and 5, so
   EVERY group ended ragged — measured trailing gaps of 2, 2, 2, 2, 1, 1. Farm
   and Raid looked worst because the hole sat under a full row.

   Five is the only column count that divides both 10 and 5 exactly, so every
   group is now a complete rectangle. This is a case where the content decides
   the grid rather than the width: letting the browser choose looked tidy in
   the abstract and broken on the page.

   If a category ever holds a count that is not a multiple of five, this goes
   back to being ragged — which is the honest trade for six perfect groups. */
.ach-wall{grid-template-columns:repeat(5, minmax(0, 1fr))}

@media (max-width:1200px){.ach-wall{grid-template-columns:repeat(5, minmax(0, 1fr))}}
@media (max-width:900px){.ach-wall{grid-template-columns:repeat(3, minmax(0, 1fr))}}
@media (max-width:560px){.ach-wall{grid-template-columns:repeat(2, minmax(0, 1fr))}}

/* wave 34d — the full arsenal in the gun table.
   ---------------------------------------------------------------------------
   The table lists EVERY weapon now, not only the ones a player has fired, so
   the rows they have actually used have to stay the ones that read first.
   Unused rows keep their name and their icon — a gun at zero is information,
   it says you have never touched the L96 — but everything about them steps
   back: the art drains, the text dims, and the row loses its hover lift. */
.pp-g.unused{background:transparent}
.pp-g.unused .pp-gn img{filter:grayscale(1) opacity(.22)}
.pp-g.unused .pp-gn b{color:var(--off); font-weight:400}
.pp-g.unused .pp-gv{color:#3E3E44}
.pp-g.unused:hover{background:rgba(255,255,255,.015)}
.pp-g.unused:hover .pp-gn img{filter:grayscale(1) opacity(.45)}

/* Sixty rows is a long card, so it scrolls inside itself rather than making
   the whole profile taller than everything beside it. */
.pp-guns{max-height:620px; overflow-y:auto; scrollbar-width:thin}
.pp-guns::-webkit-scrollbar{width:4px}
.pp-guns::-webkit-scrollbar-thumb{background:var(--line2)}
.pp-gh{position:sticky; top:0; z-index:2}

/* ==========================================================================
   WAVE 34e — the fifty scroll, like the guns do

   Six groups of badges came to 1851px: the card was almost two viewports
   tall, and because .pgrid stretches a row to its tallest card, it dragged
   every card beside it down to the same height. Now the groups live in one
   scrolling body sized to sit level with the gun table next to it.

   Every rule here is scoped under .ach-scroll. .ach-gh and .ach-group are
   shared with the dashboard achievements tab, which has no scroll wrapper —
   an unscoped sticky header would stick to the PAGE over there.
   ========================================================================== */

.ach-scroll{
  flex:1 1 auto; min-height:0;      /* a flex child will not shrink without this */
  max-height:580px; overflow-y:auto; scrollbar-width:thin;
  overscroll-behavior:contain;      /* stops the page scrolling on when it ends */
}
.ach-scroll::-webkit-scrollbar{width:4px}
.ach-scroll::-webkit-scrollbar-thumb{background:var(--line2)}

/* The category header rides with its group. Scrolled a screen into the wall,
   "which of the six am I looking at" is otherwise unanswerable — the badge art
   alone does not say farm from raid. It has to carry the panel colour and span
   the group padding, or the badges scroll through it. */
.ach-scroll .ach-gh{
  position:sticky; top:0; z-index:2;
  margin:-12px -14px 10px; padding:12px 14px 8px;
  background:var(--panel);
}

/* The last group has no border under it, which left the scroll ending flush
   against the card edge with no sign it had ended. */
.ach-scroll .ach-group:last-child{padding-bottom:14px}

/* ==========================================================================
   WAVE 35 — real item art

   The old artwork was WIDE gun renders, so every slot was sized as a landscape
   box (38x24, 34x22) with object-fit:contain. The icons from rust-items are
   SQUARE 128x128, and a square drawn into a 38x24 box renders at 24x24 with
   fourteen pixels of nothing beside it. These slots are square now.
   ========================================================================== */

/* Gun table: 64 rows, so the icon carries most of the scanning. */
.pp-gn img{width:34px; height:34px}

/* The leading cell of .pp-row-ic — top weapons, animals, NPCs, crates. The
   column stays 34px and the art is contained inside it, so an image row and a
   glyph row put their mark in the same place. */
.pp-ic{width:34px; height:26px}

/* Animals, NPCs and crates had no art at all before this; their glyph fallback
   needs to sit at the same weight as a real icon rather than float small. */
.pp-row-ic .pp-ic-x .ico{width:17px; height:17px}

/* Death log: the weapon chip now carries its icon and the English name. */
.db-death-weap{display:inline-flex; align-items:center; gap:5px}
.db-death-weap img{width:16px; height:16px; object-fit:contain; flex:none}

@media (max-width:900px){
  .pp-gn img{width:28px; height:28px}
}

/* ==========================================================================
   WAVE 36 — the achievements page shows the owner's fifty

   The fifty include ones nothing counts yet. On the profile wall they wear a
   chip; this page had no slot for them at all, so they would have sat at 0/5
   looking like something the player had simply never done.
   ========================================================================== */

/* Dashed like .is-secret, because both mean "this card is not telling you a
   number" — but not dimmed to nothing: the achievement is real, and reading it
   is the point of showing it. */
.ah-card.is-blocked{border-style:dashed}
.ah-card.is-blocked:hover{transform:none;background:var(--panel)}

.ah-blocked{
  margin:10px 0 0; padding:3px 8px;
  font-size:10px; line-height:1.6; color:var(--off);
  border:1px solid var(--line2);
}

/* ==========================================================================
   WAVE 37 — tile cards stop being stretched to a neighbour's height

   Measured: the raid-cost card sat in the achievements card's row, so the grid
   stretched it from its natural ~160px to 687px, and its THREE tiles became
   639px tall each — an icon and a number at the top of a 639px box, with the
   dividers between them running the whole way down. The gathered card did the
   same with four.

   .pp-list cards were already handled: their rows spread down the card, which
   is why the animals/NPC/crate row looks right at 362px. A single ROW of tiles
   has nothing to spread — four tiles cannot fill 500px of height in any
   arrangement — so the card has to keep its own height instead.
   ========================================================================== */

/* Rows keep their content height; leftover space is left over, not handed to
   the tiles. Belt and braces with the rule below, and it also protects any
   future card that sets a height. */
.pp-tiles{align-content:start}

/* The card itself stops filling the row. Its bottom no longer lines up with a
   tall neighbour, which is what a card grid normally looks like and is a great
   deal better than half a screen of empty panel.

   :has() is unsupported only on browsers this site already does not target, and
   an unsupported selector is skipped — so the failure mode is today's layout,
   not a broken one. */
.pgrid > .ir-card:has(> .pp-tiles){align-self:start}

/* ==========================================================================
   WAVE 38 — the achievements block gets neighbours its own size

   Reordering alone was not enough. The achievements card is 687px and two
   columns wide, so ONE band of cards beside it is stretched to 687 however
   they are sorted. Two bands are not: the three kill lists are 362 each, and
   362 + gap + 362 is 738 — enough to cover 687 with room to spare.

   So the card claims two row bands, and animals / NPCs / crates / servers fill
   the two columns beside it. Everything genuinely short — machines, raid,
   gathered, clan — then collects in the row underneath, where nothing has to
   pretend to be tall.
   ========================================================================== */

@media (min-width: 1100px) {
  /* The span only does work once the grid reaches three columns (about 1270px),
     which is the first point at which anything can sit beside a two-column
     card. Between 1100 and there it is a no-op — the card already owns both
     columns of both bands — and below 1100 it is off so a narrow layout cannot
     inherit a span it has no room for. Measured at 1120: worst gap 32px, no
     empty band. */
  .pgrid > .ach-card{grid-row:span 2}
}

/* The clan card is usually one line — "not in any clan" — and sat in a panel
   sized for a list. It keeps the height its content asks for now, like the
   tile cards next to it. */
.pgrid > .ir-card:has(> .ir-cb > .ir-empty){align-self:start}

/* ==========================================================================
   WAVE 39 — whitelist: where each server actually stands

   Paying and being let in are two different facts. This is the second one, one
   row per server, and the whole block is absent once every server is granted —
   at which point the days remaining above are the only thing left to read.
   ========================================================================== */

.wl-servers{display:flex; flex-direction:column; gap:8px; margin:16px 0 4px}

.wl-srv{
  display:flex; align-items:center; gap:12px;
  padding:11px 14px;
  background:var(--panel2); border:1px solid var(--line);
}

.wl-srv-n{font-weight:700; color:var(--bone); font-size:13px; min-width:96px}

/* The status takes the space, so the button always sits on the same edge
   however long a server name is. */
.wl-srv-s{flex:1 1 auto; font-size:12px; color:var(--off)}

.wl-srv form{margin:0; flex:none}

/* Granted: stated, not celebrated. It is the row that needs nothing from you,
   so it should be the quietest thing here. */
.wl-srv.is-on{border-color:color-mix(in srgb, var(--bc) 40%, transparent)}
.wl-srv.is-on .wl-srv-s{color:var(--bc)}

/* Waiting on the player is the row that carries an instruction, so it is the
   one that gets the accent. */
.wl-srv.is-wait{border-color:color-mix(in srgb, var(--bc) 28%, transparent)}

.wl-join{
  margin-top:12px; padding:11px 14px;
  border:1px solid color-mix(in srgb, var(--bc) 28%, transparent);
  background:color-mix(in srgb, var(--bc) 6%, transparent);
  color:var(--mute); line-height:2;
}

@media (max-width:560px){
  .wl-srv{flex-wrap:wrap}
  .wl-srv-s{flex:1 1 100%; order:3}
}

/* ---------- owner: site error log ---------- */
/* Read-only rows. The message is LTR because it is an English exception; the
   page around it stays RTL, so each block sets its own direction. */
.lg-row{padding:11px 12px;border-radius:10px;border:1px solid var(--line2);
  margin-bottom:var(--s2);background:rgba(255,255,255,.02)}
.lg-head{display:flex;align-items:center;gap:9px;margin-bottom:6px}
.lg-lv{font-size:11px;padding:2px 7px;border-radius:5px;letter-spacing:.02em}
.lg-error{background:rgba(232,68,42,.15);color:#E8442A}
.lg-warning{background:rgba(255,107,61,.15);color:#FF6B3D}
.lg-info,.lg-debug{background:rgba(255,255,255,.06);color:var(--dim)}
.lg-msg{font-size:12.5px;line-height:1.7;margin:0;word-break:break-word}
.lg-more{margin-top:6px}
.lg-more summary{font-size:11.5px;color:var(--dim);cursor:pointer}
/* The trace is the point of the page, so it scrolls on its own rather than
   stretching the layout sideways. */
.lg-body{margin:7px 0 0;padding:9px;border-radius:8px;background:rgba(0,0,0,.35);
  font-size:11px;line-height:1.6;max-height:320px;overflow:auto;white-space:pre-wrap;
  word-break:break-word}

/* ---------- profile: combat analyzer card ---------- */
/* The second data source. Kept visually quieter than the plugin's own cards
   above it: it adds context, it is not the headline. */
.pp-cbrow{display:flex; flex-wrap:wrap; gap:10px; margin-bottom:var(--s3)}
.pp-cbs{flex:1 1 104px; background:var(--panel); border-radius:9px; padding:9px 11px}
.pp-cbs small{display:block; font-size:10.5px; color:var(--dim); margin-bottom:3px}
.pp-cbs b{font-size:15px; color:var(--bone)}

.pp-cbh{font-size:11.5px; color:var(--dim); margin:0 0 7px}

.pp-rival{
  display:grid; grid-template-columns:minmax(0,1fr) auto auto;
  gap:10px; align-items:center; padding:8px 0; border-bottom:1px solid var(--line);
  font-size:12.5px;
}
.pp-rival:last-child{border-bottom:0}
/* A rival who beats this player more than they lose to them is the interesting
   one, so the record is coloured from THIS player's point of view. */
.pp-rival.is-down .pp-rs{color:var(--danger-text)}
.pp-rival.is-up .pp-rs{color:var(--live)}
.pp-rn{font-family:var(--disp); font-size:13.5px; color:var(--bone); text-decoration:none;
  direction:ltr; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
a.pp-rn:hover{color:var(--bc)}
.pp-rc{font-size:11px; color:var(--dim); direction:ltr}
.pp-rs small{font-size:10px; color:var(--dim); margin:0 3px}

.pp-cbfoot{margin:var(--s3) 0 0; font-size:11.5px; line-height:1.7}

/* ---------- clan: combat analyzer card ---------- */
/* Same second source as the profile card, same restraint: the roster board
   above is the headline, this adds the one thing totals cannot show. */
.cl-combat .card-t .dim{font-size:11px; font-weight:400; margin-inline-start:8px}

.cl-cbrow{display:flex; flex-wrap:wrap; gap:10px; margin-bottom:var(--s3)}
.cl-cbs{flex:1 1 120px; background:var(--panel); border-radius:9px; padding:9px 11px}
.cl-cbs small{display:block; font-size:10.5px; color:var(--dim); margin-bottom:3px}
.cl-cbs b{font-size:15px; color:var(--bone)}

.cl-cbh{font-size:11.5px; color:var(--dim); margin:0 0 7px}

.cl-war{
  display:grid; grid-template-columns:minmax(0,1fr) auto auto;
  gap:10px; align-items:center; padding:8px 0; border-bottom:1px solid var(--line);
  font-size:12.5px;
}
.cl-war:last-child{border-bottom:0}
/* Coloured from THIS clan's point of view, like the profile's rival rows. */
.cl-war.is-down .cl-ws{color:var(--danger-text)}
.cl-war.is-up .cl-ws{color:var(--live)}
.cl-wn{font-family:var(--disp); font-size:13.5px; color:var(--bone); text-decoration:none;
  direction:ltr; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
a.cl-wn:hover{color:var(--bc)}
.cl-wf{color:var(--dim)}
.cl-wf small,.cl-ws small{font-size:10px; color:var(--dim); margin:0 3px}

.cl-cbmeta{margin-top:var(--s3); font-size:12px; line-height:1.9}
.cl-cbmeta p{margin:0}
.cl-cbmeta .dim{margin-inline-end:8px}
.cl-ally{display:inline-block; margin-inline-end:6px; direction:ltr;
  color:var(--bone); text-decoration:none; border-bottom:1px solid var(--line)}
.cl-ally:hover{color:var(--bc)}
