/* Monitor de sedes: pestana dentro de la pagina Monitor.
 *
 * Paleta del 1.0 (decision de Julian, 29-30/10/2026): solo tokens de tokens.css, asi
 * que el modulo sigue a los cuatro temas sin redefinir nada. El color de estado es el
 * dato: una sede caida va en --danger aunque rompa la armonia (skill sistema-diseno).
 */

/* Con la pestana de sedes a la vista se ocultan los bloques de la pestana de
 * servicios. Se hace por clase en la pagina y no envolviendo el HTML existente: asi
 * el contenido de siempre no se reescribe (regla 2). */
/* `!important` porque #monitor-kpis y #vozmapa-panel llevan display en linea (el JS de
 * la voz lo pone en block) y el estilo en linea gana a cualquier selector: sin el, sus
 * bloques seguian debajo de la tabla de sedes (captura del 30/10/2026). */
#page-monitor.msedes-activo > :not(.msedes-fija) { display: none !important; }
#page-monitor:not(.msedes-activo) > #msedes-zona { display: none; }

.msedes-tabs {
  display: flex;
  gap: 0;
  margin-bottom: var(--sp-4);
  border-bottom: 1px solid var(--border);
}
.msedes-tab {
  padding: 10px 20px;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--text-tertiary);
  cursor: pointer;
  font-size: var(--text-base);
  font-family: var(--font-sans);
  transition: color .15s ease, border-color .15s ease;
}
.msedes-tab.active {
  color: var(--text-primary);
  border-bottom-color: var(--accent);
  font-weight: 600;
}
.msedes-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
@media (hover: hover) and (pointer: fine) {
  .msedes-tab:not(.active):hover { color: var(--text-secondary); }
}

.msedes-estado {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  margin-bottom: var(--sp-3);
}
.msedes-estado-error { color: var(--danger); }

.msedes-kpis {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}
/* Son 8 tarjetas: con auto-fill de 150 px caben 7 a 1440 px y la octava quedaba sola en
   una segunda fila. En ancho de escritorio van las 8 en una fila; abajo sigue el auto-fill. */
@media (min-width: 1280px) {
  .msedes-kpis { grid-template-columns: repeat(8, minmax(0, 1fr)); }
}
.msedes-kpi {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--sp-3) var(--sp-4);
}
.msedes-kpi-t {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.msedes-kpi-v {
  font-size: var(--text-xl);
  font-weight: 600;
  color: var(--text-primary);
  margin-top: var(--sp-1);
  font-variant-numeric: tabular-nums;
}
.msedes-c-ok { color: var(--success); }
.msedes-c-fallo { color: var(--danger); }
.msedes-c-sin { color: var(--text-tertiary); }
.msedes-c-inter { color: var(--warning); }

.msedes-cuerpo {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: var(--sp-4);
  margin-bottom: var(--sp-4);
}
@media (max-width: 900px) {
  .msedes-cuerpo { grid-template-columns: minmax(0, 1fr); }
}

.msedes-mapa-caja {
  background: var(--bg-hundido);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--sp-3);
}
#msedes-mapa {
  display: block;
  width: 100%;
  height: auto;
  max-height: 620px;
}
.msedes-silueta {
  fill: var(--bg-elevated);
  stroke: var(--border-strong);
  stroke-width: 1.5;
  stroke-linejoin: round;
}

.msedes-marca { cursor: pointer; outline: none; }
.msedes-punto {
  stroke: var(--bg);
  stroke-width: 2;
  transition: opacity .15s ease;
}
.msedes-marca.msedes-e-ok .msedes-punto { fill: var(--success); }
.msedes-marca.msedes-e-fallo .msedes-punto { fill: var(--danger); }
.msedes-marca.msedes-e-sin_monitoreo .msedes-punto { fill: var(--text-tertiary); }
.msedes-anillo {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
}
.msedes-marca:focus-visible .msedes-anillo,
.msedes-marca:focus-visible .msedes-punto { stroke: var(--accent); stroke-width: 2.5; }
.msedes-cuenta {
  fill: var(--bg);
  font-size: 10px;
  font-weight: 700;
  font-family: var(--font-mono);
  pointer-events: none;
}
@media (hover: hover) and (pointer: fine) {
  .msedes-marca:hover .msedes-punto { opacity: .8; }
}

/* Pulso de una sede caida: indica estado, por eso se conserva atenuado con
 * movimiento reducido en vez de quitarse. */
.msedes-pulso {
  fill: none;
  stroke: var(--danger);
  stroke-width: 2;
  transform-box: fill-box;
  transform-origin: center;
  animation: msedes-pulso 1.8s cubic-bezier(0.23, 1, 0.32, 1) infinite;
}
@keyframes msedes-pulso {
  from { transform: scale(1); opacity: .8; }
  to { transform: scale(2.6); opacity: 0; }
}

.msedes-detalle {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--sp-4);
  min-width: 0;
}
.msedes-det-cab {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}
.msedes-det-nombre {
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--text-primary);
}
.msedes-sub {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  margin-top: 2px;
}
.msedes-metricas {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}
.msedes-met-v {
  font-family: var(--font-mono);
  font-size: var(--text-lg);
  color: var(--text-primary);
  margin-top: var(--sp-1);
}

