/* Panel. Sin framework: es un archivo que se puede editar con nano por SSH. */

:root {
  --bg: #14161a;
  --bg-soft: #1b1e24;
  --bg-hover: #23272f;
  --line: #2b3038;
  --fg: #dfe3ea;
  --fg-dim: #8b93a1;
  --accent: #6ea8fe;
  --ok: #57c98a;
  --warn: #e3b341;
  --err: #f07178;
  --purple: #b48ead;
  --radius: 8px;
  --mono: ui-monospace, "Cascadia Mono", "JetBrains Mono", Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #f6f7f9;
    --bg-soft: #ffffff;
    --bg-hover: #eceff3;
    --line: #dce0e6;
    --fg: #1c2027;
    --fg-dim: #666e7b;
    --accent: #2563eb;
    --ok: #1a7f4b;
    --warn: #9a6b00;
    --err: #c0392b;
    --purple: #7e57c2;
  }
}

* { box-sizing: border-box; }

/* El navegador trae [hidden] { display: none }, pero cualquier regla de autor
   que defina display la pisa. Como .login, .app, .empty y .modal son grid, sin
   esto el atributo hidden de esos cuatro no hace absolutamente nada. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 14px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-text-size-adjust: 100%;
}

.muted { color: var(--fg-dim); }
.error { color: var(--err); }

button {
  font: inherit;
  font-weight: 500;
  color: var(--fg);
  background: var(--bg-hover);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 7px 14px;
  cursor: pointer;
  transition: border-color .12s, background .12s, color .12s;
}
button:hover:not(:disabled) { border-color: var(--accent); background: var(--bg-soft); }
button:active:not(:disabled) { transform: translateY(1px); }
button:disabled { opacity: .45; cursor: not-allowed; }
button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
button.danger:hover:not(:disabled) { border-color: var(--err); color: var(--err); }
button.link {
  background: none;
  border: none;
  color: var(--fg-dim);
  padding: 4px 6px;
  text-decoration: underline;
}
button.link:hover { color: var(--fg); }

input[type="password"], input[type="text"] {
  font: inherit;
  width: 100%;
  padding: 9px 12px;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

/* ------------------------------------------------------------------ login */

.login {
  display: grid;
  place-items: center;
  min-height: 100dvh;
  padding: 20px;
}
.login-card {
  width: min(340px, 100%);
  display: grid;
  gap: 12px;
  padding: 24px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: 12px;
}
.login-card h1 { margin: 0; font-size: 20px; }
.login-card p { margin: -8px 0 4px; font-size: 13px; }

/* -------------------------------------------------------------------- app */

.app {
  display: grid;
  grid-template-columns: 64px 1fr 260px;
  grid-template-rows: 52px 1fr;
  height: 100dvh;
}

/* ------------------------------------------------------------------ topbar */

.topbar {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 16px;
  background: var(--bg-soft);
  border-bottom: 1px solid var(--line);
}
.topbar-brand { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: 13.5px; }
.topbar-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex: none; }
.topbar-host { display: flex; align-items: center; gap: 10px; color: var(--fg-dim); font-size: 12px; flex-wrap: wrap; }
.topbar-spacer { flex: 1; }
.topbar-clock { font-size: 12px; color: var(--fg-dim); }

/* ------------------------------------------------------------------ navrail */

.navrail {
  grid-row: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 0;
  background: var(--bg-soft);
  border-right: 1px solid var(--line);
  overflow-y: auto;
}
.nav-btn {
  width: 50px;
  padding: 8px 2px 7px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  background: none;
  border: none;
  border-radius: 9px;
  color: var(--fg-dim);
  cursor: pointer;
}
.nav-btn .nav-ic { width: 19px; height: 19px; }
.nav-btn span:last-child { font-size: 9px; letter-spacing: .01em; text-align: center; line-height: 1.15; }
.nav-btn:hover { background: var(--bg-hover); color: var(--fg); }
.nav-btn[aria-current="true"] { background: var(--bg-hover); color: var(--accent); box-shadow: inset 2px 0 0 var(--accent); }

/* ------------------------------------------------------------- vistas nuevas */

.nav-view {
  overflow-y: auto;
  min-height: 0;
  padding-bottom: 24px;
}
#nav-logs {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  padding-bottom: 0;
}
#nav-logs .log { flex: 1 1 auto; min-height: 120px; }

