@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700;800;900&family=Roboto+Mono:wght@400;500;600&display=swap');

:root {
  color-scheme: dark;
  --bg: #17181c;
  --nav-bg: #0e0f12;
  --panel: #1f2128;
  --panel-2: #262932;
  --panel-3: #31353f;
  --ink: #f2f2f4;
  --muted: #8b90a0;
  --muted-2: #5b606f;
  --line: #2a2d36;
  --line-2: #3a3e4a;
  --green: #5aab28;
  --green-2: #6ec234;
  --amber: #d98c35;
  --red: #e05252;
  --blue: #4c86d6;
  --slate: #e7ebf2;
  --button-bg: #262932;
  --console-bg: #0b0c0e;
  --radius-sm: 6px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --shadow: none;
  --shadow-pop: 0 16px 44px rgba(0, 0, 0, 0.4);
}

:root[data-theme="light"] {
  color-scheme: light;
  --bg: #f2f3f6;
  --nav-bg: #ffffff;
  --panel: #ffffff;
  --panel-2: #f2f3f7;
  --panel-3: #e6e8f0;
  --ink: #1a1b1f;
  --muted: #656b7d;
  --muted-2: #8d92a4;
  --line: #e5e6ee;
  --line-2: #d3d5e2;
  --green: #3d8a1a;
  --green-2: #4da020;
  --amber: #b87828;
  --red: #cc3333;
  --blue: #3767a8;
  --slate: #263238;
  --button-bg: #ffffff;
  --console-bg: #14161a;
  --shadow: none;
  --shadow-pop: 0 16px 44px rgba(23, 24, 28, 0.14);
}

* {
  box-sizing: border-box;
}

html {
  overflow-x: hidden;
}

body {
  margin: 0;
  min-height: 100vh;
  overflow-x: hidden;
  background: var(--bg);
  color: var(--ink);
  font-family: 'Nunito', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

body.app-booting {
  overflow: hidden;
}

button,
input,
select,
textarea {
  font: inherit;
}

button {
  cursor: pointer;
  font-family: inherit;
}

button:disabled {
  cursor: not-allowed;
  opacity: 0.45;
  filter: grayscale(0.35);
}

svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: 0 0 auto;
}

::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--line-2);
  border-radius: 4px;
}

.app {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* ── Top navigation ───────────────────────────────────────────────────── */

.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  background: var(--nav-bg);
  border-bottom: 1px solid var(--line);
}

/* Utility strip: brand + account/status widgets. Kept visually apart from
   the tab bar below it (own background tint, its own bottom rule) so the
   two rows read as separate instruments instead of one crowded line. */
.topbar-utility {
  position: relative;
  min-height: 46px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--line);
}

/* Same treatment as the tab bar below it: scroll instead of wrap when it
   doesn't fit, with the same drag-to-scroll + </> affordance wired up in
   app.js, instead of squishing the brand/status/account area together. */
.topbar-utility-scroll {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 7px 24px;
  min-height: 46px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  cursor: grab;
}

.topbar-utility-scroll::-webkit-scrollbar {
  display: none;
}

.topbar-utility-scroll.is-dragging {
  cursor: grabbing;
  user-select: none;
}

.brand {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: 8px;
}

.brand-art {
  width: 22px;
  height: 18px;
  object-fit: contain;
}

h1,
h2,
p {
  margin: 0;
}

.brand h1 {
  font-size: 15px;
  font-weight: 900;
  letter-spacing: 0.02em;
  color: var(--green-2);
  line-height: 1.1;
}

.brand p {
  display: none;
}

.brand-art,
.app-boot-card img,
.auth-hero-art {
  filter: none;
}

.muted {
  color: var(--muted);
}

.top-actions {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: 10px;
  margin-left: auto;
}

.top-actions-group {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: 4px;
}

/* Hairline separators that split the utility strip into named clusters
   (status readouts | tools | account) instead of one undifferentiated row. */
.top-actions-divider {
  width: 1px;
  flex-shrink: 0;
  align-self: stretch;
  margin: 3px 0;
  background: var(--line-2);
}

.top-actions-status {
  gap: 8px;
}

/* Icon/utility buttons living inside the nav bar are borderless, like the
   reference UI's plain nav icon buttons — bordered chip styling is reserved
   for buttons inside page content. */
.top-actions .ghost-btn,
.top-actions .icon-btn {
  background: transparent;
  border-color: transparent;
  color: var(--muted);
}

.top-actions .ghost-btn:hover,
.top-actions .icon-btn:hover {
  background: transparent;
  border-color: transparent;
  color: var(--green-2);
}

.user-menu {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: 4px;
}

.user-badge {
  min-height: 30px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 0 10px 0 12px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  color: var(--ink);
  background: transparent;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}

.user-badge:hover {
  border-color: var(--green-2);
  color: var(--green-2);
}

.user-badge-gear {
  width: 13px;
  height: 13px;
  color: var(--muted);
}

.user-badge:hover .user-badge-gear {
  color: var(--green-2);
}

/* Tabs rendered as horizontal nav links, on their own row beneath the
   utility strip so the primary navigation never has to compete with the
   account/status widgets for space. */

.topbar-tabs {
  position: relative;
  display: flex;
  padding: 0 24px;
}

/* Prev/next affordance for the tab bar, shown only while it's actually
   scrolled away from that edge (toggled in app.js). Sits over the tab bar
   itself with a fading backdrop so it reads as "more this way" rather than
   a floating, disconnected button. */
.tabs-scroll-btn {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 5;
  width: 40px;
  display: flex;
  align-items: center;
  border: 0;
  border-radius: 0;
  padding: 0;
  background: none;
  color: var(--ink);
}

.tabs-scroll-btn svg {
  width: 16px;
  height: 16px;
}

.tabs-scroll-btn:hover {
  color: var(--green-2);
}

.tabs-scroll-left {
  left: 0;
  justify-content: flex-start;
  padding-left: 4px;
  background: linear-gradient(90deg, var(--nav-bg) 40%, transparent);
}

.tabs-scroll-right {
  right: 0;
  justify-content: flex-end;
  padding-right: 4px;
  background: linear-gradient(270deg, var(--nav-bg) 40%, transparent);
}

