/* ==========================================================
   DUNGEON KNIGHTS — DARK TACTICAL UI
   Design system: dark stone panels, bronze borders,
   silver typography, single gold accent, no glow spam.
   ========================================================== */

@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;600;700;900&family=Cinzel+Decorative:wght@400;700;900&family=Inter:wght@400;500;600;700&display=swap');

/* ==========================================================
   TOKENS
   ========================================================== */
:root {
  /* Surfaces */
  --bg-void:      #0D0A08;
  --bg-dark:      #12100E;
  --bg-panel:     #1A1714;
  --bg-raised:    #211E1A;
  --bg-input:     #161310;
  --bg-hover:     #2A2520;

  /* Borders */
  --border-dim:   #2E2820;
  --border-base:  #4A3F30;
  --border-bronze:#8B6B3D;
  --border-gold:  #C9A84C;

  /* Accent */
  --accent-gold:  #D4AF37;
  --accent-gold-light: #F4D03F;
  --accent-gold-dim:   #8B7A2A;

  /* Text */
  --text-primary:   #E8E0D4;
  --text-secondary: #A89A86;
  --text-muted:     #6B5F50;
  --text-gold:      #D4AF37;

  /* Dungeon accent tints */
  --tint-crypts: #7EB8DA;
  --tint-magma:  #E85D3A;
  --tint-mines:  #4ADE80;
  --tint-temple: #A3BE8C;
  --tint-void:   #B07CD8;

  /* Status */
  --danger:       #C0392B;
  --danger-hover: #E74C3C;
  --success:      #4ADE80;

  /* Typography */
  --font-display: 'Cinzel Decorative', serif;
  --font-heading: 'Cinzel', serif;
  --font-body:    'Inter', 'Segoe UI', sans-serif;

  /* Sizing */
  --radius-sm:   4px;
  --radius-md:   6px;
  --radius-lg:   10px;

  /* Shadows — only depth, no glow */
  --shadow-sm:    0 2px 8px rgba(0,0,0,0.5);
  --shadow-md:    0 4px 16px rgba(0,0,0,0.6);
  --shadow-lg:    0 8px 32px rgba(0,0,0,0.7);
  --shadow-inset: inset 0 1px 0 rgba(255,255,255,0.03);
}

/* ==========================================================
   RESET & BASE
   ========================================================== */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  width: 100%; height: 100%;
  overflow: hidden;

  /* The bone cursor. Two things were wrong with it and both are in this one line.

     The art leaned the wrong way. It ran from a knob at the top-right down to one at the
     bottom-left, which reads as a cursor tilted right; `public/assets/cursor/bone.png` is now
     that same art mirrored horizontally, so the knob sits at the top-left and the shaft trails
     down to the right — the direction every system arrow uses.

     And the hotspot was `0 0`, which on the old art was a **transparent corner**: the click
     point sat off the ink, so the visible bone hung down and right of where a click actually
     landed. It is now the top-left-most opaque pixel of the mirrored art, measured rather than
     guessed (7,0 — row 0 of the mirrored image is ink from x=7 to x=9), which is the tip the eye
     reads as the pointer.

     `?v=2` because the file changed under a URL browsers have already cached; without it a
     returning player keeps the old bone. */
  cursor: url('assets/cursor/bone.png?v=2') 7 0, auto;
}

/* Interactive elements get a pointer bone */
button, a, .card, .quest-scroll-card, .knight-card, [role="button"] {
  cursor: url('assets/cursor/bone.png?v=2') 7 0, pointer;
}

body {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text-primary);
  background: var(--bg-void);
  -webkit-font-smoothing: antialiased;
}

/* ==========================================================
   LAYOUT HELPERS
   ========================================================== */
.page {
  width: 100vw; height: 100vh;
  display: flex; flex-direction: column;
  position: relative;
  overflow: hidden;
}

.page-bg {
  position: fixed; inset: 0; z-index: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

.page-bg::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(13,10,8,0.4) 0%, rgba(13,10,8,0.85) 100%);
}

.page-content {
  position: relative; z-index: 1;
  flex: 1; display: flex; flex-direction: column;
}

/* ==========================================================
   HEADER
   ========================================================== */
.header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 24px;
  background: var(--bg-dark);
  border-bottom: 1px solid var(--border-base);
  box-shadow: var(--shadow-md);
  z-index: 50; flex-shrink: 0;
}

