/* Server Logs panel.

   No external fonts or assets: the CSP allows 'self' only, and a panel that
   needs the internet to render is a panel that breaks on a LAN server. */

:root {
  --bg:        #0b0e13;
  --panel:     #12161d;
  --panel-2:   #171d26;
  --raised:    #1d2530;
  --line:      #222b37;
  --line-soft: #1a212b;
  --text:      #dfe5ef;
  --muted:     #7f8b9e;
  --accent:    #5b9bff;

  --debug:     #78859a;
  --info:      #5b9bff;
  --warn:      #e0a83c;
  --error:     #f0763c;
  --critical:  #f2545b;

  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;

  --radius: 10px;
  --shell: 1680px;
}

* { box-sizing: border-box; }

/* The browser's own [hidden] { display: none } comes from the user-agent
   stylesheet and loses to any class rule that sets display -- such as
   .login below. Without this, toggling el.hidden does nothing to those
   elements and the login overlay stays on top of the signed-in panel. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.55 var(--sans);
  -webkit-font-smoothing: antialiased;
}

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

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

::selection { background: rgba(91, 155, 255, .3); }

/* Wide monitors otherwise stretch a table of short messages into a band of
   empty space with the last column pinned to the far edge. */
#view-logs, #view-perf, #view-player { max-width: var(--shell); margin: 0 auto; }

.ghost {
  background: var(--raised);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 7px 13px;
  border-radius: 7px;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
  transition: background .12s ease, border-color .12s ease;
}
.ghost:hover { border-color: #34404f; background: #232d3a; }
.ghost:disabled { opacity: .35; cursor: default; }
.ghost:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ---------- login ---------- */

.login { min-height: 100vh; display: grid; place-items: center; padding: 24px; }

.login-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 36px 32px;
  width: 100%;
  max-width: 370px;
  text-align: center;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .45);
}

.login-card h1 { margin: 0 0 8px; font-size: 19px; letter-spacing: -.2px; }
.login-card p  { margin: 0 0 22px; font-size: 13px; }

.login-card code {
  font-family: var(--mono);
  background: var(--raised);
  padding: 2px 6px;
  border-radius: 5px;
  font-size: 12px;
}

#login-code {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 13px;
  font-family: var(--mono);
  font-size: 21px;
  letter-spacing: 5px;
  text-align: center;
  text-transform: uppercase;
  transition: border-color .12s ease;
}
#login-code:focus { outline: none; border-color: var(--accent); }

.remember {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 14px;
  color: var(--muted);
  font-size: 12.5px;
  cursor: pointer;
  user-select: none;
}
.remember:hover { color: var(--text); }

#login-submit {
  width: 100%;
  margin-top: 12px;
  padding: 12px;
  border: 0;
  border-radius: 9px;
  background: var(--accent);
  color: #06101f;
  font-weight: 650;
  cursor: pointer;
  transition: filter .12s ease;
}
#login-submit:hover { filter: brightness(1.08); }
#login-submit:disabled { opacity: .5; cursor: default; }

.login-error { margin: 16px 0 0; color: var(--critical); font-size: 13px; }

.or {
  position: relative;
  margin: 18px 0 14px;
  color: var(--muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .8px;
}
.or::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  border-top: 1px solid var(--line);
}
.or span { position: relative; background: var(--panel); padding: 0 10px; }

.discord-btn {
  display: block;
  padding: 11px;
  border-radius: 9px;
  background: #5865f2;
  color: #fff;
  font-weight: 600;
  text-decoration: none;
  transition: filter .12s ease;
}
.discord-btn:hover { filter: brightness(1.1); }

.role-tag {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: .7px;
  font-weight: 700;
  color: var(--warn);
  background: rgba(224, 168, 60, .14);
  border: 1px solid rgba(224, 168, 60, .35);
  padding: 3px 9px;
  border-radius: 5px;
}

.danger {
  background: transparent;
  border: 1px solid rgba(242, 84, 91, .45);
  color: var(--critical);
  padding: 4px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 12px;
  transition: background .12s ease;
}
.danger:hover { background: rgba(242, 84, 91, .14); }
.danger:disabled { opacity: .4; cursor: default; }

.you { color: var(--muted); font-size: 11px; }

/* ---------- chrome ---------- */

.topbar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 24px;
  height: 54px;
  background: rgba(18, 22, 29, .88);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 5;
}

.brand {
  font-weight: 650;
  letter-spacing: -.2px;
  display: flex;
  align-items: center;
  gap: 9px;
}

/* A small mark costs nothing and stops the header reading as placeholder. */
.brand::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--accent);
  box-shadow: 0 0 10px rgba(91, 155, 255, .8);
}

