:root {
  color-scheme: dark;
  --site-bg: #07110d;
  --site-bg-raised: #0d1c15;
  --site-surface: #12261c;
  --site-surface-strong: #193326;
  --site-ink: #edf6ef;
  --site-muted: #a7baad;
  --site-faint: #718579;
  --site-accent: #74c991;
  --site-accent-strong: #8cdda7;
  --site-danger: #ee7a75;
  --site-danger-line: #ee7a7566;
  --site-danger-surface: #24110f;
  --site-line: #b7d0bf26;
  --site-line-strong: #a8c8b454;
  --site-shadow: 0 1.25rem 4rem #02080566;
  --site-panel-radius: 12px;
  --site-control-radius: 8px;
  --site-font: "Segoe UI Variable", Aptos, "Helvetica Neue", Arial, sans-serif;
  --site-mono: "Cascadia Code", "SFMono-Regular", Consolas, monospace;
  --site-space-1: .25rem;
  --site-space-2: .5rem;
  --site-space-3: .75rem;
  --site-space-4: 1rem;
  --site-space-5: 1.5rem;
  --site-space-6: 2rem;
  --site-transition: 140ms ease;
  --map-canvas: #07100c;
  --map-grid: #9cc3a5;
  --map-world-edge: #d3e3d6;
  --map-marker-halo: #07100c;
  --map-zone: #8dc79a;
  --map-location: #e6c15a;
  --map-location-spawn: #df453e;
  --map-location-spawn-accent: #fff8e8;
  --map-location-boss: #ff796c;
  --map-location-trader: #66d9d0;
  --map-location-dungeon: #b79bf2;
  --map-location-shrine: #ef8ad4;
  --map-location-tower: #a8d84f;
  --map-location-fortress: #ed9b62;
  --map-location-arena: #7ce87c;
  --map-location-mine: #d99a3f;
  --map-location-port: #8f8cff;
  --map-location-monument: #a9c8e8;
  --map-location-settlement: #72d68d;
  --map-location-resource: #e8d467;
  --map-location-ruins: #ab9c85;
  --map-location-landmark: #7dbcf2;
  --map-location-other: #b5c0b8;
  --map-location-pending: #9a8246;
  --map-build: #64d486;
  --map-portal: #7dbcf2;
  --map-container: #d0a06a;
  --map-production: #c69ae8;
  --map-creature: #dce9df;
  --map-vehicle: #f0c66b;
  --map-risk: #ef807b;
  --map-other: #b5c0b8;
  /* The roads layer. Paved and hoed-dirt ground reads as a warm pale track so it separates from
     every biome underneath it; cultivated ground is the green of a field; moved earth is a muted
     brown so a levelled platform or a dug moat is visible without competing with the road on it.
     Six-digit hex only: rgbToken parses these into pixels and refuses anything else. */
  --map-road: #e8dcc0;
  --map-road-cultivated: #8fa860;
  --map-road-earth: #9c8466;
  --map-biome-void: #07100c;
  --map-biome-void-texture: #14221a;
  --map-biome-ocean: #14374d;
  --map-biome-ocean-texture: #2d637c;
  --map-biome-deep-north: #8baac0;
  --map-biome-deep-north-texture: #c4d7df;
  --map-biome-meadows: #6f8f54;
  --map-biome-meadows-texture: #a7c47c;
  --map-biome-black-forest: #294b35;
  --map-biome-black-forest-texture: #50725a;
  --map-biome-swamp: #4f5147;
  --map-biome-swamp-texture: #777b68;
  --map-biome-mountain: #c7d1cd;
  --map-biome-mountain-texture: #edf3ef;
  --map-biome-plains: #b5ad4a;
  --map-biome-plains-texture: #ded27a;
  --map-biome-mistlands: #806456;
  --map-biome-mistlands-texture: #ae8975;
  --map-biome-ashlands: #9e4036;
  --map-biome-ashlands-texture: #d16d5c;
  --map-sidebar-left: 17rem;
  --map-sidebar-right: 19rem;
}