.tabs {
  display: flex;
  align-items: stretch;
  flex: 1 1 auto;
  min-width: 0;
  gap: 2px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  cursor: grab;
}

.tabs::-webkit-scrollbar {
  display: none;
}

.tabs.is-dragging {
  cursor: grabbing;
  user-select: none;
}

/* Admin-only tabs (Velocity, WebUI-Nutzer) stay in the tab bar, but sit in
   their own group pushed to its right end and set off with a divider —
   only once at least one of them is visible, so non-admins don't get a
   stray empty gap before the top-actions widgets. */
.tabs-admin-group {
  display: flex;
  align-items: stretch;
  flex-shrink: 0;
  gap: 2px;
}

.tabs-admin-group:has(.tab:not(.hidden)) {
  margin-left: auto;
  padding-left: 14px;
  border-left: 1px solid var(--line);
}

.tab {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  gap: 7px;
  height: 56px;
  min-height: 56px;
  padding: 0 14px;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  border-radius: 0;
  background: transparent;
  color: var(--muted);
  font-size: 13.5px;
  font-weight: 700;
  white-space: nowrap;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.tab svg {
  width: 16px;
  height: 16px;
}

.tab:hover {
  color: var(--ink);
}

.tab.is-active {
  color: var(--green-2);
  border-bottom-color: var(--green-2);
}

.layout {
  width: min(1140px, calc(100vw - 32px));
  margin: 0 auto;
  padding: 28px 0 40px;
  flex: 1;
  min-width: 0;
}

.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow);
}

.control-panel,
.workspace-panel {
  background: none;
  border: 0;
  box-shadow: none;
  padding: 0;
}

.workspace-panel {
  display: block;
}

.panel-heading {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: start;
}

h2 {
  font-size: 20px;
  font-weight: 800;
  letter-spacing: 0;
}

.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 30px;
  padding: 0 11px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}

.status-pill::before {
  content: "";
  width: 7px;
  height: 7px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--muted);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--muted) 18%, transparent);
}

.proxy-health {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 30px;
  padding: 0 11px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}

.proxy-health i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--muted);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--muted) 18%, transparent);
}

.proxy-health.is-healthy,
.proxy-health.is-unhealthy {
  color: var(--ink);
}

.proxy-health.is-healthy i {
  background: var(--green-2);
  box-shadow: 0 0 0 3px rgb(110 194 52 / 20%);
}

.proxy-health.is-unhealthy i {
  background: var(--red);
  box-shadow: 0 0 0 3px rgb(224 82 82 / 20%);
}

.status-pill.is-online {
  color: var(--ink);
}

.status-pill.is-online::before {
  background: var(--green-2);
  box-shadow: 0 0 0 3px rgb(110 194 52 / 20%);
}

.status-pill.is-busy {
  color: var(--ink);
}

.status-pill.is-busy::before {
  background: #f2b64a;
  box-shadow: 0 0 0 3px rgba(242, 182, 74, 0.2);
}

.status-pill.is-error {
  color: var(--ink);
}

.status-pill.is-error::before {
  background: var(--red);
  box-shadow: 0 0 0 3px rgb(224 82 82 / 20%);
}

/* ── Dashboard (Overview tab) ────────────────────────────────────────── */

.dash-grid {
  display: grid;
  gap: 16px;
}

/* ── Server hero banner ──────────────────────────────────────────────── */

.server-hero {
  position: relative;
  min-height: 220px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  display: flex;
  align-items: center;
  padding: 30px 34px;
  background: #1c2340;
}

.server-hero-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

.server-hero-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(4, 6, 10, 0.6) 0%, rgba(4, 6, 10, 0.28) 42%, rgba(4, 6, 10, 0) 72%);
}

.server-hero-content {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 10px;
}

.server-hero-content h1 {
  font-size: clamp(24px, 3.6vw, 34px);
  font-weight: 900;
  color: #fff;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
}

.server-hero-content p {
  color: rgba(255, 255, 255, 0.82);
  font-size: 14px;
  font-weight: 600;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.3);
}

.server-hero-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
}

.hero-chip {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding: 0 12px;
  border-radius: 999px;
  background: rgba(8, 14, 12, 0.4);
  border: 1px solid rgba(255, 255, 255, 0.16);
  color: #fff;
  font-size: 12px;
  font-weight: 800;
  backdrop-filter: blur(2px);
}

.status-card {
  padding: 16px 18px;
  display: grid;
  gap: 14px;
}

.status-card-title-row {
  display: flex;
  align-items: center;
  gap: 9px;
}

.status-dot {
  width: 10px;
  height: 10px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--muted-2);
}

.status-dot.is-online {
  background: var(--green-2);
  box-shadow: 0 0 0 4px rgba(110, 194, 52, 0.2);
  animation: status-dot-pulse 2.4s ease-in-out infinite;
}

.status-dot.is-busy {
  background: #f2b64a;
  box-shadow: 0 0 0 4px rgba(242, 182, 74, 0.2);
}

.status-dot.is-error {
  background: var(--red);
  box-shadow: 0 0 0 4px rgba(224, 82, 82, 0.2);
}

.status-dot.is-offline {
  background: var(--muted-2);
}

@keyframes status-dot-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.45; }
}

.connection-box,
.meta-panel,
.world-manager,
.plugin-browser,
.resource-card {
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
}

.connection-box,
.world-manager {
  padding: 16px 18px;
}

code {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--ink);
  font-family: "Roboto Mono", "SFMono-Regular", Consolas, "Liberation Mono", monospace;
  font-size: 13px;
}

/* Connection addresses and start/stop/restart controls are both narrow
   content in a wide panel, so they share one row instead of each claiming
   the full dashboard width — leaving the resource cards below to sit
   higher up the page. */
.dash-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 16px;
}

.connection-box {
  display: grid;
  align-content: center;
  gap: 4px;
}

.connection-row {
  min-width: 0;
  min-height: 46px;
  display: grid;
  grid-template-columns: 58px minmax(0, 1fr) 32px;
  gap: 8px;
  align-items: center;
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
}

.connection-row:last-child {
  border-bottom: 0;
}

