/* ============================================================
   Idle MMO v3 — The Astral Codex
   Generated from design concept/ — do not edit by hand.
   Source files: styles/design-system.css + components.css + items.css
   ============================================================ */

/* ============================================================
   Idle MMO v3 — The Astral Codex
   Mythic · Mystic · Modern
   ============================================================ */

:root {
  /* ---- Immersive layout ---- */
  --topbar-h:       0px;         /* removed — Wiki/Sign out live in the popover */
  --shell-h:        120px;       /* overlay-shell height — used as
                                    padding-top for non-map page content */

  /* ---- Palette ---- */

  /* Background — cosmic indigo */
  --space-0:        #07091a;     /* deepest, behind starfield */
  --space-1:        #0d1130;     /* main page bg */
  --space-2:        #15193e;     /* card matting */
  --space-3:        #1d2354;     /* raised */
  --space-4:        #292f6b;     /* hover / accent backdrop */

  /* Frosted glass surfaces */
  --glass:          rgba(255, 255, 255, 0.03);
  --glass-hi:       rgba(255, 255, 255, 0.07);
  --glass-deep:     rgba(8, 12, 32, 0.55);
  --glass-stroke:   rgba(255, 255, 255, 0.10);
  --glass-stroke-hi:rgba(255, 255, 255, 0.20);

  /* Text — values lifted in the 2026-05 legibility pass.
     Contrast targets on `--space-3` raised cards (#1d2354):
       ink:       16:1   AAA
       ink-soft:  10:1   AAA
       ink-mute:  ~5.4:1 AA  (was ~4.2:1, dipped below AA on raised cards)
       ink-quill: ~6.7:1 AA+ (was ~5.5:1; italic serif benefits from the lift) */
  --ink:            #f3f1fb;     /* primary */
  --ink-soft:       #c5c0dc;
  --ink-mute:       #9c97c4;
  --ink-quill:      #c8c3df;     /* italic flavor */

  /* Accents */
  --gold:           #e6c46d;     /* luminous warm */
  --gold-hi:        #f9e3a1;
  --gold-deep:      #b08938;
  --gold-glow:      rgba(230, 196, 109, 0.45);

  --teal:           #7fd5cb;     /* mystic cool */
  --teal-hi:        #b8ebe4;
  --teal-deep:      #2f8a82;
  --teal-glow:      rgba(127, 213, 203, 0.45);

  --violet:         #b89bff;     /* arcane */
  --violet-hi:      #d9c8ff;
  --violet-deep:    #6a4ec6;
  --violet-glow:    rgba(184, 155, 255, 0.45);

  /* Signal colors */
  --hp:             #ff8095;     /* HP */
  --hp-deep:        #a83a4f;
  --hp-soft:        rgba(255, 128, 149, 0.18);

  --sp:             #74b8ff;     /* SP / mana */
  --sp-deep:        #2962b8;
  --sp-soft:        rgba(116, 184, 255, 0.18);

  --amber:          #ffc564;     /* AP / energy */
  --amber-deep:     #b88322;
  --amber-soft:     rgba(255, 197, 100, 0.18);

  --xp:             #c5a8ff;     /* XP */
  --xp-deep:        #7253c4;
  --xp-soft:        rgba(197, 168, 255, 0.18);

  --rose:           #ff8095;     /* alias for HP-tone usage */
  --rose-deep:      #a83a4f;
  --rose-soft:      rgba(255, 128, 149, 0.18);

  --sage:           #92e0ad;     /* positive */
  --sage-deep:      #2c8a52;
  --sage-soft:      rgba(146, 224, 173, 0.18);

  --ember:          #ff7a52;     /* danger / critical */
  --ember-deep:     #a82d10;
  --ember-soft:     rgba(255, 122, 82, 0.18);

  /* ---- Type ----
     Display switched from Italiana → Marcellus in the 2026-05 legibility pass.
     Marcellus is a Roman-inspired humanist serif with chunkier strokes and
     wider apertures, so titles read cleanly at 16–40px where Italiana's
     thin verticals blurred. Same "classical/fantasy" feel, single weight. */
  --font-display:   "Marcellus", "Cormorant Garamond", "EB Garamond", serif;
  --font-banner:    "Outfit", "Inter", system-ui, sans-serif;     /* used uppercase + tracking */
  --font-body:      "Outfit", "Inter", system-ui, sans-serif;
  --font-quill:     "Cormorant Garamond", "EB Garamond", serif;   /* italic flavor */
  --font-mono:      "JetBrains Mono", ui-monospace, monospace;

  /* ---- Spacing ---- */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;
  --sp-7: 48px;
  --sp-8: 64px;

  /* ---- Radii (modern: gentle, consistent) ---- */
  --r-1: 4px;
  --r-2: 8px;
  --r-3: 14px;
  --r-4: 20px;
  --r-pill: 999px;
}

/* ============================================================
   Base
   ============================================================ */
* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--space-1);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.55;
  font-feature-settings: "ss01", "kern";
  -webkit-font-smoothing: antialiased;
}

/* Cosmic backdrop — layered: deep base + 2 nebulae + starfield */
body {
  position: relative;
  min-height: 100vh;
  background:
    /* violet nebula bloom top-left */
    radial-gradient(900px 600px at 12% -10%, rgba(106, 78, 198, 0.40) 0%, transparent 60%),
    /* teal nebula bottom-right */
    radial-gradient(1100px 700px at 95% 110%, rgba(47, 138, 130, 0.32) 0%, transparent 60%),
    /* core */
    radial-gradient(1400px 900px at 50% 30%, #161c45 0%, #0a0d28 70%),
    linear-gradient(180deg, #0a0d28 0%, #07091a 100%);
  background-attachment: fixed;
}
/* starfield overlay — three densities */
body::before {
  content: "";
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image:
    /* big stars */
    radial-gradient(1.2px 1.2px at 12% 18%, rgba(255,255,255,0.85) 50%, transparent 100%),
    radial-gradient(1.5px 1.5px at 78% 32%, rgba(255,236,200,0.85) 50%, transparent 100%),
    radial-gradient(1.2px 1.2px at 45% 75%, rgba(220,210,255,0.85) 50%, transparent 100%),
    radial-gradient(1.4px 1.4px at 88% 88%, rgba(255,255,255,0.85) 50%, transparent 100%),
    radial-gradient(1.2px 1.2px at 6% 62%, rgba(190,220,255,0.85) 50%, transparent 100%),
    radial-gradient(1.6px 1.6px at 62% 8%, rgba(255,255,255,0.95) 50%, transparent 100%),
    radial-gradient(1.3px 1.3px at 25% 92%, rgba(255,236,200,0.8) 50%, transparent 100%),
    /* small dust */
    radial-gradient(0.6px 0.6px at 35% 25%, rgba(255,255,255,0.6) 50%, transparent 100%),
    radial-gradient(0.6px 0.6px at 70% 60%, rgba(255,255,255,0.6) 50%, transparent 100%),
    radial-gradient(0.6px 0.6px at 18% 80%, rgba(255,255,255,0.6) 50%, transparent 100%),
    radial-gradient(0.6px 0.6px at 92% 22%, rgba(255,255,255,0.6) 50%, transparent 100%),
    radial-gradient(0.6px 0.6px at 50% 50%, rgba(255,255,255,0.5) 50%, transparent 100%),
    radial-gradient(0.5px 0.5px at 8% 35%, rgba(255,255,255,0.5) 50%, transparent 100%),
    radial-gradient(0.5px 0.5px at 82% 72%, rgba(255,255,255,0.5) 50%, transparent 100%);
  background-size: 100% 100%;
  opacity: 0.9;
}
/* faint grid — like a celestial sphere graticule */
body::after {
  content: "";
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image:
    linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.025) 50%, transparent 100%);
  background-size: 200px 100%;
  background-repeat: repeat-x;
  opacity: 0.6;
}

/* ============================================================
   Document chrome
   ============================================================ */

.doc {
  position: relative;
  z-index: 1;
  max-width: 1280px;
  margin: 0 auto;
  padding: var(--sp-8) var(--sp-5) var(--sp-8);
}

.doc-header {
  text-align: center;
  margin-bottom: var(--sp-7);
  position: relative;
}
.doc-eyebrow {
  font-family: var(--font-banner);
  font-size: 13px;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--teal);
  margin: 0 0 var(--sp-4);
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
}
.doc-eyebrow svg { width: 14px; height: 14px; color: var(--gold); }

.doc-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 96px;
  line-height: 0.95;
  margin: 0;
  color: var(--ink);
  letter-spacing: -0.01em;
  text-shadow: 0 0 60px rgba(184, 155, 255, 0.25);
}
.doc-title .accent {
  font-style: italic;
  color: var(--gold);
  background: linear-gradient(180deg, var(--gold-hi) 0%, var(--gold) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.doc-subtitle {
  font-family: var(--font-body);
  font-size: 19px;
  font-weight: 300;
  color: var(--ink-soft);
  margin: var(--sp-5) auto 0;
  max-width: 680px;
  text-wrap: balance;
  letter-spacing: 0.01em;
}

/* Section heading */
.section-mark {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-2);
}
.section-mark svg { width: 16px; height: 16px; color: var(--gold); }
.section-eyebrow {
  font-family: var(--font-banner);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  color: var(--teal);
  margin: 0;
}
.section-title {
  font-family: var(--font-display);
  font-size: 56px;
  font-weight: 400;
  margin: 0 0 var(--sp-3);
  color: var(--ink);
  line-height: 1;
  letter-spacing: -0.005em;
}
.section-desc {
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 300;
  color: var(--ink-soft);
  margin: 0 0 var(--sp-6);
  max-width: 760px;
  text-wrap: pretty;
  line-height: 1.6;
}

/* ============================================================
   Constellation dividers — the recurring motif
   ============================================================ */
.constellation {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  margin: var(--sp-8) auto;
  color: var(--gold);
  opacity: 0.7;
}
.constellation::before,
.constellation::after {
  content: "";
  flex: 1;
  height: 1px;
  max-width: 280px;
  background: linear-gradient(90deg, transparent, var(--gold-glow) 40%, var(--gold-glow) 60%, transparent);
}
.constellation svg { width: 56px; height: 24px; }

/* Hairline horizontal rule, used inside panels */
.line-rule {
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--glass-stroke-hi) 30%, var(--glass-stroke-hi) 70%, transparent);
  margin: var(--sp-4) 0;
  position: relative;
}
.line-rule.has-dot::after {
  content: "✦";
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  font-size: 12px;
  color: var(--gold);
  background: var(--space-1);
  padding: 0 8px;
  line-height: 1;
}

/* ============================================================
   .panel — frosted glass surface with luminous hairline border
   ============================================================ */
.panel {
  position: relative;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.045) 0%, rgba(255,255,255,0.015) 100%),
    var(--space-2);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-3);
  padding: var(--sp-5);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.06) inset,
    0 0 0 1px rgba(255, 255, 255, 0.02) inset,
    0 20px 50px -20px rgba(0, 0, 0, 0.5),
    0 4px 10px -4px rgba(0, 0, 0, 0.3);
}
/* subtle inner glow on the top edge */
.panel::before {
  content: "";
  position: absolute;
  top: 0; left: 8%; right: 8%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.25) 50%, transparent);
  pointer-events: none;
}
.panel--flat {
  background: var(--glass);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow:
    0 0 0 1px var(--glass-stroke) inset,
    0 4px 12px -4px rgba(0, 0, 0, 0.4);
  padding: var(--sp-4);
}
.panel--quiet {
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid var(--glass-stroke);
  padding: var(--sp-4);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-shadow: none;
}

/* Corner sigil ornaments — luminous rune-like marks.
   Generalised from `.panel > .corners` so any container (panels,
   wiki cards, etc.) holding a `.corners` child picks up the styling.
   Without these explicit sizes the inline SVGs fall back to the
   browser default ~300x150 and overrun the card. */
.corners { position: absolute; inset: 0; pointer-events: none; }
.corners svg {
  position: absolute; width: 18px; height: 18px;
  color: var(--gold);
  opacity: 0.7;
  filter: drop-shadow(0 0 4px var(--gold-glow));
}
.corners svg:nth-child(1) { top: 10px;    left: 10px; }
.corners svg:nth-child(2) { top: 10px;    right: 10px;  transform: scaleX(-1); }
.corners svg:nth-child(3) { bottom: 10px; left: 10px;   transform: scaleY(-1); }
.corners svg:nth-child(4) { bottom: 10px; right: 10px;  transform: scale(-1,-1); }

/* ============================================================
   Buttons — luminous with subtle glow
   ============================================================ */
.btn {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--glass-hi);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: var(--r-pill);
  padding: 11px 22px;
  cursor: pointer;
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transition: transform .12s ease, box-shadow .12s ease, background .12s ease;
  box-shadow: 0 1px 0 rgba(255,255,255,0.06) inset, 0 2px 8px -2px rgba(0,0,0,0.4);
}
.btn:hover {
  transform: translateY(-1px);
  background: rgba(255,255,255,0.10);
  box-shadow: 0 1px 0 rgba(255,255,255,0.10) inset, 0 6px 14px -4px rgba(0,0,0,0.5);
}
.btn:active { transform: translateY(0); }

/* Primary — luminous gold sigil button */
.btn--primary {
  color: #1a1325;
  background:
    linear-gradient(180deg, var(--gold-hi) 0%, var(--gold) 60%, var(--gold-deep) 100%);
  border: 1px solid var(--gold-hi);
  text-shadow: 0 1px 0 rgba(255,255,255,0.3);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.6) inset,
    0 -1px 0 rgba(0,0,0,0.15) inset,
    0 0 22px var(--gold-glow),
    0 6px 16px -4px rgba(120, 80, 20, 0.5);
}
.btn--primary:hover {
  background: linear-gradient(180deg, #fceec0 0%, var(--gold-hi) 60%, var(--gold) 100%);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.7) inset,
    0 -1px 0 rgba(0,0,0,0.15) inset,
    0 0 30px var(--gold-glow),
    0 8px 22px -4px rgba(120, 80, 20, 0.6);
}

/* Teal — secondary action */
.btn--teal {
  color: #07241f;
  background: linear-gradient(180deg, var(--teal-hi) 0%, var(--teal) 60%, var(--teal-deep) 100%);
  border: 1px solid var(--teal-hi);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.5) inset,
    0 0 22px var(--teal-glow),
    0 6px 16px -4px rgba(20, 80, 70, 0.45);
}

/* Danger */
.btn--danger {
  color: #fff;
  background: linear-gradient(180deg, #ff8d72 0%, var(--ember-deep) 100%);
  border: 1px solid #ffb39e;
  box-shadow: 0 0 22px rgba(255, 122, 82, 0.35), 0 6px 14px -4px rgba(0,0,0,0.5);
}

/* Ghost — glass outline */
.btn--ghost {
  background: transparent;
  border: 1px solid var(--glass-stroke-hi);
  color: var(--ink-soft);
  box-shadow: none;
}
.btn--ghost:hover {
  background: var(--glass);
  color: var(--ink);
}

.btn[disabled] {
  cursor: not-allowed;
  opacity: 0.4;
  filter: grayscale(0.6) brightness(0.85);
  transform: none !important;
  box-shadow: 0 0 0 1px var(--glass-stroke) inset !important;
}

.btn--small  { padding: 7px 14px; font-size: 13px; }
.btn--xsmall { padding: 5px 10px; font-size: 12px; }

/* Defensive sizing for any inline SVG inside a .btn. Without this, an
 * <svg> element whose source omits width/height/viewBox falls back to
 * the browser default of 300x150, blowing the button up to fill the
 * screen. Specific contexts (.map-embark .btn--large svg, etc.) can
 * still override via higher-specificity rules. */
.btn svg { width: 14px; height: 14px; flex-shrink: 0; }

/* ============================================================
   Type utilities
   ============================================================ */
.t-display    { font-family: var(--font-display); }
.t-banner     { font-family: var(--font-banner); font-weight: 500; letter-spacing: .24em; text-transform: uppercase; }
.t-quill      { font-family: var(--font-quill); font-style: italic; color: var(--ink-quill); }
.t-meta       { font-family: var(--font-banner); font-weight: 500; font-size: 13px; letter-spacing: .32em; text-transform: uppercase; color: var(--teal); }
.t-num        { font-family: var(--font-body); font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.t-mono       { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.t-soft       { color: var(--ink-soft); }
.t-mute       { color: var(--ink-mute); }
.t-gold       { color: var(--gold); }
.t-teal       { color: var(--teal); }
.t-violet     { color: var(--violet); }

/* Code chip */
.code-chip {
  font-family: var(--font-mono);
  font-size: 13px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-stroke);
  padding: 1px 7px;
  border-radius: 4px;
  color: var(--teal-hi);
}

/* ============================================================
   Idle MMO v3 — Components (Astral Codex)
   ============================================================ */

/* ============================================================
   Game viewport
   ============================================================ */
/* Topbar removed — Wiki/Sign out live inside the menu popover. */
.topbar, .topbar-inner, .topbar-link { display: none; }

/* Immersive viewport — fills the screen beneath the topbar. The shell
   (identity / vials / nav) is overlaid on top via position: absolute. */
.viewport {
  position: relative;
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.01) 100%),
    var(--space-3);
  box-shadow: none;
}
.viewport-inner {
  position: relative;
  background:
    /* localized starfield inside the viewport */
    radial-gradient(800px 500px at 50% 0%, rgba(106, 78, 198, 0.18) 0%, transparent 60%),
    radial-gradient(600px 400px at 90% 100%, rgba(47, 138, 130, 0.15) 0%, transparent 60%),
    linear-gradient(180deg, #0e1336 0%, #0a0d28 100%);
  border-radius: 0;
  overflow: hidden;
  padding: 0;
  min-height: calc(100vh - var(--topbar-h));
}

/* Non-map page content (inventory, shop, quests, combat, etc.) needs to
   sit below the floating shell. Map / battle stages handle their own
   layering so they can paint behind the shell for an immersive feel. */
.viewport-inner > *:not(.shell):not(.map-page):not(.battle-stage):not(.overlay-window) {
  padding-top: calc(var(--shell-h) + var(--sp-3));
  padding-left: var(--sp-5);
  padding-right: var(--sp-5);
  padding-bottom: var(--sp-7);
  box-sizing: border-box;
}
/* tiny localized stars inside viewport */
.viewport-inner::before {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  background-image:
    radial-gradient(1px 1px at 12% 18%, rgba(255,255,255,0.9) 50%, transparent 100%),
    radial-gradient(1.2px 1.2px at 78% 32%, rgba(255,236,200,0.85) 50%, transparent 100%),
    radial-gradient(1px 1px at 45% 75%, rgba(220,210,255,0.9) 50%, transparent 100%),
    radial-gradient(1.4px 1.4px at 88% 88%, rgba(255,255,255,0.85) 50%, transparent 100%),
    radial-gradient(1px 1px at 6% 62%, rgba(190,220,255,0.9) 50%, transparent 100%),
    radial-gradient(1.2px 1.2px at 62% 8%, rgba(255,255,255,0.95) 50%, transparent 100%),
    radial-gradient(0.6px 0.6px at 35% 25%, rgba(255,255,255,0.6) 50%, transparent 100%),
    radial-gradient(0.6px 0.6px at 70% 60%, rgba(255,255,255,0.6) 50%, transparent 100%),
    radial-gradient(0.6px 0.6px at 18% 80%, rgba(255,255,255,0.55) 50%, transparent 100%),
    radial-gradient(0.6px 0.6px at 92% 22%, rgba(255,255,255,0.55) 50%, transparent 100%),
    radial-gradient(0.5px 0.5px at 50% 50%, rgba(255,255,255,0.45) 50%, transparent 100%),
    radial-gradient(0.5px 0.5px at 28% 50%, rgba(255,255,255,0.4) 50%, transparent 100%);
  opacity: 0.95;
}
.viewport-inner > * { position: relative; z-index: 1; }

/* ============================================================
   Persistent Shell — frosted glass header
   ============================================================ */
/* Shell — transparent layout container over the immersive viewport.
   Holds the character box (top-left, compact glass panel) and the menu
   button (top-right). Background is NOT painted on .shell anymore — the
   chrome is on each child so the map scene reads between them. */
.shell {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  /* Stays above the window-overlay (z-index 1000) so the menu icons
     remain clickable — letting the player swap directly between overlay
     screens without first closing the active one. */
  z-index: 1100;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  pointer-events: none;
}
.shell > * { pointer-events: auto; }

/* Character box — compact glass panel grouping medallion + identity + bars.
   No longer full-width; sits in the top-left of the immersive viewport. */
.char-box {
  display: grid;
  grid-template-columns: auto auto auto;
  align-items: center;
  gap: var(--sp-6);
  padding: var(--sp-3) var(--sp-4);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.06) 0%, rgba(255,255,255,0.02) 100%),
    rgba(13, 17, 48, 0.82);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: var(--r-3);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.06) inset,
    0 10px 30px -10px rgba(0,0,0,0.5);
  position: relative;
}
/* gold accent at bottom of char-box that fades from the sides */
.char-box::after {
  content: "";
  position: absolute;
  bottom: 0; left: 12%; right: 12%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold-glow) 30%, var(--gold-glow) 70%, transparent);
  pointer-events: none;
}
@media (max-width: 720px) {
  .char-box {
    grid-template-columns: auto 1fr;
    gap: var(--sp-3);
  }
  .char-box .stat-bars { grid-column: 1 / -1; }
}

/* Identity (legacy class kept for the gold pill etc., now inline inside .char-box) */
.identity {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--sp-6);
  align-items: center;
}

/* Compact horizontal stat bars (HP/SP/AP). Sits to the right of the
   identity text inside .char-box. */
.stat-bars {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 180px;
}
.stat-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-body);
}
.stat-bar-icon {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  filter: drop-shadow(0 0 4px currentColor);
}
.stat-bar-track {
  flex: 1 1 auto;
  position: relative;
  height: 14px;
  border-radius: var(--r-pill);
  background:
    linear-gradient(180deg, rgba(0,0,0,0.45), rgba(0,0,0,0.25));
  border: 1px solid var(--glass-stroke);
  overflow: hidden;
}
.stat-bar-fill {
  position: absolute;
  inset: 0;
  width: var(--p);
  border-radius: inherit;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.18), transparent 60%),
    linear-gradient(90deg, var(--c-deep, #888), var(--c-fill, #ccc));
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.15),
    0 0 8px var(--c-fill);
  transition: width .4s ease-out;
}
.stat-bar-value {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 10px;
  font-weight: 500;
  color: var(--ink);
  text-shadow: 0 1px 2px rgba(0,0,0,0.8);
  z-index: 1;
  letter-spacing: 0.02em;
}
/* Bar-type label ("HP" / "SP" / "AP") sitting between the track and the
   regen chip. Matches the existing `.t-meta` typography family so it
   reads as a category label, not as live data. Coloured per-bar via the
   .stat-bar--hp/sp/ap variants below. */
.stat-bar-label {
  flex: 0 0 auto;
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink-mute);
  min-width: 22px;
  text-align: right;
}
.stat-bar--hp .stat-bar-label { color: #ef6b6b; }
.stat-bar--sp .stat-bar-label { color: #b89bff; }
.stat-bar--ap .stat-bar-label { color: #ffc564; }

.stat-bar-eta {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-mute);
  min-width: 64px;
  justify-content: flex-end;
}
.stat-bar-eta.is-full { opacity: 0.45; }
.stat-bar-rate { line-height: 1; }

/* Circular tick indicator — a ring outline that strokes clockwise from
   the top (12 o'clock) to --p%. The conic-gradient paints the full disc;
   a radial-gradient mask punches the centre out so only an annular ring
   is visible. JS updates --p every 250ms so the ring draws as the next
   regen tick approaches; on rollover, JS rolls the next-tick timestamp
   forward so the ring resets and starts drawing again. */
.stat-bar-tick {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  flex: 0 0 auto;
  background:
    conic-gradient(currentColor var(--p, 0%), rgba(255,255,255,0.10) 0);
  -webkit-mask: radial-gradient(circle at 50% 50%, transparent 50%, black 56%);
          mask: radial-gradient(circle at 50% 50%, transparent 50%, black 56%);
  filter: drop-shadow(0 0 2px rgba(0,0,0,0.5));
}
.stat-bar-eta.is-full .stat-bar-tick {
  background: rgba(255,255,255,0.10);
}
.stat-bar--hp .stat-bar-tick { color: #ef6b6b; }
.stat-bar--sp .stat-bar-tick { color: #b89bff; }
.stat-bar--ap .stat-bar-tick { color: #ffc564; }
.stat-bar--hp { --c-fill: #ef6b6b; --c-deep: #b03030; }
.stat-bar--hp .stat-bar-icon { color: #ef6b6b; }
.stat-bar--sp { --c-fill: #b89bff; --c-deep: #6a4ec6; }
.stat-bar--sp .stat-bar-icon { color: #b89bff; }
.stat-bar--ap { --c-fill: #ffc564; --c-deep: #b08828; }
.stat-bar--ap .stat-bar-icon { color: #ffc564; }

/* Top-right nav cluster — four circular icon buttons + the menu toggle.
   Each .nav-btn shares the same shape; the active route gets gold ring.
   The menu toggle opens a small dropdown anchored beneath it. */
.nav-buttons {
  display: flex;
  align-items: center;
  gap: 8px;
}
.nav-btn {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.06) 0%, rgba(0,0,0,0.18) 100%),
    rgba(13, 17, 48, 0.82);
  border: 1px solid var(--glass-stroke-hi);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.08),
    0 6px 14px -6px rgba(0,0,0,0.55);
  transition: transform .12s, border-color .15s, color .15s, box-shadow .15s;
}
.nav-btn:hover {
  border-color: var(--gold);
  color: var(--gold-hi);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.10),
    0 0 14px var(--gold-glow),
    0 6px 14px -6px rgba(0,0,0,0.55);
}
.nav-btn:active { transform: scale(0.96); }
.nav-btn.is-active {
  color: var(--gold-hi);
  border-color: var(--gold);
  background:
    linear-gradient(180deg, rgba(255, 197, 100, 0.12) 0%, rgba(255, 197, 100, 0.02) 60%, rgba(0,0,0,0.18) 100%),
    rgba(13, 17, 48, 0.82);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.10),
    inset 0 0 0 1px rgba(255, 197, 100, 0.20),
    0 0 14px var(--gold-glow);
}
.nav-btn svg { width: 20px; height: 20px; }

/* Menu button shares .nav-btn — extra rules for the open-popover state. */
.menu { position: relative; }
.menu.is-open .menu-toggle {
  border-color: var(--gold);
  color: var(--gold-hi);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.10),
    0 0 14px var(--gold-glow);
}

/* Popover — appears below the menu toggle. Holds the meta links
   (Wiki / Sign out) since the route navigation lives in the top-right
   icon buttons now. */
.menu-popover[hidden] { display: none; }
.menu-popover {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 12px;
  min-width: 140px;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.04) 0%, rgba(0,0,0,0.18) 100%),
    rgba(13, 17, 48, 0.94);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: var(--r-2);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.06),
    0 18px 40px -10px rgba(0,0,0,0.65);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  animation: menu-pop-in .15s ease-out;
}
@keyframes menu-pop-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.menu-popover-nav {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 5px;
}
/* Nav tiles inherit the dial-pad styling */
.menu-popover-nav a {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 70px;
  height: 60px;
  border-radius: var(--r-2);
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 9.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  text-decoration: none;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.06) 0%, rgba(255,255,255,0.01) 60%, rgba(0,0,0,0.18) 100%),
    rgba(13, 17, 48, 0.55);
  border: 1px solid var(--glass-stroke);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.08),
    inset 0 -3px 6px rgba(0,0,0,0.30);
  transition: transform .12s, color .15s, border-color .15s;
}
.menu-popover-nav a:hover {
  transform: translateY(-1px);
  color: var(--ink);
  border-color: var(--glass-stroke-hi);
}
.menu-popover-nav a.is-active {
  color: var(--gold-hi);
  border-color: var(--gold);
  background:
    linear-gradient(180deg, rgba(255, 197, 100, 0.10) 0%, rgba(255, 197, 100, 0.02) 60%, rgba(0,0,0,0.18) 100%),
    rgba(13, 17, 48, 0.65);
  box-shadow:
    inset 0 2px 6px rgba(0,0,0,0.40),
    0 0 12px var(--gold-glow);
}
.menu-popover-nav a svg {
  width: 18px;
  height: 18px;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.4));
}
/* Meta links inside the popover — Wiki + Sign out as a vertical list. */
.menu-popover-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.menu-popover-meta a {
  display: block;
  padding: 6px 8px;
  border-radius: var(--r-2);
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--ink-soft);
  text-decoration: none;
  letter-spacing: 0.04em;
  transition: color .12s, background .12s;
}
.menu-popover-meta a:hover { color: var(--gold-hi); background: rgba(255,255,255,0.04); }

