:root {
    color-scheme: dark;
    --bg: #10141c;
    --panel: #171d28;
    --panel-2: #1e2735;
    --line: #2a3547;
    --text: #e8edf6;
    --muted: #8b98ad;
    --accent: #58a6ff;
    --good: #4ade80;
    --warn: #fbbf24;
    --bad: #f87171;
    font-family: "Segoe UI", system-ui, sans-serif;
}

* { box-sizing: border-box; }

[hidden] { display: none !important; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
}

.app-shell {
    display: grid;
    grid-template-columns: 320px 1fr;
    height: 100vh;
}

/* --------------------------------------------------------------- landing */

.landing {
    min-height: 100vh;
    display: flex;
    justify-content: center;
    padding: 48px 24px;
    background:
        radial-gradient(1100px 640px at 78% -8%, #1b2740 0%, transparent 60%),
        radial-gradient(900px 520px at 8% 110%, #16202e 0%, transparent 55%),
        var(--bg);
}

.landing-inner {
    width: 100%;
    max-width: 960px;
    display: flex;
    flex-direction: column;
    gap: 22px;
}

.landing-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}

.landing-brand { display: flex; align-items: center; gap: 14px; }
.landing-logo { width: 52px; height: 52px; border-radius: 12px; flex: none; }

.landing-header h1 {
    margin: 0;
    font-size: 1.7rem;
    letter-spacing: 0.01em;
}

.icon-button {
    background: var(--panel-2);
    color: var(--text);
    border: 1px solid var(--line);
    border-radius: 8px;
    width: 38px;
    height: 38px;
    padding: 0;
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    flex: none;
}

.icon-button:hover { filter: brightness(1.15); }

.landing-sub {
    margin: 6px 0 0;
    color: var(--muted);
    font-size: 0.9rem;
}

.server-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 16px;
}

.server-card {
    display: flex;
    flex-direction: column;
    padding: 0;
    overflow: hidden;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: 12px;
    cursor: pointer;
    text-align: left;
    color: var(--text);
    font: inherit;
    transition: border-color 0.12s ease, transform 0.12s ease;
}

.server-card:hover {
    border-color: var(--accent);
    transform: translateY(-2px);
    filter: none;
}

.card-thumb {
    position: relative;
    aspect-ratio: 16 / 9;
    background:
        linear-gradient(135deg, #1c2740 0%, #10141c 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.card-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    image-rendering: pixelated;
}

/* Placeholder glyph shown when a game has no basemap image. */
.card-thumb .thumb-glyph {
    font-size: 2.2rem;
    font-weight: 700;
    color: rgba(232, 237, 246, 0.18);
    letter-spacing: 0.04em;
}

/* The game's icon sits in the info strip, right-aligned and boxless.
   Width AND height stay explicit so no generic img rule can stretch it. */
.card-body { position: relative; }
.card-body .card-icon {
    position: absolute;
    right: 14px;
    top: 50%;
    transform: translateY(-50%);
    width: 38px;
    height: 38px;
    object-fit: contain;
}

.card-thumb .card-status {
    position: absolute;
    top: 8px;
    right: 8px;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 8px;
    border-radius: 999px;
    font-size: 0.7rem;
    background: color-mix(in srgb, var(--bg) 72%, transparent);
    border: 1px solid var(--line);
    color: var(--muted);
}

.card-status .pip { width: 7px; height: 7px; border-radius: 50%; background: var(--warn); }
.card-status[data-state="live"] .pip { background: var(--good); }
.card-status[data-state="error"] .pip { background: var(--bad); }
.card-status[data-state="paused"] .pip { background: var(--warn); }

.card-body {
    padding: 12px 60px 14px 14px; /* right padding clears the icon */
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.card-game {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--accent);
}

.card-server {
    font-size: 1rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.card-meta {
    margin-top: 6px;
    display: flex;
    flex-wrap: wrap;
    gap: 4px 12px;
    font-size: 0.72rem;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

.landing-footer { min-height: 1rem; }
#landing-error { font-size: 0.75rem; color: var(--bad); overflow-wrap: anywhere; }

.landing .auth-panel { max-width: 340px; }

/* ------------------------------------------------------------- game heading */

.back-button { padding: 5px 10px; }

.game-heading {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.game-kicker {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--accent);
}

.game-kicker:empty { display: none; }

.game-heading strong { font-size: 1.05rem; }

/* ---------------------------------------------------------------- sidebar */

.sidebar {
    background: var(--panel);
    border-right: 1px solid var(--line);
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    overflow-y: auto;
}

.sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.sidebar-header h1 {
    font-size: 1.15rem;
    margin: 0;
    letter-spacing: 0.02em;
}

.connection {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.75rem;
    color: var(--muted);
    white-space: nowrap;
}

.connection .pulse {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--warn);
}

.connection[data-state="live"] .pulse { background: var(--good); }
.connection[data-state="error"] .pulse { background: var(--bad); }
.connection[data-state="paused"] .pulse { background: var(--warn); }
.connection[data-state="connecting"] .pulse {
    animation: pulse 1.2s ease-in-out infinite;
}

@keyframes pulse {
    50% { opacity: 0.3; }
}

/* ---------------------------------------------------------------- switcher */

.switcher {
    display: flex;
    flex-direction: column;
    gap: 3px;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
}

.switcher select {
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 7px;
    color: var(--text);
    padding: 7px 8px;
    font-size: 0.82rem;
    width: 100%;
    min-width: 0;
    text-transform: none;
    letter-spacing: normal;
}

/* ----------------------------------------------------------------- metrics */

/* A slim strip of label:value chips — the sidebar's quiet vital signs. */
.metrics {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.metrics:empty { display: none; }

.metrics div {
    background: var(--panel-2);
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: 3px 10px;
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
}

.metrics span {
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted);
}

.metrics strong { font-size: 0.8rem; font-variant-numeric: tabular-nums; }

.version-line {
    margin: 0;
    font-size: 0.72rem;
    color: var(--muted);
}

.map-controls {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

button {
    background: var(--accent);
    color: #0b1017;
    font-weight: 600;
    border: none;
    border-radius: 8px;
    padding: 7px 12px;
    cursor: pointer;
    font-size: 0.8rem;
}

button.secondary {
    background: var(--panel-2);
    color: var(--text);
    border: 1px solid var(--line);
}

button:hover { filter: brightness(1.12); }

.toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.8rem;
    color: var(--muted);
    cursor: pointer;
}

.coord-goto {
    display: grid;
    grid-template-columns: auto 1fr 1fr auto auto;
    gap: 6px;
    align-items: center;
}

.coord-goto input {
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 6px;
    color: var(--text);
    padding: 6px 8px;
    font-size: 0.8rem;
    width: 100%;
    min-width: 0;
}

.coord-goto button { padding: 6px 10px; }

.section-heading {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
}

.section-heading h2 {
    margin: 0;
    font-size: 0.9rem;
}

#snapshot-age {
    font-size: 0.7rem;
    color: var(--muted);
}

/* Only rendered when the feed goes stale — make it read as a warning. */
#snapshot-age.stale { color: var(--warn); }

.team-filter {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    font-size: 0.72rem;
    color: var(--muted);
}

.team-filter select {
    flex: 1;
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 6px;
    color: var(--text);
    padding: 5px 8px;
    font-size: 0.78rem;
}

.roster-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 8px;
}

.entity-card {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--panel-2);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 8px 10px;
    cursor: pointer;
    text-align: left;
    width: 100%;
    color: var(--text);
    font: inherit;
}

