/* TORRE · panel
 *
 * Un fichero, cero dependencias en tiempo de ejecución, sin build. Sustituye a Tailwind a
 * propósito: el CDN de Tailwind es un compilador de 300 KB en el navegador (dependencia
 * externa + parpadeo sin estilo) y el binario standalone es un paso de build; las dos cosas
 * rompían restricciones más importantes que el framework. Aquí se paga con escribir el CSS.
 *
 * Es un panel denso de datos, no una landing: la jerarquía la llevan el peso y el color,
 * nunca el tamaño de letra. Monoespaciada para los datos (alinea las columnas), sans para
 * el texto. Oscuro de serie porque se mira de noche y conviene que lo rojo se vea rojo.
 */

:root {
  --fondo:      #0a0c0e;
  --panel:      #101317;
  --panel-alto: #151a1f;
  --borde:      #1d242b;
  --borde-alto: #2a333c;

  --texto:      #e7ebef;
  --medio:      #a3aeb9;
  --apagado:    #6f7c88;

  --teal:       #2dd4bf;
  --teal-hueco: #0f3b36;

  --rojo:       #ff6b6b;
  --rojo-hueco: #3a1618;
  --ambar:      #f2b53b;
  --ambar-hueco:#3a2c10;
  --verde:      #44d58a;
  --verde-hueco:#0f3322;
  --gris:       #4c5661;

  --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Inter, Roboto, sans-serif;
  --mono: ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Mono", Consolas, monospace;

  --r: 7px;
  --lateral: 216px;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--fondo);
  color: var(--texto);
  font: 400 14px/1.5 var(--sans);
  font-feature-settings: "tnum" 1;          /* cifras de ancho fijo: las columnas cuadran */
  -webkit-font-smoothing: antialiased;
}

a { color: var(--texto); text-decoration: none; }
a:hover { color: var(--teal); }
code { font: 12.5px/1.4 var(--mono); color: var(--medio); }
h1, h2 { margin: 0; font-weight: 600; letter-spacing: -0.012em; }
h1 { font-size: 19px; }
h2 { font-size: 13px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--medio); }

.apagado { color: var(--apagado); }
.pequeno { font-size: 12px; }
.der { text-align: right; }

/* ── Estructura ───────────────────────────────────────────────────────────── */

.lateral {
  position: fixed; inset: 0 auto 0 0; width: var(--lateral);
  display: flex; flex-direction: column;
  padding: 18px 14px;
  background: var(--panel);
  border-right: 1px solid var(--borde);
}

.marca {
  display: flex; align-items: center; gap: 9px;
  padding: 0 6px 2px;
  color: var(--teal);
  font-weight: 650; font-size: 15px; letter-spacing: 0.1em;
}
.marca:hover { color: var(--teal); }

.nav { display: flex; flex-direction: column; gap: 1px; margin-top: 26px; }
.nav a {
  padding: 7px 10px; border-radius: 6px;
  color: var(--medio); font-size: 13.5px;
  transition: background .12s, color .12s;
}
.nav a:hover { background: var(--panel-alto); color: var(--texto); }
.nav a.activa {
  background: var(--panel-alto); color: var(--texto); font-weight: 550;
  box-shadow: inset 2px 0 0 var(--teal);
}

.lateral-pie { margin-top: auto; padding: 0 6px; }
.lateral-pie p { margin: 0 0 10px; line-height: 1.45; }

.principal {
  margin-left: var(--lateral);
  padding: 22px 26px 60px;
  max-width: 1500px;
}

.cabecera {
  display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap;
  padding-bottom: 14px; margin-bottom: 18px;
  border-bottom: 1px solid var(--borde);
}
.cabecera form { display: flex; align-items: center; gap: 10px; margin: 0 0 0 auto; }
.cabecera > span, .cabecera > a { margin-left: auto; max-width: 62ch; line-height: 1.45; }

.bloque { margin: 0 0 30px; }
.bloque h2 { margin-bottom: 9px; }

/* ── Botones ──────────────────────────────────────────────────────────────── */

.boton {
  padding: 6px 13px; border-radius: 6px;
  border: 1px solid var(--borde-alto); background: var(--panel-alto);
  color: var(--texto); font: 550 13px var(--sans); cursor: pointer;
  transition: border-color .12s, background .12s;
}
.boton:hover { border-color: var(--teal); background: var(--teal-hueco); }
.boton.grande { width: 100%; padding: 10px; margin-top: 6px; }
.boton:disabled { opacity: .45; cursor: not-allowed; }

