/*
 * /core/nodes — el plano de control de ATLAS Core, rediseñado el 2026-08-18 con el mapa como
 * imagen principal.
 *
 * Reutiliza lo canónico de css/components/kpiDashboard.css (.dashboard-banner, .banner-title,
 * .dashboard-card, .kpi-value, .kpi-label) y añade SOLO lo propio de esta pantalla: los cuatro
 * estados de salud, la fila de Conexiones y el mapa con sus overlays.
 *
 * Los colores salen de los tokens de severidad y no de literales: el día que cambie el rojo de la
 * marca, cambia en un sitio. El naranja de ERROR es --atlas-sev-pending a propósito — es el único
 * de la escala que no se confunde con el rojo de DOWN, y esa distinción es el sentido mismo del
 * estado (C10: «conecta pero manda basura» lo arregla el proveedor del dato, no el de la red).
 */

/* ── La página-mapa ────────────────────────────────────────────────────────

   `height: 100%` y no `100vh`: .content-inner ya es una columna flex a
   height:100% (mismo truco que usa technificationDev.css) — con vh habría que
   restar a mano la altura del NavBar y del banner de sesión, y ese número
   cambia si el layout cambia. Sin border-radius: el mapa llena el hueco de
   contenido borde a borde, como pide "que ocupe toda la pantalla, como un
   dashboard" — sin ocultar NavBar ni SideBar, que siguen siendo el resto del
   dashboard.                                                                */