html { background: var(--site-bg); accent-color: var(--site-accent); }
* { box-sizing: border-box; }
body {
  background:
    radial-gradient(circle at 92% -8%, #28583f55 0, transparent 32rem),
    linear-gradient(145deg, var(--site-bg) 0%, #0b1b13 48%, #08120e 100%) fixed !important;
  color: var(--site-ink) !important;
  font-family: var(--site-font) !important;
  line-height: 1.55;
  text-rendering: optimizeLegibility;
}
body::selection { background: #74c99148; color: #fff; }

h1, h2, h3, legend, summary, strong { color: var(--site-ink); }
h1, h2, h3 { text-wrap: balance; letter-spacing: -.025em; }
h1 { line-height: 1.05; }
p, li, td, th, label, small { text-wrap: pretty; }
small, .muted { color: var(--site-muted) !important; }
body p:not(.muted), body li:not(.muted), body td, body label { color: var(--site-ink) !important; }
a { color: var(--site-accent-strong); text-underline-offset: .2em; text-decoration-thickness: 1px; }
a:hover { color: #c0f0ce; }

button, input, select, textarea {
  min-height: 2.65rem;
  border: 1px solid var(--site-line-strong);
  border-radius: var(--site-control-radius);
  background: #0a1711;
  color: var(--site-ink);
  font: inherit;
}
input, select, textarea { padding: .62rem .75rem; }
input::placeholder, textarea::placeholder { color: #82978a; opacity: 1; }
button, [class*="button"], a.download {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: fit-content;
  padding: .62rem .9rem;
  border-color: #8dd6a660;
  background: #2c7048;
  color: #fff;
  font-weight: 700;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: 0 .5rem 1.5rem #04150c40;
  cursor: pointer;
  transition: background-color 140ms ease, border-color 140ms ease, transform 90ms ease;
}
button:hover, [class*="button"]:hover, a.download:hover { background: #37865a; color: #fff; }
button:active, [class*="button"]:active, a.download:active { transform: translateY(1px); }
button.danger, .danger button, button[formaction*="remove"], button[formaction*="delete"] { background: #8d3937; border-color: #ed8d885e; }
button.danger:hover, .danger button:hover, button[formaction*="remove"]:hover, button[formaction*="delete"]:hover { background: #a84844; }
/* After the hover rules on purpose: a control that cannot be used must not
   light up under the cursor. */
button:disabled, button:disabled:hover {
  border-color: var(--site-line);
  background: var(--site-surface-strong);
  color: var(--site-faint);
  box-shadow: none;
  cursor: not-allowed;
}
:focus-visible { outline: 3px solid #9be3b6; outline-offset: 3px; }

/* Every template now carries a real <head>, so render() links this file after
   each page's inline <style> and the cascade no longer has to be forced. */
section, article, fieldset, details.admin-widget {
  border-color: var(--site-line);
  background: color-mix(in srgb, var(--site-surface) 88%, transparent);
  box-shadow: var(--site-shadow);
}
section, fieldset, details.admin-widget { border-radius: var(--site-panel-radius); }
/* A permanent deletion must not look like the reversible action above it. */
section.danger {
  border-color: var(--site-danger-line);
  border-left: 4px solid var(--site-danger);
  background: linear-gradient(180deg, var(--site-danger-surface) 0%, #190d0b 100%);
  box-shadow: 0 1.25rem 4rem #1a050566;
}
section.danger h2 { color: #ffb4ac; }
section.danger code { color: #ffcac3; }
section.danger p { color: #edcdc7 !important; }
fieldset { padding: clamp(1rem, 2vw, 1.35rem); }
legend { padding: 0 .4rem; font-weight: 760; }
summary { cursor: pointer; font-weight: 760; }
summary::marker { color: var(--site-accent); }
details.admin-widget > summary {
  background: #102219 !important;
  color: var(--site-ink) !important;
  border-color: var(--site-line) !important;
}
hr { border: 0; border-top: 1px solid var(--site-line); }
code, pre { font-family: var(--site-mono); }
code { color: #bde7ca; }
pre {
  max-width: 100%;
  overflow: auto;
  padding: .85rem;
  border: 1px solid var(--site-line);
  border-radius: var(--site-control-radius);
  background: #07110d;
  color: #cfe2d5;
  line-height: 1.45;
}

table { width: 100%; border-collapse: collapse; }
th { color: var(--site-muted); font-size: .78rem; letter-spacing: .06em; text-align: left; text-transform: uppercase; }
th, td { padding: .7rem .65rem; border-bottom: 1px solid var(--site-line); vertical-align: top; }
tr:last-child td { border-bottom: 0; }

.brand-logo { background: transparent !important; border-radius: 0 !important; padding: 0 !important; }
.brand:has(.rune) { font-size: 0 !important; }
.brand:has(.rune)::after {
  content: "Gaming";
  color: var(--site-muted);
  font-size: .72rem;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
}
.brand .rune {
  display: inline-block;
  width: 10rem !important;
  height: 2.25rem !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: url("/assets/neuralyze-logo.svg") center / contain no-repeat !important;
  font-size: 0 !important;
}
.status-light { border-radius: 999px; }
.status.status-online { color: var(--site-accent-strong) !important; }
.status.status-offline { color: var(--site-muted) !important; }
.status.status-online::before { background: #b7ffd0 !important; box-shadow: 0 0 .6rem #8effa8 !important; }
.status.status-offline::before { background: #7f9086 !important; box-shadow: none !important; }
.status-light.status-online { color: #9be3b6 !important; background: #153b27 !important; }
.status-light.status-offline { color: #a7b1aa !important; background: #202823 !important; }

/* An admin-mode maintenance window. Red rather than the amber of a warning, because the
   world is not degraded - it is unusable: every player who joins it is disconnected. It
   has to read as loud in the collapsed card summary as it does in the open card, since a
   closed <details> is the state an operator scrolls past. */
.admin-mode-badge {
  display: inline-block;
  padding: .1rem .5rem;
  border-radius: 999px;
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .04em;
  color: #ffe3e3 !important;
  background: #7d1f1f !important;
}
.admin-mode-notice {
  margin: 0 0 var(--site-space-3);
  padding: .75rem 1rem;
  border: 1px solid #d16a6a;
  border-radius: .7rem;
  color: #ffe9e9 !important;
  background: #40151566;
}
.admin-mode-notice strong { color: #ffc9c9 !important; }

/* Player pages: choosing a profile, and the two values worth copying. */
/* A heading for the grid below it, not another panel competing with the cards. */
section.choose {
  margin: var(--site-space-6) 0 var(--site-space-3);
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
}
.choose h2 { margin: 0; font-size: 1.35rem; }
.choose-hint { margin: var(--site-space-1) 0 0; color: var(--site-muted) !important; }
.profile-card-recommended {
  border-color: #8cdda766 !important;
  box-shadow: 0 1rem 2rem #0003, 0 0 0 1px #8cdda73d;
}
.profile-card .eyebrow { color: var(--site-muted); }
.profile-card-recommended .eyebrow { color: var(--site-accent-strong); }
.profile-summary { margin: var(--site-space-3) 0 0; font-size: .96rem; }
.profile-slug {
  display: block;
  margin-top: .15rem;
  font-family: var(--site-mono);
  font-size: .78rem;
  overflow-wrap: anywhere;
}
.sync.sync-secondary {
  border: 1px solid var(--site-line-strong);
  background: transparent;
  color: var(--site-ink);
}
.sync.sync-secondary:hover { background: #ffffff12; }
/* The guide link sits under the install button on every profile card. It is
   deliberately quieter than .sync: installing is the action a player came for,
   reading is the thing they do once. */
.guide-link {
  display: inline-block;
  /* It sits between the summary and the version row now, so it needs air on both
     sides rather than only above. */
  margin: var(--site-space-2) 0;
  color: var(--site-muted);
  font-size: .88rem;
  text-decoration: underline;
}
.guide-link:hover { color: var(--site-ink); }
/* Long-form prose, so the body is measured in characters rather than pixels and
   the key tables are allowed to scroll rather than squeeze the page. */
/* The guide has no inline page CSS of its own, so .shell gets its width here.
   Without this the prose sits flush against the left viewport edge. */
body.guide {
  /* Type scales with the viewport so a 27-inch monitor reads at a comfortable size
     instead of showing the same 16px column it shows on a laptop. Because the
     reading measure below is in ch, growing the type also widens the column: the
     page fills more of the screen without the line length becoming unreadable. */
  font-size: clamp(1rem, 0.62rem + 0.52vw, 1.32rem) !important;
}
body.guide .shell {
  /* The shell is the outer bound, wide enough for a key table to stretch into.
     Prose does not use all of it - the grid below keeps text on a measure - so
     this is deliberately much wider than a reading column. */
  width: min(110rem, calc(100% - 3rem));
  margin-inline: auto;
  padding-block: var(--site-space-4) var(--site-space-6);
}
/* Three tracks: prose sits in the centre one at a readable measure, and anything
   that benefits from width breaks out across all three. The 128-row key reference
   is the reason this exists. */
.guide-body {
  display: grid;
  grid-template-columns:
    minmax(0, 1fr)
    minmax(0, min(78ch, 100%))
    minmax(0, 1fr);
}
.guide-body > * { grid-column: 2; }
/* Tables may use the whole shell, but they are sized to their content and centred
   rather than stretched edge to edge: a two-column table pinned to both gutters
   puts a metre of empty space between its columns and reads as broken alignment.
   Centring is justify-self, not margin-inline:auto -- the base .guide-body table
   rule below sets `margin: … 0`, has equal specificity and comes later, so it
   would silently reset an auto inline margin. */
.guide-body > table {
  grid-column: 1 / -1;
  justify-self: center;
  width: fit-content;
  max-width: 100%;
}
/* The header lines share the prose measure so the left edge stays honest. */
body.guide .back, body.guide .guide-switch, body.guide .guide-footer {
  display: block;
  width: min(78ch, 100%);
  margin-inline: auto;
}

.guide-body h1, .guide-body h2, .guide-body h3 { margin: var(--site-space-5) 0 var(--site-space-2); }
.guide-body table {
  border-collapse: collapse;
  margin: var(--site-space-3) 0;
}
/* Narrow screens keep horizontal scroll instead: a key table has no useful way to
   fit a phone, and squeezing it makes every row unreadable rather than one clipped. */
@media (max-width: 60rem) {
  .guide-body > table { display: block; width: 100%; overflow-x: auto; }
}
.guide-body th, .guide-body td {
  padding: .35rem .6rem;
  border-bottom: 1px solid var(--site-line);
  text-align: left;
  vertical-align: top;
}
.guide-body code { font-family: var(--site-mono); font-size: .88em; }
.guide-switch { color: var(--site-muted); font-size: .92rem; }
/* Contents. It sits on the prose measure like the rest of the header, and columns
   up on a wide screen so a dozen sections do not become a dozen lines of scrolling
   before the guide starts. */
.guide-toc {
  width: min(78ch, 100%);
  margin: var(--site-space-4) auto;
  padding: var(--site-space-3) var(--site-space-4);
  border: 1px solid var(--site-line);
  border-radius: var(--site-panel-radius);
  background: #ffffff08;
}
.guide-toc h2 {
  margin: 0 0 var(--site-space-2);
  font-size: .82rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--site-muted);
}
.guide-toc ol {
  margin: 0;
  padding-left: 1.35rem;
  columns: 2;
  column-gap: var(--site-space-5);
}
.guide-toc li { break-inside: avoid; margin: 0 0 .2rem; }
@media (max-width: 48rem) { .guide-toc ol { columns: 1; } }
.guide-footer { margin: var(--site-space-5) 0 var(--site-space-4); color: var(--site-muted); font-size: .85rem; }
/* Block-level so the address never shares a line with the sentence that
   follows it; the value is the thing being pointed at. */
.copy-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--site-space-2);
  margin: var(--site-space-2) 0;
  width: fit-content;
}
.copy-value {
  padding: .2rem .5rem;
  border: 1px solid var(--site-line);
  border-radius: var(--site-control-radius);
  background: #07110d;
  font-size: .92rem;
  overflow-wrap: anywhere;
  user-select: all;
}
.copy-button {
  min-height: 2.1rem;
  padding: .25rem .6rem;
  border: 1px solid var(--site-line-strong);
  background: transparent;
  color: var(--site-ink);
  font-size: .8rem;
  box-shadow: none;
}
.copy-button:hover { background: #ffffff12; color: var(--site-ink); }
.copy-button.copied { border-color: #8cdda766; color: var(--site-accent-strong); }
.empty-access h3 { margin: 0 0 var(--site-space-2); font-size: 1.05rem; }
.install-note { margin: var(--site-space-2) 0 0; color: var(--site-muted) !important; font-size: .85rem; }
.admin-nav a {
  border-color: var(--site-line) !important;
  border-radius: var(--site-control-radius) !important;
  background: #10231a !important;
  color: var(--site-ink) !important;
  box-shadow: none !important;
}
.admin-overview {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: .7rem;
  padding: .8rem !important;
}
.admin-overview article {
  display: grid;
  gap: .1rem;
  min-width: 0;
  padding: .8rem .9rem;
  border: 0;
  border-left: 2px solid #74c99166;
  border-radius: 0;
  background: transparent !important;
  box-shadow: none;
}
.admin-overview strong { font-size: 1.45rem; line-height: 1; }
.admin-overview span { color: var(--site-muted); font-size: .78rem; }
.admin-nav a:hover { border-color: #74c9917a !important; background: #173326 !important; }
.admin-nav span { color: var(--site-muted) !important; }
body:has(.admin-nav) { width: min(1280px, calc(100% - 2rem)); max-width: 1280px; }

/* Server operations: each world is a self-contained capsule card. */
#servers .server-card {
  display: grid;
  gap: var(--site-space-3);
  margin: var(--site-space-3) 0 0;
  padding: var(--site-space-4);
  border: 1px solid var(--site-line-strong) !important;
  border-radius: var(--site-panel-radius);
  background: linear-gradient(180deg, #16301f 0%, #112418 100%) !important;
  box-shadow: 0 .5rem 1.5rem #02080540;
  transition: border-color var(--site-transition), box-shadow var(--site-transition), transform var(--site-transition);
}
#servers .server-card:first-of-type { margin-top: var(--site-space-4); }
#servers .server-card:hover {
  border-color: #74c9915c !important;
  box-shadow: 0 .85rem 2.25rem #0208054d;
}
/* A fleet of tall cards is unreadable expanded, so each world collapses to its
   name. The card's own grid gap only applies to a single child now, so the open
   body owns the spacing between header, controls, sections, and footer. */
#servers .server-card-body[open] {
  display: grid;
  gap: var(--site-space-3);
}
/* display:flex suppresses ::marker, so the collapsed row had no sign it opened
   at all. The chevron is drawn from two borders rather than a glyph, so it does
   not depend on a font shipping the character. */
#servers .server-card-body > summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--site-space-2) var(--site-space-3);
  list-style: none;
}
#servers .server-card-body > summary::-webkit-details-marker { display: none; }
#servers .server-card-body > summary::after {
  content: "";
  flex: 0 0 auto;
  width: .5rem;
  height: .5rem;
  margin-left: auto;
  border-right: 2px solid var(--site-accent);
  border-bottom: 2px solid var(--site-accent);
  rotate: -45deg;
  translate: 0 -.1rem;
  transition: rotate var(--site-transition);
}
#servers .server-card-body[open] > summary::after { rotate: 45deg; translate: 0 -.15rem; }
.server-card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--site-space-2) var(--site-space-3);
}
.server-card-name {
  margin: 0;
  font-size: 1.08rem;
  font-weight: 800;
  letter-spacing: .01em;
}
.server-card-address {
  padding: .2rem .5rem;
  border: 1px solid var(--site-line);
  border-radius: var(--site-control-radius);
  background: #07110d;
  font-size: .82rem;
}
.server-card-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--site-space-3);
  margin-left: auto;
  font-size: .85rem;
}
.server-card-controls {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15.5rem, 1fr));
  gap: var(--site-space-3);
}
#servers .server-card-control {
  display: grid;
  align-content: start;
  gap: var(--site-space-2);
  min-width: 0;
  margin: 0;
  padding: var(--site-space-3);
  border: 1px solid var(--site-line);
  border-radius: var(--site-control-radius);
  background: #0c1c14;
}
#servers .server-card-control > label,
.server-card-control-title {
  display: grid;
  gap: var(--site-space-1);
  min-width: 0;
  color: var(--site-muted) !important;
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
}
#servers .server-card-control select,
#servers .server-card-control input {
  width: 100%;
  min-width: 0;
  font-size: .9rem;
  text-transform: none;
}
#servers .server-card-control button { width: 100%; font-size: .85rem; }
/* Player access has no input, so pin its button to the tile floor and keep the
   action row aligned with the sibling tiles. */
#servers .server-card-control-wide { grid-template-rows: auto 1fr; }
#servers .server-card-control-wide button { align-self: end; }
.server-card-footer {
  display: flex;
  justify-content: flex-end;
  padding-top: var(--site-space-3);
  border-top: 1px solid var(--site-line);
}
.server-card-footer .button-link.danger { font-size: .85rem; }

/* Toolbar above the cards: create a server, register a discovered one. */
.server-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--site-space-4);
  margin: var(--site-space-4) 0 0;
  padding: var(--site-space-4);
  border: 1px solid var(--site-line);
  border-radius: var(--site-panel-radius);
  background: #102219;
}
.server-toolbar-intro { flex: 1 1 22rem; min-width: 0; }
.server-toolbar-intro p { margin: 0; }
.server-toolbar-intro p + p { margin-top: var(--site-space-2); font-size: .88rem; }
.server-toolbar-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--site-space-2);
  margin-left: auto;
}
.button-link.secondary {
  border: 1px solid var(--site-line-strong);
  background: transparent;
  color: var(--site-ink);
}
#servers .server-adopt {
  margin: var(--site-space-3) 0 0;
  padding: 0 var(--site-space-4) var(--site-space-3);
  border: 1px solid var(--site-line);
  border-radius: var(--site-panel-radius);
  background: #0e2017 !important;
  box-shadow: none;
}
#servers .server-adopt:not([open]) { padding-bottom: 0; }
#servers .server-adopt > summary {
  margin: 0 calc(-1 * var(--site-space-4));
  padding: var(--site-space-3) var(--site-space-4);
  font-size: .95rem;
}
.server-adopt-form {
  align-items: end;
  padding: var(--site-space-3);
  border: 1px solid var(--site-line);
  border-radius: var(--site-control-radius);
  background: #0c1c14;
}

/* Per-world admin, embedded in the card and collapsed by default. */
.server-card-sections {
  display: grid;
  gap: var(--site-space-2);
}
#servers .server-card-section {
  padding: 0 var(--site-space-3) var(--site-space-3);
  border: 1px solid var(--site-line);
  border-radius: var(--site-control-radius);
  background: #0c1c14 !important;
  box-shadow: none;
}
#servers .server-card-section:not([open]) { padding-bottom: 0; }
#servers .server-card-section > summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--site-space-2);
  margin: 0 calc(-1 * var(--site-space-3));
  padding: var(--site-space-3);
  font-size: .92rem;
}
#servers .server-card-section > summary small { color: var(--site-muted); font-weight: 500; }
#servers .server-card-section h4 {
  margin: var(--site-space-4) 0 0;
  color: var(--site-muted);
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
}
#servers .server-card-section > p { margin: var(--site-space-2) 0; font-size: .88rem; }
#servers .server-card-section table { margin-top: var(--site-space-3); }
#servers .server-card-section pre { margin: var(--site-space-2) 0 0; font-size: .78rem; }
.server-card-form {
  align-items: end;
  margin: var(--site-space-3) 0 0 !important;
  padding: var(--site-space-3);
  border: 1px solid var(--site-line);
  border-radius: var(--site-control-radius);
  background: #07110d;
}
#servers .server-card-form select,
#servers .server-card-form input:not([type="file"]) { min-width: 0; }
.server-subrow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--site-space-2) var(--site-space-3);
  margin-top: var(--site-space-2);
  padding: var(--site-space-2) var(--site-space-3);
  border: 1px solid var(--site-line);
  border-radius: var(--site-control-radius);
  background: #07110d;
}
.server-subrow-stacked { display: grid; justify-items: start; }
#servers .server-subrow form { margin: 0 !important; }
#servers .server-subrow .button-link { margin-left: auto; font-size: .82rem; }
.server-tag {
  padding: .1rem .45rem;
  border: 1px solid var(--site-line-strong);
  border-radius: 999px;
  color: var(--site-muted);
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}