.msedes-chip {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--r-sm);
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
  background: var(--neutral-bg);
  color: var(--text-secondary);
}
.msedes-chip.msedes-e-ok { background: var(--success-bg); color: var(--success); }
.msedes-chip.msedes-e-fallo { background: var(--danger-bg); color: var(--danger); }
.msedes-chip.msedes-e-intermitente {
  background: var(--warning-bg); color: var(--warning);
  outline: 1px dashed var(--warning); outline-offset: -1px;
}
.msedes-chip.msedes-e-degradado { background: var(--warning-bg); color: var(--warning); }

.msedes-tabla-serv { width: 100%; }
/* En pantallas angostas la tabla se desplaza dentro de su caja en vez de ensanchar la pagina. */
.msedes-tabla-scroll { overflow-x: auto; max-width: 100%; }
.msedes-mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.msedes-vacio {
  color: var(--text-tertiary);
  font-size: var(--text-sm);
  padding: var(--sp-4);
  text-align: center;
}
.msedes-fila { cursor: pointer; }
.msedes-fila-sel td { background: var(--bg-active); }
@media (hover: hover) and (pointer: fine) {
  .msedes-fila:not(.msedes-fila-sel):hover td { background: var(--bg-hover); }
}

/* Movimiento reducido: menos y mas suave, no cero. El pulso deja de crecer y se
 * queda como un parpadeo lento de opacidad, que sigue diciendo "caida". */
@media (prefers-reduced-motion: reduce) {
  .msedes-pulso { animation: msedes-pulso-suave 2.4s ease infinite; transform: scale(1.6); }
  .msedes-tab, .msedes-punto { transition: none; }
}
@keyframes msedes-pulso-suave {
  0%, 100% { opacity: .15; }
  50% { opacity: .6; }
}

/* En el telefono la tabla de sedes se desplaza dentro de su panel, no la pagina. */
.msedes-tabla-caja { overflow-x: auto; }

/* ── Fase B del rehacer (30/10/2026): mapa animado como el prototipo ─────────────
 * Las clases las pinta monitor-sedes.js. Colores solo de tokens.css; el estado de la
 * sede manda el color (--success, --danger, --text-tertiary). */

/* Trama de puntos, contorno con brillo y nombres de region. */
.msedes-trama { fill: var(--border-subtle); }
.msedes-silueta-brillo {
  fill: none;
  stroke: var(--accent);
  stroke-width: 6;
  stroke-opacity: .18;
}
.msedes-region {
  fill: var(--text-disabled);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .3em;
  pointer-events: none;
}

/* Radar desde Cali: dos anillos que crecen desfasados y un barrido que gira (el giro
 * lo hace animateTransform en el SVG). */