.core-map-page {
	position: relative;
	width: 100%;
	height: 100%;
	flex: 1 1 auto;
	min-height: 520px;
	overflow: hidden;
	border-radius: 0;
	background: var(--atlas-gray-100, #e5e7eb);
}

.core-map-canvas {
	position: absolute;
	inset: 0;
	/* Explícito y bajo, no `auto`: Leaflet añade su propio contexto de apilamiento al
	   contenedor (`.leaflet-container` es `position: relative`), y sin un z-index propio
	   aquí no hay garantía de que el selector de Nodos (z-index 15) quede claramente por
	   encima en todos los navegadores. */
	z-index: 1;
}

.core-map-banner {
	position: absolute;
	top: 1rem;
	left: 50%;
	transform: translateX(-50%);
	z-index: 20;
	margin: 0;
	box-shadow: var(--atlas-shadow-2);
}

.core-map-loading {
	background: var(--surface-card, #fff);
	padding: 0.5rem 1rem;
	border-radius: var(--atlas-radius-full);
	display: flex;
	align-items: center;
	font-size: 0.875rem;
	color: var(--text-secondary);
}

/* Reserva: los Nodos que no tienen ninguna posición dentro de la ventana de
   presencia. El grid de siempre, ahora dentro de la página-mapa — con su propio
   scroll y relleno, porque ya no vive en `.content` con su padding de página
   normal.

   ⚠️ El `z-index` NO es decorativo. `.core-map-canvas` es `z-index: 1`, y un
   posicionado con `z-index: auto` se pinta ANTES que uno con z-index positivo
   aunque venga después en el DOM: sin este 10 la reserva queda tapada por el
   mapa. Va por debajo del selector y del panel (15), que siguen mandando.      */
.core-map-fallback {
	position: absolute;
	inset: 0;
	z-index: 10;
	overflow-y: auto;
	padding: 1.5rem;
	background: var(--body-bg);
}

/* Y cuando SÍ hay mapa —hay otros Nodos con posición— la reserva no puede ser
   una capa a pantalla completa: taparía justo lo que esta pantalla existe para
   enseñar. Se acopla como panel acotado en la esquina inferior derecha, la única
   libre (el selector y el panel del Nodo abierto viven a la izquierda), y deja
   de pintar fondo: lo pintan las propias tarjetas.                             */
.core-map-fallback-docked {
	inset: auto 1rem 1rem auto;
	z-index: 15;
	width: 20rem;
	max-width: calc(100% - 2rem);
	max-height: calc(100% - 2rem);
	padding: 0;
	background: transparent;
}

.core-map-fallback-head {
	font-size: 0.75rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	color: var(--text-secondary);
	background: var(--surface-card, #fff);
	border-radius: var(--atlas-radius-full);
	box-shadow: var(--atlas-shadow-2);
	padding: 0.25rem 0.75rem;
	margin-bottom: 0.5rem;
	display: inline-block;
}

/* ── El selector de Nodos, esquina superior izquierda ────────────────────── */

.core-node-picker {
	position: absolute;
	top: 1rem;
	left: 1rem;
	z-index: 15;
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	max-width: 15rem;
}

.core-node-chip {
	display: flex;
	align-items: center;
	gap: 0.625rem;
	background: var(--surface-card, #fff);
	border: 1px solid var(--atlas-border, #e5e7eb);
	border-radius: var(--atlas-radius-md, 8px);
	padding: 0.625rem 0.875rem;
	box-shadow: var(--atlas-shadow-2);
	cursor: pointer;
	text-align: left;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.core-node-chip:hover {
	border-color: var(--atlas-color-primary);
}

.core-node-chip-active {
	border-color: var(--atlas-color-primary);
	box-shadow: 0 0 0 2px var(--atlas-color-primary) inset, var(--atlas-shadow-2);
}

.core-node-chip-text {
	display: flex;
	flex-direction: column;
	line-height: 1.3;
}

.core-node-chip-title {
	font-weight: 600;
	font-size: 0.875rem;
	color: var(--text-primary);
}

.core-node-chip-count {
	font-size: 0.75rem;
	color: var(--text-secondary);
	font-variant-numeric: tabular-nums;
}

/* ── El panel del Nodo abierto ──────────────────────────────────────────────

   Cuelga justo debajo del selector, mismo margen izquierdo: es su despliegue,
   no una ventana aparte. Con scroll propio porque los repartos de un Nodo con
   muchas facetas pueden superar el alto disponible en una pantalla baja.     */

.core-node-panel {
	position: absolute;
	top: 5.5rem;
	left: 1rem;
	z-index: 15;
	width: 20rem;
	max-height: calc(100% - 7rem);
	overflow-y: auto;
	background: var(--surface-card, #fff);
	border: 1px solid var(--atlas-border, #e5e7eb);
	border-radius: var(--atlas-radius-md, 8px);
	box-shadow: var(--atlas-shadow-2);
	padding: 1rem 1.25rem;
}

.core-node-panel-head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 0.5rem;
	margin-bottom: 0.625rem;
}

/* ── La cajita de un Nodo ──────────────────────────────────────────────── */

.core-node-card {
	display: flex;
	flex-direction: column;
	height: 100%;
}

.core-node-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--atlas-space-2);
	padding: 1rem 1.25rem;
	border-bottom: 1px solid var(--atlas-border, #e5e7eb);
}

.core-node-body {
	flex-grow: 1;
	padding: 1rem 1.25rem;
}

.core-node-title {
	font-weight: 600;
	color: var(--text-primary);
}

.core-node-sub {
	font-size: 0.8125rem;
	color: var(--text-secondary);
}

/* Los tres números. Más pequeños que un KPI de dashboard: aquí van tres por cajita y varias
   cajitas por pantalla, y el .kpi-value canónico a tamaño completo las rompe. */
.core-node-card .kpi-value {
	font-size: 1.5rem;
	line-height: 1.2;
}

/* ── Salud ─────────────────────────────────────────────────────────────── */

.core-health {
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.02em;
	padding: 0.25rem 0.625rem;
	border-radius: var(--atlas-radius-full);
	white-space: nowrap;
}

.core-health-online { background: var(--atlas-sev-ok-bg); color: var(--atlas-sev-ok-text); }
.core-health-stale { background: var(--atlas-sev-warn-bg); color: var(--atlas-sev-warn-text); }
.core-health-error { background: var(--atlas-sev-pending-bg); color: var(--atlas-sev-pending-text); }
.core-health-down { background: var(--atlas-sev-danger-bg); color: var(--atlas-sev-danger-text); }

/* Sin Conexiones encendidas. Gris y no verde: «no lo hemos encendido» no es «va bien». */
.core-health-off {
	background: var(--atlas-gray-100, #f3f4f6);
	color: var(--text-secondary);
}

/* ── La lista de Conexiones ────────────────────────────────────────────── */

.core-conn {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--atlas-space-2);
	padding: 0.25rem 0;
	font-size: 0.875rem;
}

.core-dot {
	font-size: 0.625rem;
	line-height: 1;
}

.core-dot-online { color: var(--atlas-sev-ok); }
.core-dot-stale { color: var(--atlas-sev-warn); }
.core-dot-error { color: var(--atlas-sev-pending); }
.core-dot-down { color: var(--atlas-sev-danger); }
.core-dot-off { color: var(--text-muted, #9ca3af); }

.core-note {
	font-size: 0.8125rem;
	color: var(--text-secondary);
}


/* ── La cifra grande ───────────────────────────────────────────────────────

   `seen today` va en grande y las otras dos ventanas pequeñas al lado. No es
   jerarquía visual porque sí: el total del Perfil es ACUMULADO desde que se
   encendió el Nodo, y a solas se lee como «hay N en obra». Tenerlas las tres a
   la vista es lo que impide esa lectura.                                     */

.core-headline {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: var(--atlas-space-3, 0.75rem);
	margin-bottom: 0.625rem;
}

.core-headline-value {
	font-size: 1.75rem;
	font-weight: 600;
	line-height: 1.1;
	color: var(--text-primary);
	font-variant-numeric: tabular-nums;
}

.core-headline-label {
	font-size: 0.75rem;
	color: var(--text-secondary);
	text-transform: uppercase;
	letter-spacing: 0.03em;
}

.core-headline-side {
	text-align: right;
	font-size: 0.75rem;
	color: var(--text-secondary);
	line-height: 1.5;
	font-variant-numeric: tabular-nums;
}

.core-headline-side span {
	color: var(--text-muted, #9ca3af);
}

/* ── La línea de estado operativo ──────────────────────────────────────────

   Todo lo del tubo —sin casar, frescura, cola, errores— en UNA línea que se
   ajusta sola. Antes eran tres columnas centradas de las que dos vivían a cero.
   Los avisos solo aparecen cuando hay algo que mirar.                        */

.core-stats {
	display: flex;
	flex-wrap: wrap;
	gap: 0.25rem 0.875rem;
	font-size: 0.75rem;
	color: var(--text-secondary);
	margin-bottom: 0.5rem;
}

/* ── Los repartos (facetas) ────────────────────────────────────────────────

   Una barra APILADA por faceta con su leyenda debajo. Antes era una fila por
   valor: cuatro facetas por seis valores eran veinticuatro líneas y la tarjeta
   se iba metros hacia abajo.

   Qué facetas se pintan lo decide `core.node_facet`, no el CSS: estas clases
   sirven para cualquier reparto de cualquier Nodo. Por eso los colores se
   llaman `core-seg-0..3` por POSICIÓN y no por contenido — no hay ni un color
   de contratista, ni nada que nombre a Wiloc o a Blackline.                  */

.core-facet {
	margin-bottom: 0.625rem;
}

.core-facet-head {
	font-size: 0.75rem;
	font-weight: 600;
	color: var(--text-secondary);
	margin-bottom: 0.25rem;
}

.core-facet-stack {
	display: flex;
	height: 0.5rem;
	border-radius: 999px;
	overflow: hidden;
	background: var(--atlas-gray-100, #f3f4f6);
}

.core-facet-seg {
	height: 100%;
	/* Un valor de 1 sobre 4.000 sigue viéndose: un segmento de 0,02 % es
	   invisible, e «invisible» se lee como «cero». */
	min-width: 2px;
}

.core-facet-legend {
	display: flex;
	flex-wrap: wrap;
	gap: 0.125rem 0.75rem;
	margin-top: 0.3125rem;
	font-size: 0.75rem;
	color: var(--text-secondary);
}

.core-legend-item {
	display: inline-flex;
	align-items: center;
	gap: 0.25rem;
	max-width: 100%;
}

.core-legend-name {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	max-width: 8.5rem;
}

.core-legend-item b {
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	color: var(--text-primary);
}

.core-legend-dot {
	width: 0.5rem;
	height: 0.5rem;
	border-radius: 2px;
	flex: 0 0 auto;
}

/* Cuatro HUES distintos, no cuatro tonos del mismo azul.

   El primer intento fueron cuatro azules degradados y no se distinguian: dos
   segmentos contiguos parecian el mismo. Estos cuatro estan VALIDADOS con el
   script de la guia de visualizacion —banda de luminosidad, suelo de croma,
   separacion bajo daltonismo y contraste contra el fondo— y pasan las cinco
   comprobaciones en claro y en oscuro. El peor par adyacente es verde↔ambar con
   ΔE 9,3 en deuteranopia, por encima del suelo de 8.

   ⚠️ El ORDEN importa y no es alfabetico. Azul y violeta salen ΔE 0,4 en
   deuteranopia —indistinguibles— asi que van SEPARADOS: azul, ambar, verde,
   violeta. Reordenarlos rompe la validacion aunque los colores sean los mismos.

   ⚠️ Y son colores de POSICION, no de contenido: `core-seg-0` es «el primero del
   reparto», no «contratista OQC». Un color atado a un valor concreto obligaria a
   conocer los valores, que es justo lo que estas facetas evitan.

   Los de estado —emerald/amber/red de las insignias ONLINE/STALE/DOWN— no se
   reutilizan aqui como identidad: aquellos van siempre con su texto al lado. */
.core-seg-0 { background: #2563eb; }
.core-seg-1 { background: #b45309; }
.core-seg-2 { background: #059669; }
.core-seg-3 { background: #7c3aed; }
.core-seg-rest { background: var(--atlas-gray-300, #d1d5db); }

/* Separador de 2 px entre segmentos: sin el, dos fills contiguos se leen como uno
   solo aunque sean de colores distintos. Es la regla de marcas de la guia. */
.core-facet-seg + .core-facet-seg {
	box-shadow: -2px 0 0 0 var(--surface-card, #fff);
}

/* ── La misma vista, incrustada y SIN mapa propio (OwnMap=false) ────────────

   El dashboard de proyecto monta CoreNodesView en un panel estrecho colgado de
   su selector de capas, y las posiciones las pinta sobre SU mapa. Aquí, por
   tanto, no hay nada flotando: lo que en /core/nodes son capas absolutas sobre
   el mapa, aquí es una columna que se lee de arriba abajo.

   El sitio, el ancho y el fondo los pone .tdev-nodes-panel; esto es lo de
   dentro.                                                                     */

.core-stack {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}

.core-stack-head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--atlas-space-2, 0.5rem);
}

.core-stack-title {
	font-weight: 700;
	font-size: 0.8125rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--text-primary);
}

.core-stack-sub {
	font-size: 0.75rem;
	color: var(--text-secondary);
}

/* Los chips dejan de ser una pila flotante en la esquina del mapa y pasan a ser
   la lista del panel: a todo el ancho, porque aquí el ancho es el que hay. */
.core-stack-chips {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

.core-stack-chips .core-node-chip {
	width: 100%;
	box-shadow: none;
}

.core-stack-panel {
	border-top: 1px solid var(--atlas-border, #e5e7eb);
	padding-top: 0.75rem;
}

.core-stack-muted {
	border-top: 1px solid var(--atlas-border, #e5e7eb);
	padding-top: 0.75rem;
}

/* Los avisos son .core-map-banner, que en /core/nodes flota centrado sobre el
   mapa. En la columna no hay nada sobre lo que flotar. */
.core-stack .core-map-banner {
	position: static;
	transform: none;
	box-shadow: none;
	padding: 0;
	background: transparent;
	font-size: 0.8125rem;
}

/* ── Variante oscura ───────────────────────────────────────────────────────

   Se redefinen los TOKENS y no las reglas: así el bloque de un Nodo
   (CoreNodeBlock) es exactamente el mismo marcado en las dos pantallas y no hay
   una segunda versión de cada regla esperando a divergir.

   Las insignias de salud llevan fondo suave + texto oscuro, que sobre el azul
   del dashboard no se lee: aquí el fondo pasa a translúcido del propio color y
   el texto al tono claro. Los colores de estado son los mismos —el verde de
   ONLINE sigue siendo el verde de ONLINE—, cambia el soporte.                 */

.core-on-dark {
	--surface-card: rgba(16, 38, 61, 0.92);
	--text-primary: #eaf6ff;
	--text-secondary: rgba(205, 234, 254, 0.7);
	--text-muted: rgba(205, 234, 254, 0.45);
	--atlas-border: rgba(0, 229, 255, 0.18);

	--atlas-sev-ok-bg: rgba(37, 208, 125, 0.18);
	--atlas-sev-ok-text: #6ef0b4;
	--atlas-sev-warn-bg: rgba(255, 176, 32, 0.18);
	--atlas-sev-warn-text: #ffd487;
	--atlas-sev-pending-bg: rgba(255, 138, 61, 0.18);
	--atlas-sev-pending-text: #ffbb8a;
	--atlas-sev-danger-bg: rgba(255, 77, 109, 0.18);
	--atlas-sev-danger-text: #ff9db1;

	color: var(--text-primary);
}

/* Sin Conexiones encendidas: gris del dashboard, no el --atlas-gray-100 claro,
   que sobre el azul es una pastilla blanca. */
.core-on-dark .core-health-off {
	background: rgba(205, 234, 254, 0.12);
	color: var(--text-secondary);
}

/* Las utilidades de Bootstrap son literales, no tokens: sobre fondo oscuro el
   text-muted gris y el text-danger de marca pierden contraste. */
.core-on-dark .text-muted { color: var(--text-secondary) !important; }
.core-on-dark .text-danger { color: #ff9db1 !important; }
.core-on-dark .text-warning { color: #ffd487 !important; }
.core-on-dark hr { border-color: var(--atlas-border); opacity: 1; }

/* El botón de cerrar de Bootstrap es un SVG negro: invertido para que se vea. */
.core-on-dark .core-panel-close { filter: invert(1) grayscale(1) brightness(1.6); }

/* El separador entre segmentos de faceta calca el fondo de la tarjeta, y aquí
   ese fondo es el del panel oscuro. */
.core-on-dark .core-facet-seg + .core-facet-seg {
	box-shadow: -2px 0 0 0 rgba(16, 38, 61, 0.92);
}

.core-on-dark .core-seg-rest { background: rgba(205, 234, 254, 0.28); }

/* La reserva de Nodos mudos pinta el fondo de la página cuando NO hay mapa; en el
   dashboard ese fondo es el del panel, no el del body claro. */
.core-on-dark .core-map-fallback { background: transparent; }

/* Las tarjetas de esa reserva son .dashboard-card, que es blanca por definición. */
.core-on-dark .dashboard-card {
	background: rgba(11, 28, 46, 0.92);
	border-color: var(--atlas-border);
	box-shadow: none;
}

.core-on-dark .core-map-fallback-head,
.core-on-dark .core-node-chip {
	background: rgba(11, 28, 46, 0.92);
	border-color: var(--atlas-border);
	box-shadow: none;
}

.core-on-dark .core-node-panel {
	box-shadow: none;
}

/* Solo aplica cuando la vista trae su propio mapa: mientras cargan los teselas se
   ve el fondo del contenedor. */
.core-on-dark.core-map-page { background: transparent; }

/* ── Marcador con glifo de la capa de Core ──────────────────────────────────────
   Un vehículo se pinta con un coche y no con el círculo cian genérico: entre los
   puntos de un plano de obra, la forma es lo que se lee de un vistazo — el color
   sigue diciendo «esto es Core» y el icono dice QUÉ es sin abrir el tooltip.

   Vive aquí y no en technificationDev.css aunque lo use el mapa del dashboard: es
   un `divIcon` de Leaflet, que cuelga del pane del mapa y no del árbol del widget,
   y _Host carga las dos hojas en todas las páginas. Una sola copia = el mismo
   marcador en /core/nodes y en el dashboard. */
/* El acabado es el mismo que el de los detectores de gas (.tdev-gas-marker) a
   proposito: los dos son un aparato concreto puesto sobre el plano de la obra, y dos
   familias de marcador distintas para la misma idea obligan a aprenderse dos.
   Cambia el color —cian, que es el de Core— y el simbolo de dentro.

   La caja va en un <span> interior y no en la raiz: `.leaflet-div-icon` trae su
   propio fondo blanco y su borde gris, y neutralizarlos en el mismo elemento que se
   quiere pintar depende del orden en que carguen las hojas. */
.core-glyph-marker {
	background: none;
	border: 0;
}

.core-glyph-marker > span {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	box-sizing: border-box;
	border-radius: 50%;
	border: 2px solid var(--core-glyph-color, #00e5ff);
	background: rgba(6, 18, 28, 0.88);
	color: var(--core-glyph-color, #00e5ff);
	/* Dos sombras: el halo que lo despega del plano y la caida que le da volumen. */
	box-shadow: 0 0 0 4px rgba(6, 18, 28, 0.4), 0 6px 16px rgba(0, 0, 0, 0.45);
	cursor: pointer;
	transition: transform 0.12s ease;
}

/* 16 y no los 15 del detector: el coche es una silueta ancha y baja, y a la misma
   medida que la gota se ve mas pequeno de lo que es. */
.core-glyph-marker > span i {
	font-size: 16px;
	line-height: 1;
}

.core-glyph-marker:hover > span {
	transform: scale(1.1);
}

/* El destello al centrar el mapa en una entidad desde su fila de la lista. Con catorce
   marcadores parecidos en pantalla, centrar sin señalar deja al ojo buscando cuál es. */
.core-glyph-marker.is-focus > span {
	animation: core-glyph-focus 0.55s ease-out 3;
}

@keyframes core-glyph-focus {
	0% { box-shadow: 0 0 0 4px rgba(0, 229, 255, 0.55), 0 6px 16px rgba(0, 0, 0, 0.45); }
	100% { box-shadow: 0 0 0 16px rgba(0, 229, 255, 0), 0 6px 16px rgba(0, 0, 0, 0.45); }
}
