/* Design tokens come from /static/css/_tokens.css, loaded via <link> in every
   page head BEFORE this sheet (FR-3: the render-blocking CSS import chain was removed). */

/* --wgf-gold / --wgf-link / --wgf-gold-2 / --wgf-focus all live in _tokens.css
   (the shadow copies here were removed 2026-07-04, uiux-standardization). */

* {
  box-sizing: border-box;
}

/* === WGF global focus system (added 2026-06-07) === */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--wgf-focus);
  outline-offset: 2px;
}
/* === end focus system === */

/* Skip-to-content link (visually hidden until focused) — added 2026-06-07 */
.wgf-skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: var(--space-2) var(--space-3);
  background: var(--wgf-gold);
  color: var(--wgf-on-gold);
  font-weight: 800;
  text-decoration: none;
  border-radius: 0 0 var(--radius-control) 0;
}
.wgf-skip-link:focus {
  left: 0;
}

body.wgf-shell-page,
body.wgf-page {
  margin: 0;
  min-height: 100vh;
  background:
    radial-gradient(circle at top center, rgba(var(--wgf-gold-rgb), 0.08), transparent 34rem),
    linear-gradient(180deg, var(--wgf-bg-2), var(--wgf-bg));
  color: var(--wgf-text);
  font-family: var(--font-ui);
  line-height: 1.58;
}

/* Display typeface = the MASTHEAD ONLY (2026-07-02 window-chrome pass): page h1s + the
   logo wordmarks. Nav, section headings, footer heads and buttons run on the UI face —
   lapidary caps on every label was the single biggest "template" tell. */
.wgf-shell-page h1, .wgf-page h1, .wgf-article h1,
.wgf-shell-logo, .wgf-site-footer__logo,
.wgf-page-eyebrow {
  font-family: var(--font-display);
}
.wgf-shell-page h2, .wgf-shell-page h3,
.wgf-page h2, .wgf-page h3,
.wgf-article h2, .wgf-article h3,
.wgf-site-footer__nav h2 {
  font-family: var(--font-ui);
  font-weight: 700;
  letter-spacing: 0.01em;
}

/* The lore voice (docs/ui-ux/17-blizzard-palette.md): flavor lines
   speak in Morpheus via --font-game-display so lore-speech is typographically fenced
   off from data and SEO copy. Morpheus has one weight and goes ragged small, so the
   floor is 16px; the color is the muted gold step, never a data color. */
.wgf-lore {
  font-family: var(--font-game-display, serif);
  font-size: 16px;
  color: var(--wgf-gold-muted);
}

.wgf-shell-topbar {
  /* The client window TITLE BAR (docs/ui-ux/13-ingame-reference.md §0.4 + owner law 35):
     an OPAQUE Class Hall stone plate - the same rough dark-slate material as the kit window
     header (.wgf-window__title), over a dark wash, inside a metal edge. No navy fill and NO
     backdrop-filter (both condemned outside tooltips); squared, carved, reads in-game. Token
     fallbacks cover static pages that load this sheet with only _tokens.css. */
  border-bottom: 2px solid var(--wgf-metal, #6e5a2a);
  background:
    linear-gradient(rgba(0, 0, 0, 0.30), rgba(0, 0, 0, 0.42)),
    url(/assets/ui/classhall-stone-tile.png) left top / 256px 256px repeat,
    var(--wgf-plate-hi, #14161c);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    inset 0 -6px 10px rgba(0, 0, 0, 0.4),
    0 6px 18px rgba(0, 0, 0, 0.45);
  position: sticky;
  top: 0;
  z-index: 40;
}

.wgf-shell-topbar__inner {
  max-width: 1220px;
  margin: 0 auto;
  padding: var(--space-2) var(--space-3);
  display: flex;
  justify-content: flex-start;
  gap: var(--space-3);
  align-items: center;
  flex-wrap: nowrap;
}

/* Right-hand cluster: the JS-mounted Enter World / character button (wgf-shell.js) + the
   region-version selector (wgf_selector). Present on EVERY page since 2026-08-27 - seo_kit
   renders it, tools/bake_site_shell.py stamps it into the hand-authored statics, guides_app
   carries it on its user nav - so the two mounts land in the same place sitewide. It is
   pinned to the row's right edge and never grows; the nav takes the slack. ALL row layout
   (desktop grid / mid flex / phone wrap) lives in the HEADER BREAKPOINTS block at the END
   of this sheet - one home, three numbers. */
.wgf-shell-right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  min-width: 0;
  margin-left: auto;
}

.wgf-shell-logo {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--wgf-gold);
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-weight: 900;
  font-size: 15px;
  flex: 0 0 auto;
}

/* Coin mark (SVG). Sized relative to the wordmark so header + footer match. */
.wgf-logo-coin {
  display: inline-block;
  width: 1.5em;
  height: 1.5em;
  flex: 0 0 auto;
}

.wgf-shell-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-left: auto;
  justify-content: flex-end;
}

/* In the topbar the nav is the middle zone: never wraps, never grows, MAY shrink
   (min-width: 0 - a flex item's default min-content floor is what used to push the
   right cluster off the row). Row placement: HEADER BREAKPOINTS at the end. */
.wgf-shell-topbar .wgf-shell-nav {
  flex: 0 1 auto;
  min-width: 0;
  flex-wrap: nowrap;
  margin-left: 0;
  white-space: nowrap;
}

/* Hamburger toggle — hidden on desktop, shown via the mobile media query. */
.wgf-shell-nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-1);
  width: 44px;
  height: 40px;
  padding: 0 var(--space-2);
  background: transparent;
  border: 1px solid var(--wgf-border);
  border-radius: var(--radius-control);
  cursor: pointer;
}

.wgf-shell-nav-toggle__bar {
  display: block;
  width: 22px;
  height: 2px;
  border-radius: 2px;
  background: var(--wgf-gold-2);
  transition: transform 0.2s ease, opacity 0.2s ease;
}

.wgf-shell-topbar.is-open .wgf-shell-nav-toggle__bar:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.wgf-shell-topbar.is-open .wgf-shell-nav-toggle__bar:nth-child(2) {
  opacity: 0;
}

.wgf-shell-topbar.is-open .wgf-shell-nav-toggle__bar:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* Header search — primary lookup entry point. */
/* The search is the PRIMARY action in the bar — it gets the prominent central real estate
   and grows; the pillars compress to the right of it. */
.wgf-shell-search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  min-width: 0;
  max-width: 600px;
  margin: 0 auto 0 var(--space-2);
}

/* Scope toggle (Items / Characters) — injected by wgf-shell.js as the first child of
   the search form. Two themed buttons that replace the un-theme-able native <select>.
   Sits flush-left as the first segment; the input rounds only on the right side. */
.wgf-scope-toggle {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: stretch;
  border: 1px solid var(--wgf-border);
  border-right: none;
  border-radius: var(--radius-pill) 0 0 var(--radius-pill);
  overflow: hidden;
  background: rgba(0, 0, 0, 0.3);
}
.wgf-scope-btn {
  height: 42px;
  padding: 0 11px;
  border: none;
  border-right: 1px solid rgba(var(--wgf-gold-rgb), 0.15);
  background: transparent;
  color: var(--wgf-muted);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.12s ease, background 0.12s ease;
}
.wgf-scope-btn:last-child { border-right: none; }
.wgf-scope-btn:hover {
  color: var(--wgf-gold-2);
  background: rgba(var(--wgf-gold-rgb), 0.08);
}
.wgf-scope-btn.is-active {
  color: var(--wgf-gold);
  background: rgba(var(--wgf-gold-rgb), 0.12);
}

.wgf-shell-search__input {
  width: 100%;
  min-height: 42px;
  padding: var(--space-2) 42px var(--space-2) var(--space-3);
  border: 1px solid var(--wgf-border-strong);
  border-radius: var(--radius-pill);
  background: rgba(0, 0, 0, 0.3);
  color: var(--wgf-text);
  font-family: var(--font-ui);
  font-size: 15px;
}

/* When the scope toggle is present, the input butts against it (flat left edge). */
.wgf-shell-search:has(.wgf-scope-toggle) .wgf-shell-search__input {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}

.wgf-shell-search__input::placeholder {
  color: var(--wgf-muted);
}

.wgf-shell-search__input:focus {
  border-color: var(--wgf-gold-2);
  background: rgba(0, 0, 0, 0.45);
}

.wgf-shell-search__btn {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--wgf-gold-2);
  cursor: pointer;
}

.wgf-shell-search__btn:hover {
  color: var(--wgf-gold);
}

.wgf-shell-search__btn svg {
  width: 17px;
  height: 17px;
}