/* Player access: one capsule per Steam ID, listing the worlds it may join. */
#players .player-invite {
  margin: var(--site-space-3) 0 0;
  padding: 0 var(--site-space-4) var(--site-space-3);
  border: 1px solid var(--site-line);
  border-radius: var(--site-panel-radius);
  background: #0e2017 !important;
  box-shadow: none;
}
#players .player-invite:not([open]) { padding-bottom: 0; }
#players .player-invite > summary {
  margin: 0 calc(-1 * var(--site-space-4));
  padding: var(--site-space-3) var(--site-space-4);
  font-size: .95rem;
}
#players .player-invite > summary small { color: var(--site-muted); font-weight: 500; }
.player-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(21rem, 1fr));
  gap: var(--site-space-3);
  margin-top: var(--site-space-4);
}
#players .player-card {
  display: grid;
  align-content: start;
  gap: var(--site-space-2);
  min-width: 0;
  padding: var(--site-space-4);
  border: 1px solid var(--site-line-strong) !important;
  border-radius: var(--site-panel-radius);
  background: linear-gradient(180deg, #16301f 0%, #112418 100%) !important;
  box-shadow: 0 .5rem 1.5rem #02080540;
  transition: border-color var(--site-transition), box-shadow var(--site-transition);
}
#players .player-card:hover { border-color: #74c9915c !important; }
.player-card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--site-space-2);
}
.player-card-name { margin: 0; font-size: 1.02rem; font-weight: 800; }
.player-card-id {
  flex-basis: 100%;
  padding: .15rem .45rem;
  border: 1px solid var(--site-line);
  border-radius: var(--site-control-radius);
  background: #07110d;
  font-size: .78rem;
}
#players .player-card-meta { margin: 0; font-size: .82rem; }
.player-worlds {
  display: grid;
  gap: var(--site-space-2);
  margin: var(--site-space-2) 0 0;
  padding: 0;
  list-style: none;
}
.player-world {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--site-space-2);
  padding: var(--site-space-2) var(--site-space-3);
  border: 1px solid var(--site-line);
  border-radius: var(--site-control-radius);
  background: #0c1c14;
}
.player-world-name { font-weight: 700; text-decoration: none; }
.player-world-name:hover { text-decoration: underline; }
/* Keep the revoke action on the first line and drop the provenance note to its
   own line, so every row has the same shape regardless of actor name length. */