/* Portrait — concentric orbital rings, not a coin */
.medallion {
  --size: 68px;
  width: var(--size);
  height: var(--size);
  border-radius: 50%;
  position: relative;
  background:
    radial-gradient(circle at 35% 30%, var(--space-3) 0%, var(--space-1) 60%, var(--space-0) 100%);
  display: grid;
  place-items: center;
  overflow: visible;
  box-shadow:
    inset 0 -8px 20px rgba(0,0,0,0.4),
    inset 0 4px 10px rgba(255,255,255,0.04),
    0 0 0 1px var(--glass-stroke),
    0 0 16px rgba(184, 155, 255, 0.15);
}
/* Character portrait clipped to the medallion circle. A wrapper handles
   the circular clip via border-radius+overflow so the inner img can be
   transform-scaled to zoom in on the chibi figure's head without
   escaping its container. The orbital pseudo-element rings on the
   medallion remain visible because they're rendered outside this wrapper. */
.medallion-clip {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
  z-index: 1;
}
.medallion-portrait {
  position: absolute;
  top: 0;
  left: 50%;
  width: 160%;
  height: 160%;
  transform: translateX(-50%);
  object-fit: cover;
  object-position: center top;
}
.medallion::before {
  /* outer orbital ring */
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 1px solid var(--gold);
  opacity: 0.65;
  box-shadow: 0 0 12px var(--gold-glow);
}
.medallion::after {
  /* dotted orbital with four cardinal stars */
  content: "";
  position: absolute;
  inset: -12px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 0%, var(--gold-hi) 0 2px, transparent 3px),
    radial-gradient(circle at 100% 50%, var(--teal-hi) 0 2px, transparent 3px),
    radial-gradient(circle at 50% 100%, var(--gold-hi) 0 2px, transparent 3px),
    radial-gradient(circle at 0% 50%, var(--teal-hi) 0 2px, transparent 3px);
  pointer-events: none;
  filter: drop-shadow(0 0 4px var(--gold-glow));
}
.medallion svg.bust {
  width: 60%;
  height: 60%;
  color: var(--violet);
  opacity: 0.85;
  filter: drop-shadow(0 0 8px var(--violet-glow));
}

.identity-text { line-height: 1.2; }
.identity-top-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin: 0 0 2px;
}
.identity-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 24px;
  color: var(--ink);
  margin: 0;
  letter-spacing: -0.01em;
}
/* Compact gold chip sitting next to the character name. Replaces the
   old .purse on the right side of the shell. */
.identity-gold {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: linear-gradient(180deg, rgba(230, 196, 109, 0.18) 0%, rgba(230, 196, 109, 0.06) 100%);
  border: 1px solid rgba(230, 196, 109, 0.35);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: 12px;
  color: var(--gold-hi);
  line-height: 1;
  white-space: nowrap;
}
.identity-gold svg {
  width: 11px;
  height: 11px;
  color: var(--gold);
  filter: drop-shadow(0 0 3px var(--gold-glow));
}
.identity-meta {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--teal);
  margin: 0 0 6px;
  white-space: nowrap;
}
.identity-meta .dot {
  display: inline-block;
  width: 3px; height: 3px;
  background: var(--gold);
  border-radius: 50%;
  margin: 0 8px;
  vertical-align: middle;
}
.identity-gear {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 300;
  color: var(--ink-soft);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.identity-gear .gear-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
}
.identity-gear svg { width: 13px; height: 13px; color: var(--gold); opacity: 0.8; }

/* ----- Vials → CRYSTAL ORBS ----- */
.vials {
  display: flex;
  gap: var(--sp-3);
  justify-content: center;
  align-items: end;
  padding-top: 6px;
}

.vial {
  --size: 54px;
  --fill: 70%;
  --c-fill: var(--hp);
  --c-deep: var(--hp-deep);
  --c-soft: var(--hp-soft);
  flex: 0 0 auto;
  min-width: 70px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.vial-body {
  position: relative;
  width: var(--size);
  height: var(--size);
}
/* The glass crystal — circular with a faceted inner highlight */
.vial-glass {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 25%, rgba(255,255,255,0.18), rgba(255,255,255,0.02) 50%),
    var(--space-3);
  border: 1px solid var(--glass-stroke-hi);
  overflow: hidden;
  box-shadow:
    inset 0 -6px 12px rgba(0,0,0,0.45),
    inset 0 4px 10px rgba(255,255,255,0.08),
    0 0 16px var(--c-soft),
    0 0 0 1px rgba(255,255,255,0.04);
}
/* Luminous fill — radial bloom from the bottom */
.vial-glass::before {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: var(--fill);
  background:
    radial-gradient(ellipse at 50% 100%, color-mix(in srgb, var(--c-fill) 80%, white 0%) 0%, var(--c-fill) 30%, var(--c-deep) 100%);
  box-shadow:
    inset 0 6px 10px rgba(255,255,255,0.18),
    inset 0 -4px 8px rgba(0,0,0,0.25),
    0 0 12px var(--c-fill);
  filter: blur(0px);
  transition: height .3s ease;
}
/* shine */
.vial-shine {
  position: absolute;
  top: 6px; left: 10px;
  width: 8px; height: 12px;
  background: linear-gradient(180deg, rgba(255,255,255,0.85), rgba(255,255,255,0));
  border-radius: 50%;
  filter: blur(0.5px);
  pointer-events: none;
}
/* small etched glyph on the orb (the resource sigil) */
.vial-sigil {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 18px; height: 18px;
  color: rgba(255,255,255,0.78);
  filter: drop-shadow(0 1px 1px rgba(0,0,0,0.4));
  pointer-events: none;
}

.vial-label {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--ink-mute);
  text-align: center;
}
.vial-value {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  text-align: center;
  line-height: 1;
  white-space: nowrap;
}
.vial-sub {
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 13px;
  color: var(--ink-soft);
  text-align: center;
  line-height: 1.1;
  margin-top: 2px;
}

.vial--hp { --c-fill: var(--hp); --c-deep: var(--hp-deep); --c-soft: var(--hp-soft); }
.vial--sp { --c-fill: var(--sp); --c-deep: var(--sp-deep); --c-soft: var(--sp-soft); }
.vial--ap { --c-fill: var(--amber); --c-deep: var(--amber-deep); --c-soft: var(--amber-soft); }
.vial--xp { --c-fill: var(--xp); --c-deep: var(--xp-deep); --c-soft: var(--xp-soft); }

/* Right pillar */
.shell-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--sp-3);
}

.purse {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 14px;
  border-radius: var(--r-pill);
  background:
    linear-gradient(180deg, rgba(230, 196, 109, 0.18) 0%, rgba(230, 196, 109, 0.06) 100%);
  border: 1px solid rgba(230, 196, 109, 0.40);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--gold-hi);
  box-shadow: 0 0 14px rgba(230, 196, 109, 0.15), 0 0 0 1px rgba(255,255,255,0.04) inset;
}
.purse svg { width: 14px; height: 14px; color: var(--gold); filter: drop-shadow(0 0 4px var(--gold-glow)); }
.purse-amount { font-size: 15px; letter-spacing: 0.02em; }
.purse-label {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--gold);
  opacity: 0.7;
  margin-left: 4px;
}

/* Nav — dial-pad: single row of 4 chunky tiles. Each tile stacks an
   icon on top of a small uppercase label, with a tactile pressed-in
   look on the active tile. */
.nav {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 5px;
  padding: 5px;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.04) 0%, rgba(0,0,0,0.18) 100%),
    var(--glass);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-3);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.06),
    inset 0 -4px 10px rgba(0,0,0,0.30),
    0 6px 14px -8px rgba(0,0,0,0.55);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.nav a {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 60px;
  height: 54px;
  border-radius: var(--r-2);
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 9.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  text-decoration: none;
  position: relative;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.06) 0%, rgba(255,255,255,0.01) 60%, rgba(0,0,0,0.18) 100%),
    rgba(13, 17, 48, 0.55);
  border: 1px solid var(--glass-stroke);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.08),
    inset 0 -3px 6px rgba(0,0,0,0.30),
    0 2px 4px rgba(0,0,0,0.30);
  transition: transform .12s ease, color .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.nav a:hover {
  transform: translateY(-1px);
  color: var(--ink);
  border-color: var(--glass-stroke-hi);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.10),
    inset 0 -3px 6px rgba(0,0,0,0.30),
    0 4px 10px rgba(0,0,0,0.40);
}
.nav a:active {
  transform: translateY(1px);
  box-shadow:
    inset 0 2px 6px rgba(0,0,0,0.45),
    inset 0 -1px 0 rgba(255,255,255,0.04);
}
.nav a.is-active {
  color: var(--gold-hi);
  border-color: var(--gold);
  background:
    linear-gradient(180deg, rgba(255, 197, 100, 0.10) 0%, rgba(255, 197, 100, 0.02) 60%, rgba(0,0,0,0.18) 100%),
    rgba(13, 17, 48, 0.65);
  box-shadow:
    inset 0 2px 6px rgba(0,0,0,0.40),
    inset 0 0 0 1px rgba(255, 197, 100, 0.20),
    0 0 14px var(--gold-glow);
}
.nav a.is-active::after {
  /* small gold dot beneath the label on the active tile */
  content: "";
  position: absolute;
  left: 50%;
  bottom: 3px;
  width: 12px;
  height: 2px;
  transform: translateX(-50%);
  background: var(--gold);
  border-radius: 999px;
  box-shadow: 0 0 6px var(--gold-glow);
}
.nav svg {
  width: 18px;
  height: 18px;
  color: currentColor;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.4));
}
.nav a.is-active svg {
  filter: drop-shadow(0 0 4px var(--gold-glow)) drop-shadow(0 1px 2px rgba(0,0,0,0.4));
}

.shell-meta-links { display: flex; gap: var(--sp-3); align-items: center; }
.signout {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--ink-mute);
  text-decoration: none;
  letter-spacing: 0.06em;
  white-space: nowrap;
  border-bottom: 1px solid rgba(135, 130, 166, 0.35);
  padding-bottom: 1px;
}
.signout:hover { color: var(--ink-soft); }

/* ============================================================
   Town — zone header + expedition entries
   ============================================================ */
.town { margin-top: var(--sp-6); }

.zone-header {
  position: relative;
  text-align: center;
  margin: var(--sp-6) auto var(--sp-7);
  max-width: 760px;
}
.zone-eyebrow {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--teal);
  margin: 0 0 var(--sp-3);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
}
.zone-eyebrow::before, .zone-eyebrow::after {
  content: "";
  height: 1px; width: 60px;
  background: linear-gradient(90deg, transparent, var(--teal), transparent);
  opacity: 0.6;
}
.zone-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 60px;
  margin: 0;
  color: var(--ink);
  line-height: 1;
  letter-spacing: -0.005em;
  text-shadow: 0 0 50px rgba(184, 155, 255, 0.18);
}
.zone-flavor {
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 18px;
  font-weight: 400;
  color: var(--ink-soft);
  margin: var(--sp-4) auto 0;
  max-width: 540px;
  text-wrap: pretty;
  letter-spacing: 0.005em;
}

/* Expedition cards */
.expeditions {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-5);
  max-width: 1100px;
  margin: 0 auto;
}

.expedition {
  position: relative;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.01) 100%),
    rgba(13, 17, 48, 0.55);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-3);
  padding: var(--sp-5);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.05) inset,
    0 10px 30px -10px rgba(0,0,0,0.45);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}
.expedition:hover {
  transform: translateY(-2px);
  border-color: var(--glass-stroke-hi);
  box-shadow: 0 1px 0 rgba(255,255,255,0.08) inset, 0 18px 40px -10px rgba(0,0,0,0.55);
}
.expedition::before {
  /* top luminous edge */
  content: "";
  position: absolute;
  top: 0; left: 12%; right: 12%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent-glow, var(--gold-glow)) 40%, var(--accent-glow, var(--gold-glow)) 60%, transparent);
  pointer-events: none;
}

/* Card accent (color per expedition) */
.expedition--gold     { --accent: var(--gold);   --accent-glow: var(--gold-glow);   }
.expedition--teal     { --accent: var(--teal);   --accent-glow: var(--teal-glow);   }
.expedition--violet   { --accent: var(--violet); --accent-glow: var(--violet-glow); }
.expedition--rose     { --accent: var(--hp);     --accent-glow: var(--rose-soft);   }

.expedition-head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
}

/* sigil — small geometric glyph in a luminous orb */
.sigil {
  flex: 0 0 auto;
  width: 56px;
  height: 56px;
  display: grid;
  place-items: center;
  position: relative;
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 25%, rgba(255,255,255,0.10) 0%, rgba(255,255,255,0.02) 50%),
    var(--space-3);
  border: 1px solid var(--accent, var(--gold));
  color: var(--accent, var(--gold));
  box-shadow:
    0 0 18px var(--accent-glow, var(--gold-glow)),
    inset 0 -4px 8px rgba(0,0,0,0.3),
    inset 0 2px 4px rgba(255,255,255,0.06);
}
.sigil svg {
  width: 28px; height: 28px;
  filter: drop-shadow(0 0 4px var(--accent-glow, var(--gold-glow)));
}

.expedition-titles { flex: 1; min-width: 0; }
.expedition-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 26px;
  line-height: 1.05;
  color: var(--ink);
  margin: 4px 0 8px;
  text-wrap: balance;
  letter-spacing: -0.005em;
}
.expedition-tags { display: flex; gap: var(--sp-2); flex-wrap: wrap; }

.tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding: 4px 9px;
  border-radius: var(--r-pill);
  background: var(--glass);
  border: 1px solid var(--glass-stroke);
}
.tag svg { width: 11px; height: 11px; }
.tag--level  { color: var(--ink-soft); }
.tag--ap     { color: var(--amber); border-color: rgba(255,197,100,0.35); background: rgba(255,197,100,0.08); }
.tag--ap svg { color: var(--amber); }
.tag--danger { color: var(--ember); border-color: rgba(255,122,82,0.35); background: rgba(255,122,82,0.08); }

.expedition-flavor {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 14.5px;
  color: var(--ink-soft);
  line-height: 1.55;
  margin: var(--sp-1) 0 var(--sp-3);
  flex: 1;
  text-wrap: pretty;
  letter-spacing: 0.005em;
}

.expedition-cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--glass-stroke);
}
.expedition-cost {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.expedition-cost svg { width: 12px; height: 12px; color: var(--amber); }
.expedition-cost.is-blocked { color: var(--ember); }

/* "Featured" — minimal luminous tag, top-right */
.ribbon {
  position: absolute;
  top: 12px; right: 12px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  font-family: var(--font-banner);
  font-weight: 600;
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #1a1325;
  background: linear-gradient(180deg, var(--gold-hi), var(--gold));
  border: 1px solid var(--gold-hi);
  box-shadow: 0 0 18px var(--gold-glow), 0 2px 6px rgba(0,0,0,0.4);
  white-space: nowrap;
}
.ribbon::before {
  content: "✦";
  font-size: 10px;
  line-height: 1;
}
/* The featured (gold) card is the only one carrying a ribbon — reserve
   space on its title row so the expedition name can't grow underneath
   the ribbon at any width. */
.expedition--gold .expedition-titles { padding-right: 90px; }

/* ============================================================
   Combat result
   ============================================================ */
.combat-layout {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: var(--sp-5);
  margin-top: var(--sp-6);
  align-items: start;
}

.monster {
  padding: var(--sp-5);
  text-align: center;
}
.monster-portrait {
  width: 100%;
  aspect-ratio: 1;
  border-radius: var(--r-3);
  background:
    radial-gradient(circle at 50% 35%, rgba(146, 224, 173, 0.25) 0%, transparent 50%),
    linear-gradient(180deg, #1a2e1f 0%, #0c1810 100%);
  border: 1px solid rgba(146, 224, 173, 0.25);
  display: grid;
  place-items: center;
  margin-bottom: var(--sp-4);
  box-shadow:
    inset 0 -20px 30px rgba(0, 0, 0, 0.35),
    inset 0 4px 12px rgba(146, 224, 173, 0.08),
    0 0 30px rgba(146, 224, 173, 0.12);
  position: relative;
}
.monster-portrait svg { width: 50%; height: 50%; color: var(--sage); opacity: 0.85; filter: drop-shadow(0 0 8px rgba(146, 224, 173, 0.5)); }
/* Generated monster portrait fills the framed plate, cropped if the source
   is slightly taller than the slot. The reticle ::after stays on top via
   z-index so the corner marks still read as a "target locked" frame. */
.monster-portrait-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--r-3);
  display: block;
  position: absolute;
  inset: 0;
  z-index: 1;
}
.monster-portrait { position: relative; overflow: hidden; }
.monster-portrait::after { z-index: 2; }
.monster-portrait::after {
  /* corner reticle marks — like an enemy lock indicator */
  content: "";
  position: absolute;
  inset: 8px;
  border-radius: var(--r-2);
  background:
    /* TL */
    linear-gradient(90deg, var(--sage) 0 12px, transparent 12px) top left / 12px 1px no-repeat,
    linear-gradient(180deg, var(--sage) 0 12px, transparent 12px) top left / 1px 12px no-repeat,
    /* TR */
    linear-gradient(-90deg, var(--sage) 0 12px, transparent 12px) top right / 12px 1px no-repeat,
    linear-gradient(180deg, var(--sage) 0 12px, transparent 12px) top right / 1px 12px no-repeat,
    /* BL */
    linear-gradient(90deg, var(--sage) 0 12px, transparent 12px) bottom left / 12px 1px no-repeat,
    linear-gradient(0deg, var(--sage) 0 12px, transparent 12px) bottom left / 1px 12px no-repeat,
    /* BR */
    linear-gradient(-90deg, var(--sage) 0 12px, transparent 12px) bottom right / 12px 1px no-repeat,
    linear-gradient(0deg, var(--sage) 0 12px, transparent 12px) bottom right / 1px 12px no-repeat;
  opacity: 0.6;
  pointer-events: none;
}
.monster-name {
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 400;
  margin: 0;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.monster-level {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  color: var(--ember);
  margin: 6px 0 var(--sp-4);
}

/* HP bar */
.hp-bar {
  width: 100%;
  height: 8px;
  background: rgba(0,0,0,0.4);
  border-radius: var(--r-pill);
  overflow: hidden;
  position: relative;
  border: 1px solid var(--glass-stroke);
}
.hp-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--hp), var(--hp-deep));
  box-shadow: 0 0 10px var(--hp-soft), inset 0 1px 0 rgba(255,255,255,0.2);
}
.hp-bar-text {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-soft);
  letter-spacing: 0.06em;
  margin-top: 6px;
  text-align: center;
}

.combat-main { display: flex; flex-direction: column; gap: var(--sp-4); }

/* Outcome banner */
.outcome {
  text-align: center;
  padding: var(--sp-7) var(--sp-5);
  position: relative;
  overflow: hidden;
}
.outcome::before {
  /* soft radial bloom behind the word */
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 50% 50%, var(--gold-glow) 0%, transparent 50%);
  opacity: 0.5;
  pointer-events: none;
}
.outcome-banner {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 76px;
  letter-spacing: 0.02em;
  color: var(--gold-hi);
  margin: 0;
  line-height: 0.95;
  position: relative;
  text-shadow:
    0 0 40px var(--gold-glow),
    0 0 80px var(--gold-glow);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
}
.outcome-banner svg.laurel { width: 48px; height: 48px; color: var(--gold); opacity: 0.7; }
.outcome-flavor {
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 17px;
  color: var(--ink-soft);
  margin: var(--sp-3) 0 0;
  position: relative;
}

/* Rewards strip */
.rewards {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-5);
  padding: var(--sp-4);
  position: relative;
}
.reward {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-body);
  font-size: 17px;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  color: var(--ink);
}
.reward-icon {
  width: 36px; height: 36px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--glass);
  border: 1px solid var(--glass-stroke-hi);
  position: relative;
}
.reward-icon svg { width: 16px; height: 16px; }
.reward--xp   .reward-icon { border-color: rgba(197, 168, 255, 0.45); box-shadow: 0 0 12px var(--xp-soft); }
.reward--xp   .reward-icon svg { color: var(--xp); filter: drop-shadow(0 0 4px var(--xp-soft)); }
.reward--gold .reward-icon { border-color: rgba(230, 196, 109, 0.45); box-shadow: 0 0 12px var(--gold-glow); }
.reward--gold .reward-icon svg { color: var(--gold); filter: drop-shadow(0 0 4px var(--gold-glow)); }
.reward--item .reward-icon { border-color: rgba(127, 213, 203, 0.45); box-shadow: 0 0 12px var(--teal-glow); }
.reward--item .reward-icon svg { color: var(--teal); filter: drop-shadow(0 0 4px var(--teal-glow)); }
.reward-value { font-weight: 600; font-family: var(--font-display); font-size: 24px; line-height: 1; }
.reward-value .plus { color: var(--sage); margin-right: 1px; }
.reward-label {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.reward-divider {
  width: 1px; height: 32px;
  background: linear-gradient(180deg, transparent, var(--glass-stroke-hi), transparent);
}

/* Two-tier reward layout: XP + Gold on the top row, drops wrap onto
   their own row below. Stops multi-drop fights from overflowing the
   combat panel. */
.rewards-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
}
.rewards-stack .rewards {
  padding: var(--sp-3) var(--sp-4);
  flex-wrap: wrap;
}
.rewards-stack .rewards--drops {
  gap: var(--sp-3);
  border-top: 1px solid var(--glass-stroke);
  width: 100%;
  max-width: 720px;
  justify-content: center;
}
.rewards-stack .reward--item {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-pill);
  padding: 4px 12px 4px 6px;
  font-size: 14px;
}

/* Turn log */
.log { padding: var(--sp-5) var(--sp-5) var(--sp-4); }
.log-title {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--teal);
  text-align: center;
  margin: 0 0 var(--sp-5);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
}
.log-title::before, .log-title::after {
  content: "";
  height: 1px;
  width: 80px;
  background: linear-gradient(90deg, transparent, var(--teal), transparent);
  opacity: 0.6;
}
.log-lines {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.log-line {
  display: flex;
  gap: var(--sp-4);
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 17px;
  color: var(--ink-quill);
  line-height: 1.5;
  text-wrap: pretty;
  padding: 6px 0 6px var(--sp-3);
  border-left: 1px solid var(--glass-stroke);
}
.log-line .turn {
  flex: 0 0 36px;
  font-family: var(--font-display);
  font-style: normal;
  color: var(--gold);
  font-size: 18px;
  font-weight: 400;
  text-align: right;
  line-height: 1.5;
  opacity: 0.85;
}
.log-line--hero { border-left-color: var(--teal); }
.log-line--foe  { border-left-color: var(--hp); }
.log-line--crit { color: var(--gold-hi); }
.log-line .roll {
  font-family: var(--font-mono);
  font-style: normal;
  font-size: 13px;
  color: var(--teal-hi);
  margin-left: 6px;
  padding: 2px 8px;
  background: rgba(127, 213, 203, 0.10);
  border: 1px solid rgba(127, 213, 203, 0.25);
  border-radius: var(--r-pill);
  white-space: nowrap;
}
.log-line--crit .roll {
  color: var(--gold-hi);
  background: rgba(230, 196, 109, 0.12);
  border-color: rgba(230, 196, 109, 0.35);
}
.log-line--foe .roll {
  color: var(--hp);
  background: rgba(255, 128, 149, 0.10);
  border-color: rgba(255, 128, 149, 0.30);
}

/* Level-up strip */
.levelup {
  margin-top: var(--sp-4);
  padding: var(--sp-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  background:
    linear-gradient(180deg, rgba(197, 168, 255, 0.18) 0%, rgba(197, 168, 255, 0.04) 100%);
  border: 1px solid rgba(197, 168, 255, 0.35);
  border-radius: var(--r-3);
  box-shadow: 0 0 24px var(--xp-soft);
}
.levelup-text {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 22px;
  color: var(--xp);
  display: flex;
  align-items: center;
  gap: 10px;
  letter-spacing: -0.005em;
}
.levelup-text svg { width: 20px; height: 20px; filter: drop-shadow(0 0 6px var(--xp-soft)); }
.levelup-points {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-left: 8px;
}
.levelup-actions { display: flex; gap: 8px; }
.stat-pill {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding: 6px 14px;
  border-radius: var(--r-pill);
  background: rgba(197, 168, 255, 0.10);
  color: var(--ink);
  border: 1px solid rgba(197, 168, 255, 0.40);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  transition: transform .12s, background .12s, box-shadow .12s;
}
.stat-pill .plus { color: var(--sage); font-weight: 700; }
.stat-pill:hover {
  transform: translateY(-1px);
  background: rgba(197, 168, 255, 0.20);
  box-shadow: 0 0 16px var(--xp-soft);
}

/* ============================================================
   Token-display tiles (system section)
   ============================================================ */
.tokens {
  display: grid;
  grid-template-columns: 1.2fr 1fr 1fr;
  gap: var(--sp-5);
  margin-bottom: var(--sp-5);
}

.swatch-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-2); margin-bottom: var(--sp-4); }
.swatch-row:last-child { margin-bottom: 0; }
.swatch {
  border-radius: var(--r-2);
  height: 64px;
  position: relative;
  overflow: hidden;
  border: 1px solid var(--glass-stroke);
}
.swatch::after {
  content: attr(data-name);
  position: absolute;
  left: 9px; bottom: 7px;
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.92);
  text-shadow: 0 1px 2px rgba(0,0,0,0.5);
}
.swatch.is-dark::after { color: var(--ink); text-shadow: none; }
.swatch .hex {
  position: absolute;
  right: 9px; top: 7px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: rgba(255,255,255,0.78);
  text-shadow: 0 1px 2px rgba(0,0,0,0.5);
}

.type-row { display: flex; align-items: baseline; gap: var(--sp-3); margin: 0 0 var(--sp-4); }
.type-row:last-child { margin-bottom: 0; }
.type-row .label {
  flex: 0 0 84px;
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--teal);
}
.type-sample-display { font-family: var(--font-display); font-size: 32px; line-height: 1; color: var(--ink); }
.type-sample-banner  { font-family: var(--font-banner); font-weight: 500; font-size: 13px; letter-spacing: 0.3em; text-transform: uppercase; color: var(--ink); }
.type-sample-body    { font-family: var(--font-body); font-size: 16px; color: var(--ink); }
.type-sample-quill   { font-family: var(--font-quill); font-style: italic; font-size: 17px; color: var(--ink-quill); }
.type-sample-mono    { font-family: var(--font-mono); font-size: 14px; color: var(--ink); }

.token-stack { display: flex; flex-direction: column; gap: var(--sp-3); }
.token-row { display: flex; align-items: center; gap: var(--sp-3); font-family: var(--font-body); font-size: 13px; color: var(--ink-soft); }
.token-row .key {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--teal-hi);
  flex: 0 0 110px;
}
.token-row .bar {
  height: 6px;
  background: linear-gradient(90deg, var(--gold), var(--violet));
  border-radius: 1px;
  box-shadow: 0 0 6px var(--gold-glow);
}

/* ============================================================
   Misc helpers
   ============================================================ */
.row { display: flex; align-items: center; gap: var(--sp-3); }
.col { display: flex; flex-direction: column; gap: var(--sp-3); }
.center { text-align: center; }
.spacer { flex: 1; }

/* ============================================================
   Idle MMO v3 — Item tile system (Astral Codex)
   ============================================================ */

:root {
  /* Rarity color (glow) — each tier has a luminous accent */
  --r-common-c:    #c0c5d1;      /* dust / pale */
  --r-common-g:    rgba(192, 197, 209, 0.30);

  --r-uncommon-c:  #92e0ad;      /* moss */
  --r-uncommon-g:  rgba(146, 224, 173, 0.45);

  --r-rare-c:      #7fd5cb;      /* mystic teal */
  --r-rare-g:      rgba(127, 213, 203, 0.45);

  --r-epic-c:      #b89bff;      /* arcane violet */
  --r-epic-g:      rgba(184, 155, 255, 0.55);

  --r-legendary-c: #ffc564;      /* solar gold */
  --r-legendary-g: rgba(255, 197, 100, 0.55);

  --r-cursed-c:    #ff7591;      /* blood */
  --r-cursed-g:    rgba(255, 117, 145, 0.50);
}

/* ============================================================
   .item — frosted card with rarity aura
   ============================================================ */
.item {
  --accent: var(--r-common-c);
  --aura:   var(--r-common-g);

  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-4);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.01) 100%),
    rgba(13, 17, 48, 0.65);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-3);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.05) inset,
    0 8px 22px -8px rgba(0,0,0,0.45);
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.item:hover {
  transform: translateY(-2px);
  border-color: var(--accent);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.08) inset,
    0 0 28px var(--aura),
    0 14px 30px -10px rgba(0,0,0,0.55);
}
/* top luminous accent line */
.item::before {
  content: "";
  position: absolute;
  top: 0; left: 12%; right: 12%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent) 40%, var(--accent) 60%, transparent);
  opacity: 0.7;
  pointer-events: none;
}
.item > * { position: relative; z-index: 1; }

