/* ==========================================================================
   GCC Admin Panel — official design system (spec v2).
   Deep-space navy + tan/gold. Inter for UI, JetBrains Mono for numerics.
   One stylesheet, no frameworks, no build step.
   ========================================================================== */

:root {
	--bg: #060912;            /* page background */
	--surface: #151d38;       /* cards, sidebar, topbar */
	--surface-2: #1b2547;     /* inputs, table header rows, nested panels */
	--surface-3: #243059;     /* hover fills, badges-on-surface */
	--border: #354270;        /* input borders, strong dividers */
	--border-soft: #273252;   /* card borders, row dividers */

	--text: #dde5f7;
	--text-dim: #9aa7cc;
	--text-faint: #616f9c;

	--gold: #d9b45c;
	--gold-soft: rgba(217, 180, 92, 0.13);
	--blue: #6ea0f2;      --blue-soft: rgba(110, 160, 242, 0.14);
	--green: #3ecf8e;     --green-soft: rgba(62, 207, 142, 0.13);
	--red: #ff6b6b;       --red-soft: rgba(255, 107, 107, 0.12);
	--orange: #ff9f43;    --orange-soft: rgba(255, 159, 67, 0.13);
	--purple: #b28dff;    --purple-soft: rgba(178, 141, 255, 0.13);

	--sidebar-w: 250px;  --topbar-h: 60px;
	--radius: 12px;  --radius-sm: 8px;
	--shadow: 0 8px 24px rgba(0, 0, 0, 0.35);

	--font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	--font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Consolas, monospace;
}

* { box-sizing: border-box; }

html, body {
	margin: 0; padding: 0;
	color: var(--text);
	font-family: var(--font-ui);
	font-size: 15px;
	line-height: 1.45;
	min-height: 100vh;
}

/* Nebula glow + starfield: page background only — cards are opaque. */
body {
	background:
		radial-gradient(1100px 520px at 50% -140px, #17224c 0%, rgba(23,34,76,0) 65%),
		var(--bg);
	background-attachment: fixed;
}
body::before {
	content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
	background-image:
		radial-gradient(1px 1px at 22px 34px, rgba(255,255,255,.5) 50%, transparent 51%),
		radial-gradient(1px 1px at 132px 184px, rgba(255,255,255,.24) 50%, transparent 51%),
		radial-gradient(1.4px 1.4px at 224px 84px, rgba(216,190,120,.4) 50%, transparent 51%),
		radial-gradient(1px 1px at 312px 226px, rgba(160,190,255,.35) 50%, transparent 51%),
		radial-gradient(1px 1px at 382px 44px, rgba(255,255,255,.3) 50%, transparent 51%),
		radial-gradient(1px 1px at 78px 118px, rgba(255,255,255,.18) 50%, transparent 51%);
	background-size: 420px 280px;
}
#app { position: relative; z-index: 1; }

a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; }
::selection { background: var(--gold-soft); }

.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.dim { color: var(--text-dim); }
.faint { color: var(--text-faint); }
.muted { color: var(--text-dim); }
.small { font-size: .8rem; }
.spread { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }

/* ==========================================================================
   Shell: sidebar + topbar + content
   ========================================================================== */
.layout { display: flex; min-height: 100vh; }