.msedes-radar {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.2;
  animation: msedes-radar 4s ease-out infinite;
}
.msedes-radar-2 { stroke-width: 1; animation-delay: 2s; }
@keyframes msedes-radar {
  0% { r: 6; opacity: .55; }
  100% { r: 150; opacity: 0; }
}
.msedes-halo-0 { stop-color: var(--accent); stop-opacity: .35; }
.msedes-halo-1 { stop-color: var(--accent); stop-opacity: 0; }
.msedes-cuna-1 { stop-color: var(--accent); stop-opacity: .16; }
.msedes-cuna { fill: url(#msedes-cuna); }
.msedes-barrido { stroke: var(--accent); stroke-opacity: .45; stroke-width: 1.2; fill: none; }

/* Rutas desde Cali. La base siempre; encima, trafico que corre (en linea) o trazo
 * cortado (caida). */
.msedes-ruta {
  fill: none;
  stroke: var(--border);
  stroke-width: 1.2;
}
.msedes-flujo {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-dasharray: 3 9;
  animation: msedes-flujo 1.6s linear infinite;
}
@keyframes msedes-flujo { to { stroke-dashoffset: -48; } }
.msedes-ruta-caida {
  fill: none;
  stroke: var(--danger);
  stroke-opacity: .7;
  stroke-width: 1.4;
  stroke-dasharray: 2 6;
}

/* Ruta de la sede seleccionada: brillo desenfocado debajo y trafico encima. */
.msedes-ruta-sel-brillo { fill: none; stroke-width: 5; stroke-opacity: .5; }
.msedes-ruta-sel {
  fill: none;
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-dasharray: 3 9;
  animation: msedes-flujo 1.6s linear infinite;
}
.msedes-ruta-sel-brillo.msedes-e-ok, .msedes-ruta-sel.msedes-e-ok { stroke: var(--success); }
.msedes-ruta-sel-brillo.msedes-e-fallo, .msedes-ruta-sel.msedes-e-fallo { stroke: var(--danger); }
.msedes-ruta-sel-brillo.msedes-e-sin_monitoreo,
.msedes-ruta-sel.msedes-e-sin_monitoreo { stroke: var(--text-tertiary); }

/* Mira sobre la sede seleccionada: halo, dos pings, anillo que gira y cruz. */
.msedes-mira { color: var(--accent); pointer-events: none; }
.msedes-mira.msedes-e-ok { color: var(--success); }
.msedes-mira.msedes-e-fallo { color: var(--danger); }
.msedes-mira.msedes-e-sin_monitoreo { color: var(--text-tertiary); }
.msedes-ping {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.2;
  transform-box: fill-box;
  transform-origin: center;
  animation: msedes-ping 2.4s ease-out infinite;
}
.msedes-ping-2 { stroke-width: 1; animation-delay: 1.2s; }
@keyframes msedes-ping {
  0% { transform: scale(1); opacity: .75; }
  100% { transform: scale(3.4); opacity: 0; }
}
.msedes-giro {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-dasharray: 6 5;
  transform-box: fill-box;
  transform-origin: center;
  animation: msedes-giro 6s linear infinite;
}
@keyframes msedes-giro { to { transform: rotate(360deg); } }
.msedes-cruz { fill: none; stroke: currentColor; stroke-width: 1.4; }

/* Marcas: punto hueco con borde del estado, como el prototipo; nombre al lado. */
.msedes-marca .msedes-punto { fill: var(--bg-hundido); stroke-width: 2; }
.msedes-marca.msedes-e-ok .msedes-punto { fill: var(--bg-hundido); stroke: var(--success); }
.msedes-marca.msedes-e-fallo .msedes-punto { fill: var(--bg-hundido); stroke: var(--danger); }
.msedes-marca.msedes-e-sin_monitoreo .msedes-punto { fill: var(--bg-hundido); stroke: var(--text-tertiary); }
.msedes-marca .msedes-cuenta { fill: var(--text-primary); }
.msedes-sin-anillo {
  fill: none;
  stroke: var(--text-tertiary);
  stroke-width: 1;
  stroke-dasharray: 2 3;
}
.msedes-nombre {
  fill: var(--text-secondary);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  pointer-events: none;
}
/* Nombres reales de las sedes de un grupo, bajo su etiqueta. */
.msedes-nombre-sede {
  fill: var(--text-tertiary);
  font-family: var(--font-sans);
  font-size: 10px;
  pointer-events: none;
}
.msedes-nombre-sede-fallo { fill: var(--danger); font-weight: 600; }
.msedes-nombre-sel { fill: var(--text-primary); font-weight: 600; }
.msedes-marca.msedes-e-fallo .msedes-nombre { fill: var(--danger); }
.msedes-sel .msedes-punto { stroke-width: 2.5; }

/* Leyenda bajo el mapa. */
.msedes-leyenda {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  margin-top: var(--sp-3);
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}
.msedes-ley { display: inline-flex; align-items: center; gap: 6px; }
.msedes-ley-punto {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-tertiary);
}
.msedes-ley-punto.msedes-e-ok { background: var(--success); }
.msedes-ley-punto.msedes-e-fallo { background: var(--danger); }
/* Anillo punteado: se distingue de una caida sin depender del color. */
.msedes-ley-punto.msedes-e-intermitente {
  background: transparent; border: 2px dashed var(--warning);
}
.msedes-ley-linea {
  width: 18px;
  height: 0;
  border-top: 2px dashed var(--accent);
}
.msedes-ley-pos { margin-left: auto; color: var(--text-secondary); }

/* Nota bajo cada KPI. */
.msedes-kpi-n { font-size: var(--text-xs); color: var(--text-tertiary); margin-top: 2px; }

/* Columna derecha: detalle arriba, eventos recientes abajo. */
.msedes-lateral {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  min-width: 0;
}
.msedes-latido {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  margin-bottom: var(--sp-4);
  background: var(--bg-hundido);
  border: 1px solid var(--border-subtle);
  border-radius: var(--r-md);
  color: var(--text-primary);
}
.msedes-eventos-caja {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--sp-4);
}
.msedes-eventos {
  list-style: none;
  margin: var(--sp-2) 0 0;
  padding: 0;
  max-height: 320px;
  overflow-y: auto;
}
.msedes-eventos li + li { border-top: 1px solid var(--border-subtle); }
.msedes-evento {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-2) 0;
  background: none;
  border: none;
  color: var(--text-primary);
  font: inherit;
  font-size: var(--text-sm);
  text-align: left;
}
button.msedes-evento { cursor: pointer; }
button.msedes-evento:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  button.msedes-evento:hover { background: var(--bg-hover); }
}
.msedes-ev-punto {
  flex: none;
  width: 8px;
  height: 8px;
  margin-top: 5px;
  border-radius: 50%;
  background: var(--text-tertiary);
}
.msedes-ev-punto.msedes-e-ok { background: var(--success); }
.msedes-ev-punto.msedes-e-fallo { background: var(--danger); }
.msedes-ev-punto.msedes-e-degradado { background: var(--warning); }
.msedes-ev-punto.msedes-e-programado {
  background: var(--purple);
  box-shadow: 0 0 0 0 var(--purple-bg);
  animation: msedes-reinicio 3.2s ease-in-out infinite;
}
.msedes-chip.msedes-e-programado { color: var(--purple); background: var(--purple-bg); }
.msedes-chip.msedes-e-seguimiento { color: var(--purple); background: var(--purple-bg); margin-left: 4px; }
@keyframes msedes-reinicio {
  0%, 100% { box-shadow: 0 0 0 0 var(--purple-bg); }
  50% { box-shadow: 0 0 0 5px var(--purple-bg); }
}
.msedes-ev-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.msedes-ev-tit { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msedes-ev-hora { flex: none; font-size: var(--text-xs); color: var(--text-tertiary); }

/* Movimiento reducido (skill movimiento, apartado 7): menos y mas suave, no cero. El
 * barrido ya no se dibuja (lo decide el JS); el trafico corre lento, los anillos del
 * radar y los pings quedan como un latido de opacidad, y la mira deja de girar. */
@media (prefers-reduced-motion: reduce) {
  .msedes-flujo, .msedes-ruta-sel { animation-duration: 6s; }
  .msedes-radar { animation: msedes-latido-suave 4s ease infinite; r: 90; }
  .msedes-ping { animation: msedes-latido-suave 3s ease infinite; transform: scale(1.8); }
  .msedes-giro { animation: none; }
}
@keyframes msedes-latido-suave {
  0%, 100% { opacity: .1; }
  50% { opacity: .45; }
}

/* ── Fase B2 (30/10/2026): mapa montado una vez, camara y efectos del prototipo ─────
 * El SVG ya no se rehace en cada refresco: la camara, la mira y la ruta seleccionada
 * cambian por transiciones. Colores solo de tokens; el estado manda el color. */

#msedes-mapa { overflow: hidden; }
.msedes-oculta { display: none; }

/* Camara: escala y desplaza todo el mapa hacia la sede seleccionada. */
.msedes-camara {
  transform-box: view-box;
  transform-origin: 0 0;
  transition: transform .9s cubic-bezier(0.65, 0, 0.35, 1);
}
/* La mira se desliza entre sedes y la ruta cambia de forma (propiedad CSS `d`). */
.msedes-mira {
  transform-box: view-box;
  transform-origin: 0 0;
  transition: transform .6s cubic-bezier(0.23, 1, 0.32, 1);
}
.msedes-ruta-sel, .msedes-ruta-sel-brillo { transition: d .6s cubic-bezier(0.23, 1, 0.32, 1); }

/* Linea de escaneo que baja por el contorno, destellos y trazo de luz por la costa. */
.msedes-escaneo-1 { stop-color: var(--accent); stop-opacity: .10; }
.msedes-escaneo-2 { stop-color: var(--accent); stop-opacity: .45; }
.msedes-scan { animation: msedes-scan 7s linear infinite; }
@keyframes msedes-scan {
  0% { transform: translateY(-40px); opacity: 0; }
  10%, 90% { opacity: 1; }
  100% { transform: translateY(780px); opacity: 0; }
}
.msedes-destello { fill: var(--accent); animation: msedes-destello 3.2s ease-in-out infinite; }
@keyframes msedes-destello { 0%, 100% { opacity: .15; } 50% { opacity: .9; } }
.msedes-trazo {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 60 940;
  stroke-opacity: .8;
  animation: msedes-trazo 14s linear infinite;
}
@keyframes msedes-trazo { to { stroke-dashoffset: -1000; } }

/* Malla entre sedes vecinas. */
.msedes-malla {
  fill: none;
  stroke: var(--accent);
  stroke-opacity: .28;
  stroke-width: 1;
  stroke-dasharray: 4 6;
  animation: msedes-malla 3s linear infinite;
}
@keyframes msedes-malla { to { stroke-dashoffset: -30; } }
.msedes-malla-caida { stroke: var(--danger); stroke-opacity: .3; animation: none; }
.msedes-malla-muda { stroke: var(--text-tertiary); stroke-opacity: .25; animation: none; }

/* Paquetes que viajan por las rutas (el movimiento lo pone animateMotion). */
.msedes-paq { fill: var(--accent); }
.msedes-paq-vuelta { fill: var(--success); }
.msedes-paq-malla { fill: var(--accent); }
.msedes-paq-caido { fill: var(--danger); }

/* Marcas: ping escalonado en linea, anillo de alerta en fallo, rombo para la base. */
.msedes-ping-sede {
  fill: none;
  stroke: var(--success);
  stroke-width: 1.2;
  transform-box: fill-box;
  transform-origin: center;
  animation: msedes-ping 2.4s ease-out infinite;
}
.msedes-alerta {
  fill: none;
  stroke: var(--danger);
  stroke-width: 1.4;
  animation: msedes-alerta 1.4s ease-in-out infinite;
}
@keyframes msedes-alerta {
  0%, 100% { stroke-opacity: .9; transform: scale(1); }
  50% { stroke-opacity: .15; transform: scale(1.45); }
}
.msedes-alerta { transform-box: fill-box; transform-origin: center; }
.msedes-x { stroke: var(--danger); stroke-width: 1.8; stroke-linecap: round; }
.msedes-nodo {
  fill: var(--accent);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: .12em;
  pointer-events: none;
}

/* Boton de zoom de camara sobre el mapa. */
.msedes-mapa-caja { position: relative; }
.msedes-zoom {
  position: absolute;
  top: var(--sp-3);
  right: var(--sp-3);
  z-index: 1;
  padding: var(--sp-1) var(--sp-3);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  color: var(--text-secondary);
  font: inherit;
  font-size: var(--text-xs);
  cursor: pointer;
}
.msedes-zoom[aria-pressed="true"] { color: var(--accent); border-color: var(--accent-border); background: var(--accent-bg); }
.msedes-zoom:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  .msedes-zoom:hover { color: var(--text-primary); }
}