/* Rarity variants */
.item--uncommon  { --accent: var(--r-uncommon-c);  --aura: var(--r-uncommon-g); }
.item--rare      { --accent: var(--r-rare-c);      --aura: var(--r-rare-g); border-color: rgba(127,213,203,0.35); }
.item--epic      { --accent: var(--r-epic-c);      --aura: var(--r-epic-g);   border-color: rgba(184,155,255,0.45); box-shadow: 0 1px 0 rgba(255,255,255,0.05) inset, 0 0 20px var(--r-epic-g), 0 8px 22px -8px rgba(0,0,0,0.45); }
.item--legendary { --accent: var(--r-legendary-c); --aura: var(--r-legendary-g); border-color: rgba(255,197,100,0.5); box-shadow: 0 1px 0 rgba(255,255,255,0.06) inset, 0 0 26px var(--r-legendary-g), 0 8px 22px -8px rgba(0,0,0,0.45); }
.item--cursed    { --accent: var(--r-cursed-c);    --aura: var(--r-cursed-g);   border-color: rgba(255,117,145,0.45); }

/* Header row */
.item-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 9.5px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  line-height: 1;
}
.item-tier {
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  filter: drop-shadow(0 0 3px var(--aura));
}
.item-tier::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 6px var(--accent);
}
.item-type { color: var(--ink-mute); }

/* Icon plate — orb instead of paper */
.item-icon {
  position: relative;
  height: 86px;
  display: grid;
  place-items: center;
  background:
    radial-gradient(circle at 50% 30%, color-mix(in srgb, var(--accent) 25%, transparent) 0%, transparent 60%),
    linear-gradient(180deg, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.01) 100%),
    var(--space-3);
  border: 1px solid var(--accent);
  border-radius: var(--r-2);
  margin: var(--sp-2) 0;
  box-shadow:
    inset 0 -10px 18px rgba(0,0,0,0.4),
    inset 0 6px 12px rgba(255,255,255,0.05),
    0 0 18px var(--aura);
  overflow: hidden;
}
.item-icon::before {
  /* radial glow behind icon */
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 60%, var(--aura) 0%, transparent 50%);
  pointer-events: none;
}
.item-icon svg {
  width: 40px;
  height: 40px;
  color: var(--ink);
  filter: drop-shadow(0 0 6px var(--accent)) drop-shadow(0 2px 4px rgba(0,0,0,0.4));
  position: relative;
}
.item--legendary .item-icon svg { color: var(--gold-hi); }
.item--epic .item-icon svg      { color: var(--violet-hi); }
.item--rare .item-icon svg      { color: var(--teal-hi); }
.item--uncommon .item-icon svg  { color: #c6f0d3; }
.item--cursed .item-icon svg    { color: #ffb3c0; }

/* tiny corner pin on the icon — like a fixed gem inlay */
.item-icon::after {
  content: "";
  position: absolute;
  top: 6px; right: 6px;
  width: 4px; height: 4px;
  background: var(--accent);
  border-radius: 50%;
  box-shadow: 0 0 8px var(--accent);
}

/* Name */
.item-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 21px;
  line-height: 1.05;
  color: var(--ink);
  margin: 2px 0;
  text-wrap: balance;
  letter-spacing: -0.005em;
}
.item--legendary .item-name { color: var(--gold-hi); text-shadow: 0 0 12px var(--gold-glow); }
.item--epic .item-name      { color: var(--violet-hi); text-shadow: 0 0 10px var(--violet-glow); }
.item--rare .item-name      { color: var(--teal-hi); }

/* Stats */
.item-stats {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
  font-size: 13.5px;
}
.item-stat {
  display: flex;
  align-items: baseline;
  gap: 6px;
  color: var(--ink);
  flex-wrap: wrap;
}
.item-stat svg {
  width: 12px;
  height: 12px;
  color: var(--gold);
  flex: 0 0 auto;
  transform: translateY(2px);
  opacity: 0.75;
}
.item-stat .v       { font-weight: 600; }
.item-stat .v.plus  { color: var(--sage); }
.item-stat .v.minus { color: var(--ember); }
.item-stat-name {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 9.5px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-left: 4px;
}

.item-compare {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: var(--r-pill);
  margin-left: auto;
  background: var(--glass);
  border: 1px solid var(--glass-stroke);
  white-space: nowrap;
}
.item-compare.is-better { color: var(--sage); border-color: rgba(146, 224, 173, 0.3); background: rgba(146, 224, 173, 0.08); }
.item-compare.is-worse  { color: var(--ember); border-color: rgba(255, 122, 82, 0.3); background: rgba(255, 122, 82, 0.08); }

/* Flavor */
.item-flavor {
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--ink-quill);
  margin: var(--sp-1) 0 var(--sp-2);
  text-wrap: pretty;
  min-height: 1em;
  opacity: 0.9;
}

/* Footer */
.item-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: var(--sp-3);
  border-top: 1px solid var(--glass-stroke);
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.item-req           { color: var(--ink-soft); white-space: nowrap; }
.item-req.is-locked { color: var(--ember); }
.item-price {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  font-weight: 600;
  color: var(--gold);
  letter-spacing: 0;
  text-transform: none;
}
.item-price svg { width: 12px; height: 12px; color: var(--gold); opacity: 0.85; }

/* Equipped state — sage rim + glow */
.item.is-equipped {
  border-color: var(--sage);
  box-shadow:
    0 0 0 1px var(--sage) inset,
    0 0 22px rgba(146, 224, 173, 0.30),
    0 8px 22px -8px rgba(0,0,0,0.45);
}
.item.is-equipped .item-type { color: var(--sage); }
.item.is-equipped .item-price-worn {
  color: var(--sage);
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.item.is-equipped .item-price-worn svg { width: 12px; height: 12px; color: var(--sage); }


/* ============================================================
   Grids
   ============================================================ */
.items-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-4);
}
.items-grid.is-three { grid-template-columns: repeat(3, 1fr); }
.items-grid.is-five  { grid-template-columns: repeat(5, 1fr); }

/* Category banner */
.items-banner {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin: var(--sp-7) 0 var(--sp-4);
}
.items-banner-mark {
  width: 28px; height: 28px;
  flex: 0 0 auto;
  color: var(--gold);
  display: grid;
  place-items: center;
  filter: drop-shadow(0 0 6px var(--gold-glow));
}
.items-banner-mark svg { width: 100%; height: 100%; }
.items-banner-title {
  font-family: var(--font-display);
  font-size: 32px;
  font-weight: 400;
  color: var(--ink);
  margin: 0;
  letter-spacing: -0.005em;
}
.items-banner-rule {
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, var(--gold-glow), transparent);
}
.items-banner-count {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--teal);
}

/* ============================================================
   Rarity legend
   ============================================================ */
.rarity-legend {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--sp-3);
}
.rarity-chip {
  --accent: var(--r-common-c);
  --aura:   var(--r-common-g);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: var(--sp-4) var(--sp-3);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.01) 100%),
    rgba(13, 17, 48, 0.55);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-3);
}
.rarity-chip-swatch {
  width: 100%;
  height: 36px;
  border-radius: var(--r-2);
  background:
    radial-gradient(circle at 50% 30%, color-mix(in srgb, var(--accent) 35%, transparent) 0%, transparent 70%),
    var(--space-3);
  border: 1px solid var(--accent);
  box-shadow: 0 0 18px var(--aura), inset 0 -8px 14px rgba(0,0,0,0.35);
}
.rarity-chip-label {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--accent);
  filter: drop-shadow(0 0 4px var(--aura));
}
.rarity-chip--common    { --accent: var(--r-common-c);    --aura: var(--r-common-g); }
.rarity-chip--uncommon  { --accent: var(--r-uncommon-c);  --aura: var(--r-uncommon-g); }
.rarity-chip--rare      { --accent: var(--r-rare-c);      --aura: var(--r-rare-g); }
.rarity-chip--epic      { --accent: var(--r-epic-c);      --aura: var(--r-epic-g); }
.rarity-chip--legendary { --accent: var(--r-legendary-c); --aura: var(--r-legendary-g); }

/* ============================================================
   Idle MMO — Inventory & Stats screen styles
   Builds on design-system.css / components.css / items.css
   ============================================================ */

/* ============================================================
   Screen layout — two columns
   ============================================================ */
.inv-layout {
  display: grid;
  grid-template-columns: 440px minmax(0, 1fr);
  gap: var(--sp-5);
  margin-top: var(--sp-5);
  align-items: start;
}

@media (max-width: 1100px) {
  .inv-layout { grid-template-columns: 1fr; }
}

/* ============================================================
   Character panel — paperdoll + stats allocator
   ============================================================ */
.character-panel {
  padding: var(--sp-5);
}

.character-eyebrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-4);
}
.character-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 24px;
  color: var(--ink);
  margin: 0;
  letter-spacing: -0.005em;
}
.character-class {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--teal);
}
.character-class .dot {
  display: inline-block;
  width: 3px; height: 3px;
  background: var(--gold);
  border-radius: 50%;
  margin: 0 8px;
  vertical-align: middle;
}

/* ----- Paperdoll grid ----- */
.paperdoll {
  display: grid;
  grid-template-columns: 64px 1fr 64px;
  grid-template-rows: repeat(6, 64px);
  gap: 10px;
  margin-bottom: var(--sp-5);
}

/* Center column — character silhouette */
.paperdoll-figure {
  grid-column: 2;
  grid-row: 1 / -1;
  position: relative;
  border-radius: var(--r-2);
  background:
    radial-gradient(circle at 50% 30%, rgba(184, 155, 255, 0.18) 0%, transparent 50%),
    radial-gradient(circle at 50% 80%, rgba(127, 213, 203, 0.10) 0%, transparent 50%),
    linear-gradient(180deg, #0e1336 0%, #0a0d28 100%);
  border: 1px solid var(--glass-stroke);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.05),
    inset 0 -20px 40px rgba(0,0,0,0.4);
}
/* tiny starfield inside the figure pane */
.paperdoll-figure::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    radial-gradient(1px 1px at 22% 15%, rgba(255,255,255,0.85) 50%, transparent 100%),
    radial-gradient(1px 1px at 78% 28%, rgba(255,236,200,0.8) 50%, transparent 100%),
    radial-gradient(1px 1px at 38% 70%, rgba(220,210,255,0.8) 50%, transparent 100%),
    radial-gradient(0.8px 0.8px at 82% 78%, rgba(255,255,255,0.7) 50%, transparent 100%),
    radial-gradient(0.7px 0.7px at 15% 88%, rgba(255,255,255,0.7) 50%, transparent 100%);
}
/* The silhouette — abstract character + class glyph */
.paperdoll-silhouette {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 130px;
  height: 220px;
}
.paperdoll-silhouette svg.figure {
  width: 100%;
  height: 100%;
  color: var(--violet);
  opacity: 0.7;
  filter: drop-shadow(0 0 16px var(--violet-glow));
}
/* Generated character sprite — Phase 2 drops a class-gender-age WEBP into
   public/art/. The base sprite is the bottom of the paperdoll layer stack
   so worn-item overlays (Phase 3) sit cleanly on top via z-index. */
.paperdoll-sprite {
  position: relative;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  filter: drop-shadow(0 6px 12px rgba(0, 0, 0, 0.4));
  z-index: 1;
}
/* glowing aura disk behind feet */
.paperdoll-silhouette::after {
  content: "";
  position: absolute;
  bottom: 10px;
  left: 50%;
  transform: translateX(-50%);
  width: 90px; height: 14px;
  background: radial-gradient(ellipse at center, var(--violet-glow) 0%, transparent 70%);
  filter: blur(2px);
  pointer-events: none;
}

.paperdoll-figure-meta {
  position: absolute;
  bottom: 12px;
  left: 0; right: 0;
  text-align: center;
  z-index: 1;
}
.paperdoll-figure-meta .level {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--gold);
  line-height: 1;
}
.paperdoll-figure-meta .label {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-top: 3px;
}

/* ----- Equipment slot ----- */
.slot {
  --accent: var(--glass-stroke-hi);
  --aura:   transparent;
  position: relative;
  background: rgba(13, 17, 48, 0.55);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-2);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: border-color .15s, box-shadow .15s, transform .12s;
  overflow: visible;
  /* Anchor-as-slot: strip the default link affordances so filled
     paperdoll slots render identically to their <div> empty siblings. */
  text-decoration: none;
  color: inherit;
}
.slot:hover {
  transform: translateY(-1px);
  border-color: var(--glass-stroke-hi);
}
/* Selected paperdoll slot — mirrors the bag cell's gold-rimmed selection
   so clicking the equipped weapon highlights it the same way as clicking
   a bag tile. */
.slot.is-selected {
  border-color: var(--gold);
  box-shadow: 0 0 14px var(--gold-glow);
}
/* Empty slot — shows a faded category glyph */
.slot.is-empty {
  background:
    radial-gradient(circle at 50% 50%, rgba(255,255,255,0.02) 0%, transparent 70%),
    rgba(13, 17, 48, 0.45);
}
.slot.is-empty svg.placeholder {
  width: 28px; height: 28px;
  color: var(--ink-mute);
  opacity: 0.35;
}
/* Filled slot — bordered + glowing in rarity color */
.slot.is-filled {
  border-color: var(--accent);
  box-shadow:
    0 0 0 1px var(--accent) inset,
    0 0 14px var(--aura);
}
.slot.is-filled svg.item-glyph {
  width: 32px; height: 32px;
  color: var(--ink);
  filter: drop-shadow(0 0 6px var(--accent));
}
.slot.is-filled .slot-rarity-dot {
  position: absolute;
  top: 4px; right: 4px;
  width: 6px; height: 6px;
  background: var(--accent);
  border-radius: 50%;
  box-shadow: 0 0 6px var(--accent);
}

/* Tier-accented slots — match item rarity scale */
.slot.tier-common    { --accent: var(--r-common-c);    --aura: var(--r-common-g); }
.slot.tier-uncommon  { --accent: var(--r-uncommon-c);  --aura: var(--r-uncommon-g); }
.slot.tier-rare      { --accent: var(--r-rare-c);      --aura: var(--r-rare-g); }
.slot.tier-epic      { --accent: var(--r-epic-c);      --aura: var(--r-epic-g); }
.slot.tier-legendary { --accent: var(--r-legendary-c); --aura: var(--r-legendary-g); }

/* Slot label (small text below) — appears on hover. Kept compact so
   the labels of adjacent paperdoll slots can't overlap on the column. */
.slot-label {
  position: absolute;
  bottom: -16px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-soft);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity .15s ease;
}
.slot:hover .slot-label { opacity: 1; }
.slot.is-filled .slot-label { color: var(--ink-soft); }

/* Slot grid positions */
.slot-head    { grid-area: 1 / 1; }
.slot-cape    { grid-area: 2 / 1; }
.slot-weapon  { grid-area: 3 / 1; }
.slot-gloves  { grid-area: 4 / 1; }
.slot-ring-l  { grid-area: 5 / 1; }
.slot-legs    { grid-area: 6 / 1; }

.slot-amulet  { grid-area: 1 / 3; }
.slot-body    { grid-area: 2 / 3; }
.slot-shield  { grid-area: 3 / 3; }
.slot-belt    { grid-area: 4 / 3; }
.slot-ring-r  { grid-area: 5 / 3; }
.slot-boots   { grid-area: 6 / 3; }

/* ============================================================
   Stats allocator
   ============================================================ */
.stats-allocator {
  margin-top: var(--sp-5);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--glass-stroke);
}

.stats-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}
.stats-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  margin: 0;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.stats-points {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px 4px;
  border-radius: var(--r-pill);
  background:
    linear-gradient(180deg, rgba(197, 168, 255, 0.20) 0%, rgba(197, 168, 255, 0.05) 100%);
  border: 1px solid rgba(197, 168, 255, 0.45);
  box-shadow: 0 0 14px var(--xp-soft);
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--xp);
}
.stats-points .count {
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: 0;
  color: var(--violet-hi);
}

.stat-rows {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.stat-row {
  display: grid;
  grid-template-columns: auto 80px 1fr auto;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: rgba(13, 17, 48, 0.45);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-2);
}
.stat-icon {
  width: 26px; height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--glass);
  border: 1px solid var(--glass-stroke-hi);
  color: var(--gold);
}
.stat-icon svg { width: 14px; height: 14px; filter: drop-shadow(0 0 3px var(--gold-glow)); }

.stat-row--str .stat-icon { color: var(--hp);     border-color: rgba(255, 128, 149, 0.45); box-shadow: 0 0 10px var(--hp-soft); }
.stat-row--agi .stat-icon { color: var(--teal);   border-color: rgba(127, 213, 203, 0.45); box-shadow: 0 0 10px var(--teal-glow); }
.stat-row--vit .stat-icon { color: var(--sage);   border-color: rgba(146, 224, 173, 0.45); box-shadow: 0 0 10px rgba(146,224,173,0.18); }

.stat-name {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ink);
}
.stat-name .desc {
  display: block;
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
  margin-top: 1px;
}

.stat-meter {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
.stat-meter-bar {
  position: relative;
  flex: 1;
  height: 4px;
  background: rgba(0,0,0,0.5);
  border-radius: var(--r-pill);
  overflow: hidden;
}
.stat-meter-bar-fill {
  position: absolute;
  inset: 0;
  width: var(--meter, 50%);
  background: linear-gradient(90deg, var(--accent, var(--gold)) 0%, color-mix(in srgb, var(--accent, var(--gold)) 70%, white 0%) 100%);
  border-radius: var(--r-pill);
  box-shadow: 0 0 8px var(--accent-glow, var(--gold-glow));
}
.stat-row--str { --accent: var(--hp);   --accent-glow: var(--hp-soft); }
.stat-row--agi { --accent: var(--teal); --accent-glow: var(--teal-glow); }
.stat-row--vit { --accent: var(--sage); --accent-glow: rgba(146,224,173,0.4); }

.stat-value {
  font-family: var(--font-display);
  font-size: 26px;
  line-height: 1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
  min-width: 36px;
  text-align: right;
}
.stat-bonus {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sage);
}
.stat-bonus.is-zero { color: var(--ink-mute); }

.stat-add {
  font-family: var(--font-banner);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 7px 14px;
  border-radius: var(--r-pill);
  background:
    linear-gradient(180deg, rgba(197, 168, 255, 0.18) 0%, rgba(197, 168, 255, 0.05) 100%);
  border: 1px solid rgba(197, 168, 255, 0.45);
  color: var(--violet-hi);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  transition: transform .12s, background .12s, box-shadow .12s;
}
.stat-add:hover {
  transform: translateY(-1px);
  background: rgba(197, 168, 255, 0.28);
  box-shadow: 0 0 16px var(--xp-soft);
}
.stat-add .plus { color: var(--sage); font-weight: 700; font-size: 13px; }
.stat-add[disabled] {
  cursor: not-allowed;
  opacity: 0.35;
  filter: grayscale(0.5);
}

/* Derived stats (computed from STR/AGI/VIT — informational) */
.derived-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-3);
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px dashed var(--glass-stroke);
}
.derived-stat {
  text-align: center;
}
.derived-stat-label {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: 0 0 2px;
}
.derived-stat-value {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* ============================================================
   Inventory panel — loot grid
   ============================================================ */
.inventory-panel {
  padding: var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  min-height: 700px;
  min-width: 0;
}

.inv-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.inv-title {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 400;
  margin: 0;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.inv-eyebrow {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  color: var(--teal);
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Tabs */
.inv-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  background: var(--glass);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-pill);
  padding: 3px;
  max-width: 100%;
}
.inv-tab {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 6px 10px;
  border-radius: var(--r-pill);
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-mute);
  cursor: pointer;
  background: transparent;
  border: 0;
  position: relative;
  transition: color .15s, background .15s;
  white-space: nowrap;
}
.inv-tab:hover { color: var(--ink-soft); }
.inv-tab.is-active {
  color: var(--ink);
  background: rgba(255,255,255,0.08);
  box-shadow: 0 0 0 1px var(--glass-stroke-hi) inset;
}
.inv-tab.is-active::after {
  content: "";
  position: absolute;
  left: 50%; bottom: 0;
  width: 14px; height: 2px;
  transform: translateX(-50%);
  background: var(--gold);
  border-radius: 999px;
  box-shadow: 0 0 6px var(--gold-glow);
}
.inv-tab .count {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.05em;
  color: var(--ink-mute);
  margin-left: 2px;
}
.inv-tab.is-active .count { color: var(--gold); }

/* Sort + capacity row */
.inv-tools {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}
.inv-sort {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.inv-sort select {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  background: var(--glass);
  border: 1px solid var(--glass-stroke);
  color: var(--ink-soft);
  border-radius: var(--r-pill);
  padding: 5px 10px;
  cursor: pointer;
  outline: none;
}
.inv-sort select:focus { border-color: var(--gold); }

.inv-capacity {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.inv-capacity-bar {
  width: 120px;
  height: 4px;
  background: rgba(0,0,0,0.4);
  border-radius: var(--r-pill);
  overflow: hidden;
  border: 1px solid var(--glass-stroke);
}
.inv-capacity-bar-fill {
  height: 100%;
  width: var(--cap, 50%);
  background: linear-gradient(90deg, var(--teal), var(--gold));
  box-shadow: 0 0 6px var(--teal-glow);
}
.inv-capacity-num {
  color: var(--ink-soft);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  letter-spacing: 0.04em;
}

/* Loot grid — slot-based pattern, more compact than full item tiles */
.inv-grid {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 6px;
  flex: 1;
  min-width: 0;
}
@media (max-width: 1000px) {
  .inv-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
@media (max-width: 700px) {
  .inv-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

.inv-cell {
  --accent: var(--glass-stroke-hi);
  --aura:   transparent;
  position: relative;
  aspect-ratio: 1;
  background:
    radial-gradient(circle at 50% 30%, color-mix(in srgb, var(--accent) 18%, transparent) 0%, transparent 60%),
    rgba(13, 17, 48, 0.55);
  border: 1px solid var(--accent);
  border-radius: var(--r-2);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: transform .12s, box-shadow .15s, border-color .15s;
  overflow: hidden;
}
.inv-cell:hover {
  transform: translateY(-2px);
  box-shadow: 0 0 18px var(--aura), 0 6px 14px -6px rgba(0,0,0,0.4);
  z-index: 2;
}
.inv-cell.is-empty {
  background:
    repeating-linear-gradient(45deg, transparent 0 6px, rgba(255,255,255,0.015) 6px 7px),
    rgba(13, 17, 48, 0.35);
  border-color: var(--glass-stroke);
  cursor: default;
}
.inv-cell.is-empty:hover { transform: none; box-shadow: none; }

.inv-cell.tier-common    { --accent: rgba(192, 197, 209, 0.40);  --aura: var(--r-common-g); }
.inv-cell.tier-uncommon  { --accent: rgba(146, 224, 173, 0.50);  --aura: var(--r-uncommon-g); }
.inv-cell.tier-rare      { --accent: rgba(127, 213, 203, 0.55);  --aura: var(--r-rare-g); }
.inv-cell.tier-epic      { --accent: rgba(184, 155, 255, 0.60);  --aura: var(--r-epic-g); }
.inv-cell.tier-legendary { --accent: rgba(255, 197, 100, 0.65);  --aura: var(--r-legendary-g); }

.inv-cell.is-selected {
  box-shadow:
    0 0 0 1px var(--gold) inset,
    0 0 20px var(--gold-glow);
  border-color: var(--gold);
}

.inv-cell svg.icon {
  width: 36px; height: 36px;
  color: var(--ink);
  filter: drop-shadow(0 0 6px var(--accent)) drop-shadow(0 2px 3px rgba(0,0,0,0.4));
}
.inv-cell.tier-legendary svg.icon { color: var(--gold-hi); }
.inv-cell.tier-epic      svg.icon { color: var(--violet-hi); }
.inv-cell.tier-rare      svg.icon { color: var(--teal-hi); }
.inv-cell.tier-uncommon  svg.icon { color: #c6f0d3; }

/* corner stack count for stackable items */
.inv-cell-stack {
  position: absolute;
  bottom: 4px; right: 5px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  color: var(--ink);
  padding: 1px 5px;
  background: rgba(0,0,0,0.55);
  border-radius: 3px;
  letter-spacing: 0;
}

/* small top-right rarity dot */
.inv-cell-dot {
  position: absolute;
  top: 5px; right: 5px;
  width: 5px; height: 5px;
  background: var(--accent);
  border-radius: 50%;
  box-shadow: 0 0 5px var(--accent);
}
.inv-cell.is-empty .inv-cell-dot { display: none; }

/* "New" indicator */
.inv-cell-new {
  position: absolute;
  top: 4px; left: 4px;
  font-family: var(--font-banner);
  font-weight: 600;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold-hi);
  padding: 1px 5px;
  background: rgba(0,0,0,0.55);
  border: 1px solid var(--gold);
  border-radius: 2px;
  box-shadow: 0 0 6px var(--gold-glow);
  line-height: 1;
}

/* ============================================================
   Selected item detail (right side panel that shows the full item tile)
   ============================================================ */
.inv-detail {
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--glass-stroke);
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: var(--sp-4);
  min-width: 0;
}
.inv-detail-card {
  min-width: 0;
}
.inv-detail-side {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.inv-detail-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-2);
}

/* Comparison rows */
.inv-detail-compare {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: var(--sp-3) var(--sp-4);
  background: rgba(13, 17, 48, 0.45);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-2);
}
.compare-row {
  display: grid;
  grid-template-columns: 60px 48px 18px 48px 1fr;
  align-items: baseline;
  gap: 6px;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: 14px;
}
.compare-stat {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.compare-current { color: var(--ink-soft); font-weight: 500; }
.compare-arrow   { color: var(--ink-mute); text-align: center; font-size: 13px; }
.compare-new     { color: var(--ink); font-weight: 600; }
.compare-delta {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.compare-delta.is-better  { color: var(--sage); }
.compare-delta.is-worse   { color: var(--ember); }
.compare-delta.is-neutral { color: var(--ink-mute); }

/* Solo variant — used when the selected gear is already equipped, so
 * there's no current-vs-new comparison to draw. Just the stat label
 * and the actual value, no arrow, no delta chip. Two-column grid keeps
 * vertical rhythm consistent with the comparison row above it. */
.compare-row--solo {
  grid-template-columns: 60px auto;
  gap: 10px;
}

.inv-detail-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.inv-detail-actions .btn { flex: 0 0 auto; }
.inv-detail-actions .btn--primary { flex: 1 1 auto; }
.inv-detail-empty {
  font-family: var(--font-quill);
  font-style: italic;
  color: var(--ink-mute);
  text-align: center;
  padding: var(--sp-5);
}

/* ============================================================
   Inventory item detail — modal overlay (replaces inline detail
   block). Backdrop is an <a> link that navigates back to the
   bare inventory URL on click; the modal content sits above it.
   ============================================================ */
.inv-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(8, 11, 30, 0.72);
  backdrop-filter: blur(4px);
  z-index: 200;
  cursor: pointer;
  text-decoration: none;
}
.inv-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(760px, 94vw);
  max-height: 90vh;
  overflow-y: auto;
  z-index: 201;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.01) 100%),
    rgba(15, 19, 50, 0.96);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: var(--r-3);
  padding: var(--sp-5);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.06) inset,
    0 30px 80px -20px rgba(0,0,0,0.75),
    0 0 40px -10px rgba(0,0,0,0.5);
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr);
  gap: var(--sp-5);
  align-items: start;
}
@media (max-width: 720px) {
  .inv-modal { grid-template-columns: minmax(0, 1fr); }
}
.inv-modal-close {
  position: absolute;
  top: 10px;
  right: 12px;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-stroke);
  color: var(--ink);
  text-decoration: none;
  font-size: 20px;
  line-height: 1;
  z-index: 1;
  transition: background .15s, color .15s;
}
.inv-modal-close:hover {
  background: rgba(255,255,255,0.12);
  color: var(--gold);
}
/* Inside the modal, the item card icon plate is a square so the
   1024x1024 source PNG renders at its natural aspect with the full
   chibi figure visible (no pillarboxing or vertical clipping). */
.inv-modal .item-icon {
  width: 220px;
  height: 220px;
  margin-left: auto;
  margin-right: auto;
}
.inv-modal .item-icon img {
  width: 100%;
  height: 100%;
  padding: 8px;
  object-fit: contain;
  box-sizing: border-box;
}

/* ============================================================
   Idle MMO — Shop screen styles
   Builds on design-system.css / components.css / items.css / inventory.css
   ============================================================ */

/* ============================================================
   Shop layout — single full-width column (Buy OR Sell)
   ============================================================ */
.shop-body {
  margin-top: var(--sp-5);
  display: block;
}

/* Panels swapped by mode — only one is visible at a time */
.shop-panel {
  padding: var(--sp-5) var(--sp-6);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  min-height: 720px;
}
.shop-panel[hidden] { display: none; }