.sidebar {
	width: var(--sidebar-w); flex-shrink: 0;
	background: var(--surface);
	border-right: 1px solid var(--border-soft);
	display: flex; flex-direction: column;
	position: sticky; top: 0; height: 100vh; overflow-y: auto;
	z-index: 60;
}
.brand {
	display: flex; align-items: center; gap: 10px;
	padding: 14px 16px;
	border-bottom: 1px solid var(--border-soft);
}
.brand__tile {
	width: 32px; height: 32px; border-radius: 8px; flex-shrink: 0;
	background: linear-gradient(135deg, #e3c375, #a97f2e);
	color: #191d30;
	display: flex; align-items: center; justify-content: center;
	font-family: var(--font-mono); font-weight: 600; font-size: .8rem;
}
.brand__word { font-weight: 800; font-size: 1rem; letter-spacing: .02em; }
.brand__word span { color: var(--gold); }

.sidebar nav { padding: 10px 10px; flex: 1; }
.nav-section {
	padding: 14px 10px 5px;
	font-size: .68rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
	color: var(--text-faint);
}
.nav-item {
	display: flex; align-items: center; gap: 10px;
	padding: 8px 12px; margin: 1px 0;
	border-radius: var(--radius-sm);
	color: var(--text-dim);
	font-size: .9rem; font-weight: 500;
	cursor: pointer;
}
.nav-item svg { width: 17px; height: 17px; flex-shrink: 0; }
.nav-item:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.nav-item.active { background: var(--gold-soft); color: var(--gold); }
.nav-item .badge { margin-left: auto; }

.clearance {
	margin: 10px; padding: 12px;
	border: 1px solid var(--border-soft); border-radius: var(--radius-sm);
	background: var(--surface-2);
	display: flex; align-items: center; gap: 10px;
}
.clearance__avatar {
	width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
	background: var(--gold-soft); color: var(--gold);
	border: 1px solid rgba(217, 180, 92, .35);
	display: flex; align-items: center; justify-content: center;
	font-weight: 700; font-size: .95rem;
}
.clearance__who { min-width: 0; }
.clearance__name { font-weight: 600; font-size: .86rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.clearance__level { color: var(--gold); font-size: .72rem; font-weight: 600; }
.clearance__role { color: var(--text-faint); font-size: .72rem; font-weight: 600; margin-top: 1px; }
.clearance__out { font-size: .74rem; }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
	height: var(--topbar-h);
	display: flex; align-items: center; gap: 14px;
	padding: 0 20px;
	border-bottom: 1px solid var(--border-soft);
	background: rgba(21, 29, 56, 0.82);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	position: sticky; top: 0; z-index: 50;
}
.topbar .hamburger { display: none; }
.crumbs { flex: 1; display: flex; align-items: center; gap: 8px; font-size: .95rem; min-width: 0; }
.crumbs .parent { color: var(--text-dim); }
.crumbs .sep { color: var(--text-faint); }
.crumbs .here { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.content { padding: 22px; max-width: 1440px; width: 100%; margin: 0 auto; }

/* Global player search */
.gsearch { position: relative; flex-shrink: 0; }
/* input[type=text] in the base reset ties specificity and would otherwise clobber
   padding-left back to 11px (icon overlapping the text); qualify with [type] to win. */
.gsearch input[type="text"] { width: 260px; padding-left: 34px; }
.gsearch .gsearch__icon {
	position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
	width: 15px; height: 15px; color: var(--text-faint); pointer-events: none;
}
.gsearch__panel {
	position: absolute; top: calc(100% + 6px); right: 0;
	width: 320px; max-height: 380px; overflow-y: auto;
	background: var(--surface-3);
	border: 1px solid var(--border); border-radius: var(--radius-sm);
	box-shadow: var(--shadow);
	z-index: 80;
}
.gsearch__row {
	display: flex; align-items: center; gap: 10px;
	padding: 8px 12px; cursor: pointer;
}
.gsearch__row:hover, .gsearch__row.sel { background: var(--gold-soft); }
.gsearch__avatar {
	width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0;
	background: var(--surface-2); border: 1px solid var(--border-soft);
	color: var(--text-dim); font-size: .72rem; font-weight: 700;
	display: flex; align-items: center; justify-content: center;
}
.gsearch__nic { flex: 1; font-weight: 600; font-size: .86rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gsearch__id { font-family: var(--font-mono); font-size: .74rem; color: var(--text-faint); }
.gsearch__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--red); flex-shrink: 0; }
.gsearch__empty { padding: 12px; color: var(--text-faint); font-size: .82rem; text-align: center; }

.iconbtn {
	display: inline-flex; align-items: center; justify-content: center;
	width: 34px; height: 34px; border-radius: var(--radius-sm);
	background: transparent; border: 1px solid var(--border-soft);
	color: var(--text-dim); cursor: pointer;
}
.iconbtn:hover { background: var(--surface-2); color: var(--text); }
.iconbtn svg { width: 16px; height: 16px; }

/* ==========================================================================
   Cards
   ========================================================================== */
.card {
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius);
	margin-bottom: 18px;
	overflow: hidden;
}
.card-header {
	display: flex; align-items: center; gap: 10px;
	padding: 14px 18px;
	border-bottom: 1px solid var(--border-soft);
}
/* Signature: gold small-caps card titles. */
.card-title {
	margin: 0; flex: 1;
	font-size: .82rem; font-weight: 700;
	color: var(--gold);
	text-transform: uppercase; letter-spacing: .09em;
}
.card-sub { color: var(--text-faint); font-size: .78rem; }
.card-body { padding: 16px 18px; }
.card-body.tight { padding: 0; }

.table-toolbar {
	display: flex; align-items: center; gap: 12px;
	padding: 10px 18px;
	border-bottom: 1px solid var(--border-soft);
}
.table-toolbar input[type="text"] { max-width: 260px; }
.table-toolbar .count { margin-left: auto; color: var(--text-faint); font-size: .78rem; white-space: nowrap; }