/* Capa de eventos: se representa una vez sobre la sede y se retira a los 6 s. */
.msedes-ev { pointer-events: none; }
.msedes-ev-caida { color: var(--danger); }
.msedes-ev-restauracion { color: var(--success); }
.msedes-ev-intermitencia { color: var(--warning); }
.msedes-ev-novedad { color: var(--info); }
.msedes-ev-anillo { fill: none; stroke: currentColor; stroke-width: 1.6; }
.msedes-ev-anillo, .msedes-ev-pop, .msedes-ev-sacude, .msedes-ev-cae {
  transform-box: fill-box;
  transform-origin: center;
}
.msedes-ev-fondo { fill: var(--bg-hundido); stroke: currentColor; stroke-width: 2; }
.msedes-ev-signo { fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.msedes-ev-cifra { fill: currentColor; font-family: var(--font-mono); font-size: 11px; font-weight: 600; }
.msedes-ev-hilo { stroke: currentColor; stroke-width: 1.2; stroke-opacity: .5; stroke-dasharray: 2 3; }
.msedes-ev-gota { fill: currentColor; }
.msedes-ev-punteado { stroke-dasharray: 3 4; }

.msedes-ev-onda { opacity: 0; animation: msedes-ev-onda 1.6s cubic-bezier(0.23, 1, 0.32, 1) 3 both; }
@keyframes msedes-ev-onda { 0% { transform: scale(.6); opacity: 1; } 100% { transform: scale(6); opacity: 0; } }
.msedes-ev-pop { animation: msedes-ev-pop .5s cubic-bezier(0.23, 1, 0.32, 1) both; }
@keyframes msedes-ev-pop {
  0% { transform: scale(0); opacity: 0; }
  60% { transform: scale(1.25); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
.msedes-ev-sacude { animation: msedes-ev-sacude .6s ease-in-out .5s 3; }
@keyframes msedes-ev-sacude {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-3px); } 30% { transform: translateX(3px); }
  45% { transform: translateX(-2px); } 60% { transform: translateX(2px); }
  75% { transform: translateX(-1px); }
}
.msedes-ev-implota { opacity: 0; animation: msedes-ev-implota .9s cubic-bezier(0.23, 1, 0.32, 1) both; }
@keyframes msedes-ev-implota {
  0% { transform: scale(4.5); opacity: 0; }
  40% { opacity: .9; }
  100% { transform: scale(1); opacity: 0; }
}
.msedes-ev-trazo { stroke-dasharray: 1; stroke-dashoffset: 1; animation: msedes-ev-trazo .5s ease-out .8s forwards; }
@keyframes msedes-ev-trazo { to { stroke-dashoffset: 0; } }
.msedes-ev-parpadeo { animation: msedes-ev-parpadeo 1.8s linear 2; }
@keyframes msedes-ev-parpadeo {
  0%, 100% { opacity: 1; } 8% { opacity: .1; } 12% { opacity: 1; } 30% { opacity: .2; }
  34% { opacity: .9; } 52% { opacity: .05; } 60% { opacity: 1; } 78% { opacity: .3; } 82% { opacity: 1; }
}
.msedes-ev-cae { animation: msedes-ev-cae 1s cubic-bezier(0.23, 1, 0.32, 1) both; }
@keyframes msedes-ev-cae {
  0% { transform: translateY(-150px); opacity: 0; }
  15% { opacity: 1; }
  70% { transform: translateY(0); }
  82% { transform: translateY(-7px); }
  100% { transform: translateY(0); }
}
.msedes-ev-ola { opacity: 0; animation: msedes-ev-ola 1.4s ease-out .8s 2 both; }
@keyframes msedes-ev-ola { 0% { transform: scale(.5); opacity: .9; } 100% { transform: scale(4.5); opacity: 0; } }

/* Movimiento reducido (skill movimiento, apartado 7): menos y mas suave, no cero. Sin
 * escaneo, trazo ni paquetes (no se dibujan, lo decide el JS); la camara y la mira
 * cambian con un fundido corto en vez de viajar; los eventos aparecen sin sacudida ni
 * caida y sus ondas quedan como un latido de opacidad. */
@media (prefers-reduced-motion: reduce) {
  .msedes-camara, .msedes-mira { transition-duration: .2s; transition-timing-function: ease; }
  .msedes-ruta-sel, .msedes-ruta-sel-brillo { transition: none; }
  .msedes-destello { animation-duration: 6s; }
  .msedes-malla { animation: none; }
  .msedes-ping-sede { animation: msedes-latido-suave 3s ease infinite; transform: scale(1.6); }
  .msedes-alerta { animation: msedes-latido-suave 2.4s ease infinite; }
  .msedes-ev-sacude, .msedes-ev-cae { animation: none; }
  .msedes-ev-pop { animation: msedes-ev-aparece .3s ease both; }
  .msedes-ev-onda, .msedes-ev-ola, .msedes-ev-implota, .msedes-ev-parpadeo {
    animation: msedes-latido-suave 2s ease 2;
    transform: scale(2);
  }
  .msedes-ev-trazo { animation: none; stroke-dashoffset: 0; }
}
@keyframes msedes-ev-aparece { from { opacity: 0; } to { opacity: 1; } }

/* ── Fase B3 (31/10/2026): animacion del mapa tal cual el prototipo ───────────────
 * Julian, 31/10: "copia la animacion tal cual del prototipo de Claude Design". Los
 * valores salen de jarvis-monitor.dc.html (clases jv-*). Lo que no es movimiento va
 * fuera del media query; los tiempos van dentro de no-preference para que los bloques
 * de movimiento reducido de arriba sigan mandando. */

/* El prototipo no tiene brillo desenfocado alrededor del contorno del pais. */
.msedes-silueta-brillo { display: none; }

/* Pulso de cada sede: disco relleno que crece y se apaga (jv-ping), no un anillo. */
.msedes-ping-sede { fill: var(--success); fill-opacity: .6; stroke: none; }

/* Paquetes: de ida casi blancos, de vuelta del color del flujo. */
.msedes-paq, .msedes-paq-malla { fill: var(--text-primary); }
.msedes-paq-vuelta { fill: var(--accent); }

/* Malla entre sedes: trazo corto y mas visible (jv-mesh). */
.msedes-malla { stroke-dasharray: 2 4; stroke-opacity: .35; }

/* Trazo de luz por la costa (jv-trace). */
.msedes-trazo { stroke-dasharray: 90 910; stroke-opacity: 1; }

@media (prefers-reduced-motion: no-preference) {
  .msedes-camara { transition: transform 1.6s cubic-bezier(.45, 0, .2, 1); }
  .msedes-mira { transition: transform 1.8s cubic-bezier(.45, 0, .2, 1); }
  .msedes-ruta-sel, .msedes-ruta-sel-brillo {
    transition: d 1.8s cubic-bezier(.45, 0, .2, 1), stroke 1.8s ease;
  }
  .msedes-scan { animation: msedes-scan 6s ease-in-out infinite; }
  .msedes-destello { animation-duration: 2.8s; }
  .msedes-trazo { animation-duration: 9s; }
  .msedes-malla:not(.msedes-malla-caida):not(.msedes-malla-muda) { animation-duration: 2.4s; }
  .msedes-alerta { animation-duration: 1.2s; }
}

/* Aviso flotante y destello del evento (prototipo: jv-toast y jv-flash) */
.msedes-destello-pantalla, .msedes-aviso {
  position: absolute;
  pointer-events: none;
}
.msedes-destello-pantalla { inset: 0; border-radius: inherit; overflow: hidden; }
.msedes-destello-luz { position: absolute; inset: 0; opacity: 0; }
.msedes-destello-caida {
  background: radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--danger) 38%, transparent) 0%, transparent 45%);
}
.msedes-destello-restauracion {
  background: radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--success) 30%, transparent) 0%, transparent 45%);
}
.msedes-aviso { top: var(--sp-3); left: var(--sp-3); max-width: 300px; z-index: 2; }
.msedes-aviso-caja {
  display: flex;
  gap: var(--sp-2);
  align-items: flex-start;
  padding: var(--sp-2) var(--sp-3);
  background: var(--bg-hundido);
  border: 1px solid currentColor;
  border-radius: var(--r-lg);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .5);
}
.msedes-aviso-icono {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, currentColor 14%, transparent);
}
.msedes-aviso-punto { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.msedes-aviso-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.msedes-aviso-tit {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .08em;
}
.msedes-aviso-det { font-size: var(--text-sm); color: var(--text-secondary); overflow-wrap: anywhere; }
@keyframes msedes-aviso-entra {
  from { transform: translateY(-14px) scale(.98); opacity: 0; }
  to { transform: none; opacity: 1; }
}
@keyframes msedes-destello-luz { 0% { opacity: 0; } 18% { opacity: 1; } 100% { opacity: 0; } }
@keyframes msedes-aviso-parpadeo { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: no-preference) {
  .msedes-aviso-caja { animation: msedes-aviso-entra .5s cubic-bezier(.2, .8, .3, 1) both; }
  .msedes-destello-luz { animation: msedes-destello-luz 1.4s ease-out both; }
  .msedes-aviso-punto { animation: msedes-aviso-parpadeo 1.2s ease-in-out infinite; }
}

/* ── Ajustes de Julian al prototipo (01/11/2026): geografia real y camara de cine ─────
 * Contorno, departamentos, rios, cordilleras y paises vecinos; vuelo de camara con
 * Web Animations (en el JS), vineta de enfoque, reticula que se cierra al llegar y
 * deriva lenta del mapa en la vista general. Solo tokens; el movimiento, dentro de
 * no-preference. */
.msedes-lienzo { position: relative; overflow: hidden; border-radius: var(--r-lg); }
.msedes-lienzo #msedes-mapa { transform-origin: 50% 50%; }

.msedes-grat { fill: none; stroke: var(--border-subtle); stroke-width: .6; stroke-dasharray: 2 4; }
.msedes-vecinos { fill: var(--bg-hundido); stroke: var(--border-subtle); stroke-width: .8; stroke-linejoin: round; }
.msedes-region-pais { fill: var(--text-disabled); opacity: .7; }
.msedes-region-cord { font-size: 9px; letter-spacing: .25em; }
.msedes-losa-sombra { fill: var(--bg-hundido); }
.msedes-cordillera { fill: var(--accent); opacity: .12; }
.msedes-relieve-linea { stroke: var(--text-tertiary); stroke-width: .8; }
.msedes-deps { fill: none; stroke: var(--border-subtle); stroke-width: .7; stroke-linejoin: round; }
.msedes-rios { fill: none; stroke: var(--accent); stroke-width: 1; stroke-linecap: round;
  stroke-linejoin: round; opacity: .45; }
.msedes-contorno { fill: none; stroke: var(--border-strong); stroke-width: 1.3; stroke-linejoin: round; }
.msedes-silueta-brillo { display: block; fill: var(--accent); opacity: .08; }

/* Viñeta de enfoque: oscurece el entorno cuando la camara llega a la sede. */
.msedes-vineta {
  position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: radial-gradient(circle at 50% 50%, transparent 24%, var(--bg-hundido) 82%);
  transition: opacity 1.4s cubic-bezier(.22, 1, .36, 1);
}
.msedes-lienzo.msedes-cerca:not(.msedes-volando) .msedes-vineta { opacity: .72; }

/* Reticula de enfoque: cuatro esquinas que se cierran sobre la sede. */
.msedes-reticula {
  position: absolute; left: 50%; top: 50%; width: 76px; height: 76px; margin: -38px 0 0 -38px;
  pointer-events: none; opacity: 0;
}
.msedes-reticula span { position: absolute; width: 14px; height: 14px; border: 0 solid var(--accent); }
.msedes-reticula span:nth-child(1) { left: 0; top: 0; border-left-width: 2px; border-top-width: 2px; }
.msedes-reticula span:nth-child(2) { right: 0; top: 0; border-right-width: 2px; border-top-width: 2px; }
.msedes-reticula span:nth-child(3) { left: 0; bottom: 0; border-left-width: 2px; border-bottom-width: 2px; }
.msedes-reticula span:nth-child(4) { right: 0; bottom: 0; border-right-width: 2px; border-bottom-width: 2px; }
.msedes-lienzo.msedes-volando .msedes-reticula { display: none; }

@media (prefers-reduced-motion: no-preference) {
  /* El vuelo lo hace Web Animations: la transicion CSS de la camara competiria con el. */
  .msedes-camara { transition: none; }
  @keyframes msedes-deriva {
    0%, 100% { transform: scale(1) translate(0, 0); }
    50% { transform: scale(1.03) translate(-.5%, .4%); }
  }
  .msedes-lienzo:not(.msedes-cerca) #msedes-mapa { animation: msedes-deriva 26s ease-in-out infinite; }
  @keyframes msedes-cierre {
    0% { transform: scale(1.9) rotate(45deg); opacity: 0; }
    28% { transform: scale(1) rotate(0deg); opacity: 1; }
    75% { opacity: 1; }
    100% { transform: scale(1.08); opacity: .25; }
  }
  .msedes-reticula.msedes-reticula-on { animation: msedes-cierre 3.2s cubic-bezier(.22, 1, .36, 1) forwards; }
}
@media (prefers-reduced-motion: reduce) {
  .msedes-reticula.msedes-reticula-on { opacity: .6; }
}

/* Grupo con sedes caidas: el rojo queda en la insignia, no en toda la marca. */
.msedes-insignia { fill: var(--danger); stroke: var(--bg); stroke-width: 1; pointer-events: none; }
.msedes-cuenta.msedes-cuenta-ancha { font-size: 8px; }

/* ── Gráfica de latencia, barra de 24 h y registro de pings (detalle de sede) ── */
.msedes-grafica { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.msedes-gr-svg { width: 100%; height: auto; display: block; }
.msedes-gr-eje { stroke: var(--border); stroke-width: 1; }
.msedes-gr-linea { fill: none; stroke: var(--accent); stroke-width: 1.5; stroke-linejoin: round; }
.msedes-gr-fallo { stroke: var(--danger); stroke-width: 2; opacity: .55; }
.msedes-gr-txt { fill: var(--text-tertiary); font-size: 8px; font-family: var(--font-mono); }
.msedes-gr-zona { fill: transparent; }
.msedes-gr-zona:hover { fill: var(--accent-bg); }
.msedes-b24 { display: grid; grid-template-columns: repeat(24, minmax(0, 1fr)); gap: 2px; }
.msedes-b24-t { height: 14px; border-radius: 2px; background: var(--border-subtle); }
.msedes-b24-ok { background: var(--success); }
.msedes-b24-med { background: var(--warning); }
.msedes-b24-mal { background: var(--danger); }
.msedes-registro summary { cursor: pointer; padding: var(--sp-1) 0; }

/* Intermitente en el mapa: anillo punteado ambar alrededor de una marca que no esta
 * caida. Se distingue del rojo por la forma (punteado), no solo por el color. */
.msedes-inter-anillo {
  fill: none;
  stroke: var(--warning);
  stroke-width: 1.8;
  stroke-dasharray: 3 3;
}
.msedes-marca.msedes-inter .msedes-nombre { fill: var(--warning); }

/* Cortes por hora en el detalle de sede. */
.msedes-cortes { display: grid; grid-template-columns: repeat(24, minmax(0, 1fr)); gap: 2px; height: 36px; }
.msedes-cortes-c { display: flex; align-items: flex-end; border-bottom: 1px solid var(--border-subtle); }
.msedes-cortes-b { display: block; width: 100%; border-radius: 2px 2px 0 0; background: var(--border-subtle); }
.msedes-cortes-b.msedes-cortes-hay { background: var(--warning); outline: 1px dashed var(--warning); outline-offset: 1px; }

/* ── Empresas (02/11/2026) ─────────────────────────────────────────────────────
   Panel junto al mapa, por gravedad. El estado se dice con forma y con texto, no solo
   con color: caida = rombo, intermitente = anillo punteado, sin monitoreo = anillo hueco. */
.msedes-empresas-caja {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--sp-4);
}
.msedes-empresas {
  list-style: none;
  margin: var(--sp-2) 0 0;
  padding: 0;
}
.msedes-empresas li + li { border-top: 1px solid var(--border-subtle); }
.msedes-emp {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-2) var(--sp-1);
  background: none;
  border: none;
  border-left: 3px solid transparent;
  color: var(--text-primary);
  font: inherit;
  font-size: var(--text-sm);
  text-align: left;
  cursor: pointer;
}
.msedes-emp:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.msedes-emp.msedes-emp-activa { background: var(--bg-hover); border-left-color: var(--accent); }
@media (hover: hover) and (pointer: fine) {
  .msedes-emp:hover { background: var(--bg-hover); }
}
.msedes-emp-siglas {
  flex: none;
  min-width: 34px;
  padding: 2px 4px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-size: var(--text-xs);
  font-weight: 600;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.msedes-emp-texto { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.msedes-emp-nombre { overflow-wrap: anywhere; }
.msedes-emp-cuenta { font-size: var(--text-xs); color: var(--text-tertiary); }
.msedes-emp-puntos { display: flex; flex-wrap: wrap; gap: 5px; padding-top: 2px; }
.msedes-emp-estado { flex: none; font-size: var(--text-xs); color: var(--text-secondary); }
.msedes-ee-caida_total .msedes-emp-estado,
.msedes-ee-caida_parcial .msedes-emp-estado { color: var(--danger); }
.msedes-ee-intermitente .msedes-emp-estado { color: var(--warning); }
.msedes-ee-en_linea .msedes-emp-estado { color: var(--success); }

.msedes-emp-punto { display: inline-block; width: 10px; height: 10px; box-sizing: border-box; }
.msedes-ep-ok { border-radius: 50%; background: var(--success); }
.msedes-ep-fallo { background: var(--danger); transform: rotate(45deg) scale(.85); }
.msedes-ep-intermitente { border-radius: 50%; border: 2px dashed var(--warning); background: radial-gradient(circle, var(--warning) 0 25%, transparent 30%); }
.msedes-ep-sin_monitoreo { border-radius: 50%; border: 2px solid var(--text-tertiary); }

/* Siglas dentro del nodo y X de la sede caida en su insignia. */
.msedes-siglas { fill: var(--text-primary); font-weight: 600; pointer-events: none; }
.msedes-x-insignia { stroke: var(--bg); stroke-width: 1.2; stroke-linecap: round; fill: none; pointer-events: none; }
/* Hover o foco en la empresa: anillo en sus nodos. Filtro: lo demas se apaga un poco. */
.msedes-marca.msedes-resalta .msedes-punto { stroke: var(--accent); stroke-width: 3; }
.msedes-marca.msedes-fuera:not(.msedes-e-fallo) { opacity: .35; }   /* una caida nunca se atenua */

/* Movil: filas algo mas holgadas. La lista no lleva tope de alto en ningun ancho: con tope
   se ocultaban empresas (a 1440 px, 5 de 10) sin ninguna pista de que habia mas. */
@media (max-width: 900px) {
  .msedes-emp { padding: var(--sp-3) var(--sp-1); }
}