.connection-row span {
  color: var(--muted-2);
  font-size: 10.5px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.command-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.command-bar .ghost-btn,
.command-bar .primary-btn,
.command-bar .danger-btn {
  flex: 1 1 150px;
}

.action-section {
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
  display: grid;
  gap: 12px;
}

.action-heading {
  width: 100%;
}

button,
.file-picker span {
  min-width: 0;
  min-height: 38px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  padding: 0 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-weight: 800;
  font-size: 13.5px;
  white-space: nowrap;
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, color 0.15s ease;
}

button.is-loading::before {
  content: "";
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, currentColor 22%, transparent);
  border-top-color: currentColor;
  animation: spin 0.7s linear infinite;
}

button.is-loading svg {
  display: none;
}

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

.primary-btn {
  background: var(--green);
  color: #fff;
}

.primary-btn:hover {
  background: var(--green-2);
  box-shadow: 0 4px 16px rgba(90, 171, 40, 0.3);
}

.secondary-btn {
  background: var(--blue);
  color: #fff;
}

.secondary-btn:hover {
  background: color-mix(in srgb, var(--blue) 82%, white 18%);
  box-shadow: 0 4px 16px rgba(76, 134, 214, 0.28);
}

.danger-btn {
  background: transparent;
  color: var(--red);
  border-color: var(--red);
}

.danger-btn:hover {
  background: rgba(224, 82, 82, 0.12);
}

.ghost-btn,
.icon-btn {
  background: var(--button-bg);
  color: var(--slate);
  border-color: var(--line-2);
}

.ghost-btn:hover,
.icon-btn:hover {
  border-color: var(--green-2);
  color: var(--green-2);
}

.icon-btn {
  width: 36px;
  height: 36px;
  padding: 0;
}

.action-feedback {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 20px;
  color: var(--muted);
  font-size: 13px;
}

.action-feedback-spinner {
  width: 13px;
  height: 13px;
  border: 2px solid var(--line);
  border-top-color: var(--green-2);
  border-radius: 50%;
  animation: action-spin .8s linear infinite;
}

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

.upload-progress {
  display: grid;
  gap: 8px;
  margin-bottom: 14px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-2);
  color: var(--muted);
  font-size: 13px;
}

.upload-progress-heading {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  color: var(--ink);
}

.upload-progress-track {
  height: 6px;
  overflow: hidden;
  border-radius: 3px;
  background: var(--panel-3);
}

.upload-progress-track i {
  display: block;
  width: 0;
  height: 100%;
  background: var(--green-2);
  transition: width 120ms ease-out;
}

/* ── Resource / stat cards (mirrors reference dashboard tiles) ─────────── */

.resource-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
}

.resource-card {
  padding: 14px 16px;
  display: grid;
  gap: 8px;
}

.resource-card-label {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--muted-2);
  font-size: 10.5px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.resource-card-label svg {
  width: 13px;
  height: 13px;
}

.resource-card-value {
  display: flex;
  align-items: baseline;
  gap: 7px;
}

.resource-card-value strong {
  font-size: 22px;
  font-weight: 800;
  color: var(--green-2);
}

.resource-card-value span {
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
}

/* ── Server-Auslastung tab (per-instance CPU/RAM, same tiles as the
   single-server dashboard) ─────────────────────────────────────────────── */

.server-metrics-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(280px, 1fr));
  gap: 16px;
}

.server-metric-group {
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
  display: grid;
  gap: 12px;
}

.server-metric-group-heading {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.server-metric-group-heading strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.server-metric-group-heading span {
  margin-left: auto;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
}

.server-metric-group .resource-cards {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.server-metric-group .resource-card {
  padding: 12px 14px;
  background: var(--panel-2);
}

#serverMetricsSection.is-locked #serverMetricsList {
  filter: blur(4px);
  opacity: 0.58;
  pointer-events: none;
  user-select: none;
}

.mini-heading,
.section-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}

.mini-heading strong {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--muted-2);
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.09em;
}

.section-title h2 {
  display: flex;
  align-items: center;
  gap: 9px;
}

.section-title h2 svg {
  width: 20px;
  height: 20px;
  color: var(--green-2);
}

.tab-page > .section-title {
  margin-bottom: 16px;
}

.section-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
}

.text-btn {
  min-height: 28px;
  padding: 0;
  color: var(--green-2);
  background: transparent;
  border: 0;
}

.metric-row {
  display: grid;
  grid-template-columns: 44px 74px minmax(0, 1fr);
  gap: 8px;
  align-items: center;
  color: var(--muted);
  font-size: 13px;
}

.metric-row strong {
  color: var(--ink);
  text-align: right;
}

.history-list,
.user-list {
  display: grid;
  gap: 8px;
}

/* ── Stats tab ────────────────────────────────────────────────────────── */

#tab-stats .mini-heading {
  margin: 26px 0 10px;
}

#tab-stats .mini-heading:first-child {
  margin-top: 0;
}

.stats-table {
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
  overflow: hidden;
}

.stats-row {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr) 120px 110px 140px;
  gap: 14px;
  align-items: center;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
}

.stats-row:last-child {
  border-bottom: 0;
}

.stats-row-head {
  background: var(--panel-2);
  color: var(--muted-2);
  font-size: 10.5px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.stats-row strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.stats-rank {
  color: var(--muted);
  font-weight: 800;
}

.stats-bar-track {
  height: 6px;
  border-radius: 999px;
  background: var(--panel-3);
  overflow: hidden;
}

.stats-bar-track i {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--green-2);
}

.chart-card {
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
}

.chart-card svg {
  width: 100%;
  height: auto;
  display: block;
  overflow: visible;
  /* The global svg{} rule (for the app's stroke-based line icons) sets
     stroke: currentColor + stroke-width: 2 on every svg by default. Chart
     shapes that don't set their own stroke (axis text, bars) were silently
     inheriting that — a 2px near-white outline around small text reads as
     bold and washed out. Reset it here so only elements that explicitly
     opt into a stroke (grid lines, chart lines) get one. */
  stroke: none;
}

.chart-card .chart-axis {
  fill: var(--muted-2);
  font-family: 'Nunito', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 10px;
  font-weight: 500;
}

.chart-card .chart-grid {
  stroke: var(--line);
  stroke-width: 1;
}

.chart-svg-wrap {
  position: relative;
}

.chart-card .chart-hover-line {
  stroke: var(--line-2);
  stroke-width: 1;
  opacity: 0;
  pointer-events: none;
}