/* Panel header (vendor name / your inventory) */
.shop-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
}
.shop-head-left { flex: 1; min-width: 0; }
.shop-eyebrow {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  color: var(--teal);
  margin: 0 0 6px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.shop-eyebrow svg { width: 13px; height: 13px; color: var(--gold); filter: drop-shadow(0 0 4px var(--gold-glow)); }
.shop-title {
  font-family: var(--font-display);
  font-size: 32px;
  font-weight: 400;
  margin: 0;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.shop-flavor {
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 14px;
  color: var(--ink-mute);
  margin: 4px 0 0;
  max-width: 360px;
}

/* Vendor portrait — small medallion */
.shop-vendor {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
.shop-vendor-portrait {
  --size: 56px;
  width: var(--size);
  height: var(--size);
  border-radius: 50%;
  position: relative;
  display: grid;
  place-items: center;
  background:
    radial-gradient(circle at 35% 30%, rgba(255,255,255,0.08) 0%, rgba(255,255,255,0.02) 50%),
    var(--space-3);
  border: 1px solid var(--gold);
  box-shadow: 0 0 14px var(--gold-glow), inset 0 -6px 14px rgba(0,0,0,0.4);
}
.shop-vendor-portrait svg { width: 60%; height: 60%; color: var(--gold-hi); filter: drop-shadow(0 0 4px var(--gold-glow)); }
/* Generated NPC portrait fills the 56px circle. Slight face-priority crop
   via object-position so the head is centred even when the painting has
   torso/wagon below it. */
.shop-vendor-portrait { overflow: hidden; }
.shop-vendor-portrait-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 25%;
  border-radius: 50%;
  display: block;
}
.shop-vendor-meta {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.shop-vendor-meta .name {
  display: block;
  font-family: var(--font-display);
  font-size: 18px;
  letter-spacing: -0.005em;
  text-transform: none;
  color: var(--ink);
  margin-bottom: 2px;
}

/* ============================================================
   Mode tabs — BUY / SELL (large, prominent)
   ============================================================ */
/* Buy / Sell tabs — wooden plank "shelf-sign" pair that visually sits
   directly on top of the grid panel. The active tab "drops" into the
   panel (no bottom border + matching background colour) so the two
   feel like one continuous shelf. */
.shop-mode-tabs {
  display: inline-flex;
  gap: 0;
  margin: 0;
  padding: 0;
  border: none;
  background: none;
  backdrop-filter: none;
}
.shop-mode-tab {
  font-family: var(--font-banner);
  font-weight: 600;
  font-size: 11.5px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-mute);
  background:
    linear-gradient(180deg, rgba(120, 80, 50, 0.32) 0%, rgba(70, 45, 28, 0.42) 100%),
    rgba(13, 17, 48, 0.78);
  border: 1px solid var(--glass-stroke);
  padding: 8px 18px;
  border-radius: var(--r-2) var(--r-2) 0 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  position: relative;
  transition: color .15s, background .15s, transform .12s;
}
.shop-mode-tab + .shop-mode-tab { margin-left: 4px; }
.shop-mode-tab:hover { color: var(--ink); transform: translateY(-1px); }
.shop-mode-tab svg { width: 13px; height: 13px; }

/* Active BUY — gold "selected shelf tag", merges into the grid below. */
.shop-mode-tab.is-active[data-mode="buy"] {
  color: var(--gold-hi);
  background:
    linear-gradient(180deg, rgba(255, 197, 100, 0.20) 0%, rgba(255, 197, 100, 0.06) 100%),
    rgba(8, 11, 30, 0.78);
  border-color: var(--gold);
  border-bottom-color: rgba(8, 11, 30, 0.62);   /* merge into shop-grid bg */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.10),
    0 0 14px var(--gold-glow);
  margin-bottom: -1px;                          /* overlap the grid's top border */
  z-index: 1;
}
.shop-mode-tab.is-active[data-mode="buy"] svg { color: var(--gold-hi); }

/* Active SELL — teal sibling. */
.shop-mode-tab.is-active[data-mode="sell"] {
  color: var(--teal-hi);
  background:
    linear-gradient(180deg, rgba(127, 213, 203, 0.20) 0%, rgba(127, 213, 203, 0.06) 100%),
    rgba(8, 11, 30, 0.78);
  border-color: var(--teal-hi);
  border-bottom-color: rgba(8, 11, 30, 0.62);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.10),
    0 0 14px var(--teal-glow);
  margin-bottom: -1px;
  z-index: 1;
}
.shop-mode-tab.is-active[data-mode="sell"] svg { color: var(--teal-hi); }

/* ============================================================
   Category filter chips — designed, full-width row
   ============================================================ */
.shop-filter-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.025) 0%, rgba(255,255,255,0.008) 100%),
    rgba(13, 17, 48, 0.45);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-3);
  flex-wrap: wrap;
}

.shop-filters {
  display: flex;
  gap: 6px;
  align-items: center;
  flex: 1 1 auto;
  min-width: 0;
  flex-wrap: wrap;
}
.shop-filter {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 12px 6px 10px;
  border-radius: var(--r-pill);
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-mute);
  cursor: pointer;
  background: transparent;
  border: 1px solid var(--glass-stroke);
  white-space: nowrap;
  transition: color .15s, background .15s, border-color .15s, box-shadow .15s;
}
.shop-filter:hover {
  color: var(--ink-soft);
  border-color: var(--glass-stroke-hi);
  background: var(--glass);
}
.shop-filter svg {
  width: 13px; height: 13px;
  color: currentColor;
  opacity: 0.75;
}
.shop-filter .count {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--ink-mute);
  padding: 0 5px;
  background: rgba(255,255,255,0.06);
  border-radius: var(--r-pill);
  margin-left: 2px;
  line-height: 1.5;
}
.shop-filter.is-active {
  color: var(--gold-hi);
  background:
    linear-gradient(180deg, rgba(230, 196, 109, 0.16) 0%, rgba(230, 196, 109, 0.04) 100%);
  border-color: rgba(230, 196, 109, 0.50);
  box-shadow: 0 0 14px var(--gold-glow), 0 0 0 1px rgba(255,255,255,0.04) inset;
}
.shop-filter.is-active svg { color: var(--gold); filter: drop-shadow(0 0 4px var(--gold-glow)); opacity: 1; }
.shop-filter.is-active .count {
  color: var(--gold-hi);
  background: rgba(230, 196, 109, 0.14);
}

/* Sell mode tints the active filter teal instead of gold */
.shop-panel[data-mode="sell"] .shop-filter.is-active {
  color: var(--teal-hi);
  background:
    linear-gradient(180deg, rgba(127, 213, 203, 0.16) 0%, rgba(127, 213, 203, 0.04) 100%);
  border-color: rgba(127, 213, 203, 0.50);
  box-shadow: 0 0 14px var(--teal-glow), 0 0 0 1px rgba(255,255,255,0.04) inset;
}
.shop-panel[data-mode="sell"] .shop-filter.is-active svg {
  color: var(--teal); filter: drop-shadow(0 0 4px var(--teal-glow));
}
.shop-panel[data-mode="sell"] .shop-filter.is-active .count {
  color: var(--teal-hi);
  background: rgba(127, 213, 203, 0.14);
}

/* Sort dropdown styled cleaner */
.shop-sort {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.shop-sort svg { width: 12px; height: 12px; opacity: 0.75; }
.shop-sort select {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  background: rgba(13, 17, 48, 0.6);
  border: 1px solid var(--glass-stroke-hi);
  color: var(--ink-soft);
  border-radius: var(--r-pill);
  padding: 7px 12px;
  cursor: pointer;
  outline: none;
  transition: border-color .15s, color .15s;
}
.shop-sort select:hover  { color: var(--ink); border-color: var(--gold); }
.shop-sort select:focus  { border-color: var(--gold); box-shadow: 0 0 10px var(--gold-glow); }

/* Purse strip — your current gold */
.shop-purse {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  border-radius: var(--r-pill);
  background:
    linear-gradient(180deg, rgba(230, 196, 109, 0.16) 0%, rgba(230, 196, 109, 0.04) 100%);
  border: 1px solid rgba(230, 196, 109, 0.40);
  box-shadow: 0 0 14px rgba(230, 196, 109, 0.12);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--gold-hi);
}
.shop-purse svg { width: 14px; height: 14px; color: var(--gold); filter: drop-shadow(0 0 4px var(--gold-glow)); }
.shop-purse-amount { font-size: 16px; letter-spacing: 0.02em; }
.shop-purse-label {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--gold);
  opacity: 0.7;
}

/* ============================================================
   Listing rows — vendor & your-bag (wider now)
   ============================================================ */
.shop-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  flex: 1;
}

.shop-row {
  --accent: var(--glass-stroke-hi);
  --aura:   transparent;
  position: relative;
  display: grid;
  grid-template-columns: 64px 1fr auto 140px;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.035) 0%, rgba(255,255,255,0.01) 100%),
    rgba(13, 17, 48, 0.55);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-2);
  cursor: pointer;
  transition: transform .12s, border-color .15s, box-shadow .15s, background .15s;
}
.shop-row:hover {
  transform: translateX(2px);
  border-color: var(--accent);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.06) 0%, rgba(255,255,255,0.015) 100%),
    rgba(13, 17, 48, 0.62);
  box-shadow: 0 0 18px var(--aura);
}
.shop-row.is-selected {
  border-color: var(--gold);
  box-shadow:
    0 0 0 1px var(--gold) inset,
    0 0 22px var(--gold-glow);
}
/* top luminous accent edge (rarity color) */
.shop-row::before {
  content: "";
  position: absolute;
  top: 0; left: 16%; right: 16%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent) 40%, var(--accent) 60%, transparent);
  opacity: 0.6;
  pointer-events: none;
}

.shop-row.tier-common    { --accent: rgba(192, 197, 209, 0.40); --aura: var(--r-common-g); }
.shop-row.tier-uncommon  { --accent: rgba(146, 224, 173, 0.50); --aura: var(--r-uncommon-g); }
.shop-row.tier-rare      { --accent: rgba(127, 213, 203, 0.55); --aura: var(--r-rare-g); }
.shop-row.tier-epic      { --accent: rgba(184, 155, 255, 0.60); --aura: var(--r-epic-g); }
.shop-row.tier-legendary { --accent: rgba(255, 197, 100, 0.65); --aura: var(--r-legendary-g); }

/* Icon plate (square) */
.shop-row-icon {
  position: relative;
  width: 64px;
  height: 64px;
  display: grid;
  place-items: center;
  border-radius: var(--r-2);
  background:
    radial-gradient(circle at 50% 30%, color-mix(in srgb, var(--accent) 22%, transparent) 0%, transparent 60%),
    rgba(13, 17, 48, 0.6);
  border: 1px solid var(--accent);
  box-shadow:
    inset 0 -8px 14px rgba(0,0,0,0.35),
    inset 0 4px 8px rgba(255,255,255,0.04),
    0 0 10px var(--aura);
}
.shop-row-icon svg { width: 32px; height: 32px; color: var(--ink); filter: drop-shadow(0 0 4px var(--accent)); }
.shop-row.tier-legendary .shop-row-icon svg { color: var(--gold-hi); }
.shop-row.tier-epic      .shop-row-icon svg { color: var(--violet-hi); }
.shop-row.tier-rare      .shop-row-icon svg { color: var(--teal-hi); }
.shop-row.tier-uncommon  .shop-row-icon svg { color: #c6f0d3; }

.shop-row-stack {
  position: absolute;
  bottom: 3px; right: 4px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  color: var(--ink);
  padding: 1px 4px;
  background: rgba(0,0,0,0.6);
  border-radius: 2px;
}

/* Center content */
.shop-row-content { min-width: 0; }
.shop-row-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 9.5px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  line-height: 1;
  margin-bottom: 4px;
  color: var(--ink-mute);
}
.shop-row-tier {
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  gap: 5px;
  filter: drop-shadow(0 0 3px var(--aura));
}
.shop-row.tier-common    .shop-row-tier { color: var(--r-common-c); }
.shop-row.tier-uncommon  .shop-row-tier { color: var(--r-uncommon-c); }
.shop-row.tier-rare      .shop-row-tier { color: var(--r-rare-c); }
.shop-row.tier-epic      .shop-row-tier { color: var(--r-epic-c); }
.shop-row.tier-legendary .shop-row-tier { color: var(--r-legendary-c); }

.shop-row-tier::before {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 5px currentColor;
}
.shop-row-type { color: var(--ink-mute); }
.shop-row-name {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 400;
  color: var(--ink);
  margin: 0 0 4px;
  letter-spacing: -0.005em;
  line-height: 1.05;
}
.shop-row.tier-legendary .shop-row-name { color: var(--gold-hi); }
.shop-row.tier-epic      .shop-row-name { color: var(--violet-hi); }
.shop-row.tier-rare      .shop-row-name { color: var(--teal-hi); }

/* Stats line */
.shop-row-stats {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
  font-size: 13px;
}
.shop-row-stat {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  color: var(--ink-soft);
}
.shop-row-stat svg { width: 11px; height: 11px; color: var(--gold); opacity: 0.75; transform: translateY(1px); }
.shop-row-stat .v { font-weight: 600; }
.shop-row-stat .v.plus  { color: var(--sage); }
.shop-row-stat .v.minus { color: var(--ember); }
.shop-row-stat-name {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-left: 2px;
}

/* Comparison delta vs equipped */
.shop-row-compare {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: var(--r-pill);
  background: var(--glass);
  border: 1px solid var(--glass-stroke);
  white-space: nowrap;
}
.shop-row-compare.is-better { color: var(--sage); border-color: rgba(146, 224, 173, 0.3); background: rgba(146, 224, 173, 0.08); }
.shop-row-compare.is-worse  { color: var(--ember); border-color: rgba(255, 122, 82, 0.3); background: rgba(255, 122, 82, 0.08); }

/* Right side — req + price column */
.shop-row-req {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-soft);
  text-align: right;
  white-space: nowrap;
}
.shop-row-req.is-locked { color: var(--ember); }
.shop-row-req .lvl {
  display: block;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--ink-mute);
  letter-spacing: 0.04em;
  text-transform: none;
  margin-top: 2px;
}

/* Action area (price + button) */
.shop-row-action {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  min-width: 110px;
}
.shop-row-price {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: 18px;
  font-weight: 600;
  color: var(--gold-hi);
  letter-spacing: 0.02em;
}
.shop-row-price svg { width: 14px; height: 14px; color: var(--gold); filter: drop-shadow(0 0 4px var(--gold-glow)); }
.shop-row-price-sell { color: var(--teal-hi); }
.shop-row-price-sell svg { color: var(--teal); filter: drop-shadow(0 0 4px var(--teal-glow)); }

.shop-row-button {
  /* base — re-use .btn styles via class on element */
  min-width: 92px;
  justify-content: center;
}

/* "Equipped" marker on your sell list */
.shop-row-equipped-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--sage);
  padding: 2px 7px;
  border-radius: var(--r-pill);
  background: rgba(146, 224, 173, 0.08);
  border: 1px solid rgba(146, 224, 173, 0.30);
  margin-left: 6px;
}
.shop-row-equipped-tag svg { width: 10px; height: 10px; color: var(--sage); }

/* ============================================================
   Footer / totals strip (sell mode multi-select)
   ============================================================ */
.shop-footer {
  margin-top: auto;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--glass-stroke);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}
.shop-footer-total {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ink-mute);
  display: inline-flex;
  align-items: center;
  gap: 12px;
}
.shop-footer-total .amount {
  font-family: var(--font-display);
  font-size: 24px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--gold-hi);
}
.shop-footer-total.is-sell .amount { color: var(--teal-hi); }

.shop-footer-actions { display: flex; gap: 8px; }

/* ============================================================
   "Empty" states
   ============================================================ */
.shop-empty {
  flex: 1;
  display: grid;
  place-items: center;
  padding: var(--sp-7) var(--sp-5);
  text-align: center;
}
.shop-empty-glyph {
  width: 64px; height: 64px;
  color: var(--ink-mute);
  opacity: 0.4;
  margin-bottom: var(--sp-3);
}
.shop-empty-glyph svg { width: 100%; height: 100%; }
.shop-empty-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  color: var(--ink-soft);
  margin: 0 0 6px;
}
.shop-empty-flavor {
  font-family: var(--font-quill);
  font-style: italic;
  color: var(--ink-mute);
  font-size: 14px;
  max-width: 320px;
}
/* ============================================================
   Local overrides — appended after the vendored design system.
   Edit these in public/styles.css directly; not regenerated.
   ============================================================ */

/* Align the three resource orbs by their TOPS so the AP orb stops sitting
   higher than HP/SP when its "+1 in 3:42" sub-line is present.
   (The vendored CSS used align-items:end which broke alignment whenever
   one vial had a sub-line and the others didn't.) */
.vials {
  align-items: start;
}

/* Identity XP bar — slim horizontal bar shown directly beneath the
   class/level meta line in the shell's identity block. Replaces the
   fourth vial. */
.identity-xp {
  margin-top: 8px;
  max-width: 280px;
}
.identity-xp-track {
  height: 6px;
  background: rgba(0, 0, 0, 0.45);
  border-radius: var(--r-pill);
  overflow: hidden;
  border: 1px solid var(--glass-stroke);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.4);
}
.identity-xp-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--xp-deep), var(--xp));
  box-shadow: 0 0 8px var(--xp-soft), inset 0 1px 0 rgba(255, 255, 255, 0.18);
  transition: width 0.3s ease;
}
.identity-xp-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-top: 4px;
  font-size: 13px;
  color: var(--ink-mute);
}
.identity-xp-meta .t-num {
  color: var(--ink-soft);
  font-size: 13px;
  letter-spacing: 0.02em;
}
.identity-xp--cap .identity-xp-fill {
  background: linear-gradient(90deg, var(--gold-deep), var(--gold));
  box-shadow: 0 0 10px var(--gold-glow), inset 0 1px 0 rgba(255, 255, 255, 0.18);
}
.identity-xp--cap .identity-xp-meta .t-num {
  color: var(--gold);
}

/* Grid cell — visual marker for currently-equipped items */
.inv-cell.is-equipped {
  border-color: var(--sage);
  box-shadow: 0 0 0 1px var(--sage) inset, 0 0 12px rgba(146, 224, 173, 0.25);
}
.inv-cell-worn {
  position: absolute;
  top: 4px;
  left: 4px;
  font-family: var(--font-banner);
  font-weight: 600;
  font-size: 10px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--sage);
  padding: 1px 5px;
  border-radius: var(--r-pill);
  background: rgba(146, 224, 173, 0.12);
  border: 1px solid rgba(146, 224, 173, 0.4);
}

/* Town hub — banner + notice board strip
   Banner has a generous left "art" slot ready for an illustration drop;
   for now a large faint laurel sigil sits there as a placeholder. */
.town-banner {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: var(--sp-5);
  align-items: center;
  padding: var(--sp-5) var(--sp-5);
}
.town-banner-art {
  position: relative;
  height: 160px;
  display: grid;
  place-items: center;
  border-radius: var(--r-2);
  background:
    radial-gradient(circle at 50% 40%, rgba(255, 197, 100, 0.10) 0%, transparent 65%),
    linear-gradient(180deg, rgba(13, 17, 48, 0.65), rgba(8, 12, 32, 0.85));
  border: 1px solid var(--glass-stroke);
  overflow: hidden;
}
.town-banner-art::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    repeating-linear-gradient(45deg, transparent 0 12px, rgba(255,255,255,0.02) 12px 13px);
  pointer-events: none;
}
.town-banner-glyph {
  width: 96px;
  height: 96px;
  color: var(--gold);
  opacity: 0.35;
  filter: drop-shadow(0 0 12px rgba(255, 197, 100, 0.25));
}
/* Generated banner art fills the slot. object-fit: cover so the image
   scales to fully clad the container regardless of source aspect. */
.town-banner-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.town-banner-text { display: flex; flex-direction: column; gap: 6px; }
.town-banner .zone-eyebrow {
  margin: 0;
  justify-content: flex-start;
  letter-spacing: 0.3em;
}
.town-banner .zone-eyebrow::before { display: none; }
.town-banner .zone-eyebrow::after { width: 80px; }
.town-banner .zone-title {
  margin: 0;
  font-size: 38px;
  text-align: left;
}
.town-banner .zone-flavor {
  margin: 6px 0 0;
  text-align: left;
  max-width: 560px;
  font-size: 15px;
}
@media (max-width: 720px) {
  .town-banner { grid-template-columns: 1fr; }
  .town-banner-art { height: 120px; }
}

/* Notice board — two tiles linking out to the live hubs (quests + vendor) */
.town-notices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--sp-4);
  margin-top: var(--sp-5);
}
.town-tile {
  position: relative;
  display: grid;
  grid-template-columns: 56px 1fr auto;
  gap: var(--sp-3);
  align-items: center;
  padding: var(--sp-4);
  background:
    radial-gradient(circle at 100% 0%, rgba(255,255,255,0.05) 0%, transparent 45%),
    rgba(13, 17, 48, 0.50);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-2);
  color: var(--ink);
  text-decoration: none;
  transition: border-color .15s, box-shadow .15s, transform .12s;
}
.town-tile:hover {
  transform: translateY(-2px);
  border-color: var(--glass-stroke-hi);
  box-shadow: 0 6px 20px -8px rgba(0,0,0,0.5);
}
.town-tile-icon {
  width: 56px;
  height: 56px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 30%, color-mix(in srgb, var(--accent, var(--gold)) 24%, transparent) 0%, transparent 60%),
    rgba(8, 12, 32, 0.65);
  border: 1px solid var(--accent, var(--glass-stroke-hi));
  box-shadow: 0 0 14px var(--aura, transparent);
}
.town-tile-icon svg {
  width: 26px;
  height: 26px;
  color: var(--accent, var(--ink));
  filter: drop-shadow(0 0 4px var(--accent, transparent));
}
.town-tile-icon { overflow: hidden; }
.town-tile-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 22%;
  border-radius: 50%;
  display: block;
}
.town-tile-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.town-tile-eyebrow {
  font-family: var(--font-banner);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: 0;
}
.town-tile-headline {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink);
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.town-tile-detail {
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 13.5px;
  color: var(--ink-soft);
  margin: 0;
  line-height: 1.4;
}
.town-tile-cta {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-banner);
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent, var(--ink-soft));
  white-space: nowrap;
}
.town-tile-cta svg { width: 10px; height: 10px; transform: scaleX(-1) rotate(180deg); }

.town-tile--ready  { --accent: var(--sage);     --aura: rgba(146, 224, 173, 0.30); }
.town-tile--active { --accent: var(--teal-hi);  --aura: rgba(127, 213, 203, 0.25); }
.town-tile--new    { --accent: var(--gold-hi);  --aura: rgba(255, 197, 100, 0.30); }
.town-tile--idle   { --accent: var(--ink-mute); --aura: transparent; }
.town-tile--vendor { --accent: var(--gold);     --aura: rgba(255, 197, 100, 0.20); }

/* Town section heading above the expedition grid */
.town-section { margin-top: var(--sp-5); margin-bottom: var(--sp-3); }
.town-section-eyebrow {
  font-family: var(--font-banner);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: 0 0 4px;
}
.town-section-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  color: var(--ink);
  margin: 0;
}

/* Quests page — board of available + active + complete petitions */
.quests-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-5);
}
.quest-section { margin-top: var(--sp-5); }
.quest-section:first-of-type { margin-top: var(--sp-2); }
.quest-section-head { margin-bottom: var(--sp-3); }
.quest-section-eyebrow {
  font-family: var(--font-banner);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: 0 0 4px;
}
.quest-section-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  color: var(--ink);
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.quest-section-count {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-mute);
  padding: 1px 8px;
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-pill);
}
.quest-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: var(--sp-4);
}
.quest-card {
  position: relative;
  padding: var(--sp-4);
  background:
    radial-gradient(circle at 0% 0%, rgba(255,255,255,0.04) 0%, transparent 50%),
    rgba(13, 17, 48, 0.45);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-2);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.quest-card--complete {
  border-color: var(--sage);
  box-shadow: 0 0 18px rgba(146, 224, 173, 0.18), 0 0 0 1px var(--sage) inset;
}
.quest-card--active { border-color: var(--teal); }
.quest-card-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-2);
}
.quest-card-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.quest-card-eyebrow svg { width: 12px; height: 12px; flex-shrink: 0; }
.quest-badge {
  flex-shrink: 0;
  font-family: var(--font-banner);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  border: 1px solid currentColor;
  white-space: nowrap;
}
.quest-badge--new     { color: var(--gold-hi); }
.quest-badge--active  { color: var(--teal-hi); }
.quest-badge--ready   { color: var(--sage); }
.quest-badge--locked  { color: var(--ink-mute); border-color: var(--glass-stroke); }
.quest-card-title {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 400;
  color: var(--ink);
  margin: 0;
}
.quest-card-desc {
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 13.5px;
  color: var(--ink-soft);
  margin: 0;
  line-height: 1.45;
}
.quest-card-objective {
  font-size: 13px;
  color: var(--ink);
  margin: var(--sp-1) 0 0;
}
.quest-card-objective .t-meta {
  font-family: var(--font-banner);
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-right: 6px;
}
.quest-progress-bar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: 2px;
}
.quest-progress-track {
  flex: 1;
  height: 6px;
  background: rgba(0,0,0,0.4);
  border-radius: 3px;
  overflow: hidden;
  border: 1px solid var(--glass-stroke);
}
.quest-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--teal-deep, var(--teal)), var(--teal));
  box-shadow: 0 0 6px rgba(127, 213, 203, 0.5);
}
.quest-card--complete .quest-progress-fill {
  background: linear-gradient(90deg, var(--sage), var(--sage));
  box-shadow: 0 0 8px rgba(146, 224, 173, 0.55);
}
.quest-progress-meta {
  font-size: 13px;
  color: var(--ink-soft);
  white-space: nowrap;
}
.quest-card-foot {
  margin-top: auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-2);
  padding-top: var(--sp-3);
  border-top: 1px dashed var(--glass-stroke);
}
.quest-card-reward {
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
}
.reward-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  color: var(--ink);
  padding: 2px 8px;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-pill);
}
.reward-chip svg { width: 11px; height: 11px; }

/* Combat result — "Quest objective met" callout strip */
.quest-complete-banner {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.quest-complete-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border: 1px solid var(--sage);
  border-radius: var(--r-2);
  background: rgba(146, 224, 173, 0.08);
}
.quest-complete-icon {
  width: 16px;
  height: 16px;
  color: var(--sage);
  flex-shrink: 0;
}
.quest-complete-text {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}
.quest-complete-eyebrow {
  font-family: var(--font-banner);
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sage);
}
.quest-complete-name {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--ink);
}

/* Slot badge — small bodypart indicator pinned to the bottom-left of any
   item picture (inventory grid cell, shop row icon plate, detail card). The
   badge color picks up the rarity accent so it reads as part of the item. */
.slot-badge {
  position: absolute;
  bottom: 4px;
  left: 4px;
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: rgba(8, 12, 32, 0.85);
  border: 1px solid var(--accent, var(--glass-stroke-hi));
  box-shadow: 0 0 6px var(--aura, transparent), 0 1px 3px rgba(0, 0, 0, 0.5);
  color: var(--ink);
  pointer-events: none;
  z-index: 2;
}
.slot-badge svg {
  width: 11px;
  height: 11px;
  filter: drop-shadow(0 0 2px var(--accent, transparent));
}
/* Slightly larger on the shop row icon plate (64px) */
.shop-row-icon .slot-badge {
  width: 22px;
  height: 22px;
  bottom: -6px;
  left: -6px;
  border-width: 1.5px;
}
.shop-row-icon .slot-badge svg { width: 13px; height: 13px; }
/* Larger still on the detail-card orb (86px) */
.item-icon .slot-badge {
  width: 26px;
  height: 26px;
  bottom: 6px;
  left: 6px;
  border-width: 1.5px;
}
.item-icon .slot-badge svg { width: 15px; height: 15px; }
/* Rarity tint on the badge icon to match the item's plate */
.shop-row.tier-legendary .slot-badge svg,
.inv-cell.tier-legendary .slot-badge svg,
.item--legendary .slot-badge svg { color: var(--gold-hi); }
.shop-row.tier-epic .slot-badge svg,
.inv-cell.tier-epic .slot-badge svg,
.item--epic .slot-badge svg { color: var(--violet-hi); }
.shop-row.tier-rare .slot-badge svg,
.inv-cell.tier-rare .slot-badge svg,
.item--rare .slot-badge svg { color: var(--teal-hi); }
.shop-row.tier-uncommon .slot-badge svg,
.inv-cell.tier-uncommon .slot-badge svg,
.item--uncommon .slot-badge svg { color: #c6f0d3; }

/* ============================================================
   Character creation — gender / age radio pickers
   ============================================================ */
.char-pick-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
.char-pick {
  position: relative;
  flex: 1 1 0;
  min-width: 96px;
  padding: 10px 14px;
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-2);
  background: rgba(13, 17, 48, 0.45);
  text-align: center;
  cursor: pointer;
  font-family: var(--font-banner);
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
  transition: border-color .12s, background .12s, color .12s, box-shadow .12s;
}
.char-pick:hover { color: var(--ink); border-color: var(--glass-stroke-hi); }
.char-pick input { position: absolute; opacity: 0; pointer-events: none; }
.char-pick.is-active {
  color: var(--gold-hi);
  border-color: var(--gold);
  background: rgba(255, 197, 100, 0.08);
  box-shadow: 0 0 14px var(--gold-glow);
}

/* ============================================================
   Hearts — single shared visual tier ('heart' rarity).
   Crimson/rose glow; deliberately distinct from the gear ladder
   (common/uncommon/rare/etc.) since every Heart drops at the same
   low rate.
   ============================================================ */
:root {
  --r-heart-c: #ff7591;
  --r-heart-g: rgba(255, 117, 145, 0.50);
}
.item--heart, .tier-heart {
  --accent: var(--r-heart-c);
  --aura:   var(--r-heart-g);
}
.item--heart .item-icon svg,
.tier-heart .wiki-item-icon { color: var(--r-heart-c); }
.inv-cell.tier-heart svg.icon { color: var(--r-heart-c); }
.shop-row.tier-heart .shop-row-icon svg { color: var(--r-heart-c); }

