@font-face {
  font-family: "Minecraft";
  src: url("/fonts/Minecraft.otf") format("opentype");
  font-weight: normal;
}
@font-face {
  font-family: "Minecraft";
  src: url("/fonts/Minecraft-Bold.otf") format("opentype");
  font-weight: bold;
}

:root {
  color-scheme: dark;
  /* Vanilla-Inventar-Grautöne */
  --stone: #2b2b2b;
  --stone-light: #3f3f3f;
  --stone-dark: #1a1a1a;
  --slot: #8b8b8b;
  --panel: #313131;
  --panel-alt: #262626;
  --border-light: #565656;
  --border-dark: #0f0f0f;
  --text: #ffffff;
  --text-dim: #a0a0a0;
  --accent: #58a3ff;
  --danger: #d43c3c;
  --danger-dark: #7a1f1f;
  --warn: #e2a33c;
  --warn-dark: #7a4f10;
  --ok: #3fb950;
  --ok-dark: #1f6e2c;
  --accent-dark: #1c4a7a;
  --gold: #ffd83d;
}

* { box-sizing: border-box; }

html, body { height: 100%; overflow: hidden; }

/* Auf schmalen/mobilen Bildschirmen NICHT auf 100vh einsperren - sonst wird alles, was nicht
   reinpasst (z.B. die Serverstatus-Leiste ganz unten), einfach unsichtbar abgeschnitten, ohne
   dass man dorthin scrollen könnte. */
@media (max-width: 900px) {
  html, body { height: auto; min-height: 100%; overflow: visible; }
  body { overflow-y: auto; }
}

body {
  margin: 0;
  font-family: "Minecraft", "Segoe UI", monospace;
  background: var(--stone-dark);
  background-image:
    linear-gradient(rgba(255,255,255,.02) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.02) 1px, transparent 1px);
  background-size: 16px 16px;
  color: var(--text);
  text-shadow: 1px 1px 0 rgba(0,0,0,.5);
  display: flex;
  flex-direction: column;
}

.topbar, .status-bar, .site-footer { flex-shrink: 0; }

h2, h3, .brand, button, .me, input, select, textarea { font-family: "Minecraft", "Segoe UI", monospace; }

.topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 24px;
  background: var(--stone);
  border-bottom: 2px solid var(--border-dark);
  box-shadow: 0 2px 0 rgba(255,255,255,.05) inset;
}

.brand { font-size: 1.2rem; letter-spacing: .02em; }
.brand-accent { color: var(--gold); }
.me { font-weight: bold; color: var(--gold); display: flex; align-items: center; gap: 7px; }
/* Same pixelated 2px-bordered head as the team/player rows, just sized for the top bar. */
.me-head {
  width: 20px;
  height: 20px;
  image-rendering: pixelated;
  border: 2px solid #0d0a06;
  flex: none;
}

.status-bar {
  max-width: 1950px;
  margin: 0 auto;
  padding: 0 24px;
  display: flex;
  justify-content: flex-end;
  align-items: stretch;
  gap: 16px;
  flex-wrap: wrap;
}

.status-bar-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  align-items: center;
  background: var(--panel);
  border-top: 2px solid var(--border-light);
  border-left: 2px solid var(--border-light);
  border-bottom: 2px solid var(--border-dark);
  border-right: 2px solid var(--border-dark);
  padding: 10px 18px;
}

.status-item { display: flex; align-items: center; gap: 8px; cursor: help; }
.status-label { font-size: .8rem; color: var(--text-dim); flex-shrink: 0; white-space: nowrap; }