.chart-card .chart-hover-dot {
  stroke: var(--panel);
  stroke-width: 1.5;
  opacity: 0;
  pointer-events: none;
}

.chart-tooltip {
  position: absolute;
  top: 4px;
  transform: translateX(-50%);
  min-width: 128px;
  padding: 8px 10px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
  box-shadow: var(--shadow-pop);
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.1s ease;
  z-index: 2;
}

.chart-tooltip strong {
  display: block;
  margin-bottom: 4px;
  color: var(--ink);
  font-size: 11.5px;
}

.chart-tooltip span {
  display: block;
}

.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 12px;
  font-family: 'Nunito', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 12px;
  color: var(--muted);
  font-weight: 700;
}

.chart-legend span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.chart-legend i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  display: inline-block;
}

.history-list {
  min-height: 0;
  max-height: none;
  overflow: auto;
  padding-right: 4px;
}

.history-row,
.empty-note,
.context-note {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}

.history-row span,
.empty-note,
.context-note,
#metricsSampleTime {
  color: var(--muted);
  font-size: 12px;
}

.history-row {
  min-height: 68px;
  padding: 12px 14px;
  display: grid;
  grid-template-columns: minmax(180px, 1.5fr) minmax(160px, 1fr) minmax(120px, 0.8fr) minmax(120px, 0.8fr);
  gap: 12px;
  align-items: center;
}

.history-row div {
  min-width: 0;
  display: grid;
  gap: 4px;
}

.history-row strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.empty-note,
.context-note {
  padding: 12px 14px;
}

.context-note {
  margin-bottom: 14px;
}

.world-manager {
  margin-bottom: 18px;
}

.world-create {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
}

.world-list {
  display: grid;
  gap: 8px;
}

.join-profile-panel {
  display: grid;
  gap: 10px;
  margin: 0 0 16px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
}

.join-profile-form {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) auto;
  gap: 10px;
  align-items: end;
}

.world-row {
  min-height: 58px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 10px;
  align-items: center;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
  transition: border-color 0.15s ease;
}

.world-row:hover {
  border-color: var(--line-2);
}

.server-instance-row {
  grid-template-columns: minmax(0, 1fr) repeat(4, auto);
}

.world-row .server-instance-main {
  min-width: 0;
  display: grid;
  gap: 3px;
}

.world-row .server-title-line {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
}

.player-count-pill {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  padding: 0 8px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  color: var(--slate) !important;
  background: var(--panel-3);
  font-size: 11.5px;
  font-weight: 800;
}

.server-player-details {
  margin-top: 4px;
  color: var(--muted);
  font-size: 12px;
}

.server-player-details summary {
  width: fit-content;
  cursor: pointer;
  font-weight: 800;
}

.server-player-list {
  min-width: 0;
  display: flex !important;
  flex-wrap: wrap;
  gap: 6px;
  padding-top: 7px;
}

.player-name-chip,
.player-name-empty,
.player-name-note {
  white-space: normal !important;
}

.player-name-chip {
  padding: 3px 8px;
  border: 1px solid rgba(90, 171, 40, 0.35);
  border-radius: 999px;
  color: var(--green-2) !important;
  background: rgba(90, 171, 40, 0.1);
  font-size: 12px;
  font-weight: 700;
}

.player-name-note {
  flex-basis: 100%;
  color: var(--muted) !important;
}

.server-actions-menu {
  position: relative;
}

.server-actions-menu summary {
  list-style: none;
  cursor: pointer;
  min-height: 38px;
  border-radius: var(--radius-sm);
  padding: 0 13px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-weight: 800;
  font-size: 13.5px;
  white-space: nowrap;
  background: var(--button-bg);
  border: 1px solid var(--line-2);
  color: var(--slate);
}

.server-actions-menu summary:hover {
  border-color: var(--green-2);
  color: var(--green-2);
}

.server-actions-menu summary::-webkit-details-marker {
  display: none;
}

.server-actions-list {
  position: absolute;
  right: 0;
  z-index: 12;
  min-width: 150px;
  margin-top: 6px;
  padding: 8px;
  display: grid;
  gap: 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
  box-shadow: var(--shadow-pop);
}

.server-actions-list button {
  width: 100%;
}

.proxy-panel {
  display: grid;
  gap: 14px;
}

.proxy-toggle-row {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
}

.proxy-toggle {
  width: fit-content;
}

.proxy-panel.is-locked .proxy-toggle,
.proxy-panel.is-locked .proxy-lobby,
.proxy-panel.is-locked .section-actions {
  opacity: 0.56;
}

.proxy-lobby {
  max-width: 420px;
}

.proxy-lobby small {
  color: var(--muted);
  font-size: 12px;
  line-height: 1.4;
}

.proxy-panel.is-locked #proxySummary,
.proxy-panel.is-locked #bedrockGatewaySummary,
.proxy-panel.is-locked #velocityConfig {
  filter: blur(4px);
  opacity: 0.58;
  pointer-events: none;
  user-select: none;
}

#webUserSection.is-locked #userList {
  filter: blur(4px);
  opacity: 0.58;
  pointer-events: none;
  user-select: none;
}

.config-output {
  width: 100%;
  height: 320px;
  resize: vertical;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 14px;
  color: var(--ink);
  background: var(--console-bg);
  font-family: "Roboto Mono", "SFMono-Regular", Consolas, "Liberation Mono", monospace;
  font-size: 12px;
  line-height: 1.5;
}

/* Modal offen: Seite dahinter lässt sich nicht scrollen. Die Scrollleiste
   behält ihren Platz, damit die Seite beim Öffnen nicht seitlich springt. */
html.modal-open {
  overflow: hidden;
  scrollbar-gutter: stable;
}

/* Scrollen im Modal reicht am Anfang/Ende nicht an die Seite durch. */
.modal-overlay,
.config-modal {
  overscroll-behavior: contain;
}

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 35;
  display: grid;
  place-items: center;
  padding: 24px;
  overflow: auto;
  background: rgba(8, 9, 11, 0.72);
}

.config-modal {
  width: min(1060px, 100%);
  max-height: min(900px, calc(100vh - 48px));
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--panel);
  box-shadow: var(--shadow-pop);
}