.wgf-shell-topbar .wgf-shell-nav a {
  color: var(--wgf-text, #f4ecd8);
  text-decoration: none;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 15px;
}

.wgf-shell-topbar .wgf-shell-nav a:hover {
  text-decoration: underline;
}

/* Active page: subtle gold underline, not a filled pill (reserve fills for CTAs). */
.wgf-shell-topbar .wgf-shell-nav a {
  position: relative;
  padding: var(--space-1) var(--space-1);
}

.wgf-shell-topbar .wgf-shell-nav a.is-active {
  color: var(--wgf-gold);
}

.wgf-shell-topbar .wgf-shell-nav a.is-active::after {
  content: "";
  position: absolute;
  left: 4px;
  right: 4px;
  bottom: -2px;
  height: 2px;
  /* Squared, never a pill (owner in-game kit law): a flat carved gold rule under the
     active pillar, not a rounded chip. */
  border-radius: 0;
  background: linear-gradient(90deg, var(--wgf-gold-2), var(--wgf-gold));
}

.wgf-shell-topbar .wgf-shell-nav a:not(.is-active):hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}


.wgf-shell-main,
.wgf-wrap {
  max-width: 1220px;
  margin: 0 auto;
  padding: var(--space-5) var(--space-3) var(--space-6);
}

.wgf-page-hero,
.wgf-hero {
  border: 1px solid var(--wgf-border-strong);
  border-radius: var(--radius-hero);
  background: var(--wgf-bg-hero);
  padding: clamp(var(--space-4), 4vw, 36px);
  box-shadow: 0 28px 70px rgba(0, 0, 0, 0.38);
  margin-bottom: var(--space-3);
}

.wgf-page-hero--split {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-3);
}

.wgf-page-hero__aside {
  flex: 0 0 auto;
}

.wgf-page-eyebrow,
.wgf-home-eyebrow {
  color: var(--wgf-gold-2);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-weight: 850;
  font-size: 12px;
  margin: 0 0 12px;
}

.wgf-page-hero h1,
.wgf-hero h1 {
  color: var(--wgf-gold);
  font-size: clamp(28px, 4.5vw, 48px);
  line-height: 1.05;
  margin: 0 0 var(--space-3);
}

.wgf-page-hero p,
.wgf-hero p {
  max-width: 820px;
  color: var(--wgf-muted);
  font-size: clamp(16px, 2vw, 20px);
  margin: 0;
}

.wgf-tool-panel {
  border: 1px solid var(--wgf-border);
  border-radius: var(--radius-card);
  background: rgba(20, 22, 28, 0.55);
  padding: 0;
  overflow: hidden;
}

.wgf-tool-panel--ah {
  border: none;
  background: transparent;
  overflow: visible;
  width: 100%;
  min-width: 0;
}

body.wgf-ah-page .wgf-shell-topbar__inner,
body.wgf-ah-page .wgf-shell-main {
  max-width: min(1536px, calc(100vw - 36px));
  width: 100%;
}

body.wgf-ah-page .wgf-tool-panel--ah {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

/* AH tool page: low-profile header so the browser fills the viewport */
body.wgf-ah-page .wgf-shell-main {
  padding-top: var(--space-3);
  padding-bottom: 28px;
}

body.wgf-ah-page .wgf-page-hero--ah-compact {
  padding: 2px 2px var(--space-1);
  margin-bottom: var(--space-2);
  border: none;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
}

body.wgf-ah-page .wgf-page-hero--ah-compact h1 {
  font-size: clamp(18px, 2.2vw, 24px);
  margin: 0 0 var(--space-1);
  line-height: 1.15;
  letter-spacing: 0.02em;
}

body.wgf-ah-page .wgf-page-hero--ah-compact .wgf-page-hero--ah-tagline {
  margin: 0;
  font-size: 12px;
  line-height: 1.35;
  color: var(--wgf-muted);
  max-width: 42rem;
}

.wgf-tool-panel .wtd-page {
  max-width: none;
  margin: 0;
  padding: var(--space-3) var(--space-3) var(--space-6);
}

.wgf-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
  gap: var(--space-3);
  margin-top: 0;
}

.wgf-article {
  max-width: 890px;
  margin: var(--space-3) auto 0;
  border: 1px solid var(--wgf-border);
  background: rgba(20, 22, 28, 0.88);
  border-radius: var(--radius-card);
  padding: 2rem;
}

.wgf-article h1,
.wgf-article h2,
.wgf-article h3 {
  color: var(--wgf-gold);
  line-height: 1.18;
}

.wgf-article h1 {
  font-size: clamp(2rem, 4vw, 3rem);
  margin-top: 0;
}

.wgf-meta {
  color: var(--wgf-muted);
  font-size: 0.95rem;
  margin-bottom: 1rem;
}

.wgf-callout {
  border-left: 4px solid var(--wgf-gold-2);
  background: rgba(var(--wgf-gold-rgb), 0.08);
  padding: 1rem;
  border-radius: var(--radius-control);
  color: var(--wgf-text);
}

.wgf-shell-page .wgf-card h2 a {
  color: var(--wgf-gold);
  text-decoration: none;
}

.wgf-shell-page .wgf-card h2 a:hover {
  text-decoration: underline;
}

.wgf-home-hero {
  border: 1px solid var(--wgf-border-strong);
  border-radius: var(--radius-hero);
  background: var(--wgf-bg-hero);
  padding: clamp(28px, 5vw, 58px);
  box-shadow: 0 28px 70px rgba(0, 0, 0, 0.38);
}

.wgf-home-eyebrow {
  color: var(--wgf-gold-2);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-weight: 850;
  font-size: 12px;
  margin-bottom: 12px;
}

.wgf-home-hero h1,
.wgf-shell-page h1 {
  color: var(--wgf-gold);
  font-size: clamp(34px, 6vw, 68px);
  line-height: 0.98;
  margin: 0 0 var(--space-3);
}

.wgf-home-hero p {
  max-width: 820px;
  color: var(--wgf-muted);
  font-size: clamp(17px, 2.1vw, 22px);
  margin: 0 0 var(--space-4);
}

.wgf-home-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-4);
}

.wgf-home-card {
  display: block;
  padding: var(--space-3);
  border: 1px solid var(--wgf-border);
  background: rgba(26, 29, 36, 0.88);
  border-radius: var(--radius-card);
  text-decoration: none;
  transition: border-color 0.2s ease, background 0.2s ease;
}

.wgf-home-card:hover {
  border-color: var(--wgf-gold-2);
  background: rgba(26, 29, 36, 1);
}

.wgf-home-card h2 {
  color: var(--wgf-gold);
  margin: 0 0 var(--space-2);
  font-size: 22px;
}

.wgf-home-card p {
  color: var(--wgf-muted);
  margin: 0;
  font-size: 16px;
  line-height: 1.5;
}

.wgf-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 11px var(--space-3);
  border-radius: var(--radius-control);
  border: 1px solid var(--wgf-border-strong);
  color: var(--wgf-on-gold);
  background: linear-gradient(180deg, var(--wgf-gold-bright), var(--wgf-gold-accent));
  text-decoration: none;
  font-family: var(--font-ui);
  font-weight: 700;
}

.wgf-button--ghost {
  color: var(--wgf-gold-2);
  background: rgba(var(--wgf-gold-rgb), 0.08);
}

.wgf-home-grid,
.wgf-sitemap-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
  gap: var(--space-3);
  margin-top: var(--space-3);
}

.wgf-card,
.wgf-sitemap-card {
  border: 1px solid var(--wgf-border);
  background: rgba(20, 22, 28, 0.88);
  border-radius: var(--radius-card);
  padding: var(--space-3);
}

.wgf-card h2,
.wgf-sitemap-card h2 {
  color: var(--wgf-gold);
  margin: 0 0 var(--space-2);
  font-size: 20px;
}

.wgf-card p,
.wgf-sitemap-card p {
  color: var(--wgf-muted);
  margin: 0 0 12px;
}

.wgf-card a,
.wgf-sitemap-card a,
.wgf-shell-page a {
  color: var(--wgf-link);
}

.wgf-sitemap-card ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.wgf-sitemap-card li {
  margin: var(--space-2) 0;
}

.wgf-card h3 {
  color: var(--wgf-gold);
  margin: 0 0 var(--space-2);
  font-size: 18px;
}

/* .wgf-section - THE page section, and therefore the single highest-leverage surface on
   the site: all 20 content modules (quest, npc, zone, object, recipe, faction, dungeons,
   expansion, creature-family, farming, news, search, report, ...) wrap their content in it.
   It used to be a flat --wgf-panel-1 plate with rounded corners, which is precisely the
   "too much plain" the owner has circled repeatedly - a crawl found 29 hubs whose ONLY
   container was this and which therefore carried no in-game frame at all.

   Owner ruling 2026-08-14 (live-fire reskin): "near 1:1 for ALL types in game." So the
   section IS the client window now - same recipe as .wgf-chrome .wgf-window: 2px metal
   border, the client Class Hall stone tile under a heavy dark wash, and the real metal
   corner braces. Styled HERE, in the component's own home, rather than overridden from
   the kit: wgf-site-shell.css loads last, so an override layer would have to out-specify
   it forever (Rule 11 - one home per treatment).

   The MARKUP is untouched on purpose. 20 modules emit <section class="wgf-section"> inline
   and tests pin that exact HTML (test_spell_app.py, test_quest_chain_and_drops.py), so
   framing all 29 hubs is a pure stylesheet change with no template risk. */