button.texto {
  padding: 0; border: 0; background: none; cursor: pointer;
  color: var(--apagado); font: 12px var(--sans); text-decoration: underline;
  text-underline-offset: 2px;
}
button.texto:hover { color: var(--texto); }
a.texto { color: var(--apagado); font-size: 12.5px; }

.htmx-indicator { opacity: 0; transition: opacity .15s; }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { opacity: 1; }

/* ── Cartel del veredicto ─────────────────────────────────────────────────── */

.cartel {
  display: flex; gap: 13px; align-items: flex-start;
  padding: 13px 15px; margin-bottom: 18px;
  border: 1px solid var(--borde); border-left-width: 3px;
  border-radius: var(--r);
  background: var(--panel);
}
.cartel-texto { display: flex; flex-direction: column; gap: 3px; }
.cartel-texto strong { font-size: 15px; font-weight: 600; }
.cartel-texto span { color: var(--medio); font-size: 13px; line-height: 1.5; }
.cartel-texto code { font-size: 12px; }

.v-critico    { border-left-color: var(--rojo);  background: linear-gradient(90deg, var(--rojo-hueco), var(--panel) 42%); }
.v-critico    strong { color: var(--rojo); }
.v-atencion   { border-left-color: var(--ambar); background: linear-gradient(90deg, var(--ambar-hueco), var(--panel) 42%); }
.v-atencion   strong { color: var(--ambar); }
.v-incompleto { border-left-color: var(--gris); }
.v-incompleto strong { color: var(--medio); }
.v-bien       { border-left-color: var(--verde); background: linear-gradient(90deg, var(--verde-hueco), var(--panel) 42%); }
.v-bien       strong { color: var(--verde); }
.v-neutro     { border-left-color: var(--teal); }

/* ── Fichas de cifras ─────────────────────────────────────────────────────── */

.fichas {
  display: grid; gap: 10px; margin-bottom: 26px;
  grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
}
.ficha {
  display: flex; flex-direction: column; gap: 2px;
  padding: 12px 14px;
  border: 1px solid var(--borde); border-radius: var(--r);
  background: var(--panel);
}
.ficha-valor { font: 600 25px/1.1 var(--mono); letter-spacing: -0.02em; }
.ficha-pie { color: var(--apagado); font-size: 11.5px; }
.ficha.mala { border-color: color-mix(in srgb, var(--rojo) 40%, var(--borde)); }
.ficha.mala .ficha-valor { color: var(--rojo); }
.ficha.tibia { border-color: color-mix(in srgb, var(--ambar) 34%, var(--borde)); }
.ficha.tibia .ficha-valor { color: var(--ambar); }

/* ── Tablas ───────────────────────────────────────────────────────────────── */

/* La caja es la que lleva el borde y el scroll, no la tabla. Sin esto, una tabla ancha
 * empuja el ancho del documento entero y aparece una barra horizontal en el body: el panel
 * se descoloca y hay que arrastrar la página para leer una fila. Las tablas de aquí tienen
 * nueve columnas, así que esto pasa en cuanto la ventana no es enorme. Va en TODOS los
 * anchos, no solo en móvil. */
.tabla-caja {
  overflow-x: auto;
  border: 1px solid var(--borde); border-radius: var(--r);
}

.tabla {
  width: 100%; border-collapse: collapse;
  font-size: 13px;
}
/* Nada de partir «hace 87 min» en tres líneas: antes se desplaza la caja. La excepción es
 * la columna de notas, que es prosa y sí tiene que poder envolver. */
.tabla th, .tabla td { white-space: nowrap; }
.tabla td.nota { white-space: normal; }
.tabla thead th {
  padding: 8px 11px;
  background: var(--panel);
  border-bottom: 1px solid var(--borde);
  color: var(--apagado); font: 500 11px var(--sans);
  text-transform: uppercase; letter-spacing: 0.055em; text-align: left;
  white-space: nowrap;
}
.tabla tbody td {
  padding: 9px 11px;
  border-bottom: 1px solid color-mix(in srgb, var(--borde) 62%, transparent);
  vertical-align: middle;
}
.tabla tbody tr:last-child td { border-bottom: 0; }
.tabla tbody tr:hover { background: var(--panel); }
.tabla td.nota { color: var(--medio); font-size: 12.5px; max-width: 42ch; min-width: 18ch; }
.tabla td.der, .tabla th.der { text-align: right; font-family: var(--mono); }