/* ============================================================
   Socket pips — overlay rendered on slotted-gear artwork. Pips
   sit centred along the bottom of the icon plate; filled pips
   show the socketed heart's icon, empty pips are hollow rings.
   ============================================================ */
.socket-pips {
  position: absolute;
  bottom: 4px;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  gap: 4px;
  pointer-events: none;
  z-index: 3;
}
.socket-pip {
  display: grid;
  place-items: center;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: rgba(8, 12, 32, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.30);
}
.socket-pip--empty {
  border-style: dashed;
  border-color: rgba(255, 255, 255, 0.35);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5);
}
.socket-pip--filled {
  border: 1px solid var(--r-heart-c);
  background:
    radial-gradient(circle at 50% 30%, rgba(255, 117, 145, 0.35) 0%, transparent 60%),
    rgba(8, 12, 32, 0.85);
  box-shadow: 0 0 6px var(--r-heart-g);
}
.socket-pip--filled svg {
  width: 9px;
  height: 9px;
  color: var(--r-heart-c);
  filter: drop-shadow(0 0 2px var(--r-heart-g));
}

/* Slightly bigger pips on the inventory detail card (86px orb) so the
   heart icon inside is legible. */
.item-icon .socket-pips { gap: 5px; bottom: 6px; }
.item-icon .socket-pip { width: 18px; height: 18px; }
.item-icon .socket-pip--filled svg { width: 11px; height: 11px; }

/* On the wiki item card (64px square) keep them small but readable. */
.wiki-portrait--item .socket-pips { bottom: 3px; gap: 3px; }
.wiki-portrait--item .socket-pip { width: 12px; height: 12px; }
.wiki-portrait--item .socket-pip--filled svg { width: 8px; height: 8px; }

/* ============================================================
   Item PNG icons — fill the same containers their SVG fallbacks
   would. Adds object-fit so chibi item art scales cleanly inside
   inv-cells, shop rows, paperdoll slots, the inv-detail orb, and
   the combat reward strip.
   ============================================================ */
.inv-cell img.icon,
.shop-row-icon img,
.slot img.item-glyph,
.item-icon img,
.reward-icon img {
  object-fit: contain;
  display: block;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.35));
}
.inv-cell img.icon { width: 36px; height: 36px; }
.shop-row-icon img { width: 36px; height: 36px; }
.slot img.item-glyph { width: 70%; height: 70%; }
.item-icon img { width: 100%; height: 100%; padding: 6px; box-sizing: border-box; }
.reward-icon img { width: 28px; height: 28px; }

/* ============================================================
   Sockets — Heart socketing UI inside inv-detail-side
   ============================================================ */
.inv-detail-sockets {
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px dashed var(--glass-stroke);
}
.socket-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.socket-row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 6px 10px;
  background: rgba(0, 0, 0, 0.20);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-2);
}
.socket-row--filled {
  border-color: rgba(255, 197, 100, 0.40);
  background: rgba(255, 197, 100, 0.06);
}
.socket-pip {
  width: 14px; height: 14px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1px dashed rgba(255, 255, 255, 0.25);
  background: rgba(0, 0, 0, 0.25);
  display: grid;
  place-items: center;
}
.socket-pip.is-filled {
  border: 1px solid var(--gold);
  background: rgba(255, 197, 100, 0.20);
  box-shadow: 0 0 6px var(--gold-glow);
}
.socket-pip svg {
  width: 9px; height: 9px;
  color: var(--gold-hi);
}
.socket-row-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex: 1;
  min-width: 0;
}
.socket-row-name {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.socket-row-bonus {
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 12.5px;
  color: var(--ink-soft);
}
.socket-row-locked {
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
  padding: 2px 6px;
  border: 1px solid rgba(255, 197, 100, 0.35);
  border-radius: var(--r-pill);
  white-space: nowrap;
}
.socket-select {
  flex: 1;
  min-width: 0;
  background: var(--space-1);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-2);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 13px;
  padding: 4px 8px;
}

/* ============================================================
   Wiki — multi-page content browser at /wiki/<section>
   ============================================================ */
.wiki-shell {
  position: relative;
  z-index: 1; /* sit above viewport-inner ::before starfield */
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  gap: var(--sp-5);
  align-items: start;
}
@media (max-width: 820px) {
  .wiki-shell { grid-template-columns: 1fr; }
}

/* Sidebar — sticky on the left */
.wiki-sidebar {
  position: sticky;
  top: var(--sp-4);
  padding: var(--sp-4);
  background:
    radial-gradient(circle at 0% 0%, rgba(255,255,255,0.04) 0%, transparent 50%),
    rgba(13, 17, 48, 0.55);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-3);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.wiki-sidebar-eyebrow {
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--teal);
  margin: 0;
}
.wiki-sidebar-title {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 400;
  color: var(--ink);
  margin: 0 0 var(--sp-2);
  letter-spacing: -0.005em;
}
.wiki-sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.wiki-sidebar-link {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 8px 10px;
  border-radius: var(--r-2);
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-mute);
  text-decoration: none;
  transition: color .12s, background .12s, border-color .12s;
  border: 1px solid transparent;
}
.wiki-sidebar-link svg {
  width: 14px; height: 14px;
  color: var(--ink-mute);
  flex-shrink: 0;
}
.wiki-sidebar-link:hover {
  color: var(--ink);
  background: rgba(255, 255, 255, 0.04);
}
.wiki-sidebar-link:hover svg { color: var(--ink-soft); }
.wiki-sidebar-link.is-active {
  color: var(--gold-hi);
  background: rgba(255, 197, 100, 0.08);
  border-color: rgba(255, 197, 100, 0.25);
  box-shadow: 0 0 12px rgba(255, 197, 100, 0.15);
}
.wiki-sidebar-link.is-active svg {
  color: var(--gold-hi);
  filter: drop-shadow(0 0 4px var(--gold-glow));
}
.wiki-sidebar-label { flex: 1; min-width: 0; }
.wiki-sidebar-count {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-mute);
  padding: 1px 7px;
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-pill);
  background: rgba(0, 0, 0, 0.20);
}
.wiki-sidebar-link.is-active .wiki-sidebar-count {
  color: var(--gold-hi);
  border-color: rgba(255, 197, 100, 0.35);
}
.wiki-sidebar-back {
  margin-top: var(--sp-2);
  padding-top: var(--sp-3);
  border-top: 1px dashed var(--glass-stroke);
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
  text-decoration: none;
}
.wiki-sidebar-back:hover { color: var(--gold-hi); }

/* Main content column */
.wiki-content { min-width: 0; }

/* Overview landing — large tiles, one per section */
.wiki-overview-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--sp-4);
}
.wiki-overview-tile {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  gap: var(--sp-3);
  align-items: center;
  padding: var(--sp-4);
  background:
    radial-gradient(circle at 100% 0%, rgba(255,255,255,0.05) 0%, transparent 45%),
    rgba(13, 17, 48, 0.50);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-3);
  color: var(--ink);
  text-decoration: none;
  transition: transform .12s, border-color .15s, box-shadow .15s;
}
.wiki-overview-tile:hover {
  transform: translateY(-2px);
  border-color: var(--gold);
  box-shadow: 0 8px 20px -8px rgba(0,0,0,0.5), 0 0 14px var(--gold-glow);
}
.wiki-overview-icon {
  width: 56px;
  height: 56px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 30%, rgba(255, 197, 100, 0.20) 0%, transparent 60%),
    rgba(8, 12, 32, 0.65);
  border: 1px solid var(--gold);
  box-shadow: 0 0 12px var(--gold-glow);
}
.wiki-overview-icon svg {
  width: 26px; height: 26px;
  color: var(--gold-hi);
  filter: drop-shadow(0 0 4px var(--gold-glow));
}
.wiki-overview-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.wiki-overview-eyebrow {
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: 0;
}
.wiki-overview-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  color: var(--ink);
  margin: 0;
}
.wiki-overview-arrow {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--ink-mute);
}
.wiki-overview-tile:hover .wiki-overview-arrow { color: var(--gold); }

/* Boxed content panel — the whole wiki section sits inside this card
   so the title bar, filter, and grid all share a single bounded frame.
   On the overview / landing page the box is mostly invisible (no need
   for a heavy panel around the picker tiles). */
.wiki-content-box {
  background:
    radial-gradient(circle at 100% 0%, rgba(255,255,255,0.04) 0%, transparent 45%),
    rgba(13, 17, 48, 0.50);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-3);
  padding: var(--sp-4) var(--sp-5) var(--sp-5);
}

.wiki-section:first-child { margin-top: 0; }
.wiki-section { scroll-margin-top: var(--sp-5); }

/* Section header — title block on the left, filter input on the right.
   Sticks to the top of the content box so filtering long lists stays
   one-thumb-from-the-input as the player scrolls. */
.wiki-section-head {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: var(--sp-4);
  margin-bottom: var(--sp-4);
  padding: var(--sp-3) 0 var(--sp-3);
  border-bottom: 1px solid var(--glass-stroke);
  position: sticky;
  top: 0;
  z-index: 5;
  background:
    linear-gradient(180deg, rgba(13, 17, 48, 0.96) 0%, rgba(13, 17, 48, 0.86) 70%, rgba(13, 17, 48, 0) 100%);
  /* Bleed past the panel's padding so the sticky bar lines up with the
     box's edges instead of leaving a strip of background visible. */
  margin-left: calc(var(--sp-5) * -1);
  margin-right: calc(var(--sp-5) * -1);
  padding-left: var(--sp-5);
  padding-right: var(--sp-5);
}
.wiki-section-head--overview {
  /* Landing page: no filter, recenter the title. */
  justify-content: center;
  text-align: center;
  position: static;
  background: transparent;
  margin-left: 0;
  margin-right: 0;
  padding-left: 0;
  padding-right: 0;
  border-bottom: none;
}
.wiki-section-head--overview .wiki-section-title { font-size: 32px; }
.wiki-section-title-block { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.wiki-section-eyebrow {
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: 0;
}
.wiki-section-title {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 400;
  color: var(--ink);
  margin: 0;
  letter-spacing: -0.005em;
}

/* Filter input — right side of the section header. */
.wiki-section-filter {
  position: relative;
  flex: 0 1 320px;
  min-width: 200px;
}
.wiki-section-filter-icon {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  width: 14px;
  height: 14px;
  color: var(--ink-mute);
  pointer-events: none;
  opacity: 0.8;
}
.wiki-filter-input {
  width: 100%;
  padding: 8px 12px 8px 34px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.65);
  border: 1px solid var(--glass-stroke-hi);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 13.5px;
  outline: none;
  transition: border-color .12s, box-shadow .12s;
  -webkit-appearance: none;
}
.wiki-filter-input::placeholder { color: var(--ink-mute); opacity: 0.7; }
.wiki-filter-input:focus {
  border-color: var(--gold);
  box-shadow: 0 0 0 2px var(--gold-glow);
}
.wiki-filter-input:focus + * { /* no-op, just future-proofing */ }

.wiki-filter-empty {
  margin: var(--sp-5) 0 0;
  text-align: center;
  font-family: var(--font-quill);
  font-style: italic;
  color: var(--ink-mute);
}

/* Subsections inside Equipment + Items — heading + optional blurb. */
.wiki-subsection { margin-top: var(--sp-5); }
.wiki-subsection:first-child { margin-top: var(--sp-2); }
.wiki-subsection-title {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 400;
  color: var(--ink-soft);
  margin: 0 0 var(--sp-2);
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
}
.wiki-subsection-blurb {
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 13.5px;
  color: var(--ink-mute);
  margin: 0 0 var(--sp-3);
  max-width: 60ch;
}

/* Stack the filter under the title on narrow screens. */
@media (max-width: 720px) {
  .wiki-section-head {
    flex-direction: column;
    align-items: stretch;
    position: static;
  }
  .wiki-section-filter { flex: 0 0 auto; }
}
.wiki-count {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-mute);
  padding: 1px 8px;
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-pill);
}

.wiki-grid {
  display: grid;
  gap: var(--sp-4);
}
.wiki-grid--monsters { grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); }
.wiki-grid--items    { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.wiki-grid--quests   { grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); }
.wiki-grid--zones    { grid-template-columns: repeat(auto-fill, minmax(420px, 1fr)); }
.wiki-grid--npcs     { grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); }

.wiki-card {
  position: relative;
  background:
    radial-gradient(circle at 0% 0%, rgba(255,255,255,0.04) 0%, transparent 50%),
    rgba(13, 17, 48, 0.55);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-3);
  padding: var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  overflow: hidden;
}
.wiki-card--monster { flex-direction: row; align-items: stretch; }
.wiki-card--monster .wiki-card-body { flex: 1; min-width: 0; }
.wiki-card--item { flex-direction: row; align-items: stretch; }
.wiki-card--item .wiki-card-body { flex: 1; min-width: 0; }
.wiki-card--npc { flex-direction: row; align-items: stretch; }
.wiki-card--npc .wiki-card-body { flex: 1; min-width: 0; }

.wiki-portrait {
  position: relative;
  flex-shrink: 0;
  border-radius: var(--r-2);
  overflow: hidden;
  background:
    radial-gradient(circle at 50% 30%, rgba(127, 213, 203, 0.10) 0%, transparent 60%),
    rgba(8, 12, 32, 0.65);
  border: 1px solid var(--glass-stroke);
}
.wiki-portrait img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.wiki-portrait--monster { width: 128px; height: 128px; }
.wiki-portrait--npc     { width: 128px; height: 128px; }
.wiki-portrait--item    {
  width: 64px; height: 64px;
  display: grid; place-items: center;
  border-color: var(--accent, var(--glass-stroke));
  box-shadow: 0 0 12px var(--aura, transparent);
}
.wiki-item-icon { width: 36px; height: 36px; color: var(--ink); filter: drop-shadow(0 0 4px var(--accent, transparent)); }
/* Generated chibi item art — fills the portrait square with object-fit
   contain so we preserve aspect even when source is portrait/landscape. */
.wiki-item-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.4));
}
.wiki-card--item.item--legendary .wiki-item-icon { color: var(--gold-hi); }
.wiki-card--item.item--epic      .wiki-item-icon { color: var(--violet-hi); }
.wiki-card--item.item--rare      .wiki-item-icon { color: var(--teal-hi); }
.wiki-card--item.item--uncommon  .wiki-item-icon { color: #c6f0d3; }

.wiki-card-head { display: flex; flex-direction: column; gap: 4px; }
.wiki-card-eyebrow {
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: 0;
}
.wiki-card-eyebrow code {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
  background: rgba(0,0,0,0.25);
  padding: 1px 4px;
  border-radius: 3px;
}
.wiki-card-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  color: var(--ink);
  margin: 0;
  letter-spacing: -0.005em;
}

.wiki-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
  gap: var(--sp-2);
  margin-top: 2px;
}
.wiki-stats--quest { grid-template-columns: 1fr; }
.wiki-stat {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 6px 10px;
  background: rgba(0,0,0,0.22);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-2);
}
.wiki-stat-key {
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.wiki-stat-val {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 13px;
  color: var(--ink);
}

.wiki-block-label {
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: var(--sp-2) 0 6px;
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
}
.wiki-drop-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.wiki-drop {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 12.5px;
  color: var(--ink-soft);
  padding: 4px 10px;
  background: rgba(0,0,0,0.18);
  border-radius: var(--r-2);
}
.wiki-drop--none {
  color: var(--ink-mute);
  font-family: var(--font-quill);
  font-style: italic;
  justify-content: center;
}
.wiki-drop-name { font-family: var(--font-body); }
.wiki-drop-pct {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-mute);
}

/* Grouped + pill-style monster drops — used on the new bestiary cards.
   Each category (Weapons / Armor / Catalysts / Hearts / Consumables)
   becomes one row of compact rarity-tinted pills, sorted by chance. */
.wiki-drops-empty {
  margin: 0;
  padding: 6px 10px;
  font-family: var(--font-quill);
  font-style: italic;
  color: var(--ink-mute);
  text-align: center;
  background: rgba(0,0,0,0.18);
  border-radius: var(--r-2);
}
.wiki-drop-group { margin-top: 6px; }
.wiki-drop-group:first-child { margin-top: 0; }
.wiki-drop-group-label {
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: 0 0 4px;
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.wiki-drop-pill-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.wiki-drop-pill {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.58);
  border: 1px solid var(--accent, var(--glass-stroke));
  font-size: 11.5px;
  color: var(--ink);
  white-space: nowrap;
  max-width: 100%;
}
.wiki-drop-pill-name {
  overflow: hidden;
  text-overflow: ellipsis;
  font-family: var(--font-body);
}
.wiki-drop-pill-pct {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--ink-mute);
  flex-shrink: 0;
}
.wiki-drop-pill.tier-common    { --accent: rgba(192, 197, 209, 0.30); }
.wiki-drop-pill.tier-uncommon  { --accent: rgba(146, 224, 173, 0.40); color: #d8f0df; }
.wiki-drop-pill.tier-rare      { --accent: rgba(127, 213, 203, 0.45); color: #c5edec; }
.wiki-drop-pill.tier-epic      { --accent: rgba(184, 155, 255, 0.50); color: #ddd0ff; }
.wiki-drop-pill.tier-legendary { --accent: rgba(255, 197, 100, 0.55); color: var(--gold-hi); }
.wiki-drop-pill.tier-heart     { --accent: rgba(255, 117, 145, 0.50); color: #ffc8d0; }

/* "Drops from X / Sold by vendors" line on item cards — small muted
   line above the flavor copy. */
.wiki-card-source {
  display: block;
  font-family: var(--font-banner);
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: var(--sp-2) 0 0;
}

.wiki-flavor {
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 14px;
  color: var(--ink-soft);
  margin: 6px 0 0;
  line-height: 1.45;
}
.wiki-flavor--quest { font-size: 14.5px; }
.wiki-flavor--zone { margin-bottom: var(--sp-3); }

.wiki-expeditions {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  margin-top: var(--sp-3);
}
.wiki-expedition {
  padding: var(--sp-3);
  background: rgba(0,0,0,0.20);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-2);
}

/* Item rarity tinted borders on item cards in the wiki (reuse the same
   accent vars the inventory and shop rows already use). */
.wiki-card--item.item--common    { --accent: rgba(192, 197, 209, 0.45); --aura: var(--r-common-g); }
.wiki-card--item.item--uncommon  { --accent: rgba(146, 224, 173, 0.50); --aura: var(--r-uncommon-g); }
.wiki-card--item.item--rare      { --accent: rgba(127, 213, 203, 0.55); --aura: var(--r-rare-g); }
.wiki-card--item.item--epic      { --accent: rgba(184, 155, 255, 0.60); --aura: var(--r-epic-g); }
.wiki-card--item.item--legendary { --accent: rgba(255, 197, 100, 0.65); --aura: var(--r-legendary-g); }
.wiki-card--item.item--common    { border-color: rgba(192, 197, 209, 0.20); }
.wiki-card--item.item--uncommon  { border-color: rgba(146, 224, 173, 0.30); }
.wiki-card--item.item--rare      { border-color: rgba(127, 213, 203, 0.35); }
.wiki-card--item.item--epic      { border-color: rgba(184, 155, 255, 0.40); }
.wiki-card--item.item--legendary { border-color: rgba(255, 197, 100, 0.45); }

/* ============================================================
   Status window — Ragnarok-style three-column layout
   left:  stat allocator  · middle: portrait · right: totals
   ============================================================ */
.stats-page {
  display: block;
  margin: 0;
}
.stats-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr) minmax(0, 1fr);
  gap: var(--sp-3);
  align-items: stretch;
}
@media (max-width: 900px) {
  .stats-layout { grid-template-columns: 1fr; }
}
.stats-col {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-4);
  min-width: 0;
}
.stats-col-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  margin: 0;
}
.stats-points-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 4px 12px;
  border-radius: var(--r-pill);
  background: rgba(255, 197, 100, 0.10);
  border: 1px solid rgba(255, 197, 100, 0.45);
  box-shadow: 0 0 12px var(--gold-glow);
}
.stats-points-label {
  font-family: var(--font-banner);
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold);
}
.stats-points-count {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 16px;
  color: var(--gold-hi);
  line-height: 1;
}

/* Allocate column — STR/AGI/VIT rows. Compact variant of the legacy
   .stats-allocator (no derived stats grid; those now live in the
   totals column on the right). */
.stats-col--alloc .stat-rows {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.stats-col--alloc .stat-row {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--r-2);
  background: rgba(255,255,255,0.025);
  border: 1px solid var(--glass-stroke);
}
.stats-col--alloc .stat-icon {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(8, 11, 30, 0.6);
  border: 1px solid var(--glass-stroke-hi);
}
.stats-col--alloc .stat-icon svg { width: 16px; height: 16px; color: var(--gold); }
.stats-col--alloc .stat-row-text { min-width: 0; }
.stats-col--alloc .stat-name {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--ink);
}
.stats-col--alloc .stat-desc {
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 11px;
  color: var(--ink-mute);
  line-height: 1.2;
}
.stats-col--alloc .stat-meter {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
  min-width: 60px;
}
.stats-col--alloc .stat-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 16px;
  color: var(--gold-hi);
}
.stats-col--alloc .stat-meter-bar {
  width: 56px;
  height: 4px;
  background: rgba(0,0,0,0.4);
  border-radius: var(--r-pill);
  border: 1px solid var(--glass-stroke);
  overflow: hidden;
}
.stats-col--alloc .stat-meter-bar-fill {
  height: 100%;
  width: var(--meter, 0%);
  background: linear-gradient(90deg, var(--teal), var(--gold));
  box-shadow: 0 0 6px var(--teal-glow);
}
.stats-col--alloc .stat-row { grid-template-columns: 32px minmax(0, 1fr) auto auto; }
.stats-col--alloc .stat-row-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}
.stats-col--alloc .stat-add,
.stats-col--alloc .stat-sub {
  width: 32px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: var(--r-2);
  font-family: var(--font-banner);
  font-size: 12px;
  letter-spacing: 0.08em;
  cursor: pointer;
  transition: transform 100ms ease, box-shadow 120ms ease, color 120ms ease;
}
.stats-col--alloc .stat-add {
  background: linear-gradient(180deg, rgba(255,197,100,0.18), rgba(255,197,100,0.06));
  border: 1px solid rgba(255,197,100,0.55);
  color: var(--gold-hi);
}
.stats-col--alloc .stat-add:hover {
  transform: translateY(-1px);
  box-shadow: 0 0 14px var(--gold-glow);
}
.stats-col--alloc .stat-sub {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--glass-stroke);
  color: var(--ink-mute);
}
.stats-col--alloc .stat-sub:hover {
  color: var(--ink);
  border-color: rgba(255,255,255,0.30);
}
.stats-col--alloc .stat-add[hidden],
.stats-col--alloc .stat-sub[hidden] { display: none !important; }
.stats-col--alloc .stat-value {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}
.stats-col--alloc .stat-value-num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 16px;
  color: var(--gold-hi);
}
.stats-col--alloc .stat-value-delta,
.stats-totals-delta {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  color: var(--teal-hi);
  margin-left: 2px;
}
.stats-col--alloc .stat-row.has-pending { border-color: rgba(127, 213, 203, 0.55); }
.stats-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--glass-stroke);
}
.stats-foot[hidden] { display: none !important; }

/* Centre column — character portrait. Larger than the inventory's
   paperdoll preview; the focal point of the status window. */
.stats-col--portrait {
  align-items: center;
  text-align: center;
}
.stats-portrait-wrap {
  width: 100%;
  max-width: 260px;
  aspect-ratio: 4 / 5;
  display: grid;
  place-items: center;
  border-radius: var(--r-3);
  background:
    radial-gradient(circle at 50% 30%, rgba(255,255,255,0.06), transparent 60%),
    rgba(8, 11, 30, 0.55);
  border: 1px solid var(--glass-stroke);
  overflow: hidden;
}
.stats-portrait-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.45));
}
.stats-portrait-name {
  font-family: var(--font-display);
  font-size: 20px;
  color: var(--ink);
  margin: 8px 0 0;
}
.stats-portrait-meta {
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-hi);
  margin: 0;
}
.stats-col--portrait .job-change-cta {
  margin-top: var(--sp-3);
  width: 100%;
}

/* Right column — derived totals as a label/value list. */
.stats-totals {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.stats-totals-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 10px;
  border-radius: var(--r-2);
  background: rgba(255,255,255,0.025);
  border: 1px solid var(--glass-stroke);
}
.stats-totals-label {
  font-family: var(--font-banner);
  font-size: 10.5px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.stats-totals-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 16px;
  color: var(--gold-hi);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.15;
}
/* (Base N + Items N) breakdown line sitting under ATK / DEF totals.
   Smaller, muted, mono so the digits line up at a glance. */
.stats-totals-breakdown {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 10.5px;
  letter-spacing: 0.02em;
  color: var(--ink-mute);
  opacity: 0.9;
  margin-top: 1px;
}

/* Skills window (when shown solo) — when the skill panel lives on its
   own page, drop the page-wrapper grid so the panel fills the column. */
.skills-page { display: block; margin: 0; }
.character-skill-panel--solo { padding: var(--sp-4); }

/* Overlay-inside tweaks: drop padding etc. when shown inside the panel. */
.overlay-window-body > .stats-page,
.overlay-window-body > .skills-page { padding: 0; margin: 0; }
.overlay-window-body .stats-layout { gap: var(--sp-3); }
.overlay-window-body .stats-portrait-wrap { max-width: 220px; }

/* ============================================================
   Character page — portrait + stats grid above the skill tree
   ============================================================ */
.character-page {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.character-layout {
  display: grid;
  grid-template-columns: 380px minmax(0, 1fr);
  gap: var(--sp-4);
  align-items: start;
}
@media (max-width: 1000px) {
  .character-layout { grid-template-columns: minmax(0, 1fr); }
}
.character-left-col {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  min-width: 0;
}
.character-portrait-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: var(--sp-4);
}
.character-portrait-wrap {
  width: 100%;
  aspect-ratio: 1 / 1;
  max-width: 220px;
  display: grid;
  place-items: center;
  border-radius: var(--r-3);
  background:
    radial-gradient(circle at 50% 35%, rgba(255,255,255,0.05), transparent 60%),
    rgba(8, 11, 30, 0.6);
  border: 1px solid var(--glass-stroke);
  overflow: hidden;
}
.character-portrait-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 6px 12px rgba(0,0,0,0.45));
}
.character-portrait-name {
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--ink);
  margin: 6px 0 0;
}
.character-portrait-meta {
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-hi);
  margin: 0;
}

/* Stats panel reuses the existing .stats-allocator block. */
.character-stats-panel { padding: var(--sp-4); }

/* Skill tree panel */
.character-skill-panel { padding: var(--sp-3) var(--sp-4); min-width: 0; }
.skill-sections { display: flex; flex-direction: column; gap: 4px; }
.character-skill-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--sp-3);
  margin-bottom: var(--sp-3);
}
.character-skill-head-left {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.character-skill-title {
  font-family: var(--font-display);
  font-size: 22px;
  margin: 0;
  color: var(--ink);
}
.character-skill-flavor {
  margin: 0;
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 14px;
  color: var(--ink-mute);
}

/* Branch-style skill tree — class trunk forks at the top into one
   vertical branch per column. Each branch carries its own continuous
   trunk line; nodes stack on the trunk with small inline gate pips
   between tiers. Skills are circular icon plates with hover tooltips. */
.skill-tree-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
}

/* Points-available banner — top-right of the skill panel header. */
.skill-tree-points {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 6px 14px;
  flex: 0 0 auto;
  border-radius: var(--r-pill);
  background:
    linear-gradient(180deg, rgba(255, 197, 100, 0.16) 0%, rgba(255, 197, 100, 0.04) 100%),
    rgba(8, 11, 30, 0.78);
  border: 1px solid rgba(255, 197, 100, 0.5);
  box-shadow: 0 0 16px var(--gold-glow);
}
.skill-tree-points-label {
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold);
}
.skill-tree-points-amount {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 22px;
  color: var(--gold-hi);
  line-height: 1;
}
.skill-tree-points-total {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  color: var(--ink-mute);
}

/* Horizontal skill tree. Two variants:
   - .skill-tree--flat: a single row of nodes (Adventurer basic, no
     dependencies between skills).
   - .skill-tree--cols:  a column of "branch" rows; each row reads
     left → right (tier 1 → tier 2 → tier 3) with a gate connector
     between tiers. */
.skill-tree {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  width: 100%;
}
.skill-tree--flat {
  flex-direction: row;
  justify-content: space-between;
  align-items: flex-start;
  gap: 6px;
  flex-wrap: nowrap;
}

/* One branch — a horizontal row, optionally labelled on the left. */
.skill-branch {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
}
.skill-branch-label {
  flex: 0 0 70px;
  font-family: var(--font-banner);
  font-size: 9.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  text-align: right;
  padding-right: 4px;
  border-right: 1px solid var(--glass-stroke);
}
.skill-branch-line {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 0;
  min-width: 0;
}