.header-brand {
  display: flex; align-items: center; gap: 12px;
}

.header-logo-img {
  width: 32px; height: 32px;
  image-rendering: pixelated;
  filter: brightness(1.1);
}

.header-title {
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--text-gold);
  letter-spacing: 3px;
  text-transform: uppercase;
}

.header-actions {
  display: flex; align-items: center; gap: 12px;
}

.wallet-pill {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 14px;
  background: var(--bg-raised);
  border: 1px solid var(--border-bronze);
  border-radius: var(--radius-md);
  font-family: var(--font-heading);
  font-size: 13px;
  color: var(--accent-gold);
  letter-spacing: 1px;
}

/* ==========================================================
   BUTTONS — 4 variants, 3 sizes
   ========================================================== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--font-heading);
  font-weight: 600; letter-spacing: 1px; text-transform: uppercase;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer; position: relative;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: var(--shadow-inset), var(--shadow-sm);
}
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none; }

/* Sizes */
.btn-sm { padding: 6px 14px; font-size: 11px; }
.btn-md { padding: 10px 22px; font-size: 13px; }
.btn-lg { padding: 14px 32px; font-size: 15px; }

/* Variants */
.btn-primary {
  background: linear-gradient(180deg, #3D3018 0%, #2A2010 100%);
  border-color: var(--border-bronze);
  color: var(--accent-gold);
}
.btn-primary:hover:not(:disabled) {
  background: linear-gradient(180deg, #4A3A20 0%, #352818 100%);
  border-color: var(--accent-gold);
}
.btn-primary .btn-icon-img { filter: brightness(1.3) sepia(0.6) hue-rotate(5deg); }

.btn-secondary {
  background: linear-gradient(180deg, #252220 0%, #1A1816 100%);
  border-color: var(--border-base);
  color: var(--text-secondary);
}
.btn-secondary:hover:not(:disabled) {
  background: linear-gradient(180deg, #302A26 0%, #221E1A 100%);
  border-color: var(--border-dim);
  color: var(--text-primary);
}

.btn-danger {
  background: linear-gradient(180deg, #3D1818 0%, #2A1010 100%);
  border-color: #6B2828;
  color: #E07070;
}
.btn-danger:hover:not(:disabled) {
  background: linear-gradient(180deg, #4A2020 0%, #351414 100%);
  border-color: var(--danger);
  color: #F08080;
}

.btn-ghost {
  background: transparent;
  border-color: var(--border-base);
  color: var(--text-secondary);
  box-shadow: none;
}
.btn-ghost:hover:not(:disabled) {
  background: var(--bg-hover);
  border-color: var(--border-bronze);
  color: var(--text-primary);
}

.btn-icon-img {
  width: 18px; height: 18px;
  image-rendering: pixelated;
  flex-shrink: 0;
}

/* ==========================================================
   PANELS
   ========================================================== */
.panel {
  background: var(--bg-panel);
  border: 1px solid var(--border-base);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  position: relative;
}

.panel::before {
  content: '';
  position: absolute; inset: 0;
  border-radius: var(--radius-lg);
  background: repeating-linear-gradient(
    0deg, transparent, transparent 2px,
    rgba(255,255,255,0.008) 2px, rgba(255,255,255,0.008) 4px
  );
  pointer-events: none;
}

.panel-header {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border-base);
  font-family: var(--font-heading);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.panel-header-icon {
  width: 20px; height: 20px;
  image-rendering: pixelated;
  opacity: 0.7;
  filter: brightness(1.2);
}

.panel-body { padding: 16px 18px; }

/* ==========================================================
   CARD (for quest buttons, knight cards)
   ========================================================== */
.card {
  background: var(--bg-raised);
  border: 1px solid var(--border-base);
  border-radius: var(--radius-md);
  padding: 16px;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
  position: relative;
}
.card:hover {
  border-color: var(--border-bronze);
  background: var(--bg-hover);
}
.card-accent-left {
  border-left: 3px solid var(--accent-gold);
}
.card-accent-right {
  border-right: 3px solid var(--accent-gold);
}

/* ==========================================================
   STATS
   ========================================================== */
.stat-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 8px 0;
  border-bottom: 1px solid rgba(46,40,32,0.5);
  font-size: 13px;
}
.stat-row:last-child { border-bottom: none; }
.stat-label { color: var(--text-muted); letter-spacing: 0.5px; }
.stat-value {
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--text-primary);
}
.stat-value-gold { color: var(--accent-gold); }

.stat-bar-track {
  width: 100%; height: 4px;
  background: var(--bg-input);
  border-radius: 2px;
  overflow: hidden;
  margin-top: 4px;
}
.stat-bar-fill {
  height: 100%;
  background: var(--accent-gold);
  border-radius: 2px;
  transition: width 0.3s ease;
}

/* ==========================================================
   FORMS
   ========================================================== */
.select {
  appearance: none;
  background: var(--bg-input);
  border: 1px solid var(--border-base);
  border-radius: var(--radius-sm);
  padding: 8px 32px 8px 12px;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-primary);
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%23A89A86'%3E%3Cpath d='M2 4l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  transition: border-color 0.15s;
}
.select:hover { border-color: var(--border-bronze); }
.select:focus { outline: none; border-color: var(--accent-gold); }

/* ==========================================================
   MODAL
   ========================================================== */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(0,0,0,0.85);
  display: flex; align-items: center; justify-content: center;
  backdrop-filter: blur(6px);
}
.modal-backdrop.hidden { display: none; }

.modal {
  background: var(--bg-panel);
  border: 1px solid var(--border-bronze);
  border-radius: var(--radius-lg);
  padding: 32px;
  min-width: 420px; max-width: 540px;
  width: 90%;
  box-shadow: var(--shadow-lg);
  animation: modal-in 0.2s ease-out;
}
@keyframes modal-in {
  from { opacity: 0; transform: translateY(12px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.modal-title {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--accent-gold);
  letter-spacing: 2px;
  text-align: center;
  margin-bottom: 24px;
}

.modal-stats {
  background: var(--bg-dark);
  border: 1px solid var(--border-base);
  border-radius: var(--radius-md);
  padding: 16px 20px;
  margin-bottom: 24px;
}

.modal-stats p {
  display: flex; justify-content: space-between;
  padding: 6px 0;
  font-size: 14px;
  color: var(--text-secondary);
}
.modal-stats strong { color: var(--text-muted); margin-right: 12px; }
.modal-stats span { color: var(--accent-gold); font-family: var(--font-heading); font-weight: 700; }

.modal-actions {
  display: flex; gap: 12px;
}

/* ==========================================================
   SCROLLBARS
   ========================================================== */
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border-bronze);
  border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover { background: var(--accent-gold-dim); }

/* ==========================================================
   UTILITIES
   ========================================================== */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0,0,0,0);
}
.text-gold { color: var(--accent-gold); }
.text-muted { color: var(--text-muted); }
.mt-8 { margin-top: 8px; }
.mt-16 { margin-top: 16px; }
.mb-8 { margin-bottom: 8px; }
.mb-16 { margin-bottom: 16px; }
.gap-8 { gap: 8px; }
.gap-12 { gap: 12px; }
.gap-16 { gap: 16px; }
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.w-full { width: 100%; }

/* ==========================================================
   SIDE PANELS (menu, dungeon-select, mint)
   ========================================================== */
.side-panel {
  background: var(--bg-panel);
  border: 1px solid var(--border-base);
  border-right: none;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.side-panel-header {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 18px;
  background: var(--bg-dark);
  border-bottom: 1px solid var(--border-base);
  font-family: var(--font-heading);
  font-size: 12px; font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-secondary);
  flex-shrink: 0;
}
.side-panel-body {
  padding: 18px;
  flex: 1;
  overflow-y: auto;
}

/* ==========================================================
   HALL PANELS — the map art behind the Knight's Hall roster and the
   Summoning Chamber's gallery.

   Same treatment as the landing page's background: `cover`, centred, with a dark
   scrim so the roster stays readable on top of the picture.

   Painted on the panel rather than on `.side-panel-body`, and that is deliberate:
   the body is the scrolling element (`overflow-y: auto`), so a background there would
   scroll away with the roster and rescale as it grew — `cover` sizes to the element's
   box, not to the window. On the panel it holds still while the list moves.

   The visible art is still only the body, because `.side-panel-header` paints its own
   opaque strip over the top. The scrim is a second *background layer*, not an overlay:
   background layers paint behind everything the panel contains, so neither the header
   nor the knight cards are ever fogged.

   The scrim is the landing page's recipe (0.4 → 0.85), nudged to 0.45 → 0.82: the copy on
   these panels sits at the *top* of the picture — "Connect wallet to view your knights",
   the roster's empty state — and both halls are lit from above, so that is the brightest
   part of the art. Measured, the art's own mean luma is 51–74 of 255, so even at 0.45 the
   hall is plainly visible; what the extra 0.05 buys is a readable line of muted text over
   the lit ceiling rather than a marginal one.
   ========================================================== */
.hall-bg {
  background-image:
    linear-gradient(180deg, rgba(13, 10, 8, 0.45) 0%, rgba(13, 10, 8, 0.82) 100%),
    var(--hall-art, none);
  background-size: cover, cover;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
}

.hall-bg-knight {
  --hall-art: url('/assets/hall/knight-hall.webp');
}

.hall-bg-summon {
  --hall-art: url('/assets/hall/summon-hall.webp');
}

/* Phones get the smaller file. The breakpoint is the one the mobile sheets use, so the
   art and the layout change over together. */
@media (max-width: 860px) {
  .hall-bg-knight {
    --hall-art: url('/assets/hall/knight-hall-mobile.webp');
  }

  .hall-bg-summon {
    --hall-art: url('/assets/hall/summon-hall-mobile.webp');
  }
}

/* ==========================================================
   CONTROL PANEL (mint quantity, rarity)
   ========================================================== */
.control-panel {
  background: var(--bg-raised);
  border: 1px solid var(--border-base);
  border-radius: var(--radius-md);
  padding: 16px;
}

/* ==========================================================
   BADGES (dungeon type, rarity on cards)
   ========================================================== */
.badge {
  display: inline-flex; align-items: center;
  padding: 3px 10px;
  font-size: 10px; font-weight: 700;
  letter-spacing: 1px; text-transform: uppercase;
  border-radius: var(--radius-sm);
  font-family: var(--font-heading);
}
.badge-mythic { background: rgba(176,124,216,0.15); color: #B07CD8; border: 1px solid rgba(176,124,216,0.3); }
.badge-legendary { background: rgba(212,175,55,0.15); color: var(--accent-gold); border: 1px solid rgba(212,175,55,0.3); }
.badge-epic { background: rgba(232,93,58,0.15); color: #E85D3A; border: 1px solid rgba(232,93,58,0.3); }
.badge-rare { background: rgba(74,222,128,0.15); color: #4ADE80; border: 1px solid rgba(74,222,128,0.3); }
.badge-common { background: rgba(168,154,134,0.15); color: var(--text-secondary); border: 1px solid rgba(168,154,134,0.2); }
.badge-stone { background: var(--bg-raised); color: var(--text-muted); border: 1px solid var(--border-base); }

/* ==========================================================
   RARITY DOTS (mint page)
   ========================================================== */
.dot {
  width: 10px; height: 10px;
  border-radius: 2px;
  display: inline-block;
  flex-shrink: 0;
}
.dot-common { background: #9CA3AF; }
.dot-uncommon { background: #4ADE80; }
.dot-rare { background: #3B82F6; }
.dot-epic { background: #A855F7; }
.dot-legendary { background: var(--accent-gold); }

/* ==========================================================
   QUEST CARDS (dungeon-select grid)
   ========================================================== */
.quest-scrolls-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
}
.quest-scroll-card {
  background: var(--bg-raised);
  border: 1px solid var(--border-base);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: border-color 0.15s;
  cursor: pointer;
}
.quest-scroll-card:hover {
  border-color: var(--border-bronze);
}
.accept-quest-btn {
  margin-top: 12px;
}

/* ==========================================================
   LOADING OVERLAY
   ========================================================== */
.loading-transition {
  position: fixed; inset: 0; z-index: 2000;
  background: rgba(0,0,0,0.92);
  display: flex; align-items: center; justify-content: center;
}
.loading-transition.hidden { display: none; }

/* ==========================================================
   MAP LOADING GATE
   The map's own loading screen: it covers the game from the first paint (so the
   chosen dungeon never appears as the markup's placeholder map) and it is taken
   down by public/loading-gate.js once the dungeon's art has arrived. Arya stands
   on it at z-index 2200, so the gate itself sits just underneath her.
   ========================================================== */
#mapLoadingGate {
  position: fixed; inset: 0; z-index: 1900;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 18px;
  background:
    radial-gradient(ellipse at 50% 42%, rgba(212, 168, 67, 0.07) 0%, rgba(0, 0, 0, 0) 62%),
    var(--bg-dark, #0d0b09);
  transition: opacity 500ms ease-out;
  /* Room for her: she rises through the lower middle of the screen. */
  padding-bottom: 26vh;
  text-align: center;
}

#mapLoadingGate.is-open { opacity: 0; pointer-events: none; }

.map-gate-title {
  font-family: var(--font-display, 'Cinzel', serif);
  font-size: clamp(18px, 2.4vw, 26px);
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--accent-gold, #d4a843);
  text-shadow: 0 0 24px rgba(212, 168, 67, 0.25);
}

.map-gate-sub {
  font-family: var(--font-heading, 'Cinzel', serif);
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-muted, #8a8177);
}

.map-gate-track {
  width: min(320px, 62vw);
  height: 4px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.07);
  overflow: hidden;
}

.map-gate-bar {
  height: 100%;
  width: 3%;
  border-radius: 2px;
  background: linear-gradient(90deg, #7a5c2e 0%, var(--accent-gold, #d4a843) 100%);
  transition: width 260ms ease-out;
}

.map-gate-label {
  display: flex; align-items: center; gap: 10px;
  font-size: 12px;
  letter-spacing: 1px;
  color: var(--text-secondary, #cfc7bb);
}

.map-gate-count {
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  color: var(--text-muted, #8a8177);
}

/* ==========================================================
   ANIMATIONS
   ========================================================== */
/* ==========================================================
   KNIGHT CARDS (menu + mint roster)
   ========================================================== */
.knight-card {
  background: var(--bg-raised);
  border: 2px solid var(--border-base);
  border-radius: var(--radius-md);
  padding: 0;
  display: inline-flex; flex-direction: column;
  cursor: pointer;
  position: relative;
  transition: border-color 0.15s;
  flex-shrink: 0;
  width: 130px;
}
.knight-card:hover { border-color: var(--border-bronze); }
.knight-card.selected {
  border-color: var(--success);
  box-shadow: 0 0 12px rgba(74,222,128,0.15);
}
.knight-card.selected::after {
  content: '✓';
  position: absolute; top: 4px; right: 4px;
  background: var(--success);
  color: #000;
  width: 20px; height: 20px;
  border-radius: 3px;
  display: flex; align-items: center; justify-content: center;
  font-weight: bold; font-size: 12px;
  z-index: 2;
}
.knight-card.sleeping { opacity: 0.5; }

.knight-avatar {
  width: 100%; height: 100px;
  border: none;
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  display: flex; align-items: center; justify-content: center;
  position: relative;
  flex-shrink: 0;
  overflow: hidden;
  background: var(--bg-dark);
  padding: 8px;
}
/* The roster and the Summoning Chamber draw the *portrait* (`config.js` → `pfp`), not the map
   sprite. A 512px painting scaled down to 80px must not be pixelated: nearest-neighbour sampling
   drops whole rows of pixels and turns it into a mosaic. The dungeon draws the sprite at its own
   size and is untouched by this. */
.knight-avatar img {
  max-width: 100%; max-height: 100%;
  object-fit: contain;
  image-rendering: auto;
}
.knight-avatar .rarity-common { border-color: #9CA3AF; }
.knight-avatar .rarity-uncommon { border-color: #4ADE80; }
.knight-avatar .rarity-rare { border-color: #3B82F6; }
.knight-avatar .rarity-epic { border-color: #A855F7; }
.knight-avatar .rarity-legendary { border-color: var(--accent-gold); }
.knight-avatar .rarity-mythic { border-color: #B07CD8; }

#knightRoster {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 10px;
  margin-top: 10px;
}

.knight-info { padding: 8px 10px 10px; text-align: center; }
.knight-name {
  font-family: var(--font-heading);
  font-size: 11px; font-weight: 700;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.knight-rarity {
  font-size: 9px; font-weight: 700;
  padding: 1px 6px; border-radius: 3px;
  display: inline-block; margin-top: 3px;
  letter-spacing: 0.5px;
}
.knight-stats {
  display: flex; gap: 6px; margin-top: 5px;
  font-size: 10px; color: var(--text-secondary);
  justify-content: center;
  flex-wrap: wrap;
}
}
.knight-stat { font-family: var(--font-heading); }

.knight-stamina-display { margin-top: 6px; }
.knight-stamina-label {
  display: flex; justify-content: space-between;
  font-size: 10px; color: var(--text-muted); margin-bottom: 3px;
}
.stamina-bar {
  width: 100%; height: 4px;
  background: var(--bg-input);
  border-radius: 2px;
  overflow: hidden;
}
.stamina-fill {
  height: 100%; border-radius: 2px;
  background: var(--accent-gold);
  transition: width 0.3s;
}
.stamina-threshold {
  position: relative; top: -4px;
  border-left: 1px dashed rgba(255,255,255,0.15);
  height: 4px;
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* ==========================================================
   KNIGHT CARDS (mint page gallery — grid cells)
   ========================================================== */
.knight-header {
  padding: 8px 12px;
  display: flex; justify-content: space-between; align-items: center;
  border-bottom: 1px solid var(--border-base);
}
.knight-header h3 {
  font-family: var(--font-heading);
  font-size: 12px; font-weight: 700;
  letter-spacing: 0.5px;
}
.rarity-badge {
  padding: 2px 8px;
  font-size: 9px; font-weight: 700;
  letter-spacing: 1px;
  border-radius: 3px;
  text-transform: uppercase;
  font-family: var(--font-heading);
}
.knight-image {
  width: 100%; aspect-ratio: 1;
  background: var(--bg-dark);
  display: flex; align-items: center; justify-content: center;
  padding: 8px;
}
.knight-image img {
  width: 100%; height: 100%;
  object-fit: contain;
  /* Same portrait as the roster, same rule — see `.knight-avatar img` above. */
  image-rendering: auto;
}
.knight-stats { padding: 10px 12px; }
.stat-bar { display: flex; flex-direction: column; gap: 4px; }
.stat-label {
  font-size: 10px;
  color: var(--text-muted);
  letter-spacing: 0.5px;
  text-transform: uppercase;
}
.stat-value-bar {
  width: 100%; height: 6px;
  background: var(--bg-input);
  border-radius: 3px;
  overflow: hidden;
}
.stat-fill {
  height: 100%;
  border-radius: 3px;
  transition: width 0.3s;
}
.stat-value {
  font-family: var(--font-heading);
  font-size: 11px;
  color: var(--text-secondary);
  font-weight: 600;
}
/* ==========================================================
   THE ROSTER'S EMPTY STATE

   These four classes are carried by the markup `public/menu.js` writes into
   `#knightRoster`, and until now nothing styled them: the block was inherited from
   whatever the body font is, so a panel whose every other label is Cinzel showed a line of
   Inter at browser defaults. That is the "this font doesn't match" report, and it was not a
   font being wrong — it was no rule at all.

   It is also why the sentence wrapped after three words. `#knightRoster` is a *grid*
   (`repeat(auto-fill, minmax(130px, 1fr))`), so the empty state was laid into a single
   130px cell — the same reason `.no-knights` on the Summoning Chamber spans the row.

   Scoped to `#knightRoster` on purpose: `/points` loads this same sheet and has an empty
   state of its own in `public/css/points.css`, which must keep winning there.
   ========================================================== */
#knightRoster .empty-state {
  grid-column: 1 / -1;
  justify-self: center;
  text-align: center;
  max-width: 484px;
  margin: 24px auto;
  padding: 36px 24px;
  border-radius: var(--radius-lg);
  /* The room art is behind this panel now, and a hall lit from above puts the empty
     state on the brightest part of the picture — the chandelier here, the window on the
     Summoning page. Its own ground keeps the copy readable without fogging the room for
     everyone who does have knights. */
  background: radial-gradient(125% 110% at 50% 38%,
      rgba(13, 10, 8, 0.82) 0%,
      rgba(13, 10, 8, 0.60) 60%,
      rgba(13, 10, 8, 0.18) 100%);
}

#knightRoster .empty-state-icon {
  font-size: 44px;
  line-height: 1;
  opacity: 0.75;
  margin-bottom: 14px;
}

#knightRoster .empty-state-title {
  font-family: var(--font-heading);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-primary);
  margin-bottom: 10px;
}

#knightRoster .empty-state-text {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.7;
  color: var(--text-muted);
  max-width: 420px;
  margin: 0 auto 18px;
}

.no-knights {
  color: var(--text-muted);
  font-style: italic;
  grid-column: 1 / -1;
  text-align: center;
  padding: 40px 20px;
  font-size: 13px;
}

/* ==========================================================
   THE WALLET MENU

   `public/wallet-menu.js` attaches this to every wallet control in the site — the legacy
   `.wallet-pill` ids and the pill a React route renders. It lives in this sheet rather than in
   `wallet-widget.css` because every route already loads theme.css and only two routes load the
   other; a menu styled by a sheet most pages never fetch is a menu that is invisible on them.

   The trigger becomes `position: relative` (`.wallet-menu-host`) so the panel hangs off its own
   corner instead of a measured position, and the panel is a second layer: no layout in the header
   changes when it opens.
   ========================================================== */
.wallet-menu-host {
  position: relative;
  cursor: pointer;
}

.wallet-menu-caret {
  font-size: 9px;
  opacity: 0.55;
  margin-left: 2px;
  transition: opacity 0.15s, transform 0.15s;
}

.wallet-menu-host:hover .wallet-menu-caret,
.wallet-menu-host:focus-visible .wallet-menu-caret {
  opacity: 1;
}

.wallet-menu-host[aria-expanded="true"] .wallet-menu-caret {
  transform: rotate(180deg);
}

.wallet-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 1200;
  min-width: 216px;
  padding: 6px;
  background: var(--bg-raised);
  border: 1px solid var(--border-bronze);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  text-align: left;
  cursor: default;
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 0.16s ease, transform 0.16s ease;
}

.wallet-menu.is-open {
  opacity: 1;
  transform: translateY(0);
}

.wallet-menu-address {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px 6px;
  font-family: var(--font-heading);
  font-size: 11px;
  letter-spacing: 0.5px;
  color: var(--text-secondary);
}

/* The same "live" dot the Points page and the vault use for a connected wallet. */
.wallet-menu-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--success);
  box-shadow: 0 0 6px rgba(74, 222, 128, 0.7);
  flex-shrink: 0;
}

.wallet-menu-addr-text {
  font-variant-numeric: tabular-nums;
  user-select: text;
}

.wallet-menu-sep {
  height: 1px;
  margin: 5px 4px;
  background: var(--border-base);
}

.wallet-menu-item {
  display: flex;
  flex-direction: column;
  gap: 1px;
  width: 100%;
  padding: 8px 10px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-family: var(--font-heading);
  font-size: 11.5px;
  letter-spacing: 0.5px;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.wallet-menu-item:hover,
.wallet-menu-item:focus-visible {
  background: rgba(255, 255, 255, 0.04);
  color: var(--accent-gold);
  outline: none;
}

.wallet-menu-note {
  font-family: var(--font-body);
  font-size: 10px;
  letter-spacing: 0;
  color: var(--text-muted);
}

.wallet-menu-item.is-primary .wallet-menu-label {
  color: var(--accent-gold);
}

/* Why a connect did not happen — no extension, a locked wallet, a declined prompt. Shown in
   place of the menu rather than as a toast, because the menu is still open on the button that
   caused it. */
.wallet-menu-error {
  margin-top: 4px;
  padding: 7px 10px;
  border-top: 1px solid var(--border-base);
  color: var(--danger-hover);
  font-size: 10.5px;
  line-height: 1.5;
}

.wallet-menu-item.is-danger:hover,
.wallet-menu-item.is-danger:focus-visible {
  color: var(--danger-hover);
}

/* ==========================================================
   THE WALLET CHIP — the address control in a page header
   ==========================================================
   Moved here from `points.css` and `staking.css`, which each carried an identical copy of these
   two rules. Both routes needed the chip and neither sheet could serve the other, so it was
   duplicated; the Portfolio page would have made it a third copy, which is where copying stops
   being cheaper than giving it a home. `theme.css` is loaded by every route and already owns
   `.wallet-pill` and the whole `.wallet-menu-*` family, so the header's chrome has one
   definition now instead of one per page.

   `tools/check-styles.js` fails on any route whose markup uses a class no loaded sheet defines,
   and that is what found the original gap: the vault's chip carried the classes and none of the
   behaviour — no tabular figures, and a "live" dot that rendered as a 0x0 span taking a gap in
   a flex row.
   ========================================================== */
.wallet-chip-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: #5fbf6a;
  box-shadow: 0 0 6px rgba(95,191,106,0.8);
  flex-shrink: 0;
}

.wallet-chip {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.5px;
}

/* Rarity colors on knight cards */
.rarity-common { border-color: #9CA3AF; }
.rarity-uncommon { border-color: #4ADE80; }
.rarity-rare { border-color: #3B82F6; }
.rarity-epic { border-color: #A855F7; }
.rarity-legendary { border-color: var(--accent-gold); }
.rarity-mythic { border-color: #B07CD8; }