#players .player-world form { order: 2; margin: 0 !important; margin-left: auto !important; }
#players .player-world > small { order: 3; flex-basis: 100%; }
#players .player-world button { padding: .25rem .5rem; font-size: .76rem; }
.player-tag {
  padding: .1rem .45rem;
  border: 1px solid var(--site-line-strong);
  border-radius: 999px;
  color: var(--site-muted);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.player-tag.admin { border-color: #d9a51466; background: #3a2c07; color: #f0cf72; }
.player-card-actions {
  display: grid;
  gap: var(--site-space-2);
  margin-top: var(--site-space-2);
  padding-top: var(--site-space-3);
  border-top: 1px solid var(--site-line);
}
#players .player-card-actions form { align-items: end; margin: 0 !important; }
#players .player-card-actions select,
#players .player-card-actions input { min-width: 0; }

@media (max-width: 760px) {
  .player-grid { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: no-preference) {
  #servers .server-card:hover { transform: translateY(-1px); }
}

@media (max-width: 760px) {
  .server-card-links { margin-left: 0; }
  .server-card-controls { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 760px) {
  body { background-attachment: scroll; }
  .admin-nav { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  .admin-overview { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  form { align-items: stretch !important; }
  form > label { width: 100%; }
  button { max-width: 100%; }
  fieldset, label { min-width: 0; max-width: 100%; }
  input:not([type="checkbox"]):not([type="radio"]), select, textarea { width: 100%; max-width: 100%; }
  body[data-world] > header { flex-wrap: wrap; align-items: flex-start; }
  body[data-world] > header form { width: 100%; margin-left: 0 !important; }
  body[data-world] .layout {
    grid-template-columns: minmax(0, 1fr) !important;
    height: auto !important;
  }
  body[data-world] .map { order: 1; min-height: 65vh; height: 34rem; }
  body[data-world] .layout > aside:not(.right) { order: 2; overflow: visible; border: 0; border-top: 1px solid var(--site-line); }
  body[data-world] .right {
    display: block !important;
    order: 3;
    overflow: visible;
    border: 0;
    border-top: 1px solid var(--site-line);
  }
  table { display: block; overflow-x: auto; }
}

@media (max-width: 640px) {
  .shell { width: min(100% - 1rem, 1120px) !important; }
  .portal-account-actions {
    position: static !important;
    justify-content: flex-end;
    margin: .65rem 0 0;
  }
  .portal-nav-button { min-height: 2.75rem; }
  .hero {
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 1.1rem !important;
    padding: 1.5rem 0 2rem !important;
  }
  .hero h1 { font-size: clamp(2.25rem, 13vw, 3.35rem) !important; }
  .install { padding: 1rem !important; }
  .section-head {
    align-items: flex-start !important;
    flex-direction: column;
    gap: .2rem;
    margin-inline: 0 !important;
  }
  .worlds, .profile-list, .profiles { grid-template-columns: minmax(0, 1fr) !important; }
  .profile-card { min-height: 0 !important; }
  .facts { display: grid !important; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sync, .install .button { width: 100% !important; }
}

@media (max-width: 520px) {
  body:has(.admin-nav) { width: min(100% - 1rem, 1280px); }
  body:has(.admin-nav) > a[href="/"] {
    position: static !important;
    display: inline-flex;
    margin: .75rem 0 .25rem;
  }
  .admin-nav { grid-template-columns: minmax(0, 1fr) !important; gap: .5rem; }
  .admin-nav a { min-height: 3.5rem; }
  .admin-overview { gap: .45rem; padding: .55rem !important; }
  .admin-overview article { padding: .7rem !important; }
  .admin-widget { margin: .75rem 0 !important; padding-inline: .75rem !important; }
  .admin-widget > summary {
    align-items: flex-start !important;
    flex-wrap: wrap;
    margin-inline: -.75rem !important;
    padding: .85rem .75rem !important;
  }
  .admin-widget > summary small { flex-basis: 100%; }
  .admin-widget form > input[type="file"] { max-width: 100%; }
  .admin-widget form > button, .admin-widget form > .button-link { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; transition-duration: .01ms !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; }
}

[hidden] { display: none !important; }
.visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

.world-map-page {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  width: 100%;
  height: 100dvh;
  min-height: 0;
  margin: 0;
  overflow: hidden;
}
.map-header {
  z-index: 2;
  display: flex;
  align-items: center;
  gap: var(--site-space-4);
  padding: var(--site-space-3) var(--site-space-4);
  border-bottom: 1px solid var(--site-line);
  background: var(--site-bg-raised);
  box-shadow: 0 .5rem 2rem #0208054d;
}
.map-back { flex: 0 0 auto; }
.map-heading {
  display: flex;
  align-items: center;
  gap: var(--site-space-3);
  min-width: 0;
}
.map-heading h1 {
  margin: 0;
  font-size: 1.1rem;
  line-height: 1.2;
}
.map-snapshot {
  display: flex;
  align-items: center;
  gap: var(--site-space-2);
  min-width: 0;
  font-size: .78rem;
}
.map-snapshot .pill {
  max-width: 17rem;
  overflow: hidden;
  padding: var(--site-space-1) var(--site-space-2);
  border: 1px solid var(--site-line-strong);
  border-radius: 999px;
  color: var(--site-ink);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.map-analysis-form {
  display: flex;
  margin-left: auto;
}
.map-layout {
  display: grid;
  grid-template-columns: var(--map-sidebar-left) minmax(0, 1fr) var(--map-sidebar-right);
  min-width: 0;
  min-height: 0;
}
.map-sidebar {
  min-width: 0;
  overflow: auto;
  padding: var(--site-space-4);
  background: color-mix(in srgb, var(--site-bg-raised) 94%, transparent);
  scrollbar-color: var(--site-line-strong) transparent;
}
.map-controls { border-right: 1px solid var(--site-line); }
.map-inspector { border-left: 1px solid var(--site-line); }
.map-sidebar fieldset {
  margin: 0 0 var(--site-space-4);
  padding: var(--site-space-3);
  background: transparent !important;
  box-shadow: none;
}
.map-sidebar h2 {
  margin: var(--site-space-5) 0 var(--site-space-2);
  font-size: .86rem;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.map-sidebar h2:first-child { margin-top: 0; }
.map-layer {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: var(--site-space-2);
  margin: var(--site-space-2) 0;
  cursor: pointer;
}
.map-layer input {
  min-height: 0;
  margin: .22rem 0 0;
}
.map-layer:has(input:disabled) { color: var(--site-faint); cursor: not-allowed; }
.map-layer small { display: block; margin-top: var(--site-space-1); font-size: .7rem; }
.map-location-categories {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--site-space-3);
}
.map-location-categories legend { grid-column: 1 / -1; }
.map-location-categories .map-layer {
  margin: var(--site-space-1) 0;
  font-size: .78rem;
}
.map-detail {
  display: grid;
  gap: var(--site-space-2);
}
.map-detail input {
  width: 100%;
  min-height: 1.5rem;
}
.map-button-group {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: var(--site-space-2);
  margin-top: var(--site-space-3);
}
.map-button-group button { width: 100%; min-width: 2.65rem; }
.map-scale {
  display: block;
  margin-top: var(--site-space-3);
  color: var(--site-ink);
  font-family: var(--site-mono);
  font-size: .78rem;
}
#coverage-note { margin: var(--site-space-2) 0 0; font-size: .78rem; }
.map-legend ul {
  display: grid;
  gap: var(--site-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.map-legend li {
  display: grid;
  grid-template-columns: 1.5rem minmax(0, 1fr);
  align-items: center;
  gap: var(--site-space-2);
  color: var(--site-muted);
  font-size: .8rem;
}
.map-key {
  display: inline-grid;
  width: 1.35rem;
  height: 1.35rem;
  place-items: center;
  border: 1px solid currentColor;
  border-radius: 50%;
  background: var(--map-marker-halo);
  color: var(--site-muted);
  font-family: var(--site-mono);
  font-size: .8rem;
  font-style: normal;
  font-weight: 800;
  line-height: 1;
}
.map-key--terrain { color: var(--map-biome-meadows); }
.map-key--zone { color: var(--map-zone); }
.map-key--location { color: var(--map-location); }
.map-key--location-spawn { color: var(--map-location-spawn); }
.map-key--location-boss { color: var(--map-location-boss); }
.map-key--location-trader { color: var(--map-location-trader); }
.map-key--location-dungeon { color: var(--map-location-dungeon); }
.map-key--location-shrine { color: var(--map-location-shrine); }
.map-key--location-tower { color: var(--map-location-tower); }
.map-key--location-fortress { color: var(--map-location-fortress); }
.map-key--location-arena { color: var(--map-location-arena); }
.map-key--location-mine { color: var(--map-location-mine); }
.map-key--location-port { color: var(--map-location-port); }
.map-key--location-monument { color: var(--map-location-monument); }
.map-key--location-settlement { color: var(--map-location-settlement); }
.map-key--location-resource { color: var(--map-location-resource); }
.map-key--location-ruins { color: var(--map-location-ruins); }
.map-key--location-landmark { color: var(--map-location-landmark); }
.map-key--location-other { color: var(--map-location-other); }
.map-key--build { color: var(--map-build); }
.map-key--portal { color: var(--map-portal); }
.map-key--container { color: var(--map-container); }
.map-key--production { color: var(--map-production); }
.map-key--creature { color: var(--map-creature); }
.map-key--vehicle { color: var(--map-vehicle); }
.map-key--risk { color: var(--map-risk); }
.map-key--other { color: var(--map-other); }
.map-category-summary dl {
  display: grid;
  gap: var(--site-space-2);
  margin: 0;
}
.map-category-summary dl > div {
  padding-left: var(--site-space-2);
  border-left: 2px solid var(--site-line-strong);
}
.map-category-summary dt { color: var(--site-ink); font-weight: 700; }
.map-category-summary dd {
  margin: 0;
  color: var(--site-muted);
  font-size: .76rem;
}
.world-map-page .map {
  position: relative;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  border: 0 !important;
  border-radius: 0 !important;
  background: var(--map-canvas) !important;
  box-shadow: none;
}
#world-map {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--map-canvas);
  cursor: crosshair;
  touch-action: none;
}
#world-map:active { cursor: grabbing; }
.coords {
  position: absolute;
  left: var(--site-space-3);
  bottom: var(--site-space-3);
  padding: var(--site-space-1) var(--site-space-2);
  border: 1px solid var(--site-line);
  border-radius: var(--site-control-radius);
  background: color-mix(in srgb, var(--map-canvas) 88%, transparent);
  color: var(--site-ink);
  font-family: var(--site-mono);
  font-size: .78rem;
  pointer-events: none;
}
.map-status {
  position: absolute;
  left: 50%;
  top: 50%;
  max-width: min(24rem, calc(100% - var(--site-space-6)));
  translate: -50% -50%;
  padding: var(--site-space-3) var(--site-space-4);
  border: 1px solid var(--site-line-strong);
  border-radius: var(--site-control-radius);
  background: color-mix(in srgb, var(--site-bg-raised) 94%, transparent);
  color: var(--site-muted);
  box-shadow: var(--site-shadow);
  text-align: center;
}
.map-inspector .details {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.map-inspector ul { padding-left: var(--site-space-5); }

@media (max-width: 900px) {
  .world-map-page {
    display: block;
    height: auto;
    min-height: 100dvh;
    overflow: visible;
  }
  .map-header { flex-wrap: wrap; align-items: flex-start; }
  .map-heading { display: grid; gap: var(--site-space-1); }
  .map-analysis-form { width: 100%; margin-left: 0; }
  .map-analysis-form button { width: 100%; }
  .map-layout { grid-template-columns: minmax(0, 1fr); }
  .world-map-page .map {
    order: 1;
    height: min(70vh, 44rem);
    min-height: 30rem;
  }
  .map-controls {
    order: 2;
    overflow: visible;
    border: 0;
    border-top: 1px solid var(--site-line);
  }
  .map-inspector {
    order: 3;
    overflow: visible;
    border: 0;
    border-top: 1px solid var(--site-line);
  }
}

@media (max-width: 520px) {
  .map-snapshot { display: none; }
  .world-map-page .map { height: 65vh; min-height: 24rem; }
}

/* The agent page. A single reading column: the dashboard's four-column grid turned this page into
   headings beside cards and a conversation scattered across columns, which is only visible by
   looking at it. Requests stack, and each one keeps its arguments, evidence and buttons together. */
.shell > h2 { margin: 1.4rem 0 .6rem; }
.shell > .admin-widget { display: block; margin: 0 0 .8rem; padding: .9rem 1rem; }
.shell > .admin-widget h3 { margin: 0 0 .5rem; }
.shell > .admin-widget .facts { width: 100%; margin: 0 0 .6rem; }
.shell > .admin-widget .facts th { width: 11rem; text-align: left; opacity: .7; font-weight: 500; }
.shell > .admin-widget .server-card-controls { display: flex; gap: .5rem; margin-top: .7rem; }
/* Conversation text and evidence wrap. Without this a single long line runs off the right edge and
   the operator reads half a sentence - visible only by looking at the page. */
.shell pre.notes { white-space: pre-wrap; overflow-wrap: anywhere; }
.agent-compose { display: block; margin: 0 0 .6rem; }
.agent-compose textarea { display: block; width: 100%; margin-top: .3rem; }
.agent-turn { display: block; margin: 0 0 .6rem; padding: .6rem .8rem; border-radius: 4px; background: #ffffff08; }
/* The agent conversation. Roles are distinguished by a left border rather than a background, so a
   long exchange stays readable and an operator can see at a glance which turns are theirs. */
.agent-turn-operator { border-left: 4px solid #6ba3d6; }
.agent-turn-agent { border-left: 4px solid #8a8f98; }
.agent-turn-system { border-left: 4px solid #c9a227; }
.agent-turn h3 {
  margin: 0 0 0.25rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em; opacity: 0.7;
}
/* Evidence can be long. Cap the height and let it scroll rather than pushing the approval buttons
   off the screen - an operator should never have to scroll past output to reach Deny. */
.admin-widget pre.notes { max-height: 22rem; overflow: auto; }
.admin-widget details > summary { cursor: pointer; }

/* The agent page's "still working" indicator. Motion is the whole point: it is the only thing on a
   server-rendered page that distinguishes waiting from dead, and it costs no request to keep. */
.spinner {
  display: inline-block;
  width: 0.75rem;
  height: 0.75rem;
  margin-right: 0.35rem;
  vertical-align: -1px;
  border: 2px solid #74c99166;
  border-top-color: #74c991;
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* Respect a stated preference for less motion: the text and its ticking counter still say the page
   is live, so the animation is decoration rather than information. */
@media (prefers-reduced-motion: reduce) {
  .spinner { animation: none; opacity: 0.6; }
}

/* The builder legend on the world map. One row per player id the snapshot found: the colour it draws
   on the map, what it built, and - only when opened - a field to name it. Valheim stamps a number on
   a piece and nothing resolves it to a person, so the name is the operator's to give. */
.map-builder {
  display: block;
  border-top: 1px solid var(--site-line);
  font-size: .78rem;
}
.map-builder summary {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: .15rem .4rem;
  padding: .3rem 0;
  cursor: pointer;
}
.map-builder summary::-webkit-details-marker { display: none; }
/* One row per contributor of map pins. Same three-column shape as a builder row, and deliberately
   the same swatch and name treatment: a person's base and their markers are one contributor. */
.map-pin-owner {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: .15rem .4rem;
  padding: .3rem 0;
  border-top: 1px solid var(--site-line);
  font-size: .78rem;
}
.map-builder-swatch {
  grid-column: 1;
  grid-row: 1;
  width: .7rem;
  height: .7rem;
  border-radius: .15rem;
  border: 1px solid rgba(0, 0, 0, .35);
}
.map-builder-name {
  grid-column: 2;
  grid-row: 1;
  min-width: 0;
  font-weight: 600;
}
.map-builder-source {
  font-weight: 400;
  font-size: .66rem;
  color: var(--site-muted);
}
.map-builder-unnamed { font-weight: 400; font-style: italic; color: var(--site-muted); }
.map-builder-count {
  grid-column: 2 / -1;
  grid-row: 2;
  color: var(--site-muted);
  font-size: .72rem;
  font-variant-numeric: tabular-nums;
}
.map-builder-locate {
  grid-column: 3;
  grid-row: 1;
  padding: .1rem .35rem;
  font-size: .68rem;
  line-height: 1.4;
}
.map-builder form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: .4rem;
  padding: 0 0 .5rem 1.1rem;
}
.map-builder form label {
  display: flex;
  flex-direction: column;
  gap: .15rem;
  flex: 1 1 10rem;
  color: var(--site-muted);
  font-size: .72rem;
}
.map-builder form input[type=text] { font-size: .78rem; }
.map-builder form button { flex: 0 0 auto; padding: .2rem .5rem; font-size: .72rem; }


/* Whose map to show. One row per character that has reported, plus the shared view. Plain links, so the
   choice is bookmarkable and survives a reload without the renderer holding any state. */
.map-viewers { display: block; }
.map-viewer {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .4rem;
  padding: .3rem .35rem;
  border-radius: .25rem;
  color: inherit;
  font-size: .78rem;
  text-decoration: none;
}
.map-viewer:hover { background: color-mix(in srgb, var(--site-line) 60%, transparent); }
.map-viewer-current {
  background: color-mix(in srgb, var(--map-build) 22%, transparent);
  font-weight: 600;
}
.map-viewer-area { color: var(--site-muted); font-size: .7rem; font-variant-numeric: tabular-nums; }