.wgf-section {
  position: relative;
  box-sizing: border-box;
  margin-top: var(--space-4);
  border: 2px solid var(--wgf-metal);
  border-radius: 0;                                /* squared: the client has no rounded panels */
  padding: var(--space-4);
  /* NO corner-brace layers here, deliberately. .wgf-window paints
     ui-frame-metal-corner*-2x.png as 40px/26px no-repeat corner accents, but that art is
     not an ornament: its opaque content is an L-shaped EDGE piece (a horizontal bar plus a
     thin vertical rule) sitting under transparent padding, so a 40px crop of it renders as
     a small grey stub floating over the top edge. That is the "two empty grey bars" the
     owner circled on the Item Details panel (2026-08-14, images 1 and 2). Verified by
     reading the alpha channel: opaque bbox starts at (24,33) of 150x150.
     The frame here is therefore the metal border + the stone plate only - no stubs. The
     same artifact on .wgf-window is PRE-EXISTING and left alone on purpose: those URLs are
     pinned by tests/test_wgf_chrome_css.py:60 and the art is used by 10 stylesheets, so
     ripping it out is an owner call, not a side effect of this wave. */
  background:
    linear-gradient(rgba(0, 0, 0, 0.44), rgba(0, 0, 0, 0.44)),
    url(/assets/ui/classhall-stone-tile.png) left top / 256px 256px repeat,
    var(--wgf-plate);
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, 0.65),
    var(--shadow-2);
  color: var(--wgf-text);
}

/* A section nested INSIDE a real kit window must not draw a second frame (the client
   never stacks window chrome). It degrades to a plain content block. */
.wgf-window .wgf-section,
.wgf-window__body .wgf-section {
  margin-top: var(--space-3);
  border: 0;
  padding: 0;
  background: none;
  box-shadow: none;
}

/* The section heading becomes the window TITLE BAR - the carved stone bar with centred
   gold small-caps the client puts at the top of every panel. Negative margins pull it out
   to the section's own edges so it reads as part of the frame, not text inside it. */
.wgf-section > h2,
.wgf-section > .section-heading {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  min-height: 38px;
  margin: calc(var(--space-4) * -1) calc(var(--space-4) * -1) var(--space-4);
  padding: var(--space-2) var(--space-5);
  /* No gold hairline under the header - owner 2026-07-04 ("we don't like the yellow
     line"); the seam is a dark carved joint like the client's own window bars. */
  border-bottom: 1px solid rgba(0, 0, 0, 0.6);
  background:
    linear-gradient(rgba(0, 0, 0, 0.30), rgba(0, 0, 0, 0.38)),
    url(/assets/ui/classhall-stone-tile.png) left top / 256px 256px repeat,
    var(--wgf-plate-hi);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    inset 0 -6px 10px rgba(0, 0, 0, 0.4);
  color: var(--wgf-gold);
  font-family: var(--font-game);
  font-size: var(--text-md);
  font-weight: 700;
  font-variant: small-caps;
  letter-spacing: 0.03em;
  text-align: center;
  text-shadow: var(--text-ink-outline);
}

/* Nested sections keep a plain gold heading - no title bar without a frame to sit on. */
.wgf-window .wgf-section > h2,
.wgf-window .wgf-section > .section-heading,
.wgf-window__body .wgf-section > h2,
.wgf-window__body .wgf-section > .section-heading {
  display: block;
  min-height: 0;
  margin: 0 0 var(--space-2);
  padding: 0;
  border-bottom: 0;
  background: none;
  box-shadow: none;
  text-align: left;
}

.wgf-section h2 {
  color: var(--wgf-gold);
  margin-top: 0;
}

.wgf-section p {
  color: var(--wgf-muted);
}

/* Character search results (/character/search/) — a rich, scannable card per character:
   portrait, name/realm, class+spec, then the four numbers people compare (Level / Item
   Level / peak PvP / Mythic+). Its own layout — deliberately NOT the ladder table. */
.wgf-csearch {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.wgf-csearch-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 12px var(--space-3);
  border: 1px solid var(--wgf-border-neutral);
  /* Class-colour left rail + a gentle class wash (the shared leaderboard identity treatment);
     --cc is set per card, falls back to the neutral border when the class is unknown. */
  border-left: 3px solid var(--cc, var(--wgf-border-neutral));
  border-radius: var(--radius-card);
  background: linear-gradient(90deg, color-mix(in srgb, var(--cc, transparent) 13%, transparent),
              transparent 44%), var(--wgf-panel-1);
  text-decoration: none;
  transition: border-color var(--motion-fast, 120ms) ease, background var(--motion-fast, 120ms) ease;
}
.wgf-csearch-card:hover {
  border-color: var(--wgf-gold-2);
  background: linear-gradient(90deg, color-mix(in srgb, var(--cc, transparent) 18%, transparent),
              transparent 44%), var(--wgf-panel-2);
}