/* Lo roto no se señala solo con un punto de color: la fila entera cambia de temperatura. */
.fila-mala { background: color-mix(in srgb, var(--rojo) 7%, transparent); }
.fila-mala:hover { background: color-mix(in srgb, var(--rojo) 12%, transparent) !important; }
.fila-apagada td { opacity: .5; }

/* ── Puntos y etiquetas ───────────────────────────────────────────────────── */

.punto {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  vertical-align: middle;
}
.punto.ok        { background: var(--verde); box-shadow: 0 0 0 3px var(--verde-hueco); }
.punto.fallo     { background: var(--rojo);  box-shadow: 0 0 0 3px var(--rojo-hueco); }
.punto.degradado { background: var(--ambar); box-shadow: 0 0 0 3px var(--ambar-hueco); }
/* Gris, nunca verde: un activo sin latidos no está bien, está sin saber. */
.punto.nada      { background: var(--gris);  box-shadow: 0 0 0 3px #1a1f24; }

.etiqueta {
  display: inline-block; padding: 1px 7px; border-radius: 4px;
  border: 1px solid var(--borde-alto);
  background: var(--panel-alto);
  color: var(--medio);
  font: 500 11px/1.65 var(--sans); white-space: nowrap;
}
.nivel-critico { border-color: color-mix(in srgb, var(--rojo) 48%, transparent);  background: var(--rojo-hueco);  color: var(--rojo); }
.nivel-aviso   { border-color: color-mix(in srgb, var(--ambar) 44%, transparent); background: var(--ambar-hueco); color: var(--ambar); }
.nivel-info    { }
.nivel-diario, .nivel-semanal { border-color: color-mix(in srgb, var(--teal) 34%, transparent); background: var(--teal-hueco); color: var(--teal); }

.entorno-produccion { border-color: color-mix(in srgb, var(--teal) 32%, transparent); color: var(--teal); }
.entorno-staging, .entorno-demo, .entorno-local { color: var(--apagado); }
.donde-airflow, .donde-vps, .donde-pc, .donde-externo { font-family: var(--mono); font-size: 10.5px; }
.propiedad-del_cliente { border-color: color-mix(in srgb, var(--ambar) 40%, transparent); color: var(--ambar); }

.aviso-texto { color: var(--ambar); }

/* ── Tira de historial ────────────────────────────────────────────────────── */
/* Sin librería de gráficas: son 24 divs. Pesa 0 KB y se entiende de un vistazo. */

.tira { display: inline-flex; align-items: flex-end; gap: 2px; height: 16px; }
.tira .barra {
  width: 4px; border-radius: 1px; background: var(--gris);
}
.tira .barra.ok        { height: 9px;  background: var(--verde); opacity: .78; }
.tira .barra.fallo     { height: 16px; background: var(--rojo); }
.tira .barra.degradado { height: 13px; background: var(--ambar); }
.tira .barra.vacia     { height: 3px;  width: 100%; max-width: 54px; background: #1c2227; }
.tira .barra:hover     { opacity: 1; }

/* ── Lista de incidencias ─────────────────────────────────────────────────── */

.lista-incidencias { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.lista-incidencias li {
  padding: 11px 14px;
  border: 1px solid var(--borde); border-left-width: 3px;
  border-radius: var(--r);
  background: var(--panel);
}
.lista-incidencias .linea {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
}
.lista-incidencias .linea strong { font-weight: 550; font-size: 14px; }
.lista-incidencias p { margin: 5px 0 0; }
.lista-incidencias .detalle {
  color: var(--medio); font: 12.5px/1.5 var(--mono);
  padding-left: 10px; border-left: 2px solid var(--borde-alto);
}
.nivel-borde-critico { border-left-color: var(--rojo); }
.nivel-borde-aviso   { border-left-color: var(--ambar); }
.nivel-borde-info    { border-left-color: var(--gris); }

/* ── Detalle ──────────────────────────────────────────────────────────────── */

.datos {
  display: grid; grid-template-columns: max-content 1fr; gap: 7px 22px;
  margin: 0; padding: 15px 17px;
  border: 1px solid var(--borde); border-radius: var(--r); background: var(--panel);
}
.datos dt { color: var(--apagado); font-size: 12px; }
.datos dd { margin: 0; }

.config {
  margin: 0; padding: 13px 15px; overflow-x: auto;
  border: 1px solid var(--borde); border-radius: var(--r);
  background: #0c0f12;
  font: 12.5px/1.6 var(--mono); color: var(--medio);
  white-space: pre;
}

.externo { color: var(--medio); border-bottom: 1px dotted var(--borde-alto); }
.externo:hover { color: var(--teal); border-bottom-color: var(--teal); }

.vacio {
  padding: 24px; margin: 0;
  border: 1px dashed var(--borde-alto); border-radius: var(--r);
  color: var(--apagado); text-align: center;
}
.pie-refresco { margin: 26px 0 0; }

/* ── Puerta (login) ───────────────────────────────────────────────────────── */

body.centrado { display: grid; place-items: center; min-height: 100vh; padding: 20px; }
.puerta {
  width: 100%; max-width: 340px;
  padding: 28px;
  border: 1px solid var(--borde); border-radius: 11px;
  background: var(--panel);
  box-shadow: 0 22px 60px -22px #000;
}
.puerta-marca {
  display: flex; align-items: center; gap: 10px;
  color: var(--teal); font-weight: 650; font-size: 17px; letter-spacing: 0.1em;
}
.puerta p { margin: 7px 0 0; line-height: 1.5; }
.formulario { display: grid; gap: 13px; margin-top: 22px; }
.formulario label {
  display: grid; gap: 5px;
  color: var(--apagado); font-size: 12px;
}
.formulario input {
  padding: 9px 11px;
  border: 1px solid var(--borde-alto); border-radius: 6px;
  background: var(--fondo); color: var(--texto);
  font: 14px var(--sans);
}
.formulario input:focus {
  outline: none; border-color: var(--teal);
  box-shadow: 0 0 0 3px var(--teal-hueco);
}
.error {
  padding: 8px 11px; margin-top: 14px !important;
  border: 1px solid color-mix(in srgb, var(--rojo) 45%, transparent);
  border-radius: 6px; background: var(--rojo-hueco);
  color: var(--rojo); font-size: 13px;
}

/* ── Piezas de un conjunto ────────────────────────────────────────────────── */
/* El chatbot de una web y su contenedor viven DENTRO de la fila de la web. Cada chip lleva
 * su propio punto: el conjunto se pone rojo por culpa de una pieza y hay que ver cuál sin
 * abrir nada. */

.piezas { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 5px; }
.pieza {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 1px 7px 1px 6px; border-radius: 4px;
  border: 1px solid var(--borde); background: var(--panel-alto);
  color: var(--medio); font-size: 11px;
}
.pieza:hover { border-color: var(--borde-alto); color: var(--texto); }
.pieza-mala { border-color: color-mix(in srgb, var(--rojo) 42%, transparent); background: var(--rojo-hueco); }
.pieza-apagada { opacity: .5; }

.boton.mini { padding: 3px 9px; font-size: 11.5px; }
/* El estado de «estoy llamando al sitio» sin una línea de JavaScript: lo pinta la clase
 * que HTMX pone en el formulario mientras la petición está en vuelo. Con un chatbot son
 * hasta 45 segundos, y sin esto parece que el botón no ha hecho nada. */
.si-pide { display: none; }
.htmx-request .si-quieto { display: none; }
.htmx-request .si-pide { display: inline; }
form.en-linea { display: inline; margin: 0; }

/* ── La prueba: qué devolvió de verdad la llamada ─────────────────────────── */
/* Sin esto el panel pedía un acto de fe: decía «no aparece el texto» y para saber qué había
 * llegado tocaba repetir el curl en otra ventana. */

.prueba {
  padding: 10px 12px;
  border: 1px solid var(--borde); border-radius: var(--r);
  background: #0c0f12;
}
.prueba-linea { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; }
.prueba-peticion { color: var(--teal); font-size: 11.5px; }
.prueba-nota { margin: 7px 0 0; color: var(--medio); font-size: 12px; line-height: 1.5; }
.prueba-cuerpo {
  margin: 8px 0 0; padding: 8px 10px; max-height: 13em; overflow: auto;
  border-left: 2px solid var(--borde-alto); border-radius: 0 4px 4px 0;
  background: var(--fondo);
  color: var(--medio); font: 12px/1.55 var(--mono);
  /* pre-wrap y no pre: un cuerpo de 400 caracteres en una línea obliga a arrastrar. */
  white-space: pre-wrap; overflow-wrap: anywhere;
}
/* Lo que le sale al cliente en la burbuja se lee antes que el JSON que lo envuelve. */
.prueba-cuerpo.contesto { border-left-color: var(--teal); color: var(--texto); }
.prueba-cuerpo.malo { border-left-color: var(--rojo); color: var(--rojo); }

.celda-prueba { white-space: normal; max-width: 46ch; }
.celda-prueba details > summary {
  cursor: pointer; color: var(--apagado); font-size: 12px;
  text-decoration: underline; text-underline-offset: 2px; list-style: none;
}
.celda-prueba details > summary::-webkit-details-marker { display: none; }
.celda-prueba details[open] > summary { color: var(--texto); margin-bottom: 7px; }
.celda-prueba details > summary:hover { color: var(--texto); }

/* ── Formulario de alta ───────────────────────────────────────────────────── */

.formulario-alta { max-width: 940px; }
.formulario-alta fieldset {
  margin: 0 0 18px; padding: 15px 17px 17px;
  border: 1px solid var(--borde); border-radius: var(--r);
  background: var(--panel);
}
.formulario-alta legend {
  padding: 0 7px;
  color: var(--medio); font: 500 11px var(--sans);
  text-transform: uppercase; letter-spacing: 0.055em;
}
.rejilla { display: grid; gap: 13px 18px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.rejilla + .rejilla { margin-top: 13px; padding-top: 14px; border-top: 1px dashed var(--borde); }
.formulario-alta label { display: grid; gap: 5px; align-content: start; color: var(--apagado); font-size: 12px; }
.formulario-alta input, .formulario-alta select, .formulario-alta textarea {
  padding: 8px 10px;
  border: 1px solid var(--borde-alto); border-radius: 6px;
  background: var(--fondo); color: var(--texto);
  font: 13.5px var(--sans); width: 100%;
}
.formulario-alta textarea { font-family: var(--mono); font-size: 12.5px; resize: vertical; }
.formulario-alta input:focus, .formulario-alta select:focus, .formulario-alta textarea:focus {
  outline: none; border-color: var(--teal); box-shadow: 0 0 0 3px var(--teal-hueco);
}
.pista { color: var(--apagado); font-size: 11.5px; line-height: 1.5; }
.bloque-pista { margin: 0 0 14px; max-width: 78ch; }
.formulario-alta label.casilla {
  grid-template-columns: max-content 1fr; align-items: center; gap: 8px;
  color: var(--texto); font-size: 13px;
}
.formulario-alta label.casilla input { width: auto; }
.acciones { display: flex; align-items: center; gap: 14px; margin-top: 16px; }

/* Los campos de cada tipo de comprobación aparecen solos, sin JavaScript: la regla que los
 * esconde está dentro de un :has(), así que un navegador que no lo entienda los deja todos
 * visibles —molesto— en vez de dejarlos todos escondidos —roto—. El selector nombra el
 * select concreto a propósito: «chatbot» y «contenedor» también son valores de `tipo`. */
.formulario-alta:has(select[name="comprobacion_tipo"]) .campos-http,
.formulario-alta:has(select[name="comprobacion_tipo"]) .campos-chatbot,
.formulario-alta:has(select[name="comprobacion_tipo"]) .campos-contenedor { display: none; }

.formulario-alta:has(select[name="comprobacion_tipo"] option[value="http"]:checked) .campos-http,
.formulario-alta:has(select[name="comprobacion_tipo"] option[value="chatbot"]:checked) .campos-chatbot,
.formulario-alta:has(select[name="comprobacion_tipo"] option[value="contenedor"]:checked) .campos-contenedor {
  display: grid;
}

a.boton { display: inline-block; }

/* ── Pantallas estrechas ──────────────────────────────────────────────────── */
/* No es un panel de móvil, pero mirarlo desde el teléfono tiene que ser posible:
   la barra pasa arriba y las tablas ruedan en horizontal dentro de su caja. */

@media (max-width: 860px) {
  .lateral {
    position: static; width: auto; flex-direction: row; align-items: center;
    gap: 14px; padding: 11px 14px; overflow-x: auto;
    border-right: 0; border-bottom: 1px solid var(--borde);
  }
  .nav { flex-direction: row; margin-top: 0; }
  .nav a.activa { box-shadow: inset 0 -2px 0 var(--teal); }
  .lateral-pie { margin-left: auto; }
  .lateral-pie p { display: none; }
  .principal { margin-left: 0; padding: 16px 14px 48px; }
  /* El scroll de las tablas ya lo lleva .tabla-caja en todos los anchos, así que aquí no
     hace falta repetirlo. */
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}