.entity-card.selected { border-color: var(--accent); }
.entity-card.offline { opacity: 0.55; }
.entity-card.dimmed { opacity: 0.35; }

.entity-card .dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex: none;
}

/* Avatar holds the colored dot; a composited player portrait replaces it once
   built (Necesse). */
.entity-card .avatar {
    position: relative;
    width: 30px;
    height: 30px;
    flex: none;
    display: grid;
    place-items: center;
}
.entity-card .avatar .portrait {
    position: absolute;
    inset: 0;
    width: 30px;
    height: 30px;
    image-rendering: pixelated;
    display: none;
}
.entity-card .avatar.has-portrait .dot { display: none; }
.entity-card .avatar.has-portrait .portrait { display: block; }

.entity-card .who { flex: 1; min-width: 0; }

.entity-card .who strong {
    display: block;
    font-size: 0.85rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.entity-card .who span {
    font-size: 0.7rem;
    color: var(--muted);
}

.entity-card .who .team { color: hsl(35, 70%, 62%); }

/* Separate the team name from the status line ("650/650 HP · AFG"). */
.entity-card .who .status:not(:empty) + .team:not(:empty)::before {
    content: "· ";
    color: var(--muted);
    margin: 0 2px 0 5px;
}

/* AFK: an amber badge on the card's right edge, and the rest of the card
   recedes (the badge itself stays crisp so the state reads at a glance). */
.entity-card .afk-badge {
    flex: none;
    font-size: 0.64rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    color: var(--warn);
    border: 1px solid color-mix(in srgb, var(--warn) 45%, var(--line));
    background: color-mix(in srgb, var(--warn) 12%, transparent);
    border-radius: 999px;
    padding: 2px 7px;
}

.entity-card.afk { background: color-mix(in srgb, var(--panel-2) 72%, var(--bg)); }
.entity-card.afk .avatar,
.entity-card.afk .who { opacity: 0.62; }

/* A small chip on cards whose entity is on a different map than the one shown. */
.entity-card .elsewhere {
    font-size: 0.68rem;
    color: var(--muted);
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: 1px 7px;
    white-space: nowrap;
}

.empty-state {
    color: var(--muted);
    font-size: 0.8rem;
    margin: 4px 0;
}

.entity-detail {
    background: var(--panel-2);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 10px 12px;
    font-size: 0.8rem;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.entity-detail h3 { margin: 0; font-size: 0.95rem; }
.entity-detail dl {
    margin: 0;
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 2px 10px;
}
.entity-detail dt { color: var(--muted); }
.entity-detail dd { margin: 0; text-align: right; overflow-wrap: anywhere; }
.entity-detail .detail-actions { display: flex; gap: 8px; margin-top: 4px; }

.auth-panel {
    background: var(--panel-2);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.auth-panel .label { margin: 0; font-size: 0.8rem; }

.auth-panel form { display: flex; gap: 6px; }

.auth-panel input {
    flex: 1;
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 6px;
    color: var(--text);
    padding: 6px 8px;
    font-size: 0.8rem;
}

.auth-state { margin: 0; font-size: 0.75rem; color: var(--warn); }

footer { margin-top: auto; }
#error-line { font-size: 0.72rem; color: var(--bad); overflow-wrap: anywhere; }

/* -------------------------------------------------------------------- map */

.map-stage {
    position: relative;
    overflow: hidden;
    background:
        radial-gradient(1200px 700px at 70% 30%, #16202e 0%, var(--bg) 70%);
}

#map-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    cursor: grab;
    touch-action: none; /* we handle pan/pinch ourselves; don't let the browser scroll/zoom */
}

#map-canvas.dragging { cursor: grabbing; }

.map-toolbar {
    position: absolute;
    top: 10px;
    left: 10px;
    display: flex;
    gap: 6px;
    z-index: 2;
}

.map-legend,
.shortcuts-panel {
    position: absolute;
    top: 48px;
    left: 10px;
    z-index: 2;
    background: color-mix(in srgb, var(--panel) 92%, transparent);
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 10px 14px;
    font-size: 0.76rem;
    color: var(--muted);
    display: flex;
    flex-direction: column;
    gap: 5px;
    pointer-events: none;
}

.map-legend strong,
.shortcuts-panel strong {
    color: var(--text);
    font-size: 0.78rem;
    margin-bottom: 2px;
}

.map-legend span,
.shortcuts-panel span {
    display: flex;
    align-items: center;
    gap: 7px;
}

.map-legend .swatch {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    flex: none;
}

.map-legend .swatch.online { background: hsl(210, 80%, 60%); }
.map-legend .swatch.offline { background: rgba(139, 152, 173, 0.6); }
.map-legend .swatch.selected { background: transparent; box-shadow: 0 0 0 2px hsl(210, 90%, 70%); }
.map-legend .swatch.trail { background: linear-gradient(90deg, transparent, hsl(210, 80%, 65%)); border-radius: 2px; }
.map-legend .swatch.settlement { background: hsl(35, 85%, 58%); border-radius: 2px; transform: rotate(45deg); width: 10px; height: 10px; }
.map-legend .swatch.base { background: #4cc9f0; border-radius: 2px; transform: rotate(45deg); width: 10px; height: 10px; }
.map-legend .swatch.dungeon { background: #d95763; border-radius: 2px; }
.map-legend .swatch.temple { background: #b48ce8; clip-path: polygon(50% 0, 100% 100%, 0 100%); border-radius: 0; }
.map-legend .swatch.trial { background: #6aa7e8; }
.map-legend .swatch.marker { background: #e8d36a; border-radius: 50% 50% 50% 0; transform: rotate(-45deg); }
.map-legend .swatch.trader { background: #f2c94c; border-radius: 50%; box-shadow: inset 0 0 0 3px #f2c94c, inset 0 0 0 5px #0b1017; }
.map-legend .swatch.death { background: transparent; border-radius: 0; position: relative; }
.map-legend .swatch.death::before, .map-legend .swatch.death::after { content: ""; position: absolute; background: #e5484d; }
.map-legend .swatch.death::before { left: 4px; top: 0; width: 2px; height: 10px; }
.map-legend .swatch.death::after { left: 1px; top: 3px; width: 8px; height: 2px; }
.field-note { margin: 0; font-size: 0.74rem; color: var(--muted); }

/* Basemap features, generated from the geometry on screen. Square swatches, so
   an area reads as an area beside the round entity markers above it. */
.map-legend .legend-map {
    display: flex;
    flex-direction: column;
    gap: 5px;
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px solid var(--line, rgba(255, 255, 255, 0.14));
}

.map-legend .legend-map .swatch {
    border-radius: 2px;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.28);
}

.shortcuts-panel { top: auto; bottom: 42px; }
.shortcuts-panel kbd {
    background: var(--panel-2);
    border: 1px solid var(--line);
    border-radius: 4px;
    padding: 1px 5px;
    font-family: inherit;
    font-size: 0.72rem;
    color: var(--text);
}

.shortcuts-button {
    position: absolute;
    left: 10px;
    bottom: 10px;
    z-index: 2;
    width: 26px;
    height: 26px;
    padding: 0;
    border-radius: 50%;
    background: var(--panel-2);
    color: var(--text);
    border: 1px solid var(--line);
    font-weight: 700;
}

.map-hint {
    position: absolute;
    top: 58px;
    left: 50%;
    transform: translateX(-50%);
    max-width: 420px;
    background: color-mix(in srgb, var(--panel) 88%, transparent);
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 10px 14px;
    font-size: 0.78rem;
    color: var(--muted);
    pointer-events: none;
}

.map-hint strong { color: var(--text); }
.map-hint p { margin: 4px 0 0; }
.map-hint code { color: var(--accent); }

.map-coords {
    position: absolute;
    right: 10px;
    bottom: 10px;
    background: color-mix(in srgb, var(--panel) 88%, transparent);
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 4px 10px;
    font-size: 0.72rem;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------- necesse theme */

/* Per-game theme, scoped to the map view (app-shell). Redefining the CSS
   variables here re-skins the whole subtree; the landing and admin overlay sit
   outside app-shell and keep the base theme. Mirrors the Necesse mod's look. */
/* Also matched on <body> so the overlays — which sit outside
   .app-shell — inherit the game palette instead of the base one. */
.app-shell[data-theme="necesse"],
body[data-theme="necesse"] {
    --bg: #09110f;
    --panel: #10211d;
    --panel-2: #17322b;
    --line: rgba(157, 211, 183, 0.16);
    --text: #edf7f2;
    --muted: #91aaa0;
    --accent: #7fe0a7;
    --good: #7fe0a7;
    --warn: #f3bd68;
    --bad: #ff8f84;
}

.app-shell[data-theme="necesse"] .sidebar {
    background:
        radial-gradient(circle at 0 0, rgba(38, 117, 84, 0.22), transparent 24rem),
        rgba(10, 20, 18, 0.98);
    box-shadow: 14px 0 36px rgba(0, 0, 0, 0.22);
}

.app-shell[data-theme="necesse"] .map-stage {
    background: radial-gradient(1200px 700px at 70% 30%, #123a2d 0%, var(--bg) 72%);
}

.app-shell[data-theme="necesse"] .game-kicker { color: var(--accent); }

/* ---------------------------------------------------------- palworld theme */

/* Deep-ocean teal with Pal-Sphere cyan: same scoped mechanism as the Necesse
   theme — variables re-skin the map view only. */
/* Also matched on <body> so the overlays — which sit outside
   .app-shell — inherit the game palette instead of the base one. */
.app-shell[data-theme="palworld"],
body[data-theme="palworld"] {
    --bg: #0a161d;
    --panel: #10222c;
    --panel-2: #16303c;
    --line: rgba(102, 195, 226, 0.18);
    --text: #eaf6fb;
    --muted: #8fb2c0;
    --accent: #4cc9f0;
    --good: #52e0b8;
    --warn: #ffd166;
    --bad: #ff7b72;
}

.app-shell[data-theme="palworld"] .sidebar {
    background:
        radial-gradient(circle at 0 0, rgba(36, 130, 170, 0.24), transparent 24rem),
        rgba(9, 22, 29, 0.98);
    box-shadow: 14px 0 36px rgba(0, 0, 0, 0.25);
}

.app-shell[data-theme="palworld"] .map-stage {
    background: radial-gradient(1200px 700px at 70% 30%, #123a4a 0%, var(--bg) 72%);
}

.app-shell[data-theme="palworld"] .game-kicker { color: var(--accent); }

/* -------------------------------------------------------------- admin portal */

.admin-overlay {
    position: fixed;
    inset: 0;
    z-index: 20;
    background: rgba(6, 9, 14, 0.7);
    display: flex;
    align-items: flex-start;
    justify-content: center;
    --overlay-pad: 40px;
    padding: var(--overlay-pad) 16px;
    overflow-y: auto;
}

.admin-panel {
    width: 100%;
    max-width: 560px;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: 14px;
    padding: 18px 20px 22px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.admin-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.admin-head h2 { margin: 0; font-size: 1.15rem; }

.admin-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.admin-row {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--panel-2);
    border: 1px solid var(--line);
    border-radius: 9px;
    padding: 9px 12px;
}

.admin-row .pip { width: 8px; height: 8px; border-radius: 50%; background: var(--warn); flex: none; }
.admin-row[data-state="live"] .pip { background: var(--good); }
.admin-row[data-state="error"] .pip { background: var(--bad); }

.admin-row .row-main { flex: 1; min-width: 0; }
.admin-row .row-name { font-size: 0.9rem; display: flex; align-items: center; gap: 8px; }
.admin-row .row-sub { font-size: 0.72rem; color: var(--muted); margin-top: 2px; }

.badge {
    font-size: 0.66rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 1px 6px;
    border-radius: 999px;
    border: 1px solid var(--line);
    color: var(--muted);
}
.badge.type { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }

.admin-row .row-actions { display: flex; gap: 6px; flex: none; }
.admin-row .row-actions button { padding: 5px 10px; font-size: 0.74rem; }

button.ghost { background: transparent; color: var(--muted); border: 1px solid transparent; }
button.ghost:hover { color: var(--text); }
button.danger { background: transparent; color: var(--bad); border: 1px solid color-mix(in srgb, var(--bad) 40%, var(--line)); }
button.danger:hover { background: color-mix(in srgb, var(--bad) 16%, transparent); filter: none; }

#admin-body { display: flex; flex-direction: column; gap: 14px; }
.admin-add { align-self: flex-start; }

.admin-form { display: flex; flex-direction: column; gap: 12px; }
.admin-form h3 { margin: 0; font-size: 1rem; }

.field { display: flex; flex-direction: column; gap: 4px; font-size: 0.72rem; color: var(--muted); }
.field span { text-transform: uppercase; letter-spacing: 0.05em; }
.field em { text-transform: none; letter-spacing: normal; font-style: normal; opacity: 0.7; }
.field input, .field select {
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 7px;
    color: var(--text);
    padding: 8px 10px;
    font-size: 0.85rem;
    width: 100%;
    min-width: 0;
}
.field input:disabled { opacity: 0.55; }

.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.type-fields { display: flex; flex-direction: column; gap: 12px; }

.form-result {
    margin: 0;
    font-size: 0.78rem;
    padding: 8px 10px;
    border-radius: 7px;
    overflow-wrap: anywhere;
}
.form-result.ok { color: var(--good); background: color-mix(in srgb, var(--good) 12%, transparent); }
.form-result.bad { color: var(--bad); background: color-mix(in srgb, var(--bad) 12%, transparent); }
.form-result.pending { color: var(--muted); background: var(--panel-2); }

.admin-form-actions { display: flex; gap: 8px; align-items: center; }
.admin-form-actions #f-cancel { margin-left: auto; }

.admin-auth form { display: flex; gap: 6px; }
.admin-auth input {
    flex: 1;
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 6px;
    color: var(--text);
    padding: 8px 10px;
    font-size: 0.85rem;
}

/* First-run bootstrap: a proper stacked form, not the token gate's inline row. */
#admin-bootstrap {
    display: flex;
    flex-direction: column;
    gap: 10px;
    align-items: stretch;
    margin-top: 10px;
}
#admin-bootstrap .field-row { display: flex; gap: 10px; }
#admin-bootstrap .field { flex: 1; display: flex; flex-direction: column; gap: 4px; }
#admin-bootstrap .field span { font-size: 0.72rem; color: var(--muted); }
#admin-bootstrap .field em { font-style: normal; }
#admin-bootstrap button[type="submit"] { align-self: flex-start; }
@media (max-width: 520px) {
    #admin-bootstrap .field-row { flex-direction: column; }
}

@media (max-width: 760px) {
    /* Map-first on phones: the map gets most of the height, the sidebar becomes
       a scrollable panel beneath it. */
    .app-shell { grid-template-columns: 1fr; grid-template-rows: 62dvh 38dvh; height: 100dvh; }
    .sidebar { order: 2; border-right: none; border-top: 1px solid var(--line); padding: 12px; min-height: 0; }
    .map-stage { order: 1; }
    .metrics { grid-template-columns: repeat(3, 1fr); }
    .metrics span { font-size: 0.7rem; }
    .map-legend, .shortcuts-panel { font-size: 0.72rem; padding: 8px 10px; }
    /* Bigger touch targets on the overlay controls. */
    .map-toolbar button { padding: 8px 12px; }
    .coord-goto button, button { min-height: 34px; }

    .landing { padding: 20px 14px; }
    .landing-header h1 { font-size: 1.4rem; }
    .server-grid { grid-template-columns: 1fr; gap: 12px; }

    .admin-overlay { --overlay-pad: 12px; padding: var(--overlay-pad); }
    .admin-panel { max-width: none; min-height: 100%; }
    .field-row { grid-template-columns: 1fr; }
}

/* ============================================ backlog additions (tasks 1-11) */

/* ------------------------------------------------------- focus visibility */

button:focus-visible,
select:focus-visible,
input:focus-visible,
.entity-card:focus-visible,
.server-card:focus-visible,
summary:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* --------------------------------------------------------- toggle switches */

.toggle input {
    appearance: none;
    -webkit-appearance: none;
    width: 34px;
    height: 20px;
    margin: 0;
    border-radius: 999px;
    background: var(--panel-2);
    border: 1px solid var(--line);
    position: relative;
    cursor: pointer;
    transition: background 0.15s ease;
    flex: none;
}

.toggle input::before {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--muted);
    transition: transform 0.15s ease, background 0.15s ease;
}

.toggle input:checked { background: color-mix(in srgb, var(--accent) 35%, var(--panel-2)); }
.toggle input:checked::before { transform: translateX(14px); background: var(--accent); }
.toggle { min-height: 28px; }

button { min-height: 34px; }
.zoom-button { width: 34px; padding: 0; font-size: 1.05rem; }

/* Keyboard-shortcut UI is meaningless on touch devices. */
@media (hover: none) {
    .shortcuts-button, .shortcuts-panel { display: none !important; }
}

/* ------------------------------------------------------------ world clock */

.world-clock {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 3px 12px 3px 9px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--panel) 90%, transparent);
    border: 1px solid var(--line);
    color: var(--muted);
    font-size: 0.76rem;
    font-variant-numeric: tabular-nums;
}

.world-clock-dial { width: 46px; height: 27px; overflow: visible; }
.dial-sky { fill: none; stroke: color-mix(in srgb, var(--muted) 40%, transparent); stroke-width: 1; stroke-dasharray: 1.5 2.6; }
.dial-horizon { stroke: color-mix(in srgb, var(--muted) 60%, transparent); stroke-width: 1; stroke-linecap: round; }
.dial-sun, .dial-moon { opacity: 0; transition: opacity 0.8s ease, transform 1.1s linear; }
.dial-sun.visible, .dial-moon.visible { opacity: 1; }
.sun-core { fill: #f4c351; }
.sun-rays line { stroke: #f4c351; stroke-width: 0.9; stroke-linecap: round; }
.sun-rays { animation: world-clock-sun-spin 30s linear infinite; }
.moon-core { fill: #dbe4ee; }
.moon-shadow { fill: rgba(5, 10, 16, 0.92); }
.dial-stars circle { fill: #d7e7de; opacity: 0; transition: opacity 1s ease; }
.world-clock[data-phase="night"] .dial-stars circle,
.world-clock[data-phase="evening"] .dial-stars circle:nth-child(2) {
    opacity: 0.85;
    animation: world-clock-twinkle 2.6s ease-in-out infinite alternate;
}
.world-clock[data-phase="night"] .dial-stars circle:nth-child(2) { animation-delay: 0.9s; }
.world-clock[data-phase="night"] .dial-stars circle:nth-child(3) { animation-delay: 1.6s; }
.world-clock[data-phase="evening"] .dial-sky,
.world-clock[data-phase="morning"] .dial-sky { stroke: rgba(224, 158, 96, 0.4); }
@keyframes world-clock-sun-spin { to { transform: rotate(360deg); } }
@keyframes world-clock-twinkle { from { opacity: 0.3; } to { opacity: 0.95; } }
@media (prefers-reduced-motion: reduce) {
    .sun-rays, .world-clock .dial-stars circle { animation: none; }
    .dial-sun, .dial-moon { transition: opacity 0.8s ease; }
}

/* ------------------------------------------------------------ scale ruler */

.scale-ruler {
    /* Bottom-right, stacked above the coords readout — bottom-left belongs to
       the shortcuts button and its pop-up panel. */
    position: absolute;
    right: 10px;
    bottom: 44px;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 2px;
    pointer-events: none;
}

.scale-ruler span {
    display: block;
    height: 5px;
    border: 1px solid var(--text);
    border-top: none;
    opacity: 0.75;
}

.scale-ruler strong {
    font-size: 0.7rem;
    font-weight: 500;
    color: var(--muted);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
}

/* -------------------------------------------------------- sidebar collapse */

.app-shell.sidebar-collapsed { grid-template-columns: 0 1fr; }
/* Hide WITHOUT display:none — the sidebar must stay a grid item, or the map
   auto-places into the 0-width first column and the whole view vanishes. */
.app-shell.sidebar-collapsed .sidebar {
    visibility: hidden;
    padding: 0;
    border: none;
    overflow: hidden;
}

/* ------------------------------------------------------ rich detail panel */

.detail-top {
    display: flex;
    align-items: flex-start;
    gap: 10px;
}

.detail-top-left { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }

.detail-portrait {
    flex: none;
    width: 76px;
    height: 76px;
    image-rendering: pixelated;
    opacity: 0;
    transition: opacity 0.25s ease;
}

.detail-portrait.ready { opacity: 1; }

.detail-status { margin: -2px 0 0; font-size: 0.74rem; color: var(--muted); }
.detail-status[data-state="online"] { color: var(--good); }
.detail-status[data-state="afk"] { color: var(--warn); }

.team-badge {
    align-self: flex-start;
    font-size: 0.72rem;
    padding: 2px 9px;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--team-color, var(--line)) 55%, var(--line));
    color: var(--text);
    background: color-mix(in srgb, var(--team-color, transparent) 16%, transparent);
}

.equipment-list { display: flex; flex-wrap: wrap; gap: 5px; }
.equipment-list span {
    font-size: 0.7rem;
    color: var(--muted);
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 2px 7px;
}

.detail-meters { display: flex; flex-direction: column; gap: 6px; }
.meter-caption { display: flex; justify-content: space-between; font-size: 0.7rem; color: var(--muted); }
.meter-track {
    height: 6px;
    border-radius: 999px;
    background: var(--bg);
    border: 1px solid var(--line);
    overflow: hidden;
}
.meter-track span { display: block; height: 100%; border-radius: 999px; transition: width 0.5s ease; }
.meter-track.health span { background: #63d08c; }
.meter-track.mana span { background: #6aa7e8; }
.meter-track.hunger span { background: #e8b45f; }
.meter-track.resilience span { background: #b48ce8; }

/* auto-fit lets an odd count fill the last row instead of leaving a hole. */
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(76px, 1fr)); gap: 6px; }
.stats-grid div {
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 7px;
    padding: 5px 8px;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.stats-grid span { font-size: 0.64rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
.stats-grid strong { font-size: 0.82rem; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------ health panel */

.health-panel,
.side-panel {
    background: var(--panel-2);
    border: 1px solid var(--line);
    border-radius: 8px;
    font-size: 0.78rem;
}
.health-panel summary,
.side-panel summary {
    cursor: pointer;
    padding: 8px 12px;
    display: flex;
    justify-content: space-between;
    color: var(--muted);
}
.health-panel summary::-webkit-details-marker,
.side-panel summary::-webkit-details-marker { display: none; }
.health-panel[open] summary,
.side-panel[open] summary { border-bottom: 1px solid var(--line); }

/* Server diagnostics modal (admin cogwheel in the map sidebar header). */
.diag-button { font-size: 0.9rem; padding: 2px 7px; flex: none; }
.diag-panel { max-width: 440px; }
.diag-section { padding: 12px 16px; }
.diag-section + .diag-section { border-top: 1px solid var(--line); }
.diag-section h3 {
    margin: 0 0 8px;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
    display: flex;
    justify-content: space-between;
}
.diag-section .health-grid { padding: 0; }
#health-state { color: var(--text); font-variant-numeric: tabular-nums; text-transform: none; letter-spacing: normal; }

/* -------------------- Palworld game-styled player card (detail panel) */

.pw-level-block { display: flex; gap: 10px; align-items: stretch; }
.pw-level-num {
    background: var(--panel-2);
    border-left: 3px solid var(--accent);
    font: 700 30px/1 system-ui;
    padding: 8px 12px;
    display: flex;
    align-items: center;
    font-variant-numeric: tabular-nums;
}
.pw-level-side { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 3px; min-width: 0; }
.pw-name-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.pw-name-row strong { font-size: 15.5px; }
.pw-level-label {
    font-size: 0.62rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--accent);
}
.pw-guild-chip {
    display: inline-flex; align-items: center; gap: 6px;
    background: var(--panel-2);
    border: 1px solid var(--line);
    color: var(--text);
    border-radius: 999px;
    padding: 2px 10px;
    font-size: 0.75rem;
    font-weight: 500;
    cursor: pointer;
}
.pw-guild-chip:hover { filter: brightness(1.2); }
.pw-guild-chip .sw { width: 8px; height: 8px; border-radius: 2px; transform: rotate(45deg); }
.pw-guild-chip .arrow { color: var(--muted); font-size: 0.6rem; }

.pw-bars { display: flex; flex-direction: column; gap: 5px; margin-top: 8px; }
.pw-bar {
    position: relative;
    height: 19px;
    background: var(--panel-2);
    overflow: hidden;
}
.pw-bar i { position: absolute; top: 0; bottom: 0; left: 0; }
.pw-bar.hp i { background: #2ecc7a; }
.pw-bar.hunger i { background: #e8862e; }
.pw-level-label:empty { display: none; }
.pw-bar .val {
    position: absolute; inset: 0;
    display: flex; align-items: center; gap: 4px;
    padding-left: 8px;
    font: 700 12.5px ui-monospace, monospace;
    color: #fff;
    text-shadow: 0 0 3px rgba(0, 0, 0, 0.9), 0 1px 2px rgba(0, 0, 0, 0.9);
}
.pw-bar .val em { font-style: normal; font-weight: 500; opacity: 0.8; }
.pw-bar .tag {
    position: absolute; right: 8px; top: 0; bottom: 0;
    display: flex; align-items: center;
    font: 700 9.5px ui-monospace, monospace;
    letter-spacing: 0.08em;
    color: rgba(255, 255, 255, 0.85);
    text-shadow: 0 0 3px rgba(0, 0, 0, 0.9), 0 1px 2px rgba(0, 0, 0, 0.9);
}

.pw-strip {
    display: flex; align-items: center; justify-content: space-between;
    background: linear-gradient(90deg, var(--panel-2), transparent 85%);
    border-left: 3px solid var(--accent);
    padding: 3px 9px;
    font-size: 0.78rem;
    font-weight: 600;
    margin: 12px 0 7px;
}
.pw-strip .side { font-weight: 400; font-size: 0.68rem; color: var(--muted); }

.pw-slabs { display: grid; grid-template-columns: 1fr 1fr; gap: 5px; }
.pw-slab {
    display: flex; align-items: center; justify-content: space-between;
    background: rgba(13, 22, 30, 0.9);
    border: 1px solid rgba(102, 195, 226, 0.08);
    padding: 4px 9px;
    font-size: 0.76rem;
}
.pw-slab span { color: var(--muted); }
.pw-slab b { font-variant-numeric: tabular-nums; font-size: 0.8rem; }

.pw-meta { display: flex; flex-wrap: wrap; gap: 3px 10px; font-size: 0.73rem; color: var(--muted); margin-top: 10px; }

/* ------------------------------------------- guild card & base modals */

.guild-panel { max-width: 380px; }
.guild-title { display: flex; align-items: center; gap: 9px; font-size: 1rem; font-weight: 600; }
.guild-sw { width: 12px; height: 12px; border-radius: 3px; transform: rotate(45deg); background: var(--accent); flex: none; }
.guild-sw.base { border-radius: 2px; }
.guild-sub { color: var(--muted); font-size: 0.75rem; margin: -6px 0 0 37px; padding: 0 16px 0 0; }
.guild-body { padding: 8px 16px 16px; }
.guild-body .pw-strip:first-child { margin-top: 4px; }

.guild-row {
    display: flex; align-items: center; gap: 10px;
    width: 100%;
    text-align: left;
    background: rgba(13, 22, 30, 0.9);
    border: 1px solid rgba(102, 195, 226, 0.08);
    border-radius: 0;
    color: var(--text);
    padding: 8px 11px;
    font: inherit;
    cursor: pointer;
    transition: border-color 0.15s;
}
.guild-row:hover { border-color: var(--accent); filter: none; }
.guild-row + .guild-row { margin-top: 5px; }
.g-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); opacity: 0.4; flex: none; }
.g-dot.online { background: var(--good); opacity: 1; }
.g-main { flex: 1; min-width: 0; }
.g-main strong { display: block; font-size: 0.83rem; }
.g-main span { font-size: 0.72rem; color: var(--muted); }
.g-basesw { width: 11px; height: 11px; border-radius: 2px; transform: rotate(45deg); flex: none; }
.g-minipals { display: flex; gap: 3px; flex: none; }
.g-minipals img { width: 20px; height: 20px; object-fit: contain; }

.base-pals { display: flex; flex-wrap: wrap; gap: 10px; }
.pal-chip.lg { width: 56px; height: 56px; border-radius: 11px; }
.pal-chip.lg img { width: 46px; height: 46px; }
.pal-named { display: flex; flex-direction: column; align-items: center; gap: 4px; width: 62px; }
.pal-named small { font-size: 0.68rem; color: var(--muted); white-space: nowrap; }

.modal-btns { display: flex; gap: 8px; margin-top: 14px; }

/* Party pals: icon chips with a level badge in the detail panel. */
.party-row { display: flex; flex-direction: column; gap: 5px; }
.party-label {
    font-size: 0.64rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted);
}
.party-list { display: flex; flex-wrap: wrap; gap: 6px; }
.pal-chip {
    position: relative;
    width: 40px;
    height: 40px;
    background: var(--panel-2);
    border: 1px solid var(--line);
    border-radius: 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.pal-chip img { width: 34px; height: 34px; object-fit: contain; image-rendering: auto; }
.pal-chip i {
    position: absolute;
    right: -3px;
    bottom: -3px;
    font-style: normal;
    font-size: 0.6rem;
    line-height: 1;
    padding: 2px 4px;
    border-radius: 6px;
    background: var(--panel);
    border: 1px solid var(--line);
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

/* Pal welfare: a struggling pal is marked on the chip itself, so a base in
   trouble reads at a glance instead of needing a hover. */
.pal-chip[data-cond] { border-color: currentColor; }
.pal-chip[data-cond="warn"] { color: var(--warn); }
.pal-chip[data-cond="bad"] { color: var(--bad); }
.pal-chip[data-cond]::after {
    content: "";
    position: absolute;
    left: -2px;
    top: -2px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: currentColor;
    border: 1px solid var(--panel);
}
/* Character sheet: the deep dive behind the roster card. */
/* align-self resists the stretch the overlay applies on narrow screens: the
   sheet is short, and stretching left a phone-sized panel two-thirds empty. */
.profile-panel {
    width: min(680px, 96vw);
    max-height: min(88vh, 760px);
    align-self: flex-start;
    display: flex;
    flex-direction: column;
}
.profile-head { display: flex; align-items: center; gap: 12px; }
.profile-head .profile-level { flex: none; }
.profile-id { min-width: 0; }
.profile-id h2 { margin: 0; font-size: 1.15rem; }
.profile-sub { font-size: 0.78rem; color: var(--muted); }
.profile-head .icon-button { margin-left: auto; }
.profile-panel .section-tabs { margin: 4px 0 0; }
.profile-body { overflow: auto; padding: 12px 14px 14px; }
.profile-body .pw-bars { margin-top: 0; }
#profile-pal-warning:empty { display: none; }
.profile-panelbox[hidden] { display: none; }
.profile-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 12px; }
@media (max-width: 620px) { .profile-grid { grid-template-columns: 1fr; } }
.profile-block {
    background: rgba(0, 0, 0, 0.2);
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 10px;
}
.profile-block h3 {
    margin: 0 0 8px;
    font-size: 0.64rem;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--muted);
}
.profile-rows { display: grid; gap: 5px; margin: 0; }
.profile-row { display: flex; justify-content: space-between; gap: 12px; font-size: 0.82rem; }
.profile-row dt { color: var(--muted); margin: 0; }
.profile-row dd { margin: 0; }
.profile-note { margin: 8px 0 0; font-size: 0.74rem; color: var(--muted); }

/* Allocated points shown as a distribution: the save records what was spent,
   and gear changes the resulting maximums, so a derived total would be a guess. */
.alloc-line { display: grid; grid-template-columns: 1fr 2.6rem 5rem; gap: 10px; align-items: baseline; font-size: 0.82rem; }
.alloc-line + .alloc-line { margin-top: 5px; }
.alloc-name { color: var(--muted); }
.alloc-bar { height: 7px; border-radius: 4px; background: rgba(0, 0, 0, 0.35); border: 1px solid var(--line); overflow: hidden; }
.alloc-bar i { display: block; height: 100%; background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 55%, transparent), var(--accent)); }
.alloc-amt { text-align: right; font-variant-numeric: tabular-nums; color: var(--text); }
.alloc-eff { text-align: right; font-size: 0.76rem; color: var(--accent); font-variant-numeric: tabular-nums; }

.paldet-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; margin: 12px 0 8px; }
.paldet-head span { font-size: 0.78rem; color: var(--muted); }
.iv-list { display: grid; gap: 5px; }
.iv-row { display: grid; grid-template-columns: 4.4rem 1fr 2.2rem; gap: 8px; align-items: center; font-size: 0.78rem; color: var(--muted); }
.iv-bar { height: 7px; border-radius: 4px; background: rgba(0, 0, 0, 0.35); border: 1px solid var(--line); overflow: hidden; }
.iv-bar i { display: block; height: 100%; background: var(--muted); }
.iv-bar i[data-tier="high"] { background: var(--good); }
.iv-bar i[data-tier="mid"] { background: var(--accent); }
.iv-num { text-align: right; color: var(--text); font-variant-numeric: tabular-nums; }
#profile-pal-detail h4 {
    margin: 12px 0 6px;
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--muted);
}
.chips { display: flex; flex-wrap: wrap; gap: 5px; }
.chip {
    background: color-mix(in srgb, var(--accent) 10%, transparent);
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: 3px 9px;
    font-size: 0.74rem;
}
.chip.soul {
    background: color-mix(in srgb, var(--warn) 12%, transparent);
    border-color: color-mix(in srgb, var(--warn) 34%, transparent);
    color: var(--warn);
}

/* The card's way into the sheet. */
.sheet-open {
    margin-top: 10px;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 0.82rem;
    background: color-mix(in srgb, var(--accent) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--accent) 34%, transparent);
    color: var(--text);
    border-radius: 9px;
    padding: 7px 10px;
}
.sheet-open:hover { background: color-mix(in srgb, var(--accent) 18%, transparent); }

/* What is behind the button, sitting with the arrow rather than centred by
   space-between. It turns amber when a pal needs attention, so the card can
   still raise that without carrying the whole party. */
.sheet-note { margin-left: auto; font-size: 0.75rem; color: var(--muted); }
.sheet-open.warn {
    background: color-mix(in srgb, var(--warn) 12%, transparent);
    border-color: color-mix(in srgb, var(--warn) 42%, transparent);
}
.sheet-open.warn:hover { background: color-mix(in srgb, var(--warn) 20%, transparent); }
.sheet-open.warn .sheet-note { color: var(--warn); }

.pal-warning {
    flex: 1 0 100%;
    margin: 0 0 10px;
    padding: 8px 10px;
    border-radius: 9px;
    font-size: 0.8rem;
    line-height: 1.45;
    color: var(--text);
    background: color-mix(in srgb, var(--warn) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--warn) 38%, transparent);
}

/* Map layers modal: one toggle per row with a muted description. */
.layers-panel { max-width: 360px; }
.layers-list {
    padding: 12px 16px 16px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.layers-list .toggle span {
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.layers-list .toggle em {
    font-style: normal;
    font-size: 0.7rem;
    color: var(--muted);
}

/* Map quality picker (per-device; only for maps with encode variants). */
.layers-quality { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line); }
.layers-quality-title { margin: 0 0 8px; font-size: 0.8rem; font-weight: 650; }
.layers-quality-title em { font-style: normal; font-weight: 400; font-size: 0.7rem; color: var(--muted); }
.layers-quality-options { display: flex; gap: 6px; }
.quality-option {
    flex: 1;
    display: flex; flex-direction: column; align-items: center; gap: 2px;
    background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
    color: var(--text); padding: 8px 6px; font-size: 0.8rem; font-weight: 600; cursor: pointer;
}
.quality-option em { font-style: normal; font-size: 0.68rem; color: var(--muted); font-weight: 400; }
.quality-option:hover { border-color: color-mix(in srgb, var(--accent) 50%, var(--line)); }
.quality-option.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--panel)); }
.quality-option.on em { color: var(--text); }

/* The admin form's checkbox rows (reuses the map-controls .toggle look). */
.admin-toggle { margin: 4px 0 2px; font-size: 0.8rem; }
.admin-toggle em { color: var(--muted); font-style: normal; font-size: 0.72rem; }

/* "Displayed on the map" — the per-server display-feature toggles. */
.admin-display {
    margin-top: 10px;
    padding: 10px 12px 8px;
    border: 1px solid var(--line);
    border-radius: 8px;
}
.admin-display-title {
    margin: 0 0 6px;
    font-size: 0.8rem;
    font-weight: 600;
}
.admin-display-title em { color: var(--muted); font-style: normal; font-weight: 400; font-size: 0.72rem; }
.admin-display .admin-toggle { display: flex; }

/* ------------------------------------------------ user auth (identity layer) */
.landing-actions { display: flex; align-items: center; gap: 10px; }
.signin-button { white-space: nowrap; }
.user-chip {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 6px 4px 4px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--panel);
}
.user-avatar {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: var(--accent);
    color: #0b1017;
    font-weight: 700;
    font-size: 0.85rem;
}
.user-name { font-size: 0.85rem; font-weight: 600; }
.user-signout { font-size: 0.75rem; padding: 4px 8px; }

.login-panel { max-width: 360px; }
.login-panel .field { margin: 8px 0; }
.login-note {
    margin: 10px 0 0;
    font-size: 0.75rem;
    color: var(--muted);
}

/* The viewer's own player in the roster. */
.entity-card.mine .who strong::after {
    content: " you";
    color: #ffd666;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    margin-left: 4px;
}

/* Admin: the Users section. */
.admin-section-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin: 18px 0 8px;
    padding-top: 14px;
    border-top: 1px solid var(--line);
}
.admin-section-head h3 { margin: 0; font-size: 0.95rem; }
.admin-section-sub { font-size: 0.72rem; color: var(--muted); }
.admin-row .pip.user { background: var(--accent); }
.user-links {
    margin-top: 10px;
    padding: 10px 12px 8px;
    border: 1px solid var(--line);
    border-radius: 8px;
}
.links-group { margin: 6px 0; }
.links-game {
    margin: 0 0 2px;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* ------------------------------------------ privacy page (per-server) */
.privacy-panel { max-width: 760px; width: min(760px, 94vw); }
.privacy-sub { margin: 2px 0 0; color: var(--muted); font-size: 0.75rem; }

.section-tabs {
    display: flex; align-items: center; gap: 2px;
    margin: 10px 0 12px; border-bottom: 1px solid var(--line);
}
.section-tabs button {
    border: none; background: transparent; color: var(--muted);
    padding: 7px 13px 8px; font-size: 0.83rem; font-weight: 600; cursor: pointer;
    border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.section-tabs button:hover { color: var(--text); }
.section-tabs button.on { color: var(--text); border-bottom-color: var(--accent); }
.section-tabs button .n {
    display: inline-block; margin-left: 6px; font-size: 0.66rem; font-weight: 700;
    background: var(--panel); border: 1px solid var(--line); border-radius: 999px;
    padding: 0 6px; color: var(--muted);
}
.tabs-soon { margin-left: auto; font-size: 0.68rem; color: var(--muted); font-style: italic; }

.privacy-grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(230px, 1fr); gap: 18px; }
@media (max-width: 640px) { .privacy-grid { grid-template-columns: 1fr; } }

.privacy-facets .row {
    display: flex; align-items: center; gap: 14px;
    padding: 10px 0; border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
}
.privacy-facets .row:last-child { border-bottom: none; }
.privacy-facets .info { flex: 1; min-width: 0; }
.privacy-facets .info b { display: block; font-size: 0.88rem; font-weight: 600; }
.privacy-facets .info span { color: var(--muted); font-size: 0.73rem; }

.seg { display: flex; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; flex-shrink: 0; background: var(--panel); }
.seg button {
    border: none; background: transparent; color: var(--muted);
    padding: 6px 10px; font-size: 0.73rem; cursor: pointer; font-weight: 600;
    border-left: 1px solid var(--line);
}
.seg button:first-child { border-left: none; }
.seg button:hover:not(.on) { color: var(--text); }
.seg button.on { background: var(--accent); color: #0b1017; }

.privacy-preview-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.privacy-preview-head h3 { margin: 0; font-size: 0.8rem; font-weight: 650; }
.viewer-pick { margin-left: auto; display: flex; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; background: var(--panel); }
.viewer-pick button {
    border: none; background: transparent; color: var(--muted); padding: 5px 10px;
    font-size: 0.7rem; cursor: pointer; font-weight: 600; border-left: 1px solid var(--line);
}
.viewer-pick button:first-child { border-left: none; }
.viewer-pick button.on { background: #ffd666; color: #0b1017; }

.privacy-card {
    background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
    padding: 14px;
}
.privacy-card-head { display: flex; align-items: center; gap: 9px; }
.privacy-card-head b { font-size: 0.98rem; }
.pc-lvl {
    display: grid; place-items: center; width: 30px; height: 30px;
    background: var(--bg); border: 1px solid var(--line); border-radius: 8px;
    font-weight: 700; font-size: 0.85rem;
}
.pc-team { font-size: 0.7rem; color: var(--muted); border: 1px solid var(--line); border-radius: 999px; padding: 1px 8px; }
.pc-bar {
    position: relative; height: 19px; border-radius: 5px; background: #26120f;
    border: 1px solid var(--line); overflow: hidden; margin-top: 10px;
}
.pc-fill { position: absolute; inset: 0; background: linear-gradient(180deg,#57d364,#2f9e46); }
.pc-bar span {
    position: absolute; inset: 0; display: flex; align-items: center; padding: 0 8px;
    font-size: 0.7rem; font-weight: 700; color: #fff;
    text-shadow: 0 0 3px rgba(0,0,0,0.9), 0 1px 2px rgba(0,0,0,0.9);
}
.pc-party { margin-top: 10px; font-size: 0.78rem; }
.pc-meta { margin-top: 10px; color: var(--muted); font-size: 0.73rem; }
.pc-hidden {
    margin-top: 10px; padding-top: 8px; border-top: 1px dashed var(--line);
    color: var(--muted); font-size: 0.7rem; font-style: italic;
}
.privacy-note { margin: 8px 0 0; color: var(--muted); font-size: 0.7rem; }
.privacy-saved { margin: 10px 0 0; color: var(--good); font-size: 0.75rem; font-weight: 600; }
.privacy-facets .pos-sub { padding-left: 22px; }
.privacy-facets .pos-sub .info span { font-style: italic; }
.guild-rules-head { padding: 4px 0 8px; }
.guild-rules-head b { display: block; font-size: 0.95rem; }
.guild-rules-head span { color: var(--muted); font-size: 0.73rem; }
.base-rules {
    margin: 10px 0 4px; padding: 4px 12px 8px;
    border: 1px solid var(--line); border-radius: 10px;
}
.base-rules-title { padding: 8px 0 2px; font-size: 0.85rem; font-weight: 650; }
.base-rules-title span { color: var(--muted); font-weight: 400; font-size: 0.73rem; }

/* Playtime leaderboard (per-server setting). */
.leaderboard-list {
    list-style: none;
    counter-reset: lb;
    margin: 0;
    padding: 8px 12px;
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.leaderboard-list li {
    counter-increment: lb;
    display: flex;
    align-items: center;
    gap: 8px;
}
.leaderboard-list li::before {
    content: counter(lb);
    min-width: 16px;
    text-align: right;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    font-size: 0.7rem;
}
.leaderboard-list .lb-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: 6px;
}
.leaderboard-list .lb-online {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--good);
    flex: none;
}
.leaderboard-list strong {
    font-variant-numeric: tabular-nums;
    font-size: 0.76rem;
    flex: none;
}

/* Join/leave feed from the server's player memory. */
.activity-list {
    list-style: none;
    margin: 0;
    padding: 8px 12px;
    max-height: 180px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.activity-list li {
    display: flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
}
.activity-list .event-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex: none;
}
.activity-list .event-dot.joined { background: var(--good); }
.activity-list .event-dot.left { background: var(--bad); }
.activity-list span {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.activity-list time {
    color: var(--muted);
    font-size: 0.68rem;
    font-variant-numeric: tabular-nums;
    flex: none;
}

/* World-settings rules card (e.g. Palworld difficulty/rates). */
.rules-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; padding: 10px 12px; }
.rules-grid div { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.rules-grid span { font-size: 0.64rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
.rules-grid strong { font-size: 0.76rem; overflow-wrap: anywhere; }
#health-state { color: var(--text); font-variant-numeric: tabular-nums; }
.health-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; padding: 10px 12px; }
.health-grid div { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.health-grid span { font-size: 0.64rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
.health-grid strong { font-size: 0.76rem; overflow-wrap: anywhere; }

/* --------------------------------------------- mobile hierarchy + fitting */

@media (max-width: 760px) {
    /* The roster comes first; controls drop below it. */
    .sidebar { display: flex; }
    .sidebar-header { order: 0; }
    .game-heading { order: 1; }
    #map-switcher { order: 2; }
    .roster-section { order: 3; }
    .entity-detail { order: 4; }
    .metrics { order: 5; }
    .coord-goto { order: 7; }
    .side-panel { order: 8; }
    .health-panel { order: 9; }
    .version-line { order: 10; }
    footer { order: 11; margin-top: 8px; }

    /* Collapsing the bottom panel gives the map the full height. */
    .app-shell.sidebar-collapsed { grid-template-rows: 100dvh 0; }

    .world-clock { font-size: 0.7rem; }
    .world-clock-dial { width: 38px; }
}


/* ------------------------------------------------ zomboid character sheet */

/* Skills are a long list of small numbers; a bar per row makes the shape of a
   character readable at a glance without reading any of them. */
.skill-list { display: flex; flex-direction: column; gap: 6px; }
.skill-row { display: grid; grid-template-columns: 1fr 90px 26px; align-items: center; gap: 10px; }
.skill-row span { font-size: 0.82rem; }
.skill-bar { height: 6px; border-radius: 999px; background: rgba(0, 0, 0, 0.35); overflow: hidden; }
.skill-bar i { display: block; height: 100%; background: var(--accent); border-radius: inherit; }
.skill-row b { font-size: 0.8rem; text-align: right; font-variant-numeric: tabular-nums; }

/* A survivor's condition: the things that will kill them, loudest first. */
.condition-flag {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 10px;
    border-radius: 9px;
    font-size: 0.82rem;
    margin-bottom: 8px;
}
.condition-flag[data-level="bad"] {
    background: color-mix(in srgb, var(--bad, #e5484d) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--bad, #e5484d) 42%, transparent);
}
.condition-flag[data-level="warn"] {
    background: color-mix(in srgb, var(--warn) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--warn) 38%, transparent);
}

/* A source-reported event (a Zomboid death). Neither a join nor a leave, and
   the one line in the feed anybody scrolls back to find. */
.event-dot.notable { background: var(--bad, #e5484d); }

/* ---------------------------------------------------------------- zomboid */

/* Knox County after the outbreak: the game's own palette is desaturated olive
   and bone, with a rusted orange for anything that matters. Deliberately
   grimmer than the other two -- a survival horror map should not look like a
   creature collector's. */
.app-shell[data-theme="zomboid"],
body[data-theme="zomboid"] {
    --bg: #101208;
    --panel: #191c12;
    --panel-2: #222618;
    --line: rgba(176, 168, 122, 0.16);
    --text: #e9e6d6;
    --muted: #97957f;
    --accent: #c8783c;
    --good: #8aa653;
    --warn: #d9a441;
    --bad: #c0483c;
}

.app-shell[data-theme="zomboid"] .sidebar {
    background:
        radial-gradient(circle at 0 0, rgba(120, 98, 44, 0.20), transparent 22rem),
        rgba(14, 16, 9, 0.98);
    box-shadow: 14px 0 36px rgba(0, 0, 0, 0.35);
}

/* The map is mostly forest; the surround leans earthy rather than blue so the
   basemap's edges do not sit on a colour the game never uses. */
.app-shell[data-theme="zomboid"] .map-stage {
    background: radial-gradient(1200px 700px at 70% 30%, #2a2c18 0%, var(--bg) 72%);
}

/* ------------------------------------------------- sidebar conditions line */

/* World state -- date, weather, how many nights survived -- reads as one
   sentence rather than five chips competing with the server's own counts. */
.conditions-line {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 10px;
    margin: -2px 0 10px;
    font-size: 0.76rem;
    color: var(--muted);
}
.conditions-line b {
    color: var(--text);
    font-weight: 600;
}

/* ------------------------------------------------ accounts and the portal */

/* Placeholders are examples, not values: dimmer and italic so "default 2"
   never reads as something already filled in. */
input::placeholder { color: color-mix(in srgb, var(--muted) 70%, transparent); font-style: italic; opacity: 1; }

.manage-button { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }

.user-chip-open {
    display: flex;
    align-items: center;
    gap: 8px;
    background: transparent;
    border: 0;
    padding: 0 4px 0 0;
    color: var(--text);
    cursor: pointer;
    border-radius: 999px;
}
.user-chip-open:hover .user-name { text-decoration: underline; }

.sidebar-account { display: flex; align-items: center; gap: 6px; flex: none; }
.map-signin { font-size: 0.74rem; padding: 4px 9px; min-height: 0; }
.map-account {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    padding: 0;
    border: 0;
    background: var(--accent);
    color: #0b1017;
    font-weight: 700;
    font-size: 0.85rem;
    cursor: pointer;
}

.account-panel { max-width: 420px; }
.account-sub { margin: 2px 0 0; font-size: 0.78rem; color: var(--muted); }
.account-password {
    border: 1px solid var(--line);
    border-radius: 9px;
    padding: 6px 12px 10px;
    margin: 6px 0;
}
.account-password legend { font-size: 0.8rem; font-weight: 600; padding: 0 4px; }
.account-password legend em, .account-links em { font-style: normal; color: var(--muted); font-weight: 400; }
.account-note { margin: 4px 0 0; font-size: 0.74rem; color: var(--muted); }
.account-links { margin: 6px 0 10px; }
.account-links ul { margin: 6px 0 0; padding-left: 18px; font-size: 0.82rem; }
.account-links li span { color: var(--muted); }
.account-signout, .form-delete { margin-left: auto; }

/* Admin rows: a username is a handle, not a type badge. */
.row-handle { color: var(--muted); font-size: 0.76rem; font-weight: 400; margin-left: 6px; }
.badge.you { color: #ffd666; border-color: color-mix(in srgb, #ffd666 40%, var(--line)); }
.admin-notice { margin: 0; }

/* Save and Test stay in reach at the bottom of a long server form. */
.sticky-actions {
    position: sticky;
    /* Sticky insets measure from inside the overlay's padding, which left
       rows showing beneath the bar; reach past it to the screen's edge. */
    bottom: calc(-1 * var(--overlay-pad, 0px));
    z-index: 1;
    background: var(--panel);
    padding: 10px 0;
    border-top: 1px solid var(--line);
}

/* The first section needs no divider above it. */
#admin-body > .admin-section-head:first-of-type { border-top: 0; padding-top: 0; margin-top: 0; }