.grid { display: grid; gap: 14px; margin-bottom: 18px; }
.grid.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1100px) {
	.grid.cols-4, .grid.cols-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 700px) {
	.grid.cols-4, .grid.cols-3, .grid.cols-2 { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Stat cards: horizontal, 42px icon tile + mono-gold value
   ========================================================================== */
.stat {
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius);
	padding: 14px 16px;
	display: flex; align-items: center; gap: 13px;
}
a.stat { color: inherit; }
a.stat:hover { text-decoration: none; border-color: var(--border); }
.stat__tile {
	width: 42px; height: 42px; border-radius: 10px; flex-shrink: 0;
	display: flex; align-items: center; justify-content: center;
}
.stat__tile svg { width: 20px; height: 20px; }
.stat__tile.gold { background: var(--gold-soft); color: var(--gold); }
.stat__tile.blue { background: var(--blue-soft); color: var(--blue); }
.stat__tile.green { background: var(--green-soft); color: var(--green); }
.stat__tile.red { background: var(--red-soft); color: var(--red); }
.stat__tile.purple { background: var(--purple-soft); color: var(--purple); }
.stat__tile.orange { background: var(--orange-soft); color: var(--orange); }
.stat__body { min-width: 0; }
/* Signature: mono gold stat values, small-caps faint labels. */
.stat__value {
	font-family: var(--font-mono); font-size: 1.2rem; font-weight: 600;
	color: var(--gold); font-variant-numeric: tabular-nums;
	line-height: 1.2;
}
.stat__value.red { color: var(--red); }
.stat__label {
	font-size: .68rem; font-weight: 700;
	text-transform: uppercase; letter-spacing: .08em;
	color: var(--text-faint);
}
.stat__sub { font-size: .76rem; color: var(--text-dim); margin-top: 2px; }
.stat__sub a { color: var(--text-dim); text-decoration: underline; }

/* ==========================================================================
   Tables (+ sortable)
   ========================================================================== */
.table-wrap { overflow-x: auto; }
table.tbl { width: 100%; border-collapse: collapse; font-size: .86rem; }
/* Signature: muted-gold small-caps headers on surface-2. */
table.tbl th {
	text-align: left; white-space: nowrap;
	font-size: .7rem; font-weight: 700;
	text-transform: uppercase; letter-spacing: .08em;
	color: #bda265;
	background: var(--surface-2);
	border-bottom: 1px solid var(--border);
	padding: 9px 14px;
}
table.tbl td {
	padding: 9px 14px;
	border-bottom: 1px solid var(--border-soft);
	vertical-align: top;
}
/* Align the outer columns with the card header/body (18px) so tables inside a
   card line up with the title instead of sitting 4px inset. */
table.tbl th:first-child, table.tbl td:first-child { padding-left: 18px; }
table.tbl th:last-child, table.tbl td:last-child { padding-right: 18px; }
/* Row banding. A 1px divider alone is hard to track across a wide table - the
   eye loses which cells belong together somewhere around the middle columns.
   Alternating rows give it something continuous to follow. Kept faint enough
   that it reads as texture rather than as two kinds of row. */
table.tbl tbody tr:nth-child(even) { background: rgba(255, 255, 255, 0.055); }

/* Hover has to beat the band on even rows, so it is both stronger and declared
   after it. The gold edge marks where the pointer is without having to compare
   two near-identical fills. */
table.tbl tbody tr.hoverable:hover, table.tbl tbody tr.clickable:hover {
	background: var(--surface-3);
	box-shadow: inset 3px 0 0 var(--gold);
}
table.tbl tbody tr.clickable { cursor: pointer; }
/* Numeric alignment applies to both the header and its cells so values line
   up under their label; the mono/tabular typography is body-cell only so the
   header keeps its uppercase gold styling. */
table.tbl .num { text-align: right; }
table.tbl td.num {
	font-family: var(--font-mono); font-size: .8rem;
	font-variant-numeric: tabular-nums;
}
table.tbl td.dim, table.tbl .cell-dim { color: var(--text-dim); }
table.tbl .empty-cell { color: var(--text-faint); }
table.tbl tfoot td {
	font-weight: 700; background: var(--surface-2);
	border-top: 2px solid var(--border);
	font-family: var(--font-mono); font-size: .8rem;
}
table.tbl .empty-row td { text-align: center; color: var(--text-faint); padding: 26px; }
table.tbl tr.wiped { opacity: .5; }

table.sortable th:not([data-nosort]) { cursor: pointer; user-select: none; }
table.sortable th .sort-ind { margin-left: 5px; color: var(--text-faint); font-size: .68rem; }
table.sortable th.sorted .sort-ind { color: var(--gold); }

/* IP cells */
.ipcell {
	font-family: var(--font-mono); font-size: .78rem;
	max-width: 160px; display: inline-block;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
	direction: rtl; text-align: left;   /* middle-ish truncation: keep the tail visible */
	cursor: copy; vertical-align: bottom;
}
.ipcell.faint { color: var(--text-faint); cursor: default; direction: ltr; }

/* ==========================================================================
   Badges
   ========================================================================== */
.badge {
	display: inline-block;
	font-size: .72rem; font-weight: 700;
	padding: 1px 9px; border-radius: 999px;
	white-space: nowrap; line-height: 1.5;
}
.badge.gold   { color: var(--gold); background: var(--gold-soft); }
.badge.blue   { color: var(--blue); background: var(--blue-soft); }
.badge.green  { color: var(--green); background: var(--green-soft); }
.badge.red    { color: var(--red); background: var(--red-soft); }
.badge.orange { color: var(--orange); background: var(--orange-soft); }
.badge.purple { color: var(--purple); background: var(--purple-soft); }
.badge.dim    { color: var(--text-dim); background: var(--surface-3); }
.badge.outline { color: var(--text-faint); background: transparent; border: 1px solid var(--border); }
.badge.mono   { font-family: var(--font-mono); font-weight: 600; }

/* ==========================================================================
   Buttons, inputs, forms
   ========================================================================== */
.btn {
	display: inline-flex; align-items: center; gap: 7px;
	background: var(--surface-2);
	color: var(--text);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	padding: 8px 16px;
	font-family: inherit; font-size: .88rem; font-weight: 600;
	cursor: pointer; white-space: nowrap;
	position: relative;
}
.btn:hover { background: var(--surface-3); }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn.primary { background: var(--gold); color: #191d30; border-color: var(--gold); }
.btn.primary:hover { background: #e9c878; }
.btn.danger { background: var(--red-soft); color: var(--red); border-color: rgba(255, 107, 107, .35); }
.btn.danger:hover { background: rgba(255, 107, 107, .2); }
/* Extreme, destructive action (e.g. scrubbing a chat post): a solid red fill
   so it reads unmistakably as more severe than the softer warn/silence controls. */
.btn.danger-solid { background: var(--red); color: #2a0d0d; border-color: var(--red); font-weight: 700; }
.btn.danger-solid:hover { background: #ff8585; border-color: #ff8585; }
/* Removed-post reveal in the chat feed (mirrors the battle-report expander). */
/* Admin-scrubbed chat post: same .removed class the game chat uses. */
.removed { color: var(--red); font-style: italic; }
/* Staff chat name - a post made from the Chat screen. Same look as the game's
   .gc-chat-staff in app/theme.css (defined in both on purpose: the same stored
   name renders on both surfaces - see docs/CHAT-MODERATION.md). */
.gc-chat-staff { font-weight: 700; color: #5b9bff; white-space: nowrap; }
.gc-chat-staff::after {
	content: "STAFF"; display: inline-block; margin-left: 5px; padding: 1px 5px;
	border-radius: 3px; background: #0f52ba; color: #fff;
	font-size: 9px; font-weight: 700; letter-spacing: .08em; line-height: 1.4; vertical-align: middle;
}
details.orig-post { margin-top: 5px; }
details.orig-post > summary {
	cursor: pointer; list-style: none; display: inline-flex; gap: 5px; align-items: center;
	color: var(--text-dim); font-size: .76rem; user-select: none;
}
details.orig-post > summary::-webkit-details-marker { display: none; }
details.orig-post > summary:hover { color: var(--text); }
details.orig-post > summary .arrow { transition: transform .15s; color: var(--text-faint); }
details.orig-post[open] > summary .arrow { transform: rotate(90deg); }
.orig-post__body {
	margin-top: 6px; padding: 8px 11px; border-left: 2px solid var(--red);
	background: var(--surface-2); border-radius: 4px;
	color: var(--text); font-size: .82rem; word-break: break-word; white-space: pre-wrap;
}
.btn.warn { background: var(--orange-soft); color: var(--orange); border-color: rgba(255, 159, 67, .35); }
.btn.warn:hover { background: rgba(255, 159, 67, .2); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--text-dim); }
.btn.ghost:hover { background: var(--surface-2); color: var(--text); }
.btn.sm { padding: 5px 11px; font-size: .8rem; }
.btn .dirty-dot {
	width: 8px; height: 8px; border-radius: 50%;
	background: var(--gold); display: inline-block;
}
.btn.primary .dirty-dot { background: #191d30; }

label.lbl {
	display: block;
	font-size: .68rem; font-weight: 700;
	text-transform: uppercase; letter-spacing: .08em;
	color: var(--text-faint);
	margin-bottom: 5px;
}
input[type="text"], input[type="password"], input[type="number"], input[type="email"],
select, textarea {
	width: 100%;
	background: var(--surface-2);
	color: var(--text);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	padding: 8px 11px;
	font-family: inherit; font-size: .88rem;
	outline: none;
}
input:focus, select:focus, textarea:focus {
	border-color: var(--gold);
	box-shadow: 0 0 0 3px var(--gold-soft);
}
textarea { resize: vertical; min-height: 74px; }
input::placeholder { color: var(--text-faint); }
input[type="radio"], input[type="checkbox"] { accent-color: var(--gold); width: auto; }
select {
	appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%239aa7cc' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
	background-repeat: no-repeat; background-position: right 11px center;
	padding-right: 30px;
}
input.mini { width: 90px; padding: 4px 8px; font-size: .8rem; font-family: var(--font-mono); text-align: right; }
input.mini.dirty { border-color: var(--gold); box-shadow: 0 0 0 2px var(--gold-soft); }

.form-row { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; }
.form-row > div { flex: 1; min-width: 130px; }
.field { margin-bottom: 13px; }

/* ==========================================================================
   Tabs (hash deep-linked)
   ========================================================================== */
.tabs {
	display: flex; gap: 2px; flex-wrap: wrap;
	border-bottom: 1px solid var(--border-soft);
	margin-bottom: 16px;
}
.tabs .tab {
	background: transparent; border: none;
	padding: 9px 14px; margin-bottom: -1px;
	font-family: inherit; font-size: .88rem; font-weight: 600;
	color: var(--text-dim); cursor: pointer;
	border-bottom: 2px solid transparent;
}
.tabs .tab:hover { color: var(--text); text-decoration: none; }
.tabs .tab.active { color: var(--gold); border-bottom-color: var(--gold); }

/* ==========================================================================
   Toasts
   ========================================================================== */
#toasts { position: fixed; right: 18px; bottom: 18px; z-index: 200; display: flex; flex-direction: column; gap: 8px; }
.toast {
	background: var(--surface-3);
	border: 1px solid var(--border-soft);
	border-left: 3px solid var(--gold);
	border-radius: var(--radius-sm);
	box-shadow: var(--shadow);
	padding: 10px 16px;
	font-size: .86rem; max-width: 380px;
	animation: toast-in .18s ease-out;
}
.toast.good { border-left-color: var(--green); }
.toast.bad { border-left-color: var(--red); }
@keyframes toast-in { from { transform: translateY(8px); opacity: 0; } to { transform: none; opacity: 1; } }

/* ==========================================================================
   Action rows (moderation)
   ========================================================================== */
.action-group { margin-bottom: 14px; }
.action-group > .lbl { margin-bottom: 7px; }
label.action-row {
	display: flex; align-items: center; gap: 11px;
	padding: 9px 13px; margin: 3px 0;
	border: 1px solid var(--border-soft);
	border-left: 2px solid transparent;
	border-radius: var(--radius-sm);
	cursor: pointer; font-size: .86rem;
}
label.action-row:hover { background: var(--surface-2); }
label.action-row.selected { background: var(--gold-soft); border-left-color: var(--gold); }
label.action-row.danger .action-row__name { color: var(--red); }
label.action-row.danger.selected { background: var(--red-soft); border-left-color: var(--red); }
.action-row__name { font-weight: 700; white-space: nowrap; }
.action-row__desc { color: var(--text-faint); font-size: .78rem; flex: 1; min-width: 120px; }
.action-row__params { display: flex; gap: 8px; align-items: center; margin-left: auto; flex-wrap: wrap; justify-content: flex-end; }
.action-row__params input, .action-row__params select { width: auto; min-width: 80px; padding: 4px 8px; font-size: .8rem; }
.action-footer {
	display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap;
	padding-top: 13px; margin-top: 6px;
	border-top: 1px solid var(--border-soft);
}
.action-footer > div { flex: 1; min-width: 150px; }

/* ==========================================================================
   Log feed
   ========================================================================== */
.feed { font-size: .86rem; }
.feed__row {
	display: flex; align-items: baseline; gap: 10px;
	padding: 7px 4px;
	border-bottom: 1px solid var(--border-soft);
}
/* Banded like the tables: these rows are wide too, and the event text on the
   right is a long way from the timestamp on the left. */
.feed__row:nth-child(even) { background: rgba(255, 255, 255, 0.055); }
.feed__row:hover { background: var(--surface-3); box-shadow: inset 3px 0 0 var(--gold); }
.feed__row:last-child { border-bottom: none; }
.feed__ts {
	flex: 0 0 118px;
	font-family: var(--font-mono); font-size: .74rem;
	color: var(--text-faint); white-space: nowrap;
}
.feed__dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; align-self: center; }
.feed__dot.battle { background: var(--red); }
.feed__dot.market { background: var(--gold); }
.feed__dot.system { background: var(--blue); }
.feed__body { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.feed__body .amt { font-family: var(--font-mono); color: var(--gold); }
.feed__body .who { color: var(--blue); font-weight: 600; }

/* ==========================================================================
   Battle reports
   ========================================================================== */
details.battle {
	border: 1px solid var(--border-soft);
	border-radius: var(--radius-sm);
	margin: 6px 0; background: var(--surface);
}
details.battle > summary {
	display: flex; align-items: center; gap: 10px;
	padding: 9px 13px; cursor: pointer; list-style: none;
	font-size: .86rem;
}
details.battle > summary::-webkit-details-marker { display: none; }
details.battle > summary .arrow { transition: transform .15s; color: var(--text-faint); }
details.battle[open] > summary .arrow { transform: rotate(90deg); }
.battle__panels { padding: 4px 13px 13px; display: grid; gap: 10px; }
.battle__panel {
	border: 1px solid var(--border-soft);
	border-radius: var(--radius-sm);
	background: var(--surface-2);
	overflow: hidden;
}
.fleet-title {
	padding: 7px 12px;
	font-size: .7rem; font-weight: 700;
	text-transform: uppercase; letter-spacing: .08em;
	color: var(--gold);
	border-bottom: 1px solid var(--border-soft);
}
.battle__panel td.cas { color: var(--red); }
.battle__panel td.rem { color: var(--green); }

/* ==========================================================================
   Chart
   ========================================================================== */
.chart-wrap { position: relative; }
.chart-wrap svg { display: block; width: 100%; }
.chart-tip {
	position: absolute; pointer-events: none;
	background: var(--surface-3);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	box-shadow: var(--shadow);
	padding: 6px 10px; font-size: .76rem;
	white-space: nowrap; z-index: 10;
	transform: translate(-50%, calc(-100% - 10px));
}
.chart-tip .t { font-family: var(--font-mono); color: var(--text-dim); }
.chart-tip .v { font-family: var(--font-mono); color: var(--gold); font-weight: 600; }
.chip-row { display: flex; gap: 4px; }
.chip {
	background: transparent; border: 1px solid var(--border-soft);
	color: var(--text-dim); border-radius: 999px;
	font-family: inherit; font-size: .74rem; font-weight: 600;
	padding: 3px 11px; cursor: pointer;
}
.chip:hover { background: var(--surface-2); }
.chip.active { background: var(--gold-soft); color: var(--gold); border-color: rgba(217, 180, 92, .35); }

/* ==========================================================================
   Modal
   ========================================================================== */
.modal-backdrop {
	position: fixed; inset: 0; z-index: 100;
	background: rgba(4, 6, 14, .74);
	display: flex; align-items: center; justify-content: center;
	padding: 20px;
}
.modal {
	background: var(--surface);
	border: 1px solid var(--border);
	border-radius: var(--radius);
	box-shadow: var(--shadow);
	width: 100%; max-width: 480px;
	max-height: 88vh; overflow-y: auto;
}
.modal.wide { max-width: 760px; }
/* Sticky because .modal is the scroll container (max-height 88vh, overflow-y
   auto): on a long editor the head — and with it the only X — used to scroll
   out of reach, leaving no visible way to close once you were partway down.
   Needs its own opaque background or the scrolled content shows through it. */
.modal__head {
	position: sticky;
	top: 0;
	z-index: 2;
	background: var(--surface);
	padding: 14px 18px;
	border-bottom: 1px solid var(--border-soft);
	font-size: .82rem; font-weight: 700;
	color: var(--gold); text-transform: uppercase; letter-spacing: .09em;
	display: flex; align-items: center; gap: 12px;
}
.modal__title { flex: 1 1 auto; min-width: 0; }

/* Close control. Dialogs no longer dismiss on a backdrop click, so this is the
   pointer route out - it has to be obvious and hard to miss. Negative margins
   pull it into the head padding so the head keeps its original height. */
.modal__x {
	flex: 0 0 auto;
	width: 26px; height: 26px;
	margin: -4px -6px -4px 0;
	padding: 0;
	display: inline-flex; align-items: center; justify-content: center;
	background: none;
	border: 1px solid transparent;
	border-radius: 6px;
	color: var(--text-dim);
	font-size: 1.2rem; font-weight: 400; line-height: 1;
	cursor: pointer;
	transition: color .12s ease, background .12s ease, border-color .12s ease;
}
.modal__x:hover, .modal__x:focus-visible {
	color: var(--text);
	background: var(--surface-2);
	border-color: var(--border-soft);
}
.modal__body { padding: 18px; }
.modal__foot {
	padding: 12px 18px;
	border-top: 1px solid var(--border-soft);
	display: flex; justify-content: flex-end; gap: 10px;
}

/* Searchable select */
.sselect { position: relative; }
.sselect__panel {
	position: absolute; top: calc(100% + 4px); left: 0; right: 0;
	max-height: 260px; overflow-y: auto;
	background: var(--surface-3);
	border: 1px solid var(--border); border-radius: var(--radius-sm);
	box-shadow: var(--shadow); z-index: 90;
}
.sselect__opt { padding: 7px 11px; cursor: pointer; font-size: .84rem; display: flex; gap: 8px; align-items: baseline; }
.sselect__opt:hover, .sselect__opt.sel { background: var(--gold-soft); }
.sselect__opt .oid { font-family: var(--font-mono); font-size: .72rem; color: var(--text-faint); margin-left: auto; }
.sselect__opt .odesc { color: var(--text-faint); font-size: .74rem; }

/* ==========================================================================
   Misc components
   ========================================================================== */
.kv { display: grid; grid-template-columns: 160px 1fr; gap: 0 14px; font-size: .86rem; }
.kv dt { color: var(--text-faint); }
.kv dd { margin: 0; word-break: break-word; }
/* Banded in pairs so a label and its value share a tint. The grid places dt and
   dd as separate items, so both halves of a pair have to be tinted together -
   nth-of-type keeps them in step. Padding replaces the old row gap so the tint
   forms a continuous band rather than striped fragments. */
.kv dt, .kv dd { padding: 4px 6px; }
.kv dt:nth-of-type(even), .kv dd:nth-of-type(even) { background: rgba(255, 255, 255, 0.055); }

.note-item {
	border: 1px solid var(--border-soft);
	border-radius: var(--radius-sm);
	padding: 10px 12px; margin-bottom: 8px;
	background: var(--surface-2);
	font-size: .86rem;
}
.note-item.pinned { border-color: rgba(217, 180, 92, .4); }
.note-item .meta { font-size: .72rem; color: var(--text-faint); margin-bottom: 4px; }

.alert {
	border-radius: var(--radius-sm);
	padding: 10px 14px; margin-bottom: 14px; font-size: .84rem;
}
.alert.warn { background: var(--orange-soft); border: 1px solid rgba(255, 159, 67, .35); color: var(--orange); }
.alert.info { background: var(--blue-soft); border: 1px solid rgba(110, 160, 242, .35); color: var(--blue); }
.alert.error { background: var(--red-soft); border: 1px solid rgba(255, 107, 107, .35); color: var(--red); }

.error-box {
	background: var(--red-soft);
	border: 1px solid rgba(255, 107, 107, .4);
	color: var(--red);
	border-radius: var(--radius-sm);
	padding: 12px 16px; margin-bottom: 16px;
}

.loading { display: flex; align-items: center; justify-content: center; color: var(--text-faint); padding: 40px; gap: 10px; }
.loading::before {
	content: ""; width: 14px; height: 14px;
	border: 2px solid var(--border-soft);
	border-top-color: var(--gold);
	border-radius: 50%;
	animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Rarity tints for the artifact inventory */
.rarity-common { color: #c9d3e8; }
.rarity-uncommon { color: var(--green); }
.rarity-rare { color: var(--blue); }
.rarity-unique { color: var(--purple); }
.rarity-special { color: var(--gold); }
.rarity-bar { height: 3px; border-radius: 2px; }
.rarity-bar.common { background: #c9d3e8; }
.rarity-bar.uncommon { background: var(--green); }
.rarity-bar.rare { background: var(--blue); }
.rarity-bar.unique { background: var(--purple); }
.rarity-bar.special { background: var(--gold); }
.art-row { display: flex; align-items: center; gap: 8px; padding: 4px 8px; border-radius: 6px; font-size: .82rem; }
.art-row.owned { font-weight: 700; }
.art-row.empty { color: var(--text-faint); }
.art-count {
	margin-left: auto;
	font-family: var(--font-mono); font-size: .74rem; font-weight: 600;
	color: var(--gold); background: var(--gold-soft);
	border-radius: 999px; padding: 0 8px;
}
.art-row.empty .art-count { color: var(--text-faint); background: var(--surface-2); }

/* Access-control rows */
.acl-row {
	display: flex; align-items: center; justify-content: space-between; gap: 12px;
	padding: 9px 4px;
	border-bottom: 1px solid var(--border-soft);
}
.acl-row:last-child { border-bottom: none; }
.acl-row__label { min-width: 0; }
.acl-row__label > div:first-child { font-weight: 600; font-size: .88rem; }

/* To-Do board (kanban) */
.todo-board {
	display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
	align-items: start;
}
.todo-col {
	background: var(--surface-2);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius-sm);
	padding: 10px;
	display: flex; flex-direction: column; gap: 8px;
	min-height: 120px;
}
.todo-col__head {
	display: flex; align-items: center; justify-content: space-between;
	font-size: .78rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
	color: var(--text-dim);
	padding: 2px 2px 6px;
	border-bottom: 1px solid var(--border-soft);
}
.todo-col__count {
	font-family: var(--font-mono); font-size: .72rem; font-weight: 600;
	color: var(--text-dim); background: var(--surface-3);
	border-radius: 999px; padding: 0 8px;
}
.todo-empty { color: var(--text-faint); font-size: .82rem; text-align: center; padding: 18px 0; }
.todo-item {
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-left-width: 3px;
	border-radius: var(--radius-sm);
	padding: 10px 12px;
	display: flex; flex-direction: column; gap: 6px;
}
.todo-item.pri-high { border-left-color: var(--red); }
.todo-item.pri-med  { border-left-color: var(--orange); }
.todo-item.pri-low  { border-left-color: var(--border); }
.todo-item__title { font-weight: 600; font-size: .88rem; }
.todo-item__badges { display: flex; gap: 4px; flex-wrap: wrap; }
.todo-item__body {
	color: var(--text-dim); font-size: .8rem;
	white-space: pre-wrap; word-break: break-word;
}
/* Long details clamp and expand in place rather than scrolling: a nested
   scroll area inside a card traps the wheel, and the browser's default
   scrollbar is the one chrome the panel never styles. */
.todo-item__body.clamped {
	display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical;
	overflow: hidden;
}
.todo-item__more {
	align-self: flex-start;
	background: none; border: 0; padding: 0;
	font: inherit; font-size: .74rem; font-weight: 600;
	color: var(--text-faint); cursor: pointer;
}
.todo-item__more:hover { color: var(--gold); }
.todo-item__meta {
	display: flex; flex-direction: column; gap: 2px;
	color: var(--text-dim); font-size: .74rem;
}
.todo-item__actions { display: flex; gap: 2px; flex-wrap: wrap; margin-top: 2px; }
.todo-del { color: var(--red); }
.todo-del:hover { background: var(--red-soft); color: var(--red); }
@media (max-width: 1100px) {
	.todo-board { grid-template-columns: 1fr; }
}

/* Login screen */
.login-wrap { display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 24px; }
.login-card {
	width: 100%; max-width: 390px;
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius);
	box-shadow: var(--shadow);
	padding: 32px;
}
.login-card h1 { margin: 0 0 4px; font-size: 1.25rem; font-weight: 800; letter-spacing: .02em; }
.login-card h1 span { color: var(--gold); }
.login-card .sub { color: var(--text-dim); font-size: .82rem; margin-bottom: 22px; }

.boot-splash { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; gap: 12px; }
.boot-splash__mark { font-family: var(--font-mono); font-size: 28px; font-weight: 600; letter-spacing: 6px; color: var(--gold); }
.boot-splash__text { color: var(--text-dim); }

/* ==========================================================================
   Responsive: off-canvas sidebar under 900px
   ========================================================================== */
.scrim { display: none; }
@media (max-width: 900px) {
	.sidebar {
		position: fixed; left: 0; top: 0; bottom: 0;
		transform: translateX(-100%);
		transition: transform .2s ease-out;
	}
	.layout.nav-open .sidebar { transform: none; }
	.layout.nav-open .scrim {
		display: block; position: fixed; inset: 0; z-index: 55;
		background: rgba(4, 6, 14, .6);
	}
	.topbar .hamburger { display: inline-flex; }
	.gsearch input[type="text"] { width: 190px; }
	.gsearch__panel { width: 270px; }
	.content { padding: 14px; }
	.kv { grid-template-columns: 120px 1fr; }
	.feed__ts { flex-basis: 84px; }
}

/* Turn-use boxes that drill into the Turn Logs screen. Only rendered as links
   when the admin can open that section, so the affordance is never a lie. */
a.stat--link { text-decoration: none; cursor: pointer; transition: border-color .12s ease, transform .12s ease; }
a.stat--link:hover { border-color: var(--gold); transform: translateY(-1px); }
a.stat--link:hover .stat__value { color: var(--gold); }
a.stat--link .stat__label::after { content: " →"; opacity: .55; }

/* ---------------------------------------------------------------------------
   IP cells. The address links into the shared-login scan; the buttons look the
   address up and copy it. Rendered everywhere an IP appears.
   --------------------------------------------------------------------------- */
.ipcell { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; max-width: 100%; min-width: 0; }
/* A full IPv6 is 39 characters and would shove the buttons out of the cell, so
   the address truncates on the right and the buttons keep their place. The
   whole value stays available on hover and through the copy button. */
.ipcell__ip {
  font-family: var(--mono, ui-monospace, Consolas, monospace); font-size: .92em;
  flex: 0 1 auto; min-width: 0; max-width: 22ch;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ipcell__ip--plain { cursor: default; }
.ipcell__btn {
  flex: none;
  background: none; border: 1px solid transparent; border-radius: 4px;
  color: var(--muted); cursor: pointer; font-size: .95em; line-height: 1;
  padding: 1px 4px; opacity: .55; transition: opacity .12s ease, border-color .12s ease;
}
.ipcell:hover .ipcell__btn { opacity: 1; }
.ipcell__btn:hover { color: var(--gold); border-color: var(--gold); }

/* Lookup popover. Body-anchored so table overflow cannot clip it. */
.ippop {
  position: absolute; z-index: 900; width: 300px; padding: 10px 12px;
  background: var(--panel, #161b22); border: 1px solid var(--line, #30363d);
  border-radius: 6px; box-shadow: 0 8px 22px rgba(0, 0, 0, .45); font-size: 12px;
}
.ippop__head { font-weight: 600; margin-bottom: 6px; display: flex; align-items: center; gap: 8px; }
.ippop__tag { font-weight: 400; font-size: 11px; color: var(--muted); }
.ippop__note, .ippop__loading { color: var(--muted); }
.ippop__err { color: var(--red, #f85149); }
.ippop__flags { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 7px; }
.ippop__flag {
  border: 1px solid var(--line); border-radius: 10px; padding: 1px 7px;
  font-size: 11px; color: var(--muted);
}
/* Datacentre or proxy: the signal that the address is not a home line. */
.ippop__flag--hot { border-color: var(--red, #f85149); color: var(--red, #f85149); }
.ippop__row { display: flex; gap: 8px; padding: 2px 0; }
.ippop__k { width: 74px; flex: none; color: var(--muted); }
.ippop__v { flex: 1; min-width: 0; word-break: break-word; }

/* Single-letter status badge (A / S) used in table status columns. Fixed width
   so the column does not jitter between the two states; full word on hover. */
.badge.badge--letter {
  display: inline-block; width: 1.35em; padding-left: 0; padding-right: 0;
  text-align: center; font-weight: 700; cursor: default;
}

/* ==========================================================================
   Sidebar customisation
   ========================================================================== */
/* Grouped items collapse into a button that opens a flyout to the right. */
.nav-groupwrap { position: relative; }
.nav-item--group { width: 100%; text-align: left; background: none; font: inherit; cursor: pointer; }
.nav-item__label { flex: 1; }
.nav-item__chev { opacity: .5; font-size: 1.05em; line-height: 1; }
.nav-groupwrap.is-open .nav-item__chev { opacity: 1; color: var(--gold); }

.nav-flyout {
	display: none;
	position: fixed; left: var(--sidebar-w, 232px); z-index: 700;
	min-width: 190px; padding: 6px;
	background: var(--surface-2); border: 1px solid var(--border);
	border-radius: var(--radius-sm); box-shadow: 0 10px 26px rgba(0, 0, 0, .5);
}
.nav-groupwrap.is-open .nav-flyout { display: block; }
.nav-flyout__head {
	font-size: .68rem; font-weight: 700; text-transform: uppercase;
	letter-spacing: .08em; color: var(--text-faint); padding: 4px 10px 6px;
}
.nav-flyout__item { margin: 0; }

/* A quiet entry point at the foot of the sidebar. */
.nav-item--setup { margin-top: 10px; opacity: .68; font-size: .82rem; }
.nav-item--setup:hover { opacity: 1; }

/* Editor */
.navcfg__head, .navcfg__row {
	display: grid; grid-template-columns: 42px 26px minmax(90px, 1fr) 132px 132px;
	align-items: center; gap: 8px;
}
/* Two dropdowns per row need more room than half the screen gives, so the
   editor takes the larger share and the preview the smaller. */
.grid.cols-2.navcfg__split { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); }
@media (max-width: 1100px) {
	.navcfg__head, .navcfg__row { grid-template-columns: 36px 24px minmax(70px, 1fr) 108px 108px; }
}
/* The section / group management rows are a different shape to the item rows,
   so they opt out of the grid rather than being squeezed into its columns. */
.navcfg__row.navcfg__manage { display: flex; gap: 8px; }
.navcfg__row.navcfg__manage .navcfg__label { flex: 1; }
.navcfg__row.navcfg__manage .btn[disabled] { opacity: .35; pointer-events: none; }
.navcfg__head {
	font-size: .68rem; font-weight: 700; text-transform: uppercase;
	letter-spacing: .08em; color: var(--text-faint);
	padding: 0 4px 6px; border-bottom: 1px solid var(--border-soft);
}
.navcfg__row { padding: 5px 4px; border-bottom: 1px solid var(--border-soft); }
.navcfg__row:last-child { border-bottom: none; }
.navcfg__row:nth-child(even) { background: rgba(255, 255, 255, 0.055); }
.navcfg__row.is-hidden .navcfg__label, .navcfg__row.is-hidden .navcfg__icon { opacity: .4; }
.navcfg__vis { display: flex; justify-content: center; }
.navcfg__icon { display: flex; color: var(--text-faint); }
.navcfg__group select { width: 100%; }

/* Live preview of the resulting sidebar. */
.navprev {
	background: var(--surface); border: 1px solid var(--border-soft);
	border-radius: var(--radius-sm); padding: 12px; margin-bottom: 16px;
}
.navprev__title {
	font-size: .68rem; font-weight: 700; text-transform: uppercase;
	letter-spacing: .08em; color: var(--text-faint); margin-bottom: 8px;
}
.navprev__row {
	display: flex; align-items: center; gap: 9px;
	padding: 6px 9px; border-radius: var(--radius-sm);
	font-size: .86rem; color: var(--text-dim);
}
.navprev__row--group { color: var(--text); background: var(--surface-2); }
/* Mirrors .nav-section so the preview reads like the real sidebar. */
.navprev__section {
	padding: 12px 9px 4px;
	font-size: .68rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
	color: var(--text-faint);
}
.navprev__section:first-of-type { padding-top: 4px; }
.navprev__count {
	margin-left: auto; font-size: .7rem; color: var(--text-faint);
	background: var(--surface-3); border-radius: 9px; padding: 0 7px;
}
.navprev__chev { color: var(--text-faint); }

/* =========================================================
   EXCAVATION DIG WINDOW (turn log timeline)
   Which dig was running when a turn was spent. Rarity is carried by colour so
   a column of them can be skimmed — Rare and UnCommon are what an admin is
   looking for, Default is deliberately quiet. Uses the panel's own tokens so
   it stays in step with the rest of the design system.
   ========================================================= */
.digcard {
	display: inline-block;
	padding: 1px 8px;
	border-radius: 999px;
	border: 1px solid transparent;
	font-size: .72rem;
	font-weight: 600;
	letter-spacing: .03em;
	white-space: nowrap;
}

.digcard--default  { color: var(--text-dim); border-color: var(--border-soft); background: rgba(255, 255, 255, 0.03); }
.digcard--common   { color: var(--blue);   border-color: rgba(110, 160, 242, 0.35); background: var(--blue-soft); }
.digcard--uncommon { color: var(--green);  border-color: rgba(62, 207, 142, 0.38);  background: var(--green-soft); }
.digcard--rare     { color: var(--gold);   border-color: rgba(217, 180, 92, 0.45);  background: var(--gold-soft); }
.digcard--mixed    { color: var(--purple); border-color: rgba(178, 141, 255, 0.38); background: var(--purple-soft); }

/* =========================================================
   YELLOW ANNOUNCEMENT (Server Settings)
   A preview of the notice bar the game paints across the top of every page.
   It mirrors the game's own modern styling — gold on a bordered surface, mono,
   small, centred — so what an admin approves here is what players get. The
   game's rule lives in theme.css (#topnavbar); this is a deliberate second
   definition on a second surface, the same arrangement as `.removed`, because
   the same content renders in two independent places.
   ========================================================= */
.annbar-wrap { margin-top: 4px; }

.annbar-cap {
	font-size: .7rem;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--text-faint);
	margin-bottom: 5px;
}

.annbar {
	background: var(--surface-2);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	padding: 8px 14px;
	color: var(--gold);
	font-family: var(--font-mono);
	font-size: .8rem;
	letter-spacing: .04em;
	text-align: center;
	/* A long notice must not stretch the card; the real bar wraps too. */
	overflow-wrap: anywhere;
}

.annbar a { color: var(--gold); text-decoration: underline; }

/* Nothing stored: keep the frame so the space does not jump when text is
   typed, but drop the gold — an empty bar is not a live one. */
.annbar-wrap.is-empty .annbar {
	border-style: dashed;
	border-color: var(--border-soft);
	background: transparent;
}

.annbox {
	font-family: var(--font-mono);
	font-size: .82rem;
	min-height: 96px;
}