/* Each skill cell holds one icon node — sits between gate connectors. */
.skill-cell {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 0 0 auto;
  z-index: 1;
}

/* Horizontal gate connector — line — pip — line — sits between two
   sibling tier nodes inside a branch. Never overlaps any other element
   because it lives between two cells. */
.skill-gate {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0 4px;
  flex: 1 1 0;
  min-width: 36px;
  font-family: var(--font-banner);
  font-size: 8.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  z-index: 0;
}
.skill-gate-line {
  flex: 1 1 auto;
  height: 2px;
  background: linear-gradient(90deg, var(--gold) 0%, rgba(255,197,100,0.35) 100%);
  border-radius: 2px;
  box-shadow: 0 0 6px rgba(255,197,100,0.25);
}
.skill-gate.is-unmet .skill-gate-line {
  background: linear-gradient(90deg, rgba(255,117,145,0.55) 0%, rgba(255,117,145,0.22) 100%);
  box-shadow: none;
}
.skill-gate-pip {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(0,0,0,0.4);
  border: 1px solid currentColor;
  flex: 0 0 auto;
}
.skill-gate-pip svg { width: 9px; height: 9px; }
.skill-gate.is-met { color: var(--sage); }
.skill-gate.is-unmet { color: var(--r-cursed-c); }
.skill-gate-text { white-space: nowrap; }

/* Skill node — circular icon plate + name + rank pips beneath. The
   icon, name, and pips are all centred so the branch trunk line runs
   through the middle of each. The node sits over the trunk; everything
   beneath the icon (name, pips) inherits the centred layout. */
.skill-node {
  position: relative;
  z-index: 1;
  background: transparent;
  border: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  /* Mask out the trunk where the node sits so the line doesn't show
     through the icon plate. */
}
.skill-node:disabled { cursor: default; }
.skill-node-form { margin: 0; padding: 0; }
.skill-node.is-spendable .skill-node-icon {
  cursor: pointer;
  animation: skill-spendable-pulse 1.8s ease-in-out infinite;
}
@keyframes skill-spendable-pulse {
  0%, 100% { box-shadow: inset 0 -6px 12px rgba(0,0,0,0.45), inset 0 4px 8px rgba(255,197,100,0.10), 0 0 12px var(--gold-glow); }
  50%      { box-shadow: inset 0 -6px 12px rgba(0,0,0,0.45), inset 0 4px 8px rgba(255,197,100,0.18), 0 0 22px var(--gold-glow); }
}

.skill-node-icon {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background:
    radial-gradient(circle at 50% 35%, rgba(255,197,100,0.18) 0%, transparent 60%),
    linear-gradient(180deg, rgba(13, 17, 48, 0.85), rgba(8, 11, 30, 0.95));
  border: 2px solid var(--glass-stroke-hi);
  box-shadow:
    inset 0 -6px 12px rgba(0,0,0,0.45),
    inset 0 4px 8px rgba(255,255,255,0.05),
    0 6px 14px -6px rgba(0,0,0,0.6);
  transition: border-color .15s, transform .12s, box-shadow .15s;
}
.skill-node-icon svg {
  width: 24px;
  height: 24px;
  color: var(--ink);
  filter: drop-shadow(0 0 6px rgba(255,197,100,0.4)) drop-shadow(0 2px 3px rgba(0,0,0,0.5));
}

.skill-node.is-available .skill-node-icon {
  border-color: var(--gold);
  box-shadow:
    inset 0 -6px 12px rgba(0,0,0,0.45),
    inset 0 4px 8px rgba(255,197,100,0.10),
    0 0 18px var(--gold-glow),
    0 6px 14px -6px rgba(0,0,0,0.6);
}
.skill-node.is-available .skill-node-icon svg { color: var(--gold-hi); }

.skill-node.is-mastered .skill-node-icon {
  border-color: var(--teal-hi);
  background:
    radial-gradient(circle at 50% 35%, rgba(127,213,203,0.28) 0%, transparent 60%),
    linear-gradient(180deg, rgba(13, 17, 48, 0.85), rgba(8, 11, 30, 0.95));
  box-shadow:
    inset 0 -6px 12px rgba(0,0,0,0.45),
    inset 0 4px 8px rgba(127,213,203,0.10),
    0 0 22px rgba(127,213,203,0.55);
}
.skill-node.is-mastered .skill-node-icon svg { color: var(--teal-hi); }

.skill-node.is-locked {
  cursor: default;
  filter: grayscale(0.7);
}
.skill-node.is-locked .skill-node-icon {
  opacity: 0.55;
}

.skill-node:hover:not(.is-locked) .skill-node-icon {
  transform: translateY(-2px) scale(1.04);
}

.skill-node-name {
  font-family: var(--font-display);
  font-size: 11.5px;
  color: var(--ink);
  letter-spacing: 0.01em;
  text-align: center;
  line-height: 1.1;
  max-width: 84px;
}
.skill-node.is-available .skill-node-name { color: var(--gold-hi); }
.skill-node.is-mastered  .skill-node-name { color: var(--teal-hi); }

/* Rank pips beneath the icon — 5 small circles. */
.skill-pips {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.skill-pip {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-stroke-hi);
}
.skill-pip.is-filled {
  background: var(--gold);
  border-color: var(--gold);
  box-shadow: 0 0 4px var(--gold-glow);
}
.skill-node.is-mastered .skill-pip.is-filled {
  background: var(--teal-hi);
  border-color: var(--teal-hi);
  box-shadow: 0 0 4px rgba(127,213,203,0.6);
}

/* Active vs passive — a small notch on the icon plate. */
.skill-node--active  .skill-node-icon { border-top-color: var(--teal-hi); }
.skill-node--passive .skill-node-icon { border-top-color: var(--gold); }

/* Tooltip — shown on :hover / :focus of the node. */
.skill-tooltip {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 12px);
  transform: translateX(-50%) translateY(4px);
  width: 240px;
  z-index: 30;
  padding: 10px 12px;
  background: rgba(8, 11, 30, 0.96);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: var(--r-2);
  box-shadow: 0 18px 38px -10px rgba(0,0,0,0.7);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s, transform .15s;
  text-align: left;
}
.skill-node:hover .skill-tooltip,
.skill-node:focus-visible .skill-tooltip {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.skill-tooltip-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px;
  margin-bottom: 4px;
}
.skill-tooltip-name {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--gold-hi);
}
.skill-tooltip-kind {
  font-family: var(--font-banner);
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.skill-tooltip-effect {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--teal-hi);
}
.skill-tooltip-mute {
  font-family: var(--font-banner);
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-left: 4px;
}
.skill-tooltip-desc {
  margin: 6px 0 0;
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 12.5px;
  color: var(--ink-soft);
}
.skill-tooltip-rank {
  margin: 6px 0 0;
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-hi);
}
.skill-tooltip-gate {
  margin: 4px 0 0;
  font-family: var(--font-banner);
  font-size: 9.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

/* --- Job sections ----------------------------------------------------
   Three sections stack on the character page: Basic (Adventurer),
   First Job, Second Job. Each section has its own origin Y-fork +
   branch tree. Locked sections fade everything inside and overlay a
   lock badge with the unlock requirement. */
.skill-section {
  position: relative;
  margin-top: var(--sp-3);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--glass-stroke);
}
.skill-section-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: var(--sp-2);
}
.skill-section-sub {
  font-family: var(--font-banner);
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.skill-section-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--ink);
  letter-spacing: 0.01em;
  line-height: 1.1;
}
.skill-section.is-locked .skill-section-title { color: var(--ink-mute); }
.skill-section-body {
  position: relative;
}
.skill-section.is-locked .skill-section-body {
  filter: grayscale(0.85);
  opacity: 0.6;
  pointer-events: none;
}
.skill-section-lock {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  pointer-events: none;
}
.skill-section-lock-icon {
  width: 36px;
  height: 36px;
  color: var(--r-cursed-c);
  filter: drop-shadow(0 0 12px rgba(255, 117, 145, 0.4));
}
.skill-section-lock-text {
  margin: 0;
  padding: 6px 14px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.92);
  border: 1px solid var(--r-cursed-c);
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #ffd6df;
}
.skill-section-locked {
  text-align: center;
  font-family: var(--font-quill);
  font-style: italic;
  color: var(--ink-mute);
  margin: var(--sp-3) 0;
}

/* --- Pending allocation state ---------------------------------------- */
.skill-pip.is-pending {
  background: transparent;
  border: 2px solid var(--gold-hi);
  box-shadow: 0 0 6px var(--gold-glow);
  animation: skill-pip-pulse 1.6s ease-in-out infinite;
}
@keyframes skill-pip-pulse {
  0%, 100% { box-shadow: 0 0 4px var(--gold-glow); }
  50%      { box-shadow: 0 0 10px var(--gold-hi); }
}
.skill-node.has-pending {
  outline: 2px dashed rgba(255, 213, 130, 0.55);
  outline-offset: 3px;
  border-radius: 50%;
}
.skill-node.has-pending .skill-node-name { color: var(--gold-hi); }

/* --- Skill footer (Reset / pending / Save) --------------------------- */
.skill-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--glass-stroke);
}
.skill-foot-left {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 28px;
}
.skill-pending-summary {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 12px;
  border-radius: var(--r-pill);
  background: rgba(255, 197, 100, 0.10);
  border: 1px solid rgba(255, 197, 100, 0.40);
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
}
.skill-pending-summary .t-num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  letter-spacing: 0;
  color: var(--gold-hi);
}
.skill-pending-label { opacity: 0.85; }
.skill-reset {
  background: transparent;
  border: 1px solid var(--glass-stroke);
  color: var(--ink-mute);
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 6px 12px;
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease;
}
.skill-reset:hover { color: var(--ink); border-color: rgba(255,255,255,0.30); }
.skill-save:disabled {
  opacity: 0.40;
  cursor: not-allowed;
  filter: grayscale(0.4);
}
.skill-save:not(:disabled) {
  box-shadow: 0 0 14px var(--gold-glow);
}

/* Job-change CTA — appears when the player can promote into a new job. */
.job-change-cta {
  margin-bottom: var(--sp-4);
  padding: var(--sp-3);
  border-radius: var(--r-2);
  background: linear-gradient(180deg, rgba(255,197,100,0.10) 0%, rgba(255,197,100,0.02) 100%);
  border: 1px solid rgba(255,197,100,0.45);
  text-align: center;
}
.job-change-cta-text {
  margin: 0 0 8px;
  font-family: var(--font-quill);
  font-style: italic;
  color: var(--ink);
}
.job-change-options { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }

/* The icon plate is its own stacking context so glow / hover lifts
   don't bleed into neighbours along the branch row. */
.skill-node-icon { position: relative; isolation: isolate; }

/* Helper hint replacing the old stats block inside the inventory's
   character panel. */
.character-panel-hint {
  margin: 0;
  padding: var(--sp-4) var(--sp-3);
  font-family: var(--font-quill);
  font-style: italic;
  text-align: center;
  color: var(--ink-mute);
}

/* Inventory stack-count badge — bottom-left of a cell. */
.inv-cell-stack {
  position: absolute;
  left: 4px;
  bottom: 4px;
  z-index: 2;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  background: rgba(13, 17, 48, 0.85);
  border: 1px solid var(--glass-stroke-hi);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 10px;
  color: var(--ink);
  pointer-events: none;
}

/* ============================================================
   Map screen — visual map paradigm. Each "map" is a backdrop
   image (town-banner or one of the bg-greenwood-* biomes) with
   absolutely-positioned hotspots: buildings (Quests, Shop) on
   the town map, and portals leading out to expedition maps.
   ============================================================ */
/* Immersive map — fills the full viewport behind the shell. Backdrop
   spans edge-to-edge, hotspots are positioned absolutely over it, and
   eyebrow / helper text float at the top-left and bottom respectively. */
.map-page {
  position: relative;
  width: 100%;
  min-height: calc(100vh - var(--topbar-h));
  margin: 0;
  padding: 0;
  display: block;
}
.map-eyebrow {
  position: absolute;
  top: calc(var(--shell-h) + var(--sp-2));
  left: var(--sp-5);
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  text-align: left;
  text-shadow: 0 1px 4px rgba(0,0,0,0.7), 0 0 12px rgba(0,0,0,0.5);
  pointer-events: none;
  padding: var(--sp-2) var(--sp-5);
  isolation: isolate;
}
/* Soft radial backdrop behind the title — extends well past the text
   bounds, fades to transparent fully inside the box, and gets a heavy
   blur so the rendered shape reads as a soft halo, not a rectangle.
   Keeps the realm/zone copy legible on any map backdrop. */
.map-eyebrow::before {
  content: "";
  position: absolute;
  inset: -24px -60px -24px -40px;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(ellipse 60% 70% at 25% 50%,
      rgba(8, 11, 30, 0.70) 0%,
      rgba(8, 11, 30, 0.45) 30%,
      rgba(8, 11, 30, 0.20) 60%,
      transparent 90%);
  filter: blur(14px);
}
.map-eyebrow-realm {
  margin: 0;
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.map-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 28px;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.map-flavor {
  margin: 0;
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 15px;
  color: var(--ink-soft);
  max-width: 60ch;
}
.map-helper {
  position: absolute;
  bottom: var(--sp-4);
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  margin: 0;
  text-align: center;
  font-family: var(--font-quill);
  font-style: italic;
  color: var(--ink-soft);
  font-size: 13.5px;
  padding: 5px 14px;
  background: rgba(8, 11, 30, 0.6);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-pill);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  pointer-events: none;
}

/* The map canvas — fills the entire viewport behind the shell. No
   border, no rounded corners; the backdrop image spans edge-to-edge. */
.map-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: none;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  overflow: visible;
  z-index: 0;
}
.map-backdrop {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  z-index: 0;
}
/* Subtle dark vignette so hotspots read against bright art. */
.map-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  border-radius: inherit;
  background:
    radial-gradient(ellipse at 50% 55%, transparent 35%, rgba(8, 11, 30, 0.55) 100%),
    linear-gradient(180deg, rgba(8, 11, 30, 0.18) 0%, transparent 30%, rgba(8, 11, 30, 0.35) 100%);
}

/* Town buildings — a circular plate with a sprite/icon and a label
   beneath. Hovers raise the plate and lift the gold ring. */
.map-building {
  position: absolute;
  transform: translate(-50%, -50%);
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-decoration: none;
  color: var(--ink);
  cursor: pointer;
  transition: transform .15s;
}
.map-building:hover { transform: translate(-50%, -52%); }
.map-building-icon {
  width: 76px;
  height: 76px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background:
    radial-gradient(circle at 50% 35%, rgba(255, 197, 100, 0.18), transparent 60%),
    linear-gradient(180deg, rgba(255,255,255,0.06), rgba(13, 17, 48, 0.85));
  border: 2px solid var(--glass-stroke-hi);
  box-shadow:
    inset 0 -8px 14px rgba(0,0,0,0.45),
    inset 0 4px 10px rgba(255,255,255,0.06),
    0 0 18px rgba(0,0,0,0.35),
    0 6px 14px -6px rgba(0,0,0,0.6);
  overflow: hidden;
  transition: border-color .15s, box-shadow .15s;
}
.map-building:hover .map-building-icon {
  border-color: var(--gold);
  box-shadow:
    inset 0 -8px 14px rgba(0,0,0,0.45),
    inset 0 4px 10px rgba(255,255,255,0.06),
    0 0 22px var(--gold-glow),
    0 8px 18px -6px rgba(0,0,0,0.65);
}
.map-building-icon svg { width: 36px; height: 36px; color: var(--ink); }
.map-building-icon img { width: 100%; height: 100%; object-fit: cover; }
.map-building-label {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.78);
  border: 1px solid var(--glass-stroke);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  white-space: nowrap;
}
.map-building-name {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--ink);
  line-height: 1;
}
.map-building-meta {
  font-family: var(--font-banner);
  font-size: 9.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-top: 3px;
}

/* Quest board badge state — tint the ring/label based on urgency. */
.map-building--quests.is-ready  .map-building-icon { border-color: var(--gold); box-shadow: 0 0 22px var(--gold-glow), inset 0 -8px 14px rgba(0,0,0,0.45); }
.map-building--quests.is-ready  .map-building-meta { color: var(--gold-hi); }
.map-building--quests.is-active .map-building-icon { border-color: var(--teal-hi); }
.map-building--quests.is-active .map-building-meta { color: var(--teal-hi); }
.map-building--quests.is-new    .map-building-icon { border-color: var(--sage); }
.map-building--quests.is-new    .map-building-meta { color: var(--sage); }

/* Portals — pure-CSS magical effect. No image, just stacked animated
   gradient layers:
     - .map-portal-glow:   soft outer halo, breathes
     - .map-portal-aura:   outer light ring, rotates clockwise
     - .map-portal-vortex: swirling interior, rotates counter-clockwise
     - .map-portal-core:   bright central pulse
     - .map-portal-spark:  motes drifting upward off the vortex
   Recommended-band portals shift the teal/violet palette to gold. */
.map-portal {
  position: absolute;
  transform: translate(-50%, -50%);
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  color: var(--ink);
  cursor: pointer;
  /* Outbound portals (town → expedition) use a fixed blue palette. */
  --portal-c1: rgba(94, 170, 255, 0.95);     /* primary: bright blue */
  --portal-c2: rgba(140, 200, 255, 0.80);    /* secondary: pale blue */
  --portal-c3: rgba(94, 170, 255, 0.35);     /* soft halo tint */
  --portal-core: rgba(220, 240, 255, 1);     /* near-white core */
}
/* Return-to-town portal uses a yellow/gold palette so it reads as
   "go back" at a glance, distinct from the blue outbound portals. */
.map-portal--return {
  --portal-c1: rgba(255, 197, 100, 0.95);
  --portal-c2: rgba(255, 220, 150, 0.80);
  --portal-c3: rgba(255, 197, 100, 0.35);
  --portal-core: rgba(255, 248, 220, 1);
}
/* Sub-dungeon portal (e.g. shrine entrance on Deep Woods) — violet
   palette so it reads as "deeper, darker" vs the blue field portals. */
.map-portal--dungeon {
  --portal-c1: rgba(184, 155, 255, 0.95);
  --portal-c2: rgba(217, 196, 255, 0.80);
  --portal-c3: rgba(150, 110, 220, 0.35);
  --portal-core: rgba(230, 215, 255, 1);
}
/* Locked / coming-soon portal — desaturated, no swirl animation. Used on
   city gates that don't yet lead anywhere so the player can SEE the
   future expansion point without walking through it. */
.map-portal--locked {
  --portal-c1: rgba(160, 170, 190, 0.55);
  --portal-c2: rgba(190, 195, 205, 0.45);
  --portal-c3: rgba(120, 130, 150, 0.20);
  --portal-core: rgba(190, 195, 205, 0.85);
  cursor: not-allowed;
  filter: grayscale(0.75) brightness(0.85);
  opacity: 0.7;
}
.map-portal--locked:hover .map-portal-arena { transform: none; }
/* City buildings — same shape as town buildings, but greyed when no NPC
   route is wired yet. */
.map-building--city.is-disabled {
  cursor: not-allowed;
  opacity: 0.6;
  filter: grayscale(0.5);
}
.map-building--city.is-disabled:hover { transform: none; }

/* Stacking arena — relative box that holds every layer. */
.map-portal-arena {
  position: relative;
  width: 110px;
  height: 110px;
  display: block;
  transition: transform .2s;
}
.map-portal:hover .map-portal-arena { transform: scale(1.06); }

/* Outer soft halo behind the portal. Scale + opacity breathe in a 3s cycle. */
.map-portal-glow {
  position: absolute;
  inset: -14%;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 50%, var(--portal-c1) 0%, var(--portal-c3) 32%, transparent 65%);
  filter: blur(8px);
  z-index: 0;
  animation: portal-breathe 3s ease-in-out infinite;
}

/* Outer rotating light ring — conic gradient masked to an annulus so
   only the rim is visible. */
.map-portal-aura {
  position: absolute;
  inset: 2%;
  border-radius: 50%;
  background: conic-gradient(
    from 0deg,
    transparent 0deg,
    var(--portal-c1) 60deg,
    transparent 120deg,
    var(--portal-c2) 200deg,
    transparent 260deg,
    var(--portal-c1) 320deg,
    transparent 360deg
  );
  -webkit-mask: radial-gradient(circle at 50% 50%, transparent 44%, black 50%, black 58%, transparent 64%);
          mask: radial-gradient(circle at 50% 50%, transparent 44%, black 50%, black 58%, transparent 64%);
  z-index: 1;
  animation: portal-spin 12s linear infinite;
  filter: blur(0.5px) drop-shadow(0 0 6px var(--portal-c2));
}

/* The swirling interior. A conic gradient with several teal/violet stops
   gives the swirl, then a radial-gradient mask fades it from solid at
   the centre to transparent at the rim. Counter-rotates relative to
   the outer aura for a real "spinning vortex" feel. */
.map-portal-vortex {
  position: absolute;
  inset: 12%;
  border-radius: 50%;
  background:
    conic-gradient(
      from 90deg,
      var(--portal-c1) 0deg,
      var(--portal-c2) 70deg,
      var(--portal-c1) 140deg,
      var(--portal-c2) 210deg,
      var(--portal-c1) 280deg,
      var(--portal-c2) 350deg,
      var(--portal-c1) 360deg
    );
  -webkit-mask: radial-gradient(circle at 50% 50%, black 30%, black 50%, transparent 90%);
          mask: radial-gradient(circle at 50% 50%, black 30%, black 50%, transparent 90%);
  z-index: 2;
  animation: portal-spin-rev 8s linear infinite;
  filter: blur(2px) saturate(1.2);
  opacity: 0.95;
}

/* Bright central pulse — a small near-white core that brightens and dims. */
.map-portal-core {
  position: absolute;
  inset: 32%;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 50%, var(--portal-core) 0%, var(--portal-c1) 30%, transparent 70%);
  filter: blur(3px);
  z-index: 3;
  animation: portal-core-pulse 1.8s ease-in-out infinite;
  mix-blend-mode: screen;
}

/* SVG fallback if a portal layer fails to render — keeps the link visible. */
.map-portal-sigil {
  position: relative;
  z-index: 2;
  width: 60px;
  height: 60px;
  color: var(--teal-hi);
}
.map-portal.is-recommended .map-portal-sigil { color: var(--gold-hi); }

/* Sparks — small motes that float upward off the vortex and fade out.
   Each spark gets its own delay + horizontal offset so they don't
   march in lock-step. */
.map-portal-spark {
  position: absolute;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--portal-core);
  box-shadow: 0 0 6px var(--portal-c1), 0 0 12px var(--portal-c2);
  z-index: 4;
  opacity: 0;
  pointer-events: none;
  animation: portal-spark 3.4s ease-in-out infinite;
}
.map-portal-spark--1 { left: 30%; top: 50%; animation-delay: 0.0s; }
.map-portal-spark--2 { left: 56%; top: 56%; animation-delay: 0.8s; }
.map-portal-spark--3 { left: 44%; top: 44%; animation-delay: 1.6s; }
.map-portal-spark--4 { left: 64%; top: 48%; animation-delay: 2.2s; }
.map-portal-spark--5 { left: 38%; top: 60%; animation-delay: 2.8s; }

/* Label overlay on top of the portal — no background pill; text is
   readable against the swirling magic via a thick text-stroke (paint-order)
   and a tight drop-shadow halo. */
.map-portal-label {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  white-space: nowrap;
  pointer-events: none;
  text-align: center;
}
.map-portal-name {
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--ink);
  line-height: 1;
  -webkit-text-stroke: 3px rgba(8, 11, 30, 0.92);
  paint-order: stroke fill;
  text-shadow:
    0 0 6px rgba(8, 11, 30, 0.9),
    0 1px 2px rgba(0, 0, 0, 0.8);
  letter-spacing: 0.01em;
}
.map-portal-meta {
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  margin-top: 3px;
  color: var(--ink);
  -webkit-text-stroke: 2.5px rgba(8, 11, 30, 0.92);
  paint-order: stroke fill;
  text-shadow:
    0 0 5px rgba(8, 11, 30, 0.9),
    0 1px 2px rgba(0, 0, 0, 0.8);
}
/* Level-band colour variants on the outbound portal meta chip:
   green = below player level (easy), orange = current band, red = above. */
.map-portal-meta--easy    { color: #6be07a; }
.map-portal-meta--current { color: #ffb74a; }
.map-portal-meta--hard    { color: #ff6b6b; }
/* Icon variant on the return portal — meta becomes a small house glyph. */
.map-portal-meta--icon {
  margin-top: 4px;
  -webkit-text-stroke: 0;
  text-shadow: none;
  filter:
    drop-shadow(0 0 5px rgba(8, 11, 30, 0.9))
    drop-shadow(0 1px 2px rgba(0, 0, 0, 0.8));
}
/* Terrain icon below the portal name — tree for field portals, stone
   arch for dungeon portals. Sits between the name and the level chip. */
.map-portal-terrain {
  display: inline-block;
  margin-top: 4px;
  -webkit-text-stroke: 0;
  filter:
    drop-shadow(0 0 5px rgba(8, 11, 30, 0.9))
    drop-shadow(0 1px 2px rgba(0, 0, 0, 0.8));
}
.map-portal-terrain svg {
  width: 16px;
  height: 16px;
  color: var(--gold-hi);
  vertical-align: middle;
}
.map-portal--dungeon .map-portal-terrain svg { color: rgba(217, 196, 255, 1); }
.map-portal-meta--icon svg {
  width: 16px;
  height: 16px;
  color: var(--gold-hi);
  display: block;
}

@keyframes portal-breathe {
  0%, 100% { transform: scale(0.92); opacity: 0.7; }
  50%      { transform: scale(1.10); opacity: 1; }
}
@keyframes portal-spin {
  to { transform: rotate(360deg); }
}
@keyframes portal-spin-rev {
  to { transform: rotate(-360deg); }
}
@keyframes portal-core-pulse {
  0%, 100% { transform: scale(0.85); opacity: 0.75; }
  50%      { transform: scale(1.15); opacity: 1; }
}
@keyframes portal-spark {
  0%   { opacity: 0; transform: translateY(0)    scale(0.5); }
  20%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-48px) scale(1.3); }
}

@media (prefers-reduced-motion: reduce) {
  .map-portal-glow,
  .map-portal-aura,
  .map-portal-vortex,
  .map-portal-core,
  .map-portal-spark { animation: none; }
}

/* Expedition map specifics — central Embark CTA, return portal in
   the top-left corner, level-band chip in the top-right. */
.map-canvas--biome .map-overlay {
  background:
    radial-gradient(ellipse at 50% 60%, transparent 25%, rgba(8, 11, 30, 0.55) 100%),
    linear-gradient(180deg, rgba(8, 11, 30, 0.22) 0%, transparent 35%, rgba(8, 11, 30, 0.4) 100%);
}
.map-return {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 4;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.82);
  border: 1px solid var(--glass-stroke-hi);
  color: var(--ink);
  text-decoration: none;
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: background .15s, border-color .15s;
}
.map-return:hover {
  background: rgba(8, 11, 30, 0.92);
  border-color: var(--gold);
  color: var(--gold-hi);
}
.map-return svg { width: 12px; height: 12px; transform: scaleX(-1); }
.map-band {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 4;
  padding: 5px 12px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.82);
  border: 1px solid var(--glass-stroke);
  color: var(--ink-soft);
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.map-band.is-match {
  border-color: var(--gold);
  color: var(--gold-hi);
  box-shadow: 0 0 10px var(--gold-glow);
}
.map-embark {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin: 0;
}
.map-embark .btn--large {
  padding: 12px 28px;
  font-size: 14px;
  letter-spacing: 0.22em;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.map-embark .btn--large svg { width: 18px; height: 18px; }
.map-embark-cost {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.78);
  border: 1px solid var(--glass-stroke);
  font-family: var(--font-banner);
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.map-embark-cost svg { width: 12px; height: 12px; color: var(--gold-hi); }
.map-embark-cost.is-blocked { color: var(--r-cursed-c); border-color: rgba(255,117,145,0.4); }
.map-embark-cost.is-blocked svg { color: var(--r-cursed-c); }

/* ============================================================
   Battle stage — full-width combat scene on the biome backdrop.
   Stack (bottom-to-top):
     .battle-stage-bg       — biome WEBP, object-fit cover
     .battle-stage-overlay  — dark vignette so foreground reads
     .battle-search         — initial 1-30s searching state
     .battle-arena          — hero | narration | foe row
     .battle-outcome        — rewards panel, revealed after the
                              last turn animates
   ============================================================ */
.battle-stage {
  position: relative;
  width: 100%;
  margin: 0;
  border-radius: 0;
  min-height: calc(100vh - var(--topbar-h));
  isolation: isolate;
}
.battle-stage-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  z-index: 0;
}
.battle-stage-overlay {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(ellipse at 50% 65%, transparent 25%, rgba(8, 11, 30, 0.55) 90%),
    linear-gradient(180deg, rgba(8, 11, 30, 0.35) 0%, transparent 35%, rgba(8, 11, 30, 0.55) 100%);
}