.user-edit-modal {
  width: min(720px, 100%);
}

.confirm-modal {
  width: min(520px, 100%);
}

.confirm-message {
  margin: 0 0 18px;
  line-height: 1.5;
}

.modal-heading {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  padding: 18px 20px;
  border-bottom: 1px solid var(--line);
  background: var(--panel-2);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

.modal-heading h2 {
  margin-top: 3px;
}

.config-running-notice {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 16px 20px 0;
  padding: 10px 14px;
  border: 1px solid var(--amber);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--amber) 12%, transparent);
  color: var(--ink);
  font-size: 13px;
  line-height: 1.45;
}

.config-running-notice strong {
  color: var(--amber);
}

.config-modal .tab-page {
  display: block;
  padding: 20px;
}

.config-modal .tab-page + .tab-page {
  border-top: 1px solid var(--line);
}

/* ── Server-Konfiguration: Raster, Selects, Welt-Bereich, Aktionsleiste ── */

#configForm {
  --modal-pad: 20px;
}

/* Felder nur so hoch wie ihr Inhalt. Sonst dehnt eine höhere Nachbarzelle
   (z. B. Velocity-Name mit Hinweis) das Label und schiebt das Eingabefeld
   nach unten. */
#configForm .form-grid {
  align-items: start;
}

/* Breite Felder nutzen die volle Zeilenbreite statt zwei von drei Spalten,
   damit rechts keine Lücke bleibt und Server-Typ nicht danebenrutscht. */
#configForm .form-grid > .wide {
  grid-column: 1 / -1;
}

/* Checkboxen: am Boden der Zeile ausrichten (auf Höhe der Eingabefelder) und
   ohne Extra-Abstand oben, wenn eine Zeile nur aus Checkboxen besteht. */
#configForm .form-grid > .check-row {
  align-self: end;
  padding-top: 0;
}

/* Native Selects sind in Safari nur ~27px hoch und haben einen eigenen
   Verlauf; hier sehen sie aus und messen wie die Eingabefelder. */
.config-modal select {
  -webkit-appearance: none;
  appearance: none;
  padding-right: 38px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238b90a0' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 14px;
  cursor: pointer;
}

/* Welt-Bereich: gleichmäßiger Abstand zwischen Titel, Eingabezeilen und Liste. */
.world-manager {
  display: grid;
  gap: 12px;
}

/* Aktionsleiste bleibt beim Scrollen am unteren Rand des Modals erreichbar. */
#configForm .form-actions {
  position: sticky;
  bottom: 0;
  z-index: 1;
  margin: 20px calc(var(--modal-pad) * -1) calc(var(--modal-pad) * -1);
  padding: 14px var(--modal-pad);
  border-top: 1px solid var(--line);
  background: var(--panel-2);
}

.modal-form {
  padding: 20px;
}

.modal-form .context-note {
  margin: 0 0 14px;
}

.modal-form .form-actions {
  gap: 10px;
}

.create-world-setup {
  margin-bottom: 18px;
}

.world-row.is-active {
  border-color: var(--green-2);
  background: rgba(90, 171, 40, 0.06);
}

/* Versteckte Instanzen (nur für WebUI-Admins sichtbar): gestrichelte Kontur,
   auch zusammen mit der grünen Kontur der ausgewählten Instanz erkennbar. */
.world-row.is-hidden-instance {
  outline: 2px dashed var(--amber);
  outline-offset: 2px;
}

.world-row.is-hidden-instance:not(.is-active) {
  background: color-mix(in srgb, var(--amber) 7%, var(--panel-2));
}

.world-row div {
  min-width: 0;
  display: grid;
  gap: 3px;
}

.world-row .server-actions-list {
  display: grid;
  gap: 10px;
}

.world-folder-list {
  margin-top: 8px;
  display: grid;
  gap: 6px;
}

.world-folder-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
  padding: 7px 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
}

.world-row strong,
.world-row span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.world-row span {
  color: var(--muted);
  font-size: 12px;
}

.world-server-info {
  color: var(--ink) !important;
}

.world-warning {
  margin-top: 6px;
  padding: 8px 10px;
  border: 1px solid rgba(217, 140, 53, 0.4);
  border-radius: var(--radius-sm);
  background: rgba(217, 140, 53, 0.12);
  color: var(--amber);
  font-size: 12px;
  line-height: 1.35;
}

.meter {
  height: 5px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--panel-3);
}

.meter i {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--green-2);
  transition: width 180ms ease;
}

.meta-panel {
  display: contents;
}

.meta-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
}

.meta-grid-narrow {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.meta-grid div {
  min-width: 0;
}

.meta-directory {
  min-width: 0;
}

.meta-grid span,
.meta-directory span {
  display: block;
  color: var(--muted-2);
  font-size: 10.5px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.meta-grid strong,
.meta-directory strong {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 5px;
  font-size: 15px;
  font-weight: 800;
}

.tab-page {
  display: none;
  max-width: 100%;
  min-width: 0;
}

.tab-page.is-active {
  display: block;
}

#tab-console.is-active {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  height: calc(100vh - 200px);
  min-height: 480px;
  gap: 12px;
}

#tab-console .section-title {
  margin-bottom: 0;
}

.form-section + .form-section {
  margin-top: 26px;
}

.form-section-title {
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line);
  color: var(--muted-2);
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.09em;
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(160px, 1fr));
  gap: 14px;
}

label {
  display: grid;
  gap: 7px;
  min-width: 0;
}

label span {
  color: var(--muted-2);
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

input,
select {
  width: 100%;
  min-height: 40px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  color: var(--ink);
  background: var(--button-bg);
  padding: 0 12px;
  outline: none;
}

input:focus,
select:focus {
  border-color: var(--green-2);
  box-shadow: 0 0 0 3px rgba(90, 171, 40, 0.18);
}

.proxy-name-field {
  display: grid;
  gap: 7px;
  min-width: 0;
}

.proxy-name-row {
  display: flex;
  gap: 8px;
}

.proxy-name-row input {
  flex: 1 1 auto;
}

.proxy-name-hint {
  color: var(--muted);
  font-size: 12px;
  line-height: 1.4;
}

.proxy-name-hint code {
  color: var(--ink);
}

.wide {
  grid-column: span 2;
}

.check-row {
  min-height: 40px;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 9px;
  padding-top: 21px;
}

.check-row input {
  width: 18px;
  min-height: 18px;
  accent-color: var(--green);
}

.form-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 18px;
}