.pending-view {
  margin: 22px;
  padding: 20px;
  border: 1px dashed var(--line);
  border-radius: 10px;
  color: var(--fg-dim);
  font-size: 13px;
}
.pending-view code {
  font-family: var(--mono);
  font-size: 12px;
  background: var(--bg-hover);
  padding: 1px 5px;
  border-radius: 4px;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  background: var(--bg-hover);
  color: var(--fg-dim);
}
.chip.ok { background: color-mix(in srgb, var(--estado-ok) 18%, transparent); color: var(--estado-ok); }
.chip.critico { background: color-mix(in srgb, var(--estado-critico) 18%, transparent); color: var(--estado-critico); }

.uptime-table { display: grid; gap: 6px; margin-top: 10px; font-size: 12px; }
.uptime-row {
  display: grid;
  grid-template-columns: minmax(80px, 26%) repeat(3, 1fr);
  gap: 8px;
  align-items: center;
}
.uptime-row .un { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--fg-dim); }
.uptime-row .uv { text-align: right; font-variant-numeric: tabular-nums; }
.uptime-head { color: var(--fg-dim); font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; }
.uptime-head .uv { text-align: right; }

.sidebar {
  grid-column: 3;
  grid-row: 2;
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-height: 0;
  background: var(--bg-soft);
  border-left: 1px solid var(--line);
}

.overview-btn {
  margin: 8px 8px 0;
  padding: 9px 12px;
  text-align: left;
  background: none;
  border-color: transparent;
}
.overview-btn[aria-selected="true"] {
  background: var(--bg-hover);
  box-shadow: inset 2px 0 0 var(--accent);
  color: var(--accent);
}
.sidebar-head, .sidebar-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
}
.sidebar-foot {
  border-bottom: none;
  border-top: 1px solid var(--line);
  font-size: 12px;
}
.sidebar-foot .link { margin-left: auto; }

.badge {
  margin-left: auto;
  padding: 1px 8px;
  font-size: 12px;
  color: var(--fg-dim);
  background: var(--bg-hover);
  border-radius: 999px;
}

.proc-list {
  margin: 0;
  padding: 6px;
  list-style: none;
  overflow-y: auto;
  min-height: 0;
}
.proc-list li {
  display: grid;
  grid-template-columns: 8px 1fr auto;
  align-items: center;
  gap: 9px;
  padding: 9px 10px;
  border-radius: var(--radius);
  cursor: pointer;
}
.proc-list li:hover { background: var(--bg-hover); }
.proc-list li[aria-selected="true"] {
  background: var(--bg-hover);
  box-shadow: inset 2px 0 0 var(--accent);
}
/* Arrastre para reordenar. */
.proc-list li.arrastrando { opacity: .4; }
.proc-list li.destino { box-shadow: inset 0 2px 0 var(--accent); }
/* Los cuatro renglones de una instancia. Ninguno envuelve: si el texto no
   entra se recorta con puntos suspensivos, para que todas las filas de la lista
   midan exactamente lo mismo. */
.proc-name,
.proc-real,
.proc-estado,
.proc-meta {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.proc-name { font-weight: 500; }
.proc-real { font-size: 10px; color: var(--fg-dim); }
.proc-estado { font-size: 11px; color: var(--fg); }

.titulo { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; }
.titulo p { width: 100%; margin: 2px 0 0; font-size: 13px; }


#rename-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px;
  width: 100%;
  margin-top: 8px;
}
#rename-form label { display: grid; gap: 3px; }
#rename-form label span {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--fg-dim);
}
#rename-form input { padding: 6px 10px; font-size: 14px; }
#rename-input { width: 200px; }
.form-actions { display: flex; gap: 6px; }
#rename-form button { padding: 6px 12px; font-size: 13px; }
.proc-meta { font-size: 11px; color: var(--fg-dim); font-variant-numeric: tabular-nums; }
.proc-tag {
  font-size: 10px;
  padding: 0 5px;
  color: var(--accent);
  border: 1px solid var(--line);
  border-radius: 4px;
}

/* Marca "vuelve sola tras un reinicio". Se distingue de la etiqueta mc por
   color: son dos cosas distintas y aparecen pegadas. */
.proc-tag-boot {
  color: var(--ok, #4ade80);
  font-size: 11px;
  line-height: 1;
  padding: 1px 4px;
}

.dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--fg-dim);
  flex: none;
}
/* Verde: corriendo y funcionando. En mcchat eso significa DENTRO del servidor,
   no solo que el proceso viva. */
.dot.online { background: var(--ok); }

/* Rojo: apagada. */
.dot.stopped { background: var(--err); }

/* Morado: falló. Se distingue del rojo a proposito — "la pare yo" y "se rompio"
   piden cosas distintas de quien mira. */
.dot.errored { background: var(--purple); }