/* Searching state — centred spinner + flavor */
.battle-search[hidden] { display: none; }
.battle-search {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  text-align: center;
  padding: var(--sp-5);
  transition: opacity .4s;
}
.battle-search.is-leaving { opacity: 0; }
/* Searching binoculars — scans left-right while the wood is quiet. */
.battle-search-binoculars {
  width: 68px;
  height: 68px;
  color: var(--gold-hi);
  filter:
    drop-shadow(0 0 12px var(--gold-glow))
    drop-shadow(0 2px 6px rgba(0,0,0,0.6));
  animation: battle-binos-scan 2.4s ease-in-out infinite;
  transform-origin: 50% 50%;
}
@keyframes battle-binos-scan {
  0%   { transform: rotate(-14deg) translateX(-6px) scale(0.96); }
  30%  { transform: rotate(-3deg)  translateX(-2px) scale(1);    }
  50%  { transform: rotate(0deg)   translateX(0)    scale(1.04); }
  70%  { transform: rotate(3deg)   translateX(2px)  scale(1);    }
  100% { transform: rotate(14deg)  translateX(6px)  scale(0.96); }
}
.battle-search-text {
  margin: 0;
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.battle-search-flavor {
  margin: 0;
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 14px;
  color: var(--ink-mute);
  max-width: 32ch;
}
@keyframes battle-spin { to { transform: rotate(360deg); } }

/* Arena: 1fr | 1.2fr | 1fr — narration column slightly wider. The
   `display: grid` would override the default hidden { display: none },
   so re-assert it below. */
.battle-arena[hidden] { display: none; }
.battle-arena {
  position: relative;
  z-index: 3;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 1fr);
  gap: var(--sp-4);
  padding: calc(var(--shell-h) + var(--sp-3)) var(--sp-5) var(--sp-5);
  align-items: center;
  min-height: calc(100vh - var(--topbar-h));
}
.battle-arena.is-entering { animation: battle-enter .5s ease-out; }
@keyframes battle-enter {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (max-width: 800px) {
  .battle-arena {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto auto;
  }
}

/* Hero / foe side */
.battle-side {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  transition: transform .15s;
}
.battle-side.is-hit { transform: translateX(-4px); }
.battle-side--foe.is-hit { transform: translateX(4px); }

.battle-bars {
  width: 100%;
  max-width: 220px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 12px;
  background: rgba(8, 11, 30, 0.78);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: var(--r-2);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.battle-name-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px;
}
.battle-name {
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.battle-level {
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.battle-hp {
  position: relative;
  width: 100%;
  height: 16px;
  border-radius: var(--r-pill);
  background:
    linear-gradient(180deg, rgba(0,0,0,0.45), rgba(0,0,0,0.25));
  border: 1px solid var(--glass-stroke);
  overflow: hidden;
}
.battle-hp-fill {
  position: absolute;
  inset: 0;
  width: var(--p);
  border-radius: inherit;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.18), transparent 60%),
    linear-gradient(90deg, #d04a4a 0%, #ef6b6b 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.18),
    0 0 10px rgba(208, 74, 74, 0.4);
  transition: width .45s ease-out;
}
.battle-hp-fill.is-low {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.18), transparent 60%),
    linear-gradient(90deg, #b03030 0%, #d44848 100%);
  animation: battle-hp-pulse 1s ease-in-out infinite;
}
.battle-hp-text {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  font-weight: 500;
  color: var(--ink);
  text-shadow: 0 1px 2px rgba(0,0,0,0.7);
  z-index: 1;
}
@keyframes battle-hp-pulse {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(1.25); }
}

/* Combatant figure */
.battle-figure-wrap {
  position: relative;
  width: 100%;
  max-width: 240px;
  aspect-ratio: 3 / 4;
  display: grid;
  place-items: center;
}
.battle-figure {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 6px 12px rgba(0,0,0,0.55));
  animation: battle-idle 2.8s ease-in-out infinite;
}
.battle-figure--hero { animation-delay: 0s; }
.battle-figure--foe  { animation-delay: 1.4s; transform: scaleX(-1); }
.battle-figure--foe { transform-origin: center; }
@keyframes battle-idle {
  0%, 100% { transform: translateY(0)   scaleX(var(--scale, 1)); }
  50%      { transform: translateY(-4px) scaleX(var(--scale, 1)); }
}
.battle-figure--foe { --scale: -1; }

/* Defeat overlay — grey wash + skull when a combatant dies */
.battle-death {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  z-index: 2;
  background: rgba(20, 20, 30, 0.6);
  border-radius: var(--r-3);
  backdrop-filter: grayscale(1) blur(1px);
  -webkit-backdrop-filter: grayscale(1) blur(1px);
  opacity: 0;
  pointer-events: none;
  transition: opacity .6s ease-out;
}
.battle-death.is-active { opacity: 1; }
.battle-death-icon {
  width: 56px;
  height: 56px;
  color: rgba(220, 220, 230, 0.75);
  filter: drop-shadow(0 0 12px rgba(0,0,0,0.7));
  animation: battle-death-rise .7s ease-out;
}
.battle-death-text {
  font-family: var(--font-display);
  font-size: 26px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(230, 230, 235, 0.85);
  text-shadow: 0 0 14px rgba(0,0,0,0.8), 0 2px 4px rgba(0,0,0,0.6);
  animation: battle-death-rise .7s ease-out .1s both;
}
@keyframes battle-death-rise {
  from { transform: translateY(8px) scale(0.85); opacity: 0; }
  to   { transform: translateY(0)   scale(1);    opacity: 1; }
}

/* Battle figure also greyscale when its side is defeated, so the painted
   sprite reads as a corpse rather than just being covered by the overlay. */
.battle-figure-wrap:has(.battle-death.is-active) .battle-figure {
  filter: grayscale(1) brightness(0.55) drop-shadow(0 6px 12px rgba(0,0,0,0.55));
  animation: none;
}

/* Narration column */
.battle-narration {
  display: flex;
  align-items: stretch;
  height: 100%;
}
.battle-log-panel {
  width: 100%;
  display: flex;
  flex-direction: column;
  padding: var(--sp-4);
  background: rgba(8, 11, 30, 0.86);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.battle-log-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 17px;
  color: var(--gold-hi);
  margin: 0 0 var(--sp-3);
  text-align: center;
  letter-spacing: -0.005em;
}
.battle-log {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow-y: auto;
  max-height: 360px;
  padding-right: 4px;
}
.battle-log-line[hidden] { display: none; }
.battle-log-line {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--r-2);
  background: rgba(13, 17, 48, 0.55);
  border-left: 3px solid var(--glass-stroke);
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--ink-soft);
  opacity: 0;
  transform: translateY(4px);
  transition: opacity .25s, transform .25s;
}
.battle-log-line.is-revealed {
  opacity: 1;
  transform: translateY(0);
}
.battle-log-line--hero { border-left-color: var(--teal-hi); }
.battle-log-line--foe  { border-left-color: var(--r-cursed-c); }
.battle-log-line--crit { background: rgba(255, 197, 100, 0.10); border-left-color: var(--gold); }
.battle-log-body { flex: 1; }
.battle-roll {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-style: normal;
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  letter-spacing: 0.04em;
  padding: 2px 7px;
  border-radius: var(--r-pill);
  background: rgba(0,0,0,0.45);
  border: 1px solid var(--glass-stroke);
  color: var(--ink);
  white-space: nowrap;
}

/* Outcome — now lives INSIDE the narration panel at the top, above the
   turn log. Revealed after the last turn animates. */
.battle-outcome[hidden] { display: none; }
.battle-outcome {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--glass-stroke);
  animation: battle-enter .5s ease-out;
}
.battle-outcome .outcome-banner {
  margin: 0;
  font-family: var(--font-display);
  font-size: 22px;
  text-align: center;
  letter-spacing: 0.04em;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  color: var(--gold-hi);
}
.battle-outcome .outcome-banner .laurel { width: 26px; height: 26px; color: var(--gold); }
.battle-outcome .outcome-flavor {
  margin: 0;
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 13.5px;
  color: var(--ink-soft);
  text-align: center;
  line-height: 1.4;
}
.battle-outcome-actions {
  display: flex;
  justify-content: center;
  margin-top: var(--sp-2);
}
.battle-outcome-actions .btn { padding: 8px 22px; }

@media (prefers-reduced-motion: reduce) {
  .battle-search-binoculars,
  .battle-figure,
  .battle-hp-fill.is-low,
  .battle-arena.is-entering,
  .battle-outcome { animation: none; }
}

/* ============================================================
   World map — fixed 100x100 tile grid. Reference only (non-
   interactive); the viewport is full-screen and click-dragged
   to pan around. Empty tiles render as flat boxes so the grid
   reads as a board even where nothing has been placed yet.
   ============================================================ */
:root {
  --world-tile-size: 96px;
  --world-gap: 4px;
}
.world-page {
  position: relative;
  width: 100%;
  height: calc(100vh - var(--topbar-h));
  margin: 0;
  padding: 0;
  overflow: hidden;
}

/* Full-screen viewport that windows onto the huge grid. */
.world-viewport {
  position: absolute;
  inset: 0;
  overflow: auto;
  background:
    radial-gradient(900px 600px at 50% 50%, rgba(106, 78, 198, 0.10) 0%, transparent 60%),
    var(--space-1);
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  -webkit-overflow-scrolling: touch;
}
.world-viewport.is-dragging { cursor: grabbing; }
.world-viewport::-webkit-scrollbar { width: 10px; height: 10px; }
.world-viewport::-webkit-scrollbar-track { background: rgba(0,0,0,0.3); }
.world-viewport::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,0.12);
  border-radius: 5px;
}

.world-grid {
  display: grid;
  gap: var(--world-gap);
  padding: var(--world-gap);
}

/* Empty cell — flat dark box, no interaction. 9996 of these render. */
.world-tile-empty {
  display: block;
  width: var(--world-tile-size);
  height: var(--world-tile-size);
  background: rgba(20, 25, 60, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.03);
  border-radius: 4px;
}

/* Populated tile — shows the location's top-down art + label.
   No anchor / no hover / no cursor change: reference only. */
.world-tile {
  position: relative;
  display: block;
  border-radius: var(--r-2);
  overflow: hidden;
  background: rgba(13, 17, 48, 0.55);
  border: 1px solid var(--glass-stroke-hi);
  color: var(--ink);
  width: var(--world-tile-size);
  height: var(--world-tile-size);
  text-decoration: none;
}
.world-tile.is-here {
  border-color: var(--teal-hi);
  box-shadow: 0 0 16px rgba(127, 213, 203, 0.45), inset 0 0 0 1px var(--teal-hi);
}

/* ============================================================
   Quest log — the menu-icon screen. Laid out like the inventory /
   character pages: standard padded content inside .viewport-inner
   (no fullscreen absolute stage), with the parchment-board art
   sitting behind the cards as a soft backdrop layer.
   ============================================================ */
.quest-log-page {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  min-height: calc(100vh - var(--topbar-h) - var(--shell-h) - var(--sp-7));
}
.quest-log-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.22;
  filter: blur(1px) saturate(0.85);
  pointer-events: none;
  z-index: 0;
  border-radius: var(--r-3);
  mask-image: radial-gradient(ellipse at 50% 40%, #000 50%, transparent 95%);
  -webkit-mask-image: radial-gradient(ellipse at 50% 40%, #000 50%, transparent 95%);
}
.quest-log-head {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.quest-log-head .character-skill-title { font-size: 26px; }
.quest-log-head .map-eyebrow-realm svg {
  width: 12px;
  height: 12px;
  margin-right: 6px;
  vertical-align: middle;
  color: var(--gold);
}
.quest-log-body {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}

/* ============================================================
   Quest board — immersive scene. Backdrop = painted notice board,
   quest cards stack inside a scrollable centred column over the
   top, framed by a glass panel so the cards stay legible against
   the painted scene.
   ============================================================ */
.quest-stage {
  position: relative;
  width: 100%;
  min-height: calc(100vh - var(--topbar-h));
  overflow: hidden;
}
.quest-stage-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.quest-stage-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(ellipse at 50% 55%, transparent 30%, rgba(8, 11, 30, 0.55) 100%),
    linear-gradient(180deg, rgba(8, 11, 30, 0.30) 0%, transparent 35%, rgba(8, 11, 30, 0.40) 100%);
}
.quest-stage-eyebrow {
  position: absolute;
  top: calc(var(--shell-h) - var(--sp-2));
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  pointer-events: none;
  text-shadow: 0 1px 4px rgba(0,0,0,0.7), 0 0 12px rgba(0,0,0,0.5);
}
.quest-stage-eyebrow .map-eyebrow-realm svg {
  width: 11px;
  height: 11px;
  margin-right: 4px;
  vertical-align: middle;
  color: var(--gold);
}
.quest-board-renewal {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 8px;
  padding: 4px 12px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.78);
  border: 1px solid rgba(255, 197, 100, 0.45);
  box-shadow: 0 0 12px var(--gold-glow);
  pointer-events: auto;
}
.quest-board-renewal-label {
  font-family: var(--font-banner);
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold);
}
.quest-board-renewal-time {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  color: var(--gold-hi);
  letter-spacing: 0.03em;
}
.quest-stage-scroll {
  position: absolute;
  top: calc(var(--shell-h) + 80px);
  bottom: var(--sp-5);
  left: 50%;
  transform: translateX(-50%);
  width: min(900px, 92vw);
  z-index: 4;
  overflow-y: auto;
  padding: var(--sp-3) var(--sp-3) var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}

/* ============================================================
   Shop — Mira's Wagon, immersive scene. Backdrop = painted wagon
   with Mira on the left. Vendor strip floats centred near the
   top; the wares grid floats over the wagon's counter on the
   right side of the viewport.
   ============================================================ */
.shop-stage {
  position: relative;
  width: 100%;
  min-height: calc(100vh - var(--topbar-h));
  overflow: hidden;
}
.shop-stage-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.shop-stage-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(ellipse at 30% 50%, transparent 25%, rgba(8, 11, 30, 0.30) 80%),
    linear-gradient(90deg, transparent 0%, transparent 35%, rgba(8, 11, 30, 0.40) 100%),
    linear-gradient(180deg, rgba(8, 11, 30, 0.25) 0%, transparent 35%, rgba(8, 11, 30, 0.40) 100%);
}

/* Mira's chibi NPC sprite — composited over the painted shop interior.
   Sits in the bottom-right corner of the scene, facing inward, with
   a soft drop shadow for lift against the backdrop. */
.shop-stage-vendor {
  position: absolute;
  right: max(2vw, var(--sp-4));
  bottom: 0;
  left: auto;
  z-index: 3;
  height: clamp(260px, 50vh, 500px);
  width: auto;
  object-fit: contain;
  filter: drop-shadow(0 12px 22px rgba(0,0,0,0.55));
  pointer-events: none;
  user-select: none;
}
@media (max-width: 900px) {
  .shop-stage-vendor { display: none; }
}

/* Return-to-town button — top-left corner of any immersive stage that
   isn't a map (quest board, shop, etc.). Same shape as the legacy
   map-return pill so it reads consistently across the game. */
.map-return-btn {
  position: absolute;
  top: calc(var(--shell-h) + var(--sp-3));
  left: var(--sp-5);
  z-index: 6;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.82);
  border: 1px solid var(--glass-stroke-hi);
  color: var(--ink);
  text-decoration: none;
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: background .15s, border-color .15s, color .15s;
}
.map-return-btn:hover {
  background: rgba(8, 11, 30, 0.92);
  border-color: var(--gold);
  color: var(--gold-hi);
}
.map-return-btn svg { width: 12px; height: 12px; transform: scaleX(-1); }

/* Portal-style return-to-town button — used on immersive stages that
   aren't maps (shop, quest board). Glows like a portal in a warm amber
   palette distinct from the blue outbound + gold field-return portals.
   Pinned to the bottom-left of the stage. */
.portal-return {
  --return-c1: rgba(255, 158, 87, 0.95);   /* primary: warm amber */
  --return-c2: rgba(255, 200, 130, 0.78);  /* secondary: pale amber */
  --return-c3: rgba(255, 158, 87, 0.30);   /* halo tint */
  position: absolute;
  bottom: var(--sp-5);
  left: var(--sp-5);
  z-index: 6;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px 10px 12px;
  border-radius: var(--r-pill);
  background:
    linear-gradient(180deg, rgba(255, 158, 87, 0.18) 0%, rgba(255, 158, 87, 0.04) 100%),
    rgba(8, 11, 30, 0.86);
  border: 1px solid var(--return-c1);
  color: var(--return-c2);
  text-decoration: none;
  font-family: var(--font-banner);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow:
    0 0 16px var(--return-c3),
    inset 0 0 12px rgba(255, 158, 87, 0.18),
    inset 0 1px 0 rgba(255,255,255,0.08);
  transition: transform .12s, color .15s, box-shadow .15s, border-color .15s;
  isolation: isolate;
}
.portal-return:hover {
  transform: translateY(-1px);
  color: #fff;
  border-color: var(--return-c2);
  box-shadow:
    0 0 26px var(--return-c1),
    inset 0 0 14px rgba(255, 158, 87, 0.30),
    inset 0 1px 0 rgba(255,255,255,0.12);
}
/* Pulsing halo behind the button — portal-style glow. */
.portal-return-glow {
  position: absolute;
  inset: -10px -16px;
  border-radius: var(--r-pill);
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 50%, var(--return-c1) 0%, var(--return-c3) 45%, transparent 75%);
  filter: blur(10px);
  opacity: 0.6;
  animation: portal-return-pulse 2.6s ease-in-out infinite;
}
@keyframes portal-return-pulse {
  0%, 100% { opacity: 0.45; transform: scale(0.96); }
  50%      { opacity: 0.85; transform: scale(1.04); }
}
/* Arrow inside its own circular plate so it reads as a portal sigil. */
.portal-return-arrow {
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 50%, rgba(255, 158, 87, 0.35) 0%, rgba(255, 158, 87, 0.05) 70%, transparent 100%),
    rgba(8, 11, 30, 0.7);
  border: 1px solid var(--return-c1);
  color: var(--return-c2);
  box-shadow: 0 0 10px rgba(255, 158, 87, 0.5);
}
.portal-return-arrow svg { width: 14px; height: 14px; }
.portal-return-label { line-height: 1; }
@media (prefers-reduced-motion: reduce) {
  .portal-return-glow { animation: none; }
}

.shop-stage-head {
  position: absolute;
  top: calc(var(--shell-h) - var(--sp-2));
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: 8px 14px;
  background: rgba(8, 11, 30, 0.72);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: var(--r-pill);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  max-width: 92vw;
  flex-wrap: wrap;
  justify-content: center;
}
.shop-vendor {
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.1;
}
.shop-vendor-name {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--ink);
}
.shop-vendor-flavor {
  font-family: var(--font-banner);
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-hi);
  margin-top: 2px;
}

/* Map-style eyebrow on the shop — centered title above the body. */
.shop-stage .map-eyebrow {
  position: absolute;
  top: calc(var(--shell-h) - var(--sp-2));
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
}

.shop-stage-body {
  position: absolute;
  top: calc(var(--shell-h) + 80px);
  bottom: 90px;            /* leave room for the bottom-left return button */
  left: 50%;
  transform: translateX(-50%);
  z-index: 4;
  width: min(960px, 78vw);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
@media (max-width: 1000px) {
  .shop-stage-body { width: calc(100vw - var(--sp-5) * 2); }
}

/* Two-column body row: wares grid on the left, checkout cart on the right. */
.shop-body-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: var(--sp-3);
  flex: 1 1 auto;
  min-height: 0;
}
.shop-grid-col {
  display: flex;
  flex-direction: column;
  gap: 0;
  min-width: 0;
}
.shop-grid-col .shop-mode-tabs {
  align-self: flex-start;
  margin-bottom: -1px;     /* overlap the panel's top border for a "shelf" effect */
}

/* Panel that holds controls + grid + pagination, sits beneath the tabs
   with matching border so the active tab visually merges in. Sized to
   its content (grid is fixed-height) so the panel itself never shifts. */
.shop-grid-panel {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-3);
  background: rgba(8, 11, 30, 0.62);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: 0 var(--r-3) var(--r-3) var(--r-3);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  flex: 0 0 auto;
}
/* Inside the panel the grid no longer needs its own panel chrome. */
.shop-grid-panel .shop-grid {
  background: none;
  border: none;
  padding: 0;
  border-radius: 0;
  backdrop-filter: none;
}
@media (max-width: 760px) {
  .shop-body-row { grid-template-columns: minmax(0, 1fr); }
  .shop-checkout { order: 2; }
}

/* ---------------- Checkout panel ---------------- */
.shop-checkout {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-3);
  background: rgba(8, 11, 30, 0.78);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: var(--r-3);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  min-width: 0;
}
.shop-checkout-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--glass-stroke);
}
.shop-checkout-icon { width: 14px; height: 14px; color: var(--gold); }
.shop-checkout-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 17px;
  color: var(--ink);
  flex: 1 1 auto;
}
.shop-checkout-count {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  padding: 1px 7px;
  border-radius: var(--r-pill);
  background: rgba(0, 0, 0, 0.35);
  color: var(--ink-mute);
}
.shop-checkout-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1 1 auto;
  overflow-y: auto;
  min-height: 0;
}
.shop-checkout-empty {
  margin: var(--sp-3) 0;
  text-align: center;
  font-family: var(--font-quill);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-mute);
}
.shop-cart-line {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: rgba(13, 17, 48, 0.55);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-2);
  font-size: 13px;
}
/* Cart thumbnail — square icon plate echoing the shop-card-icon shape. */
.shop-cart-thumb {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: var(--r-2);
  background:
    radial-gradient(circle at 50% 35%, rgba(255,255,255,0.05), transparent 60%),
    rgba(8, 11, 30, 0.55);
  border: 1px solid var(--glass-stroke);
  flex: 0 0 auto;
  overflow: hidden;
}
.shop-cart-thumb img {
  max-width: 80%;
  max-height: 80%;
  object-fit: contain;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.5));
}
.shop-cart-thumb.is-empty { opacity: 0.3; }
.shop-cart-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.shop-cart-name {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 1.15;
}
.shop-cart-line-price {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 12.5px;
  color: var(--gold-hi);
}
.shop-cart-line-price svg { width: 11px; height: 11px; color: var(--gold); }
.shop-cart-qty {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.shop-cart-qbtn {
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-stroke);
  color: var(--ink);
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
  padding: 0;
}
.shop-cart-qbtn:hover { background: rgba(255,255,255,0.14); }
.shop-cart-qval {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  min-width: 16px;
  text-align: center;
}
.shop-cart-remove {
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: transparent;
  border: 1px solid var(--glass-stroke);
  color: var(--ink-mute);
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
  padding: 0;
}
.shop-cart-remove:hover {
  border-color: var(--r-cursed-c);
  color: var(--r-cursed-c);
}

.shop-checkout-foot {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: var(--sp-2);
  border-top: 1px solid var(--glass-stroke);
}
.shop-checkout-total {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: var(--font-banner);
  font-size: 10.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.shop-checkout-total-amount {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 16px;
  color: var(--gold-hi);
  letter-spacing: 0.04em;
  text-transform: none;
}
.shop-checkout-total-amount svg { width: 13px; height: 13px; color: var(--gold); }
.shop-checkout-confirm { width: 100%; }
.shop-checkout-clear {
  background: transparent;
  border: none;
  color: var(--ink-mute);
  font-family: var(--font-banner);
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  padding: 4px 0 0;
}
.shop-checkout-clear:hover { color: var(--r-cursed-c); }

/* The wares grid — fixed 4×3 layout with FIXED row height so the panel
   is exactly the same size on every page no matter what cards land in
   it. Cards stretch to fill their cell; their content is clipped if
   it would otherwise grow past the cell. */
.shop-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-template-rows: repeat(3, 165px);
  gap: var(--sp-2);
  padding: var(--sp-3);
  background: rgba(8, 11, 30, 0.62);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: var(--r-3);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  overflow: visible;
  flex: 0 0 auto;
}
@media (max-width: 720px) {
  .shop-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-rows: repeat(4, 155px);
  }
}
@media (max-width: 480px) {
  .shop-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: repeat(6, 150px);
  }
}
/* Make each card fill its cell and clip overflowing content rather than
   pushing the cell taller. */
.shop-card {
  height: 100%;
  overflow: hidden;
}
.shop-card-name {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.shop-grid-empty {
  padding: var(--sp-6);
  background: rgba(8, 11, 30, 0.62);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: var(--r-3);
  text-align: center;
  font-family: var(--font-quill);
  font-style: italic;
  color: var(--ink-soft);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* Shop card — image, name, action row (cost + button), info pill. */
.shop-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 32px 10px 10px;     /* room at the top for the Info pill */
  background: rgba(13, 17, 48, 0.88);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: var(--r-2);
}
.shop-card-icon {
  width: 56px;
  height: 56px;
  margin: 0 auto;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 35%, rgba(255,255,255,0.06), transparent 60%),
    rgba(8, 11, 30, 0.55);
  flex: 0 0 auto;
}
.shop-card-icon img,
.shop-card-icon svg {
  display: block;
  width: 70%;
  height: 70%;
  object-fit: contain;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.4));
}
.shop-card-name {
  margin: 0;
  font-family: var(--font-display);
  font-size: 13px;
  line-height: 1.2;
  text-align: center;
  color: var(--ink);
  flex: 1 1 auto;
  /* Allow long names to wrap onto two lines without clipping the icon. */
  word-break: break-word;
}

/* Bottom row — cost label on the left, action button on the right. */
.shop-card-action {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--glass-stroke);
}
.shop-card-cost {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  color: var(--gold-hi);
}
.shop-card-cost svg { width: 12px; height: 12px; color: var(--gold); filter: drop-shadow(0 0 4px var(--gold-glow)); }
.shop-card-cost-sell { color: var(--teal-hi); }
.shop-card-cost-sell svg { color: var(--teal); filter: drop-shadow(0 0 4px var(--teal-glow, rgba(127,213,203,0.5))); }

.shop-card-btn-form { margin: 0; display: inline-block; }
.shop-card-btn {
  padding: 5px 10px;
  font-size: 10.5px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.shop-card-btn-lock { width: 10px; height: 10px; }
.shop-card-btn:disabled { opacity: 0.55; cursor: not-allowed; }

/* Shop card is fully clickable — opens the info modal on click.
   On hover, a centred eye-icon fades in over the card to signal the
   click affordance. The action button (Add) stops propagation so it
   doesn't trigger the modal. */
.shop-card { cursor: pointer; }
.shop-card:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
.shop-card-eye {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0.85);
  z-index: 3;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(8, 11, 30, 0.78);
  border: 1px solid var(--gold);
  color: var(--gold-hi);
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s, transform .15s;
  box-shadow: 0 0 14px var(--gold-glow), 0 6px 14px -6px rgba(0,0,0,0.6);
}
.shop-card-eye svg { width: 22px; height: 22px; }
.shop-card:hover .shop-card-eye,
.shop-card:focus-visible .shop-card-eye {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

/* Worn pip on a sell-mode card */
.shop-card-worn {
  position: absolute;
  top: 6px;
  left: 6px;
  z-index: 2;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: rgba(146, 224, 173, 0.18);
  border: 1px solid rgba(146, 224, 173, 0.55);
  color: var(--sage);
  font-family: var(--font-banner);
  font-size: 8.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/* ------------------------------------------------------------
   Info modal — opens when ?info=<id> is set on the shop URL.
   Same modal pattern as the inventory detail (backdrop link +
   floating card + close button).
   ------------------------------------------------------------ */
.shop-modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(8, 11, 30, 0.72);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  cursor: pointer;
  text-decoration: none;
}
.shop-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(720px, 94vw);
  max-height: 90vh;
  overflow-y: auto;
  z-index: 201;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.01) 100%),
    rgba(15, 19, 50, 0.96);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: var(--r-3);
  padding: var(--sp-5);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.06) inset,
    0 30px 80px -20px rgba(0,0,0,0.75),
    0 0 40px -10px rgba(0,0,0,0.5);
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr);
  gap: var(--sp-5);
  align-items: start;
}
@media (max-width: 720px) {
  .shop-modal { grid-template-columns: minmax(0, 1fr); }
}
.shop-modal-close {
  position: absolute;
  top: 10px;
  right: 12px;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-stroke);
  color: var(--ink);
  text-decoration: none;
  font-size: 20px;
  line-height: 1;
  z-index: 1;
  transition: background .15s, color .15s;
}
.shop-modal-close:hover { background: rgba(255,255,255,0.12); color: var(--gold); }

/* Bigger item card inside the modal (same artwork plate styling as the
   inventory detail modal). */