.user-form {
  display: grid;
  grid-template-columns: minmax(150px, 1fr) minmax(190px, 1.2fr) minmax(140px, 180px) minmax(170px, 1fr) auto;
  gap: 14px;
  align-items: end;
  margin: 14px 0 16px;
}

.user-form .form-actions {
  margin-top: 0;
}

.user-minecraft-field {
  grid-column: span 4;
}

.server-role-heading {
  margin: 20px 0 10px;
}

.user-row {
  min-height: 58px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 130px 120px auto auto;
  gap: 10px;
  align-items: center;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}

.user-row div {
  min-width: 0;
  display: grid;
  gap: 3px;
}

.server-role-row {
  min-height: 54px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 120px 120px 150px auto auto;
  column-gap: 22px;
  row-gap: 10px;
  align-items: center;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}

.server-role-row div {
  min-width: 0;
  display: grid;
  gap: 3px;
}

.user-row strong,
.user-row span,
.server-role-row strong,
.server-role-row span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-row span,
.server-role-row span {
  color: var(--muted);
  font-size: 12px;
}

.server-role-row > span:not(.role-chip) {
  min-width: 0;
  padding-left: 10px;
  line-height: 1.35;
  white-space: normal;
}

.role-chip {
  justify-self: start;
  min-height: 26px;
  display: inline-flex;
  align-items: center;
  padding: 0 10px;
  line-height: 1.2;
  text-align: center;
  white-space: normal;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: var(--panel-3);
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 800;
}

.role-chip.is-operator {
  color: var(--green-2);
  background: rgba(90, 171, 40, 0.12);
  border-color: rgba(90, 171, 40, 0.4);
}

.hidden {
  display: none !important;
}

.file-toolbar {
  display: grid;
  max-width: 100%;
  min-width: 0;
  grid-template-columns: 220px auto;
  align-items: end;
  gap: 12px;
}

.file-picker input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.file-picker span {
  border-color: var(--line);
  background: var(--green);
  color: #fff;
  text-transform: none;
  letter-spacing: normal;
}

.url-installer {
  margin-top: 14px;
  display: grid;
  max-width: 100%;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
}

.plugin-browser {
  margin-top: 16px;
  max-width: 100%;
  min-width: 0;
  padding: 16px;
}

.plugin-browser .section-title {
  margin-bottom: 10px;
}

.plugin-search {
  display: grid;
  max-width: 100%;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr) 160px auto;
  gap: 10px;
}

.plugin-browser .context-note {
  margin: 10px 0 0;
  padding: 8px 0 0;
  border: 0;
  background: transparent;
}

/* Anchor for the floating results panel below — sized by its normal-flow
   content (search form + status line) only, so the panel's "top: 100%"
   always lands right under it regardless of layout/breakpoint. */
.plugin-search-wrap {
  position: relative;
}

.plugin-list {
  display: none;
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  z-index: 8;
  margin-top: 8px;
  gap: 8px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
  box-shadow: var(--shadow-pop);
  /* Cap the visible list to ~5 results (5 * 64px rows + 4 * 8px gaps);
     anything beyond that scrolls, and the panel floats over the installed
     plugins list below instead of pushing it down. */
  max-height: 352px;
  overflow-y: auto;
}

/* Only shown while the search input is focused (see app.js) — a dropdown,
   not a permanent fixture, so it doesn't sit over the installed list when
   the user isn't actively searching. */
.plugin-list.is-open {
  display: grid;
}

.plugin-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 10px;
  align-items: center;
  min-height: 64px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}

.plugin-row div {
  min-width: 0;
  display: grid;
  gap: 3px;
}

.plugin-row strong,
.plugin-row span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.plugin-row span {
  color: var(--muted);
  font-size: 12px;
}

.plugin-open-link {
  min-height: 38px;
  padding: 0 13px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  font-weight: 800;
  border-radius: var(--radius-sm);
}

.file-list {
  margin-top: 16px;
  display: grid;
  gap: 8px;
}

.file-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 10px;
  align-items: center;
  min-height: 48px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}

.file-row strong {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-row span {
  color: var(--muted);
  font-size: 12px;
}

.console-output {
  min-height: 0;
  height: auto;
  margin: 0;
  overflow: auto;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--console-bg);
  color: #b9f0c4;
  font: 13px/1.7 "Roboto Mono", "SFMono-Regular", Consolas, "Liberation Mono", monospace;
  white-space: pre-wrap;
}

#tab-console.is-locked .console-output {
  filter: blur(4px);
  opacity: 0.58;
  pointer-events: none;
  user-select: none;
}

#tab-console.is-locked .console-command {
  opacity: 0.56;
}

.console-command {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  margin-top: 0;
}

#commandLocked {
  margin: 0;
}

.command-input-wrap {
  position: relative;
  min-width: 0;
}

.command-input-wrap input {
  font-family: "Roboto Mono", "SFMono-Regular", Consolas, "Liberation Mono", monospace;
}

.command-palette {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(100% + 8px);
  z-index: 10;
  display: none;
  max-height: 260px;
  overflow: auto;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
  box-shadow: var(--shadow-pop);
}

.command-palette.is-open {
  display: grid;
  gap: 4px;
}

.command-suggestion {
  min-height: 44px;
  justify-content: flex-start;
  display: grid;
  grid-template-columns: minmax(120px, 0.7fr) minmax(0, 1fr);
  width: 100%;
  border-color: transparent;
  background: transparent;
  color: var(--ink);
  text-align: left;
}

.command-suggestion:hover {
  background: var(--panel-2);
}

.command-suggestion span {
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
}

.toast {
  position: fixed;
  left: 50%;
  bottom: 20px;
  transform: translate(-50%, 16px);
  opacity: 0;
  pointer-events: none;
  max-width: min(520px, calc(100vw - 24px));
  padding: 12px 16px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  background: var(--panel-3);
  color: var(--ink);
  font-weight: 700;
  box-shadow: var(--shadow-pop);
  transition: opacity 160ms ease, transform 160ms ease;
  z-index: 60;
}

.toast.is-visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

