:root {
  --bg: #0d1117;
  --panel: #161b22;
  --panel2: #0d1117;
  --line: #21262d;
  --line-strong: #30363d;
  --text: #e6edf3;
  --muted: #8b949e;
  --accent: #2f81f7;
  --accent-ink: #6cb6ff;   /* acento legible como TEXTO sobre el fondo del tema */
  --fiber: #ff7b00;
  --ok: #3fb950;
  --ok-ink: #3fb950;
  --warn-ink: #d29922;
  --bad: #f85149;          /* rojo para FONDOS/sólidos */
  --bad-ink: #f85149;      /* rojo legible como TEXTO */
  --grad: linear-gradient(135deg,#2f81f7,#7c3aed); /* gradiente de marca (botones primarios) */
  --overlay: rgba(0,0,0,.55);
  --shadow-1: 0 2px 8px #0006;
  --shadow-2: 0 8px 28px #0008;
  --shadow-3: 0 12px 44px #000a;
}
/* Tema claro (DEFAULT; toggle 🌓 vuelve al oscuro; no afecta el mapa ni los
   colores semánticos). Tokens calibrados al tema claro frío de MAS-WISP. */
body.light {
  --bg: #eef3f7;
  --panel: #ffffff;
  --panel2: #f5f9fb;
  --line: #e3eaf0;
  --line-strong: #cfdbe4;
  --text: #14303a;
  --muted: #54707c;
  --accent: #2f9fe0;
  --accent-ink: #1a72ac;
  --fiber: #9a5a0e;        /* ámbar tinta: legible sobre claro (marca/realces de texto) */
  --ok: #14b8a6;
  --ok-ink: #0a766a;
  --warn-ink: #9a5a0e;
  --bad: #f0626d;
  --bad-ink: #c41f2d;
  --grad: linear-gradient(135deg,#14b8a6,#2f9fe0);
  --overlay: rgba(20,48,58,.38);
  --shadow-1: 0 2px 8px rgba(20,48,58,.12);
  --shadow-2: 0 8px 28px rgba(20,48,58,.16);
  --shadow-3: 0 12px 44px rgba(20,48,58,.20);
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; font-family: 'Hanken Grotesk', system-ui, -apple-system, Segoe UI, Roboto, sans-serif; background: var(--bg); color: var(--text); }
button, input, select, textarea { font-family: inherit; }
/* Tipografía de display (títulos) y técnica (mono), estilo MAS-WISP */
h1, h2, h3, h4, .brand, .login-card h1, .info-title, .edit-title {
  font-family: 'Bricolage Grotesque', 'Hanken Grotesk', system-ui, sans-serif; }
.menu-sec, .tools-cat-h, .acc-h, .kpi-l, .info-type, .info-actions-h, .trace-step .tag,
.tree-node .tag, .catalog-list th, .dash-card .lbl, .search-results .res .k,
.search-results .res-sep, .sidebar h3 {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .15em; }
.hidden { display: none !important; }

/* ---- Login ---- */
.login-screen { height: 100%; display: grid; place-items: center;
  background: radial-gradient(1200px 600px at 50% -10%, #14315c, var(--bg)); }
body.light .login-screen { background: radial-gradient(1200px 600px at 50% -10%, #d8ecf1, var(--bg)); }
.login-card { width: 320px; background: var(--panel); border: 1px solid var(--line);
  border-radius: 12px; padding: 28px; display: flex; flex-direction: column; gap: 12px; box-shadow: var(--shadow-2); }
.login-card h1 { margin: 0; font-size: 26px; letter-spacing: 1px; }
.login-card h1 span { color: var(--fiber); }
.subtitle { margin: 0 0 8px; color: var(--muted); font-size: 13px; }
.login-card input { background: var(--bg); border: 1px solid var(--line); color: var(--text);
  padding: 10px 12px; border-radius: 7px; font-size: 14px; }
.login-card button { background: var(--grad); color: white; border: 0; padding: 11px;
  border-radius: 7px; font-weight: 600; cursor: pointer; }
.error { color: var(--bad-ink); font-size: 13px; min-height: 16px; }

/* ---- App ---- */
.app { height: 100%; position: relative; display: grid;
  grid-template-columns: 240px 1fr; grid-template-rows: 56px 1fr;
  grid-template-areas: "top top" "side map"; }
.topbar { grid-area: top; display: flex; align-items: center; gap: 20px;
  padding: 0 18px; background: var(--panel); border-bottom: 1px solid var(--line); }
.brand { font-weight: 700; letter-spacing: 1px; }
.brand span { color: var(--fiber); }
.kpis { display: flex; gap: 18px; flex: 1; font-size: 13px; color: var(--muted); flex-wrap: wrap; }
.kpis b { color: var(--text); }
.ghost { background: transparent; border: 1px solid var(--line); color: var(--text);
  padding: 7px 14px; border-radius: 8px; cursor: pointer; }
.sidebar { grid-area: side; background: var(--panel); border-right: 1px solid var(--line);
  padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.sidebar h3 { margin: 0 0 6px; font-size: 13px; text-transform: uppercase; color: var(--muted); }
.sidebar label { display: flex; align-items: center; gap: 8px; font-size: 14px; cursor: pointer; }
.sidebar label .dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 10px; }
.hint { margin-top: auto; font-size: 12px; color: var(--muted); }
/* Fondo gris neutro mientras cargan los tiles */
#map { grid-area: map; background: #c8d2dc; }
/* Modo presentación: solo el mapa (demos / capturas) */
.app.presentation { grid-template-columns: 1fr; grid-template-rows: 1fr; grid-template-areas: "map"; }
.app.presentation .topbar, .app.presentation .sidebar, .app.presentation #tbToggles { display: none; }
#presExit { position: absolute; top: 10px; right: 10px; z-index: 1200; display: none;
  background: var(--panel); color: var(--text, #c9d1d9); border: 1px solid var(--line);
  border-radius: 7px; padding: 6px 10px; font-size: 12px; cursor: pointer; box-shadow: var(--shadow-1); }
.app.presentation #presExit { display: block; }
.maplibregl-map { background: #c8d2dc; }
/* Popups de MapLibre con tema oscuro */
.maplibregl-popup-content { background: var(--panel); color: var(--text);
  border: 1px solid var(--line); border-radius: 8px; font-size: 13px; padding: 10px 12px; }
.maplibregl-popup-anchor-top .maplibregl-popup-tip,
.maplibregl-popup-anchor-top-left .maplibregl-popup-tip,
.maplibregl-popup-anchor-top-right .maplibregl-popup-tip { border-bottom-color: var(--panel); }
.maplibregl-popup-anchor-bottom .maplibregl-popup-tip,
.maplibregl-popup-anchor-bottom-left .maplibregl-popup-tip,
.maplibregl-popup-anchor-bottom-right .maplibregl-popup-tip { border-top-color: var(--panel); }
.maplibregl-popup-anchor-left .maplibregl-popup-tip { border-right-color: var(--panel); }
.maplibregl-popup-anchor-right .maplibregl-popup-tip { border-left-color: var(--panel); }
.maplibregl-popup-close-button { color: var(--text); font-size: 16px; padding: 0 6px; }
.maplibregl-popup-content button.trace-btn { margin-top: 8px; background: var(--accent);
  color: #fff; border: 0; padding: 6px 10px; border-radius: 6px; cursor: pointer; font-size: 12px; }

/* Barra de acciones del popup: botones de ícono en horizontal con tooltip */
.pop-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px;
  padding-top: 9px; border-top: 1px solid color-mix(in srgb, var(--line) 70%, transparent); }
.pop-btn { --pa: var(--accent); width: 36px; height: 36px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center; font-size: 17px; line-height: 1;
  border: 1px solid color-mix(in srgb, var(--pa) 45%, transparent);
  background: color-mix(in srgb, var(--pa) 15%, var(--panel)); color: #fff;
  border-radius: 11px; cursor: pointer; box-shadow: 0 1px 2px #0003, inset 0 1px 0 #ffffff14;
  transition: transform .11s ease, box-shadow .16s ease, background .16s ease, border-color .16s ease; }
.pop-btn:hover { background: var(--pa); transform: translateY(-2px); border-color: var(--pa);
  box-shadow: 0 5px 14px color-mix(in srgb, var(--pa) 55%, transparent); }
.pop-btn:active { transform: translateY(0); box-shadow: 0 1px 3px #0005; }
.pop-btn:focus-visible { outline: 2px solid var(--pa); outline-offset: 2px; }
/* En claro el fondo del botón es casi blanco: el glifo/texto va en tinta, y
   vuelve a blanco cuando el hover pinta el fondo con el color pleno. */
body.light .pop-btn { color: var(--text); box-shadow: var(--shadow-1); }
body.light .pop-btn:hover { color: #fff; }
/* "⋯ Más" y el contenedor de acciones secundarias del popup */
.pop-more.open { background: var(--accent); color: #fff; border-color: var(--accent); }
.pop-extra { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 8px; padding-top: 8px;
  border-top: 1px solid color-mix(in srgb, var(--line) 70%, transparent); }
.base-select { width: 100%; background: var(--bg); border: 1px solid var(--line);
  color: var(--text); padding: 7px 9px; border-radius: 7px; font-size: 13px; }
/* Selector con filtro activo (proyecto/zona): resaltado para no perder contexto */
.base-select.filtered { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--bg)); font-weight: 600; }
/* Iconos emoji en el mapa (Leaflet divIcon) */
.emoji-icon { background: none !important; border: none !important; }
.emoji-pin { font-size: 20px; line-height: 26px; display: block; text-align: center;
  filter: drop-shadow(0 1px 1px rgba(0,0,0,.5)); }
/* Planta interna de la manga/mufa */
.cl-form { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; margin-bottom: 12px; }
.cl-form-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: end; margin-top: 8px; }
.cl-form-row label { display: flex; flex-direction: column; font-size: 11px; color: var(--muted); gap: 2px; }
.cl-form-row select, .cl-form-row input { background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 6px; padding: 5px 6px; font-size: 12px; }
.cl-amp { align-self: center; font-size: 16px; color: var(--muted); }
.cl-tray { border: 1px solid var(--line); border-radius: 8px; margin-bottom: 10px; overflow: hidden; }
.cl-tray-h { background: var(--panel); padding: 7px 10px; font-size: 13px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.cl-tray-h small { color: var(--muted); font-weight: 400; }
.cl-splice { display: flex; align-items: center; gap: 5px; padding: 6px 10px; font-size: 13px; border-top: 1px solid var(--line); }
.cl-empty { padding: 6px 10px; color: var(--muted); font-size: 12px; }
.cl-x { margin-left: auto; background: transparent; border: 0; color: var(--bad-ink); cursor: pointer; font-size: 15px;
  border-radius: 7px; padding: 1px 5px; transition: background .12s; }
.cl-x:hover { background: color-mix(in srgb, var(--bad) 18%, transparent); }
/* Botones de los paneles internos (manga/NAP): look moderno + hover con acento */
.cl-mini { font-size: 11px; padding: 3px 8px; margin-left: 4px; cursor: pointer; border-radius: 8px;
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--line)); background: color-mix(in srgb, var(--accent) 8%, var(--bg));
  color: var(--text); transition: background .13s, transform .1s, border-color .13s; }
.cl-mini:hover { background: var(--accent); color: #fff; border-color: var(--accent); transform: translateY(-1px); }
.cl-mini:active { transform: translateY(0); }
.cl-outs { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 10px; }
.cl-out { font-size: 11px; padding: 3px 7px; border-radius: 6px; border: 1px solid var(--line); background: var(--bg); display: inline-flex; align-items: center; gap: 3px; }
.cl-out.ocupado { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, transparent); }
.cl-out.editing { background: var(--panel); }
.cl-out select { background: var(--bg); color: var(--text); border: 1px solid var(--line); border-radius: 5px; font-size: 11px; }
/* Pin de imagen (iconos subidos en un paquete) */
.img-pin { width: 26px; height: 26px; object-fit: contain; display: block;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.5)); }
.img-icon { display: inline-block; }
.icon-pack-preview { margin-top: 10px; }
.icon-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.icon-grid label { flex-direction: row !important; align-items: center; gap: 6px; }
.icon-grid input { width: 46px; text-align: center; font-size: 16px; }
/* Paletas de color */
.palette-row { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 6px; }
.swatch { width: 28px; height: 28px; border-radius: 50%; border: 2px solid var(--line); cursor: pointer; }
.swatch:hover { border-color: var(--text); }
.theme-sw { width: 42px; height: 30px; border-radius: 6px; border: 2px solid var(--line); cursor: pointer; display: grid; place-items: center; padding: 0; }
.theme-sw:hover { outline: 2px solid var(--accent); }
.theme-sw span { width: 14px; height: 14px; border-radius: 50%; display: block; border: 1px solid #0006; }
/* Selector de iconos (paleta) */
.icon-picker { display: flex; flex-wrap: wrap; gap: 4px; max-height: 120px; overflow: auto;
  background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 6px; }
.icon-picker .ic { width: 30px; height: 30px; display: grid; place-items: center; font-size: 18px;
  border-radius: 6px; cursor: pointer; border: 2px solid transparent; }
.icon-picker .ic:hover { background: var(--line); }
.icon-picker .ic.sel { border-color: var(--accent); background: var(--line); }
.icon-lib-grid { display: flex; flex-wrap: wrap; gap: 6px; }
.icon-lib-grid .ic { width: 34px; height: 34px; display: grid; place-items: center; font-size: 20px;
  border: 1px solid var(--line); border-radius: 6px; position: relative; }
.icon-lib-grid .ic button { position: absolute; top: -6px; right: -6px; background: var(--bad); color: #fff;
  border: 0; border-radius: 50%; width: 16px; height: 16px; font-size: 10px; cursor: pointer; line-height: 1; }

/* Panel de trazado / impacto */
.trace-panel { position: absolute; top: 100px; right: 14px; width: 320px; max-height: 78vh;
  overflow: auto; background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
  padding: 16px; box-shadow: var(--shadow-2); z-index: 1000; }
.trace-close { position: absolute; top: 8px; right: 10px; background: transparent; border: 0;
  color: var(--muted); font-size: 20px; cursor: pointer; }
.trace-panel h4 { margin: 0 0 10px; font-size: 15px; }
.trace-step { display: flex; gap: 8px; align-items: baseline; padding: 6px 0; border-bottom: 1px solid var(--line); }
.trace-step .tag { font-size: 10px; text-transform: uppercase; color: var(--muted); min-width: 62px; }
.trace-step b { color: var(--text); }
.trace-step small { color: var(--muted); }
.impact-kpi { font-size: 13px; color: var(--muted); margin: 4px 0 10px; }
.impact-kpi b { color: var(--fiber); font-size: 18px; }
/* Campo obligatorio (asterisco rojo) */
.req { color: var(--bad-ink); font-weight: 700; }
/* Spinner de carga: agregar la clase "loading" a un elemento con texto de carga */
@keyframes dfm-spin { to { transform: rotate(360deg); } }
.loading::before { content: ''; display: inline-block; width: 12px; height: 12px; margin-right: 8px;
  vertical-align: -2px; border: 2px solid var(--line); border-top-color: var(--accent); border-radius: 50%;
  animation: dfm-spin .7s linear infinite; }
.impact-item { font-size: 13px; padding: 4px 0; border-bottom: 1px solid var(--line); }
.impact-item .st { float: right; font-size: 11px; color: var(--muted); }

/* ── Tarjeta de equipo del nodo: jerarquía visual de 3 niveles ────────────── */
/* --eq-c = color de la categoría (ancla visual por tipo de equipo). */
.eq-card { --eq-c: #64748b; background: var(--panel); border: 1px solid var(--line);
  border-left: 4px solid var(--eq-c); border-radius: 12px; padding: 16px 18px;
  margin-bottom: 12px; box-shadow: var(--shadow-1); }
.eq-head { display: flex; align-items: flex-start; gap: 13px; }
/* Iconografía de anclaje: icono representativo en la esquina superior izquierda. */
.eq-icon { flex: 0 0 auto; width: 40px; height: 40px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center; font-size: 21px; line-height: 1;
  background: color-mix(in srgb, var(--eq-c) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--eq-c) 34%, transparent); }
.eq-titlewrap { flex: 1 1 auto; min-width: 0; }
/* Título: lectura rápida — negrita y mayor tamaño. */
.eq-title { font-size: 16px; font-weight: 700; color: var(--text); line-height: 1.25;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.eq-cat { font-size: 9.5px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase;
  color: var(--eq-c); background: color-mix(in srgb, var(--eq-c) 15%, transparent);
  padding: 2px 7px; border-radius: 5px; }
/* Metadatos: detalle secundario en texto pequeño y gris. */
.eq-meta { margin-top: 5px; font-size: 11.5px; color: var(--muted); line-height: 1.5;
  display: flex; align-items: center; gap: 5px 9px; flex-wrap: wrap; }
.eq-meta .dot { opacity: .5; }
.eq-actions { flex: 0 0 auto; display: inline-flex; gap: 5px; }
.eq-toolrow { margin: 13px 0 0; display: flex; flex-wrap: wrap; gap: 6px; }
.eq-body { margin-top: 12px; }
.eq-body:empty { display: none; }

/* ── RackContainer: chasis vertical rígido de 19" con unidades de rack (U) ── */
.rack-wrap { display: inline-flex; flex-direction: column; gap: 8px; }
.rack-title { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 700; }
.rack-title small { color: var(--muted); font-weight: 500; }
.rack-face-sw { display: inline-flex; border: 1px solid var(--line-strong); border-radius: 8px; overflow: hidden; }
.rack-face-sw button { border: 0; background: var(--panel2); color: var(--muted); font-size: 12px;
  padding: 4px 12px; cursor: pointer; font-weight: 600; }
.rack-face-sw button.on { background: var(--accent); color: #fff; }
/* El chasis: dos rieles metálicos + área de U. Ancho fijo (emula 19"). */
.rack-frame { position: relative; display: grid; grid-template-columns: 26px 1fr 26px;
  width: 320px; background: linear-gradient(180deg, #1a1f27, #10141a); border: 2px solid #3a4250;
  border-radius: 8px; padding: 8px 0; box-shadow: inset 0 0 22px #0009, 0 6px 20px #0006; }
.rack-frame.rear { background: linear-gradient(180deg, #201a1a, #171012); border-color: #4a3a3a; }
.rack-rail { display: flex; flex-direction: column; background: #0c0f14;
  border-left: 1px solid #ffffff10; border-right: 1px solid #ffffff10; }
.rack-rail.left { border-left: 0; } .rack-rail.right { border-right: 0; }
.rack-u-num { display: flex; align-items: center; justify-content: center; font-size: 8.5px;
  color: #6b7688; font-family: var(--mono, monospace); border-bottom: 1px solid #ffffff08; }
.rack-slots { position: relative; background:
  repeating-linear-gradient(180deg, #0d1117 0, #0d1117 calc(var(--u) - 1px), #ffffff10 var(--u)); }
.rack-eq { position: absolute; left: 3px; right: 3px; border-radius: 4px; overflow: hidden;
  cursor: pointer; box-shadow: 0 1px 3px #0008; border-left: 4px solid var(--eqc, #888); }
.rack-eq .re-label { font-size: 10px; color: #fff; font-weight: 600; padding: 2px 5px;
  display: flex; align-items: center; gap: 5px; white-space: nowrap; }
.rack-eq .re-label small { color: #b9c2d0; font-weight: 500; }
.rack-empty-note { font-size: 11.5px; color: var(--muted); }
.rack-u-free { position: absolute; left: 3px; right: 3px; border: 1px dashed #ffffff1a;
  border-radius: 3px; cursor: pointer; }
.rack-u-free:hover { background: color-mix(in srgb, var(--accent) 18%, transparent); border-color: var(--accent); }

/* ── Faceplate del equipo: etiqueta arriba-izquierda + puertos debajo ──────── */
.fp { background: linear-gradient(180deg, #2b3038 0%, #1c2027 55%, #14171d 100%); min-height: 100%; width: 100%; }
/* Layout vertical: etiqueta (nombre+modelo) arriba, rejilla de puertos debajo. */
.fp-v { display: flex; flex-direction: column; overflow: visible; }
/* Equipo que CRECE con su contenido en modo panel (se muestra completo aunque
   exceda su altura en U; ej. EDFA con UPC/APC/PUMP apilados). */
.rack-eq.grow { overflow: visible; height: auto; }
.rack-eq.grow:hover { z-index: 6; }
.fp-label { flex: 0 0 auto; display: flex; align-items: baseline; gap: 5px; padding: 1px 6px;
  background: linear-gradient(180deg, #363d48, #2a303a); border-bottom: 1px solid #ffffff14; }
.fp-name { font-size: 9px; font-weight: 700; color: #eef2f7; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fp-model { font-size: 7px; color: #96a2b3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fp-ports-v { flex: 1 1 auto; display: flex; flex-wrap: wrap; align-items: flex-start; align-content: flex-start;
  gap: 3px 7px; padding: 3px 5px; }
/* Rejilla de puertos según el layout configurado en el área de equipos. */
.fp-grid { display: grid; gap: 1.5px; width: max-content; }
.fp-card { display: flex; flex-direction: column; gap: 1px; }
.fp-card-h { font-size: 7px; color: #8ea0b6; font-weight: 600; white-space: nowrap; line-height: 1.1; }
/* PDU: tomas con forma de enchufe + voltaje de salida en la etiqueta. */
.fp-pdu { display: flex; flex-direction: column; gap: 2px; }
.fp-outlets { display: flex; flex-wrap: wrap; gap: 5px; }
.pdu-outlet-wrap { display: flex; flex-direction: column; align-items: center; gap: 1px; }
.pdu-outlet { width: 15px; height: 15px; border-radius: 50%; border: 1.5px solid #b78a12; padding: 0;
  background: radial-gradient(circle at 50% 42%, #3a3320, #17140c); cursor: pointer; position: relative; }
/* Dos clavijas de la toma (tipo Schuko / NEMA). */
.pdu-outlet::before, .pdu-outlet::after { content: ''; position: absolute; top: 4px; width: 1.5px; height: 6px;
  background: #eab308; border-radius: 1px; }
.pdu-outlet::before { left: 5px; } .pdu-outlet::after { right: 5px; }
.pdu-outlet.linked { border-color: #22c55e; box-shadow: 0 0 5px #22c55e88; }
.pdu-outlet.linked::before, .pdu-outlet.linked::after { background: #22c55e; }
/* Toma que supera su límite físico seguro (80% de 10A/15A…): en rojo. */
.pdu-outlet.over { border-color: #ef4444; box-shadow: 0 0 6px #ef4444; }
.pdu-outlet.over::before, .pdu-outlet.over::after { background: #ef4444; }
.pdu-outlet:hover { outline: 1.5px solid #fff; }
.pdu-v { font-size: 6.5px; color: #d4b24a; font-weight: 700; line-height: 1; }
.pdu-v.over { color: #ef4444; }
.fp-port { width: 6px; height: 6px; padding: 0; border: 1px solid #00000066; border-radius: 1.5px;
  cursor: pointer; transition: outline .05s; }
.fp-port:hover { outline: 1.5px solid #fff; z-index: 3; position: relative; }
.fp-port.sel { outline: 2px solid #fff; }
/* Zoom cercano: puerto con número + borde por conector (UPC azul / APC verde). */
.fp-port-lg { width: 13px; height: 11px; border-width: 1.5px; border-radius: 2px; font-size: 7px;
  font-weight: 700; color: #fff; display: flex; align-items: center; justify-content: center;
  text-shadow: 0 1px 1px #0009; }

/* Barra de calor de ocupación del rack (visible sobre todo en zoom lejano). */
.rack-heat { display: flex; align-items: center; gap: 8px; margin: -2px 0 2px; max-width: 320px; }
.rack-heat-bar { flex: 1 1 auto; height: 7px; border-radius: 4px; background: #ffffff14; overflow: hidden; }
.rack-heat-bar span { display: block; height: 100%; border-radius: 4px; }
.rack-heat-txt { font-size: 10.5px; color: var(--muted); white-space: nowrap; }

/* ── Dashboard de energía del rack (termómetro de carga) ──────────────────── */
.pwr-dash { flex: 0 0 auto; width: 96px; border: 1px solid var(--line-strong); border-radius: 10px;
  padding: 8px 6px; background: linear-gradient(180deg, #12161c, #0c0f14); display: flex;
  flex-direction: column; align-items: center; gap: 4px; }
.pwr-h { font-size: 10px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .3px; }
.pwr-thermo { position: relative; width: 20px; border-radius: 10px; background: #0c0f14;
  border: 1px solid #2a3340; overflow: hidden; display: flex; align-items: flex-end; }
.pwr-fill { width: 100%; border-radius: 0 0 9px 9px; transition: height .3s; }
.pwr-mark { position: absolute; left: -3px; right: -3px; height: 0; border-top: 1px dashed #ffffff40; z-index: 2; }
.pwr-mark.red { border-top-color: #ef444488; }
.pwr-pct { font-size: 16px; font-weight: 800; line-height: 1; }
.pwr-kv { font-size: 11px; color: var(--text); } .pwr-kv b { font-size: 13px; }
.pwr-kv2 { font-size: 9px; color: var(--muted); text-align: center; }
.pwr-state { font-size: 10px; font-weight: 700; }
.pwr-none { font-size: 10px; color: var(--muted); text-align: center; margin-top: 8px; }
.pwr-redun { font-size: 8.5px; color: #f59e0b; text-align: center; line-height: 1.2; margin-top: 2px; }
/* Desglose por PDU (cada barra = carga real enchufada a esa PDU). */
.pwr-pdus { width: 100%; display: flex; flex-direction: column; gap: 4px; margin-top: 4px;
  border-top: 1px solid #ffffff14; padding-top: 5px; }
.pwr-pdu { border-left: 3px solid #22c55e; padding-left: 5px; }
.pwr-pdu-c { font-size: 9px; font-weight: 700; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pwr-pdu-bar { height: 4px; border-radius: 3px; background: #ffffff14; overflow: hidden; margin: 1px 0; }
.pwr-pdu-bar span { display: block; height: 100%; border-radius: 3px; }
.pwr-pdu-v { font-size: 8px; color: var(--muted); }
/* Parpadeo rojo de peligro (rack + dashboard cuando >95% de carga). */
.blink-red { animation: blinkRed 1s ease-in-out infinite; }
@keyframes blinkRed { 0%, 100% { box-shadow: 0 0 0 0 #ef444400, inset 0 0 22px #0009; } 50% { box-shadow: 0 0 14px 2px #ef4444cc, inset 0 0 22px #0009; border-color: #ef4444; } }

/* ── Panel de árbol (navegación rápida) + layout del rack ─────────────────── */
.rack-layout { display: grid; grid-template-columns: 214px 1fr; gap: 18px; align-items: start; }
.rack-tree { position: sticky; top: 0; align-self: start; border: 1px solid var(--line);
  border-radius: 10px; padding: 8px; background: var(--panel2); max-height: 78vh; overflow: auto; }
.rt-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .4px;
  color: var(--muted); padding: 2px 4px 7px; }
.rt-rack-h { font-size: 12.5px; font-weight: 700; padding: 5px 4px; }
.rt-rack-h small { color: var(--muted); font-weight: 500; }
.rt-empty { font-size: 11px; color: var(--muted); padding: 2px 6px 6px; }
.rt-eq-h { display: flex; align-items: center; gap: 5px; font-size: 12px; padding: 4px 5px;
  border-left: 3px solid var(--eqc, #888); border-radius: 4px; cursor: pointer; }
.rt-eq-h:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.rt-eq-h b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rt-eq-h small { color: var(--muted); margin-left: auto; white-space: nowrap; }
.rt-tw { width: 12px; text-align: center; color: var(--muted); cursor: pointer; flex: 0 0 auto; }
.rt-ic { flex: 0 0 auto; }
.rt-ports { display: flex; flex-wrap: wrap; gap: 2px; padding: 3px 6px 5px 22px; }
.rt-port { min-width: 14px; height: 13px; padding: 0 2px; border-radius: 2px; font-size: 8px;
  color: #fff; display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  border: 1px solid #0006; text-shadow: 0 1px 1px #0008; }
/* Conexiones del rack: resaltan al pasar el cursor. El SVG no captura eventos,
   salvo el trazo "hit" transparente de cada cable. */
.rack-cables { pointer-events: none; }
.cable-hit { pointer-events: stroke; cursor: pointer; }
.cable-vis { transition: stroke-width .08s, opacity .08s; }
.cable-g:hover .cable-vis { stroke-width: 4 !important; opacity: 1 !important; filter: drop-shadow(0 0 4px var(--cc)); }
.cable-tip { pointer-events: none; }
.rack-eq-flash { animation: rackFlash 1.4s ease; }
@keyframes rackFlash { 0%, 100% { box-shadow: 0 1px 3px #0008; } 30% { box-shadow: 0 0 0 3px var(--accent), 0 0 18px var(--accent); } }

/* ── Mini-mapa flotante ───────────────────────────────────────────────────── */
.rack-minimap { position: fixed; right: 18px; bottom: 18px; z-index: 60; width: 74px;
  background: var(--panel); border: 1px solid var(--line-strong); border-radius: 8px;
  padding: 6px; box-shadow: 0 8px 24px #0007; }
.rmm-title { font-size: 9px; color: var(--muted); text-align: center; margin-bottom: 4px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rmm-body { position: relative; width: 100%; background: #0d1117; border: 1px solid #ffffff14; border-radius: 4px; }
.rmm-view { position: absolute; left: 0; right: 0; background: color-mix(in srgb, var(--accent) 30%, transparent);
  border: 1.5px solid var(--accent); border-radius: 3px; pointer-events: none; }

/* Compatibilidad de conectores en la barra de conexión */
.cc-tag { font-size: 10px; font-weight: 700; color: var(--muted); background: color-mix(in srgb, var(--muted) 16%, transparent);
  padding: 1px 5px; border-radius: 4px; margin-left: 2px; }
.cc-chip { font-size: 11px; font-weight: 700; border: 1.5px solid; border-radius: 999px; padding: 2px 9px; margin: 0 4px; }

/* ── Modo Patchcord (conexión interactiva) ────────────────────────────────── */
body.patching { cursor: none; }
#patchCursor { position: fixed; z-index: 5001; pointer-events: none; font-size: 17px;
  transform: translate(-3px, -15px); filter: drop-shadow(0 1px 2px #000a); }
/* Puertos incompatibles / ocupados: atenuados y bloqueados para clics. */
.patch-block { opacity: .3; filter: grayscale(.55); pointer-events: none !important; }
/* Puerto destino compatible bajo el cursor: halo verde de confirmación. */
.patch-target { outline: 2px solid #22c55e !important; outline-offset: 1px;
  box-shadow: 0 0 9px #22c55e, 0 0 3px #22c55e inset !important; z-index: 8; position: relative; }
body.patching [data-pid].patch-ok { cursor: none; }

/* ── Menú contextual del puerto (clic derecho) ────────────────────────────── */
.port-ctx { position: fixed; z-index: 6000; min-width: 200px; background: var(--panel);
  border: 1px solid var(--line-strong); border-radius: 9px; padding: 4px; box-shadow: 0 10px 30px #000a; }
.port-ctx button { display: block; width: 100%; text-align: left; border: 0; background: none; color: var(--text);
  font-size: 13px; padding: 7px 10px; border-radius: 6px; cursor: pointer; }
.port-ctx button:hover { background: color-mix(in srgb, var(--accent) 16%, transparent); }

/* ── Panel de trazado de fibra (traceroute) ───────────────────────────────── */
.tr-panel { display: flex; flex-direction: column; padding: 4px 2px; }
.tr-step { display: flex; align-items: center; gap: 11px; padding: 9px 12px; border: 1px solid var(--line);
  border-radius: 10px; background: var(--panel2); }
.tr-ic { flex: 0 0 auto; width: 34px; height: 34px; border-radius: 9px; display: flex; align-items: center;
  justify-content: center; font-size: 18px; background: color-mix(in srgb, var(--accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent); }
.tr-t { font-size: 13.5px; font-weight: 700; color: var(--text); }
.tr-s { font-size: 11px; color: var(--muted); margin-top: 1px; }
.tr-rel { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .4px;
  color: var(--accent-ink); padding: 4px 0 4px 20px; }

/* ── Panel de resumen del rack (energía + ocupación) ──────────────────────── */
.rs-panel { display: flex; flex-direction: column; gap: 14px; }
.rs-rack { border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; background: var(--panel2); }
.rs-h { font-size: 14px; font-weight: 700; margin-bottom: 10px; }
.rs-h small { color: var(--muted); font-weight: 500; }
.rs-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; margin-bottom: 12px; }
.rs-kpi { border: 1px solid var(--line); border-radius: 10px; padding: 8px 10px; background: var(--panel); }
.rs-n { font-size: 20px; font-weight: 800; color: var(--text); line-height: 1; }
.rs-n span { font-size: 11px; font-weight: 600; color: var(--muted); margin-left: 2px; }
.rs-l { font-size: 11px; color: var(--muted); margin-top: 3px; }
.rs-cols { max-height: 190px; overflow: auto; border: 1px solid var(--line); border-radius: 9px; }
.rs-tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.rs-tbl th { position: sticky; top: 0; background: var(--panel); text-align: left; font-size: 10.5px;
  text-transform: uppercase; letter-spacing: .3px; color: var(--muted); padding: 6px 10px; border-bottom: 1px solid var(--line); }
.rs-tbl td { padding: 5px 10px; border-bottom: 1px solid var(--line); }
.rs-tbl tr:last-child td { border-bottom: 0; }
.rs-pdu { margin-top: 9px; font-size: 12px; color: var(--muted); }

/* ── Catálogo de plantillas de equipos ────────────────────────────────────── */
.tpl-cat { max-height: 64vh; overflow: auto; }
.tpl-group { margin-bottom: 14px; }
.tpl-group-h { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .4px;
  color: var(--muted); margin: 4px 2px 7px; }
.tpl-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 9px; }
.tpl-card { display: flex; align-items: center; gap: 10px; text-align: left; padding: 10px 11px;
  background: var(--panel); border: 1px solid var(--line); border-left: 4px solid var(--eqc, #888);
  border-radius: 10px; cursor: pointer; transition: transform .06s, border-color .06s; }
.tpl-card:hover { transform: translateY(-1px); border-color: var(--eqc, var(--accent)); box-shadow: var(--shadow-1); }
.tpl-ic { flex: 0 0 auto; width: 34px; height: 34px; border-radius: 8px; display: flex; align-items: center;
  justify-content: center; font-size: 18px; background: color-mix(in srgb, var(--eqc) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--eqc) 32%, transparent); }
.tpl-body { min-width: 0; }
.tpl-brand { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .3px; color: var(--eqc, var(--muted)); }
.tpl-model { font-size: 13px; font-weight: 700; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tpl-ports { font-size: 10.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Port Channel (LACP) en la lista de conexiones */
.lag-box { border: 1px solid #7c3aed55; border-left: 3px solid #7c3aed; border-radius: 8px;
  padding: 4px 8px 6px; margin: 4px 0; background: color-mix(in srgb, #7c3aed 7%, transparent); }
.lag-h { font-size: 12px; font-weight: 700; color: #a78bfa; display: flex; align-items: center; gap: 6px; padding: 3px 0; }
.lag-h small { color: var(--muted); font-weight: 500; }
.lag-pick { display: flex; align-items: center; gap: 7px; font-size: 12.5px; padding: 3px 5px; border-radius: 5px; cursor: pointer; }
.lag-pick:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
/* Slot SFP vacío: rayado, indica que falta insertar módulo */
.fp-port.sfp-empty, .port-chip.sfp-empty { background-image: repeating-linear-gradient(45deg, #ffffff18 0 2px, transparent 2px 4px) !important; }
/* Puerto CONECTADO: un punto blanco en la esquina, SIN tapar el color de estado
   en vivo del fondo (verde activo / naranja sin clientes / rojo falla desde la OLT). */
.port-chip { position: relative; }
.port-chip.linked::after { content: ''; position: absolute; top: -2px; right: -2px; width: 7px; height: 7px;
  border-radius: 50%; background: #fff; border: 1.5px solid #0b0e13; box-shadow: 0 0 3px #000; }
.fp-port.linked::after { content: ''; position: absolute; top: -2px; right: -2px; width: 4px; height: 4px;
  border-radius: 50%; background: #fff; border: 1px solid #0b0e13; }
.fp-port.linked { position: relative; }
/* Dos LEDs verdes parpadeantes = actividad de red NATIVA (puerto emparejado en
   vivo con el equipo físico real, vía MAS-WISP). */
.live-act { position: relative; }
.fp-port.live-act::before, .port-chip.live-act::before {
  content: ''; position: absolute; bottom: 1px; left: 1.5px; width: 2px; height: 2px; border-radius: 50%;
  background: #4dff88; box-shadow: 3px 0 0 #4dff88, 0 0 3px #4dff88; animation: liveLeds .9s ease-in-out infinite; pointer-events: none; }
.port-chip.live-act::before { width: 3px; height: 3px; bottom: 2px; left: 3px; box-shadow: 5px 0 0 #4dff88, 0 0 3px #4dff88; }
@keyframes liveLeds { 0%, 100% { opacity: 1; } 50% { opacity: .2; } }

/* Presupuesto óptico GPON */
.ob-panel { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.ob-inputs { display: flex; flex-direction: column; gap: 8px; }
.ob-inp { display: flex; flex-direction: column; gap: 3px; font-size: 11px; color: var(--muted); }
.ob-inp input, .ob-inp select { width: 100%; padding: 5px 8px; background: var(--panel2); color: var(--text);
  border: 1px solid var(--line-strong); border-radius: 7px; font-size: 13px; }
.ob-result { align-self: start; border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; background: var(--panel2); }
.ob-line { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; padding: 3px 0; }
.ob-line span { color: var(--muted); }
.ob-total { border-top: 1px solid var(--line); margin-top: 4px; padding-top: 6px; font-size: 14px; font-weight: 700; }
.ob-total span { color: var(--text); }
.ob-verdict { margin-top: 8px; text-align: center; font-weight: 700; font-size: 12.5px; padding: 6px; border: 1px solid; border-radius: 8px; }
.ob-panel .odf-note { grid-column: 1 / -1; }
@media (max-width: 560px) { .ob-panel { grid-template-columns: 1fr; } }

/* ── Tooltip flotante de puerto (carga cognitiva mínima) ──────────────────── */
.port-tip { position: fixed; z-index: 100000; display: none; min-width: 178px; max-width: 260px;
  background: #0d1117; color: #e6edf3; border: 1px solid #30363d; border-radius: 8px;
  padding: 8px 10px; box-shadow: 0 10px 30px #000a; font-size: 11.5px; pointer-events: none; }
.port-tip .pt-head { display: flex; align-items: center; gap: 6px; font-weight: 700; font-size: 12px;
  padding-bottom: 5px; margin-bottom: 5px; border-bottom: 1px solid #ffffff14; }
.port-tip .pt-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.port-tip .pt-row { display: flex; justify-content: space-between; gap: 12px; line-height: 1.7; }
.port-tip .pt-k { color: #8b949e; white-space: nowrap; }
.port-tip .pt-v { color: #e6edf3; font-weight: 600; text-align: right; }

/* ── Esquema de Fusión de Extremo a Extremo (camino de la luz) ────────────── */
.e2e-head { display: grid; grid-template-columns: 1fr 34px 1.1fr 34px 1.2fr; gap: 4px;
  padding: 4px 10px; margin-bottom: 6px; }
.e2e-col-h { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .4px; color: var(--muted); }
.e2e-col-h small { text-transform: none; font-weight: 500; letter-spacing: 0; }
.e2e-cable { border: 1px solid var(--line); border-radius: 10px; margin-bottom: 10px; overflow: hidden; }
.e2e-cable-h { display: flex; align-items: center; gap: 6px; font-size: 13px; padding: 7px 12px;
  background: var(--panel2); border-bottom: 1px solid var(--line); }
.e2e-cable-h small { color: var(--muted); font-weight: 500; }
.e2e-row { display: grid; grid-template-columns: 1fr 34px 1.1fr 34px 1.2fr; gap: 4px; align-items: center;
  padding: 7px 12px; border-bottom: 1px solid var(--line); font-size: 12.5px; }
.e2e-row:last-child { border-bottom: 0; }
.e2e-row:hover { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.e2e-in, .e2e-fuse, .e2e-out { display: flex; align-items: center; gap: 5px; min-width: 0; }
.e2e-in small, .e2e-fuse small { color: var(--muted); }
.e2e-link { display: flex; align-items: center; justify-content: center; gap: 2px; color: var(--muted); font-size: 11px; }
.e2e-line { height: 2px; width: 8px; background: color-mix(in srgb, var(--accent) 55%, transparent); border-radius: 2px; }
.e2e-dot { width: 10px; height: 10px; border-radius: 3px; flex: 0 0 auto; }
.e2e-led { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; display: inline-block; }

/* Barra de edición */
/* Barra flotante horizontal de Objetos y Herramientas (íconos con tooltip) */
.edit-toolbar { position: absolute; top: 60px; left: 50%; transform: translateX(-50%); z-index: 1000;
  display: flex; flex-direction: row; align-items: center; flex-wrap: wrap; gap: 8px;
  background: color-mix(in srgb, var(--panel) 92%, transparent); backdrop-filter: blur(8px);
  border: 1px solid var(--line); border-radius: 12px; padding: 7px 12px; width: auto; max-width: calc(100vw - 32px);
  box-shadow: var(--shadow-2); }
.edit-title { font-size: 10px; text-transform: uppercase; color: var(--muted); letter-spacing: .3px; }
.tb-icons { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.tb-sep { width: 1px; align-self: stretch; background: var(--line); margin: 0 2px; }

/* Gestión de obra / As-built: letra más compacta para ver más en pantalla */
#workModal { font-size: 12.5px; }
#workBody { font-size: 12.5px; }
#workBody h4 { font-size: 13.5px; margin: 0 0 6px; }
#workBody table { font-size: 12px; }
#workBody .cl-card > div > div:first-child { font-size: 13px; }
#workModal .catalog-header h3 { font-size: 15px; }
#workTabs .tool-btn { font-size: 12px; padding: 4px 9px; }
.edit-toolbar button { background: var(--bg); border: 1px solid var(--line); color: var(--text);
  padding: 7px 9px; border-radius: 7px; cursor: pointer; font-size: 13px; text-align: left; }
.edit-toolbar button:hover { border-color: var(--accent); }
.edit-toolbar button.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.edit-hint { font-size: 11px; color: var(--fiber); line-height: 1.3; }
.edit-finish { background: var(--ok) !important; border-color: var(--ok) !important; color: #fff !important; }
.edit-cancel { background: transparent !important; color: var(--muted) !important; }
.map-editing { cursor: crosshair !important; }

/* Modal genérico */
.modal-overlay { position: absolute; inset: 0; z-index: 1100; background: var(--overlay);
  display: grid; place-items: center; padding: 18px; box-sizing: border-box; }
/* Modal chico (formularios simples): ancho responsivo + tope de alto con scroll
   para que el contenido largo NO se corte fuera de la pantalla. */
.modal-card { width: min(360px, 96vw); max-height: 92vh; overflow-y: auto; background: var(--panel);
  border: 1px solid var(--line); border-radius: 12px; padding: 22px; display: flex; flex-direction: column; gap: 12px; box-shadow: var(--shadow-3); }
.modal-card h4 { margin: 0; }
.modal-card label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--muted); }
.modal-card input, .modal-card select { background: var(--bg); border: 1px solid var(--line);
  color: var(--text); padding: 9px 10px; border-radius: 7px; font-size: 14px; }
.modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 4px; }
.modal-actions button { padding: 9px 16px; border-radius: 7px; border: 0; cursor: pointer;
  background: var(--grad); color: #fff; font-weight: 600; }
.modal-actions .ghost { background: transparent; border: 1px solid var(--line); color: var(--text); }

/* Catálogo */
.catalog-overlay { position: absolute; inset: 0; z-index: 1200; background: var(--overlay);
  display: grid; place-items: center; padding: 18px; box-sizing: border-box; }
/* Tarjeta estándar de modal: ancho responsivo, alto AUTO hasta 92vh (crece con el
   contenido y scrollea el cuerpo). Esquema común: header fijo arriba + cuerpo scrolleable. */
.catalog-card { width: min(820px, 96vw); height: auto; max-height: 92vh; background: var(--panel);
  border: 1px solid var(--line); border-radius: 12px; display: flex; flex-direction: column; overflow: hidden; box-shadow: var(--shadow-3); }
.catalog-header { display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px; border-bottom: 1px solid var(--line); }
.catalog-header h3 { margin: 0; font-size: 16px; }
.catalog-header .trace-close { position: static; }
.catalog-tabs { display: flex; gap: 6px; padding: 12px 18px 0; flex-wrap: wrap; }
.catalog-tabs button { background: var(--bg); border: 1px solid var(--line); color: var(--muted);
  padding: 8px 14px; border-radius: 8px 8px 0 0; cursor: pointer; font-size: 13px; }
.catalog-tabs button.active { background: var(--panel); color: var(--text); border-bottom-color: var(--panel); border-top: 2px solid var(--accent); }
.catalog-body { display: grid; grid-template-columns: 300px 1fr; gap: 16px; padding: 16px 18px;
  flex: 1; overflow: hidden; }
.catalog-form { display: flex; flex-direction: column; gap: 10px; overflow: auto; padding-right: 6px; }
.catalog-form label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--muted); }
.catalog-form input, .catalog-form select { background: var(--bg); border: 1px solid var(--line);
  color: var(--text); padding: 8px 10px; border-radius: 7px; font-size: 13px; }
.catalog-form button[type=submit] { background: var(--grad); color: #fff; border: 0;
  padding: 10px; border-radius: 7px; font-weight: 600; cursor: pointer; margin-top: 4px; }
.photo-preview { width: 100%; height: 110px; border: 1px dashed var(--line); border-radius: 8px;
  object-fit: contain; background: var(--bg); }
.catalog-list { overflow: auto; }
.catalog-list table { width: 100%; border-collapse: collapse; font-size: 13px; }
.catalog-list th { text-align: left; color: var(--muted); font-weight: 500; font-size: 11px;
  text-transform: uppercase; padding: 6px 8px; border-bottom: 1px solid var(--line); position: sticky; top: 0; background: var(--panel); }
.catalog-list td { padding: 7px 8px; border-bottom: 1px solid var(--line); }
.catalog-list img.thumb { width: 34px; height: 34px; object-fit: cover; border-radius: 5px; vertical-align: middle; }
.catalog-list .del { background: transparent; border: 0; color: var(--bad-ink); cursor: pointer; font-size: 16px; }
.catalog-error { color: var(--bad-ink); font-size: 12px; min-height: 14px; }

/* Búsqueda en topbar */
.search-box { position: relative; width: 280px; }
.search-box input { width: 100%; background: var(--bg); border: 1px solid var(--line); color: var(--text);
  padding: 8px 12px; border-radius: 8px; font-size: 13px; }
.search-results { position: absolute; top: 38px; left: 0; right: 0; background: var(--panel);
  border: 1px solid var(--line); border-radius: 8px; max-height: 320px; overflow: auto; z-index: 1500; }
.search-results .res { padding: 8px 12px; cursor: pointer; font-size: 13px; border-bottom: 1px solid var(--line); display: flex; gap: 8px; align-items: center; }
.search-results .res:hover { background: var(--bg); }
.search-results .res .k { font-size: 10px; text-transform: uppercase; color: var(--accent-ink); min-width: 50px; }

/* Botones de herramientas en sidebar */
.tool-btn { background: var(--bg); border: 1px solid var(--line); color: var(--text);
  padding: 8px 10px; border-radius: 7px; cursor: pointer; font-size: 13px; text-align: left; }
.tool-btn:hover { border-color: var(--accent); }
.tool-btn.active-tool { background: var(--ok); border-color: var(--ok); color: #fff; font-weight: 600; }

/* Dashboard */
/* Cuerpo genérico de modal: bloque scrolleable, mismo padding en todos.
   `min-height:0` + `flex:1` permiten que SCROLLEE dentro de la tarjeta (flex column)
   en vez de desbordarse y quedar cortado. */
.dash-body { padding: 16px 18px; overflow: auto; display: block; flex: 1 1 auto; min-height: 0; }
.dash-body > table, .modal-body > table { width: 100%; }
/* Grilla de tarjetas KPI (dashboard, mantenimiento): solo donde se quiere grid. */
.dash-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px,1fr)); gap: 12px; }
.dash-card { background: var(--bg); border: 1px solid var(--line); border-radius: 10px; padding: 14px; }
.dash-card .big { font-size: 26px; font-weight: 700; color: var(--accent-ink); font-family: 'Bricolage Grotesque', 'Hanken Grotesk', sans-serif; }
.dash-card .lbl { font-size: 11px; text-transform: uppercase; color: var(--muted); margin-top: 4px; }
.dash-card.wide { grid-column: 1 / -1; }
.dash-bar { height: 8px; background: var(--line); border-radius: 4px; overflow: hidden; margin-top: 8px; }
.dash-bar > span { display: block; height: 100%; background: var(--accent); }
.dash-row { display: flex; justify-content: space-between; font-size: 13px; padding: 4px 0; border-bottom: 1px solid var(--line); }
.dash-row b { color: var(--fiber); }

/* Árbol */
.tree-body { padding: 18px; overflow: auto; max-height: 76vh; font-size: 13px; }
.tree-node { margin-left: 16px; border-left: 1px solid var(--line); padding-left: 12px; }
.tree-node > .lbl { padding: 4px 0; }
.tree-node .tag { display: inline-block; font-size: 9px; text-transform: uppercase; padding: 1px 5px;
  border-radius: 4px; margin-right: 6px; background: var(--line); color: var(--text); }
.tag-olt { background: #f778ba33; color: #f778ba; }
.tag-splitter { background: #d2992233; color: var(--warn-ink); }
.tag-nap { background: #2f81f733; color: var(--accent-ink); }
.tag-cliente { background: #3fb95033; color: var(--ok-ink); }
/* Tintas legibles de los badges en tema claro */
body.light .tag-olt { background: #f778ba26; color: #b03579; }
body.light .tag-splitter { background: #f59e4226; }
body.light .tag-nap { background: #2f9fe022; }
body.light .tag-cliente { background: #14b8a622; }
.budget-box { background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 10px; margin-top: 10px; }
.budget-box .row { display: flex; justify-content: space-between; font-size: 12px; padding: 2px 0; }
/* Editor de empalmes */
.splice-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; padding: 0 18px; max-height: 40vh; overflow: auto; }
.strand-col { display: flex; flex-direction: column; gap: 3px; }
.strand { display: flex; align-items: center; gap: 8px; padding: 5px 8px; border: 1px solid var(--line);
  border-radius: 6px; cursor: pointer; font-size: 12px; }
.strand:hover { border-color: var(--accent); }
.strand.sel { border-color: var(--accent); background: var(--line); }
.strand.used { opacity: .5; }
.strand .sw { width: 14px; height: 14px; border-radius: 3px; border: 1px solid #0006; flex: 0 0 14px; }
.splice-row { display: flex; justify-content: space-between; font-size: 12px; padding: 5px 0; border-bottom: 1px solid var(--line); }
.splice-row .del { background: transparent; border: 0; color: var(--bad-ink); cursor: pointer; }
.budget-status { padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
.bs-ok { background: #3fb95033; color: var(--ok-ink); }
.bs-ajustado { background: #d2992233; color: var(--warn-ink); }
.bs-critico { background: #f8514933; color: var(--bad-ink); }
body.light .bs-ok { background: #14b8a622; }
body.light .bs-ajustado { background: #f59e4226; }
body.light .bs-critico { background: #f0626d22; }

/* Planta interna del nodo: grilla de puertos */
.port-grid { display:flex; flex-wrap:wrap; gap:4px; margin-top:4px; }
.port-chip {
  display:inline-flex; align-items:center; justify-content:center;
  min-width:24px; height:24px; padding:0 4px; border-radius:5px;
  color:#fff; font-size:11px; font-weight:600; cursor:pointer; user-select:none;
}
.port-chip:hover { filter:brightness(1.15); }

/* ---- Modal del nodo: botones y tarjetas más modernos ---- */
.node-btn { border:none; border-radius:6px; padding:3px 8px; background:var(--line); color:var(--text); cursor:pointer; font-size:12px; line-height:1; }
.node-btn:hover { filter:brightness(1.2); }
.node-btn.danger { background:color-mix(in srgb, var(--bad) 12%, transparent); }
.node-btn.danger:hover { background:var(--bad); color:#fff; }
#nodeBody .impact-item { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:10px 12px; box-shadow:var(--shadow-1); margin-bottom:8px; }
#nodeBody h4 { margin:12px 0 6px; font-size:13px; }
#nodeBody .trace-btn { background:var(--line); color:var(--text); border:none; border-radius:7px; padding:5px 11px; font-size:12px; cursor:pointer; margin:2px 4px 2px 0; transition:background .12s,color .12s; }
#nodeBody .trace-btn:hover { background:var(--accent); color:#fff; }
#nodeBody .trace-btn.active-tool { background:var(--accent); color:#fff; }
#nodeToolbar { background:var(--panel); border:1px solid var(--line); border-radius:10px; padding:8px 10px; }
#nodeToolbar select, #nodeToolbar input { border-radius:7px; padding:5px 8px; }
#nodeToolbar .trace-btn { background:var(--grad); color:#fff; font-weight:600; border:none; border-radius:7px; padding:6px 12px; cursor:pointer; }

/* ---- Barra superior compacta + menú agrupado + panel colapsable (estilo MAS-WISP) ---- */
.topbar { gap: 10px !important; }
.kpis { gap: 12px !important; font-size: 12px !important; }
#sideToggle { padding: 6px 11px; font-size: 16px; line-height: 1; }
.app-menu-wrap { position: relative; margin-left: auto; }
.app-menu { position: absolute; right: 0; top: 44px; background: var(--panel);
  border: 1px solid var(--line); border-radius: 12px; padding: 8px; display: flex;
  flex-direction: column; gap: 4px; min-width: 210px; box-shadow: var(--shadow-2); z-index: 1500; }
.app-menu .ghost { text-align: left; border: none; padding: 8px 10px; border-radius: 7px; }
.app-menu .ghost:hover { background: var(--line); }
/* Encabezados de sección del menú ☰ (Operación / Análisis / Configuración / Plataforma) */
.menu-sec { font-size: 10px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted);
  font-weight: 700; padding: 9px 10px 3px; }
.menu-sec:first-child { padding-top: 3px; }
/* Módulos del menú ☰ como acordeón (clic en el encabezado despliega sus botones) */
.menu-sec-acc { cursor: pointer; display: flex; align-items: center; justify-content: space-between;
  padding: 8px 10px; border-radius: 7px; }
.menu-sec-acc:hover { background: var(--line); color: var(--text); }
.menu-sec-acc::after { content: '▸'; opacity: .7; transition: transform .15s ease; }
.menu-sec-acc.open::after { transform: rotate(90deg); }

/* Panel de Herramientas por categoría */
.tools-cat { margin-bottom: 16px; }
.tools-cat-h { font-size: 12px; text-transform: uppercase; letter-spacing: .4px; color: var(--muted);
  font-weight: 700; margin: 0 0 8px; }
.tools-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 8px; }
.tool-card { text-align: left; background: var(--bg); border: 1px solid var(--line); color: var(--text);
  padding: 10px 12px; border-radius: 9px; cursor: pointer; font-size: 13px; line-height: 1.25;
  transition: border-color .12s, background .12s; }
.tool-card:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--bg)); }
/* Tarjetas de acción de la bienvenida (título + subtítulo) */
.welcome-actions { display: flex; flex-direction: column; gap: 8px; margin: 4px 0; }
/* ---- Tarjeta de información del item (reemplaza el popup chico) ---- */
#infoSheet { position: fixed; top: 52px; right: 12px; width: 340px; max-width: calc(100vw - 24px);
  max-height: calc(100vh - 190px); overflow-y: auto; z-index: 1250;
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow-3); animation: dfm-slide-r .28s cubic-bezier(.34,1.45,.42,1) both; }
.info-head { display: flex; align-items: center; gap: 10px; padding: 12px 14px;
  border-bottom: 1px solid var(--line); position: sticky; top: 0; background: var(--panel); z-index: 1; border-radius: 12px 12px 0 0; }
.info-icon { font-size: 26px; line-height: 1; flex: 0 0 auto; }
.info-titles { flex: 1; min-width: 0; }
.info-title { font-size: 18px; font-weight: 700; word-break: break-word; }
.info-type { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); }
.info-close { background: transparent; border: 0; color: var(--muted); font-size: 24px; line-height: 1;
  cursor: pointer; padding: 0 4px; transition: color .12s ease, transform .12s ease; flex: 0 0 auto; }
.info-close:hover { color: var(--text); transform: scale(1.12); }
.info-body { padding: 12px 14px; display: flex; flex-direction: column; gap: 12px; }
.info-photo { width: 100%; max-height: 150px; object-fit: contain; border-radius: 8px; background: var(--bg); }
.info-rows { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: 9px; overflow: hidden; }
.info-row { display: flex; justify-content: space-between; gap: 12px; padding: 10px 12px; font-size: 14.5px; background: var(--bg); }
.info-row:nth-child(even) { background: color-mix(in srgb, var(--text) 5%, var(--bg)); }
.info-k { color: color-mix(in srgb, var(--text) 62%, transparent); flex: 0 0 auto; }
.info-v { color: var(--text); font-weight: 700; text-align: right; word-break: break-word; }
.info-empty { color: var(--muted); font-size: 13px; padding: 2px; }
.info-actions { display: flex; flex-direction: column; gap: 6px; }
.info-actions-h { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); margin-bottom: 2px; }
.pop-btn.info-act { width: 100%; height: auto; justify-content: flex-start; gap: 10px; padding: 11px 13px;
  border-radius: 10px; font-size: 18px; color: var(--text); }
.pop-btn.info-act:hover { color: #fff; } /* al pasar el mouse el fondo es de color → texto blanco */
.info-act-l { font-size: 14px; font-weight: 600; line-height: 1.25; }

/* Lista de pasos de la guía de uso / tutorial */
.guide-list { margin: 4px 0; padding-left: 18px; display: flex; flex-direction: column; gap: 5px; }
.guide-list li { font-size: 12.5px; line-height: 1.4; color: var(--text); }
/* Tutorial completo */
.tutorial { max-height: 76vh; }
.tut-intro { font-size: 13px; color: var(--muted); margin: 0 0 4px; }
.tut-h { margin: 16px 0 2px; font-size: 14px; color: var(--accent-ink); }
.tut-h:first-of-type { margin-top: 2px; }
.tool-card.wc { display: flex; flex-direction: column; gap: 2px; }
.tool-card.wc span { font-size: 11px; color: var(--muted); }
/* Panel lateral colapsable: el mapa ocupa todo el ancho */
.app.side-collapsed { grid-template-columns: 0 1fr; }
.app.side-collapsed .sidebar { display: none; }

/* Menús Materiales/Herramientas: ancho acorde al texto (placeholder), no al más largo */
#editSelect { width: 170px !important; }
#toolSelect { width: 165px !important; }

/* Campana de alertas + badge */
.alerts-badge { position:absolute; top:-4px; right:-4px; min-width:16px; height:16px;
  padding:0 4px; border-radius:8px; background:var(--bad); color:#fff; font-size:10px;
  line-height:16px; text-align:center; font-weight:700; box-shadow:0 0 0 2px var(--bg); }
.alert-row { display:flex; gap:10px; align-items:flex-start; padding:10px 14px;
  border-bottom:1px solid var(--line); }
.alert-sev { width:8px; align-self:stretch; border-radius:4px; flex:0 0 8px; }
.alert-sev.alta { background:var(--bad); } .alert-sev.media { background:#f5c518; } .alert-sev.baja { background:#3fb950; }
body.light .alert-sev.media { background:#f59e42; } body.light .alert-sev.baja { background:#14b8a6; }
.alert-acts { margin-left:auto; display:flex; gap:6px; }
.alert-acts button { font-size:11px; padding:3px 8px; }

/* Continuidad / cortes a mitad de tramo */
.ms-paso { border:1px solid var(--line); border-radius:8px; padding:10px 12px; margin-bottom:12px; }
.ms-paso h4 { margin:0 0 6px; display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.ms-strand { display:flex; align-items:center; gap:8px; padding:5px 6px; border-bottom:1px solid var(--line); font-size:12px; }
.ms-line { flex:1; display:flex; align-items:center; gap:2px; min-width:120px; }
.ms-seg { height:4px; border-radius:2px; flex:1; }
.ms-cut { color:var(--bad-ink); font-weight:700; }
.ms-fuse { color:var(--warn-ink); font-weight:700; }
.ms-strand button { font-size:11px; padding:2px 7px; }
.ms-dot { width:12px; height:12px; border-radius:50%; border:1px solid #0006; flex:0 0 12px; }
.ms-branch { margin:4px 0 4px 26px; font-size:11px; color:var(--muted); display:flex; gap:6px; align-items:center; }
.ms-suger { background:#0891b21a; border:1px dashed #0891b2; border-radius:8px; padding:8px 10px; margin-bottom:10px; }

/* Toast efímero (deshacer/rehacer y avisos) */
.dfm-toast { position:fixed; bottom:24px; left:50%; transform:translateX(-50%) translateY(20px);
  background:var(--panel); color:var(--text); border:1px solid var(--line); border-radius:8px;
  padding:10px 16px; font-size:13px; box-shadow:var(--shadow-2); opacity:0; pointer-events:none;
  transition:opacity .2s, transform .2s; z-index:9999; }
.dfm-toast.show { opacity:1; transform:translateX(-50%) translateY(0); }
#undoBtn:disabled, #redoBtn:disabled { opacity:.35; cursor:default; }

/* Ficha "Contenido" de la manga/caja */
.cl-stats { display:grid; grid-template-columns:repeat(auto-fit,minmax(130px,1fr)); gap:8px; }
.cl-stat { background:var(--bg); border:1px solid var(--line); border-radius:8px; padding:8px 10px; }
.cl-stat-v { font-size:18px; font-weight:700; }
.cl-stat-l { font-size:11px; color:var(--text); opacity:.8; }

/* Separador de sección en resultados de búsqueda (objetos vs direcciones) */
.search-results .res-sep { font-size: 10px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); padding: 6px 12px 2px; border-top: 1px solid var(--line); background: var(--bg); }

/* Menú contextual del mapa (clic derecho) */
.map-ctx { position: fixed; z-index: 1500; min-width: 210px; background: var(--panel);
  border: 1px solid var(--line); border-radius: 10px; padding: 5px; box-shadow: var(--shadow-2);
  display: flex; flex-direction: column; }
.map-ctx button { text-align: left; background: transparent; border: 0; color: var(--text);
  padding: 8px 10px; border-radius: 7px; cursor: pointer; font-size: 13px; }
.map-ctx button:hover { background: color-mix(in srgb, var(--accent) 16%, transparent); }

/* Indicador de enganche (snap) al dibujar cables */
.snap-hint { width: 18px; height: 18px; border: 2.5px solid #3fb950; border-radius: 50%;
  background: rgba(63,185,80,.18); box-shadow: 0 0 0 2px #0006; pointer-events: none; }

/* ---- Impresión / exportación del plano del mapa ---- */
#printHeader { display: none; }
@media print {
  body * { visibility: hidden; }
  #map, #map * { visibility: visible; }
  #map { position: fixed; inset: 0; width: 100%; height: 100%; }
  /* ocultar UI no-mapa (pero conservar la barra de escala) */
  .sidebar, .topbar, .trace-panel, .catalog-overlay, .modal-overlay, .edit-toolbar,
  #toolBarIcons, #tbToggles, .map-ctx, .maplibregl-ctrl-zoom, .maplibregl-ctrl-attrib,
  .leaflet-control-zoom, .leaflet-control-attribution { display: none !important; }
  #printHeader { display: block; visibility: visible; position: fixed; top: 0; left: 0; right: 0;
    z-index: 99999; background: #fff; color: #111; border-bottom: 2px solid #111; padding: 8px 14px; }
  #printHeader * { visibility: visible; }
  #printHeader .ph-title { font-weight: 700; font-size: 16px; }
  #printHeader .ph-meta { font-size: 12px; color: #555; }
  #printHeader .ph-legend { display: flex; flex-wrap: wrap; gap: 12px; font-size: 11px; margin-top: 4px; }
  #printHeader .ph-legend span { display: inline-flex; align-items: center; gap: 4px; }
  #printHeader .ph-legend i { width: 11px; height: 11px; border-radius: 2px; display: inline-block; }
}

/* ---- Controles flotantes del mapa: leyenda + etiquetas ---- */
#mapControls { position: absolute; right: 14px; bottom: 40px; z-index: 700; display: flex; flex-direction: column; gap: 6px; }
#mapControls button { width: 38px; height: 38px; font-size: 18px; border-radius: 10px; cursor: pointer;
  background: var(--panel); color: var(--text); border: 1px solid var(--line); box-shadow: var(--shadow-1); }
#mapControls button.on { background: var(--accent); border-color: var(--accent); }
#mapLegend { position: absolute; right: 60px; bottom: 40px; z-index: 700; min-width: 160px; max-height: 50vh; overflow: auto;
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 8px 10px; box-shadow: var(--shadow-2); font-size: 12px; }
#mapLegend .lg-head { font-weight: 700; margin-bottom: 6px; font-size: 12px; }
#mapLegend .lg-row { display: flex; align-items: center; gap: 7px; padding: 2px 0; }
#mapLegend .lg-ic { width: 16px; text-align: center; }
#mapLegend .lg-sw { width: 12px; height: 12px; border-radius: 3px; flex: 0 0 12px; border: 1px solid #0006; }
/* Etiqueta sobre el mapa: siempre oscura (legible sobre cualquier mapa base),
   independiente del tema del chrome. */
.map-label { background: rgba(13,17,23,.85); color: #e6edf3; border: 1px solid rgba(255,255,255,.18);
  border-radius: 5px; padding: 1px 5px; font-size: 10px; font-weight: 600; box-shadow: none; }
.map-label::before { display: none; }
@media print { #mapControls, #mapLegend { display: none !important; } }

/* ---- Flecha norte (overlay permanente, también al imprimir) ---- */
#northArrow { position: absolute; top: 52px; right: 14px; z-index: 650; width: 34px; height: 40px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1;
  background: var(--panel); color: var(--text); border: 1px solid var(--line); border-radius: 8px;
  box-shadow: var(--shadow-1); font-size: 18px; font-weight: 700; }
#northArrow span { font-size: 10px; margin-top: -2px; }
@media print {
  /* En el plano: mostrar barra de escala y flecha norte */
  .leaflet-control-scale, .maplibregl-ctrl-scale { display: block !important; visibility: visible !important;
    position: fixed !important; bottom: 12px !important; left: 12px !important; z-index: 99999 !important;
    background: #fff !important; color: #111 !important; }
  .leaflet-control-scale *, .maplibregl-ctrl-scale * { visibility: visible !important; color: #111 !important; }
  #northArrow { display: flex !important; visibility: visible !important; background: #fff !important; color: #111 !important;
    border: 1px solid #111 !important; top: 48px !important; }
  #northArrow * { visibility: visible !important; }
}

/* ============================================================
   UI compacta (~−25%) — chrome más chico sin tocar el mapa.
   ============================================================ */
.app { grid-template-columns: 184px 1fr; grid-template-rows: 44px minmax(0, 1fr); }
.topbar { gap: 8px !important; padding: 0 13px; }
.brand { font-size: 13px; display: flex; align-items: center; }
/* Logo de marca: sin texto al lado, aprovecha casi toda la altura de la barra. */
.brand-logo { height: 34px; width: auto; max-width: 190px; display: block; object-fit: contain; }
.ghost { padding: 5px 10px; font-size: 12px; border-radius: 7px; }
.kpis { gap: 9px !important; font-size: 10px !important; }
.search-box { width: 210px; }
.search-box input { font-size: 11px; padding: 6px 9px; }
.search-results .res { font-size: 12px; padding: 6px 10px; }
.base-select { font-size: 11px; padding: 5px 7px; }
.sidebar { padding: 11px 12px; gap: 5px; overflow-y: auto; min-height: 0; }
.sidebar label { font-size: 11px; gap: 6px; }
.sidebar label .dot { width: 8px; height: 8px; flex: 0 0 8px; }
.tool-btn { font-size: 11px; padding: 6px 8px; }
.trace-panel { width: 250px; padding: 12px; }
.trace-panel h4 { font-size: 13px; }
/* Barra a la derecha del botón flotante y en su misma línea; se desplaza con él
   al colapsar el panel (deja 56px a la derecha para la flecha norte). */
.edit-toolbar { padding: 5px 9px; gap: 6px; top: 52px; left: 292px; transform: none;
  width: auto; max-width: calc(100vw - 348px); flex-wrap: nowrap; overflow-x: auto;
  transition: left .18s ease, max-width .18s ease; }
.app.side-collapsed .edit-toolbar { left: 98px; max-width: calc(100vw - 154px); }
.edit-toolbar .tb-icons { flex-wrap: nowrap; }
.edit-toolbar .edit-title { white-space: nowrap; }
.edit-toolbar button { font-size: 11px; padding: 5px 7px; }
.pop-btn { width: 30px; height: 30px; font-size: 15px; }
#sideToggle { padding: 5px 9px; font-size: 14px; }
#mapControls button { width: 32px; height: 32px; font-size: 15px; }
#editSelect { width: 150px !important; }
#toolSelect { width: 150px !important; }

/* ============================================================
   Módulos del panel en acordeón (máx. 2 abiertos, controlado por JS).
   ============================================================ */
/* Tarjeta de resumen (KPIs) en el panel lateral, legible con número grande. */
.kpi-card { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 4px; }
.kpi { background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px;
  display: flex; flex-direction: column; gap: 1px; }
.kpi-n { font-size: 17px; font-weight: 700; color: var(--accent-ink); line-height: 1.1; font-family: 'Bricolage Grotesque', 'Hanken Grotesk', sans-serif; }
.kpi-l { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: .2px; }

.acc { border-bottom: 1px solid var(--line); }
.acc-h { width: 100%; text-align: left; background: transparent; border: 0; cursor: pointer;
  color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .3px; font-weight: 600;
  padding: 8px 2px; display: flex; align-items: center; justify-content: space-between; }
.acc-h:hover { color: var(--text); }
.acc-h::after { content: '▸'; opacity: .7; transition: transform .15s ease; }
.acc.open > .acc-h::after { transform: rotate(90deg); }
.acc-b { display: none; flex-direction: column; gap: 6px; padding: 2px 0 9px; }
/* Control "Todas / Ninguna" de las capas */
.layers-toggle { display: flex; gap: 6px; margin-bottom: 2px; }
.layers-toggle button { font-size: 10px; padding: 2px 9px; background: var(--bg); border: 1px solid var(--line);
  color: var(--muted); border-radius: 6px; cursor: pointer; }
.layers-toggle button:hover { border-color: var(--accent); color: var(--text); }
.acc.open > .acc-b { display: flex; }

/* ============================================================
   Botón flotante para mostrar/ocultar la barra de objetos/herramientas.
   ============================================================ */
/* Botón flotante: por defecto a la DERECHA del panel (184 px + 10). Cuando el
   panel está colapsado, salta al borde izquierdo. Transición suave al moverse. */
#tbToggles { position: absolute; top: 52px; left: 204px; z-index: 1100; display: flex; gap: 6px;
  align-items: flex-start; transition: left .18s ease; }
/* Columna: el botón arriba y su lista vertical de iconos colgando debajo */
.tb-col { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.tb-vert { display: flex; flex-direction: column; gap: 5px; padding: 6px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow-2);
  max-height: calc(100vh - 140px); overflow-y: auto; scrollbar-width: thin; }
.tb-vert.hidden { display: none; }
#tbToggles button { width: 32px; height: 32px; padding: 0;
  border-radius: 9px; cursor: pointer; font-size: 16px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow-1);
  /* estado SECCIÓN VISIBLE (acento) */
  background: var(--accent); color: #fff; border: 1px solid var(--accent); }
/* estado SECCIÓN OCULTA (atenuado / neutro) */
#tbToggles button.off { background: var(--panel); color: var(--text); border-color: var(--line); }
#tbToggles button:hover { filter: brightness(1.08); }
/* Selector flotante de tipo de mapa (capa base) */
#basePopover { position: absolute; right: 58px; bottom: 40px; z-index: 760; background: var(--panel);
  border: 1px solid var(--line); border-radius: 10px; padding: 6px; box-shadow: var(--shadow-2);
  display: flex; flex-direction: column; gap: 3px; min-width: 150px; animation: dfm-pop .2s cubic-bezier(.34,1.45,.42,1) both; }
#basePopover button { text-align: left; background: transparent; border: 0; color: var(--text);
  padding: 9px 11px; border-radius: 7px; cursor: pointer; font-size: 13px; transition: background .12s ease; }
#basePopover button:hover { background: var(--line); }
#basePopover button.active { background: color-mix(in srgb, var(--accent) 22%, transparent); color: #fff; font-weight: 600; }
body.light #basePopover button.active { color: var(--accent-ink); }
.app.side-collapsed #tbToggles { left: 10px; }
.edit-toolbar.tb-hidden { display: none !important; }

/* ============================================================
   VISTA MÓVIL / TABLET (Bloque 1: layout + cajón lateral)
   Todo dentro de media queries → el escritorio no se altera.
   ============================================================ */
#sideBackdrop { display: none; }
@media (max-width: 820px) {
  /* El mapa ocupa todo; la barra superior arriba (override también side-collapsed).
     minmax(0,1fr) permite que la columna se achique al ancho real del celular. */
  .app, .app.side-collapsed { grid-template-columns: minmax(0, 1fr); grid-template-areas: "top" "map"; }
  /* Barra superior: compacta y con scroll horizontal si no entra todo */
  .topbar { gap: 6px !important; padding: 0 8px; overflow-x: auto; }
  .search-box { width: auto; flex: 1 1 100px; min-width: 90px; }
  /* !important: estos selects traen max-width inline (200/170/190px) que si no ganaría */
  #projectSelect, #zoneSelect, #viewSelect { max-width: 120px !important; }
  /* El menú ☰ y los resultados de búsqueda viven DENTRO de la topbar, que en móvil
     es un contenedor con overflow-x:auto (eso también recorta en Y). position:fixed
     los saca del recorte y los ancla al viewport. */
  .app-menu { position: fixed; top: 46px; right: 6px; width: min(300px, calc(100vw - 12px));
    max-height: calc(100vh - 56px); max-height: calc(100dvh - 56px); overflow-y: auto; }
  .search-results { position: fixed; top: 46px; left: 8px; right: 8px;
    max-height: 55vh; max-height: 55dvh; }
  /* Panel lateral = cajón deslizable sobre el mapa */
  .sidebar { position: fixed; top: 44px; left: 0; bottom: 0; width: min(280px, 82vw); z-index: 1300;
    display: flex; transform: translateX(0); transition: transform .22s ease;
    box-shadow: var(--shadow-3); overflow-y: auto; }
  .app.side-collapsed .sidebar { display: flex; transform: translateX(-100%); }
  /* Fondo oscuro cuando el cajón está abierto (tocar = cerrar) */
  .app:not(.side-collapsed) #sideBackdrop { display: block; position: fixed; inset: 44px 0 0 0;
    background: #00000066; z-index: 1290; }

  /* Bloque 3: paneles flotantes como hoja inferior + overlays reubicados */
  .trace-panel { top: auto; left: 8px; right: 8px; bottom: 8px; width: auto; max-height: 62vh; }
  /* Tarjeta de info: hoja inferior casi a pantalla completa (todos los botones visibles) */
  #infoSheet { top: auto; right: 0; left: 0; bottom: 0; width: 100%; max-width: none;
    max-height: 85vh; border-radius: 16px 16px 0 0;
    animation: dfm-pop .3s cubic-bezier(.34,1.45,.42,1) both; }
  .info-head { border-radius: 16px 16px 0 0; }
  .edit-toolbar, .app.side-collapsed .edit-toolbar { top: 90px; left: 6px; right: 6px; width: auto; max-width: none; }

  /* Botones flotantes 📦/🧰: en móvil el panel es un cajón overlay (no ocupa columna),
     así que siempre van pegados al borde izquierdo, esté o no colapsado el panel. */
  #tbToggles, .app.side-collapsed #tbToggles { left: 10px; }
  .tb-vert { max-height: calc(100vh - 160px); max-height: calc(100dvh - 160px); }

  /* Modales grandes (.catalog-card): hoja inferior a todo el ancho. !important porque
     varias tarjetas traen width/height inline (p. ej. height:min(720px,94vh)). */
  .catalog-overlay { padding: 0; place-items: end center; }
  .catalog-card { width: 100vw !important; max-width: 100vw; height: auto !important;
    max-height: 96vh !important; max-height: 96dvh !important; border-radius: 14px 14px 0 0; }
  /* Formulario + lista en una sola columna; scrollea el conjunto, la página nunca desborda */
  .catalog-body { grid-template-columns: 1fr !important; overflow: auto; }
  #invPreview { border-left: 0 !important; padding-left: 0 !important; }

  /* Modales chicos (.modal-card): a todo el ancho útil (algunos traen width inline 380/420px) */
  .modal-overlay { padding: 10px; }
  .modal-card { width: 100% !important; max-width: 100%; max-height: 94vh; max-height: 94dvh; }

  /* Hoja de info: dvh para que la barra del navegador móvil no tape el final */
  #infoSheet { max-height: 85dvh; }
  /* La leyenda flotante nunca más ancha que la pantalla */
  #mapLegend { max-width: calc(100vw - 76px); }

  /* Bloque 4: objetivos táctiles + tipografía (inputs ≥16px evita el zoom de iOS).
     !important para ganarle a los tamaños específicos de cada modal (13/14px). */
  .pop-btn { width: 40px; height: 40px; font-size: 19px; }
  .tool-btn, .ghost, .trace-btn { min-height: 38px; }
  input, select, textarea, .base-select { font-size: 16px !important; }
}

/* ============================================================
   Pantallas angostas (≤640px): liberar espacio en la topbar.
   La marca y el tutorial (🎓, duplicado en ☰ → Guía de uso) se ocultan.
   ============================================================ */
@media (max-width: 640px) {
  .brand { display: none; }
  #btnTutorial { display: none; }
}

/* ============================================================
   Ajustes responsive globales (seguros también en escritorio).
   ============================================================ */
/* Menú contextual del mapa: nunca se sale de la pantalla (scrollea si es muy alto) */
.map-ctx { max-width: calc(100vw - 12px); max-height: calc(100vh - 16px); overflow-y: auto; }
/* Toast: que el texto largo envuelva en vez de desbordar */
.dfm-toast { max-width: calc(100vw - 28px); }
/* Login usable en pantallas de 320px */
.login-card { width: min(320px, calc(100vw - 28px)); }
/* Pestañas de modales creadas con estilo inline sin flex-wrap */
#usersTabs, #pzTabs, #masterUsersTabs { flex-wrap: wrap; }

/* ============================================================
   MICRO-ANIMACIONES (leves) — solo chrome/UI, NO tocan los iconos del mapa.
   Respetan "prefers-reduced-motion".
   ============================================================ */
@keyframes dfm-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes dfm-pop { from { opacity: 0; transform: translateY(18px) scale(.93); } to { opacity: 1; transform: none; } }
@keyframes dfm-menu-in { from { opacity: 0; transform: translateY(-14px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes dfm-slide-r { from { opacity: 0; transform: translateX(28px); } to { opacity: 1; transform: none; } }

/* Aparición de overlays y tarjetas modales (con leve rebote) */
.modal-overlay, .catalog-overlay { animation: dfm-fade .26s ease both; }
.modal-card, .catalog-card { animation: dfm-pop .34s cubic-bezier(.34,1.45,.42,1) both; }
/* Panel de operación (recorrido/impacto) y menú desplegable */
.trace-panel { animation: dfm-slide-r .32s cubic-bezier(.34,1.45,.42,1) both; }
.app-menu:not(.hidden) { animation: dfm-menu-in .24s cubic-bezier(.34,1.45,.42,1) both; }
/* Cuerpo de acordeón al desplegar (panel izquierdo) */
.acc.open > .acc-b { animation: dfm-pop .28s cubic-bezier(.2,.85,.3,1) both; }

/* Micro-interacciones de hover (más marcadas) */
.ghost, .tool-btn { transition: transform .14s ease, border-color .14s ease, background .14s ease, color .14s ease; }
.ghost:hover, .tool-btn:hover { transform: translateY(-2px); }
.tool-card { transition: transform .14s ease, border-color .14s ease, background .14s ease, box-shadow .14s ease; }
.tool-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-2); }
.kpi { transition: transform .12s ease, border-color .12s ease; }
.kpi:hover { transform: translateY(-1px); border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); }
.trace-btn { transition: transform .1s ease, filter .12s ease; }
.trace-btn:hover { transform: translateY(-1px); }

/* Accesibilidad: si el usuario pide menos movimiento, se desactiva todo */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}

/* ============================================================================
   ESTILO GMAIL / MATERIAL DESIGN  (reemplaza el tema anterior)
   Superficies blancas planas, sombras de elevación sutiles (no relieve),
   navegación tipo "pill", barra de búsqueda tipo Gmail, acento azul Google.
   Cubre tema claro (Gmail light) y oscuro (Gmail dark).
   Además: barras de OBJETOS y HERRAMIENTAS reubicadas a la DERECHA.
   ==========================================================================*/
:root {
  /* Dark = Gmail dark */
  --bg: #131314;
  --panel: #1e1f20;
  --panel2: #2d2e30;
  --line: #444746;
  --line-strong: #5f6368;
  --text: #e3e3e3;
  --muted: #9aa0a6;
  --accent: #a8c7fa;
  --accent-ink: #a8c7fa;
  --grad: #8ab4f8;                 /* sin gradiente: azul sólido */
  --gm-search: #1e1f20;            /* barra de búsqueda */
  --gm-search-focus: #2d2e30;
  --gm-compose: #004a77;           /* botón de acción (Compose) */
  --gm-compose-ink: #c2e7ff;
  --gm-sel: #004a77;               /* nav seleccionado */
  --gm-sel-ink: #c2e7ff;
  --gm-hover: #2d2e30;             /* nav hover */
  --sh-1: 0 1px 2px rgba(0,0,0,.45), 0 1px 3px 1px rgba(0,0,0,.30);
  --sh-2: 0 1px 3px rgba(0,0,0,.45), 0 4px 8px 3px rgba(0,0,0,.30);
  --sh-3: 0 4px 8px 3px rgba(0,0,0,.35), 0 8px 24px 6px rgba(0,0,0,.40);
  --r-card: 12px;
  --r-dialog: 28px;
  --r-pill: 999px;
  --r-field: 8px;
}
body.light {
  /* Light = Gmail light */
  --bg: #f6f8fc;
  --panel: #ffffff;
  --panel2: #f0f4f9;
  --line: #dadce0;
  --line-strong: #c4c7c5;
  --text: #1f1f1f;
  --muted: #5f6368;
  --accent: #0b57d0;
  --accent-ink: #0b57d0;
  --grad: #0b57d0;
  --gm-search: #eaf1fb;
  --gm-search-focus: #ffffff;
  --gm-compose: #c2e7ff;
  --gm-compose-ink: #001d35;
  --gm-sel: #d3e3fd;
  --gm-sel-ink: #041e49;
  --gm-hover: #ebeef2;
  --sh-1: 0 1px 2px rgba(60,64,67,.30), 0 1px 3px 1px rgba(60,64,67,.15);
  --sh-2: 0 1px 3px rgba(60,64,67,.30), 0 4px 8px 3px rgba(60,64,67,.15);
  --sh-3: 0 4px 8px 3px rgba(60,64,67,.15), 0 8px 24px 6px rgba(60,64,67,.18);
}

/* ---- Superficies base: blancas, planas, radios Material ---- */
.topbar, .sidebar { box-shadow: none !important; }
.topbar { border-bottom: 1px solid var(--line); }
.sidebar { border-right: 1px solid var(--line); }
.login-card, .app-menu, .tools-cat, .search-results,
.cl-tray, .icon-picker, .map-ctx, .dfm-toast, #presExit {
  border: 1px solid var(--line) !important;
  border-radius: var(--r-card) !important;
  box-shadow: var(--sh-2) !important;
}
.login-screen { background: var(--bg) !important; }
body.light .login-screen { background: var(--bg) !important; }

/* ---- Barra de búsqueda estilo Gmail (pill gris que se aclara al enfocar) ---- */
.search-box { width: 360px; }
.search-box input {
  background: var(--gm-search) !important;
  border: 1px solid transparent !important;
  border-radius: var(--r-pill) !important;
  padding: 10px 16px !important;
  box-shadow: none !important;
  transition: background .15s, box-shadow .15s, border-color .15s;
}
.search-box input:hover { background: var(--gm-search-focus) !important; box-shadow: var(--sh-1) !important; }
.search-box input:focus {
  background: var(--gm-search-focus) !important;
  box-shadow: var(--sh-1) !important;
  border-color: transparent !important;
  outline: none !important;
}

/* ---- Navegación de la barra lateral: ítems tipo "pill" ---- */
.tool-card, .menu-sec-acc, .acc-h {
  border: 0 !important;
  border-radius: var(--r-pill) !important;
  background: transparent !important;
  transition: background .12s ease, color .12s ease;
}
.tool-card { padding: 9px 14px !important; }
.tool-card:hover, .menu-sec-acc:hover, .acc-h:hover {
  background: var(--gm-hover) !important;
  color: var(--text) !important;
}
.tool-card.active-tool, .tool-card.active, .acc.open > .acc-h {
  background: var(--gm-sel) !important;
  color: var(--gm-sel-ink) !important;
}
.sidebar label { border-radius: var(--r-pill); padding: 6px 12px; transition: background .12s; }
.sidebar label:hover { background: var(--gm-hover); }

/* ---- Botones: Material tonal / text ---- */
.ghost {
  background: var(--panel2) !important;
  border: 1px solid transparent !important;
  border-radius: var(--r-pill) !important;
  color: var(--text) !important;
  box-shadow: none !important;
  transition: background .12s, box-shadow .12s;
}
.ghost:hover { background: var(--gm-hover) !important; box-shadow: var(--sh-1) !important; }
.app-menu .ghost { background: transparent !important; border-radius: 8px !important; }
.app-menu .ghost:hover { background: var(--gm-hover) !important; box-shadow: none !important; }
.node-btn { border-radius: var(--r-pill) !important; }

/* Botón de acción principal (estilo "Compose" celeste) */
.login-card button, .edit-finish, .modal-actions button:first-child,
.trace-btn, .welcome-actions .ghost.primary, #btnNew, .btn-new {
  background: var(--gm-compose) !important;
  color: var(--gm-compose-ink) !important;
  border: 0 !important;
  border-radius: var(--r-pill) !important;
  box-shadow: var(--sh-1) !important;
  font-weight: 600;
  transition: box-shadow .12s, filter .12s;
}
.login-card button:hover, .edit-finish:hover, .trace-btn:hover,
.modal-actions button:first-child:hover { box-shadow: var(--sh-2) !important; filter: brightness(.98); }
.edit-finish { background: #1e8e3e !important; color: #fff !important; }  /* verde acción, plano */

/* ---- Inputs: Material outlined ---- */
.login-card input, .search-box input,
.modal-card input, .modal-card select,
.catalog-form input, .catalog-form select,
.cl-form-row input, .cl-form-row select, .cl-out select, .base-select {
  border-radius: var(--r-field) !important;
}
.login-card input, .modal-card input, .modal-card select,
.catalog-form input, .catalog-form select, .cl-form-row input, .cl-form-row select {
  background: var(--panel) !important;
  border: 1px solid var(--line) !important;
  box-shadow: none !important;
  transition: border-color .12s, box-shadow .12s;
}
.login-card input:focus, .modal-card input:focus, .modal-card select:focus,
.catalog-form input:focus, .catalog-form select:focus,
.cl-form-row input:focus, .cl-form-row select:focus {
  border-color: var(--accent) !important;
  box-shadow: 0 0 0 1px var(--accent) !important;
  outline: none !important;
}

/* ---- KPIs / dash-cards: tarjetas blancas planas ---- */
.kpi, .kpi-card > *, .cl-stat {
  background: var(--panel) !important;
  border: 1px solid var(--line) !important;
  border-radius: var(--r-card) !important;
  box-shadow: var(--sh-1) !important;
}
.kpi:hover { box-shadow: var(--sh-2) !important; transform: none !important; }
.dash-card { border-radius: var(--r-card) !important; box-shadow: var(--sh-1) !important; border: 1px solid var(--line) !important; }
.dash-bar { border-radius: var(--r-pill) !important; overflow: hidden; }

/* ---- Chips / tags ---- */
.tree-node .tag, .trace-step .tag, .impact-kpi, .port-chip,
.alert-sev, .base-select, .catalog-tabs button {
  border-radius: var(--r-pill) !important;
}
.catalog-tabs button { border: 0 !important; }
.catalog-tabs button.active { background: var(--gm-sel) !important; color: var(--gm-sel-ink) !important; }

/* ---- Modales / diálogos Material ---- */
.modal-card, .catalog-card {
  border: 0 !important;
  border-radius: var(--r-dialog) !important;
  box-shadow: var(--sh-3) !important;
  background: var(--panel) !important;
}
.trace-panel { border-radius: var(--r-card) !important; box-shadow: var(--sh-2) !important; border: 1px solid var(--line) !important; }
.modal-overlay, .catalog-overlay { backdrop-filter: none; background: rgba(32,33,36,.5); }

/* ---- Popups del mapa ---- */
.maplibregl-popup-content, .leaflet-popup-content-wrapper {
  border: 1px solid var(--line) !important;
  border-radius: var(--r-card) !important;
  box-shadow: var(--sh-2) !important;
}

/* ---- Controles y botones de mapa: icon buttons Material ---- */
#mapControls button, .maplibregl-ctrl button {
  border-radius: var(--r-pill) !important;
  box-shadow: var(--sh-1) !important;
  border: 1px solid var(--line) !important;
}
#mapControls button:hover { background: var(--gm-hover) !important; }

/* =====================================================================
   BARRAS DE OBJETOS (📦) Y HERRAMIENTAS (🧰)
   En su sitio original (izquierda, junto a la barra lateral), pero
   desplegadas en HORIZONTAL: el toggle a la izquierda y los íconos en fila.
   (No se toca left/right → conserva el posicionamiento responsivo original.)
   ===================================================================*/
/* UNA SOLA PÍLDORA: el contenedor lleva el fondo/borde/sombra y envuelve
   ambas filas (objetos + herramientas). */
#tbToggles {
  flex-direction: row;
  align-items: center;
  background: var(--panel) !important;
  border: 1px solid var(--line) !important;
  border-radius: 28px !important;
  box-shadow: var(--sh-2) !important;
  padding: 6px !important;
  gap: 10px;
}
/* Cada sección: botón toggle a la izquierda + fila de íconos a su derecha */
.tb-col { flex-direction: row !important; align-items: center !important; gap: 6px; }
/* Los íconos en FILA, sin píldora propia (comparten la del contenedor) */
.tb-vert {
  flex-direction: row !important;
  flex-wrap: wrap;
  max-height: none !important;
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  border-radius: 0 !important;
  padding: 0 !important;
}
.tb-vert button { border-radius: var(--r-pill) !important; }

/* Toggles integrados en la píldora (conservan su color, sin recuadro propio) */
#tbToggles > .tb-col > button {
  border: 0 !important;
  box-shadow: none !important;
  border-radius: var(--r-pill) !important;
}
#tbToggles > .tb-col > button:hover { filter: brightness(1.06) !important; box-shadow: none !important; }

/* =====================================================================
   CAMPANA DE NOTIFICACIONES — estilo MAS-WISP
   El modal grande de alertas se muestra como un DROPDOWN anclado a la
   campana (arriba-derecha), con la lista tipo "notif-item".
   ===================================================================*/
#alertsModal { background: transparent; }
#alertsModal > .catalog-card {
  position: absolute !important; top: 52px !important; right: 14px !important; left: auto !important; margin: 0 !important;
  width: min(384px, 94vw) !important; max-height: 74vh; height: auto;
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 12px 40px rgba(0,0,0,.28);
}
#alertsModal .catalog-header { padding: 11px 14px; border-bottom: 1px solid var(--line); }
#alertsModal .catalog-header h3 { font-size: 15px; margin: 0; }
/* Filas de alerta como los items de la campana de MAS-WISP */
#alertsModal .alert-row { border-bottom: 1px solid var(--line); padding: 10px 14px; flex-wrap: wrap; }
#alertsModal .alert-row:last-child { border-bottom: 0; }
#alertsModal .alert-row:hover { background: color-mix(in srgb, var(--accent) 7%, transparent); }
/* El mensaje ocupa toda la 1ª línea; las acciones bajan a una fila, como MAS-WISP */
#alertsModal .alert-row > div[style*="flex:1"] { flex: 1 1 100% !important; }
#alertsModal .alert-acts { margin-left: 18px; margin-top: 8px; flex: 0 0 auto; }
#alertsModal .alert-acts button { border-radius: 999px; }

/* =====================================================================
   OTDR PANTALLA COMPLETA — mapa al centro, información distribuida
   (reemplaza el panel emergente .trace-panel para la herramienta OTDR).
   ===================================================================*/
.app.otdr-mode { grid-template-columns: 1fr; grid-template-rows: 1fr; grid-template-areas: "map"; }
.app.otdr-mode .topbar, .app.otdr-mode .sidebar, .app.otdr-mode #tbToggles,
.app.otdr-mode .edit-toolbar, .app.otdr-mode #mapControls { display: none !important; }
#otdrFull { position: fixed; inset: 0; z-index: 1500; pointer-events: none; display: none; }
.app.otdr-mode #otdrFull { display: block; }
#otdrFull > * { pointer-events: auto; }
/* Barra superior */
#otdrFull .of-top { position: absolute; top: 0; left: 0; right: 0; height: 46px; display: flex;
  align-items: center; gap: 14px; padding: 0 16px; background: var(--panel); border-bottom: 1px solid var(--line); box-shadow: var(--shadow-1); }
#otdrFull .of-top .of-title { font-weight: 700; letter-spacing: .04em; font-size: 14px; }
#otdrFull .of-top .of-title span { color: var(--fiber); }
#otdrFull .of-spacer { flex: 1; }
#otdrFull .of-x { background: transparent; border: 1px solid var(--line); color: var(--text);
  border-radius: 8px; padding: 6px 12px; cursor: pointer; font-size: 13px; }
#otdrFull .of-x:hover { background: var(--line); }
/* Paneles laterales */
#otdrFull .of-left, #otdrFull .of-right { position: absolute; top: 54px; bottom: 214px; width: 310px;
  background: color-mix(in srgb, var(--panel) 92%, transparent); backdrop-filter: blur(8px);
  border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow-2); overflow-y: auto; padding: 14px; }
#otdrFull .of-left { left: 12px; }
#otdrFull .of-right { right: 12px; width: 340px; }
#otdrFull .of-h { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
  font-family: 'JetBrains Mono', ui-monospace, monospace; margin: 2px 0 8px; }
#otdrFull label { display: block; font-size: 12px; opacity: .8; margin: 8px 0 3px; }
#otdrFull select, #otdrFull input { width: 100%; }
#otdrFull .of-btn { width: 100%; margin-top: 10px; background: var(--grad); color: #fff; border: 0;
  padding: 10px; border-radius: 8px; font-weight: 600; cursor: pointer; }
#otdrFull .of-btn.alt { background: transparent; border: 1px solid var(--line); color: var(--text); }
/* Franja inferior: traza reflectograma a lo ancho */
#otdrFull .of-bottom { position: absolute; left: 12px; right: 12px; bottom: 12px; height: 192px;
  background: color-mix(in srgb, var(--panel) 92%, transparent); backdrop-filter: blur(8px);
  border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow-2); padding: 10px 14px;
  display: grid; grid-template-columns: 1fr 320px; gap: 14px; }
#otdrFull .of-bottom .of-trace { min-width: 0; }
#otdrFull .of-bottom .of-events { overflow-y: auto; border-left: 1px solid var(--line); padding-left: 12px; }
#otdrFull .of-toggle { display: flex; align-items: center; gap: 8px; font-size: 12px; margin: 10px 0 2px; cursor: pointer; }
/* Veredicto de certificación */
#otdrFull .of-verdict { margin-top: 10px; border-radius: 10px; padding: 10px 12px; font-weight: 700; text-align: center; }
#otdrFull .of-verdict.pass { background: color-mix(in srgb, var(--ok) 18%, transparent); color: var(--ok-ink); }
#otdrFull .of-verdict.fail { background: color-mix(in srgb, var(--bad) 16%, transparent); color: var(--bad-ink); }
@media (max-width: 820px) {
  #otdrFull .of-left, #otdrFull .of-right { position: absolute; top: 54px; bottom: auto; width: auto; left: 8px; right: 8px; max-height: 34vh; }
  #otdrFull .of-right { top: 40vh; }
  #otdrFull .of-bottom { grid-template-columns: 1fr; height: 30vh; }
}

/* ─────────────────────────────────────────────────────────────
   Módulo Mapeo físico ODF & cross-connects (pantalla completa)
   ───────────────────────────────────────────────────────────── */
.app.odf-mode { grid-template-columns: 1fr; grid-template-rows: 1fr; grid-template-areas: "map"; }
.app.odf-mode .topbar, .app.odf-mode .sidebar, .app.odf-mode #tbToggles,
.app.odf-mode .edit-toolbar, .app.odf-mode #mapControls { display: none !important; }
#odfFull { position: fixed; inset: 0; z-index: 1500; display: none; background: var(--bg, #0b1326); }
.app.odf-mode #odfFull { display: grid; grid-template-rows: 48px 1fr; }
#odfFull .of-top { display: flex; align-items: center; gap: 8px; padding: 0 12px; background: var(--panel, #0f1830);
  border-bottom: 1px solid var(--line, #22314f); }
#odfFull .of-title { font-weight: 700; font-size: 15px; color: var(--text, #e8eefc); }
#odfFull .of-spacer { flex: 1; }
#odfFull .of-btn { background: var(--grad, linear-gradient(90deg,#0ea5e9,#2563eb)); color: #fff; border: 0;
  border-radius: 8px; padding: 7px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer; }
#odfFull .of-btn.alt { background: transparent; border: 1px solid var(--line, #22314f); color: var(--text, #e8eefc); }
#odfFull .of-body { display: grid; grid-template-columns: 340px 1fr; overflow: hidden; }
#odfFull .odf-left { border-right: 1px solid var(--line, #22314f); overflow-y: auto; padding: 10px; }
#odfFull .odf-main { overflow-y: auto; padding: 16px 20px; }
#odfFull .odf-search { width: 100%; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--line, #22314f);
  background: var(--panel2, #0b1220); color: var(--text, #e8eefc); margin-bottom: 8px; }
#odfFull .odf-item { padding: 9px 10px; border-radius: 9px; border: 1px solid var(--line, #22314f);
  margin-bottom: 6px; cursor: pointer; background: var(--panel2, #0b1220); transition: border-color .12s; }
#odfFull .odf-item:hover { border-color: #0ea5e9; }
#odfFull .odf-item.sel { border-color: #0ea5e9; box-shadow: 0 0 0 1px #0ea5e9 inset; }
#odfFull .odf-item .lbl { font-weight: 600; font-size: 13px; color: var(--text, #e8eefc); }
#odfFull .odf-item .sub { font-size: 11.5px; color: var(--muted, #8aa0c6); margin-top: 2px; }
#odfFull .odf-rx { font-weight: 700; font-variant-numeric: tabular-nums; }
#odfFull .odf-rx.ok { color: #22c55e; } #odfFull .odf-rx.warn { color: #f59e0b; } #odfFull .odf-rx.bad { color: #ef4444; }
#odfFull .odf-chain { display: flex; flex-direction: column; gap: 0; max-width: 720px; }
#odfFull .odf-node { border: 1px solid var(--line, #22314f); border-radius: 12px; padding: 12px 14px;
  background: var(--panel, #0f1830); position: relative; }
#odfFull .odf-node h5 { margin: 0 0 6px; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted, #8aa0c6); }
#odfFull .odf-node .big { font-size: 15px; font-weight: 700; color: var(--text, #e8eefc); }
#odfFull .odf-node .kv { font-size: 12.5px; color: var(--text, #e8eefc); margin-top: 3px; }
#odfFull .odf-node .kv b { color: var(--muted, #8aa0c6); font-weight: 600; }
#odfFull .odf-link { width: 2px; height: 20px; background: #0ea5e9; margin: 0 auto; }
#odfFull .odf-node.miss { border-style: dashed; opacity: .7; }
#odfFull .odf-live { margin-top: 6px; border-top: 1px dashed var(--line, #22314f); padding-top: 6px; }
#odfFull .odf-badge { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 700; }
#odfFull .odf-badge.on { background: rgba(34,197,94,.16); color: #22c55e; }
#odfFull .odf-badge.off { background: rgba(239,68,68,.16); color: #ef4444; }
#odfFull .odf-badge.warn { background: rgba(245,158,11,.16); color: #f59e0b; }
#odfFull .odf-empty { color: var(--muted, #8aa0c6); font-size: 13px; padding: 30px 10px; text-align: center; }
#odfFull .odf-banner { background: rgba(14,165,233,.12); border: 1px solid #0ea5e9; border-radius: 8px;
  padding: 6px 10px; font-size: 12px; color: var(--text, #e8eefc); margin-bottom: 8px; }
.odf-form { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.odf-form label { display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--muted, #8aa0c6); }
.odf-form input, .odf-form select { padding: 7px 9px; border-radius: 7px; border: 1px solid var(--line, #22314f);
  background: var(--panel2, #0b1220); color: var(--text, #e8eefc); font-size: 13px; }
@media (max-width: 760px) { #odfFull .of-body { grid-template-columns: 1fr; } #odfFull .odf-left { max-height: 40vh; } }

/* ─────────────────────────────────────────────────────────────
   Módulo RED — réplica 1:1 del dashboard "Servidores y OLT" de MAS-WISP.
   Paleta clara teal scoped a #redFull (aunque DAS use tema oscuro).
   ───────────────────────────────────────────────────────────── */
.app.red-mode { grid-template-columns: 1fr; grid-template-rows: 1fr; grid-template-areas: "map"; }
.app.red-mode .topbar, .app.red-mode .sidebar, .app.red-mode #tbToggles,
.app.red-mode .edit-toolbar, .app.red-mode #mapControls { display: none !important; }
#redFull {
  --bg-0:#eef3f7; --bg-1:#f5f9fb; --bg-2:#fff; --bg-3:#eef4f8; --line:#e3eaf0; --line-bright:#cfdbe4;
  --tx-0:#14303a; --tx-1:#3a5560; --tx-2:#54707c; --tx-3:#6a828e;
  --signal:#14b8a6; --signal-ink:#0a766a; --signal-dim:#5ecfc0; --info:#2f9fe0; --info-ink:#1a72ac;
  --amber:#f59e42; --amber-ink:#9a5a0e; --danger:#f0626d; --danger-ink:#c41f2d;
  --grad:linear-gradient(135deg,#14b8a6,#2f9fe0); --radius:7px; --radius-lg:12px;
  --shadow:0 1px 2px rgba(20,48,58,.05), 0 16px 34px -22px rgba(20,48,58,.30);
  position: fixed; inset: 0; z-index: 1500; display: none; background: var(--bg-0);
  color: var(--tx-1); font-size: 14px;
}
.app.red-mode #redFull { display: grid; grid-template-rows: 52px auto 1fr; }
#redFull .of-top { display: flex; align-items: center; gap: 8px; padding: 0 18px; background: var(--bg-2); border-bottom: 1px solid var(--line); }
#redFull .of-title { font-weight: 600; font-size: 18px; color: var(--tx-0); letter-spacing: -.01em; }
#redFull .of-title span { color: var(--tx-2); font-size: 13px; font-weight: 400; }
#redFull .of-spacer { flex: 1; }
#redFull .of-btn { background: var(--grad); color: #fff; border: 0; border-radius: var(--radius); padding: 9px 15px; font-size: 13px; font-weight: 600; cursor: pointer; box-shadow: 0 4px 14px -4px rgba(20,184,166,.5); }
#redFull .of-btn.alt { background: var(--bg-3); border: 1px solid var(--line-bright); color: var(--tx-0); box-shadow: none; }
.red-tabs { display: flex; gap: 4px; padding: 0 18px; background: var(--bg-2); border-bottom: 1px solid var(--line); overflow-x: auto; }
.red-tab { background: transparent; border: 0; border-bottom: 2px solid transparent; color: var(--tx-2); padding: 11px 16px; font-size: 13.5px; font-weight: 600; cursor: pointer; white-space: nowrap; margin-bottom: -1px; }
.red-tab:hover { color: var(--tx-0); }
.red-tab.active { color: var(--signal-ink); border-bottom-color: var(--signal); }
.red-body { overflow-y: auto; padding: 20px; }
.red-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(272px, 1fr)); gap: 14px; }
.red-card { background: linear-gradient(180deg, var(--bg-2), var(--bg-1)); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow); display: flex; flex-direction: column; padding: 0; overflow: hidden; transition: box-shadow .22s, border-color .22s; }
.red-card.sel { box-shadow: 0 0 0 2px var(--signal); border-color: var(--signal); }
.red-card .rc-head { padding: 13px 16px; display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; border-bottom: 1px solid var(--line); }
.red-card .rc-name { font-weight: 600; font-size: 15.5px; color: var(--tx-0); line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.red-card .rc-sub { font-size: 11.5px; color: var(--tx-2); margin-top: 1px; }
.red-card .rc-body { padding: 16px; display: flex; flex-direction: column; align-items: center; gap: 14px; flex: 1; justify-content: center; }
.red-card .rc-foot { padding: 10px 14px; border-top: 1px solid var(--line); background: var(--bg-1); display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.red-led { width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex: none; }
.red-led.on { background: var(--signal); box-shadow: 0 0 8px var(--signal); } .red-led.off { background: var(--tx-3); }
.red-badge { display: inline-flex; align-items: center; gap: 6px; font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; padding: 3px 8px; border-radius: 100px; border: 1px solid var(--line-bright); color: var(--tx-1); font-variant-numeric: tabular-nums; }
.red-badge.ok { color: var(--signal-ink); border-color: rgba(20,184,166,.28); background: rgba(20,184,166,.10); }
.red-badge.warn { color: var(--amber-ink); border-color: rgba(245,158,66,.30); background: rgba(245,158,66,.12); }
.red-badge.bad { color: var(--danger-ink); border-color: rgba(240,98,109,.30); background: rgba(240,98,109,.10); }
.red-badge.mute { color: var(--tx-2); background: var(--bg-3); border-color: var(--line); }
.red-counters { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px 6px; width: 100%; }
.red-counter { text-align: center; padding: 5px 2px; border-radius: 8px; cursor: default; }
.red-counter .n { font-size: 19px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; color: var(--tx-0); }
.red-counter .l { font-size: 9.5px; color: var(--tx-2); text-transform: uppercase; letter-spacing: .04em; margin-top: 3px; white-space: nowrap; }
.red-rings { display: flex; gap: 20px; justify-content: center; flex-wrap: wrap; }
.red-ring { display: flex; flex-direction: column; align-items: center; gap: 7px; }
.red-ring .rr-wrap { position: relative; width: 80px; height: 80px; }
.red-ring .rr-val { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: 800; color: var(--tx-0); }
.red-ring .rr-lbl { font-size: 11px; font-weight: 700; color: var(--tx-2); text-transform: uppercase; letter-spacing: .06em; }
.red-ring .rr-sub { font-size: 10.5px; color: var(--tx-2); }
.red-chips { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
.red-chip { display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px; border-radius: 999px; background: var(--bg-3); color: var(--tx-1); font-size: 12px; font-weight: 700; white-space: nowrap; }
.red-toolbar { display: flex; gap: 8px; align-items: center; margin-bottom: 14px; flex-wrap: wrap; }
.red-search { padding: 8px 11px; border-radius: var(--radius); border: 1px solid var(--line-bright); background: var(--bg-2); color: var(--tx-0); min-width: 240px; font-size: 13px; }
.red-h { font-size: 13px; font-weight: 700; color: var(--tx-2); margin: 14px 0 8px; text-transform: uppercase; letter-spacing: .04em; }
.red-table-wrap { overflow-x: auto; background: linear-gradient(180deg, var(--bg-2), var(--bg-1)); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow); }
.red-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.red-table th { text-align: left; font-size: 10px; letter-spacing: .16em; text-transform: uppercase; color: var(--tx-2); font-weight: 500; padding: 11px 16px; border-bottom: 1px solid var(--line); cursor: pointer; white-space: nowrap; position: sticky; top: 0; background: var(--bg-2); }
.red-table td { padding: 12px 16px; border-bottom: 1px solid var(--line); color: var(--tx-1); white-space: nowrap; }
.red-table tr:last-child td { border-bottom: 0; }
.red-table tbody tr { transition: background .12s; }
.red-table tbody tr:hover { background: var(--bg-3); }
.red-table td.num { font-variant-numeric: tabular-nums; color: var(--tx-0); text-align: right; }
.red-table td.strong { color: var(--tx-0); font-weight: 600; }
.red-table tr.click { cursor: pointer; }
.red-empty { color: var(--tx-3); text-align: center; padding: 36px; font-size: 12px; letter-spacing: .08em; }
.red-detail { margin-top: 16px; }
.red-metric { border: 1px solid var(--line); border-radius: 10px; padding: 12px; background: var(--bg-2); margin-bottom: 10px; }
.red-metric-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 8px; }
.red-metric-head .t { font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--tx-2); }
.red-metric-head .v { font-size: 18px; font-weight: 600; color: var(--tx-0); }
.red-axis { display: flex; gap: 6px; }
.red-axis-y { position: relative; width: 40px; flex: none; }
.red-axis-y span { position: absolute; right: 0; font-size: 9.5px; color: var(--tx-2); font-variant-numeric: tabular-nums; }
.red-chart { width: 100%; display: block; }
.red-axis-x { position: relative; height: 14px; margin-left: 46px; }
.red-axis-x span { position: absolute; font-size: 9.5px; color: var(--tx-2); font-variant-numeric: tabular-nums; }
.red-note { font-size: 12px; color: var(--tx-2); }
.red-btn-xs { background: var(--bg-3); border: 1px solid var(--line-bright); color: var(--tx-0); border-radius: 6px; padding: 4px 9px; font-size: 11.5px; font-weight: 600; cursor: pointer; }
.red-btn-xs:hover { border-color: var(--signal-dim); }
.red-btn-xs.range { background: transparent; border-color: var(--line); color: var(--tx-2); }
.red-btn-xs.range.on { background: var(--grad); color: #fff; border-color: transparent; }
@media (max-width: 760px) { #redFull .red-cards { grid-template-columns: 1fr; } }

/* ─────────────────────────────────────────────────────────────
   Área de trabajo del NODO — full-screen moderno (planta + conexiones)
   ───────────────────────────────────────────────────────────── */
.catalog-overlay.node-fs { padding: 0; align-items: stretch; justify-content: stretch; }
.node-fs .catalog-card { width: 100% !important; height: 100% !important; max-width: none; max-height: none; border-radius: 0; display: flex; flex-direction: column; }
.node-fs .catalog-header { padding: 12px 22px; border-bottom: 1px solid var(--line, #22314f); background: var(--panel, #0f1830); }
.node-fs .catalog-header h3 { font-size: 17px; font-weight: 700; }
.node-fs .catalog-body { flex: 1; min-height: 0; padding: 0 22px 18px; grid-template-rows: auto 1fr; }
.node-fs #nodeToolbar { padding-top: 12px; }
.node-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line, #22314f); margin-bottom: 14px; }
.node-tab { background: transparent; border: 0; border-bottom: 2px solid transparent; color: var(--muted, #8aa0c6); padding: 10px 18px; font-size: 14px; font-weight: 600; cursor: pointer; white-space: nowrap; margin-bottom: -1px; }
.node-tab:hover { color: var(--text, #e8eefc); }
.node-tab.active { color: var(--text, #e8eefc); border-bottom-color: #0ea5e9; }
/* Vista de conexiones dentro del nodo (mapeo físico embebido) */
.node-conx { display: grid; grid-template-columns: 340px 1fr; gap: 16px; height: 100%; min-height: 0; }
.node-conx-left { border-right: 1px solid var(--line, #22314f); padding-right: 14px; overflow-y: auto; }
.node-conx-main { overflow-y: auto; }
.node-conx .odf-node { border: 1px solid var(--line, #22314f); border-radius: 12px; padding: 12px 14px; background: var(--panel, #0f1830); }
@media (max-width: 820px) { .node-conx { grid-template-columns: 1fr; } }

/* Puertos de fibra en vivo de una OLT emparejada al módulo RED (LED parpadeante) */
.olt-live { margin: 8px 0 4px; padding: 8px 10px; border: 1px solid var(--line, #22314f); border-radius: 10px; background: rgba(14,165,233,.06); }
.olt-live-h { font-size: 11.5px; font-weight: 700; color: #38bdf8; margin-bottom: 6px; }
.pon-ports { display: flex; flex-wrap: wrap; gap: 8px; }
.pon-port { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--text, #e8eefc); padding: 3px 8px; border-radius: 7px; background: var(--panel2, #0b1220); border: 1px solid var(--line, #22314f); }
.pon-port small { color: var(--muted, #8aa0c6); }
.pon-led { display: inline-block; width: 10px; height: 10px; border-radius: 50%; flex: none; }
.pon-led.active { background: #22c55e; animation: ponBlink 1.15s ease-in-out infinite; }
.pon-led.idle { background: #475569; }
.pon-led.warn { background: #f59e0b; animation: ponBlink 1.15s ease-in-out infinite; }
@keyframes ponBlink { 0%,100% { opacity: 1; box-shadow: 0 0 4px currentColor; } 50% { opacity: .3; box-shadow: 0 0 9px currentColor; } }
.pon-led.active { color: #22c55e; } .pon-led.warn { color: #f59e0b; }

/* Tarjetas/puertos en vivo de la OLT integrada — estado por color (verde/naranja/rojo) */
.olt-legend { display: flex; gap: 14px; margin-bottom: 8px; font-size: 11px; color: var(--muted, #8aa0c6); flex-wrap: wrap; }
.olt-legend span { display: inline-flex; align-items: center; gap: 5px; }
.olt-card { margin-top: 8px; padding: 7px 9px; border: 1px solid var(--line, #22314f); border-radius: 9px; background: var(--panel, #0f1830); }
.olt-card-h { font-size: 12px; font-weight: 700; color: var(--text, #e8eefc); margin-bottom: 6px; }
.olt-card-h small { color: var(--muted, #8aa0c6); font-weight: 400; }
.pon-led.idle-orange { background: #f59e0b; color: #f59e0b; animation: ponBlink 1.6s ease-in-out infinite; }
.pon-led.fault { background: #ef4444; color: #ef4444; animation: ponBlink .7s ease-in-out infinite; }

/* Puerto conectable del nodo emparejado a un PON real: parpadea con su estado en vivo */
.port-chip.pon-live { animation: ponBlink 1.4s ease-in-out infinite; box-shadow: 0 0 0 1px rgba(255,255,255,.15) inset; }

/* Tarjeta (slot) de una OLT con su propia grilla de puertos */
.olt-slot { border: 1px solid var(--line, #22314f); border-radius: 8px; padding: 6px 8px; background: rgba(0,0,0,.10); }
.olt-slot-h { font-size: 11px; font-weight: 600; color: var(--muted, #8aa0c6); margin-bottom: 4px; }
.olt-slot-h small { font-weight: 400; }