/* Naranja: el proceso corre pero todavia no hace lo suyo. En mcchat es el caso
   de no haber entrado al servidor: reconectando, o sin hacer /login. */
.dot.esperando { background: var(--warn); }
.dot.launching { background: var(--warn); }

/* Existe en el config de mcchat pero pm2 todavia no la registro. Hueco y no
   relleno: no es un proceso apagado, es un proceso que aun no existe. */
.dot.sin-registrar {
  background: transparent;
  border: 1px solid var(--err);
}

/* ------------------------------------------------------------------- main */

/* El scroll lo hace el log, no la pagina: si scrolleara .main, la barra de
   herramientas se iria de pantalla justo cuando la necesitas. */
.main { grid-column: 2; grid-row: 2; display: grid; min-height: 0; overflow: hidden; }

.empty { display: grid; place-items: center; height: 100%; color: var(--fg-dim); }

.detail-head {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  padding: 18px 22px;
  border-bottom: 1px solid var(--line);
}
.detail-head h2 { margin: 0; font-size: 18px; }
.detail-head p { margin: 2px 0 0; font-size: 13px; }
.actions { display: flex; gap: 6px; margin-left: auto; flex-wrap: wrap; align-items: center; }

/* Acciones como iconos. El rotulo vive en title (tooltip al pasar el mouse) y
   en aria-label, porque un simbolo suelto no le dice nada a un lector de
   pantalla ni a quien no conoce la convencion. */
.icon-btn {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  padding: 0;
  font-size: 15px;
  line-height: 1;
}
.icon-btn.danger:not(:disabled):hover { color: var(--err); border-color: var(--err); }
.icon-btn[aria-expanded="true"], .icon-btn.activo {
  color: var(--accent);
  border-color: var(--accent);
}
/* La tuerca y el expulsar van despues de un respiro: no son del mismo grupo
   que arrancar/parar. */
#mc-link { margin-left: 6px; }

/* Cada par etiqueta/valor va en su propio bloque. Antes dt y dd eran items
   sueltos del mismo grid, asi que se repartian por columnas y el valor de una
   estadistica terminaba debajo de la etiqueta de otra.

   Todo en una sola fila: si no entra, scrollea el contenedor y no la pagina. */
.stats {
  display: flex;
  gap: 20px;
  margin: 0;
  padding: 16px 22px;
  overflow-x: auto;
  scrollbar-width: thin;
}
/* Reparten el ancho disponible en proporcion a su contenido, pero nunca se
   encogen por debajo de el: cuando ya no entran, scrollea el contenedor en vez
   de recortar los valores. */
.stats > div {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 auto;
  min-width: max-content;
}
.stats dt {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--fg-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.stats dd {
  margin: 0;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.stats dd.mono { font-family: var(--mono); font-size: 12px; }

/* ---------------------------------------------------------------- resumen */

/* Dos tonos categoricos, validados contra las superficies reales del panel con
   scripts/validate_palette.js: pasan banda de luminosidad, croma, separacion
   para daltonismo y contraste, en los dos modos.

   No son decoracion: el tono codifica QUE magnitud se esta mirando. Azul es
   siempre CPU, naranja es siempre RAM, en el grafico, en las barras y en el
   medidor. Por eso son dos y no ocho: no hay una tercera magnitud que nombrar.

   Los de estado van aparte y no se reutilizan como serie. Un color de estado
   siempre viene con texto ("alto", "critico", "descargando"): el color solo no
   alcanza para avisar nada. */
:root {
  --serie: #3987e5;
  --serie-suave: rgba(57, 135, 229, .16);
  --serie-b: #d95926;
  --serie-b-suave: rgba(217, 89, 38, .16);
  --grid: #2c2c2a;
  --axis: #898781;
  --estado-alerta: #fab219;
  --estado-critico: #d03b3b;
  --estado-ok: #0ca30c;
}
@media (prefers-color-scheme: light) {
  :root {
    --serie: #2a78d6;
    --serie-suave: rgba(42, 120, 214, .14);
    --serie-b: #eb6834;
    --serie-b-suave: rgba(235, 104, 52, .14);
    --grid: #e1e0d9;
    --axis: #6b6a66;
  }
}

.overview { overflow-y: auto; min-height: 0; padding-bottom: 24px; }

.kpis {
  display: grid;
  /* 165 y no 150: "3,0 GB / 5,4 GB" a 26px no entra en 150 y parte el valor en
     dos lineas. Si igual no entra, parte por el espacio del medio y no recorta
     nada, que es lo unico inaceptable. */
  grid-template-columns: repeat(auto-fit, minmax(165px, 1fr));
  gap: 12px;
  padding: 18px 22px 4px;
}
.kpi {
  padding: 14px 16px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: 10px;
}
.kpi-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--fg-dim);
}
/* Figuras proporcionales, no tabulares: a 26px los digitos de ancho fijo hacen
   que un "121" se vea suelto. Las tabulares quedan para lo que se alinea en
   columna (ejes, filas de tabla). */