.crumb .brand::before { display: none; }

.spacer { flex: 1; }
.who { color: var(--muted); font-size: 13px; }

.toggle {
  display: flex;
  align-items: center;
  gap: 7px;
  color: var(--muted);
  font-size: 13px;
  cursor: pointer;
  user-select: none;
}
.toggle:hover { color: var(--text); }

.tabs { display: flex; gap: 2px; margin-left: 10px; }

.tab {
  background: transparent;
  border: 0;
  color: var(--muted);
  padding: 7px 13px;
  border-radius: 7px;
  cursor: pointer;
  font-weight: 500;
  transition: background .12s ease, color .12s ease;
}
.tab:hover { color: var(--text); background: var(--panel-2); }
.tab.is-active { color: var(--text); background: var(--raised); }

.chip {
  background: rgba(91, 155, 255, .13);
  border: 1px solid rgba(91, 155, 255, .5);
  color: var(--text);
  padding: 7px 12px;
  border-radius: 7px;
  cursor: pointer;
  font-family: var(--mono);
  font-size: 12px;
}
.chip:hover { background: rgba(91, 155, 255, .2); }
.chip::after { content: '  ✕'; color: var(--muted); }

.hint { font-size: 12px; align-self: center; }

/* ---------- stat tiles ---------- */

.summary { display: flex; flex-wrap: wrap; gap: 10px; padding: 20px 24px 0; }

.stat {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 12px 16px 11px;
  min-width: 116px;
  overflow: hidden;
}

/* The severity reads before the number does. */
.stat::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  background: var(--line);
}
.stat.sev-10::before { background: var(--debug); }
.stat.sev-20::before { background: var(--info); }
.stat.sev-30::before { background: var(--warn); }
.stat.sev-40::before { background: var(--error); }
.stat.sev-50::before { background: var(--critical); }

.stat .n {
  font-size: 22px;
  font-weight: 600;
  font-family: var(--mono);
  letter-spacing: -.5px;
  line-height: 1.2;
}
.stat .k {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: .7px;
  color: var(--muted);
  margin-top: 1px;
}

.stat.sev-10 .n { color: var(--debug); }
.stat.sev-20 .n { color: var(--info); }
.stat.sev-30 .n { color: var(--warn); }
.stat.sev-40 .n { color: var(--error); }
.stat.sev-50 .n { color: var(--critical); }

/* ---------- filters ---------- */

.filters { display: flex; flex-wrap: wrap; gap: 10px; padding: 18px 24px; }

.filters input[type=search], .filters select {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 8px 12px;
  transition: border-color .12s ease;
}
.filters input[type=search] { flex: 1; min-width: 240px; }
.filters input:focus, .filters select:focus { outline: none; border-color: var(--accent); }
.filters select { cursor: pointer; }

/* ---------- table ---------- */

.table-wrap {
  margin: 0 24px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  overflow-x: auto;      /* wide rows scroll here, never the page */
  background: var(--panel);
}

.logs { width: 100%; border-collapse: collapse; min-width: 900px; }

.logs th {
  text-align: left;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: .7px;
  color: var(--muted);
  font-weight: 600;
  padding: 11px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--panel-2);

  /* Sticky against .table-wrap, not the viewport: overflow-x on the wrapper
     makes overflow-y compute to auto, so the wrapper -- not the page -- is
     this header's scrollport. An offset here pushed the header down inside
     the wrapper and hid the newest row behind it. */
  position: sticky;
  top: 0;
}

.logs td {
  padding: 9px 14px;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}

.logs tbody tr { cursor: pointer; transition: background .1s ease; }
.logs tbody tr:hover { background: var(--panel-2); }
.logs tbody tr:last-child td { border-bottom: 0; }

/* A badge alone makes you read every row to find the one that matters.
   The accent stripe lets the eye find trouble while scrolling. Every row
   carries the transparent border so nothing shifts sideways. */
.logs td:first-child { border-left: 2px solid transparent; }

.logs tbody tr[data-sev="30"] td:first-child { border-left-color: var(--warn); }
.logs tbody tr[data-sev="40"] td:first-child { border-left-color: var(--error); }
.logs tbody tr[data-sev="50"] td:first-child { border-left-color: var(--critical); }

.logs tbody tr[data-sev="40"] { background: rgba(240, 118, 60, .045); }
.logs tbody tr[data-sev="50"] { background: rgba(242, 84, 91, .075); }

.c-time   { width: 108px; white-space: nowrap; }
.c-sev    { width: 92px; }
.c-cat    { width: 132px; }
.c-player { width: 196px; }
.c-res    { width: 148px; color: var(--muted); font-size: 12px; font-family: var(--mono); }
.c-msg    { word-break: break-word; }