.app-boot-overlay {
  position: fixed;
  inset: 0;
  z-index: 55;
  display: grid;
  place-items: center;
  padding: 24px;
  background:
    radial-gradient(circle at 20% 0%, rgba(90, 171, 40, 0.16), transparent 42%),
    radial-gradient(circle at 85% 20%, rgba(76, 134, 214, 0.14), transparent 42%),
    var(--bg);
  opacity: 1;
  transition: opacity 260ms ease, visibility 260ms ease;
}

body.app-ready .app-boot-overlay {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.app-boot-card {
  width: min(360px, 100%);
  display: grid;
  justify-items: center;
  gap: 12px;
  padding: 30px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--panel);
  box-shadow: var(--shadow-pop);
  text-align: center;
}

.app-boot-card img {
  width: 64px;
  height: 50px;
  object-fit: contain;
}

.app-boot-card strong {
  font-size: 19px;
  font-weight: 800;
}

.app-boot-card span {
  color: var(--muted);
  font-size: 13px;
}

.app-boot-card i {
  width: 100%;
  height: 4px;
  margin-top: 6px;
  border-radius: 999px;
  background: linear-gradient(90deg, transparent, var(--green-2), transparent);
  background-size: 220% 100%;
  animation: boot-meter 1.1s ease-in-out infinite;
}

body.app-booting .app {
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
}

/* Ruhezustand ohne transform: auch translateY(0) würde .app zum Bezugsrahmen
   für position: fixed machen, und Modals/Overlays hingen dann an der
   Seitenhöhe statt am Fenster (verschoben, unten abgeschnitten). */
body.app-ready .app {
  opacity: 1;
  transform: none;
  transition: opacity 260ms ease, transform 260ms ease;
}

@keyframes boot-meter {
  from {
    background-position: 120% 0;
  }
  to {
    background-position: -120% 0;
  }
}

.auth-overlay {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  padding: 26px;
  overflow: auto;
  background:
    radial-gradient(circle at 15% 10%, rgba(90, 171, 40, 0.18), transparent 40%),
    radial-gradient(circle at 88% 22%, rgba(76, 134, 214, 0.16), transparent 42%),
    var(--bg);
}

.auth-shell {
  width: min(940px, 100%);
  display: grid;
  grid-template-columns: minmax(280px, 0.95fr) minmax(340px, 420px);
  gap: 18px;
  align-items: stretch;
}

.auth-hero {
  min-height: 520px;
  display: grid;
  align-content: center;
  gap: 22px;
  padding: 32px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0)),
    var(--panel);
  box-shadow: var(--shadow);
}

.auth-hero-art {
  width: 96px;
  height: 76px;
  object-fit: contain;
}

.auth-hero h1 {
  font-size: 40px;
  font-weight: 900;
}

.auth-hero p {
  margin-top: 8px;
  color: var(--muted);
}

.auth-hero-status {
  display: grid;
  gap: 6px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-2);
}

.auth-hero-status span {
  color: var(--muted-2);
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.auth-hero-status strong {
  font-size: 18px;
  font-weight: 800;
}

.auth-card {
  display: grid;
  gap: 14px;
  align-content: center;
  min-height: 520px;
  padding: 28px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--panel);
  box-shadow: var(--shadow);
}

.auth-card-header {
  min-height: 58px;
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr);
  align-items: start;
  column-gap: 12px;
}

.auth-back-icon {
  grid-column: 1;
  align-self: start;
  margin-top: 2px;
}

.auth-back-icon.hidden {
  display: inline-flex !important;
  visibility: hidden;
  pointer-events: none;
}

.auth-card-header > div {
  min-width: 0;
  grid-column: 2;
}