.kpi-value { margin-top: 4px; font-size: 26px; line-height: 1.15; }
.kpi-sub { margin-top: 2px; font-size: 12px; color: var(--fg-dim); }

/* El punto de estado nunca viaja solo: el texto del sub dice lo mismo
   ("descargando", "85 °C"). Sirve para encontrar el problema de un vistazo
   entre siete tarjetas, no para ser la unica fuente del dato. */
.kpi-sub .punto {
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 5px;
  border-radius: 50%;
  vertical-align: baseline;
  background: var(--fg-dim);
}
.kpi-sub .punto.ok { background: var(--estado-ok); }
.kpi-sub .punto.alerta { background: var(--estado-alerta); }
.kpi-sub .punto.critico { background: var(--estado-critico); }

.charts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 12px;
  padding: 12px 22px 0;
}
.card {
  margin: 0;
  padding: 14px 16px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: 10px;
}
.card figcaption {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-size: 13px;
  color: var(--fg-dim);
}
.card figcaption strong {
  font-size: 18px;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
}
.card figcaption.sub { margin-top: 16px; font-size: 12px; }

.chart-box { position: relative; margin-top: 8px; }
.chart { display: block; width: 100%; }
.chart .grid { stroke: var(--grid); stroke-width: 1; }
.chart .axis { fill: var(--axis); font-size: 10px; font-variant-numeric: tabular-nums; }
.chart .area { fill: var(--serie-suave); stroke: none; }
/* Linea de 2px y marca de punta: sin un numero en cada punto. */
.chart .line { fill: none; stroke: var(--serie); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart .punta { fill: var(--serie); stroke: var(--bg-soft); stroke-width: 2; }

/* Tono B (naranja) = RAM. El mismo tono lo usa el medidor de RAM del celular:
   la magnitud se reconoce por color aunque cambie la forma del grafico. */
.chart.tono-b .area { fill: var(--serie-b-suave); }
.chart.tono-b .line { stroke: var(--serie-b); }
.chart.tono-b .punta { fill: var(--serie-b); }
.chart .cursor { stroke: var(--axis); stroke-width: 1; stroke-dasharray: 3 3; }

.chart-tip {
  position: absolute;
  padding: 3px 8px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  background: var(--bg-hover);
  border: 1px solid var(--line);
  border-radius: 6px;
  pointer-events: none;
  white-space: nowrap;
}
.chart-foot {
  display: flex;
  justify-content: space-between;
  margin-top: 2px;
  font-size: 11px;
  color: var(--fg-dim);
}

.bars { display: grid; gap: 8px; margin-top: 10px; }
.bar-row {
  display: grid;
  grid-template-columns: minmax(70px, 26%) 1fr auto;
  align-items: center;
  gap: 10px;
  font-size: 12px;
}
.bar-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { height: 10px; background: var(--bg-hover); border-radius: 5px; }
/* Punta redondeada de 4px anclada a la base, como manda la guia de marcas. */
.bar-fill { height: 100%; background: var(--serie); border-radius: 0 4px 4px 0; }
.bar-fill.tono-b { background: var(--serie-b); }
/* Instancia parada: la barra se apaga, pero lo que lo dice es la nota de al
   lado. El color acompaña, no informa solo. */
.bar-fill.apagado { background: var(--line); }
.bar-value { color: var(--fg-dim); font-variant-numeric: tabular-nums; }
.bar-value.muted { font-variant-numeric: normal; font-size: 12px; opacity: .75; }

.meter + .meter { margin-top: 14px; }
.meter { margin-top: 10px; }
.meter-label { font-size: 12px; color: var(--fg-dim); margin-bottom: 5px; }
.meter-track { height: 14px; background: var(--bg-hover); border-radius: 7px; overflow: hidden; }
.meter-fill { height: 100%; background: var(--serie); border-radius: 0 4px 4px 0; }
.meter-fill.tono-b { background: var(--serie-b); }
.meter-fill.alerta { background: var(--estado-alerta); }
.meter-fill.critico { background: var(--estado-critico); }
.meter-legend { margin-top: 6px; font-size: 12px; color: var(--fg-dim); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------- configuracion de mcchat */

.mcconf { border-top: 1px solid var(--line); }

#mcconf-form {
  padding: 4px 22px 18px;
  border-top: 1px solid var(--line);
  background: var(--bg-soft);
  /* Son 29 campos: abierto de par en par no dejaria ver ni una linea del log.
     Scrollea el formulario, no el panel entero. */
  max-height: 55dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.mcconf-group { margin-top: 14px; }
.mcconf-group > h4 {
  margin: 0 0 8px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--fg-dim);
  font-weight: 600;
}
/* Formulario clave-valor: cada campo es una fila "etiqueta | valor", y esas
   filas se acomodan en columnas segun el ancho. La grilla de columnas
   automaticas que habia antes desparramaba los campos y dejaba la etiqueta
   lejos de su valor. */
.mcconf-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px 28px;
}