/* XP-Bar-Look: dunkles Gehäuse, heller Fill mit Glanzstreifen, wie die EXP-Leiste in Minecraft. */
.xp-bar {
  width: 140px;
  height: 14px;
  background: var(--stone-dark);
  border: 2px solid var(--border-dark);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.4);
  overflow: hidden;
}
.xp-bar-fill {
  height: 100%;
  width: 0%;
  min-width: 2px;
  background: linear-gradient(to bottom, #b8ff3d 0%, #7ce619 45%, #5cb814 100%);
  transition: width .6s ease, background-color .6s ease;
}
.xp-bar-fill.warn { background: linear-gradient(to bottom, #ffd83d 0%, #e2a33c 45%, #a5730f 100%); }
.xp-bar-fill.danger { background: linear-gradient(to bottom, #ff7a5c 0%, var(--danger) 45%, var(--danger-dark) 100%); }

@media (max-width: 700px) {
  .xp-bar { width: 90px; }
}

.maintenance-btn {
  flex-shrink: 0;
  padding: 0 20px;
  font-size: .85rem;
  color: var(--text);
  text-shadow: 1px 1px 0 rgba(0,0,0,.6);
  cursor: pointer;
  /* Plain stone gray in its normal state - green read like a status ("everything fine") rather
     than like a button. Only the active state stays colored, see below. */
  background: var(--stone);
  border-top: 2px solid rgba(255,255,255,.35);
  border-left: 2px solid rgba(255,255,255,.35);
  border-bottom: 2px solid var(--border-dark);
  border-right: 2px solid var(--border-dark);
}
.maintenance-btn:hover { background: var(--stone-light); }
.maintenance-btn.active {
  background: color-mix(in srgb, var(--danger-dark) 75%, var(--stone-light));
}
.maintenance-btn.active:hover { background: color-mix(in srgb, var(--danger-dark) 50%, var(--stone-light)); }


.site-footer {
  padding: 24px;
  color: var(--text-dim);
  font-size: .8rem;
  text-shadow: none;
}

.footer-inner {
  max-width: 1700px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}

.footer-col { flex: 1; min-width: 180px; }
.footer-col-right { text-align: right; }
.footer-title { color: var(--gold); font-size: .85rem; margin-bottom: 6px; }
.footer-text { line-height: 1.6; }
.footer-text code { background: var(--panel-alt); padding: 1px 4px; }

.layout {
  display: grid;
  grid-template-columns: 340px 460px 1fr 360px;
  grid-template-rows: minmax(0, 1fr);
  gap: 20px;
  padding: 20px 24px;
  max-width: 1950px;
  width: 100%;
  margin: 0 auto;
  flex: 1;
  min-height: 0;
}

@media (max-width: 1400px) {
  .layout { grid-template-columns: 1fr 1fr; grid-template-rows: repeat(2, minmax(0, 1fr)); overflow-y: auto; }
  .team-panel, .team-chat-panel { grid-column: span 2; }
}

@media (max-width: 900px) {
  .layout { grid-template-columns: 1fr; grid-template-rows: none; overflow-y: auto; }
  .team-panel, .team-chat-panel { grid-column: span 1; }
}

.players-panel, .map-panel, .team-panel, .team-chat-panel {
  background: var(--panel);
  border-top: 2px solid var(--border-light);
  border-left: 2px solid var(--border-light);
  border-bottom: 2px solid var(--border-dark);
  border-right: 2px solid var(--border-dark);
  padding: 16px;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.team-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}

.team-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  background: color-mix(in srgb, var(--slot) 22%, var(--panel));
  border: 1px solid var(--border-dark);
}

.team-row { opacity: .5; }
.team-row.online { opacity: 1; }
.team-row img { width: 28px; height: 28px; image-rendering: pixelated; border: 1px solid var(--border-dark); filter: grayscale(1); }
.team-row.online img { filter: none; }
.team-row .team-name { flex: 1; font-size: .85rem; color: #AAAAAA; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.team-row .team-clock { font-size: .8rem; flex-shrink: 0; cursor: help; }

.team-chat-messages {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 10px;
  scrollbar-width: none; /* Firefox */
}
.team-chat-messages::-webkit-scrollbar {
  display: none; /* Chrome/Edge/Safari */
}

.team-chat-msg { display: flex; gap: 8px; align-items: flex-start; }
.team-chat-msg img { width: 24px; height: 24px; image-rendering: pixelated; border: 1px solid var(--border-dark); margin-top: 2px; }
.team-chat-msg .team-chat-body { flex: 1; font-size: .85rem; }
.team-chat-msg .team-chat-meta { color: var(--text-dim); font-size: .7rem; }
.team-chat-msg .team-chat-date { color: #555555; font-size: .7rem; margin-bottom: 2px; }
.team-chat-msg .team-chat-text {
  display: inline-block;
  color: var(--text);
  word-break: break-word;
  background: color-mix(in srgb, var(--slot) 20%, var(--panel));
  border: 1px solid var(--border-dark);
  border-radius: 4px;
  padding: 6px 10px;
  margin-top: 2px;
}
.team-chat-msg.own .team-chat-text {
  background: color-mix(in srgb, var(--accent-dark) 45%, var(--panel));
}

.team-chat-input-row { display: flex; gap: 8px; }
.team-chat-input-row input { flex: 1; min-width: 0; }
.team-chat-input-row button { flex-shrink: 0; font-size: 1.1rem; line-height: 1; padding: 6px 10px; }

.team-chat-msg.own { flex-direction: row-reverse; }
.team-chat-msg.own .team-chat-body { text-align: right; }
.team-chat-msg.own .team-chat-meta { flex-direction: row-reverse; }

h2 {
  margin: 0 0 12px 0;
  font-size: 1rem;
  color: var(--gold);
  text-transform: uppercase;
  letter-spacing: .05em;
  display: flex;
  align-items: center;
  gap: 8px;
}

h3 { color: var(--gold); font-size: .95rem; letter-spacing: .03em; margin: 16px 0 8px; }

.badge {
  background: var(--stone-dark);
  border: 1px solid var(--border-dark);
  padding: 2px 8px;
  font-size: .8rem;
  color: var(--text-dim);
}

.search-input {
  width: 100%;
  background: var(--stone-dark);
  color: var(--text);
  border: 2px solid var(--border-dark);
  padding: 8px 10px;
  margin-bottom: 10px;
}
.search-input:focus { outline: none; border-color: var(--accent); }

.player-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

.player-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  background: var(--slot);
  background: color-mix(in srgb, var(--slot) 22%, var(--panel));
  border-top: 1px solid rgba(255,255,255,.08);
  border-left: 1px solid rgba(255,255,255,.08);
  border-bottom: 1px solid rgba(0,0,0,.4);
  border-right: 1px solid rgba(0,0,0,.4);
  cursor: pointer;
}

.player-row:hover { background: color-mix(in srgb, var(--accent) 20%, var(--panel)); }

.player-row img {
  width: 32px;
  height: 32px;
  image-rendering: pixelated;
  border: 1px solid var(--border-dark);
}

.player-name { flex: 1; font-weight: normal; color: #AAAAAA; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.status-dot {
  width: 11px;
  height: 11px;
  margin-right: 10px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #777, #444 70%);
  border: 1px solid var(--border-dark);
  box-shadow: inset 0 0 2px rgba(0,0,0,.6);
  flex-shrink: 0;
}
.status-dot.online {
  background: radial-gradient(circle at 35% 30%, #7CFF8A, var(--ok) 70%);
  border-color: var(--ok-dark);
  box-shadow: 0 0 6px 1px rgba(63,185,80,.9), inset 0 0 2px rgba(0,0,0,.3);
}

.tag-banned {
  font-size: .7rem;
  background: var(--danger-dark);
  color: white;
  padding: 2px 6px;
  border: 1px solid var(--border-dark);
}
.tag-banned.tag-muted { background: var(--warn-dark); }
.tag-banned.tag-jailed { background: var(--accent-dark); }

.map-wrap { display: flex; justify-content: center; align-items: center; position: relative; flex: 1; min-height: 0; }
#island-map { max-width: 100%; max-height: 100%; width: auto; height: auto; }

.island-tooltip {
  position: absolute;
  pointer-events: none;
  background: var(--stone-dark);
  border-top: 2px solid var(--border-light);
  border-left: 2px solid var(--border-light);
  border-bottom: 2px solid var(--border-dark);
  border-right: 2px solid var(--border-dark);
  padding: 8px 10px;
  font-size: .8rem;
  color: var(--text-dim);
  white-space: nowrap;
  z-index: 10;
  box-shadow: 0 6px 18px rgba(0,0,0,.5);
  border-radius: 4px;
}
.island-tooltip.hidden { display: none; }
.hidden { display: none !important; }

.rank-row { display: flex; gap: 8px; margin-bottom: 10px; }
.rank-row select { margin-bottom: 0; flex: 1; height: 38px; }
.rank-save-btn { flex-shrink: 0; height: 38px; padding: 0 12px; font-size: .95rem; display: flex; align-items: center; }

.session-info { display: flex; align-items: center; gap: 10px; margin-right: 16px; }
#session-timer { font-size: .8rem; color: var(--text-dim); }
#session-timer.warn { color: var(--warn); }
#session-renew-btn:disabled { opacity: .4; cursor: not-allowed; }

.lenny-disabled {
  font-family: Arial, "Bahnschrift", sans-serif;
  text-align: center;
  padding: 14px;
  font-size: 1.3rem;
  color: var(--text-dim);
  border: 1px dashed var(--border-light);
  border-radius: 4px;
  cursor: not-allowed;
  user-select: none;
  opacity: .7;
}
.island-tooltip b { color: var(--text); font-weight: normal; text-shadow: 1px 1px 0 rgba(0,0,0,.5); }
#island-map {
  /* Der Holzrahmen wird direkt auf die Canvas gezeichnet (Minecraft-Kartenitem-Look) - hier nur
     ein Schlagschatten, damit die Karte auf dem dunklen Panel-Hintergrund "aufliegt". */
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(0,0,0,.45);
}

.modal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 50;
}
.modal.hidden { display: none; }

.modal-box {
  background: var(--panel);
  border-top: 2px solid var(--border-light);
  border-left: 2px solid var(--border-light);
  border-bottom: 2px solid var(--border-dark);
  border-right: 2px solid var(--border-dark);
  padding: 20px;
  width: min(520px, 92vw);
  max-height: 85vh;
  overflow-y: auto;
  position: relative;
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* alte Edge-Versionen */
}
.modal-box::-webkit-scrollbar { display: none; } /* Chrome/Safari/neues Edge */

/* The charts need considerably more room than a confirmation dialog. */
.modal-box-wide { width: min(1180px, 94vw); }

/* ---------------------------------------------------------------------------
   Server statistics charts (see renderCharts in app.js)
   --------------------------------------------------------------------------- */

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

.chart-card {
  background: var(--panel-alt);
  border-top: 2px solid var(--border-light);
  border-left: 2px solid var(--border-light);
  border-bottom: 2px solid var(--border-dark);
  border-right: 2px solid var(--border-dark);
  padding: 12px 14px 8px;
}

.chart-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 2px;
}
.chart-title { font-size: 13px; color: var(--text); }
/* The current value carries the reading, so it is the largest thing on the card. */
.chart-value { font-size: 20px; color: var(--text); }
.chart-value.warn { color: var(--warn); }
.chart-value.danger { color: var(--danger); }
.chart-hint { font-size: 10px; color: var(--text-dim); margin: 0 0 8px; }
.chart-range-note { font-size: 11px; color: var(--text-dim); margin: 0 0 14px; }

/* Scaled by width with the viewBox aspect kept - a stretched viewBox would thin out the
   stroke on one axis and make the 2px line specification a lie. */
.chart-plot { display: block; width: 100%; height: auto; touch-action: none; }
.chart-plot .grid-line { stroke: rgba(255,255,255,.07); stroke-width: 1; }
.chart-plot .axis-label { fill: var(--text-dim); font-size: 9px; }
.chart-plot .series-area { fill: rgba(88,163,255,.14); }
.chart-plot .series-line { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
/* A threshold is a rule, not data - dashed and recessive so it never reads as a second series. */
.chart-plot .threshold { stroke: var(--warn); stroke-width: 1; stroke-dasharray: 4 4; opacity: .55; }
.chart-plot .crosshair { stroke: var(--text-dim); stroke-width: 1; }
/* 2px surface ring, so the dot stays readable on top of the line. */
.chart-plot .cursor-dot { fill: var(--accent); stroke: var(--panel-alt); stroke-width: 2; }

/* Combined overview chart (see app.js -> renderOverviewCard).
   Spans the whole grid: eight series need the width, and it is the entry point to
   everything the single-metric cards below say in detail. */
.chart-card-wide { grid-column: 1 / -1; }

/* Categorical palette, dark steps - validated as a set against this panel's own card
   surface (#262626): every slot inside the L 0.48-0.67 band, >= 3:1 contrast, and every
   ADJACENT pair separated for protanopia/deuteranopia/tritanopia. Fixed order, never
   cycled: an entry past slot 8 does not get a generated hue, it stays out of the chart.
   The order itself is part of the validation - do not reshuffle these. */
.overview-plot .series-1, .overview-swatch.series-1 { --series: #3987e5; } /* blue */
.overview-plot .series-2, .overview-swatch.series-2 { --series: #d95926; } /* orange */
.overview-plot .series-3, .overview-swatch.series-3 { --series: #199e70; } /* aqua */
.overview-plot .series-4, .overview-swatch.series-4 { --series: #c98500; } /* yellow */
.overview-plot .series-5, .overview-swatch.series-5 { --series: #d55181; } /* magenta */
.overview-plot .series-6, .overview-swatch.series-6 { --series: #008300; } /* green */
.overview-plot .series-7, .overview-swatch.series-7 { --series: #9085e9; } /* violet */
.overview-plot .series-8, .overview-swatch.series-8 { --series: #e66767; } /* red */

.overview-line {
  fill: none;
  stroke: var(--series);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.overview-line.hidden { display: none; }

.overview-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-bottom: 8px;
}
/* Every entry is a real button - the legend doubles as the series filter. */
.overview-legend-item {
  display: flex;
  align-items: center;
  gap: 5px;
  background: none;
  border: none;
  padding: 2px 4px;
  cursor: pointer;
  font: inherit;
  font-size: 11px;
  color: var(--text);
}
.overview-legend-item:hover { background: var(--stone-light); }
/* A switched-off series stays legible - dimmed, not hidden, so it can be switched back on. */
.overview-legend-item.off { opacity: .4; text-decoration: line-through; }
.overview-legend-value { color: var(--text-dim); }
.overview-swatch {
  width: 10px;
  height: 10px;
  background: var(--series);
  flex: none;
}

.chart-tooltip {
  position: absolute;
  pointer-events: none;
  background: var(--stone-dark);
  border-top: 1px solid var(--border-light);
  border-left: 1px solid var(--border-light);
  border-bottom: 1px solid var(--border-dark);
  border-right: 1px solid var(--border-dark);
  padding: 4px 8px;
  font-size: 11px;
  color: var(--text);
  white-space: nowrap;
  z-index: 60;
}
.chart-tooltip.hidden { display: none; }

/* Tab row of the statistics modal (charts / calendar) - the active tab is the one filled in. */
.stats-tabs { margin-bottom: 10px; }
.stats-tab.active { background: var(--accent-dark); color: var(--text); }

/* Range filter: one row above the grid, since the range applies to every chart at once. */
.chart-range-row { flex-wrap: wrap; margin-bottom: 8px; }
.chart-range-btn.active {
  background: var(--accent-dark);
  color: var(--text);
}

/* ---------------------------------------------------------------------------
   Server calendar (see renderCalendar in app.js)
   --------------------------------------------------------------------------- */

.cal-nav { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.cal-month { font-size: 14px; }

.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.cal-weekday { font-size: 10px; color: var(--text-dim); text-align: center; padding-bottom: 2px; }

.cal-cell {
  position: relative;
  min-height: 104px;
  padding: 6px;
  text-align: left;
  background: var(--panel-alt);
  border-top: 2px solid var(--border-light);
  border-left: 2px solid var(--border-light);
  border-bottom: 2px solid var(--border-dark);
  border-right: 2px solid var(--border-dark);
  color: var(--text);
  font-family: inherit;
  cursor: pointer;
  overflow: hidden;
}
.cal-cell.cal-empty, .cal-cell.cal-nodata { cursor: default; opacity: .45; }
/* The month's best day is marked by a border, not by hue alone - the number is right there too. */
.cal-record { border-color: var(--gold); }

/* One fill per cell whose opacity encodes the peak - a sequential ramp in a single hue. */
.cal-fill {
  position: absolute;
  inset: 0;
  background: var(--accent);
  pointer-events: none;
}
.cal-day { position: relative; font-size: 10px; color: var(--text-dim); }
.cal-peak { position: relative; display: block; font-size: 22px; line-height: 1; margin: 2px 0 3px; }
.cal-sub { position: relative; display: block; font-size: 9px; color: var(--text-dim); }
.cal-nodata .cal-day { color: var(--text-dim); }

/* One color per metric, identical in the cell, the legend and the trend charts - that mapping is
   the only thing that makes eight numbers in one small tile readable. */
.cal-m-players { color: #7aa2ff; }
.cal-m-avg { color: #b3b3b3; }
.cal-m-tps { color: #3fb950; }
.cal-m-cpu { color: #e2a33c; }
.cal-m-ram { color: #c678dd; }
.cal-m-ent { color: #56b6c2; }
.cal-m-chunks { color: #ffd83d; }
.cal-m-new { color: #ff7ab6; }
/* The TPS value keeps its own judgement colors, which deliberately override the metric color. */
.cal-m-tps.cal-warn { color: var(--warn); }
.cal-m-tps.cal-bad { color: var(--danger); }

.cal-head { position: relative; display: flex; justify-content: space-between; align-items: center; }

/* Achievement badges: what was good about that day, at most two per cell. */
.cal-badges { position: relative; display: flex; flex-wrap: wrap; gap: 3px; margin-top: 5px; }
.cal-badge {
  font-size: 8px;
  line-height: 1.5;
  padding: 1px 4px;
  white-space: nowrap;
  background: rgba(0, 0, 0, .45);
  border-left: 2px solid currentColor;
}
.cal-badge-record { color: var(--gold); }
.cal-badge-busy { color: #7aa2ff; }
.cal-badge-growth { color: #ff7ab6; }
.cal-badge-smooth { color: var(--ok); }
.cal-badge-lag { color: var(--danger); }
.cal-badge-quiet { color: var(--text-dim); }

.cal-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-size: 9px;
  color: var(--text-dim);
  margin-bottom: 8px;
}
.cal-legend-item { display: inline-flex; align-items: center; gap: 4px; }
.cal-legend-dot { width: 8px; height: 8px; background: currentColor; display: inline-block; }

/* Month development: one small SVG per series, the same colors as the cells. */
.cal-trends { margin-top: 16px; }
.cal-trends-title { font-size: 11px; color: var(--text); margin-bottom: 6px; }
.cal-trends-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 8px;
}
.cal-chart-card {
  background: var(--panel-alt);
  border-top: 2px solid var(--border-light);
  border-left: 2px solid var(--border-light);
  border-bottom: 2px solid var(--border-dark);
  border-right: 2px solid var(--border-dark);
  padding: 6px 8px;
}
.cal-chart-head { display: flex; align-items: baseline; gap: 6px; font-size: 9px; color: var(--text-dim); }
.cal-chart-label { flex: 1; }
.cal-chart-value { font-size: 13px; }
.cal-chart-change { font-size: 9px; }
.cal-chart-svg { width: 100%; height: 52px; display: block; margin: 4px 0 2px; }
.cal-chart-foot { display: flex; justify-content: space-between; font-size: 8px; color: var(--text-dim); }

/* Weekend/today are structure, not data - a tint and a border, never a competing fill color. */
.cal-weekend { background: var(--stone-dark); }
.cal-today { outline: 1px dashed var(--text-dim); outline-offset: -4px; }

/* Corner markers of a cell: record star left of the top edge, growth badge on the right. */
.cal-star { position: absolute; top: 4px; right: 5px; font-size: 10px; color: var(--gold); }
.cal-new {
  position: absolute;
  bottom: 4px;
  right: 5px;
  font-size: 9px;
  color: var(--ok);
}
.cal-record .cal-new { right: 5px; }

/* The day's worst TPS is the one cell value that is judged, not just read. */
.cal-ok { color: var(--ok); }
.cal-warn { color: var(--warn); }
.cal-bad { color: var(--danger); }
.cal-health { font-size: 9px; }

/* Month tiles above the grid - the scale everything in the grid is compared against. */
.cal-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 6px;
  margin-bottom: 12px;
}
.cal-summary-tile {
  background: var(--panel-alt);
  border-top: 2px solid var(--border-light);
  border-left: 2px solid var(--border-light);
  border-bottom: 2px solid var(--border-dark);
  border-right: 2px solid var(--border-dark);
  padding: 6px 8px;
}
.cal-summary-value { display: block; font-size: 18px; line-height: 1.2; }
.cal-summary-label { display: block; font-size: 9px; color: var(--text-dim); }

.cal-detail { margin-top: 16px; font-size: 11px; color: var(--text-dim); }
.cal-detail-title { font-size: 13px; color: var(--text); margin-bottom: 8px; }

/* Headline figure of the picked day, then its numbers in one card per topic. */
.cal-detail-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 10px; }
.cal-detail-big { font-size: 26px; line-height: 1; color: var(--text); }
.cal-detail-big-label { font-size: 10px; color: var(--text-dim); }
.cal-detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px;
}
.cal-detail-card {
  background: var(--panel-alt);
  border-top: 2px solid var(--border-light);
  border-left: 2px solid var(--border-light);
  border-bottom: 2px solid var(--border-dark);
  border-right: 2px solid var(--border-dark);
  padding: 8px 10px;
}
.cal-detail-card-title { font-size: 11px; color: var(--text); margin-bottom: 4px; }
.cal-detail-card .chart-table td { border-bottom: 1px solid var(--border-dark); }
.cal-detail-card .chart-table tr:last-child td { border-bottom: none; }

.chart-table-wrap { max-height: 60vh; overflow: auto; }
.chart-table { width: 100%; border-collapse: collapse; font-size: 11px; }
.chart-table th, .chart-table td { padding: 4px 8px; text-align: right; border-bottom: 1px solid var(--stone); }
.chart-table th { color: var(--text-dim); text-align: right; position: sticky; top: 0; background: var(--panel); }
.chart-table th:first-child, .chart-table td:first-child { text-align: left; }

.modal-close {
  position: absolute;
  top: 8px;
  right: 10px;
  background: var(--danger-dark);
  border-top: 1px solid rgba(255,255,255,.3);
  border-left: 1px solid rgba(255,255,255,.3);
  border-bottom: 1px solid var(--border-dark);
  border-right: 1px solid var(--border-dark);
  color: white;
  width: 26px;
  height: 26px;
  line-height: 1;
  font-size: 1.1rem;
  cursor: pointer;
}
.modal-close:hover { background: var(--danger); }

.info-row { margin-bottom: 6px; color: var(--text-dim); text-shadow: none; }
.info-row b { color: var(--text); font-weight: normal; text-shadow: 1px 1px 0 rgba(0,0,0,.5); }

.warning-item {
  background: var(--stone-dark);
  border-left: 3px solid var(--warn);
  padding: 8px 10px;
  margin: 6px 0;
  font-size: .85rem;
  text-shadow: none;
}

.warning-item.revoked { opacity: .55; }

.revoked-note {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px dashed var(--border-light);
  color: var(--ok);
  font-size: .8rem;
}

.tag-expired {
  font-size: .7rem;
  background: var(--panel);
  color: var(--text-dim);
  border: 1px solid var(--border-light);
  padding: 1px 6px;
}

/* Vanilla-Button: heller Bevel oben/links, dunkler unten/rechts, dunkelt beim Hover leicht ab */
button {
  font-family: "Minecraft", monospace;
  cursor: pointer;
}

button.revoke-btn,
button.duration-btn,
button.action {
  background: var(--stone-light);
  border-top: 2px solid rgba(255,255,255,.35);
  border-left: 2px solid rgba(255,255,255,.35);
  border-bottom: 2px solid var(--border-dark);
  border-right: 2px solid var(--border-dark);
  color: var(--text);
  text-shadow: 1px 1px 0 rgba(0,0,0,.6);
  padding: 6px 12px;
  font-size: .85rem;
}
button.revoke-btn:hover,
button.duration-btn:hover,
button.action:not(:disabled):hover {
  background: color-mix(in srgb, var(--accent) 35%, var(--stone-light));
}
button.revoke-btn:active,
button.duration-btn:active,
button.action:not(:disabled):active {
  border-top-color: var(--border-dark);
  border-left-color: var(--border-dark);
  border-bottom-color: rgba(255,255,255,.35);
  border-right-color: rgba(255,255,255,.35);
}

button.duration-btn.selected { background: color-mix(in srgb, var(--accent) 55%, var(--stone-light)); }

textarea, select.preset-select {
  width: 100%;
  background: var(--stone-dark);
  color: var(--text);
  border: 2px solid var(--border-dark);
  padding: 8px;
  font-family: inherit;
  text-shadow: none;
}

textarea { min-height: 90px; resize: vertical; }
textarea[readonly] { resize: none; cursor: default; color: var(--text-dim); background: color-mix(in srgb, var(--stone-dark) 85%, black); }
select.preset-select { margin-bottom: 8px; cursor: pointer; }

.duration-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0; }

.char-counter { font-size: .8rem; color: var(--text-dim); margin: 4px 0 12px; text-shadow: none; }
.char-counter.ok { color: var(--ok); }

.action-row { display: flex; gap: 10px; margin-top: 8px; }

button.action:disabled { opacity: .4; cursor: not-allowed; }
button.warn-btn { background: color-mix(in srgb, var(--warn-dark) 75%, var(--stone-light)); }
button.ban-btn { background: color-mix(in srgb, var(--danger-dark) 75%, var(--stone-light)); }
button.visit-btn { background: color-mix(in srgb, var(--ok-dark) 75%, var(--stone-light)); }
button.spectate-btn { background: color-mix(in srgb, var(--accent-dark) 75%, var(--stone-light)); }
button.revoke-btn { background: color-mix(in srgb, var(--danger-dark) 55%, var(--stone-light)); }

/* Farbige Buttons sollen beim Hover heller in IHRER EIGENEN Farbe werden statt (wie der generische
   button.action-Hover oben) immer Richtung Blau (--accent) zu wandern. */
button.warn-btn:not(:disabled):hover { background: color-mix(in srgb, var(--warn-dark) 50%, var(--stone-light)); }
button.ban-btn:not(:disabled):hover { background: color-mix(in srgb, var(--danger-dark) 50%, var(--stone-light)); }
button.visit-btn:not(:disabled):hover { background: color-mix(in srgb, var(--ok-dark) 50%, var(--stone-light)); }
button.spectate-btn:not(:disabled):hover { background: color-mix(in srgb, var(--accent-dark) 50%, var(--stone-light)); }
button.revoke-btn:not(:disabled):hover { background: color-mix(in srgb, var(--danger-dark) 35%, var(--stone-light)); }

.error-text { color: var(--danger); font-size: .85rem; margin-top: 6px; text-shadow: none; }

/* ------------------------------------------------------------------------- */
/* Notizzettel - echter Post-it-Look (frei verschiebbar, siehe app.js)       */
/* ------------------------------------------------------------------------- */

.sticky-note {
  position: fixed;
  width: 240px;
  z-index: 40;
  padding: 22px 16px 14px;
  background: linear-gradient(135deg, #fff9b0 0%, #ffe873 55%, #ffdf5c 100%);
  box-shadow: 3px 8px 16px rgba(0,0,0,.45), 0 1px 0 rgba(255,255,255,.5) inset;
  transform: rotate(-2deg);
  font-family: "Segoe Print", "Bradley Hand", "Comic Sans MS", cursive;
  color: #4a3f1a;
  text-shadow: none;
}

/* Kleiner "Pin" oben mittig, damit es wie an eine Pinnwand geheftet aussieht. */
.sticky-note-pin {
  position: absolute;
  top: -9px;
  left: 50%;
  transform: translateX(-50%);
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #ff8a80, #b33a2e 75%);
  box-shadow: 0 2px 3px rgba(0,0,0,.5);
  cursor: grab;
}
.sticky-note-pin:active { cursor: grabbing; }

.sticky-note-header {
  display: flex;
  justify-content: flex-end;
  user-select: none;
  margin: -6px -6px 4px 0;
}

.sticky-note-icon-btn {
  flex-shrink: 0;
  background: transparent;
  border: none;
  color: #6b5c25;
  font-family: inherit;
  font-size: .8rem;
  line-height: 1;
  padding: 3px 6px;
  opacity: .75;
}
.sticky-note-icon-btn:hover { opacity: 1; }
.sticky-note-icon-btn.active { color: #7a3a1a; opacity: 1; font-weight: bold; }

.sticky-note-textarea {
  width: 100%;
  min-height: 130px;
  max-height: 320px;
  border: none;
  background: transparent;
  color: #4a3f1a;
  font-family: inherit;
  font-size: 1.05rem;
  line-height: 1.4;
  resize: vertical;
  padding: 0;
  scrollbar-width: none;
}
.sticky-note-textarea::-webkit-scrollbar { display: none; }
.sticky-note-textarea::placeholder { color: #8a7c40; }
.sticky-note-textarea:focus { outline: none; }

.sticky-note-audit {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px dashed #b3a04a;
  max-height: 220px;
  overflow-y: auto;
  scrollbar-width: none;
}
.sticky-note-audit::-webkit-scrollbar { display: none; }
.sticky-note-audit.hidden { display: none; }

.sticky-note-audit-title {
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: #6b5c25;
  margin-bottom: 6px;
  font-family: "Minecraft", "Segoe UI", monospace;
}

.sticky-note-audit-entry {
  font-size: .7rem;
  font-family: "Minecraft", "Segoe UI", monospace;
  margin-bottom: 8px;
  padding-bottom: 8px;
  border-bottom: 1px dashed #cabb6e;
}
.sticky-note-audit-entry:last-child { border-bottom: none; margin-bottom: 0; padding-bottom: 0; }

.sticky-note-audit-meta { margin-bottom: 2px; }
.sticky-note-audit-name { color: #5a4d1f; }
.sticky-note-audit-time { color: #8a7c40; margin-left: 4px; }

.sticky-note-audit-added, .sticky-note-audit-removed {
  word-break: break-word;
  white-space: pre-wrap;
  padding: 2px 4px;
  margin-top: 2px;
}
.sticky-note-audit-added { color: #1f6e2c; background: rgba(63,185,80,.18); }
.sticky-note-audit-removed { color: #7a1f1f; background: rgba(212,60,60,.18); }
.sticky-note-audit-removed-text { text-decoration: line-through; }

.sticky-note-audit-empty { color: #6b5c25; font-size: .7rem; font-family: "Minecraft", "Segoe UI", monospace; }

/* ---------------------------------------------------------------------------
   Player detail windows (see openPlayerModal in app.js)

   Several can be open at the same time and each is dragged by its title bar, so
   unlike the modals above these are positioned absolutely and do NOT dim the
   page behind them - the whole point is comparing players side by side while
   still being able to work with the list underneath.
   --------------------------------------------------------------------------- */

.player-window {
  position: fixed;
  z-index: 60;
  width: min(520px, 92vw);
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border-top: 2px solid var(--border-light);
  border-left: 2px solid var(--border-light);
  border-bottom: 2px solid var(--border-dark);
  border-right: 2px solid var(--border-dark);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .55);
}

.player-window-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  background: var(--panel-soft, rgba(255, 255, 255, .06));
  border-bottom: 2px solid var(--border-dark);
  cursor: grab;
  /* A drag must not select the title text on the way. */
  user-select: none;
}
.player-window-bar:active { cursor: grabbing; }
.player-window-title {
  flex: 1;
  font-size: 13px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.player-window-close {
  background: var(--danger-dark);
  border-top: 1px solid rgba(255, 255, 255, .3);
  border-left: 1px solid rgba(255, 255, 255, .3);
  border-bottom: 1px solid rgba(0, 0, 0, .4);
  border-right: 1px solid rgba(0, 0, 0, .4);
  color: #fff;
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
  padding: 3px 9px;
}
.player-window-content {
  padding: 16px 20px 20px;
  overflow-y: auto;
  scrollbar-width: none;
}
.player-window-content::-webkit-scrollbar { display: none; }

/* Marks the frozen player in the list and in the card header. */
.tag-frozen { background: #1f5fa8; }