/* portrait — race/gender face ringed in the class color */
.wgf-csearch-card__av {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  padding: 2px;
  background: var(--ring, var(--wgf-border-neutral, #2e313a));
  display: inline-flex;
}
.wgf-csearch-card__av img,
.wgf-csearch-card__av .wgf-csearch-av-blank {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  display: block;
  background: var(--wgf-well, #08090c);
}
/* neutral silhouette inside the blank avatar (discovered-but-not-yet-crawled characters) */
.wgf-csearch-card__av .wgf-csearch-av-blank {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.wgf-csearch-av-glyph {
  width: 66%;
  height: 66%;
  opacity: .55;
}

.wgf-csearch-card__id {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 0 0 auto;
}
.wgf-csearch-card__name {
  font-weight: 700;
  font-size: 16px;
  line-height: 1.2;
}
.wgf-csearch-card__sub {
  color: var(--wgf-muted);
  font-size: 13px;
}

.wgf-csearch-card__spec {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 160px;
  color: var(--wgf-muted);
  font-size: 14px;
}
.wgf-csearch-card__spec img {
  width: 20px;
  height: 20px;
  border-radius: 4px;
  flex: 0 0 auto;
}
/* honest placeholder text when class/spec isn't crawled yet (keeps the slot from being a phantom) */
.wgf-csearch-card__hint {
  font-style: italic;
  font-size: 13px;
  color: var(--wgf-muted);
  opacity: .8;
}

.wgf-csearch-card__stats {
  display: flex;
  gap: 20px;
  margin-left: auto;
  flex: 0 0 auto;
}
.wgf-csearch-stat {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  min-width: 46px;
}
.wgf-csearch-stat b {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.1;
  color: var(--wgf-text);
}
.wgf-csearch-stat small {
  margin-top: var(--space-1);
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--wgf-muted);
}
.wgf-csearch__empty {
  color: var(--wgf-muted);
  margin: 0;
}

/* Player-card upgrades (owner spec 2026-07-03, shared vocabulary with wgf-player-card.css):
   faction-lit wash on the card's stat side, red-bold ratings, the searched-substring mark,
   and the quiet missing-stat placeholder. Faction hues are the in-game Horde/Alliance colours. */
.wgf-csearch-card { --wgf-rating-red: #ff6257; position: relative; overflow: hidden; }
.wgf-csearch-card[data-faction="horde"] {
  background: linear-gradient(270deg, rgba(196, 30, 58, .16), transparent 38%),
    linear-gradient(90deg, color-mix(in srgb, var(--cc, transparent) 13%, transparent),
    transparent 44%), var(--wgf-panel-1);
}
.wgf-csearch-card[data-faction="alliance"] {
  background: linear-gradient(270deg, rgba(0, 112, 221, .16), transparent 38%),
    linear-gradient(90deg, color-mix(in srgb, var(--cc, transparent) 13%, transparent),
    transparent 44%), var(--wgf-panel-1);
}
.wgf-csearch-card__sub .wgf-pvp-crest {
  width: 16px; height: 16px; border-radius: 3px; vertical-align: -3px; margin-right: var(--space-1);
}
.wgf-csearch-card .wgf-pc-mark,
mark.wgf-pc-mark {
  background: rgba(var(--wgf-gold-rgb), .24); color: inherit;
  border-radius: 3px; padding: 0 .06em;
}
.wgf-pc-nostat { color: var(--wgf-muted); opacity: .55; font-weight: 400; }

@media (max-width: 680px) {
  .wgf-csearch-card { flex-wrap: wrap; gap: var(--space-2) var(--space-3); }
  .wgf-csearch-card__spec { order: 3; flex-basis: 100%; min-width: 0; }
  .wgf-csearch-card__stats {
    order: 4;
    width: 100%;
    margin-left: 0;
    justify-content: space-between;
    gap: var(--space-2);
    border-top: 1px solid var(--wgf-border-neutral);
    padding-top: var(--space-2);
  }
  .wgf-csearch-stat { align-items: flex-start; }
}

/* Item search results (/item/search/) — rich row per item: rarity-framed icon, name in
   rarity color, type/ilvl, item ID, cheapest live price. Sibling of .wgf-csearch. */
.wgf-isearch {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.wgf-isearch-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 12px var(--space-3);
  border: 1px solid var(--wgf-border-neutral);
  border-radius: var(--radius-card);
  background: var(--wgf-panel-1);
  text-decoration: none;
  transition: border-color var(--motion-fast, 120ms) ease, background var(--motion-fast, 120ms) ease;
}
.wgf-isearch-card:hover {
  border-color: var(--wgf-gold-2);
  background: var(--wgf-panel-2);
}
/* icon framed by the item's rarity color (inset ring so the art never gets clipped) */
.wgf-isearch-card__icon {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--wgf-well, #08090c);
  box-shadow: inset 0 0 0 2px var(--q, var(--wgf-border-neutral, #2e313a));
}
.wgf-isearch-card__icon img {
  width: 40px;
  height: 40px;
  border-radius: 6px;
  display: block;
}
.wgf-isearch-card__id {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1 1 auto;
}
.wgf-isearch-card__name {
  font-weight: 700;
  font-size: 16px;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wgf-isearch-card__sub {
  color: var(--wgf-muted);
  font-size: 13px;
}
.wgf-isearch-stat {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  flex: 0 0 auto;
  min-width: 70px;
}
.wgf-isearch-stat b {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.1;
  color: var(--wgf-text);
}
.wgf-isearch-stat small,
.wgf-isearch-price small {
  margin-top: var(--space-1);
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--wgf-muted);
}
.wgf-isearch-price {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  flex: 0 0 auto;
  min-width: 96px;
}
@media (max-width: 680px) {
  .wgf-isearch-card { flex-wrap: wrap; }
  .wgf-isearch-card__id { flex-basis: calc(100% - 58px); }
  .wgf-isearch-stat,
  .wgf-isearch-price {
    align-items: flex-start;
    min-width: 0;
    flex: 1 1 auto;
    margin-top: var(--space-1);
  }
}

/* Breadcrumb — a SHELL component (single-sourced via site_shell.render_breadcrumb), so its CSS
   lives here in the shell sheet (loaded on EVERY page, incl. the static AH browser/deals pages
   which don't load wgf-seo-pages.css). Class kept as .wgf-seo-breadcrumb for back-compat. */
/* M03 harmonization (2026-06-23): restyled to the locked breadcrumb design — muted
   links → gold hover, brighter current page, chevron separators, home glyph on crumb 1.
   Markup stays .wgf-seo-breadcrumb (render_breadcrumb); this is the single visual home. */
/* Kit re-cut (2026-07-04): the trail is a SQUARED in-game strip in the small-caps game face,
   gold chevron separators, sitting AGAINST the window chrome (a carved metal seam under it)
   rather than floating as a plain web crumb row. Markup stays .wgf-seo-breadcrumb
   (render_breadcrumb). Token fallbacks cover static pages loaded with only _tokens.css. */
.wgf-seo-breadcrumb { padding: var(--space-2) var(--space-3); max-width: 1180px; margin: 0 auto; border-bottom: 1px solid var(--wgf-metal-soft, #3a3120); }
.wgf-seo-breadcrumb ol { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 0; font-family: var(--font-game); font-variant: small-caps; letter-spacing: 0.04em; font-size: var(--text-sm, 0.875rem); }
.wgf-seo-breadcrumb li { display: flex; align-items: center; white-space: nowrap; color: var(--wgf-muted); }
.wgf-seo-breadcrumb li::after { content: "\203A"; color: var(--wgf-gold-2); padding: 0 var(--space-2); line-height: 1; }
.wgf-seo-breadcrumb li:last-child { color: var(--wgf-gold); opacity: 1; }
.wgf-seo-breadcrumb li:last-child::after { content: ""; padding: 0; }
.wgf-seo-breadcrumb a { text-decoration: none; color: var(--wgf-muted); text-underline-offset: 2px; border-radius: 0; }
.wgf-seo-breadcrumb a:hover { color: var(--wgf-gold); text-decoration: underline; }
.wgf-seo-breadcrumb .bc-home-icon { width: 1em; height: 1em; fill: currentColor; vertical-align: -0.12em; margin-right: var(--space-1); flex: 0 0 auto; }

.wgf-site-footer {
  position: relative;
  /* Owner 2026-07-30: "this blue looks like shit" - navy tint killed. 2026-09-02: the
     footer runs on the near-black slate panel ramp (docs/ui-ux/17-blizzard-palette.md),
     matching every other surface. */
  border-top: 1px solid var(--wgf-metal, #6e5a2a);
  background:
    linear-gradient(180deg, rgba(20, 22, 28, 0.99), rgba(8, 9, 12, 1));
  color: var(--wgf-muted);
  padding: var(--space-5) var(--space-3) var(--space-4);
  margin-top: 40px;
  font-family: var(--font-ui);
}

.wgf-site-footer::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(var(--wgf-gold-rgb), 0.22) 20%,
    rgba(var(--wgf-gold-rgb), 0.6) 50%,
    rgba(var(--wgf-gold-rgb), 0.22) 80%,
    transparent 100%
  );
}

.wgf-site-footer__inner {
  max-width: 1220px;
  margin: 0 auto;
}

.wgf-site-footer__brand {
  margin-bottom: var(--space-4);
}

.wgf-site-footer__logo {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--wgf-gold);
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-weight: 900;
  font-size: 15px;
  margin-bottom: var(--space-2);
}

.wgf-site-footer__brand p {
  max-width: 620px;
  margin: 0;
  color: var(--wgf-muted);
}

.wgf-site-footer__nav {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(185px, 1fr));
  gap: var(--space-4);
  padding: var(--space-4) 0;
  border-top: 1px solid rgba(var(--wgf-gold-rgb), 0.18);
  border-bottom: 1px solid rgba(var(--wgf-gold-rgb), 0.18);
}

/* Phones: two columns instead of one 32-link tower (halves the footer scroll). */
@media (max-width: 680px) {
  .wgf-site-footer__nav {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-3) var(--space-3);
  }
}

.wgf-site-footer__nav h2 {
  color: var(--wgf-gold);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  margin: 0 0 var(--space-2);
}

.wgf-site-footer__nav a {
  display: block;
  color: var(--wgf-gold-soft, #d4ad3d);
  text-decoration: none;
  margin: var(--space-2) 0;
  font-size: 14px;
  font-weight: 650;
}

.wgf-site-footer__nav a:hover {
  text-decoration: underline;
}

.wgf-site-footer__bottom {
  padding-top: var(--space-3);
}

.wgf-site-footer__bottom p {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--wgf-neutral-text);
}

.wgf-site-footer__copy {
  margin-top: var(--space-2) !important;
  font-size: 12px !important;
  color: var(--wgf-gold-muted) !important;
  opacity: 0.85;
}

.wgf-site-footer__copy a {
  color: var(--wgf-gold-soft, #d4ad3d);
  text-decoration: none;
}

.wgf-site-footer__copy a:hover {
  color: var(--wgf-gold);
  text-decoration: underline;
}

@media (max-width: 760px) {
  .wgf-home-hero,
  .wgf-page-hero,
  .wgf-hero {
    padding: var(--space-4);
  }

  .wgf-article {
    padding: 1.25rem;
  }
}

/* === Collapsing mobile header (added 2026-06-12; breakpoint raised 2026-06-23) ===
   Below 1020px the logo + search + the eight primary pillars can't share one row
   without crowding/wrapping, so they collapse behind the hamburger and reveal as a
   stacked dropdown when open. (Bumped from 1200px when Leaderboards became a top-level
   pillar — 8 items, two of them wide: "Cheapest Realm" + "Leaderboards".) */
/* Re-keyed 2026-08-27 from 1020px to the PHONE tier (< 900px) - see HEADER BREAKPOINTS
   at the end of the sheet for the whole rule set. Row 1 here is brand | right cluster |
   hamburger; the pillars are the drawer under it. */
@media (max-width: 899px) {
  .wgf-shell-topbar__inner {
    flex-wrap: wrap;
    row-gap: 0;
  }

  .wgf-shell-topbar__inner > .wgf-shell-logo {
    order: 1;
    flex: 0 1 auto;
    min-width: 0;
    white-space: nowrap;
  }

  .wgf-shell-nav-toggle {
    display: flex;
    order: 3;
    flex: 0 0 auto;
    margin-left: 0;
  }

  /* Search stays VISIBLE on mobile (search-first product) — it is no longer buried in the
     hamburger. The whole right group (search + the region chips on region-aware pages)
     drops to its OWN full-width row under the logo/toggle bar; without this the search
     was squeezed to a sliver between the logo and the hamburger on one cramped row
     (owner: "the entire nav is awkward on mobile"). */
  /* The right cluster (Enter World / character + the selector chip) stays on ROW 1,
     pinned right, between the brand and the hamburger - it no longer drops to its own
     full-width second row (that second row is what read as 'the header is odd on
     mobile'). The selector's own bottom sheet (<= 720px) is untouched. */
  .wgf-shell-topbar .wgf-shell-right,
  .wgf-shell-topbar__inner > .gsh-user-nav {
    order: 2;
    flex: 0 0 auto;
    min-width: 0;
    margin: 0 0 0 auto;
    display: flex;
    align-items: center;
    gap: var(--space-2);
  }

  .wgf-shell-topbar .wgf-shell-search {
    flex: 1 1 auto;
    min-width: 0;
    max-width: none;
    margin: 0;
    display: flex;
  }

  .wgf-shell-topbar .wgf-shell-nav {
    order: 4;
    flex-basis: 100%;
    flex-direction: column;
    flex-wrap: nowrap;
    gap: 0;
    margin: var(--space-2) 0 0;
    display: none;
    white-space: normal;
  }

  .wgf-shell-topbar.is-open .wgf-shell-nav {
    display: flex;
    /* The open menu is a DRAWER, not a header that grows without bound: it scrolls
       internally (the page behind is scroll-locked via html.wgf-nav-open), so every
       pillar/link is reachable on a short phone viewport without losing the header. */
    max-height: calc(100vh - 180px);
    max-height: calc(100dvh - 180px);
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }

  /* Page scroll-lock while the mobile menu is open (wgf-shell.js toggles the class). */
  html.wgf-nav-open,
  html.wgf-nav-open body {
    overflow: hidden;
  }

  .wgf-shell-topbar .wgf-shell-nav a {
    padding: 13px var(--space-1);
    border-top: 1px solid rgba(var(--wgf-gold-rgb), 0.12);
  }

  .wgf-shell-topbar .wgf-shell-nav a.is-active {
    color: var(--wgf-gold);
  }

  .wgf-shell-topbar .wgf-shell-nav a.is-active::after {
    left: 4px;
    right: auto;
    width: 18px;
    bottom: 8px;
  }
}

/* === Grouped primary-nav dropdowns (added 2026-06-20, nav IA) ==================
   Pillar links are server-rendered (crawler-visible); the dropdown is progressive
   enhancement. Desktop reveals on hover / keyboard focus; mobile shows every link
   expanded inside the existing hamburger panel (no accordion JS). */
.wgf-shell-topbar .wgf-shell-nav { align-items: center; }

.wgf-nav-group { position: relative; display: flex; align-items: center; }

.wgf-shell-topbar .wgf-shell-nav .wgf-nav-trigger {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}

.wgf-nav-caret {
  width: 0; height: 0; margin-left: var(--space-1);
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  opacity: 0.85;
  transition: transform 0.15s ease, opacity 0.15s ease;
}
.wgf-nav-group:hover .wgf-nav-caret,
.wgf-nav-group:focus-within .wgf-nav-caret { transform: rotate(180deg); opacity: 1; }

/* In-game dropdown surface (2026-07-04 chrome re-cut, docs/ui-ux/13-ingame-reference.md
   §0.10 / ig-51): the open menu is a SQUARED near-black well plate with a thin metal edge
   and a subtle inset shadow - the same visual family as the kit .wgf-dropdown open menu,
   never a warm-brown rounded panel. Tokens fall back to literals because wgf-chrome.css
   (where --wgf-well/--wgf-metal-soft live) is not loaded on every shell page. */
.wgf-nav-menu {
  position: absolute;
  top: 100%; left: 0;
  width: 210px;
  margin-top: var(--space-1);
  padding: var(--space-1);
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: linear-gradient(180deg, var(--wgf-well, #08090c), var(--wgf-well-edge, #040507));
  border: 1px solid var(--wgf-metal-soft);
  border-radius: 0;
  box-shadow: var(--shadow-2, 0 4px 16px rgba(0, 0, 0, 0.5)), inset 0 0 0 1px rgba(0, 0, 0, 0.7);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-5px);
  /* Forgiving close: the hide transition is DELAYED 450ms, so briefly leaving the
     trigger/menu (crossing the gap, overshooting) never snaps it shut (owner bugs
     2026-07-03 + 2026-07-31). Opening stays instant via the :hover rule. */
  transition: opacity 0.15s ease 0.45s, transform 0.15s ease 0.45s, visibility 0s linear 0.6s;
  z-index: 50;
  /* Short laptop screens: the Database menu (17 links + group heads) must never clip
     off the bottom of the viewport - scroll inside the popover instead. */
  max-height: calc(100vh - 96px);
  overflow-y: auto;
}
/* Invisible hover bridge covering the gap under the trigger. Lives on the GROUP, not
   the menu: the menu is an overflow-y:auto scroll container, which CLIPS any ::before
   hung above its content box - that clipped bridge was the 2026-07-31 owner bug
   ("nav disappears when I mouse toward the options"). Only exists while the group is
   hovered/open, so it can never intercept clicks meant for content under the header. */
.wgf-nav-group:hover::after,
.wgf-nav-group:focus-within::after {
  content: "";
  position: absolute;
  top: 100%; left: -12px; right: -12px;
  height: 16px;
}

.wgf-nav-group:hover > .wgf-nav-menu,
.wgf-nav-group:focus-within > .wgf-nav-menu {
  opacity: 1; visibility: visible; transform: translateY(0);
  transition-delay: 0s, 0s, 0s;
}

/* The right-most pillar (More) anchors its menu to the right edge of the trigger so a
   left-anchored panel never spills off the viewport. (No effect in the mobile static view.) */
.wgf-shell-topbar .wgf-shell-nav .wgf-nav-group:last-child > .wgf-nav-menu {
  left: auto; right: 0;
}

.wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu a {
  display: block;
  padding: var(--space-2) var(--space-3);
  border-radius: 0;
  white-space: nowrap;
  font-family: var(--font-game);
  font-size: 13px;
  font-weight: 650;
}
/* Hover/focus = the in-game subtle white glow (§9b / ig-57): a soft light lift + faint
   outer glow, never a rounded brown fill or a colour swap. Keyboard focus keeps the site
   focus ring (the global a:focus-visible outline) on top of the glow. */
.wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu a:hover,
.wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu a:focus-visible {
  background: rgba(255, 255, 255, 0.07);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 0 8px rgba(255, 255, 255, 0.10);
  text-decoration: none;
}
/* In-menu active item: gold text + chip, never the underline bar used in the bar. */
.wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu a.is-active {
  color: var(--wgf-gold);
  background: rgba(var(--wgf-gold-rgb), 0.10);
}
.wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu a.is-active::after { display: none; }
/* Non-clickable "coming soon" note inside a dropdown — muted, italic, no hover. */
.wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu .wgf-nav-note {
  display: block;
  padding: var(--space-2) 12px;
  font-size: 12px;
  font-style: italic;
  font-weight: 500;
  color: var(--wgf-muted);
  cursor: default;
  border-top: 1px solid rgba(var(--wgf-gold-rgb), 0.10);
  margin-top: 2px;
}
/* Section subheader inside a dropdown (e.g. "PvP" / "PvE") so one hover reads as a complete map. */
.wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu .wgf-nav-grouphead {
  display: block;
  padding: var(--space-2) var(--space-3) var(--space-1);
  font-family: var(--font-game);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--wgf-gold);
  cursor: default;
  opacity: 0.78;
}
/* First subheader hugs the top; later ones get a faint divider above. */
.wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu .wgf-nav-grouphead:not(:first-child) {
  margin-top: var(--space-1);
  border-top: 1px solid rgba(var(--wgf-gold-rgb), 0.10);
  padding-top: var(--space-2);
}

/* === Grouped dropdowns flow into COLUMNS, they never scroll ===================
   Measured 2026-08-04 (owner bug: "why is the Database menu cut off"): the
   Database menu is 16 links + 4 group heads = 746px of content against a
   max-height of calc(100vh - 96px) — 663px on a 759px viewport — so it clipped
   and grew an internal scrollbar. Every ancestor was already overflow:visible,
   so the menu's own max-height was the clipper; simply raising it only moves the
   break to the next laptop (and a scrollbar inside a dropdown is not something an
   in-game WoW menu ever does — owner: the nav "should always feel like an in-game
   menu").
   The fix is layout, not a bigger number: server-side each group head + its links
   is wrapped in .wgf-nav-section (site_shell.render_primary_nav), and a sectioned
   menu becomes a 2-column block. Database now stands ~9 rows tall instead of 20 —
   no scrollbar at any realistic viewport. break-inside: avoid keeps a group whole,
   so a column never splits "Collections" from its items.
   The inherited max-height + overflow-y stay as a last-resort safety for very
   short windows; column-count is fixed at 2, so overflow scrolls rather than
   spilling sideways. NONE of the in-game chrome (well plate, metal edge, inset
   shadow, gold type) is touched — this rule only changes flow. */
.wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu--sections {
  display: block;
  width: 424px;
  column-count: 2;
  column-gap: var(--space-3);
}
.wgf-shell-topbar .wgf-shell-nav .wgf-nav-section {
  display: flex;
  flex-direction: column;
  gap: 1px;
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
}
/* Inside a sectioned menu every head is its section's first child, so the
   :not(:first-child) divider above would never fire. Hang it off the section
   instead — the leading section (ungrouped links) stays flush. */
.wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu--sections .wgf-nav-section:not(:first-child) .wgf-nav-grouphead {
  margin-top: var(--space-1);
  border-top: 1px solid rgba(var(--wgf-gold-rgb), 0.10);
  padding-top: var(--space-2);
}

@media (max-width: 899px) {
  .wgf-nav-group { position: static; display: block; }
  .wgf-nav-caret { display: none; }
  .wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu {
    position: static;
    opacity: 1; visibility: visible; transform: none;
    margin: 0; padding: 0;
    background: transparent; border: none; box-shadow: none;
    width: auto; min-width: 0;
  }
  /* The desktop 2-column flow is a desktop affordance only — on mobile the menu is a
     stacked accordion panel, so sectioned menus collapse back to one full-width column. */
  .wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu--sections {
    column-count: 1;
    width: auto;
  }
  .wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu a {
    padding: 11px var(--space-1) 11px var(--space-3);
    border-top: 1px solid rgba(var(--wgf-gold-rgb), 0.10);
    border-radius: 0;
    font-size: 14px;
  }

  /* Accordion (wgf-shell.js adds .is-accordion on mobile): collapse each pillar's children
     behind its trigger so the open menu is the 8 pillars, not a flat wall of ~25 links. The
     pillar's hub is its first child, so it stays reachable. Without JS the menus stay expanded
     (the rules above) — no regression. */
  .wgf-shell-nav.is-accordion .wgf-nav-menu {
    overflow: hidden;
    max-height: 0;
    transition: max-height 0.22s ease;
  }
  .wgf-shell-nav.is-accordion .wgf-nav-group.is-expanded > .wgf-nav-menu {
    /* Tall enough for the LARGEST pillar (Database: 17 links + 4 group heads ≈ 800px).
       The old 640px cap CLIPPED its tail (Quests/Achievements/Currencies were unreachable
       on mobile). The drawer itself scrolls, so a generous cap costs nothing. */
    max-height: 1200px;
  }
  /* Every top-level pillar row rides the same flex grid — grouped triggers AND single
     pillars (e.g. Token, which has no submenu/caret). Without this, single .wgf-nav-link
     pillars render as plain block links on a different box model than the flex triggers,
     so their text left-edge and row structure don't line up with the rest of the menu. */
  .wgf-shell-nav.is-accordion .wgf-nav-trigger,
  .wgf-shell-nav.is-accordion > .wgf-nav-link {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  .wgf-shell-nav.is-accordion .wgf-nav-caret {
    display: inline-block;
    margin-left: auto;
    transition: transform 0.18s ease;
  }
  .wgf-shell-nav.is-accordion .wgf-nav-group.is-expanded > .wgf-nav-trigger .wgf-nav-caret {
    transform: rotate(180deg);
  }
}

/* === Tool-page quick links (added 2026-06-22) ===================================
   A compact "where to go next" row that sits right under a tool page's hero so the
   primary intents (find deals / browse item prices / compare realms) are one tap away
   without competing with the tool itself. Used on the Auction House browser page. */
.wgf-ah-quicklinks {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-1) 0 2px;
}
.wgf-ah-quicklinks__label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--wgf-muted);
  margin-right: 2px;
}
/* The quicklink chips are the in-game red kit button now (AH kit re-cut, owner
   "OPUS agent" 2026-07-04): the rounded-pill idiom is dead here. This rule only
   styles any NON-kit link that might still land in the row; `.wgf-btn-red` links
   render as the client red button from wgf-chrome.css. */
.wgf-ah-quicklinks a:not(.wgf-btn-red) {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) 12px;
  border: 1px solid var(--wgf-border);
  background: rgba(var(--wgf-gold-rgb), 0.06);
  color: var(--wgf-gold-2);
  text-decoration: none;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.2;
}
.wgf-ah-quicklinks a:not(.wgf-btn-red):hover {
  border-color: var(--wgf-gold-2);
  background: rgba(var(--wgf-gold-rgb), 0.14);
  color: var(--wgf-gold);
}

/* (Removed 2026-07-04, AH kit re-cut) The old "search-first emphasis" block that
   nudged the search box and dimmed Market/Export/Sort lived here. Its job is now
   done by the in-game chrome kit re-cut in assets/ah/base.css (the inset near-black
   fields, the black filter-button idiom, the collapsed dropdown look) so the two no
   longer fight over the same controls. */

/* Region selection moved 2026-08-27: the old rounded US/EU pill (.wgf-region-select,
   retired from the shell 2026-08-01, and a banned pill shape besides) is gone. Region
   and game version are ONE header control now - wgf_selector.py + assets/wgf-selector.css,
   mounted from the footer seam beside the Enter World button. */

/* Stable scrollbar gutter (owner review 2026-07-03): without this the centered nav shifts
   between short pages (no scrollbar) and long pages. One line kills the residual nav shift. */
html { scrollbar-gutter: stable; }

/* Native dropdown popups follow the dark theme (owner blue-circle 2026-07-30: the white
   option list must be dark - for ALL dropdowns, site-wide). color-scheme makes Chromium
   paint the native popup dark; the option rules cover Firefox and the fallback path. */
select { color-scheme: dark; }
select option,
select optgroup {
  background-color: var(--wgf-panel-1, #14161c);
  color: var(--wgf-gold, #ffd100);
}

/* === Nav re-cut (2026-08-01, owner "FIX THE NAV") ==============================
   One height system (32px controls), SQUARED kit chrome on search + scope pills
   (the pill radii read web and clashed with the game-menu nav), compression rules
   so the right zone can NEVER overlap the centre nav (see the minmax(0,1fr) grid
   note above), and a real mobile collapse. Later in the cascade on purpose - this
   block overrides the legacy pill styling in one coherent place. */
.wgf-shell-right { gap: 8px; }
.wgf-shell-right .wgf-shell-search { flex: 1 1 150px; min-width: 90px; }
.wgf-shell-search { max-width: 480px; }
.wgf-shell-search__input {
  height: 32px;
  min-height: 32px;
  padding: 0 34px 0 10px;
  border-radius: 0;
  border: 1px solid var(--wgf-metal-soft, #3a3120);
  background: linear-gradient(180deg, var(--wgf-well, #08090c), var(--wgf-well-edge, #040507));
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.8);
  font-size: 13.5px;
}
.wgf-shell-search:has(.wgf-scope-toggle) .wgf-shell-search__input {
  border-left: none;
  border-radius: 0;
}
.wgf-scope-toggle {
  border-radius: 0;
  border-color: var(--wgf-metal-soft, #3a3120);
}
.wgf-scope-btn { height: 32px; padding: 0 9px; font-size: 12px; }
.wgf-shell-search__btn { width: 28px; height: 28px; border-radius: 0; }
.wgf-realm-btn { max-width: 150px; overflow: hidden; text-overflow: ellipsis; }

/* Collapsed-by-default search (2026-08-01 owner "dogshitto" round): the bar carries
   ONE 32px kit magnifier; clicking expands a full-width kit search row hung under
   the topbar. The scope pills are retired in wgf-shell.js (database scope only).
   Without JS the wgf-search--collapsible class never lands, so the plain inline
   input keeps working. */
.wgf-shell-topbar { position: relative; }
.wgf-search--collapsible:not(.is-open) { flex: 0 0 auto; min-width: 0; max-width: none; }
.wgf-search--collapsible:not(.is-open) .wgf-shell-search__input {
  width: 0; min-width: 0; height: 0; min-height: 0;
  padding: 0; border: none; opacity: 0; pointer-events: none;
}
.wgf-search--collapsible:not(.is-open) .wgf-shell-search__btn {
  position: static; transform: none;
  width: 32px; height: 32px;
  border: 1px solid var(--wgf-metal-soft, #3a3120);
  background: linear-gradient(180deg, var(--wgf-panel-2, #1a1d24), var(--wgf-bg-2, #0d0f14));
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.6);
}
.wgf-search--collapsible.is-open {
  position: absolute;
  left: 0; right: 0; top: 100%;
  max-width: none;
  margin: 0;
  padding: 10px clamp(16px, 4vw, 48px);
  background: linear-gradient(180deg, var(--wgf-panel-1, #14161c), var(--wgf-bg, #0a0b0f));
  border-bottom: 1px solid var(--wgf-metal-soft, #3a3120);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.55);
  z-index: 60;
}
.wgf-search--collapsible.is-open .wgf-shell-search__input {
  height: 40px; min-height: 40px; font-size: 15px;
}
.wgf-search--collapsible.is-open .wgf-shell-search__btn {
  position: absolute;
  right: clamp(20px, 4vw, 52px); top: 50%;
  transform: translateY(-50%);
  width: 32px; height: 32px;
  border: none; background: transparent; box-shadow: none;
}

@media (max-width: 899px) {
  .wgf-scope-toggle { display: none; }
  .wgf-shell-search__btn { width: 36px; height: 36px; }
}

/* === Enter World nav button (Change Realm 2026-07-31; merged with sign-in 2026-08-02)
   ONE control, injected by wgf-shell.js next to the header search. It opens the
   Enter World window (wgf-realm-picker.js, lazy-loaded on first click), which
   carries Character Select, the realm list, and - signed out - the Battle.net
   login. Owner direction: "merge the realm selector + the bnet login."
   Label is the player's character when signed in, else their realm, else the
   invitation. Lives HERE because the picker's own CSS only loads on demand - the
   button must be dressed on page load.
   Real red-button atlas slices, calibrated 26px/11px pair (see game-skin note below). */
.wgf-realm-btn {
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 11px;
  margin-right: 8px;
  border: 0;
  border-radius: 0;
  background:
    url(/assets/ui/128-redbutton-left-cap.png) left center / auto 100% no-repeat border-box,
    url(/assets/ui/128-redbutton-right-cap.png) right center / auto 100% no-repeat border-box,
    url(/assets/ui/_128-redbutton-center.png) left center / auto 100% repeat-x content-box;
  color: var(--wgf-gold-bright, #ffe375);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9);
  font-family: var(--font-game, serif);
  font-size: 12.5px;
  font-weight: 650;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
}
.wgf-realm-btn:hover  { filter: brightness(1.14); }
.wgf-realm-btn:active { filter: brightness(0.92); transform: translateY(1px); }
@media (max-width: 720px) { .wgf-realm-btn { margin-right: 4px; } }

/* Signed in, showing a character: the label wears the class colour (set inline
   from pvp_icons, so no copy of the class palette lives in CSS). Capped so a long
   name cannot push the nav around, with the ellipsis inside the atlas caps. */
.wgf-realm-btn--character {
  max-width: 16ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: inline-block;
  line-height: 26px;
}

/* === Game-menu nav skin (2026-07-31, MOONSHOTS #19 rung 1) =====================
   DARK until owner ready-check: wgf-shell.js adds html.wgf-navskin-game only when
   armed via ?navskin=game (sticky in localStorage; ?navskin=off clears). Pillars
   become the client's red action buttons - the REAL 128-redbutton atlas slices
   (same three-layer recipe as .wgf-btn-red in wgf-chrome.css; 26px height pairs
   with 11px caps, the calibrated --sm ratio - padding MUST equal the scaled cap
   width or the center tile gaps under the cap alpha). Desktop only: the mobile
   drawer keeps the stacked link list. */
@media (min-width: 900px) {
  html.wgf-navskin-game .wgf-shell-topbar {
    background: linear-gradient(180deg, var(--wgf-panel-2, #1a1d24) 0%, var(--wgf-bg-2, #0d0f14) 100%);
    border-bottom: 1px solid var(--wgf-metal-soft, #3a3120);
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.85), 0 3px 10px rgba(0, 0, 0, 0.45);
  }
  html.wgf-navskin-game .wgf-shell-topbar .wgf-shell-nav .wgf-nav-trigger,
  html.wgf-navskin-game .wgf-shell-topbar .wgf-shell-nav > .wgf-nav-link {
    height: 26px;
    padding: 0 11px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background:
      url(/assets/ui/128-redbutton-left-cap.png) left center / auto 100% no-repeat border-box,
      url(/assets/ui/128-redbutton-right-cap.png) right center / auto 100% no-repeat border-box,
      url(/assets/ui/_128-redbutton-center.png) left center / auto 100% repeat-x content-box;
    color: var(--wgf-gold-bright, #ffe375);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9);
    font-size: 12.5px;
    line-height: 1;
    border-radius: 0;
  }
  html.wgf-navskin-game .wgf-shell-topbar .wgf-shell-nav .wgf-nav-trigger:hover,
  html.wgf-navskin-game .wgf-shell-topbar .wgf-shell-nav > .wgf-nav-link:hover {
    filter: brightness(1.14);
    text-decoration: none;
  }
  html.wgf-navskin-game .wgf-shell-topbar .wgf-shell-nav .wgf-nav-trigger:active,
  html.wgf-navskin-game .wgf-shell-topbar .wgf-shell-nav > .wgf-nav-link:active {
    filter: brightness(0.92);
    transform: translateY(1px);
  }
  /* The bar's active-page underline reads web, not client: replace with pressed-state
     language (persistent gold text; the red button itself is the affordance). */
  html.wgf-navskin-game .wgf-shell-topbar .wgf-shell-nav .wgf-nav-trigger::after,
  html.wgf-navskin-game .wgf-shell-topbar .wgf-shell-nav > .wgf-nav-link::after {
    display: none;
  }
  html.wgf-navskin-game .wgf-nav-caret { border-top-color: var(--wgf-gold-bright, #ffe375); }
  /* Hover bridge must clear the taller travel from the 26px button into the menu. */
  html.wgf-navskin-game .wgf-nav-group:hover::after,
  html.wgf-navskin-game .wgf-nav-group:focus-within::after { height: 20px; }
}

/* === Mobile drawer alignment fix (2026-08-01, owner: "fix this navigation") =====
   `.wgf-shell-topbar .wgf-shell-nav { align-items: center }` (the grouped-nav block
   above) is UNSCOPED and sits later in the cascade than the max-width:900px block,
   so it won the mobile case too. On a flex COLUMN, align-items:center sizes every
   child to its own content width and centres it - which is why the open drawer
   rendered as a ragged staircase of centred links with dividers of different widths
   instead of a clean stacked list.

   Full-width rows, text left, dividers edge to edge. Placed at the very end of the
   sheet so it cannot be re-overridden by the earlier unscoped rule. */
@media (max-width: 899px) {
  .wgf-shell-topbar .wgf-shell-nav {
    align-items: stretch;
    text-align: left;
  }

  .wgf-shell-topbar .wgf-shell-nav > *,
  .wgf-shell-topbar .wgf-shell-nav .wgf-nav-group,
  .wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu {
    width: 100%;
    max-width: none;
  }

  /* Rows: full-bleed tap targets, label hard left, caret pushed to the right edge. */
  .wgf-shell-topbar .wgf-shell-nav a,
  .wgf-shell-topbar .wgf-shell-nav .wgf-nav-trigger {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
    text-align: left;
    box-sizing: border-box;
  }

  .wgf-shell-topbar .wgf-shell-nav .wgf-nav-trigger .wgf-nav-caret,
  .wgf-shell-topbar .wgf-shell-nav .wgf-nav-caret {
    margin-left: auto;
  }

  /* Child links read as children, not siblings of the pillar. */
  .wgf-shell-topbar .wgf-shell-nav .wgf-nav-menu a {
    padding-left: var(--space-3, 16px);
  }
}

/* Signed in but no character chosen: the label falls back to the realm name, which
   looked identical to signed-out. A thin gold underline says "there is an account
   behind this button" without stealing attention from the label itself. */
.wgf-realm-btn--signedin:not(.wgf-realm-btn--character) {
  box-shadow: inset 0 -2px 0 rgba(var(--wgf-gold-rgb), 0.55);
}

/* Nav pillar icon (2026-08-02) - Tracked Items carries the client's AH favourite
   star. Decorative: the label is the accessible name, the image is alt="". */
.wgf-nav-icon {
  width: 16px;
  height: 16px;
  margin-right: 5px;
  vertical-align: -3px;
  object-fit: contain;
}

/* ── Community door: the Discord CTA (2026-08-05) ─────────────────────────────────
   Added because the site linked to the Discord from nowhere while the server sat at
   3 members. Rendered by site_shell.render_community_cta(); absent entirely when
   WGF_DISCORD_INVITE is unset, so these rules simply never match in that case.

   Deliberately NOT Discord blurple (#5865F2): the owner's 1:1 in-game-kit law rules
   the chrome, so this wears the site's gold. Squared corners, never a rounded pill -
   same law as the active-pillar rule above. Fills are reserved for CTAs, and this is
   the one real CTA in the bar, so it gets the carved gold treatment. */

.wgf-community-cta {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  text-decoration: none;
  font-family: var(--font-ui);
  font-weight: 700;
  border-radius: 0;
}

.wgf-community-cta__mark {
  flex: 0 0 auto;
  vertical-align: -3px;
}

/* Header pill: carved gold outline that fills on hover. Higher specificity than the
   generic `.wgf-shell-nav a` colour rule it sits inside, so it keeps its own look. */
.wgf-shell-topbar .wgf-shell-nav a.wgf-community-cta--nav {
  margin-left: var(--space-2, 10px);
  padding: 5px 12px;
  color: var(--wgf-gold);
  border: 1px solid rgba(var(--wgf-gold-rgb), 0.55);
  background: linear-gradient(180deg, rgba(var(--wgf-gold-rgb), 0.14), rgba(var(--wgf-gold-rgb), 0.05));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
  transition: background 120ms linear, border-color 120ms linear, color 120ms linear;
}

.wgf-shell-topbar .wgf-shell-nav a.wgf-community-cta--nav:hover {
  text-decoration: none;
  color: var(--wgf-on-gold, #1a1200);
  border-color: var(--wgf-gold);
  background: linear-gradient(180deg, var(--wgf-gold), var(--wgf-gold-2));
}

.wgf-shell-topbar .wgf-shell-nav a.wgf-community-cta--nav:focus-visible {
  outline: 2px solid var(--wgf-focus, #ffe375);
  outline-offset: 2px;
}

/* The active-pillar underline must never attach to the CTA - it is an action, not a
   section, and it is already filled. */
.wgf-shell-topbar .wgf-shell-nav a.wgf-community-cta--nav.is-active::after {
  content: none;
}

/* Footer block CTA: sits under the brand blurb with room for a one-line pitch. */
.wgf-community-cta--footer {
  margin-top: var(--space-3, 14px);
  padding: 10px 14px;
  align-items: center;
  gap: 10px;
  color: var(--wgf-gold);
  border: 1px solid rgba(var(--wgf-gold-rgb), 0.45);
  background: linear-gradient(180deg, rgba(var(--wgf-gold-rgb), 0.10), rgba(0, 0, 0, 0.20));
  transition: border-color 120ms linear, background 120ms linear;
}

.wgf-community-cta--footer:hover {
  border-color: var(--wgf-gold);
  background: linear-gradient(180deg, rgba(var(--wgf-gold-rgb), 0.18), rgba(0, 0, 0, 0.16));
}

.wgf-community-cta--footer:focus-visible {
  outline: 2px solid var(--wgf-focus, #ffe375);
  outline-offset: 2px;
}

.wgf-community-cta--footer .wgf-community-cta__mark {
  width: 22px;
  height: 22px;
}

.wgf-community-cta__text {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
}

.wgf-community-cta__text strong {
  font-size: 14px;
  color: var(--wgf-gold);
}

.wgf-community-cta__text small {
  font-size: 12px;
  font-weight: 500;
  color: var(--wgf-muted, #b3a88f);
}

/* Inside the hamburger the bar goes vertical: let the CTA span the drawer width so it
   reads as the drawer's closing action rather than a stray 12th pillar.
   1020px, NOT 900px - that is where .wgf-shell-nav-toggle flips to display:flex and the
   nav actually becomes a drawer. Matching the wrong breakpoint left the CTA carrying its
   desktop margin-left inside a vertical drawer between 901-1020px. */
@media (max-width: 899px) {
  .wgf-shell-topbar .wgf-shell-nav a.wgf-community-cta--nav {
    margin-left: 0;
    margin-top: var(--space-2, 10px);
    justify-content: center;
  }
}
/* =============================================================================
   HEADER BREAKPOINTS (2026-08-27, owner: "the header behaves oddly on different
   sizes of the page, same with mobile and desktop") - THE one rule set for the
   topbar row. Three tiers, three numbers, used verbatim by assets/wgf-shell.js
   (drawer + accordion below 900) and assets/wgf-search-bar.css (band padding):

     DESKTOP  >= 1280px  ONE row, 3 zones: brand | all 7 pillars centred | right
                         cluster pinned right. Never wraps.
     MID      900-1279   ONE flex row: brand | pillars | right cluster pinned right.
                         Pillars FOLD into the Menu directory by tier so the row
                         never wraps: tier 3 (Token, Tracked) below 1180, tier 2
                         (Leaderboards, Guides) below 1000. Every folded link is
                         already in the Menu directory, so nothing is lost.
     PHONE    < 900px    row 1: brand | right cluster | hamburger. Pillars in the
                         drawer (the accordion). The command band keeps its own
                         full-width row below. < 600 compacts the chrome, < 430
                         tighter still; < 380 the brand is the coin alone.

   Before this block: grid at 1261, hamburger at 1020, JS accordion at 1260, drawer
   alignment at 900, band padding at 1020, skin at 1201 - six numbers, and the
   baked statics had no .wgf-shell-right at all, so Enter World + the selector fell
   into the command band and read as an orphan second header row. The selector's
   bottom sheet (<= 720px, wgf-selector.css) is that control's own affordance, not
   a header breakpoint. Add header rules HERE; never introduce a fourth number.
   ============================================================================= */

/* -- DESKTOP >= 1280: three zones. auto | minmax(0,1fr) | auto so the side zones
      are sized by their content and can never overlap the nav; the nav centres in
      whatever is left (a long character name shifts it by a few px, never off-row). */
@media (min-width: 1280px) {
  .wgf-shell-topbar__inner {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    column-gap: var(--space-3);
  }
  .wgf-shell-topbar__inner > .wgf-shell-logo { grid-column: 1; grid-row: 1; justify-self: start; }
  .wgf-shell-topbar__inner > .wgf-shell-nav-toggle { display: none; }
  /* grid-row: 1 on every zone is load-bearing: the nav sits AFTER the toggle and BEFORE
     the right cluster in the DOM, and grid auto-placement would otherwise wrap one of
     them to a second row (the 2026-07-03 off-centre bug). */
  .wgf-shell-topbar__inner > .wgf-shell-nav {
    grid-column: 2; grid-row: 1;
    justify-self: center;
    margin: 0;
    min-width: 0;
  }
  .wgf-shell-topbar__inner > .wgf-shell-right,
  .wgf-shell-topbar__inner > .gsh-user-nav {
    grid-column: 3; grid-row: 1;
    justify-self: end;
    margin: 0;
  }
}

/* -- MID 900-1279: one flex row, nothing wraps, pillars fold by tier. -- */
@media (min-width: 900px) and (max-width: 1279px) {
  .wgf-shell-topbar__inner {
    display: flex;
    flex-wrap: nowrap;
    justify-content: flex-start;
  }
  .wgf-shell-topbar__inner > .wgf-shell-nav-toggle { display: none; }
  .wgf-shell-topbar .wgf-shell-nav {
    display: flex;
    flex-direction: row;
    flex: 0 1 auto;
    min-width: 0;
    margin: 0;
    order: 0;
  }
  .wgf-shell-topbar .wgf-shell-right,
  .wgf-shell-topbar__inner > .gsh-user-nav {
    flex: 0 0 auto;
    margin-left: auto;
    order: 0;
  }
}
/* Fold steps inside MID, from measurement (the AH page container, 100vw - 36px, is the
   tightest row; a 16ch character name is the widest right cluster):
     all 7 pillars need ~1050px of row            -> hold them down to 1180;
     minus Token + Tracked (tier 3) ~910px        -> hold down to 1000;
     minus Leaderboards + Guides (tier 2) ~740px  -> fits any 900+ row.
   `html` + the child combinator on purpose: the game-skin block sets display on
   `html.wgf-navskin-game ... > .wgf-nav-link` at (0,4,1); these tie it and win by
   order, so Token/Tracked actually fold (they did not at (0,3,0)). */
@media (min-width: 900px) and (max-width: 1179px) {
  html .wgf-shell-topbar .wgf-shell-nav > .wgf-nav-group[data-nav-tier="3"],
  html .wgf-shell-topbar .wgf-shell-nav > .wgf-nav-link[data-nav-tier="3"] { display: none; }
}
@media (min-width: 900px) and (max-width: 999px) {
  html .wgf-shell-topbar .wgf-shell-nav > .wgf-nav-group[data-nav-tier="2"],
  html .wgf-shell-topbar .wgf-shell-nav > .wgf-nav-link[data-nav-tier="2"] { display: none; }
}

/* -- PHONE < 900: the row rules live in the re-keyed collapse block above (order:
      brand 1, right cluster 2, hamburger 3, drawer 4). Below 600 the chrome compacts,
      below 430 tighter still, so brand + Enter World + selector + hamburger share one
      row on a 390 phone (measured: 370 of 375px); below 380 the wordmark yields to the
      coin (the aria-label still names the brand). -- */
@media (max-width: 599px) {
  .wgf-shell-topbar__inner {
    gap: 6px;
    padding-left: var(--space-2);
    padding-right: var(--space-2);
  }
  .wgf-shell-topbar__inner > .wgf-shell-logo {
    font-size: 13px;
    letter-spacing: 0.08em;
    gap: 6px;
  }
  .wgf-shell-topbar .wgf-shell-right { gap: 6px; }
  .wgf-shell-topbar .wgf-realm-btn { margin-right: 0; padding: 0 9px; }
  .wgf-shell-topbar .wgf-realm-btn--character { max-width: 11ch; }
  .wgf-shell-topbar .wgf-sel { margin-right: 0; }
  .wgf-shell-topbar .wgf-shell-nav-toggle { width: 40px; height: 36px; }
}
@media (max-width: 429px) {
  /* Measured on the AH page (the tightest container, 100vw - 36px): wordmark ~100 +
     Enter World ~81 + chip ~105 + hamburger 36 + three 4px gaps = 334 of the 338px
     row at 390. flex-wrap: wrap moves an item to a new line BEFORE shrinking anything,
     so base sizes must fit or the hamburger drops to row 2. */
  .wgf-shell-topbar__inner { gap: 4px; }
  .wgf-shell-topbar__inner > .wgf-shell-logo { font-size: 11.5px; letter-spacing: 0.04em; gap: 4px; }
  .wgf-shell-topbar .wgf-shell-right { gap: 4px; }
  .wgf-shell-topbar .wgf-realm-btn { padding: 0 7px; }
  .wgf-shell-topbar .wgf-shell-nav-toggle { width: 36px; padding: 0 6px; }
}
@media (max-width: 379px) {
  .wgf-shell-topbar__inner > .wgf-shell-logo { font-size: 0; letter-spacing: 0; gap: 0; }
  .wgf-shell-topbar__inner > .wgf-shell-logo .wgf-logo-coin { width: 26px; height: 26px; }
}