.auth-step-label {
  color: var(--green-2);
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.auth-card button {
  width: 100%;
}

.auth-card .auth-back-icon {
  width: 36px;
  min-width: 36px;
}

.auth-links {
  display: flex;
  justify-content: space-between;
  gap: 10px;
}

.auth-links button {
  width: auto;
  color: var(--green-2);
}

.auth-card p {
  min-height: 18px;
  font-size: 13px;
}

.app.is-auth-locked {
  display: none;
}

/* ── Profile page ─────────────────────────────────────────────────────── */

.profile-hero {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  gap: 22px;
  padding: 26px 30px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background:
    radial-gradient(circle at 88% -20%, rgba(90, 171, 40, 0.28), transparent 55%),
    linear-gradient(135deg, #1c2340 0%, #241b3d 100%);
}

.profile-hero-avatar-wrap {
  flex: 0 0 auto;
  width: 76px;
  height: 76px;
  padding: 2px;
  border-radius: var(--radius-md);
  background: linear-gradient(135deg, var(--green-2), var(--blue));
}

.profile-hero-avatar {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: calc(var(--radius-md) - 2px);
  object-fit: cover;
  background: #0e0f12;
}

.profile-hero-info {
  min-width: 0;
  display: grid;
  gap: 10px;
}

.profile-hero-info h1 {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: clamp(20px, 2.4vw, 26px);
  font-weight: 900;
  color: #fff;
}

.profile-hero-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.profile-columns {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  align-items: start;
  margin-top: 16px;
}

.profile-column {
  display: grid;
  gap: 16px;
}

.profile-card {
  padding: 18px 20px;
  display: grid;
  align-content: start;
  gap: 14px;
}

.profile-card-heading {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.profile-card-heading svg {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  color: var(--green-2);
}

.profile-card-heading h3 {
  font-size: 14px;
  font-weight: 800;
}

.profile-card-heading p {
  margin-top: 2px;
  color: var(--muted);
  font-size: 12px;
}

.profile-form {
  display: grid;
  gap: 12px;
}

.profile-form .form-actions {
  margin-top: 0;
}

.profile-email-current {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 24px;
  color: var(--ink);
  font-weight: 700;
  font-size: 14px;
}

/* Shown in place of the verified email while a new one is awaiting
   confirmation: paled back so it visually reads as "not final yet". */
.profile-pending-email {
  color: var(--muted);
  opacity: 0.65;
}

/* A <details> so the "needs confirmation" note opens on click (native,
   works on touch) as well as on hover (via the CSS below) — same
   interaction the server-actions dropdown already uses elsewhere. */
.profile-pending-flag {
  position: relative;
  display: inline-flex;
}

.profile-pending-flag summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  color: var(--amber);
}

.profile-pending-flag summary::-webkit-details-marker {
  display: none;
}

.profile-pending-flag svg {
  width: 16px;
  height: 16px;
}

.profile-pending-tooltip {
  position: absolute;
  left: 0;
  top: calc(100% + 8px);
  z-index: 6;
  display: none;
  width: max-content;
  max-width: 260px;
  padding: 10px 12px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-md);
  background: var(--panel-2);
  box-shadow: var(--shadow-pop);
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.4;
}

.profile-pending-flag:hover .profile-pending-tooltip,
.profile-pending-flag[open] .profile-pending-tooltip {
  display: block;
}

.profile-autojoin {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid rgba(76, 134, 214, 0.4);
  border-radius: var(--radius-sm);
  background: rgba(76, 134, 214, 0.08);
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.4;
}

.profile-autojoin span {
  min-width: 0;
  flex: 1 1 220px;
}

.profile-server-roles {
  display: grid;
  gap: 8px;
}

.profile-server-role-row {
  min-height: 48px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}

.profile-server-role-row strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.profile-server-role-row.is-active {
  border-color: var(--green-2);
  background: rgba(90, 171, 40, 0.06);
}

.profile-verified-names {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.verified-name-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px 3px 7px;
  border: 1px solid rgba(90, 171, 40, 0.35);
  border-radius: 999px;
  background: rgba(90, 171, 40, 0.1);
  color: var(--green-2);
  font-size: 12px;
  font-weight: 700;
}

.verified-name-chip svg {
  width: 12px;
  height: 12px;
}

.verified-name-chip.is-unverified {
  border-color: rgba(217, 140, 53, 0.45);
  background: rgba(217, 140, 53, 0.12);
  color: var(--amber);
}

.profile-name-note {
  flex-basis: 100%;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.4;
}

.profile-code-verify {
  display: grid;
  gap: 6px;
  padding-top: 4px;
  border-top: 1px solid var(--line);
}

.profile-code-verify p {
  color: var(--muted);
  font-size: 12px;
}

.profile-code-box {
  display: grid;
  gap: 6px;
  padding: 12px 14px;
  border: 1px solid rgba(90, 171, 40, 0.35);
  border-radius: var(--radius-sm);
  background: rgba(90, 171, 40, 0.08);
  font-size: 12px;
  color: var(--muted);
}

.profile-code-box code {
  overflow: visible;
  color: var(--green-2);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.04em;
  user-select: all;
}

.profile-microsoft-link {
  display: grid;
  gap: 6px;
  padding-top: 4px;
  border-top: 1px solid var(--line);
}

.profile-microsoft-link p {
  color: var(--muted);
  font-size: 12px;
}

@media (max-width: 980px) {
  .meta-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .form-grid {
    grid-template-columns: repeat(2, minmax(150px, 1fr));
  }

  .server-metrics-list,
  .auth-shell,
  .join-profile-form,
  .server-instance-row,
  .user-form,
  .user-row,
  .server-role-row,
  .history-row,
  .profile-columns,
  .profile-server-role-row {
    grid-template-columns: 1fr;
  }

  .profile-hero {
    flex-wrap: wrap;
  }

  .server-instance-row button {
    width: 100%;
  }

  .user-minecraft-field {
    grid-column: auto;
  }
}

@media (max-width: 720px) {
  .topbar-utility-scroll {
    padding: 10px 16px;
    min-height: 0;
  }

  .topbar-tabs {
    padding: 0 16px;
  }

  .tab {
    height: 44px;
    min-height: 44px;
  }

  .top-actions {
    margin-left: auto;
  }

  #tab-console.is-active {
    height: auto;
    min-height: 0;
  }

  .console-output {
    height: 420px;
  }
}

@media (max-width: 640px) {
  .layout {
    width: min(100vw - 20px, 1140px);
    padding-top: 16px;
  }

  .command-bar,
  .form-grid,
  .file-toolbar,
  .url-installer,
  .plugin-search,
  .plugin-row,
  .console-command,
  .world-create,
  .world-row,
  .dash-split {
    width: 100%;
    grid-template-columns: 1fr;
  }

  .command-bar .ghost-btn,
  .command-bar .primary-btn,
  .command-bar .danger-btn {
    flex-basis: 100%;
  }

  .server-actions-list {
    position: static;
    min-width: 0;
  }

  .wide {
    grid-column: auto;
  }

  .auth-overlay {
    padding: 14px;
  }

  .auth-hero {
    min-height: auto;
    padding: 22px;
  }

  .auth-card {
    min-height: auto;
    padding: 22px;
  }

  .meta-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
  }

  /* The generic "stack this row's buttons full-width" rule from the 980px
     tier also catches the small square edit icon button — keep that one
     compact instead of stretching it across the row. */
  .server-instance-row .icon-btn {
    width: 36px;
    justify-self: start;
  }

  .modal-overlay {
    padding: 10px;
  }

  .config-modal .tab-page,
  .modal-form {
    padding: 16px;
  }

  #configForm {
    --modal-pad: 16px;
  }

  .modal-heading {
    padding: 16px;
  }

  /* Stats table: with no room for five fixed columns, stack each player's
     numbers into labeled lines instead of letting the row overflow. */
  .stats-row-head {
    display: none;
  }

  .stats-row {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "rank name"
      ". conn"
      ". play"
      ". bar";
    row-gap: 5px;
  }

  .stats-row > .stats-rank {
    grid-area: rank;
  }

  .stats-row > strong {
    grid-area: name;
  }

  .stats-row > span:nth-of-type(2) {
    grid-area: conn;
  }

  .stats-row > span:nth-of-type(3) {
    grid-area: play;
  }

  .stats-row > span:nth-of-type(2)::before {
    content: "Verbindungen: ";
    color: var(--muted-2);
  }

  .stats-row > span:nth-of-type(3)::before {
    content: "Spielzeit: ";
    color: var(--muted-2);
  }

  .stats-row > .stats-bar-track {
    grid-area: bar;
  }
}

@media (max-width: 420px) {
  .meta-grid {
    grid-template-columns: 1fr;
  }

  .resource-cards {
    grid-template-columns: 1fr;
  }
}