/* Cada columna nueva entra recien cuando hay ancho para que el valor no se
   parta en dos lineas. */
@media (min-width: 900px)  { .mcconf-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1300px) { .mcconf-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1650px) { .mcconf-grid { grid-template-columns: repeat(4, 1fr); } }

/* La columna de la clave mide lo mismo en TODOS los campos, en px y no en
   porcentaje. Con minmax(90px, 44%) cada celda resolvia su propio ancho segun
   el largo de la etiqueta, y por eso los inputs de columnas distintas
   arrancaban en posiciones distintas y el formulario se veia desparejo. */
.mcconf-field {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  align-items: center;
  column-gap: 12px;
  min-width: 0;
  /* Alto minimo igual para todos: una fila con un checkbox y otra con un input
     tienen que medir lo mismo o la grilla queda escalonada. */
  min-height: 44px;
  padding: 3px 0;
  border-bottom: 1px solid var(--line);
}
.mcconf-field > label {
  font-size: 12px;
  color: var(--fg-dim);
  /* Sin esto, una etiqueta larga empuja la columna del valor y las filas dejan
     de estar alineadas entre si. */
  overflow-wrap: anywhere;
}

/* La ayuda del campo vive en el title de la etiqueta. El subrayado punteado es
   lo que avisa que ahi hay algo que leer: un tooltip sin señal no lo encuentra
   nadie. */
.mcconf-field > label.con-pista {
  cursor: help;
  text-decoration: underline dotted var(--fg-dim);
  text-underline-offset: 3px;
}
.mcconf-field > label.con-pista:hover { color: var(--fg); }
.mcconf-field input[type="text"],
.mcconf-field input[type="password"],
.mcconf-field input[type="number"],
.mcconf-field select,
.mcconf-field textarea {
  font: inherit;
  width: 100%;
  padding: 6px 10px;
  font-size: 13px;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.mcconf-field input[type="text"],
.mcconf-field input[type="password"],
.mcconf-field input[type="number"],
.mcconf-field select {
  height: 32px;
}
.mcconf-field textarea { min-height: 62px; resize: vertical; font-family: var(--mono); font-size: 12px; }
.mcconf-field input:disabled { opacity: .5; }

/* La pista va debajo del valor, nunca debajo de la etiqueta: si arrancara en la
   primera columna cortaria la lectura de arriba abajo de los valores. */
/* Las listas ocupan el ancho completo: un textarea de varias lineas al lado de
   una fila de una sola desalinea todo lo que viene despues. */
.mcconf-field.lines {
  grid-column: 1 / -1;
  grid-template-columns: minmax(120px, 14%) 1fr;
  align-items: start;
}
.mcconf-field.lines > label { padding-top: 6px; }
.mcconf-field.lines .mcconf-valor { align-items: stretch; }

/* Los booleanos siguen la misma estructura que el resto: etiqueta a la
   izquierda, valor a la derecha. Antes tenian el checkbox primero y rompian la
   grilla de dos columnas. */
.mcconf-field.bool input[type="checkbox"] {
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Borrado de un secreto guardado.

   Antes era una casilla en su propia linea debajo del input, y eso agrandaba la
   fila entera: en una grilla, un campo mas alto estira a todos los de su fila.
   Ahora va al lado del input, dentro de la misma celda. */
.mcconf-valor { display: flex; align-items: center; gap: 6px; min-width: 0; }
.mcconf-valor input { min-width: 0; }

.mcconf-clear {
  flex: none;
  width: 26px;
  height: 26px;
  padding: 0;
  display: grid;
  place-items: center;
  font-size: 14px;
  line-height: 1;
  color: var(--fg-dim);
}
.mcconf-clear:hover { color: var(--err); border-color: var(--err); }
.mcconf-clear[aria-pressed="true"] {
  color: var(--err);
  border-color: var(--err);
  background: var(--bg);
}

.mcconf-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
#mcconf-msg { font-size: 12px; }
#mcconf-msg.ok { color: var(--ok); }
#mcconf-msg.err { color: var(--err); }

/* -------------------------------------------------------------------- logs */

/* OJO: esto era una grilla con ocho filas asignadas POR POSICION
   (auto auto auto auto auto auto 1fr auto). Cuatro de los ocho hijos son
   `hidden`, y un elemento en display:none deja de ser item de la grilla: los
   demas se corrian de fila y el mapeo dejaba de valer. Con la configuracion
   abierta el contenido no entraba en el height:100%, las filas `auto` se
   comprimian y las estadisticas terminaban dibujadas encima del titulo.

   En columna flex no hay posiciones que mantener: cada hijo ocupa lo que
   necesita, los ocultos simplemente no estan, y el log se queda con el resto. */
.detail {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}

/* Lo que no es el log conserva su tamano natural. Sin esto, flex reparte y les
   recorta altura hasta hacerlas ilegibles. */
.detail > * { flex: 0 0 auto; }

.detail > .log {
  /* El log se lleva lo que sobra y scrollea el, no la pagina. El min-height es
     imprescindible: sin el, un hijo flex no baja de su contenido y el log
     empuja al chat fuera de la pantalla. */
  flex: 1 1 auto;
  min-height: 120px;
}

/* ------------------------------------------------------------------- chat */

.chat-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 22px;
  background: var(--bg-soft);
  border-top: 1px solid var(--line);
}
/* Separado del grupo Inventario/Mando: no es una herramienta del bot, cambia
   si la sesion esta dentro del servidor o no. */
#mc-link { margin-left: 6px; white-space: nowrap; }

.chat-bar input {
  flex: 1;
  min-width: 0;
  padding: 8px 12px;
  font-size: 13px;
}
.chat-bar button { flex: none; }

/* Punto de estado: siempre acompañado del title, nunca color solo. */
.chat-state {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--fg-dim);
}
.chat-state.online { background: var(--ok); }
.chat-state.reconnecting { background: var(--warn); }
.chat-state.off { background: var(--err); }

.logbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 10px 22px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--bg-soft);
}
.logbar input[type="search"] {
  flex: 1;
  min-width: 120px;
  max-width: 260px;
  padding: 5px 10px;
  font-size: 13px;
}
.logbar button { padding: 5px 10px; font-size: 13px; }
.logbar button.active { border-color: var(--accent); color: var(--accent); }
#log-status { font-size: 12px; margin-left: auto; font-variant-numeric: tabular-nums; }

.tabs { display: flex; gap: 4px; }
.tab {
  padding: 5px 12px;
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
  background: none;
}
.tab[aria-selected="true"] {
  background: var(--bg-hover);
  border-color: var(--accent);
  color: var(--accent);
}

.file-select {
  font: inherit;
  font-size: 13px;
  max-width: 190px;
  padding: 5px 8px;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

/* ------------------------------------------------------------- buscador */

.search-panel {
  display: grid;
  gap: 8px;
  padding: 12px 22px;
  background: var(--bg-soft);
  border-bottom: 1px solid var(--line);
  max-height: 42dvh;
  overflow: auto;
}
#search-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}
#search-form input[type="search"] {
  flex: 1;
  min-width: 160px;
  padding: 6px 10px;
  font-size: 13px;
}
#search-form label {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--fg-dim);
}
#search-info { margin: 0; font-size: 12px; }

.results {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 2px;
}
.results li {
  display: grid;
  grid-template-columns: auto auto 1fr;
  gap: 10px;
  align-items: baseline;
  padding: 4px 8px;
  border-radius: var(--radius);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 12px;
}
.results li:hover { background: var(--bg-hover); }
.results li[aria-disabled="true"] { cursor: default; opacity: .8; }
.results .r-file { color: var(--accent); white-space: nowrap; }
.results .r-ts { color: var(--fg-dim); white-space: nowrap; }
.results .r-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 8px 22px;
  font-size: 13px;
  color: var(--warn);
  background: color-mix(in srgb, var(--warn) 10%, var(--bg-soft));
  border-bottom: 1px solid var(--line);
}
.banner .link { color: var(--fg); margin-left: auto; }

.cargando {
  padding: 8px 22px;
  font-size: 12px;
  color: var(--fg-dim);
  text-align: center;
}