.shop-modal-card .item-icon {
  width: 220px;
  height: 220px;
  margin-left: auto;
  margin-right: auto;
}
.shop-modal-card .item-icon img {
  width: 100%;
  height: 100%;
  padding: 8px;
  object-fit: contain;
  box-sizing: border-box;
}
.shop-modal-stats {
  display: flex;
  justify-content: center;
  font-family: var(--font-body);
  font-size: 14px;
  margin-top: var(--sp-2);
}
.shop-modal-stat .v.plus { color: var(--gold-hi); font-weight: 600; margin-right: 4px; }
.shop-modal-stat .stat-name {
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.shop-modal-side {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.shop-modal-compare {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 14px;
  background: rgba(13, 17, 48, 0.55);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-2);
}
.shop-modal-compare-eyebrow {
  margin: 0 0 4px;
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-hi);
}
.shop-modal-compare-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  font-size: 13px;
}
.shop-modal-compare-row.is-equipped { color: var(--ink-mute); font-size: 12px; }
.shop-modal-compare-name {
  font-family: var(--font-display);
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.shop-modal-compare-stat {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
.shop-modal-delta {
  margin: 6px 0 0;
  text-align: center;
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.shop-modal-delta.is-better  { color: #6be07a; }
.shop-modal-delta.is-worse   { color: #ff6b6b; }
.shop-modal-delta.is-neutral { color: var(--ink-mute); }

/* Modal meta row — sits in the side panel under the comparison. No
   action button: buying/selling happens from the card on the grid. */
.shop-modal-meta {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: var(--sp-2);
  align-items: center;
  text-align: center;
}
.shop-modal-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: var(--sp-2);
  align-items: stretch;
}
.shop-modal-req {
  font-family: var(--font-banner);
  font-size: 10.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  text-align: center;
}
.shop-modal-req.is-locked {
  color: #ff6b6b;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  justify-content: center;
}
.shop-modal-req.is-locked svg { width: 11px; height: 11px; }
.shop-modal-price {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 16px;
  color: var(--gold-hi);
}
.shop-modal-price svg { width: 14px; height: 14px; color: var(--gold); }
.shop-modal-price-sell { color: var(--teal-hi); }
.shop-modal-price-sell svg { color: var(--teal); }
.shop-modal-actions .btn { width: 100%; padding: 10px 16px; }

/* Level badge — small chip pinned to the bottom-right of every card.
   Default = subtle dark with gold text; locked = red with a padlock. */
.shop-row-lvl {
  position: absolute;
  right: 6px;
  bottom: 6px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 7px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.85);
  border: 1px solid var(--glass-stroke);
  font-family: var(--font-banner);
  font-size: 9px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-hi);
  line-height: 1;
}
.shop-row-lvl.is-locked {
  background: rgba(150, 30, 40, 0.85);
  border-color: rgba(255, 90, 100, 0.55);
  color: #ffe5e5;
}
.shop-row-lvl-icon { width: 9px; height: 9px; }

/* Hover-popover — comparison vs equipped. Hidden by default, fades in
   when the parent card is hovered. Tooltip floats above the card so it
   doesn't push neighbours around. */
.shop-row-popover {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 6px);
  transform: translateX(-50%) translateY(4px);
  width: 220px;
  z-index: 30;
  padding: 10px 12px;
  background: rgba(8, 11, 30, 0.96);
  border: 1px solid var(--glass-stroke-hi);
  border-radius: var(--r-2);
  box-shadow: 0 18px 38px -10px rgba(0,0,0,0.65);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s, transform .15s;
}
.shop-grid .shop-row:hover .shop-row-popover {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.shop-row-popover-eyebrow {
  margin: 0 0 6px;
  font-family: var(--font-banner);
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-hi);
  text-align: center;
}
.shop-row-popover-rows {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.shop-row-popover-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--ink);
}
.shop-row-popover-row.is-equipped {
  color: var(--ink-mute);
  font-size: 11px;
}
.shop-row-popover-name {
  font-family: var(--font-display);
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.shop-row-popover-stat {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
.shop-row-popover-delta {
  margin: 6px 0 0;
  text-align: center;
  font-family: var(--font-banner);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.shop-row-popover-delta.is-better  { color: #6be07a; }
.shop-row-popover-delta.is-worse   { color: #ff6b6b; }
.shop-row-popover-delta.is-neutral { color: var(--ink-mute); }

/* Sort dropdown — sits next to the buy/sell filter chips. */
.shop-controls-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.shop-controls-row .shop-filter-bar { margin: 0; }
.shop-sort-form { margin: 0; }
.shop-sort-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  background: rgba(8, 11, 30, 0.78);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-pill);
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.shop-sort-label svg { width: 11px; height: 11px; color: var(--gold-hi); }
.shop-sort-label select {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: none;
  color: var(--ink);
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  padding: 0 4px 0 2px;
  cursor: pointer;
}
.shop-sort-label select:focus { outline: 1px solid var(--gold); outline-offset: 2px; border-radius: 2px; }

/* Pagination row — lives inside the grid panel footer, beside the gold chip. */
.shop-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  flex: 1 1 auto;
}

/* Grid footer — sits at the bottom of the grid panel. Pagination
   centred / left-fills, character's total gold pinned to the right. */
.shop-grid-footer {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--glass-stroke);
}
.shop-grid-footer-spacer { flex: 1 1 auto; }
.shop-grid-gold {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--r-pill);
  background:
    linear-gradient(180deg, rgba(230, 196, 109, 0.18) 0%, rgba(230, 196, 109, 0.06) 100%);
  border: 1px solid rgba(230, 196, 109, 0.45);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--gold-hi);
  box-shadow: 0 0 12px rgba(230, 196, 109, 0.18);
  margin-left: auto;       /* pin right even if pagination is absent */
}
.shop-grid-gold svg {
  width: 13px;
  height: 13px;
  color: var(--gold);
  filter: drop-shadow(0 0 4px var(--gold-glow));
}
.shop-grid-gold-amount { font-size: 14px; }
.shop-grid-gold-label {
  font-family: var(--font-banner);
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold);
  opacity: 0.75;
  margin-left: 2px;
}
.shop-page-btn {
  display: inline-flex;
  align-items: center;
  padding: 5px 12px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.78);
  border: 1px solid var(--glass-stroke);
  color: var(--ink);
  text-decoration: none;
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transition: background .15s, border-color .15s, color .15s;
}
.shop-page-btn:hover {
  background: rgba(8, 11, 30, 0.92);
  border-color: var(--gold);
  color: var(--gold-hi);
}
.shop-page-btn.is-disabled {
  opacity: 0.4;
  pointer-events: none;
}
.shop-page-count {
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.shop-page-count .t-num { color: var(--gold-hi); }

/* Inventory — level chip pinned to bottom-right of each cell, mirrors
   the shop card's badge. Red + padlock when char is below requirement. */
.inv-cell-lvl {
  position: absolute;
  right: 4px;
  bottom: 4px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 1px 5px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.85);
  border: 1px solid var(--glass-stroke);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 9px;
  color: var(--gold-hi);
  line-height: 1.1;
  pointer-events: none;
}
.inv-cell-lvl.is-locked {
  background: rgba(150, 30, 40, 0.85);
  border-color: rgba(255, 90, 100, 0.55);
  color: #ffe5e5;
}
.inv-cell-lvl-icon { width: 8px; height: 8px; }

/* +N inline badge for the gear detail card's <h4> title. Mirrors the
   inventory-cell badge but inlined into the heading copy. */
.item-name-plus {
  display: inline-block;
  margin-left: 4px;
  padding: 0 6px;
  border-radius: var(--r-pill);
  background: rgba(255, 197, 100, 0.92);
  color: rgba(8, 11, 30, 0.95);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
  vertical-align: 2px;
}

/* Forge-upgrade chip — top-right gold pill showing +N on any inventory
   cell whose gear has been upgraded at Hadric's. Mirrors the level chip
   on the opposite corner so the cell stays visually balanced. */
.inv-cell-upgrade {
  position: absolute;
  right: 4px;
  top: 4px;
  z-index: 2;
  padding: 1px 5px;
  border-radius: var(--r-pill);
  background: rgba(255, 197, 100, 0.92);
  border: 1px solid rgba(255, 197, 100, 0.95);
  color: rgba(8, 11, 30, 0.95);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 9px;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: 0.02em;
  box-shadow: 0 0 6px rgba(255, 197, 100, 0.6);
  pointer-events: none;
}

/* Inventory sort dropdown — mirrors the shop sort select. */
.inv-sort-form { margin: 0; }
.inv-sort {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-banner);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.inv-sort select {
  appearance: none;
  -webkit-appearance: none;
  background: rgba(8, 11, 30, 0.6);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-pill);
  color: var(--ink);
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  padding: 3px 10px;
  cursor: pointer;
}
.inv-sort select:focus { outline: 1px solid var(--gold); outline-offset: 2px; }
.world-tile-img {
  position: absolute;
  inset: 0;
  display: block;
  background: rgba(13, 17, 48, 0.85);
}
.world-tile-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.world-tile-label {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 8px 10px;
  background: linear-gradient(180deg, transparent 0%, rgba(8, 11, 30, 0.85) 70%);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  pointer-events: none;
}
.world-tile-name {
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--ink);
  letter-spacing: -0.005em;
  line-height: 1.1;
  text-shadow: 0 1px 4px rgba(0,0,0,0.7);
}
.world-tile-meta {
  font-family: var(--font-banner);
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--teal-hi);
  margin-top: 2px;
}

/* ============================================================
   Window-overlay (Ragnarok-style). A bordered game panel that
   floats over the current scene with a title bar + close button.
   The scene stays partially visible around the panel — the
   backdrop is only a soft dim, not an opaque scrim.
   ============================================================ */
.overlay-window {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.overlay-window[hidden] { display: none !important; }
.overlay-window-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(8, 11, 30, 0.25);
  pointer-events: auto;
  animation: overlay-fade-in 160ms ease-out;
}
.overlay-window-panel {
  position: relative;
  z-index: 1;
  pointer-events: auto;
  box-sizing: border-box;
  width: clamp(720px, 84vw, 1180px);
  height: clamp(540px, 82vh, 820px);
  max-width: 94vw;
  max-height: calc(100vh - var(--shell-h) - var(--sp-5));
  margin-top: var(--shell-h);
  display: flex;
  flex-direction: column;
  background:
    radial-gradient(circle at 50% 0%, rgba(255,197,100,0.06) 0%, transparent 60%),
    linear-gradient(180deg, rgba(20, 23, 56, 0.96) 0%, rgba(10, 13, 40, 0.97) 100%);
  border: 2px solid var(--glass-stroke-hi);
  border-radius: var(--r-3);
  box-shadow:
    0 22px 60px -10px rgba(0,0,0,0.7),
    0 0 0 1px rgba(255,197,100,0.15) inset,
    0 0 36px rgba(106, 78, 198, 0.20);
  overflow: hidden;
  animation: overlay-pop 180ms cubic-bezier(0.4, 1.4, 0.6, 1);
}
@keyframes overlay-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes overlay-pop {
  from { opacity: 0; transform: scale(0.96) translateY(8px); }
  to   { opacity: 1; transform: scale(1)    translateY(0); }
}
.overlay-window-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: 10px 16px;
  border-bottom: 1px solid var(--glass-stroke);
  background:
    linear-gradient(180deg, rgba(255, 197, 100, 0.10) 0%, rgba(255, 197, 100, 0.02) 100%),
    rgba(8, 11, 30, 0.85);
}
.overlay-window-title {
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: 0.02em;
  color: var(--gold-hi);
  text-shadow: 0 0 10px var(--gold-glow);
}
.overlay-window-close {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid var(--glass-stroke);
  border-radius: 50%;
  color: var(--ink-mute);
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
}
.overlay-window-close:hover {
  color: var(--gold-hi);
  border-color: rgba(255,197,100,0.55);
  background: rgba(255,197,100,0.08);
}
.overlay-window-close svg { width: 16px; height: 16px; }
.overlay-window-body {
  position: relative;
  flex: 1 1 auto;
  overflow: auto;
  padding: var(--sp-4);
  min-height: 0;
  /* Keep scrollability for tall content (world map drag, long lists) but
     hide the visible scrollbars — they break the polished window look. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.overlay-window-body::-webkit-scrollbar { display: none; }
/* Also hide scrollbars on the world map's own viewport inside the overlay
   (drag-to-pan still works). */
.overlay-window-body .world-viewport {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.overlay-window-body .world-viewport::-webkit-scrollbar { display: none; }
.overlay-window-loading,
.overlay-window-error {
  text-align: center;
  padding: var(--sp-5);
  font-family: var(--font-quill);
  font-style: italic;
  color: var(--ink-mute);
  margin: 0;
}
.overlay-window-error { color: var(--r-cursed-c); }
/* Body lock when an overlay is open — keep the scene visible but stop
   the underlying page from scrolling while the panel is active. */
body.has-overlay { overflow: hidden; }

/* When a page is rendered inline inside an overlay, drop the page-level
   padding so the panel itself controls spacing. Most page roots already
   sit at z-index 0/1 inside .viewport-inner; overlay context strips the
   outer padding-top that viewport-inner > * normally adds. */
.overlay-window-body > .inventory-page,
.overlay-window-body > .character-page,
.overlay-window-body > .quest-log-page,
.overlay-window-body > .world-page,
.overlay-window-body > .inv-layout {
  padding: 0;
  margin: 0;
}

/* --- Inventory inside the overlay panel ------------------------------- */
/* The panel is narrower than a full page screen, so:
   - paperdoll column shrinks (380px instead of 440px)
   - header wraps with a clear gap so tabs sit on their own row
   - inventory panel's min-height of 700px doesn't make sense inside a
     panel, drop it so the grid sizes to its content
   - grid drops to 6 columns by default, 5 on very narrow panels        */
.overlay-window-body .inv-layout {
  grid-template-columns: 320px minmax(0, 1fr);
  gap: var(--sp-4);
  margin-top: 0;
}
.overlay-window-body .inventory-panel {
  padding: var(--sp-4);
  gap: var(--sp-3);
  min-height: 0;
}
.overlay-window-body .inv-header {
  flex-direction: column;
  align-items: stretch;
  gap: var(--sp-3);
}
.overlay-window-body .inv-title { font-size: 22px; }
.overlay-window-body .inv-tabs { justify-content: flex-start; }
.overlay-window-body .inv-tools { flex-wrap: wrap; gap: var(--sp-2) var(--sp-3); }
.overlay-window-body .inv-grid {
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 8px;
}
@media (max-width: 1100px) {
  .overlay-window-body .inv-layout { grid-template-columns: minmax(0, 1fr); }
  .overlay-window-body .inv-grid { grid-template-columns: repeat(8, minmax(0, 1fr)); }
}
@media (max-width: 820px) {
  .overlay-window-body .inv-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}
/* The paperdoll panel scales its character art down too — keep it from
   forcing the column wider than its grid track. */
.overlay-window-body .character-panel { padding: var(--sp-4); min-width: 0; }
.overlay-window-body .paperdoll { gap: 6px; }
/* Quest log's full-viewport min-height + backdrop image are scaled to the
   page; reset them inside the overlay so the panel controls the size. */
.overlay-window-body > .quest-log-page { min-height: 0; }
.overlay-window-body > .quest-log-page > .quest-log-bg { display: none; }
.overlay-window-body > .world-page { height: 100%; }
.overlay-window-body .world-viewport { max-height: calc(86vh - 56px); }

/* ============================================================
   Travel splash — 10-second interstitial between maps
   ============================================================ */

.travel-splash {
  position: fixed;
  inset: 0;
  z-index: 9999;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: #000;
  animation: travel-splash-in 220ms ease-out;
}
.travel-splash[hidden] { display: none; }

.travel-splash-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.7) saturate(1.1);
}
.travel-splash-overlay {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse at center, rgba(0,0,0,0) 40%, rgba(0,0,0,0.55) 100%),
    linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.75) 100%);
}

.travel-splash-content {
  position: relative;
  z-index: 2;
  text-align: center;
  padding: var(--sp-5);
}
.travel-splash-eyebrow {
  margin: 0 0 8px;
  font-family: var(--font-banner);
  font-size: 12px;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: var(--ink-soft);
  opacity: 0.85;
}
.travel-splash-title {
  margin: 0;
  font-family: var(--font-banner);
  font-weight: 700;
  font-size: clamp(36px, 7vw, 64px);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  text-shadow:
    0 2px 14px rgba(0,0,0,0.85),
    0 0 24px rgba(255, 197, 100, 0.4);
}

/* Progress strip pinned along the bottom of the viewport. */
.travel-progress {
  position: absolute;
  bottom: clamp(40px, 8vh, 80px);
  left: 50%;
  transform: translateX(-50%);
  width: min(720px, 80vw);
  z-index: 3;
}
.travel-progress-track {
  position: relative;
  width: 100%;
  height: 12px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.78);
  border: 1px solid var(--glass-stroke);
  box-shadow:
    inset 0 1px 4px rgba(0,0,0,0.6),
    0 2px 12px -2px rgba(0,0,0,0.7);
  overflow: visible;     /* the rider sticks above the track */
}
.travel-progress-fill {
  position: relative;
  height: 100%;
  width: 0;
  border-radius: var(--r-pill);
  background:
    linear-gradient(90deg, rgba(255, 100, 40, 0.85), rgba(255, 197, 100, 0.98), rgba(255, 100, 40, 0.85));
  background-size: 200% 100%;
  animation: forge-shimmer 1.2s linear infinite;
  box-shadow: 0 0 14px rgba(255, 197, 100, 0.55);
}
.travel-character {
  position: absolute;
  right: 0;
  bottom: 100%;
  width: clamp(56px, 6vw, 84px);
  height: clamp(56px, 6vw, 84px);
  transform: translate(50%, 18%);   /* center horizontally on the leading edge, dip slightly so feet kiss the bar */
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.6));
  pointer-events: none;
  animation: travel-character-bob 600ms ease-in-out infinite alternate;
}

@keyframes travel-splash-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes travel-character-bob {
  from { transform: translate(50%, 18%); }
  to   { transform: translate(50%, 4%); }
}

/* ============================================================
   Hadric's Forge — upgrade UI
   ============================================================ */

.forge-body {
  gap: var(--sp-4);
}

.forge-flash {
  position: absolute;
  top: calc(var(--shell-h) + 24px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  padding: 8px 18px;
  border-radius: var(--r-pill);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.02em;
  background: rgba(8, 11, 30, 0.85);
  border: 1px solid var(--glass-stroke);
  box-shadow: 0 6px 18px -8px rgba(0,0,0,0.6);
  white-space: nowrap;
}
.forge-flash--success { color: var(--gold);  border-color: var(--gold); box-shadow: 0 0 22px var(--gold-glow); }
.forge-flash--fail    { color: var(--ember); border-color: var(--ember); box-shadow: 0 0 22px rgba(220, 80, 50, 0.4); }
.forge-flash--warn    { color: #d8c47a;      border-color: rgba(216,196,122,0.55); }

.forge-panel {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-4);
  background: rgba(8, 11, 30, 0.78);
}

.forge-row {
  display: grid;
  gap: var(--sp-3);
}
.forge-row--inputs { grid-template-columns: 1fr 1fr; }
/* Info row holds Upgrade / Success / Duration / Cost — four equal
   boxes at desktop, collapses to 2-wide / 1-wide at narrower viewports. */
.forge-row--info   { grid-template-columns: repeat(4, 1fr); }
.forge-row--action {
  grid-template-columns: 1fr;
  justify-items: center;
  text-align: center;
  margin-top: var(--sp-1);
}
@media (max-width: 980px) {
  .forge-row--info { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 720px) {
  .forge-row--inputs { grid-template-columns: 1fr; }
  .forge-row--info   { grid-template-columns: 1fr; }
}

.forge-box {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 12px 14px;
  min-height: 96px;
  border-radius: var(--r-md);
  border: 2px solid var(--glass-stroke);
  background:
    radial-gradient(circle at 50% 30%, rgba(255, 197, 100, 0.06), transparent 60%),
    linear-gradient(180deg, rgba(255,255,255,0.04), rgba(13, 17, 48, 0.78));
}
.forge-box.is-empty  { border-style: dashed; border-color: rgba(255, 197, 100, 0.22); }
.forge-box.is-filled { border-color: var(--gold); box-shadow: inset 0 0 22px rgba(255, 197, 100, 0.10); }
.forge-box.is-locked { border-color: rgba(220, 80, 50, 0.45); }
.forge-box.is-safe   { border-color: rgba(120, 200, 130, 0.55); box-shadow: inset 0 0 22px rgba(120, 200, 130, 0.10); }
.forge-box.is-risky  { border-color: var(--ember); box-shadow: inset 0 0 22px rgba(220, 80, 50, 0.10); }
.forge-box.is-cap    { opacity: 0.7; }

.forge-box-eyebrow {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  opacity: 0.85;
}
.forge-box-glyph svg { width: 38px; height: 38px; color: var(--ink); opacity: 0.5; }
.forge-box-art       { display: flex; align-items: center; justify-content: center; }
.forge-box-img       { width: 48px; height: 48px; object-fit: contain; }
.forge-box-line      { font-size: 13.5px; color: var(--ink); text-align: center; line-height: 1.3; }
.forge-box-line strong { color: var(--ink); }
.forge-box-plus {
  display: inline-block;
  margin-left: 4px;
  padding: 0 6px;
  border-radius: var(--r-pill);
  background: rgba(255, 197, 100, 0.92);
  color: rgba(8, 11, 30, 0.95);
  font-size: 11px;
  font-weight: 700;
}
.forge-box-stock { font-size: 11px; color: var(--ink-soft); opacity: 0.9; }
.forge-box-stock.is-short { color: var(--ember); }

.forge-box-big {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 22px;
  font-weight: 700;
  color: var(--gold);
  letter-spacing: 0.02em;
}
.forge-box.is-safe  .forge-box-big { color: #9fde9f; }
.forge-box.is-risky .forge-box-big { color: var(--ember); }
.forge-box.is-cap   .forge-box-big { color: var(--ink-soft); }
.forge-box-arrow { color: var(--ink-soft); opacity: 0.7; margin: 0 4px; }

/* Coin glyph inside the Cost box — keeps the gold figure flush with
   the standard gold-purse styling used elsewhere in the app. */
.forge-box-coin {
  width: 16px;
  height: 16px;
  vertical-align: -2px;
  color: var(--gold);
  margin-right: 4px;
}
.forge-box-delta {
  font-family: var(--font-banner);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  margin-left: 6px;
  opacity: 0.9;
}

.forge-box-clear {
  position: absolute;
  top: 4px;
  right: 8px;
  font-size: 16px;
  line-height: 1;
  color: var(--ink);
  opacity: 0.55;
  text-decoration: none;
}
.forge-box-clear:hover { opacity: 1; color: var(--ember); }

/* --- Forge button + 20-second progress + result panel ----------------- */

.forge-fire {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: max-content;
  max-width: 220px;
}
.forge-fire-btn { gap: 6px; }
.forge-fire-btn svg { width: 14px; height: 14px; }
.forge-fire-hint { margin: 0; font-size: 11px; color: var(--ink-soft); opacity: 0.85; }

.forge-progress {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
/* `display: flex` above wins over the user-agent `[hidden] { display: none }`
   default, so the element shows on first paint. Restore the hide. */
.forge-progress[hidden] { display: none; }
.forge-progress-track {
  width: 100%;
  height: 14px;
  border-radius: var(--r-pill);
  background: rgba(8, 11, 30, 0.85);
  border: 1px solid var(--glass-stroke);
  overflow: hidden;
  position: relative;
}
.forge-progress-fill {
  height: 100%;
  width: 0;
  background:
    linear-gradient(90deg, rgba(255, 100, 40, 0.85), rgba(255, 197, 100, 0.95), rgba(255, 100, 40, 0.85));
  background-size: 200% 100%;
  animation: forge-shimmer 1.2s linear infinite;
  box-shadow: 0 0 14px rgba(255, 197, 100, 0.55);
  border-radius: var(--r-pill);
}
@keyframes forge-shimmer {
  from { background-position: 200% 0; }
  to   { background-position: 0 0; }
}
.forge-progress-label {
  margin: 0;
  font-size: 12px;
  color: var(--gold);
  letter-spacing: 0.03em;
  font-style: italic;
}

/* Result modal — full-viewport overlay with dimmed backdrop + centered
   result panel. Pops in once the forge progress bar fills. */
.forge-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
}
.forge-modal[hidden] { display: none; }
.forge-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(4, 6, 18, 0.72);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}
.forge-result {
  position: relative;
  z-index: 1;
  width: min(420px, 88vw);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 22px 28px;
  border-radius: var(--r-md);
  border: 2px solid var(--glass-stroke);
  background: rgba(8, 11, 30, 0.96);
}
.forge-result-headline {
  margin: 0;
  font-family: var(--font-banner);
  font-weight: 700;
  font-size: 26px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  line-height: 1;
}
.forge-result-line {
  margin: 0;
  font-size: 14px;
  text-align: center;
  line-height: 1.4;
}

/* Success = green. Failure = red. Anything else (cap, no-material,
   unknown) stays neutral amber so it doesn't read as a win or a loss. */
.forge-result--success { border-color: #6fd17e; box-shadow: 0 0 38px rgba(111, 209, 126, 0.45); }
.forge-result--success .forge-result-headline { color: #8ee698; text-shadow: 0 0 14px rgba(111, 209, 126, 0.55); }
.forge-result--success .forge-result-line     { color: #b6e9b9; }
.forge-result--success .forge-result-line strong { color: #d6f5d8; }

.forge-result--fail    { border-color: var(--ember); box-shadow: 0 0 38px rgba(255, 122, 82, 0.45); }
.forge-result--fail    .forge-result-headline { color: #ff8d72; text-shadow: 0 0 14px rgba(255, 122, 82, 0.55); }
.forge-result--fail    .forge-result-line     { color: #ffb6a6; }
.forge-result--fail    .forge-result-line strong { color: #ffd6cb; }

.forge-result--warn    { border-color: rgba(216,196,122,0.55); }
.forge-result--warn    .forge-result-headline { color: #d8c47a; }
.forge-result--warn    .forge-result-line     { color: #d8c47a; }

/* Lock the picker grid while the forge is running so the player can't
   swap items mid-cycle. The .is-locked class is added by the inline JS. */
.forge-pick.is-locked {
  pointer-events: none;
  opacity: 0.5;
  filter: grayscale(0.6);
}

.forge-picker {
  padding: var(--sp-3);
  max-height: 220px;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.forge-picker-title {
  margin: 0;
  font-size: 13px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 0.7;
}
.forge-picker-empty { margin: 0; font-size: 13px; color: var(--ink); opacity: 0.7; }
.forge-picker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 6px;
  overflow-y: auto;
  padding-right: 4px;
}
.forge-pick {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border-radius: var(--r-sm);
  background: rgba(8, 11, 30, 0.55);
  border: 1px solid var(--glass-stroke);
  color: var(--ink);
  text-decoration: none;
  font-size: 13px;
  transition: border-color 120ms, background 120ms;
}
.forge-pick:hover    { border-color: var(--gold); background: rgba(8, 11, 30, 0.75); }
.forge-pick.is-selected { border-color: var(--gold); box-shadow: 0 0 14px var(--gold-glow); }
.forge-pick-icon img,
.forge-pick-icon svg { width: 28px; height: 28px; }
.forge-pick-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.forge-pick-plus {
  display: inline-block;
  margin-left: 4px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: rgba(255, 197, 100, 0.18);
  color: var(--gold);
  font-size: 11px;
  font-weight: 700;
}
.forge-pick-eq {
  display: inline-block;
  margin-left: 4px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: rgba(64, 196, 220, 0.18);
  color: #82d6e8;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* ============================================================
   Leaderboard — ranked table of every character in the DB
   ============================================================ */
.leaderboard-head {
  text-align: center;
  margin-bottom: var(--sp-5);
}
.leaderboard-title {
  font-size: 40px;
  line-height: 1;
  margin: var(--sp-2) 0 0;
  color: var(--gold-hi);
  text-shadow: 0 0 32px var(--gold-glow);
}
.leaderboard-blurb {
  margin: var(--sp-3) auto 0;
  max-width: 460px;
  font-size: 15px;
}
.leaderboard-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.leaderboard-row {
  display: grid;
  grid-template-columns: 44px 56px 1fr auto;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--glass);
  border: 1px solid var(--glass-stroke);
  border-radius: var(--r-3);
  transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
}
.leaderboard-row:hover {
  transform: translateY(-1px);
  border-color: var(--glass-stroke-hi);
  box-shadow: 0 4px 16px -6px rgba(0, 0, 0, 0.5);
}
.leaderboard-row--self {
  border-color: var(--gold-hi);
  background:
    linear-gradient(180deg, rgba(238, 188, 100, 0.10) 0%, rgba(238, 188, 100, 0.02) 100%);
  box-shadow: 0 0 18px var(--gold-glow);
}
.leaderboard-rank {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 400;
  color: var(--gold-hi);
  text-align: center;
  text-shadow: 0 0 12px var(--gold-glow);
}
.leaderboard-medallion {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--glass-hi);
  border: 1px solid var(--glass-stroke-hi);
  display: flex;
  align-items: center;
  justify-content: center;
}
.leaderboard-portrait {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}
.leaderboard-portrait-fallback {
  width: 30px;
  height: 30px;
  color: var(--ink-mute);
}
.leaderboard-identity {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0; /* enables text-overflow on long names */
}
.leaderboard-name {
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.leaderboard-class {
  font-family: var(--font-banner);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.leaderboard-level {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding-left: var(--sp-2);
}
.leaderboard-level .t-meta {
  font-size: 11px;
  letter-spacing: 0.24em;
}
.leaderboard-level .t-num {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--xp);
}
.leaderboard-empty {
  text-align: center;
  margin: var(--sp-5) 0;
  color: var(--ink-mute);
}