/* Date under time: the day repeats for hundreds of rows, the clock does not. */
.tm { font-family: var(--mono); font-size: 12.5px; }
.dt { font-family: var(--mono); font-size: 10.5px; color: var(--muted); display: block; margin-top: 1px; }

.badge {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .5px;
  padding: 3px 8px;
  border-radius: 5px;
  white-space: nowrap;   /* 'read-only' must not break across two lines */
}
.badge.sev-10 { color: var(--debug);    background: rgba(120, 133, 154, .16); }
.badge.sev-20 { color: var(--info);     background: rgba(91, 155, 255, .15); }
.badge.sev-30 { color: var(--warn);     background: rgba(224, 168, 60, .16); }
.badge.sev-40 { color: var(--error);    background: rgba(240, 118, 60, .17); }
.badge.sev-50 { color: #fff;            background: var(--critical); }

.cid { font-family: var(--mono); font-size: 10.5px; color: var(--muted); display: block; margin-top: 1px; }

/* ---------- session table ---------- */

/* Seven columns of its own shape. Reusing the log table's widths left the
   message column swallowing the row and forced the whole thing to scroll. */
.sessions { min-width: 760px; }

.sessions tbody tr { cursor: default; }
.sessions tbody tr:hover { background: transparent; }

.s-time, .s-exp { width: 116px; white-space: nowrap; }
.s-name { width: 170px; }
.s-role { width: 112px; }
.s-via  { width: 92px; color: var(--muted); font-family: var(--mono); font-size: 12px; }
.s-act  { width: 74px; text-align: right; }

.s-id {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--muted);
  word-break: break-all;
}

/* Present for screen readers, absent for everyone else. */
.sr {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---------- expanded row ---------- */

.detail td { background: var(--bg); padding: 16px 18px; }

.detail pre {
  margin: 0;
  padding: 13px 15px;
  background: #080b10;
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.6;
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-word;
  color: #b9c4d4;
}

.kv {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px 24px;
  margin-bottom: 14px;
}
.kv b {
  display: block;
  color: var(--muted);
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .6px;
  margin-bottom: 2px;
}
.kv span { font-family: var(--mono); font-size: 12px; word-break: break-all; }

.empty { padding: 40px; text-align: center; color: var(--muted); }

/* ---------- player ---------- */

.crumb { display: flex; align-items: center; gap: 14px; padding: 20px 24px 0; }
.identity { padding: 18px 24px; }
.identity .kv { margin: 0; }

/* The name is the way into a player's history, so it has to look like it
   does something rather than being one more column of text. */
.player-link {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: rgba(91, 155, 255, .35);
  text-underline-offset: 3px;
}
.player-link:hover { text-decoration-color: var(--accent); }

/* ---------- charts ---------- */

.charts { display: grid; gap: 14px; margin: 0 24px; }

.chart {
  background: var(--panel);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 15px 18px 8px;
}

.chart h3 {
  margin: 0 0 1px;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: .7px;
  color: var(--muted);
  font-weight: 600;
}

.chart .peak { font-family: var(--mono); font-size: 12px; color: var(--text); margin-bottom: 4px; }
.chart svg { display: block; width: 100%; height: 150px; cursor: crosshair; }

.chart .grid  { stroke: var(--line-soft); stroke-width: 1; }
.chart .limit { stroke: var(--critical); stroke-width: 1; stroke-dasharray: 4 4; opacity: .65; }
.chart .axis  { fill: var(--muted); font-size: 10px; font-family: var(--mono); }
.chart .hover { stroke: var(--muted); stroke-width: 1; }

.note {
  margin: 20px 24px 36px;
  padding: 13px 16px;
  background: var(--panel);
  border-left: 2px solid var(--line);
  border-radius: 0 8px 8px 0;
  color: var(--muted);
  font-size: 12.5px;
  max-width: 78ch;
}

.tip {
  position: fixed;
  pointer-events: none;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 7px 10px;
  font-family: var(--mono);
  font-size: 11px;
  white-space: pre;
  z-index: 20;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .5);
}

/* ---------- pager ---------- */

.pager { display: flex; align-items: center; justify-content: center; gap: 18px; padding: 22px 24px 40px; }

@media (max-width: 700px) {
  .topbar { padding: 0 14px; gap: 10px; }
  .who { display: none; }
  .summary, .filters, .crumb, .identity { padding-left: 14px; padding-right: 14px; }
  .table-wrap, .charts { margin: 0 14px; }
  .note { margin-left: 14px; margin-right: 14px; }
}