.log {
  overflow: auto;
  min-height: 0;
  padding: 10px 0;
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.55;
  background: var(--bg);
}
.log:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.line {
  display: flex;
  gap: 10px;
  padding: 0 22px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.line:hover { background: var(--bg-soft); }
/* La linea a la que saltó una busqueda. */
.line.hit {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  box-shadow: inset 2px 0 0 var(--accent);
}
.line .ts { flex: none; color: var(--fg-dim); user-select: none; }
/* Hora de llegada al panel, no del log: se distingue para no confundirlas. */
.line .ts.aprox { opacity: .6; font-style: italic; }
.line .body { flex: 1; min-width: 0; }
.oculto { display: none; }

.marker {
  margin: 6px 22px;
  padding: 3px 8px;
  font-size: 11px;
  color: var(--warn);
  border-left: 2px solid var(--warn);
  background: color-mix(in srgb, var(--warn) 8%, transparent);
}

/* Paleta ANSI. Los 16 basicos por clase: cambiar el tema se hace solo aca. */
.f0  { color: #5c6370; } .b0  { background: #5c6370; }
.f1  { color: #e06c75; } .b1  { background: #e06c75; }
.f2  { color: #98c379; } .b2  { background: #98c379; }
.f3  { color: #e5c07b; } .b3  { background: #e5c07b; }
.f4  { color: #61afef; } .b4  { background: #61afef; }
.f5  { color: #c678dd; } .b5  { background: #c678dd; }
.f6  { color: #56b6c2; } .b6  { background: #56b6c2; }
.f7  { color: #abb2bf; } .b7  { background: #abb2bf; }
.f8  { color: #7f848e; } .b8  { background: #7f848e; }
.f9  { color: #ff7b86; } .b9  { background: #ff7b86; }
.f10 { color: #b6e3a1; } .b10 { background: #b6e3a1; }
.f11 { color: #ffd68a; } .b11 { background: #ffd68a; }
.f12 { color: #82c7ff; } .b12 { background: #82c7ff; }
.f13 { color: #e0a3f0; } .b13 { background: #e0a3f0; }
.f14 { color: #74d4de; } .b14 { background: #74d4de; }
.f15 { color: #ffffff; } .b15 { background: #ffffff; }

@media (prefers-color-scheme: light) {
  .f0  { color: #383a42; }
  .f7  { color: #4b5263; }
  .f8  { color: #8a8f98; }
  .f15 { color: #1c2027; }
  .f3  { color: #986801; }
  .f11 { color: #b8860b; }
}

.bold { font-weight: 700; }
.dim { opacity: .65; }
.it { font-style: italic; }
.un { text-decoration: underline; }
.inv { background: var(--fg); color: var(--bg); }

/* ------------------------------------------------------------ inventario */

.inv-card {
  width: min(560px, 100%);
  max-height: 88dvh;
  overflow-y: auto;
  gap: 14px;
}
.inv-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}
.inv-head h3 { margin: 0; }
.inv-head p { margin: 2px 0 0; font-size: 12px; }
.inv-actions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.inv-actions button { padding: 5px 10px; font-size: 13px; }

.inv-block > h4 {
  margin: 0 0 6px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--fg-dim);
  font-weight: 600;
}

.inv-grid {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  gap: 3px;
}
.inv-grid.hotbar { margin-top: 8px; }

/* Cada casilla es cuadrada, como en el juego. */
.slot {
  position: relative;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  padding: 2px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 4px;
  cursor: pointer;
  overflow: hidden;
}
.slot:hover { border-color: var(--accent); }
.slot.vacio { cursor: default; opacity: .5; }
.slot.vacio:hover { border-color: var(--line); }
.slot.seleccionado { box-shadow: inset 0 0 0 2px var(--accent); }

/* Sin texturas: se muestran las iniciales del item, que con el tooltip
   alcanzan para reconocerlo. Meter un atlas de texturas seria otro proyecto. */
.slot-ini {
  font-size: 10px;
  font-weight: 600;
  line-height: 1.05;
  text-align: center;
  color: var(--fg-dim);
  word-break: break-all;
  max-height: 100%;
}
.slot.nombrado .slot-ini { color: var(--accent); }
.slot-count {
  position: absolute;
  right: 2px;
  bottom: 1px;
  font-size: 10px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  text-shadow: 0 0 3px var(--bg), 0 0 3px var(--bg);
}

.inv-acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 10px 0 0;
  border-top: 1px solid var(--line);
}
.inv-acciones button { padding: 5px 11px; font-size: 13px; }
.inv-sel {
  flex: 1 1 100%;
  font-size: 12px;
  color: var(--fg-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.slot.elegido { box-shadow: inset 0 0 0 2px var(--accent); border-color: var(--accent); }
/* Slot levantado: el item esta "en la mano" esperando destino. */
.slot.levantado { opacity: .45; box-shadow: inset 0 0 0 2px var(--warn); }
/* Casilla sobre la que se esta por soltar. */
.slot.destino { border-color: var(--ok); box-shadow: inset 0 0 0 2px var(--ok); }
.slot[draggable="true"] { cursor: grab; }
.slot[draggable="true"]:active { cursor: grabbing; }

.inv-msg { margin: 0; font-size: 12px; min-height: 1em; }
.inv-msg.err { color: var(--err); }
.inv-msg.ok { color: var(--ok); }
.inv-hint { margin: 0; font-size: 11px; line-height: 1.5; }

/* ------------------------------------------------------------------ mando */

.pad {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 20;
  display: grid;
  gap: 10px;
  padding: 14px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .45);
}
.pad-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; }

.pad-grid {
  display: grid;
  grid-template-areas:
    ".  f  ."
    "l  b  r"
    "j  j  j"
    "n  n  s";
  gap: 6px;
}
.pad-key {
  min-width: 58px;
  padding: 12px 8px;
  font-size: 13px;
  /* Sin esto, mantener apretado en el celular selecciona el texto del boton. */
  user-select: none;
  touch-action: none;
}
.pad-key.activa { border-color: var(--accent); color: var(--accent); background: var(--bg-hover); }
.pad-hint { margin: 0; max-width: 210px; font-size: 11px; line-height: 1.4; }

/* ------------------------------------------------------------------ modal */

.modal {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(0, 0, 0, .55);
}
.modal-card {
  width: min(400px, 100%);
  display: grid;
  gap: 10px;
  padding: 20px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: 12px;
}
.modal-card h3 { margin: 0; font-size: 16px; }
.modal-card p { margin: 0; font-size: 13px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; }

/* ---------------------------------------------------------------- celular */

/* ----------------------------------------------------------- responsive */

/* Portatil chico: la barra lateral de 260px se come demasiado ancho util. */
@media (max-width: 1000px) {
  .app { grid-template-columns: 64px 1fr 200px; }
  .detail-head,
  #mcconf-form,
  .stats,
  .chat-bar { padding-left: 14px; padding-right: 14px; }
}

/* Tablet y telefono: todo en una columna, el riel pasa a barra horizontal. El
   panel se mira desde el celular mismo mas de una vez, no es decorativo. */
@media (max-width: 760px) {
  .app { grid-template-columns: 1fr; grid-template-rows: 52px 44px auto 1fr; }
  .navrail {
    grid-row: 2;
    flex-direction: row;
    width: 100%;
    overflow-x: auto;
    border-right: none;
    border-bottom: 1px solid var(--line);
    padding: 4px 6px;
  }
  .nav-btn { width: auto; flex-direction: row; padding: 6px 10px; flex: none; }
  .nav-btn span:last-child { font-size: 11px; }
  .sidebar {
    grid-column: 1;
    grid-row: 3;
    grid-template-rows: auto auto auto;
    border-left: none;
    border-bottom: 1px solid var(--line);
  }
  .main { grid-column: 1; grid-row: 4; }
  .proc-list { max-height: 26dvh; }

  /* El titulo y los botones dejan de pelear por la misma linea. */
  .detail-head { padding-top: 12px; padding-bottom: 12px; }
  .actions { margin-left: 0; width: 100%; }
  .actions button { flex: 1 1 auto; }

  /* Con poco alto, un formulario que se lleva el 55% deja el log inservible. */
  #mcconf-form { max-height: 62dvh; }

  /* Una fila clave-valor en 360px parte el valor en dos lineas: mejor
     etiqueta arriba y valor abajo, que es como se lee un formulario en mano. */
  .mcconf-field,
  .mcconf-field.lines {
    grid-template-columns: 1fr;
    gap: 3px;
    padding: 8px 0;
  }
  .mcconf-field > label { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; }
  .mcconf-clear { grid-column: 1; }
  .mcconf-field.lines > label { padding-top: 0; }

  /* Las estadisticas pasan a rejilla: en una sola fila habria que scrollear
     de costado para ver la RAM. */
  .stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 12px; }
  .stats > div { min-width: 0; }
}

/* Telefono angosto de verdad. */
@media (max-width: 420px) {
  .detail-head, #mcconf-form, .stats, .chat-bar {
    padding-left: 10px;
    padding-right: 10px;
  }
  .stats { grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)); }
}
