  /* Colour variables live in theme.css (shared with the login pages). */

  * { box-sizing: border-box; }

  html, body {
    margin: 0;
    height: 100%;
    background: var(--bg-void);
    color: var(--text-primary);
    font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    font-size: 15px;
  }

  body {
    display: grid;
    grid-template-columns: 220px 1fr auto;
    grid-template-rows: 1fr 280px;
    grid-template-areas:
      "nav game panel"
      "nav chat  panel";
    height: 100vh;
    overflow: hidden;
    transition: grid-template-columns 0.25s ease;
  }

  body.panel-collapsed {
    grid-template-columns: 220px 1fr 44px;
  }

  a, button {
    font-family: inherit;
    color: inherit;
  }

  button:focus-visible, a:focus-visible, input:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
  }

  /* ---------- Left nav ---------- */

  .nav {
    grid-area: nav;
    background: var(--bg-panel);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    padding: 20px 0;
  }

  .nav-brand {
    padding: 0 20px 20px;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: 0.5px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 12px;
    position: relative;
  }
  .nav-brand::after {
    content: "";
    position: absolute;
    bottom: -1px;
    left: 20px;
    width: 40px;
    height: 2px;
    background: var(--accent);
    box-shadow: 0 0 8px 1px rgba(212,162,76,0.6);
  }

  .nav-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 20px;
    color: var(--text-muted);
    text-decoration: none;
    font-size: 14px;
    border-left: 2px solid transparent;
    cursor: pointer;
    background: none;
    border-top: none;
    border-right: none;
    border-bottom: none;
    width: 100%;
    text-align: left;
  }

  /* Shared by the sidebar items and combat's area list. */
  .nav-item:hover, .area-item:hover {
    color: var(--text-primary);
    background: rgba(255,255,255,0.03);
  }

  .nav-item.active, .area-item.active {
    color: var(--text-primary);
    border-left-color: var(--accent);
    background: rgba(212,162,76,0.08);
  }

  /* skill-nav items (Combat + gathering skills) get a two-row block
     instead of the plain single-line nav-item layout: label+dot on
     top, exp progress bar below. */
  .nav-item.skill-nav {
    display: block;
    padding: 8px 20px;
  }
  .skill-nav-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 4px;
  }
  .skill-nav-bar {
    height: 3px;
    border-radius: 2px;
    background: var(--bg-void);
    overflow: hidden;
  }
  .skill-nav-bar-fill {
    height: 100%;
    background: var(--accent);
  }
  .skill-nav-level {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 11px;
    color: var(--text-muted);
  }
  .skill-nav-exp {
    font-size: 10px;
    color: var(--text-muted);
    margin-top: 3px;
    font-variant-numeric: tabular-nums;
  }

  /* The "this is what's actually running" signal -- a pulsing dot,
     deliberately distinct from the active-view border/background
     above, so "what you're looking at" and "what's running" never
     read as the same thing when they're on different nav items. */
  .nav-running-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--success);
    box-shadow: 0 0 6px 1px rgba(79,158,106,0.7);
    animation: running-pulse 1.4s ease-in-out infinite;
  }
  @keyframes running-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.35; }
  }
  @media (prefers-reduced-motion: reduce) {
    .nav-running-dot { animation: none; opacity: 0.85; }
  }

  .nav-icon {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    opacity: 0.8;
  }

  .nav-spacer { flex: 1; }

  .nav-foot {
    padding: 12px 20px 0;
    border-top: 1px solid var(--border);
    font-size: 12px;
    color: var(--text-muted);
  }

  /* ---------- Game viewport ---------- */

  .game {
    grid-area: game;
    padding: 24px;
    overflow: auto;
    display: flex;
    flex-direction: column;
    gap: 20px;
  }

  .status-bar {
    background: var(--bg-panel);
    border: 1px solid rgba(212,162,76,0.35);
    border-radius: 8px;
    padding: 12px 18px;
  }

  .status-bar-row {
    display: flex;
    align-items: center;
    gap: 14px;
  }

  .status-bar-name {
    font-weight: 600;
    white-space: nowrap;
  }

  .status-bar-name.status-bar-idle {
    font-weight: 400;
    color: var(--text-muted);
    font-style: italic;
  }

  .status-bar-row .timer-track {
    flex: 1;
  }

  .status-bar-row .hp-bar {
    flex: 1;
    max-width: 120px;
  }

  .status-bar-target {
    color: var(--text-muted);
    white-space: nowrap;
    font-size: 13px;
  }

  .status-bar-actions {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 10px;
  }

  .status-bar-queue {
    color: var(--accent);
    white-space: nowrap;
    font-size: 12px;
  }

  .status-bar-wrap {
    position: relative;
  }

  /* Inventory (inventory.js): grouped, collapsible sections + search */
  .inv-header { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 14px; }
  .inv-search {
    width: 220px;
    max-width: 50%;
    background: var(--bg-void);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 7px 10px;
    font-size: 13px;
    color: var(--text-primary);
    font-family: inherit;
  }
  .inv-search:focus { outline: none; border-color: var(--accent); }
  .inv-section { margin-bottom: 12px; }
  /* One line per subgroup: its label in a fixed column on the left, its
     tiles flowing (and wrapping) to the right -- every subgroup has a
     fixed place to look. Tiles are as wide as their full name, never
     cut off, so different stacks of the same item are told apart. */
  .inv-subgroup {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 5px 0;
    border-bottom: 1px solid rgba(255,255,255,0.04);
  }
  .inv-subgroup:last-child { border-bottom: none; }
  .inv-subgroup .inv-subheader { flex: 0 0 130px; margin: 0; padding-top: 8px; }
  .inv-grid { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; gap: 6px; }
  .inv-tile {
    min-width: 130px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 6px 10px;
    font-size: 13px;
    background: var(--bg-panel-raised);
    border: 1px solid var(--border);
    border-radius: 5px;
  }
  .inv-tile-name { white-space: nowrap; display: inline-flex; align-items: center; gap: 8px; }
  /* Item pictures are wider than tall (~4:3); the tile shows them at a fixed height. */
  .inv-icon { height: 28px; width: auto; border-radius: 3px; flex: none; }
  .inv-tile-qty { color: var(--text-muted); font-variant-numeric: tabular-nums; font-size: 12px; white-space: nowrap; }
  .inv-section-header {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    background: none;
    border: none;
    border-bottom: 1px solid rgba(212,162,76,0.35);
    padding: 6px 0;
    margin-bottom: 4px;
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--accent);
    cursor: pointer;
    text-align: left;
  }
  .inv-caret { width: 10px; color: var(--text-muted); }
  .inv-section-count { margin-left: auto; color: var(--text-muted); font-weight: 400; letter-spacing: 0; }
  .inv-subheader { font-size: 11px; color: var(--text-muted); margin: 8px 0 5px; text-transform: uppercase; letter-spacing: 0.06em; }
  .inv-clickable { cursor: pointer; }
  .inv-clickable:hover { border-color: var(--accent); }

  /* Market (market.js): item list | selected item's book + my orders; trading in a popup */
  .market-search-row { display: block; margin: 0 0 14px; } /* keeps .inv-search's own width (220px/50%), left-aligned on its own row */
  /* Fills the leftover column height the same way Combat's picker row
     does (see #view-container > .combat-card:has(#area-monster-picker)
     below), instead of always claiming a flat 600px whether or not the
     window has room for it -- that flat height was pushing the whole
     page taller than the viewport and forcing #view-container's own
     scrollbar on top of the item list's own inner one. */
  #view-container > .combat-card:has(#market-layout) { display: flex; flex-direction: column; min-height: 0; }
  .market-layout { display: grid; grid-template-columns: minmax(240px, 300px) 1fr; gap: 24px; align-items: start; flex: 1 1 auto; min-height: 320px; }
  .market-items {
    align-self: stretch;
    min-height: 0;
    contain: size; /* don't let the item list's own content dictate the row's height -- see .area-list's comment below for the same trick */
    overflow-y: auto;
    padding-right: 4px;
  }
  /* Right column: the selected item's book (or the intro) on the left,
     the player's own open orders as a sidebar on the right -- one
     section, side by side, not a second card. */
  .market-right { min-width: 0; width: 100%; display: flex; align-items: flex-start; gap: 32px; }
  .market-my-orders-block { flex: 0 0 260px; width: 260px; min-width: 0; border-left: 1px solid var(--border); padding-left: 24px; }
  .market-item-head, .market-item {
    display: grid;
    grid-template-columns: 1fr 64px 64px;
    gap: 8px;
    align-items: center;
    font-size: 13px;
  }
  .market-item-head { color: var(--text-muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; padding: 0 8px 4px; }
  .market-item-head span:not(:first-child), .market-item span:not(:first-child) { text-align: right; font-variant-numeric: tabular-nums; }
  .market-item {
    width: 100%;
    background: none;
    border: 1px solid transparent;
    border-radius: 5px;
    padding: 6px 8px;
    color: var(--text-primary);
    font-family: inherit;
    cursor: pointer;
    text-align: left;
  }
  .market-item:hover { border-color: var(--border); }
  .market-item.selected { border-color: var(--accent); background: rgba(212,162,76,0.06); }
  .market-item-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .market-ask { color: var(--error); }
  .market-bid { color: var(--success); }

  .market-detail { min-width: 0; flex: 1 1 auto; max-width: 620px; }
  .market-intro { text-align: center; padding: 40px 12px; }
  .market-intro-title { font-size: 18px; font-weight: 600; color: var(--text-primary); margin-bottom: 12px; }
  .market-intro p { font-size: 13px; line-height: 1.6; color: var(--text-muted); margin: 0 auto; max-width: 480px; }
  .market-detail-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 4px; }
  .market-detail-title { font-size: 16px; font-weight: 600; }
  .market-you-have { text-align: center; color: var(--text-muted); font-size: 13px; margin-bottom: 12px; }
  .market-actions { display: flex; gap: 8px; }
  .market-actions .btn { padding: 6px 18px; font-size: 13px; }
  .market-btn-buy { background: var(--success); color: #fff; border: none; font-weight: 600; }
  .market-btn-sell { background: var(--error); color: #fff; border: none; font-weight: 600; }
  /* The book: sells | divider | buys, close together */
  .market-book { display: grid; grid-template-columns: 1fr 1px 1fr; gap: 16px; }
  .market-divider { background: var(--border); }
  .market-col-title { font-size: 12px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 6px; text-align: center; }
  /* Price | Qty header, and each row lined up under it */
  .market-book-head { display: grid; grid-template-columns: 1fr 1fr; font-size: 11px; color: var(--text-muted); padding: 0 6px 2px; border-bottom: 1px solid var(--border); margin-bottom: 2px; }
  .market-book-head span, .market-level span { text-align: center; }
  .market-col-title.sell { color: var(--error); }
  .market-col-title.buy { color: var(--success); }
  .market-level {
    display: grid;
    grid-template-columns: 1fr 1fr;
    width: 100%;
    font-size: 13px;
    padding: 4px 6px;
    border: 1px solid transparent;
    border-radius: 4px;
    background: none;
    color: var(--text-primary);
    font-family: inherit;
    cursor: pointer;
    font-variant-numeric: tabular-nums;
  }
  .market-level:hover { background: var(--bg-panel-raised); }
  .market-level.sell:hover { border-color: var(--success); } /* clicking a sell order = buying */
  .market-level.buy:hover { border-color: var(--error); }   /* clicking a buy order = selling */
  .market-level.sell span:first-child { color: var(--error); }
  .market-level.buy span:first-child { color: var(--success); }
  .market-empty-side { color: var(--text-muted); font-size: 12px; padding: 4px 6px; text-align: center; }
  .market-hint { color: var(--text-muted); font-size: 11px; margin-top: 8px; text-align: center; }
    .market-trade { display: flex; justify-content: space-between; font-size: 12px; color: var(--text-muted); padding: 2px 6px; font-variant-numeric: tabular-nums; }
  .market-result { font-size: 12px; margin: -4px 0 10px; color: var(--success); }
  .market-result.error { color: var(--error); }

  /* The buy / sell popup */
  .market-popup-have { font-size: 12px; color: var(--text-muted); margin: -8px 0 12px; }
  .market-inputs { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
  .market-inputs label { font-size: 12px; color: var(--text-muted); display: flex; flex-direction: column; gap: 4px; min-width: 0; }
  .market-inputs input { width: 100%; box-sizing: border-box; min-width: 0; background: var(--bg-void); border: 1px solid var(--border); border-radius: 5px; padding: 7px 8px; font-size: 13px; color: var(--text-primary); font-family: inherit; }
  .market-max { background: none; border: none; color: var(--accent); font-size: 11px; cursor: pointer; padding: 0; font-family: inherit; align-self: flex-start; }
  .market-preview { font-size: 12px; color: var(--text-muted); margin: 10px 0 6px; min-height: 16px; }
  .market-popup-error { font-size: 12px; color: var(--error); min-height: 16px; margin-bottom: 6px; }

  /* My sell orders / My buy orders: two sections stacked in the 260px
     sidebar (see .market-my-orders-block), each a plain list of one-line
     rows -- side is said once by the section title, not repeated per row. */
  .market-my-orders-section { margin-bottom: 20px; }
  .market-my-orders-section:last-child { margin-bottom: 0; }
  .market-my-orders-section-title { font-size: 13px; font-weight: 600; margin: 0 0 8px; text-align: center; }
  .market-my-orders-section-title.sell { color: var(--error); }
  .market-my-orders-section-title.buy { color: var(--success); }
  .market-my-orders-section .empty-note { text-align: center; } /* just "-- None --" here, not the shared .empty-note default elsewhere */
  /* Item | Qty | Price columns, plus a small cancel icon that isn't part
     of the column grid (the header row has no 4th label for it). */
  .market-my-orders-head, .market-my-order { display: grid; grid-template-columns: 1fr 44px 44px 20px; column-gap: 6px; align-items: center; }
  .market-my-orders-head { font-size: 10px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; padding: 0 0 4px; border-bottom: 1px solid var(--border); margin-bottom: 2px; }
  .market-my-orders-head span:not(:first-child) { text-align: right; }
  .market-my-order { font-size: 12px; padding: 5px 0; border-bottom: 1px solid rgba(255,255,255,0.04); }
  .market-my-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .market-my-qty, .market-my-price { text-align: right; color: var(--text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .market-my-cancel {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    text-align: right;
  }
  .market-my-cancel:hover { color: var(--error); }

  /* Inventory hover tooltip (inventory.js) */
  .item-tip {
    display: none;
    position: fixed;
    z-index: 2500;
    max-width: 300px;
    padding: 10px 12px;
    background: var(--bg-panel-raised);
    border: 1px solid rgba(212,162,76,0.5);
    border-radius: 6px;
    box-shadow: 0 6px 20px rgba(0,0,0,0.5);
    font-size: 12px;
    line-height: 1.5;
    pointer-events: none;
  }
  .tip-icon { display: block; width: 120px; height: auto; border-radius: 4px; margin-bottom: 8px; }
  .tip-name { font-size: 14px; font-weight: 600; margin-bottom: 4px; }
  .tip-line { color: var(--text-primary); }
  .tip-label { color: var(--text-muted); }
  .tip-bonus { color: var(--accent); }
  .tip-desc { color: var(--text-muted); font-style: italic; margin-top: 2px; }
  .tip-rule { height: 1px; background: var(--border); margin: 6px 0; }
  .tip-hint { color: var(--text-muted); font-size: 11px; margin-top: 6px; }

  /* Side panel quest tracker (quests.js) */
  .quest-tracker-row, .quest-tracker-link {
    display: block;
    width: 100%;
    background: none;
    border: none;
    padding: 6px 0;
    text-align: left;
    font-family: inherit;
    color: inherit;
    cursor: pointer;
    border-bottom: 1px solid rgba(255,255,255,0.04);
  }
  .quest-tracker-row:hover .quest-tracker-name { color: var(--accent); }
  .quest-tracker-top { display: flex; justify-content: space-between; gap: 8px; font-size: 13px; }
  .quest-tracker-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .quest-tracker-count { color: var(--text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; font-size: 12px; }
  .quest-tracker-row.done .quest-tracker-count { color: var(--accent); font-weight: 600; }
  .quest-tracker-bar { display: block; height: 3px; margin-top: 5px; border-radius: 2px; background: rgba(255,255,255,0.08); overflow: hidden; }
  .quest-tracker-fill { display: block; height: 100%; background: var(--accent); transition: width 0.3s ease; }
  .quest-tracker-empty { font-size: 12px; color: var(--text-muted); }
  .quest-tracker-link:hover { color: var(--accent); }

  /* Quests view (quests.js) */
  .quest-count { color: var(--text-muted); font-weight: 400; font-size: 14px; }
  .quest-note { color: var(--text-muted); font-size: 12px; margin: -6px 0 12px; }
  .quest-row {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 12px 0;
    border-bottom: 1px solid var(--border);
  }
  .quest-row:last-of-type { border-bottom: none; }
  .quest-main { flex: 1; min-width: 0; }
  .quest-name { font-weight: 600; }
  .quest-done-count { color: var(--text-muted); font-weight: 400; font-size: 12px; margin-left: 6px; }
  .quest-desc { color: var(--text-muted); font-size: 13px; margin-top: 2px; }
  .quest-reward { font-size: 12px; color: var(--accent); margin-top: 6px; }
  .quest-progress { display: flex; align-items: center; gap: 10px; margin-top: 8px; max-width: 360px; }
  .quest-progress .timer-track { flex: 1; }
  .quest-progress .timer-fill { transition: width 0.3s ease; }
  .quest-progress-text { font-size: 12px; color: var(--text-muted); white-space: nowrap; }
  .quest-buttons { display: flex; gap: 8px; align-items: center; }
  .quest-buttons .btn { padding: 6px 14px; font-size: 13px; }
  .quest-buttons .btn[disabled] { opacity: 0.45; cursor: default; }
  .quest-error { color: var(--error); font-size: 12px; min-height: 16px; margin-top: 8px; }

  /* Problem warning under the status bar row (statusbar.js): the
     server is struggling (warn), or can't be reached at all (error). */
  .status-bar-warning {
    margin-top: 10px;
    padding: 8px 12px;
    border-radius: 6px;
    border: 1px solid var(--warn);
    background: rgba(212,162,76,0.12);
    font-size: 13px;
    line-height: 1.4;
  }

  .status-bar-warning strong {
    color: var(--warn);
  }

  .status-bar-warning.status-bar-warning-info {
    border-color: var(--accent);
    background: rgba(212,162,76,0.06);
  }

  .status-bar-warning.status-bar-warning-info strong {
    color: var(--text-primary);
  }

  .status-bar-warning.status-bar-warning-error {
    border-color: var(--error);
    background: rgba(193,82,74,0.14);
  }

  .status-bar-warning.status-bar-warning-error strong {
    color: var(--error);
  }

  button.status-bar-queue {
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    font-family: inherit;
    text-decoration: underline dotted;
    text-underline-offset: 3px;
  }

  .queue-panel {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 900;
    width: 320px;
    max-width: 100%;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 10px 12px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.4);
  }

  .queue-panel-title {
    font-size: 12px;
    color: var(--text-muted);
    margin-bottom: 6px;
  }

  .queue-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 0;
    border-top: 1px solid rgba(255,255,255,0.06);
    font-size: 13px;
  }

  .queue-row-tag {
    font-size: 11px;
    color: var(--text-muted);
    min-width: 30px;
  }

  .queue-row.active .queue-row-tag {
    color: var(--accent);
    font-weight: 600;
  }

  .queue-row-label {
    flex: 1;
  }

  .queue-row-note {
    font-size: 11px;
    color: var(--text-muted);
    font-style: italic;
  }

  .queue-row-count {
    color: var(--text-muted);
    white-space: nowrap;
  }

  .queue-row-controls {
    display: flex;
    gap: 4px;
  }

  .queue-btn {
    background: var(--bg-panel-raised);
    border: 1px solid var(--border);
    border-radius: 4px;
    width: 24px;
    height: 24px;
    padding: 0;
    font-size: 13px;
    line-height: 1;
    color: var(--text-primary);
    cursor: pointer;
    font-family: inherit;
  }

  .queue-btn:disabled {
    opacity: 0.3;
    cursor: default;
  }

  .queue-btn-remove:hover {
    border-color: var(--error);
    color: var(--error);
  }

  .queue-panel-error {
    color: var(--error);
    font-size: 12px;
  }

  .queue-panel-error:not(:empty) {
    margin-top: 6px;
  }

  .status-bar-stop {
    background: var(--bg-panel-raised);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 4px 12px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-primary);
    cursor: pointer;
    font-family: inherit;
  }

  .combat-card {
    background: var(--bg-panel);
    border: 1px solid rgba(212,162,76,0.35);
    border-radius: 8px;
    padding: 24px;
    position: relative;
    box-shadow: 0 0 0 1px rgba(212,162,76,0.08), 0 0 24px -6px rgba(212,162,76,0.35), inset 0 0 40px -20px rgba(212,162,76,0.15);
  }
  /* Page titles: center the heading that leads a card (Market, Inventory,
     Quests, Settings, etc). Only matches an h2 that's a direct child of the
     card, so it doesn't touch a title still sharing a flex row with a
     search box (.inv-header) -- see the Inventory note below. */
  .combat-card > h2:first-child { text-align: center; }

  .combat-card::before, .combat-card::after,
  .log-card::before, .log-card::after {
    content: "";
    position: absolute;
    width: 14px;
    height: 14px;
    pointer-events: none;
  }
  .combat-card::before, .log-card::before { top: -1px; left: -1px; border-top: 2px solid var(--accent); border-left: 2px solid var(--accent); }
  .combat-card::after, .log-card::after { bottom: -1px; right: -1px; border-bottom: 2px solid var(--accent); border-right: 2px solid var(--accent); }

  .combat-row {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 24px;
  }

  .combatant {
    text-align: center;
  }

  .combatant.enemy { text-align: center; }

  .combatant-name {
    font-size: 14px;
    color: var(--text-muted);
    margin-bottom: 4px;
  }

  .combatant-portrait {
    width: 88px;
    height: 88px;
    margin: 0 auto 6px;
    border-radius: 6px;
    background: var(--bg-panel-raised);
    border: 1px solid var(--accent);
    box-shadow: 0 0 0 3px rgba(212,162,76,0.12), 0 0 14px -2px rgba(212,162,76,0.4);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 34px;
    overflow: hidden;
  }
  .combatant-portrait .portrait-img { width: 100%; height: 100%; object-fit: contain; padding: 3px; box-sizing: border-box; }
  .portrait-img.item-icon-missing { width: 70%; height: 70%; font-size: 36px; }

  .hp-bar {
    height: 10px;
    border-radius: 4px;
    background: var(--bg-void);
    overflow: hidden;
    border: 1px solid rgba(212,162,76,0.3);
    position: relative;
    box-shadow: 0 0 6px -1px rgba(212,162,76,0.25);
  }

  .hp-bar::after {
    content: "";
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(90deg, transparent 0, transparent calc(10% - 1px), var(--bg-void) calc(10% - 1px), var(--bg-void) 10%);
    pointer-events: none;
  }

  .hp-fill { height: 100%; }
  .hp-fill.player { background: var(--hp-player); width: 82%; }
  .hp-fill.monster { background: var(--hp-monster); width: 41%; }

  .hp-label {
    font-size: 12px;
    color: var(--text-muted);
    margin-top: 4px;
    font-variant-numeric: tabular-nums;
  }

  .hit-chance-row {
    font-size: 12px;
    color: var(--text-muted);
    margin-top: 3px;
    font-variant-numeric: tabular-nums;
  }

  .hit-chance-row span { color: var(--text-primary); }

  .rating-breakdown {
    font-size: 11px;
    opacity: 0.75;
  }

  .vs-mark {
    font-size: 13px;
    color: var(--text-muted);
  }

  .stance-toggle {
    display: flex;
    gap: 8px;
    margin-top: 14px;
  }

  /* Stance row: auto-eat food slots centred in the space left of the stance
     buttons, the buttons themselves dead centre (the right column is an empty
     balance), so the food doesn't push them off-centre. */
  .stance-row {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    column-gap: 12px;
    margin-top: 10px;
  }
  .stance-row .stance-toggle { margin-top: 0; }
  .stance-food { display: flex; justify-content: center; flex-wrap: wrap; gap: 10px; }
  .stance-food .food-slot { width: 44px; height: 44px; }
  .stance-food .food-slot-img { width: 34px; max-height: 34px; }

  .stance-btn {
    background: var(--bg-panel-raised);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 8px 16px;
    font-size: 13px;
    color: var(--text-muted);
    cursor: pointer;
    font-family: inherit;
  }

  .stance-btn:hover { color: var(--text-primary); border-color: var(--accent-dim); }

  .stance-btn.active {
    color: #201607;
    background: var(--accent);
    border-color: var(--accent);
    font-weight: 600;
  }

  .attack-timers {
    margin-top: 12px;
    display: flex;
    flex-direction: column;
    gap: 6px;
  }

  /* Waiting to respawn after a death: the fight display stays exactly
     where it is (so the layout doesn't jump), grayed out, with the
     countdown over it. */
  #fight-display { position: relative; }
  #fight-display .respawn-overlay {
    display: none;
    position: absolute;
    inset: 0;
    z-index: 2;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    font-size: 22px;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--text-muted, #aaa);
  }
  #fight-display.respawning .respawn-overlay,
  #fight-display.idle .respawn-overlay { display: flex; }
  #fight-display.respawning .combat-row,
  #fight-display.respawning .attack-timers,
  #fight-display.idle .combat-row,
  #fight-display.idle .attack-timers { opacity: 0.35; filter: grayscale(1); }

  .area-monster-picker {
    display: flex;
    margin-top: 16px;
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
    min-height: 320px;
  }

  .area-monster-picker.compact {
    min-height: 160px;
  }
  .area-monster-picker.compact .area-list { max-height: 160px; }
  .area-monster-picker.compact .monster-card { width: 137px; padding: 20px 4px 20px; }
  .area-monster-picker.compact .monster-card-icon { font-size: 54px; margin-bottom: 4px; }
  .area-monster-picker.compact .monster-card-name { font-size: 12px; }
  .area-monster-picker.compact .area-item { padding: 7px 12px; font-size: 12px; }

  .area-list {
    width: 150px;
    flex-shrink: 0;
    background: var(--bg-void);
    border-right: 1px solid var(--border);
    overflow-y: auto;
    max-height: 220px;
  }

  .area-item {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    padding: 10px 14px;
    font-size: 13px;
    color: var(--text-muted);
    cursor: pointer;
    font-family: inherit;
    border-left: 2px solid transparent;
  }
  /* .area-item hover/active: shared with .nav-item, see the sidebar section. */

  .monster-grid {
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    gap: 10px;
    padding: 14px;
  }

  .monster-card {
    width: 187px;
    padding: 26px 8px 20px;
    background: var(--bg-panel-raised);
    border: 1px solid var(--border);
    border-radius: 8px;
    text-align: center;
    cursor: pointer;
  }
  .monster-card:hover { border-color: var(--accent-dim); }
  .monster-card.active { border-color: var(--accent); background: rgba(212,162,76,0.1); }
  .monster-card-icon { font-size: 80px; line-height: 1.15; margin-bottom: 8px; }
  .monster-card-name { font-size: 13px; color: var(--text-primary); line-height: 1.3; }
  .monster-card-img { display: block; width: 100%; height: 110px; object-fit: contain; pointer-events: none; }
  .monster-card-img.item-icon-missing { display: flex; width: 80px; height: 80px; margin: 0 auto; font-size: 40px; }
  .monster-tip-img { display: block; width: 130px; height: 130px; object-fit: contain; margin: 0 auto 8px; }
  .monster-tip-img.item-icon-missing { display: flex; font-size: 56px; }

  .skill-grid {
    display: grid;
    grid-template-columns: repeat(4, 144px);
    gap: 24px;
    justify-content: center;
    padding: 12px 0;
  }
  /* The item column of a split view (smithing gear): more, slightly smaller cards per row. */
  .skill-grid.skill-grid-tight { gap: 12px; }
  .skill-grid-tight .skill-card { padding: 12px 6px 18px; }
  .skill-grid-tight .skill-card-icon { font-size: 44px; }
  .skill-grid-tight .skill-card-img { height: 52px; }
  .skill-grid-tight .skill-card-name { font-size: 13px; overflow-wrap: anywhere; }
  .skill-grid-tight .skill-card-level { font-size: 15px; margin-bottom: 8px; }
  .skill-grid-tight .skill-card-mats { font-size: 12px; }
  .skill-card {
    padding: 16px 10px 26px;
    background: var(--bg-panel-raised);
    border: 1px solid var(--border);
    border-radius: 8px;
    text-align: center;
    cursor: pointer;
  }
  .skill-card:hover { border-color: var(--accent-dim); }
  .skill-card.locked { opacity: 0.4; cursor: default; }
  .skill-card.locked:hover { border-color: var(--border); }
  .skill-card-icon { font-size: 52px; line-height: 1.1; margin-bottom: 8px; }
  /* A real picture instead of the emoji: same slot, roughly the same height. */
  .skill-card-img { display: block; margin: 0 auto; height: 64px; width: auto; max-width: 100%; object-fit: contain; border-radius: 4px; }
  .skill-card-name { font-size: 15px; font-weight: 700; color: #f4efe6; line-height: 1.25; }
  .skill-card-level { font-size: 17px; font-weight: 800; letter-spacing: 0.5px; color: #ffd98a; text-shadow: 0 1px 3px rgba(0,0,0,0.9); margin: 2px 0 14px; }
  .skill-card.locked .skill-card-level { color: var(--hp-monster); }
  .skill-card-mats { margin-top: 8px; font-size: 13px; font-weight: 600; color: #d6d0c4; line-height: 1.4; }
  .skill-card-mats .short { color: #ff7a6b; }
  .skill-tooltip {
    position: fixed; z-index: 1000; pointer-events: none;
    background: var(--bg-panel); border: 1px solid var(--border); border-radius: 8px;
    padding: 12px; min-width: 180px; max-width: 260px; font-size: 12px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.4);
  }
  .skill-tip-name { font-weight: 700; margin-bottom: 2px; }
  .skill-tip-muted { color: var(--text-muted); }

  .timer-row {
    display: grid;
    grid-template-columns: 110px 1fr 54px;
    align-items: center;
    gap: 12px;
    font-size: 12px;
    color: var(--text-muted);
  }

  .timer-track {
    height: 6px;
    border-radius: 3px;
    background: var(--bg-void);
    border: 1px solid var(--border);
    overflow: hidden;
  }

  .timer-fill {
    height: 100%;
    background: var(--accent);
    width: 0%;
  }

  .timer-fill.monster-speed { background: var(--hp-monster); }

  @keyframes fill-loop {
    from { width: 0%; }
    to { width: 100%; }
  }

  @media (prefers-reduced-motion: reduce) {
    .timer-fill { animation: none; width: 60%; }
  }

  /* ---------- Admin view (merged from admin.html, for in-shell loading) ---------- */

  /* Admin tab pages (admin-*.html) are loaded as fragments into
     #admin-tab-content -- their own <style> blocks never apply, so
     everything they need lives here. */
  #admin-tab-content h1 { margin: 0 0 24px; font-size: 24px; }
  .stat-note { font-size: 11px; color: var(--text-muted); margin-top: 6px; }
  .section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
  .section-head h2 { margin: 0; font-size: 16px; }
  .reset-btn { background: var(--bg-panel-raised); border: 1px solid var(--border); color: var(--text-muted); border-radius: 6px; padding: 7px 14px; font-size: 12px; cursor: pointer; font-family: inherit; }
  .reset-btn:hover { color: var(--text-primary); border-color: var(--error); }
  table.query-table { width: 100%; border-collapse: collapse; font-size: 12px; background: var(--bg-panel); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
  table.query-table th, table.query-table td { padding: 8px 12px; text-align: left; border-bottom: 1px solid var(--border); }
  table.query-table th { color: var(--text-muted); font-weight: 600; cursor: pointer; user-select: none; white-space: nowrap; }
  table.query-table th:hover { color: var(--text-primary); }
  table.query-table th.sorted { color: var(--accent); }
  table.query-table td.num { font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
  table.query-table td.query-text { font-family: "Cascadia Code", Consolas, monospace; color: var(--text-primary); max-width: 640px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  table.query-table tr:last-child td { border-bottom: none; }
  table.query-table tr:hover td { background: rgba(255,255,255,0.02); }

  .nav-group-label {
    padding: 14px 20px 6px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
  }

  .nav-item.sub { padding-left: 34px; font-size: 13px; }

  /* Combat group: the sub-skills open the combat view and fold away
     under the Combat button's chevron (shell.js). */
  .nav-item.combat-sub { cursor: pointer; }
  .nav.combat-collapsed .combat-sub { display: none; }
  .nav-collapse {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    margin-right: -4px;
    border-radius: 4px;
    font-size: 13px;
    line-height: 1;
    color: var(--text-muted);
    cursor: pointer;
    transition: transform 0.2s ease, color 0.15s;
  }
  .nav-collapse:hover, .nav-collapse:focus-visible { color: var(--text-primary); background: rgba(255,255,255,0.06); outline: none; }
  .nav.combat-collapsed .nav-collapse { transform: rotate(-90deg); }

  #view-container {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 20px;
    overflow-y: auto;
  }

  /* The view fills the game column down to the chat: its last main
     card grows into the leftover height (Quests has two cards -- the
     board grows). Combat is left alone: its log card already fills
     the space and scrolls inside. Taller content still scrolls. */
  #view-container > .combat-card:not(:has(~ .combat-card, ~ .log-card)) {
    flex: 1 0 auto;
  }

  /* Combat: the extra height goes to the picker row (areas | monsters
     | log), so the log gets taller on a taller window. */
  #view-container > .combat-card:has(#area-monster-picker) {
    display: flex;
    flex-direction: column;
  }
  #view-container > .combat-card:has(#area-monster-picker) > .area-monster-picker {
    flex: 1 0 auto;
  }

  /* The combat/drop log, as the picker's right-hand column. Its lines
     take whatever height the row has (contain: size keeps a long log
     from stretching the row) and scroll inside. */
  .area-monster-picker:has(.picker-log) { min-height: 200px; }
  /* Monster cards: exactly 4 per row (an area has at most 8 monsters), and
     room for 2 rows (2 x 92px cards, the gap and the padding); more monsters
     scroll inside the grid. */
  .area-monster-picker.compact:has(.picker-log) { min-height: 216px; }
  .area-monster-picker.compact .monster-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-auto-rows: 92px;
    align-content: start;
    gap: 8px;
    padding: 10px;
    overflow-y: auto;
    contain: size;
  }
  .area-monster-picker.compact .monster-grid .monster-card {
    width: auto;
    height: 92px;
    box-sizing: border-box;
    padding: 8px 4px 6px;
  }
  /* Picture + name sit as one block in the middle of the card, not stuck to the top. */
  .area-monster-picker.compact .monster-grid .monster-card { display: flex; flex-direction: column; align-items: center; justify-content: center; }
  .area-monster-picker.compact .monster-grid .monster-card-icon { width: 100%; margin-bottom: 4px; }
  .area-monster-picker.compact .monster-grid .monster-card-img { height: 46px; }
  .area-monster-picker.compact .monster-grid .monster-card-img.item-icon-missing { width: 42px; height: 42px; font-size: 22px; }
  /* Names like "Blighted Farmhand" can wrap: keep to two lines so the card never overflows. */
  .area-monster-picker.compact .monster-grid .monster-card-name { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.2; }
  /* The area list runs the full height of the row and scrolls inside
     it when there are many areas (contain: size keeps a long list from
     stretching the row). Overrides the old 220px / 130px caps. */
  .area-monster-picker:has(.picker-log) .area-list,
  .area-monster-picker.compact:has(.picker-log) .area-list {
    max-height: none;
    contain: size;
    overflow-y: auto;
  }
  /* Areas not open yet (areas.is_active = 0): listed, dimmed, tagged. */
  .area-item.coming-soon { opacity: 0.55; }
  .area-soon {
    margin-left: 4px;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
  }
  /* "Not open yet" / "no monsters" notice: big and faded, centred over the
     whole monster area -- the same look as "Select a monster to fight". */
  .monster-grid { position: relative; }
  .monster-grid-empty {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    padding: 0 24px; text-align: center;
    font-size: 22px; font-weight: 600; letter-spacing: 0.04em;
    color: var(--text-muted); opacity: 0.55;
    pointer-events: none;
  }
  .picker-log {
    flex: 0 0 38%;
    min-width: 240px;
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding: 10px 14px;
    border-left: 1px solid var(--border);
    background: rgba(0,0,0,0.18);
  }
  .picker-log .log-tabs { flex-shrink: 0; }
  .picker-log .log-lines {
    flex: 1;
    min-height: 0;
    contain: size;
    overflow-y: auto;
    margin-top: 8px;
  }

  /* "Loading…" placeholders stay invisible for their first 0.4s: data
     usually arrives before that, so nothing flashes. On a slow
     connection they still show. */
  .loading-note { animation: loading-note-appear 0s linear 0.4s both; }
  @keyframes loading-note-appear { from { visibility: hidden; } to { visibility: visible; } }

  .breadcrumb { font-size: 12px; color: var(--text-muted); margin-bottom: 6px; }
  .breadcrumb strong { color: var(--text-primary); }

  .admin-header-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 24px;
  }
  .admin-header-row h1 { margin: 0; font-size: 24px; }

  .account-badge { display: flex; align-items: center; gap: 10px; }
  .avatar {
    width: 34px; height: 34px;
    border-radius: 50%;
    background: var(--accent);
    color: #201607;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 13px;
  }
  .account-name { font-size: 13px; font-weight: 600; }
  .account-role { font-size: 11px; color: var(--text-muted); }

  .stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 24px; }
  .stat-card { background: var(--bg-panel); border: 1px solid var(--border); border-radius: 8px; padding: 16px 18px; }
  .stat-label { font-size: 12px; color: var(--text-muted); margin-bottom: 8px; }
  .stat-value { font-size: 24px; font-weight: 700; font-variant-numeric: tabular-nums; }
  .stat-trend { font-size: 12px; margin-top: 6px; }
  .stat-trend.up { color: var(--success); }
  .stat-trend.down { color: var(--hp-monster); }
  .stat-trend.neutral { color: var(--text-muted); }

  .admin-columns { display: grid; grid-template-columns: 1fr 300px; gap: 18px; align-items: start; }
  .panel-card { background: var(--bg-panel); border: 1px solid var(--border); border-radius: 8px; margin-bottom: 18px; overflow: hidden; }
  .panel-card-header { display: flex; justify-content: space-between; padding: 14px 18px; border-bottom: 1px solid var(--border); font-weight: 600; font-size: 14px; }
  .panel-card-header .muted { color: var(--text-muted); font-weight: 400; font-size: 12px; }

  .admin-table { width: 100%; border-collapse: collapse; }
  .admin-table th { text-align: left; font-size: 11px; text-transform: uppercase; color: var(--text-muted); padding: 10px 18px; border-bottom: 1px solid var(--border); }
  .admin-table td { padding: 12px 18px; border-bottom: 1px solid var(--border); font-size: 13px; vertical-align: middle; }
  .admin-table tr:last-child td { border-bottom: none; }
  .muted { color: var(--text-muted); font-size: 12px; }

  .tag { display: inline-block; padding: 3px 9px; border-radius: 5px; font-size: 11px; border: 1px solid; }
  .tag-warn { color: var(--accent); border-color: var(--accent); background: rgba(212,162,76,0.08); }
  .tag-danger { color: var(--hp-monster); border-color: var(--hp-monster); background: rgba(193,82,74,0.08); }
  .tag-info { color: var(--success); border-color: var(--success); background: rgba(79,158,106,0.08); }

  .btn-sm { background: var(--bg-panel-raised); border: 1px solid var(--border); color: var(--text-primary); border-radius: 5px; padding: 5px 10px; font-size: 12px; cursor: pointer; margin-right: 6px; }
  .btn-sm:hover { border-color: var(--accent); }
  .btn-danger { border-color: var(--hp-monster); color: var(--hp-monster); }
  .btn-danger:hover { background: rgba(193,82,74,0.1); }

  .callout { margin: 0 18px 18px; padding: 12px 14px; border-left: 3px solid var(--accent); background: rgba(212,162,76,0.06); font-size: 12px; color: var(--text-muted); border-radius: 0 6px 6px 0; }

  .quick-action { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; background: none; border: none; border-bottom: 1px solid var(--border); padding: 14px 18px; color: var(--text-primary); cursor: pointer; font-family: inherit; }
  .quick-action:last-child { border-bottom: none; }
  .quick-action:hover { background: rgba(255,255,255,0.03); }
  .quick-action:disabled { opacity: 0.45; cursor: default; }
  .quick-action:disabled:hover { background: none; }
  .qa-icon { width: 30px; height: 30px; border-radius: 6px; background: var(--bg-panel-raised); display: flex; align-items: center; justify-content: center; font-size: 14px; flex-shrink: 0; }
  .qa-title { font-size: 13px; font-weight: 600; }
  .qa-sub { font-size: 11px; color: var(--text-muted); }

  .log-entry { padding: 10px 18px; border-bottom: 1px solid var(--border); font-size: 12px; line-height: 1.6; color: var(--text-muted); }
  .log-entry:last-child { border-bottom: none; }
  /* Overview's recent admin actions: ~10 rows tall, the rest (up to 30) scrolls. */
  #admin-recent-actions { max-height: 370px; overflow-y: auto; }
  .log-time { color: var(--text-muted); margin-right: 6px; font-variant-numeric: tabular-nums; }
  .log-actor { color: var(--accent); font-weight: 600; }
  .log-entry strong { color: var(--text-primary); }

  .log-card {
    background: var(--bg-panel);
    border: 1px solid rgba(212,162,76,0.35);
    border-radius: 8px;
    padding: 16px 20px;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    position: relative;
    box-shadow: 0 0 0 1px rgba(212,162,76,0.08), 0 0 20px -8px rgba(212,162,76,0.3);
  }
  /* .log-card corner brackets: shared with .combat-card, see above. */

  .log-tabs {
    display: flex;
    gap: 4px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 10px;
  }

  .log-tab {
    background: none;
    border: none;
    padding: 6px 12px 8px;
    font-size: 13px;
    color: var(--text-muted);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    font-family: inherit;
  }

  .log-tab.active {
    color: var(--text-primary);
    border-bottom-color: var(--accent);
  }

  .log-lines {
    flex: 1;
    min-height: 0;
    font-size: 13px;
    line-height: 1.7;
    color: var(--text-muted);
    overflow-y: auto;
  }

  .log-lines .hit { color: var(--text-primary); }
  .log-lines .dmg-in { color: var(--hp-monster); }
  .log-lines .dmg-out { color: var(--hp-player); }

  /* ---------- Right panel ---------- */

  .panel {
    grid-area: panel;
    background: var(--bg-panel);
    border-left: 1px solid var(--border);
    width: 260px;
    overflow: hidden;
    position: relative;
    transition: width 0.25s ease;
  }

  body.panel-collapsed .panel {
    width: 44px;
  }

  .panel-toggle {
    position: absolute;
    top: 16px;
    left: 10px;
    width: 24px;
    height: 24px;
    border-radius: 5px;
    border: 1px solid var(--border);
    background: var(--bg-panel-raised);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: 12px;
    color: var(--text-muted);
  }

  .panel-toggle:hover { color: var(--text-primary); }

  .panel-body {
    padding: 16px 20px 16px 46px;
    white-space: nowrap;
  }

  body.panel-collapsed .panel-body {
    opacity: 0;
    pointer-events: none;
  }

  /* Side panel: the character you're playing, above the quest tracker */
  .panel-identity {
    text-align: center;
    padding: 12px 10px 14px;
    margin-bottom: 14px;
    border: 1px solid rgba(212,162,76,0.35);
    border-radius: 8px;
    background: linear-gradient(to bottom, rgba(212,162,76,0.10), rgba(212,162,76,0.02));
  }
  .panel-identity-name { font-size: 18px; font-weight: 700; color: var(--accent); letter-spacing: 0.02em; overflow-wrap: anywhere; }
  .panel-identity-mode {
    display: inline-block;
    margin-top: 6px;
    padding: 2px 10px;
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
  }
  .panel-identity-mode:empty { display: none; }

  .panel-section {
    margin-bottom: 22px;
  }

  /* Side panel headings: centered, gold, framed by fading rules. */
  .panel-section-title {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: 12px;
  }

  .panel-section-title::before,
  .panel-section-title::after {
    content: '';
    flex: 1;
    height: 1px;
  }
  .panel-section-title::before { background: linear-gradient(to right, transparent, rgba(212,162,76,0.4)); }
  .panel-section-title::after { background: linear-gradient(to left, transparent, rgba(212,162,76,0.4)); }

  #quest-tracker-count {
    color: var(--text-muted);
    font-weight: 400;
    letter-spacing: 0.04em;
    margin-left: -4px;
  }

  .stat-row {
    display: flex;
    justify-content: space-between;
    font-size: 13px;
    padding: 5px 0;
    border-bottom: 1px solid rgba(255,255,255,0.04);
  }

  .stat-row span:last-child {
    font-variant-numeric: tabular-nums;
    color: var(--text-primary);
  }

  .equip-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-areas:
      ".     head  ."
      ".     neck  ."
      "main  chest off"
      "ring1 legs  ring2"
      ".     feet  .";
    gap: 8px;
    justify-items: center;
    padding: 4px 0;
  }
  .equip-slot {
    width: 38px;
    height: 38px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--bg-panel-raised);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    cursor: pointer;
  }
  .equip-slot:hover { border-color: var(--accent-dim); }

  .enchant-slot {
    width: 100px;
    height: 100px;
    border: 2px solid var(--border);
    border-radius: 10px;
    background: var(--bg-panel-raised);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 36px;
    cursor: pointer;
    flex-shrink: 0;
  }
  .enchant-slot:hover { border-color: var(--accent-dim); }
  .enchant-slot.filled { border-color: var(--accent); border-style: solid; }

  .enchant-item-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 4px;
    border-bottom: 1px solid rgba(255,255,255,0.06);
    cursor: pointer;
    font-size: 13px;
  }
  .enchant-item-row:hover { background: var(--bg-panel-raised); }
  .equip-slot.filled { border-color: var(--accent); }
  /* An empty slot reads as empty: ghosted glyph of what goes there (and a
     dashed frame in themes that draw a border), against a filled slot's
     full-colour icon and highlighted frame. */
  .equip-empty { opacity: 0.3; filter: grayscale(1); pointer-events: none; }
  .equip-slot:not(.filled) { border-style: dashed; }

  .equip-tabs { display: flex; gap: 4px; justify-content: center; margin: 0 0 8px; }
  .equip-tab { flex: 1; padding: 4px 10px; }

  .equip-icon { width: 85%; height: 85%; object-fit: contain; pointer-events: none; }

  /* Item with no icon assigned: deliberately ugly so it gets noticed. */
  .item-icon-missing {
    display: inline-flex; align-items: center; justify-content: center;
    box-sizing: border-box; flex: none;
    background: repeating-linear-gradient(45deg, #ff00cc 0 6px, #7a0066 6px 12px);
    border: 2px dashed #ffee00; border-radius: 4px;
    color: #fff; font: 900 16px/1 sans-serif; text-shadow: 0 0 3px #000, 0 0 3px #000;
    pointer-events: none;
  }
  .inv-icon.item-icon-missing { width: 28px; height: 28px; }
  .tip-icon.item-icon-missing { display: flex; width: 120px; height: 120px; font-size: 56px; margin-bottom: 8px; }
  .equip-icon.item-icon-missing { width: 85%; height: 85%; font-size: 20px; }

  .food-slot-grid {
    display: flex;
    justify-content: center;
    gap: 8px;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--border);
  }
  .food-slot {
    width: 38px;
    height: 38px;
    border: 1px dashed var(--border);
    border-radius: 6px;
    background: var(--bg-panel-raised);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    cursor: pointer;
    color: var(--text-muted);
    position: relative;
  }
  .food-slot:hover { border-color: var(--accent-dim); }
  .food-slot.filled { border-style: solid; border-color: var(--success); }
  .food-slot.on-cooldown { border-color: var(--border); }
  .food-slot.on-cooldown .food-slot-icon { opacity: 0.25; }
  .food-slot.on-cooldown .food-slot-qty { opacity: 0.25; }
  /* The food's picture in a slot (~4:3, so width-limited to fit the 38px box). */
  .food-slot-img { display: block; width: 30px; height: auto; max-height: 30px; object-fit: contain; border-radius: 3px; }
  /* Auto-eat picker: one tile per food you own -- picture, name, heal. */
  .food-pick-grid { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
  .food-pick {
    width: 96px;
    box-sizing: border-box;
    padding: 10px 6px 8px;
    text-align: center;
    cursor: pointer;
    background: var(--bg-panel-raised);
    border: 1px solid var(--border);
    border-radius: 6px;
  }
  .food-pick:hover { border-color: var(--accent-dim); filter: brightness(1.15); }
  .food-pick-img { display: block; width: 56px; height: auto; margin: 0 auto 6px; border-radius: 4px; }
  .food-pick-img.item-icon-missing { display: flex; width: 56px; height: 56px; margin: 0 auto 6px; font-size: 28px; }
  .food-pick-emoji { display: block; font-size: 36px; margin-bottom: 6px; }
  .food-pick-name { font-size: 12px; line-height: 1.2; }
  .food-pick-heal { font-size: 11px; color: var(--success); margin-top: 2px; }
  .food-slot-cooldown {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 15px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: #ffffff;
    background: rgba(0,0,0,0.7);
    border-radius: 5px;
    z-index: 1;
  }
  .food-slot-qty {
    position: absolute;
    bottom: -6px;
    right: -6px;
    background: var(--bg-void);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 0 4px;
    font-size: 10px;
    font-variant-numeric: tabular-nums;
    color: var(--text-primary);
    line-height: 1.4;
    z-index: 2;
  }

  /* ---------- Chat ---------- */

  .chat {
    grid-area: chat;
    background: var(--bg-panel);
    border-top: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .chat-tabs {
    display: flex;
    gap: 4px;
    padding: 8px 16px 0;
    border-bottom: 1px solid var(--border);
  }

  .chat-tab {
    position: relative;
    background: none;
    border: none;
    padding: 8px 14px;
    font-size: 13px;
    color: var(--text-muted);
    cursor: pointer;
    border-bottom: 2px solid transparent;
  }

  /* A message arrived on a tab you're not currently viewing (see
     markUnread/switchChatTab in chat.js) -- a small dot, cleared the
     moment you switch to that tab. Lives here (the base layer) rather
     than a theme file so every theme gets it via var(--accent). */
  .chat-tab.unread::after {
    content: '';
    position: absolute;
    top: 6px;
    right: 4px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent);
  }

  .chat-tab.active {
    color: var(--text-primary);
    border-bottom-color: var(--accent);
  }

  .chat-tab:disabled {
    color: var(--text-muted);
    opacity: 0.4;
    cursor: not-allowed;
  }

  .chat-messages {
    flex: 1;
    overflow-y: auto;
    padding: 10px 16px;
    font-size: 13px;
    line-height: 1.6;
  }

  .chat-messages .msg-muted { color: var(--text-muted); }

  .chat-username {
    color: var(--accent);
    font-weight: 700;
    cursor: pointer;
  }
  .chat-username:hover { text-decoration: underline; }

  .whisper-label {
    color: var(--text-muted);
    font-size: 12px;
  }

  .chat-timestamp {
    color: var(--text-muted);
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    margin-right: 6px;
  }

  #user-context-menu .user-menu-btn {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    border-radius: 5px;
    padding: 7px 10px;
    font-size: 13px;
    color: var(--text-primary);
    cursor: pointer;
    font-family: inherit;
  }
  #user-context-menu .user-menu-btn:hover { background: var(--bg-panel-raised); }
  #user-context-menu .user-menu-btn-danger { color: var(--error); }

  .chat-input-row {
    display: flex;
    gap: 8px;
    padding: 10px 16px;
    border-top: 1px solid var(--border);
  }

  .chat-input-row input {
    flex: 1;
    background: var(--bg-void);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 8px 12px;
    color: var(--text-primary);
    font-size: 13px;
  }

  .chat-input-row input::placeholder { color: var(--text-muted); }

  .chat-send {
    background: var(--accent);
    border: none;
    border-radius: 6px;
    padding: 8px 16px;
    font-size: 13px;
    font-weight: 600;
    color: #201607;
    cursor: pointer;
  }

  .chat-send:hover { background: var(--accent-dim); color: var(--text-primary); }

  /* ---- Shared building blocks ----
     Used instead of copying the same inline styles into every view.
     Sizing (padding, font-size, width, margins) stays on the element. */

  .btn {
    border-radius: 5px;
    cursor: pointer;
    font-family: inherit;
  }

  .btn-accent {
    background: var(--accent);
    border: none;
    color: #201607;
    font-weight: 600;
  }

  .btn-raised {
    background: var(--bg-panel-raised);
    border: 1px solid var(--border);
    color: var(--text-primary);
  }
  .btn-raised.active { border-color: var(--accent); color: var(--accent); font-weight: 600; } /* the log level currently in effect */

  /* Modal popups: hidden until openModal(id) adds .open (shell.js). */
  .modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.6);
    z-index: 1000;
    align-items: center;
    justify-content: center;
  }

  .modal-overlay.open {
    display: flex;
  }

  .modal-box {
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 20px;
  }

  .modal-title {
    margin: 0 0 14px;
    font-size: 15px;
  }

  /* "Nothing here yet" lines inside lists. */
  .empty-note {
    color: var(--text-muted);
    font-size: 13px;
    margin: 0;
  }

  /* Settings view (settings.js). Theme-neutral: uses the colour
     variables so it looks right in every theme. */
  .settings-section { margin-top: 8px; }
  .settings-section-title { font-size: 13px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent); margin-bottom: 4px; }
  .settings-note { font-size: 13px; color: var(--text-muted); margin: 0 0 14px; }
  .theme-options { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; }
  .settings-section + .settings-section { margin-top: 26px; }
  .warning-preview-buttons { display: flex; flex-wrap: wrap; gap: 8px; }
  .warning-preview-buttons .btn { padding: 7px 14px; font-size: 13px; }
  .theme-card {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 14px;
    text-align: left;
    background: var(--bg-panel-raised);
    border: 2px solid var(--border);
    border-radius: 8px;
    color: var(--text-primary);
    cursor: pointer;
    font-family: inherit;
  }
  .theme-card:hover { border-color: var(--accent-dim); }
  .theme-card.selected { border-color: var(--accent); }
  .theme-swatches { display: flex; height: 34px; border-radius: 5px; overflow: hidden; border: 1px solid rgba(255,255,255,0.08); }
  .theme-swatches span { flex: 1; }
  .theme-card-name { font-size: 15px; font-weight: 600; display: flex; align-items: center; justify-content: space-between; gap: 8px; }
  .theme-card-active { font-size: 11px; font-weight: 600; color: var(--accent); text-transform: uppercase; letter-spacing: 0.06em; }
  .theme-card-desc { font-size: 13px; color: var(--text-muted); line-height: 1.4; }

  /* Staff broadcast (admin Quick actions -> Send broadcast): stands out
     from normal chat and system lines in every chat tab. */
  .msg-announcement {
    margin: 4px 0;
    padding: 6px 10px;
    border-left: 3px solid var(--accent);
    background: rgba(212,162,76,0.10);
    color: var(--text-primary);
    font-weight: 600;
    overflow-wrap: anywhere;
  }
  .msg-announcement-tag {
    margin-right: 6px;
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--accent);
  }

  /* Admin quick-action forms */
  .admin-form label { display: block; font-size: 12px; color: var(--text-muted); margin: 10px 0 5px; }
  .admin-form input, .admin-form textarea {
    width: 100%; box-sizing: border-box; padding: 8px; font-size: 13px; font-family: inherit;
    background: var(--bg-void); border: 1px solid var(--border); border-radius: 5px; color: var(--text-primary);
  }
  .admin-form textarea { resize: vertical; min-height: 80px; }
  .admin-form-count { font-size: 11px; color: var(--text-muted); text-align: right; margin-top: 3px; }
  .admin-form-error { color: var(--error); font-size: 12px; min-height: 16px; margin-top: 8px; }
