/* app.css — SOLO editor de flujos (React Flow / drawflow). El resto del CRM
   vive en tailwind.css (@layer components). */
/* Un poco más de aire entre la topbar y el título de cada página (Dashboard,
   Informes, Contactos…). Todas las páginas usan `.app > main ... py-6` (1.5rem);
   subimos solo el padding SUPERIOR. Gana a la utilidad `.py-6` de Tailwind por
   especificidad (.app > main). El editor en fullscreen no se ve afectado: su
   layout es position:fixed y además `.content` fuerza padding 0. */
.app > main { padding-top: 2.25rem; }

/* ───────────── Flow canvas (editor visual de flujos) ───────────── */
.flow-editor-layout {
  display: grid;
  grid-template-columns: 1fr 480px;
  gap: 0.75rem;
  align-items: stretch;
}
@media (max-width: 1100px) {
  .flow-editor-layout { grid-template-columns: 1fr; }}
.flow-canvas-card {
  position: relative;
  background: var(--bg-card, var(--bg));
  border: 1px solid var(--border, hsl(243 30% 88%));
  border-radius: 12px;
  /* IMPORTANTE: overflow hidden — el pan/zoom lo hacemos vía viewBox.
     Si dejamos auto, la rueda hace scroll y se rompe el zoom. */
  overflow: hidden;
  min-height: 560px;
  height: 70vh;
  max-height: 820px;
  display: flex; flex-direction: column;
}
.flow-canvas-banner {
  flex: 0 0 auto;
  padding: 0.4rem 0.75rem;
  font-size: 0.78rem;
  background: var(--surface-2, var(--bg-soft));
  border-bottom: 1px solid var(--border, hsl(243 30% 88%));
  color: var(--muted);
}
/* Toolbar flotante en la esquina superior derecha del canvas */
.flow-canvas-toolbar {
  position: absolute;
  top: 36px;
  right: 8px;
  z-index: 3;
  display: flex;
  gap: 2px;
  padding: 3px;
  background: var(--bg-card, var(--bg));
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.flow-canvas-toolbar button {
  appearance: none;
  background: transparent;
  border: none;
  color: var(--text);
  font-size: 1rem;
  font-weight: 600;
  width: 26px; height: 26px;
  border-radius: 4px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.flow-canvas-toolbar button:hover {
  background: var(--accent-soft);
  color: var(--accent);
}
/* Acciones de prueba: pill flotante DENTRO del lienzo, arriba-izquierda (el zoom va a
   la derecha, los Controls de React Flow abajo-izquierda → esta esquina queda libre).
   Mismo lenguaje visual que la toolbar de zoom: superficie con borde+sombra, botones
   compactos. El primario va en acento (descubrible); el visual, discreto. */
.flow-canvas-actions {
  position: absolute;
  top: 10px;
  left: 8px;
  z-index: 4;
  display: flex;
  gap: 3px;
  padding: 3px;
  background: var(--bg-card, var(--bg));
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.flow-canvas-actions .btn {
  height: 26px;
  padding: 0 10px;
  font-size: 0.72rem;
  font-weight: 600;
  border: none;
  border-radius: 5px;
  box-shadow: none;
  white-space: nowrap;
}
/* Iconos de la paleta: monocromo, tamaño fijo, tono atenuado (sin emojis a color). */
.flow-palette .pi-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.2em;
  color: var(--muted);
  font-variant-emoji: text;
  font-size: 0.95em;
}
.flow-palette .palette-item:hover .pi-icon { color: var(--accent); }
.flow-palette .pi-icon svg { width: 1.05em; height: 1.05em; }

/* Iconos SVG inline (sprite #i-*): heredan color del texto, sin emojis a color.
   `.ico` para usos sueltos; `.icon svg` para los <span class="icon"> de cabeceras. */
.ico { width: 1.1em; height: 1.1em; display: inline-block; vertical-align: -0.15em; flex-shrink: 0; }
.icon svg { width: 1.1em; height: 1.1em; vertical-align: -0.15em; }

.flow-canvas-banner[data-kind="error"]  { color: hsl(0 70% 55%); }
.flow-canvas-banner[data-kind="warn"]   { color: hsl(35 90% 50%); }
.flow-canvas-banner[data-kind="ok"]     { color: hsl(155 60% 38%); }

#flow-canvas {
  flex: 1 1 auto;
  min-height: 0;        /* permite que flex shrink funcione */
  cursor: grab;
  position: relative;
  background: var(--bg-soft, var(--bg));
}
#flow-canvas.panning { cursor: grabbing; }

/* Paleta lateral del flow editor */
.flow-editor-layout {
  grid-template-columns: 160px 1fr 420px;
}
@media (max-width: 1280px) {
  .flow-editor-layout { grid-template-columns: 1fr; }
  .flow-palette { display: none; }}
.flow-palette {
  border: 1px solid var(--border, hsl(243 30% 88%));
  border-radius: 12px;
  padding: 0.5rem;
  background: var(--bg-card, var(--bg));
  display: flex; flex-direction: column;
  max-height: 720px;
  overflow-y: auto;
}
.flow-palette h3 {
  margin: 0 0 0.5rem 0;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.flow-palette h4 {
  margin: 0.6rem 0 0.3rem 0;
  font-size: 0.7rem;
  text-transform: uppercase;
  color: var(--muted);
  letter-spacing: 0.05em;
}
.palette-group { display: flex; flex-direction: column; gap: 0.2rem; }
.palette-item {
  appearance: none;
  background: transparent;
  border: 1px solid var(--border, hsl(243 30% 88%));
  color: var(--text);
  text-align: left;
  font-size: 0.78rem;
  padding: 0.32rem 0.5rem;
  border-radius: 6px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  transition: background 100ms ease, border-color 100ms ease;
}
.palette-item:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
}
.pi-icon {
  display: inline-block;
  width: 16px; text-align: center;
  font-size: 0.95rem;
  color: var(--accent);
}

/* Inspector flotante del flow editor */
.flow-canvas-card { position: relative; }
.flow-inspector-link, .flow-inspector-close {
  appearance: none;
  background: transparent;
  border: 1px solid transparent;
  color: var(--muted);
  font-size: 0.75rem;
  padding: 0.1rem 0.4rem;
  border-radius: 4px;
  cursor: pointer;
}
.flow-inspector-link:hover, .flow-inspector-close:hover {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent);
}

/* Modo Probar — modal */
.flow-test-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: color-mix(in oklab, var(--bg) 40%, rgba(6,4,14,.7));
  -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px);
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
  animation: vx-modal-in .18s ease both;
}
/* `hidden` attribute necesita ganar al display:flex de arriba.
   Sin esto el modal seguía visible y capturando todos los clicks
   (bloqueando el canvas debajo). */
.flow-test-modal[hidden] { display: none !important; }
/* Animación de SALIDA (cierre): el JS añade .is-closing, espera a que termine y
   entonces oculta. Sin esto el modal desaparecía de golpe (se veía forzado). */
@keyframes vx-modal-out { from { opacity: 1 } to { opacity: 0 } }
@keyframes vx-modal-pop-out { from { opacity: 1; transform: none } to { opacity: 0; transform: translateY(8px) scale(.985) } }
.flow-test-modal.is-closing { animation: vx-modal-out .16s ease both; }
.flow-test-modal.is-closing .flow-test-card { animation: vx-modal-pop-out .16s ease both; }
@media (prefers-reduced-motion: reduce) {
  .flow-test-modal, .flow-test-card, .fe-modal-backdrop, .fe-modal { animation: none !important }
}
.flow-test-card {
  background: var(--bg-card, var(--bg));
  border: 1px solid var(--border);
  border-radius: 12px;
  width: 880px; max-width: 100%;
  max-height: 90vh;
  animation: vx-modal-pop .22s var(--ease-out) both;
  overflow: hidden;
  display: flex; flex-direction: column;
  box-shadow: 0 24px 60px -16px rgba(0,0,0,0.5);
}
.flow-test-card > header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.6rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2, var(--bg-soft));
}
.flow-test-card > header h3 { margin: 0; font-size: 1rem; }
.flow-test-body {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 1rem;
  padding: 1rem;
  overflow: auto;
}
@media (max-width: 720px) {
  .flow-test-body { grid-template-columns: 1fr; }}
.flow-test-form { display: flex; flex-direction: column; gap: 0.6rem; }
.flow-test-output { min-height: 360px; }
.ft-status {
  padding: 0.4rem 0.6rem;
  border-radius: 6px;
  font-size: 0.85rem;
  background: var(--bg-soft, var(--bg));
  margin-bottom: 0.5rem;
}
.ft-status[data-kind="error"] { color: hsl(0 75% 55%); background: hsl(0 88% 96%); }
/* Inspector de variables del simulador */
.ft-vars { display: flex; flex-direction: column; gap: 3px; font-size: 0.82rem; }
.ft-vars-empty { color: var(--muted); }
.ft-var-row { display: flex; gap: 8px; align-items: baseline; padding: 2px 0; border-bottom: 1px dashed var(--border); }
.ft-var-k { font-family: ui-monospace, monospace; color: var(--accent); white-space: nowrap; }
.ft-var-v { color: var(--text); word-break: break-word; }
[data-theme="dark"] .ft-status[data-kind="error"] { background: hsl(0 50% 18%); color: hsl(0 75% 65%); }
.ft-status[data-kind="ok"] { color: hsl(155 60% 38%); }
.flow-test-output h4 {
  margin: 0.5rem 0 0.3rem;
  font-size: 0.7rem;
  text-transform: uppercase;
  color: var(--muted);
  letter-spacing: 0.05em;
}
.ft-trace, .ft-audio {
  list-style: none; padding: 0; margin: 0;
  font-size: 0.78rem;
  font-family: ui-monospace, monospace;
}
.ft-trace-item, .ft-audio li {
  display: flex; gap: 0.5rem; align-items: baseline;
  padding: 0.2rem 0.4rem;
  border-radius: 4px;
}
.ft-trace-item:hover { background: var(--bg-soft, var(--bg)); }
.ft-trace-item code { font-weight: 600; }
.ft-trace-item.ft-enter { border-left: 3px solid var(--accent); }
.ft-trace-item.ft-exit  { border-left: 3px solid var(--muted); }
.ft-trace-item.ft-error { border-left: 3px solid hsl(0 75% 55%); }
.ft-trace-item.ft-hook_jump { border-left: 3px solid hsl(35 90% 50%); }
.ft-trace-item.ft-done { border-left: 3px solid hsl(155 60% 38%); }
.ft-kind {
  font-size: 0.65rem;
  padding: 0 0.3rem;
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 3px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
  flex-shrink: 0;
}

/* Highlight nodos visitados tras un test_run */
.flow-node.visited .flow-node-bg {
  stroke-width: 2.5;
  filter: brightness(1.05);
}
.flow-node.visited::after {
  content: ""; /* marker visual */
}

/* Tabs del Test modal */
.flow-test-card > header { gap: 0; }
.ft-tabs { display: flex; gap: 0.25rem; }
.ft-tab {
  background: transparent;
  border: 1px solid transparent;
  color: var(--muted);
  font-size: 0.85rem;
  padding: 0.3rem 0.7rem;
  border-radius: 6px;
  cursor: pointer;
}
.ft-tab.active {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent);
}

/* Keypad DTMF */
.ft-keypad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.3rem;
  margin: 0.5rem 0;
}
.ft-keypad button {
  appearance: none;
  background: var(--surface-2, var(--bg-soft));
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 1.15rem;
  font-weight: 600;
  padding: 0.55rem;
  border-radius: 8px;
  cursor: pointer;
  transition: background 80ms ease, transform 80ms ease;
}
.ft-keypad button:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
}
.ft-keypad button:active { transform: scale(0.96); }

/* Highlight del nodo activo en modo interactivo */
.flow-node.active .flow-node-bg {
  stroke-width: 3;
  filter: drop-shadow(0 0 8px var(--accent, hsl(243 75% 59%)));
}

/* ───────── Drawflow custom skin ───────── */
/* Drawflow trae su propio CSS; aquí estilamos solo el contenido custom
   de cada nodo (.df-card) y el contenedor para encajar con el resto. */
.drawflow {
  width: 100%; height: 100%;
  background: var(--bg-soft, #f7f8fb);
  background-image:
    radial-gradient(circle, var(--border, #ddd) 1px, transparent 1px);
  background-size: 16px 16px;
}
.drawflow .drawflow-node {
  background: transparent;
  border: none !important;
  padding: 0;
  min-width: 200px;
}
.drawflow .drawflow-node .df-card {
  background: var(--bg, #fff);
  border: 2px solid;
  border-radius: 10px;
  padding: 8px 10px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
  min-width: 200px;
}
[data-theme="dark"] .drawflow .drawflow-node .df-card {
  background: var(--surface, hsl(220 17% 12%));
  box-shadow: 0 2px 8px rgba(0,0,0,0.4);
}
.drawflow .drawflow-node .input,
.drawflow .drawflow-node .output {
  background: var(--accent, #6366f1);
  border: 2px solid var(--bg, #fff);
  width: 14px; height: 14px;
}
.drawflow .drawflow-node .output { right: -7px; }
.drawflow .drawflow-node .input { left: -7px; }
.drawflow .connection .main-path {
  stroke: var(--muted, #888);
  stroke-width: 2;
}
.drawflow .connection .main-path:hover {
  stroke: var(--accent);
  cursor: pointer;
}
.drawflow .drawflow-node.selected .df-card {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ═════════════════════════════════════════════════════════════════════
   FLOW EDITOR — SaaS skin override (Linear/Notion/Vercel inspired)
   ═════════════════════════════════════════════════════════════════════
   Este bloque va AL FINAL y sobreescribe todo lo anterior con un look
   profesional. Variables CSS se respetan; light + dark mode soportados. */

/* ── Layout general ────────────────────────────────────────────────── */
.flow-editor-layout {
  display: grid;
  grid-template-columns: 200px 1fr 380px;
  gap: 12px;
  align-items: stretch;
}
@media (max-width: 1280px) {
  .flow-editor-layout { grid-template-columns: 1fr; }
  .flow-palette { display: none; }}

/* ── Canvas card ──────────────────────────────────────────────────── */
.flow-canvas-card {
  position: relative;
  background: var(--surface, #fff);
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
  min-height: 600px;
  height: 75vh;
  max-height: 900px;
  display: flex; flex-direction: column;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}

.flow-canvas-banner {
  flex: 0 0 auto;
  padding: 0.55rem 1rem;
  font-size: 0.78rem;
  font-weight: 500;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  color: var(--muted);
  letter-spacing: -0.01em;
  display: flex; align-items: center; gap: 0.5rem;
}
.flow-canvas-banner::before {
  content: "";
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--muted);
  flex: 0 0 auto;
}
.flow-canvas-banner[data-kind="ok"]::before    { background: hsl(155 60% 45%); }
.flow-canvas-banner[data-kind="warn"]::before  { background: hsl(35 90% 55%); }
.flow-canvas-banner[data-kind="error"]::before { background: hsl(0 75% 55%); }
.flow-canvas-banner[data-kind="error"] { color: hsl(0 75% 55%); }
.flow-canvas-banner[data-kind="warn"]  { color: hsl(35 80% 45%); }
.flow-canvas-banner[data-kind="ok"]    { color: hsl(155 50% 38%); }

/* ── Toolbar flotante (glassmorphism) ─────────────────────────────── */
.flow-canvas-toolbar {
  position: absolute;
  top: 52px;
  right: 16px;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 4px;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 4px 16px -4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.04);
}
[data-theme="dark"] .flow-canvas-toolbar {
  background: rgba(30, 32, 40, 0.85);
}
.flow-canvas-toolbar button {
  appearance: none;
  background: transparent;
  border: none;
  color: var(--text-2);
  font-size: 1rem;
  font-weight: 500;
  width: 30px; height: 30px;
  border-radius: 6px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 120ms ease, color 120ms ease;
}
.flow-canvas-toolbar button:hover {
  background: var(--accent-soft);
  color: var(--accent);
}
.flow-canvas-toolbar button:active {
  transform: scale(0.94);
}
/* Separador entre el grupo de vista (zoom/fit/fullscreen) y el de documento
   (exportar/importar) en la toolbar del canvas. */
.flow-toolbar-sep {
  width: 1px;
  align-self: stretch;
  margin: 4px 2px;
  background: var(--border);
}

/* ── Canvas / fondo ────────────────────────────────────────────────── */
#flow-canvas {
  flex: 1 1 auto;
  min-height: 0;
  cursor: grab;
  position: relative;
  background: var(--bg-soft);
}
#flow-canvas.panning { cursor: grabbing; }

/* Drawflow container — fondo dot grid sutil estilo Figma */
.drawflow {
  width: 100%; height: 100%;
  background-color: var(--bg-soft);
  background-image:
    radial-gradient(circle at 1px 1px, var(--border-strong, hsl(220 13% 82%)) 1px, transparent 0);
  background-size: 20px 20px;
}
[data-theme="dark"] .drawflow {
  background-image:
    radial-gradient(circle at 1px 1px, hsl(220 15% 22%) 1px, transparent 0);
}

/* ── Nodos drawflow (cards Linear-style) ──────────────────────────── */
.drawflow .drawflow-node {
  all: unset;
  position: absolute;
  display: block !important;
  padding: 0;
  background: transparent !important;
  border: none !important;
  min-width: 220px;
  border-radius: 12px;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.05))
          drop-shadow(0 4px 8px rgba(0, 0, 0, 0.04));
  transition: filter 160ms ease, transform 160ms ease;
  cursor: grab;
}
.drawflow .drawflow-node:active { cursor: grabbing; }
.drawflow .drawflow-node:hover {
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.08))
          drop-shadow(0 12px 24px -4px rgba(0, 0, 0, 0.08));
  transform: translateY(-1px);
}
.drawflow .drawflow-node.selected {
  background: transparent !important;
}
.drawflow .drawflow-node.selected .df-card {
  border-color: var(--accent) !important;
  box-shadow:
    0 0 0 3px var(--accent-soft),
    0 4px 12px rgba(0, 0, 0, 0.06);
}

.drawflow .drawflow-node .drawflow_content_node {
  width: 100%;
  display: block;
}

/* ── Puertos input/output ──────────────────────────────────────────── */
.drawflow .drawflow-node .input,
.drawflow .drawflow-node .output {
  width: 10px; height: 10px;
  background: var(--surface, #fff);
  border: 2px solid var(--df-accent, var(--muted));
  cursor: crosshair;
  transition: transform 120ms ease, background 120ms ease, border-color 120ms ease;
  z-index: 4;
}
[data-theme="dark"] .drawflow .drawflow-node .input,
[data-theme="dark"] .drawflow .drawflow-node .output {
  background: hsl(220 17% 14%);
}
.drawflow .drawflow-node .output { right: -6px; }
.drawflow .drawflow-node .input  { left:  -6px; top: 0; }

.drawflow .drawflow-node .output:hover,
.drawflow .drawflow-node .input:hover {
  transform: scale(1.4);
  background: var(--df-accent, var(--accent));
}
.drawflow .drawflow-node:hover .df-port-label { opacity: 0.95; }

/* ── Conexiones ────────────────────────────────────────────────────── */
.drawflow .connection .main-path {
  stroke: var(--border-strong, #b0b6c2);
  stroke-width: 2;
  fill: none;
  transition: stroke 120ms ease, stroke-width 120ms ease;
}
.drawflow .connection .main-path:hover {
  stroke: var(--accent);
  stroke-width: 2.5;
  cursor: pointer;
}
.drawflow .connection .main-path.selected {
  stroke: hsl(0 75% 55%);
  stroke-width: 2.5;
}
.drawflow .connection .point {
  fill: var(--surface);
  stroke: var(--accent);
  stroke-width: 2;
  r: 4;
}
[data-theme="dark"] .drawflow .connection .point { fill: hsl(220 17% 14%); }

/* ── Paleta lateral ────────────────────────────────────────────────── */
.flow-palette {
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 12px 10px;
  background: var(--surface);
  display: flex; flex-direction: column;
  max-height: 75vh;
  overflow-y: auto;
  box-shadow: 0 1px 3px rgba(0,0,0,0.04);
}
.flow-palette h3 {
  margin: 0 0 10px 4px;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.flow-palette h4 {
  margin: 12px 4px 6px;
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--muted);
  letter-spacing: 0.08em;
}
.palette-group { display: flex; flex-direction: column; gap: 2px; }
.palette-item {
  appearance: none;
  background: transparent;
  border: 1px solid transparent;
  color: var(--text);
  text-align: left;
  font-size: 0.82rem;
  font-weight: 500;
  padding: 6px 9px;
  border-radius: 7px;
  cursor: pointer;
  display: flex; align-items: center; gap: 8px;
  transition: background 100ms ease, border-color 100ms ease, transform 100ms ease;
  letter-spacing: -0.005em;
}
.palette-item:hover {
  background: var(--accent-soft);
  border-color: transparent;
}
.palette-item:active { transform: translateX(1px); }
.palette-item::before {
  content: "";
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--pi-color, var(--muted));
  flex: 0 0 auto;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--pi-color, var(--muted)) 20%, transparent);
}
.pi-icon { display: none; }     /* ya teníamos un span .pi-icon — lo escondemos */

/* Color del dot por tipo de nodo (alineado con --df-accent del nodo). */
.palette-item[data-node-type="play_audio"],
.palette-item[data-node-type="tts"],
.palette-item[data-node-type="beep"],
.palette-item[data-node-type="silence"]                 { --pi-color: hsl(262 83% 58%); }
.palette-item[data-node-type="menu"],
.palette-item[data-node-type="collect_digits"]          { --pi-color: hsl(35 92% 55%); }
.palette-item[data-node-type="business_hours_gate"]     { --pi-color: hsl(45 90% 55%); }
.palette-item[data-node-type="from_match"],
.palette-item[data-node-type="var_match"],
.palette-item[data-node-type="switch"]                  { --pi-color: hsl(217 91% 60%); }
.palette-item[data-node-type="ring_extension"],
.palette-item[data-node-type="ring_group"],
.palette-item[data-node-type="queue"]                   { --pi-color: hsl(189 94% 43%); }
.palette-item[data-node-type="forward"],
.palette-item[data-node-type="voicemail"],
.palette-item[data-node-type="transfer"]                { --pi-color: hsl(330 81% 60%); }
.palette-item[data-node-type="hangup"]                  { --pi-color: hsl(0 75% 55%); }
.palette-item[data-node-type="terminal"]                { --pi-color: hsl(155 60% 45%); }
.palette-item[data-node-type="set_var"],
.palette-item[data-node-type="log_event"],
.palette-item[data-node-type="delay"]                   { --pi-color: hsl(220 9% 55%); }
.flow-inspector-link, .flow-inspector-close {
  appearance: none;
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 500;
  padding: 4px 8px;
  border-radius: 5px;
  cursor: pointer;
  transition: background 100ms ease, color 100ms ease;
}
.flow-inspector-close:hover { background: var(--bg-soft); color: var(--text); }

/* ═══ Conexiones + puertos — versión legibilidad clara ═══════════════
   Pasada de mejora: flechas, edges más gruesas, labels siempre visibles,
   contraste de puertos. */

/* Puertos: más grandes (12px) y con relleno del color del tipo
   semi-transparente — se ven incluso cuando no hay hover. */
.drawflow .drawflow-node .input,
.drawflow .drawflow-node .output {
  width: 13px; height: 13px;
  background: color-mix(in srgb, var(--df-accent, #888) 35%, var(--surface));
  border: 2px solid var(--df-accent, var(--muted));
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.5);
}
[data-theme="dark"] .drawflow .drawflow-node .input,
[data-theme="dark"] .drawflow .drawflow-node .output {
  background: color-mix(in srgb, var(--df-accent, #888) 30%, hsl(220 17% 14%));
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4);
}
.drawflow .drawflow-node .output { right: -7px; }
.drawflow .drawflow-node .input  { left:  -7px; }
.drawflow .drawflow-node .output:hover,
.drawflow .drawflow-node .input:hover {
  transform: scale(1.5);
  background: var(--df-accent, var(--accent));
}

/* Edges: más gruesas, color de contraste, con flecha al final */
.drawflow .connection { color: var(--border-strong, hsl(220 13% 70%)); }
[data-theme="dark"] .drawflow .connection { color: hsl(220 14% 40%); }

.drawflow .connection .main-path {
  stroke: currentColor;
  stroke-width: 2.5;
  stroke-linecap: round;
  fill: none;
  marker-end: url(#flow-arrow);
  transition: stroke-width 120ms ease, color 120ms ease, filter 120ms ease;
}
.drawflow .connection:hover { color: var(--accent); }
.drawflow .connection:hover .main-path {
  stroke-width: 3;
  filter: drop-shadow(0 0 4px color-mix(in srgb, var(--accent) 50%, transparent));
}
.drawflow .connection .main-path.selected {
  color: hsl(0 75% 55%);
  stroke-width: 3;
}

/* Cuando el nodo está seleccionado, resaltar también sus conexiones
   próximas (efecto sutil): los outputs y el connector cercano se ven más. */
.drawflow .drawflow-node.selected .output {
  background: var(--df-accent);
  transform: scale(1.15);
}

/* Mientras se hace drag de un puerto, el cursor cambia para indicar
   conexión en progreso. */
.drawflow .drawflow-node .output:active,
.drawflow .drawflow-node .input:active {
  cursor: grabbing;
}

/* Asegurar que el puerto no quede oculto por el .df-card al hacer hover */
.drawflow .drawflow-node .outputs,
.drawflow .drawflow-node .inputs {
  position: absolute;
  top: 0; bottom: 0;
  display: flex; flex-direction: column;
  justify-content: space-around;
  z-index: 5;
}
.drawflow .drawflow-node .outputs { right: 0; }
.drawflow .drawflow-node .inputs  { left:  0; }
.drawflow .drawflow-node.selected .df-card {
  border-color: var(--df-accent, var(--accent)) !important;
  box-shadow:
    0 0 0 3px color-mix(in srgb, var(--df-accent, var(--accent)) 18%, transparent),
    0 8px 24px -8px rgba(15, 23, 42, 0.12) !important;
}

/* ── Edges con flowing animation y arrow ───────────────────────────── */
.drawflow .connection .main-path {
  stroke-dasharray: 6 4;
  animation: flow-dash 1.2s linear infinite;
  animation-play-state: paused;
}
.drawflow .connection:hover .main-path,
.drawflow .drawflow-node:hover ~ * .connection .main-path {
  animation-play-state: running;
}
@keyframes flow-dash { to { stroke-dashoffset: -20; } }

/* ── Drag desde paleta al canvas ───────────────────────────────────── */
.palette-item[draggable="true"] { cursor: grab; }
.palette-item.dragging { opacity: 0.5; }

/* Hover de card más sutil */
.drawflow .drawflow-node:hover .df-card {
  border-color: color-mix(in srgb, var(--df-accent, #888) 30%, var(--border));
}

/* Selected ring del card más currado */
.drawflow .drawflow-node.selected .df-card {
  border-color: var(--df-accent, var(--accent)) !important;
  box-shadow:
    0 0 0 4px color-mix(in srgb, var(--df-accent, var(--accent)) 16%, transparent),
    0 10px 30px -8px color-mix(in srgb, var(--df-accent, var(--accent)) 35%, transparent) !important;
}

/* ═════════════════════════════════════════════════════════════════════
   REACT FLOW EDITOR — sustituye drawflow. Estilo Dify/n8n.
   ═════════════════════════════════════════════════════════════════════ */
.rfwrap {
  width: 100%; height: 100%;
  position: relative;
  display: flex; flex-direction: column;
}
.rfbanner {
  flex: 0 0 auto;
  padding: 0.55rem 1rem;
  font-size: 0.78rem;
  font-weight: 500;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  color: var(--muted);
  display: flex; align-items: center; gap: 0.5rem;
  letter-spacing: -0.01em;
}
.rfbanner::before {
  content: "";
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--muted);
  flex: 0 0 auto;
}
.rfbanner[data-kind="ok"]::before    { background: hsl(155 60% 45%); }
.rfbanner[data-kind="warn"]::before   { background: hsl(35 90% 55%); }
.rfbanner[data-kind="error"]::before  { background: hsl(0 75% 55%); }
.rfbanner[data-kind="error"] { color: hsl(0 75% 55%); }
.rfbanner[data-kind="warn"]  { color: hsl(35 80% 45%); }
.rfbanner[data-kind="ok"]    { color: hsl(155 50% 38%); }

/* Sobreescribir el background del pane React Flow */
.react-flow {
  background: var(--bg-soft, #f6f7f9);
}
[data-theme="dark"] .react-flow {
  background: hsl(220 17% 9%);
}
.react-flow__minimap {
  bottom: 12px !important;
  right: 12px !important;
}
.react-flow__controls {
  bottom: 12px !important;
  left: 12px !important;
  box-shadow: 0 4px 12px rgba(0,0,0,0.08) !important;
  border-radius: 8px !important;
  overflow: hidden;
  border: 1px solid var(--border) !important;
}
.react-flow__controls-button {
  background: var(--surface) !important;
  border-bottom: 1px solid var(--border) !important;
  color: var(--text) !important;
}
.react-flow__controls-button:hover {
  background: var(--accent-soft) !important;
  color: var(--accent) !important;
}
.react-flow__controls-button svg { fill: currentColor; }

/* ── Nodo custom (fn-card) ─────────────────────────────────────────── */
.fn-card {
  background: var(--surface, #fff);
  border: 1px solid var(--border);
  border-radius: 14px;
  min-width: 260px;
  max-width: 280px;
  overflow: hidden;
  font-family: var(--font-sans);
  transition: box-shadow 160ms ease, border-color 160ms ease, transform 160ms ease;
}
[data-theme="dark"] .fn-card {
  background: hsl(220 17% 14%);
  border-color: hsl(220 14% 22%);
}
.fn-card:hover { transform: translateY(-1px); }

.fn-header {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid color-mix(in srgb, var(--accent, #888) 18%, transparent);
}
.fn-icon {
  width: 24px; height: 24px;
  border-radius: 7px;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 1px 3px color-mix(in srgb, var(--accent, #888) 50%, transparent);
  flex: 0 0 auto;
}
.fn-type {
  font-family: ui-monospace, monospace;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fn-badge {
  font-size: 0.58rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  padding: 2px 7px;
  border-radius: 4px;
  background: hsl(155 55% 38%);
  color: white;
  flex: 0 0 auto;
}
.fn-body {
  padding: 12px 14px 14px;
}
.fn-id {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 8px;
  padding-bottom: 8px;
  border-bottom: 1px dashed var(--border);
  letter-spacing: -0.01em;
}
.fn-fields {
  display: flex; flex-direction: column;
  gap: 6px;
}
.fn-field {
  display: grid;
  grid-template-columns: 92px 1fr;
  align-items: center;
  gap: 8px;
  font-size: 0.78rem;
}
.fn-field-lbl {
  color: var(--text-2);
  font-size: 0.72rem;
  font-weight: 600;
  /* Antes: monospace + nowrap + ellipsis → labels largas ("máx en cola
     (desborde)") se cortaban con "…". Ahora envuelven a 2 líneas y usan la
     fuente de la app (se lee como producto, no como código). */
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.2;
}
.fn-field-input, .fn-field-select {
  width: 100%;
  padding: 4px 8px;
  border: 1px solid transparent;
  background: var(--bg-soft, #f6f7f9);
  color: var(--text);
  border-radius: 5px;
  font-size: 0.78rem;
  font-family: inherit;
  outline: none;
  transition: background 100ms, border-color 100ms, box-shadow 100ms;
  min-width: 0;
}
[data-theme="dark"] .fn-field-input,
[data-theme="dark"] .fn-field-select {
  background: hsl(220 17% 10%);
}
.fn-field-input:hover, .fn-field-select:hover {
  background: var(--surface);
  border-color: var(--border);
}
.fn-field-input:focus, .fn-field-select:focus {
  background: var(--surface);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
.fn-field-cb {
  width: 16px; height: 16px;
  accent-color: var(--accent);
  cursor: pointer;
  justify-self: start;
}
.fn-field-vert {
  grid-template-columns: 1fr;
  align-items: stretch;
  gap: 4px;
}
.fn-field-textarea {
  resize: vertical;
  min-height: 56px;
  font-family: ui-monospace, monospace;
  line-height: 1.35;
}

/* Descripción VISIBLE bajo el label de un campo (spec.desc) — modales detallados (ai_agent). */
.fn-field-desc {
  font-size: 0.74rem;
  color: var(--muted);
  font-weight: 400;
  line-height: 1.4;
}
/* Descripción de la OPCIÓN elegida en un select_labeled (p.ej. preset de VAD):
   se actualiza al cambiar, con un realce sutil del acento. */
.fn-field-opthint {
  font-size: 0.74rem; line-height: 1.4; margin-top: 5px; padding: 6px 9px;
  color: var(--text-2, var(--muted)); background: var(--bg-soft);
  border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: 7px;
}
/* Etiqueta hoverable (modales, SIN icono): subrayado punteado + tooltip flotante (hover 0,5 s). */
.fn-field-lbl-tip { cursor: help; border-bottom: 1px dotted var(--border); align-self: flex-start; }
.fn-field-lbl-tip:hover { color: var(--accent); border-bottom-color: var(--accent); }
.fn-desc-pop {
  z-index: 10001; max-width: 280px; padding: 9px 12px; border-radius: 9px;
  background: var(--surface); color: var(--text); border: 1px solid var(--border);
  box-shadow: 0 10px 30px rgba(0,0,0,.30); font-size: 12px; line-height: 1.5;
  pointer-events: none; font-weight: 400; letter-spacing: normal; text-transform: none;
  animation: descPopIn 120ms ease-out;
}
@keyframes descPopIn { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }

/* Modal "Agente de IA": layout VERTICAL y holgado — los selects del nodo iban muy justos. */
.agent-brain { gap: 14px; }
.agent-brain-section {
  display: flex; flex-direction: column; gap: 12px;
  padding: 14px 16px; border: 1px solid var(--border); border-radius: 12px;
  background: color-mix(in srgb, var(--text) 3%, var(--surface));
}
/* Filas de "audios periódicos" del nodo Cola — etiquetadas e intuitivas. */
.periodic-row {
  display: flex; flex-direction: column; gap: 7px;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: 9px; background: var(--surface);
}
.periodic-line { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; }
.periodic-lbl { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); min-width: 50px; }
.periodic-unit { font-size: 0.78rem; color: var(--muted); }
.periodic-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.periodic-sum { font-size: 0.74rem; color: var(--accent); line-height: 1.4; }
.periodic-sum.warn { color: var(--danger, #dc2626); }
.agent-brain-section-title {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text);
  display: flex; align-items: center; gap: 7px;
  padding-left: 9px; border-left: 3px solid var(--accent);
}
.agent-brain-section-desc {
  font-size: 0.77rem; color: var(--muted); line-height: 1.45;
  margin: -6px 0 0 12px;
}
/* Visualizador de micro del VAD: barras de espectro en vivo + marca de umbral. */
.vad-preview { margin: 12px 0 0 12px; display: flex; flex-direction: column; gap: 8px; }
.vad-preview-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.vad-preview-preset { font-size: 0.75rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.vad-canvas {
  width: 100%; height: 96px; border-radius: 10px; display: block;
  background: var(--surface-2, var(--bg-soft)); border: 1px solid var(--border);
}
.vad-canvas.idle { opacity: 0.5; }
.vad-preview-hint { font-size: 0.72rem; color: var(--faint, var(--muted)); line-height: 1.4; }
/* Guía PCI de cobros en el editor de herramientas del agente. */
.fn-hint-pci {
  font-size: 0.72rem; line-height: 1.45; color: var(--text-2, var(--muted));
  background: color-mix(in srgb, #0e7490 8%, transparent); border: 1px solid color-mix(in srgb, #0e7490 22%, transparent);
  border-radius: 8px; padding: 7px 9px; margin: 4px 0 8px;
}
.agent-brain .fn-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;   /* MULTI-COLUMNA: campos a 2 columnas */
  gap: 14px 16px;
}
.agent-brain .fn-field {
  display: flex;                     /* dentro de cada celda: label + desc + input apilados */
  flex-direction: column;
  align-items: stretch;
  gap: 5px;
  font-size: 0.85rem;
  min-width: 0;
}
/* El prompt (textarea) y cualquier campo ancho ocupan la FILA ENTERA. */
.agent-brain .fn-field:has(.fn-field-textarea) { grid-column: 1 / -1; }
@media (max-width: 640px) {
  .agent-brain .fn-fields { grid-template-columns: 1fr; }   /* móvil: 1 columna */
}

/* Dropdown CUSTOM de modelos del Agente IA (compacto): trigger 1 línea + panel flotante (portal). */
.mdd-trigger {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; padding: 6px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--text); cursor: pointer; font-family: inherit; font-size: 0.83rem;
  transition: border-color 120ms, box-shadow 120ms;
}
.mdd-trigger:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); }
.mdd-trigger.open, .mdd-trigger:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
.mdd-trigger-txt { display: flex; align-items: center; gap: 7px; min-width: 0; overflow: hidden; }
.mdd-trigger-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mdd-trigger-cost { font-size: 0.7rem; color: var(--text-2); white-space: nowrap; font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.mdd-caret { color: var(--muted); font-size: 0.65rem; flex: 0 0 auto; transition: transform 120ms; }
.mdd-trigger.open .mdd-caret { transform: rotate(180deg); }
.mdd-logo { flex: 0 0 auto; display: block; }
.mdd-panel {
  /* Por encima del modal (.fe-modal-backdrop = 10000): el picker se abre DENTRO
     del modal del Agente IA y, con z-index empatado, quedaba tapado/incliclable. */
  z-index: 10010; max-height: 320px; overflow-y: auto; padding: 4px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0,0,0,.22);
}
/* Barra de filtro de idioma del picker TTS: sticky arriba del panel scrollable. */
.mdd-langbar { position: sticky; top: -4px; z-index: 1; display: flex; align-items: center; gap: 8px; padding: 6px 8px; margin: -4px -4px 4px; background: var(--surface); border-bottom: 1px solid var(--border); }
.mdd-langbar-lbl { font-size: 0.65rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.mdd-langsel { flex: 1; font-size: 0.8rem; padding: 3px 6px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--text); }
.mdd-group-label { display: flex; align-items: center; gap: 6px; font-size: 0.65rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); padding: 7px 8px 2px; cursor: pointer; user-select: none; border-radius: 6px; transition: background .1s; }
.mdd-group-label:hover { background: var(--bg-soft); color: var(--text-2, var(--muted)); }
.mdd-group-label .mdd-logo { width: 13px; height: 13px; }
.mdd-group-caret { font-size: 0.6rem; width: 10px; display: inline-block; color: var(--muted); }
.mdd-group-name { flex: 0 1 auto; }
.mdd-group-count { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--muted);
  background: var(--bg-soft); border: 1px solid var(--border); border-radius: 999px; padding: 0 6px; font-size: 0.6rem; }
.mdd-group.collapsed { padding-bottom: 2px; }
.mdd-opt {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 8px; border-radius: 6px; cursor: pointer;
}
.mdd-opt:hover { background: var(--bg-soft, #f1f5f9); }
.mdd-opt.sel { background: color-mix(in srgb, var(--accent) 12%, transparent); }
/* flex:1 (crece y ocupa el hueco) para que el badge de proveedor quede pegado a la
   izquierda y los badges de coste/latencia queden pegados a la derecha — antes el
   row usaba justify-content:space-between, que con 3 hijos dejaba huecos raros. */
.mdd-opt-name { flex: 1 1 auto; font-size: 0.82rem; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.mdd-opt-note { font-weight: 400; color: var(--muted); }
.mdd-opt-cost { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.mdd-opt-cost.muted { color: var(--muted); font-size: 0.68rem; }
.mdd-tier { font-size: 0.7rem; letter-spacing: 1px; font-weight: 700; }
.mdd-tier.tier-1 { color: #16a34a; }
.mdd-tier.tier-2 { color: #d97706; }
.mdd-tier.tier-3 { color: #dc2626; }
.mdd-permin { font-size: 0.68rem; color: var(--text-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Sólido como GDPR/HIPAA/PCI/entrena — antes iban tintados (12% opacidad) y
   quedaban deslavados al lado de esos pills sólidos. Mismo peso visual ahora. */
.mdd-lat {
  font-size: 0.66rem; font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap;
  color: #fff; background: #2563eb; padding: 1px 5px; border-radius: 5px;
}
.mdd-lat.muted { color: var(--muted); background: transparent; font-weight: 400; }
/* Créditos/min por modelo en el selector (coste de plataforma) — verde, para
   distinguirlo de la latencia (azul). Ordena el listado de más barato a más caro. */
.mdd-cr {
  font-size: 0.66rem; font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap;
  color: #fff; background: #0f7a4d; padding: 1px 5px; border-radius: 5px;
}
/* Base común de TODOS los badges de cumplimiento (GDPR/HIPAA/entrena) — mismo peso
   visual (pill sólida, texto blanco), solo cambia el color por tipo. */
.mdd-gdpr, .mdd-hipaa, .mdd-train {
  font-size: 0.6rem; font-weight: 800; letter-spacing: 0.03em; white-space: nowrap;
  color: #fff; padding: 1px 5px; border-radius: 5px; flex: 0 0 auto; cursor: help;
}
/* Azul: residencia de datos en la UE. */
.mdd-gdpr { background: #2563eb; }
/* Morado: BAA (obligación legal salud US) YA incluido en la cuenta, sin trámite.
   Ámbar (.request): el proveedor lo OFRECE pero hay que pedirlo a ventas/soporte. */
.mdd-hipaa { background: #7e22ce; }
.mdd-hipaa.request { background: #b45309; }
/* Entrena: verde = NO entrena (caso normal/bueno) · ámbar = SÍ entrena (excepción,
   avisa). Mismo pill sólido que el resto, el color ya distingue. */
.mdd-train.ok { background: #0f7a4d; }
.mdd-train.warn { background: #b45309; }
/* Badge de proveedor técnico (Azure/OpenAI/Groq/…) — SIEMPRE visible, no solo en
   desambiguación. Pill SÓLIDA (mismo peso que gdpr/hipaa/entrena/lat/cr). Teal: color
   libre desde que se quitó el badge PCI-DSS, no choca con azul(gdpr/lat)/morado(hipaa)/
   verde(entrena-ok/coste)/ámbar(alerta). */
.mdd-provider {
  font-size: 0.6rem; font-weight: 800; letter-spacing: 0.03em; text-transform: uppercase; white-space: nowrap;
  color: #fff; background: #0e7490; padding: 1px 5px; border-radius: 5px; flex: 0 0 auto;
}
/* Botón "escuchar" (preview de voz TTS) en el selector. */
.mdd-preview {
  font-size: 0.62rem; line-height: 1; color: var(--accent); flex: 0 0 auto; cursor: pointer;
  background: color-mix(in srgb, var(--accent) 14%, transparent); border: none;
  border-radius: 4px; padding: 2px 5px;
}
.mdd-preview:hover { background: var(--accent); color: #fff; }
.mdd-trigger-lat {
  font-size: 0.66rem; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; flex: 0 0 auto;
  color: #2563eb; background: color-mix(in srgb, #2563eb 12%, transparent); padding: 1px 5px; border-radius: 5px;
}
/* Botón "Medir latencia" del Agente IA (compacto, bajo el desplegable de LLM). */
.mdd-measure {
  align-self: flex-start; margin: -2px 0 2px; padding: 4px 9px;
  font-size: 0.72rem; font-family: inherit; color: var(--accent); cursor: pointer;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--border)); border-radius: 7px;
  transition: background 120ms;
}
.mdd-measure:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.mdd-measure:disabled { opacity: 0.6; cursor: default; }

/* Coste total estimado bajo los desplegables de modelos del Agente IA (compacto). */
.model-total {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  margin-top: 6px; padding: 9px 12px; border-radius: 9px;
  background: color-mix(in srgb, var(--accent) 7%, var(--surface)); border: 1px solid var(--border);
}
.model-total-lbl { font-size: 0.78rem; font-weight: 600; color: var(--text); }
.model-total-val { font-size: 0.92rem; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
.model-total-note { width: 100%; font-size: 0.68rem; color: var(--muted); line-height: 1.35; }
.agent-brain .fn-field-lbl { font-size: 0.83rem; }
.agent-brain .fn-field-input,
.agent-brain .fn-field-select,
.agent-brain .fn-field-textarea {
  padding: 9px 11px;
  font-size: 0.86rem;
  border-radius: 8px;
  border-color: var(--border);
  background: var(--surface);
}
.agent-brain .fn-field-textarea { min-height: 88px; font-family: inherit; }
.fn-empty {
  font-size: 0.72rem;
  color: var(--muted);
  font-style: italic;
}

/* Botón "Probar endpoint" del webhook de Hangup + resultado */
.fn-webhook-test { margin-top: 6px; }
.fn-test-btn {
  width: 100%;
  border: 1px solid var(--accent, #6366f1);
  background: color-mix(in srgb, var(--accent, #6366f1) 10%, transparent);
  color: var(--accent, #6366f1);
  border-radius: 7px;
  padding: 5px 8px;
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
}
.fn-test-btn:hover { background: color-mix(in srgb, var(--accent, #6366f1) 18%, transparent); }
.fn-test-result {
  margin-top: 5px;
  font-size: 0.68rem;
  line-height: 1.35;
  padding: 5px 7px;
  border-radius: 6px;
  word-break: break-word;
  white-space: pre-wrap;
  font-family: ui-monospace, monospace;
}
.fn-test-result.ok  { background: hsl(145 60% 50% / 0.12); color: hsl(145 60% 32%); }
.fn-test-result.err { background: hsl(0 80% 60% / 0.12); color: hsl(0 70% 45%); }

/* Control de webhook en el nodo Hangup (checkbox + botón abrir modal) */
.fn-webhook-ctl { margin-top: 6px; display: flex; flex-direction: column; gap: 5px; }
.fn-webhook-check {
  display: flex; align-items: center; gap: 6px;
  font-size: 0.74rem; color: var(--text, var(--fg)); cursor: pointer;
}
.fn-webhook-check input { cursor: pointer; }
.fn-webhook-cfg {
  border: 1px solid var(--accent, #6366f1);
  background: color-mix(in srgb, var(--accent, #6366f1) 10%, transparent);
  color: var(--accent, #6366f1);
  border-radius: 7px; padding: 5px 8px;
  font-size: 0.72rem; font-weight: 600; cursor: pointer;
}
.fn-webhook-cfg:hover { background: color-mix(in srgb, var(--accent, #6366f1) 18%, transparent); }

/* Modal del editor (portal a body) — webhook del Hangup */
.fe-modal-backdrop {
  position: fixed; inset: 0; z-index: 10000;
  background: color-mix(in oklab, var(--bg) 40%, rgba(6,4,14,.7));
  -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  animation: vx-modal-in .18s ease both;
}
.fe-modal {
  width: min(560px, 96vw); max-height: 90vh; overflow: auto;
  background: var(--surface, #fff); color: var(--text, var(--fg));
  border-radius: 14px; box-shadow: 0 24px 64px rgba(0,0,0,0.3);
  display: flex; flex-direction: column;
  animation: vx-modal-pop .22s var(--ease-out) both;
}
.fe-modal-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  padding: 14px 18px; border-bottom: 1px solid var(--border);
}
.fe-modal-head h3 { margin: 0; font-size: 1.05rem; }
.fe-modal-head-txt { display: flex; flex-direction: column; gap: 3px; }
.fe-modal-sub { font-size: 0.78rem; color: var(--muted); line-height: 1.4; }
.fe-modal-x {
  border: 0; background: transparent; cursor: pointer;
  font-size: 1.1rem; color: var(--muted); line-height: 1;
}
.fe-modal-x:hover { color: var(--text, var(--fg)); }
/* Pestañas dentro de un modal (Básico / Avanzado del Agente IA) */
.fe-tabs {
  display: flex; gap: 4px;
  padding: 8px 18px 0; border-bottom: 1px solid var(--border);
}
.fe-tab {
  border: 0; background: transparent; cursor: pointer;
  padding: 8px 14px; font-size: 0.82rem; font-weight: 600;
  color: var(--muted); border-radius: 8px 8px 0 0;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.fe-tab:hover { color: var(--text, var(--fg)); }
.fe-tab.active {
  color: var(--accent, var(--text, var(--fg)));
  border-bottom-color: var(--accent, currentColor);
}
.fe-modal-body { padding: 16px 18px; display: flex; flex-direction: column; gap: 14px; }
/* Modal del Agente IA: alto FIJO con scroll interno → no cambia de tamaño al
   cambiar de pestaña (LLM/STT/TTS/Docs/Tools tienen contenidos de distinta altura). */
.fe-modal-body.agent-brain { height: min(60vh, 560px); overflow-y: auto; overscroll-behavior: contain; }
.fe-modal-hint { margin: 0; font-size: 0.8rem; color: var(--muted); line-height: 1.45; }
.fe-modal-field { display: flex; flex-direction: column; gap: 5px; }
.fe-modal-field > span { font-size: 0.78rem; font-weight: 600; color: var(--text-2, var(--muted)); }
.fe-modal-field input[type="text"], .fe-modal-field select {
  width: 100%; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg, #fff); color: var(--text, var(--fg));
  font-size: 0.85rem;
}
.fe-modal-foot {
  padding: 12px 18px; border-top: 1px solid var(--border);
  display: flex; justify-content: flex-end;
}

/* Labels de output (no React Flow Handle pero junto a ellos) */
.fn-out-label {
  position: absolute;
  right: 18px;
  transform: translateY(-50%);
  font-size: 0.6rem;
  font-family: ui-monospace, monospace;
  font-weight: 600;
  letter-spacing: 0.02em;
  background: var(--surface);
  padding: 1px 5px;
  border-radius: 3px;
  border: 1px solid var(--border);
  pointer-events: none;
  white-space: nowrap;
  z-index: 2;
}
[data-theme="dark"] .fn-out-label {
  background: hsl(220 17% 14%);
}

/* Edges React Flow custom */
.react-flow__edge-path { stroke-width: 2; }
.react-flow__edge.selected .react-flow__edge-path { stroke: hsl(0 75% 55%); }
.react-flow__edge-textbg { fill: var(--surface); }
.react-flow__edge-text {
  font-size: 11px;
  font-family: ui-monospace, monospace;
  font-weight: 600;
}

/* React Flow handles (puertos) — más visibles y con hover crece */
.react-flow__handle {
  width: 12px !important;
  height: 12px !important;
  transition: transform 120ms ease;
}
.react-flow__handle:hover { transform: scale(1.4); }

/* ── Trigger node (cuando entra una llamada) ─────────────────────── */
.fn-trigger {
  min-width: 280px;
  max-width: 300px;
  border-width: 1.5px;
}
.fn-trigger .fn-header {
  padding: 12px 14px;
}
.fn-trigger .fn-icon {
  width: 28px; height: 28px;
  border-radius: 8px;
}
.fn-trigger .fn-icon svg { width: 16px; height: 16px; }
.fn-trigger .fn-type {
  font-size: 0.72rem;
  letter-spacing: 0.08em;
}
.fn-trigger-section {
  margin-top: 10px;
}
.fn-trigger-label {
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin-bottom: 4px;
}
.fn-did-list, .fn-var-list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.fn-did-chip {
  display: inline-block;
  font-family: ui-monospace, monospace;
  font-size: 0.72rem;
  font-weight: 600;
  color: hsl(155 55% 30%);
  background: hsl(155 55% 95%);
  border: 1px solid hsl(155 45% 75%);
  padding: 2px 7px;
  border-radius: 5px;
}
[data-theme="dark"] .fn-did-chip {
  color: hsl(155 60% 75%);
  background: hsl(155 50% 18%);
  border-color: hsl(155 50% 30%);
}
.fn-var-chip {
  display: inline-block;
  font-family: ui-monospace, monospace;
  font-size: 0.68rem;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  padding: 2px 6px;
  border-radius: 4px;
}

/* Banner warn (call-to-action falta trigger) */
.rfbanner-warn {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  background: hsl(35 100% 96%);
  border-bottom: 1px solid hsl(35 90% 80%);
  color: hsl(35 80% 35%);
  font-size: 0.82rem;
  font-weight: 500;
}
[data-theme="dark"] .rfbanner-warn {
  background: hsl(35 60% 15%);
  border-bottom-color: hsl(35 60% 30%);
  color: hsl(35 80% 75%);
}
.rfbanner-warn .btn {
  margin-left: auto;
}

/* Select de referencia (autofill) — mismo estilo que input pero appearance
   native dropdown */
.fn-field-ref {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='%23888' d='M0 0l5 6 5-6z'/></svg>");
  background-repeat: no-repeat;
  background-position: right 6px center;
  padding-right: 22px;
  appearance: none;
  -webkit-appearance: none;
}
.fn-field-ref:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* Editor de ramas dinámicas (Switch.cases, Menu.options) */
.fn-branches {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--border);
  display: flex; flex-direction: column;
  gap: 6px;
}
.fn-branches-label {
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin-bottom: 2px;
}
.fn-branch-row {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 0.75rem;
}
.fn-branch-row .fn-field-input,
.fn-branch-row .fn-field-select {
  width: auto;
  flex: 1;
  min-width: 0;
}
.fn-branch-val { max-width: 70px; flex: 0 0 70px; }
.fn-branch-dtmf {
  max-width: 32px; flex: 0 0 32px;
  text-align: center;
  font-family: ui-monospace, monospace;
  font-weight: 600;
}
.fn-branch-lbl { flex: 1; min-width: 0; }
.fn-branch-arrow {
  color: var(--muted);
  font-weight: 600;
  flex: 0 0 auto;
  padding: 0 2px;
}
.fn-branch-rm {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  width: 22px; height: 22px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
}
.fn-branch-rm:hover {
  background: hsl(0 88% 96%);
  border-color: hsl(0 75% 55%);
  color: hsl(0 75% 55%);
}
[data-theme="dark"] .fn-branch-rm:hover {
  background: hsl(0 50% 18%);
  color: hsl(0 75% 65%);
}
.fn-branch-add {
  margin-top: 4px;
  background: var(--accent-soft);
  border: 1px dashed var(--accent);
  color: var(--accent);
  padding: 6px 8px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 0.72rem;
  font-weight: 600;
}
.fn-branch-add:hover {
  background: var(--accent);
  color: white;
}

/* ref-select con botón gestionar (↗) */
.fn-ref-wrap {
  display: flex;
  align-items: stretch;
  gap: 4px;
  min-width: 0;
}
.fn-ref-wrap > .fn-field-ref {
  flex: 1;
  min-width: 0;
}
.fn-ref-manage {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 6px;
  border: 1px solid var(--border);
  background: var(--bg-soft);
  color: var(--muted);
  text-decoration: none !important;
  border-radius: 5px;
  font-size: 0.85rem;
  font-weight: 700;
  flex: 0 0 auto;
  transition: background 100ms, color 100ms, border-color 100ms;
}
.fn-field-badge {
  flex: 0 0 auto;
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  cursor: help;
  border: 1px solid transparent;
}
.fn-field-badge--info {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent);
}
.fn-field-badge--warn {
  background: hsl(38 95% 92%);
  color: hsl(28 80% 35%);
  border-color: hsl(35 90% 55%);
}
[data-theme="dark"] .fn-field-badge--warn {
  background: hsl(35 60% 18%);
  color: hsl(38 95% 70%);
  border-color: hsl(35 80% 45%);
}
/* Chips de variables detectadas en campos de texto (TTS, etc.). */
.fn-varchips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin-top: 4px;
}
.fn-varchips-label {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.fn-varchip {
  font-size: 0.66rem;
  font-family: ui-monospace, monospace;
  padding: 1px 6px;
  border-radius: 999px;
  border: 1px solid transparent;
  white-space: nowrap;
}
.fn-varchip.is-ok {
  background: hsl(142 60% 92%);
  color: hsl(142 70% 28%);
  border-color: hsl(142 50% 60%);
}
[data-theme="dark"] .fn-varchip.is-ok {
  background: hsl(142 40% 16%);
  color: hsl(142 60% 70%);
  border-color: hsl(142 45% 40%);
}
.fn-varchip.is-warn {
  background: hsl(38 95% 92%);
  color: hsl(28 80% 35%);
  border-color: hsl(35 90% 55%);
  cursor: help;
}
[data-theme="dark"] .fn-varchip.is-warn {
  background: hsl(35 60% 18%);
  color: hsl(38 95% 70%);
  border-color: hsl(35 80% 45%);
}
.fn-ref-manage:hover {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent);
}
[data-theme="dark"] .fn-ref-manage {
  background: hsl(220 17% 10%);
}
[data-theme="dark"] .fn-ref-manage:hover {
  background: var(--accent-soft);
}

/* Highlight de nodos durante modo Probar (test_run o WS interactivo) */
.react-flow__node.flow-visited .fn-card {
  box-shadow:
    0 0 0 2px hsl(243 75% 70% / 0.4),
    0 8px 24px -6px hsl(243 75% 50% / 0.25) !important;
}
.react-flow__node.flow-active .fn-card {
  box-shadow:
    0 0 0 3px hsl(155 60% 45%),
    0 0 32px hsl(155 60% 45% / 0.4) !important;
  animation: flow-pulse 1.2s ease-in-out infinite;
}
/* Preview del asistente IA en el canvas */
.react-flow__node.flow-preview-hover .fn-card {
  box-shadow: 0 0 0 3px var(--accent), 0 0 28px color-mix(in srgb, var(--accent) 45%, transparent) !important;
}
.react-flow__node.flow-preview-added .fn-card {
  box-shadow: 0 0 0 3px hsl(145 62% 45%), 0 0 30px hsl(145 62% 45% / 0.45) !important;
  animation: flow-pulse 1.2s ease-in-out 3;
}
.react-flow__node.flow-preview-modified .fn-card {
  box-shadow: 0 0 0 3px hsl(212 90% 55%), 0 0 30px hsl(212 90% 55% / 0.45) !important;
  animation: flow-pulse 1.2s ease-in-out 3;
}
@keyframes flow-pulse {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(1.08); }
}

/* Puertos de salida como filas dentro del card (estilo Dify/n8n).
   La bola se ancla al borde derecho del nodo — siempre misma X.
   El label va alineado a la derecha, dentro de la fila. */
.fn-ports {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--border);
  display: flex; flex-direction: column;
  gap: 4px;
  position: relative;
}
.fn-port-row {
  position: relative;
  display: flex; align-items: center; justify-content: flex-end;
  padding: 4px 0 4px 8px;
  font-size: 0.72rem;
  font-family: ui-monospace, monospace;
  font-weight: 600;
  min-height: 22px;
  border-radius: 5px;
  transition: background 100ms ease;
}
.fn-port-row:hover {
  background: color-mix(in srgb, var(--df-accent, var(--accent)) 8%, transparent);
}
.fn-port-row-label {
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  text-align: right;
  padding-right: 14px;
}
/* React Flow handle, dentro del row — overrideamos su posicionamiento
   absoluto para que se alinee al borde derecho de la card, alineado con
   esta fila. Sigue siendo un Handle real (drag-to-connect funciona). */
.fn-port-row .react-flow__handle {
  position: absolute !important;
  top: 50% !important;
  right: -7px !important;
  transform: translate(0, -50%);
  z-index: 5;
}
/* Colores por kind del puerto */
.fn-port-canon .fn-port-row-label  { opacity: 0.85; }
.fn-port-option .fn-port-row-label { font-weight: 700; }
.fn-port-case .fn-port-row-label   { font-weight: 700; }
.fn-port-extra .fn-port-row-label  { font-style: italic; opacity: 0.75; }

/* Banner clickable + panel de issues */
.rfbanner-clickable { cursor: pointer; }
.rfbanner-clickable:hover { background: var(--bg-soft); }
.rfbanner-toggle {
  margin-left: auto;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-2);
  background: var(--bg-soft, #f4f5f7);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 3px 10px;
  cursor: pointer;
  line-height: 1.2;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  transition: background 100ms, border-color 100ms, color 100ms;
}
.rfbanner-toggle:hover {
  background: var(--surface);
  border-color: var(--accent);
  color: var(--accent);
}
.rfbanner-toggle.is-open {
  background: var(--accent-soft, color-mix(in srgb, var(--accent) 12%, transparent));
  border-color: var(--accent);
  color: var(--accent);
}
.rfbanner-toggle-ok {
  cursor: default;
  background: transparent;
  border-color: transparent;
  color: hsl(155 50% 38%);
}
.rfbanner-toggle-ok:hover {
  background: transparent;
  border-color: transparent;
  color: hsl(155 50% 38%);
}
[data-theme="dark"] .rfbanner-toggle {
  background: hsl(220 17% 12%);
  color: var(--text-2);
}
.rfissues {
  flex: 0 0 auto;
  max-height: 200px;
  overflow-y: auto;
  background: var(--surface-2, var(--bg-soft));
  border-bottom: 1px solid var(--border);
  padding: 4px;
  display: flex; flex-direction: column;
  gap: 2px;
}
.rfissue {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 8px;
  border-radius: 5px;
  font-size: 0.78rem;
  cursor: pointer;
  background: var(--surface);
  border: 1px solid var(--border);
}
.rfissue:hover { background: var(--accent-soft); }
.rfissue-level {
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 1px 6px;
  border-radius: 3px;
  flex: 0 0 auto;
}
.rfissue-error .rfissue-level { background: hsl(0 88% 96%); color: hsl(0 75% 40%); }
.rfissue-warn  .rfissue-level { background: hsl(35 100% 96%); color: hsl(35 80% 35%); }
[data-theme="dark"] .rfissue-error .rfissue-level { background: hsl(0 50% 18%); color: hsl(0 75% 75%); }
[data-theme="dark"] .rfissue-warn  .rfissue-level { background: hsl(35 60% 15%); color: hsl(35 80% 75%); }
.rfissue-node {
  background: var(--accent-soft);
  color: var(--accent);
  padding: 1px 6px;
  border-radius: 3px;
  font-size: 0.7rem;
  font-family: ui-monospace, monospace;
  flex: 0 0 auto;
}
.rfissue-field {
  background: var(--bg-soft);
  color: var(--text-2);
  padding: 1px 6px;
  border-radius: 3px;
  font-size: 0.7rem;
  font-family: ui-monospace, monospace;
  flex: 0 0 auto;
}
.rfissue-msg { color: var(--text); flex: 1; min-width: 0; }

/* Badge de error/warn en el nodo */
.fn-err-badge, .fn-warn-badge {
  position: absolute;
  top: -8px; right: -8px;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: hsl(0 75% 55%);
  color: white;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px;
  border: 2px solid var(--surface);
  z-index: 6;
  box-shadow: 0 2px 6px rgba(0,0,0,0.2);
}
.fn-warn-badge { background: hsl(35 90% 55%); }
.fn-card.fn-has-err  { border-color: hsl(0 75% 55%) !important; }
.fn-card.fn-has-warn { border-color: hsl(35 90% 55%) !important; }

/* Puerto terminal (answered) — fin natural del flow, ok que no esté
   conectado. Estilo más suave + sufijo "→ fin". */
.fn-port-terminal-clean .fn-port-row-label {
  opacity: 0.55;
  font-weight: 500;
}
.fn-port-terminal-clean .react-flow__handle {
  opacity: 0.5;
}

/* Editor If — multi-rama con condiciones AND/OR */
.fn-if-branches { gap: 10px; }
.fn-if-branch {
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 8px;
  display: flex; flex-direction: column;
  gap: 6px;
}
[data-theme="dark"] .fn-if-branch { background: hsl(220 17% 11%); }
.fn-if-branch-head {
  display: flex;
  align-items: center;
  gap: 5px;
}
.fn-if-label {
  font-size: 0.65rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  color: var(--accent);
  background: var(--accent-soft);
  padding: 2px 6px;
  border-radius: 4px;
  flex: 0 0 auto;
}
.fn-if-combinator { flex: 0 0 auto; font-size: 0.7rem; max-width: 80px; }
.fn-if-cond {
  display: flex;
  align-items: center;
  gap: 4px;
  padding-left: 12px;
  font-size: 0.72rem;
}
.fn-if-var { flex: 1; min-width: 0; }
.fn-if-op { flex: 0 0 auto; max-width: 100px; font-size: 0.7rem; }
.fn-if-value { flex: 1; min-width: 50px; }
.fn-if-cond-add {
  font-size: 0.65rem;
  margin-left: 12px;
}
.fn-if-else-hint {
  font-size: 0.65rem;
  color: var(--muted);
  font-style: italic;
  padding: 4px;
  text-align: center;
}

/* Nodo If: más ancho para que los dropdowns respiren */
.fn-card:has(.fn-if-branches) {
  min-width: 340px;
  max-width: 380px;
}
/* Cada condición en 2 filas: var arriba a full width, op + value abajo. */
.fn-if-cond {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-rows: auto auto;
  gap: 4px;
  align-items: center;
  padding: 6px 0 6px 12px;
  font-size: 0.74rem;
  border-left: 2px solid var(--accent-soft);
  margin-bottom: 4px;
}
.fn-if-cond .fn-if-var {
  grid-column: 1 / 2;
  grid-row: 1;
  max-width: 100%;
  min-width: 0;
  width: 100%;
}
.fn-if-cond .fn-branch-rm {
  grid-column: 2;
  grid-row: 1 / 3;
  align-self: center;
}
.fn-if-cond .fn-if-op {
  grid-column: 1 / 2;
  grid-row: 2;
  max-width: 130px;
  min-width: 90px;
}
.fn-if-cond .fn-if-value {
  grid-column: 1 / 2;
  grid-row: 2;
  margin-left: 138px;  /* alineado tras op */
  width: calc(100% - 138px);
  min-width: 0;
}
/* Dropdowns del if: padding más cómodo + altura */
.fn-if-cond select.fn-field-select,
.fn-if-cond input.fn-field-input {
  height: 26px;
  padding: 2px 6px;
  font-size: 0.78rem;
}

/* Flow trace en /calls/{id}
.ft-sym {
  display: inline-block;
  width: 22px; text-align: center;
  font-weight: 600;
  font-size: 0.95rem;
  line-height: 1;
}
.ft-exit  { color: hsl(155 55% 40%); }

/* ── Diagnóstico IA (detalle de llamada): barras de latencia por etapa ── */
.ai-bar {
  display: flex; width: 100%; height: 20px;
  background: var(--bg-soft, rgba(127,127,127,.12));
  border-radius: 6px; overflow: hidden;
}
.ai-bar > span { height: 100%; display: block; min-width: 0; transition: width 120ms ease; }
/* STT = cian · LLM = violeta · TTS = esmeralda (consistente con la leyenda) */
.ai-seg-stt { background: #06b6d4; }
.ai-seg-llm { background: #8b5cf6; }
.ai-seg-tts { background: #10b981; }
.ai-dot { width: 10px; height: 10px; border-radius: 3px; display: inline-block; flex: 0 0 auto; }
/* Badges de estado por turno */
.aiflag {
  display: inline-flex; align-items: center;
  border-radius: 9999px; padding: 1px 8px;
  font-size: 0.68rem; font-weight: 600; line-height: 1.4;
}
.aiflag-info   { background: rgba(99,102,241,.15);  color: #6366f1; }
.aiflag-warn   { background: rgba(245,158,11,.18);  color: #b45309; }
.aiflag-danger { background: rgba(239,68,68,.16);   color: #dc2626; }

/* ── Panel YAML colapsable ── */
.flow-yaml-pane {
  display: flex;
  flex-direction: column;
  margin: 0;
  min-width: 0;
  border: 1px solid var(--border, hsl(243 30% 88%));
  border-radius: 12px;
  background: var(--bg-card, var(--bg));
  overflow: hidden;
  transition: max-width 180ms ease;
}
.flow-yaml-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 6px 10px;
  font-size: 0.75rem; font-weight: 600;
  color: var(--text-2, var(--muted));
  background: var(--bg-soft);
  border-bottom: 1px solid var(--border);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.flow-yaml-toggle {
  width: 22px; height: 22px;
  padding: 0; border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
  font-size: 0.9rem; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background 100ms, color 100ms;
}
.flow-yaml-toggle:hover {
  background: var(--accent-soft, color-mix(in srgb, var(--accent) 14%, transparent));
  color: var(--accent);
  border-color: var(--accent);
}
.flow-yaml-textarea {
  flex: 1; min-height: 520px; height: 100%;
  border: none; outline: none;
  padding: 8px 10px;
  resize: none;
  background: transparent;
  color: var(--text);
  width: 100%;
}
/* Modo colapsado: layout pasa de 3 cols a 2 (paleta + canvas), el pane YAML
   se reduce a una barra delgada que sigue clickable para expandir. */
.flow-editor-layout.yaml-collapsed { grid-template-columns: 160px 1fr 28px !important; }
.yaml-collapsed .flow-yaml-pane { max-width: 28px; }
.yaml-collapsed .flow-yaml-header > span { display: none; }
.yaml-collapsed .flow-yaml-textarea { display: none; }
.yaml-collapsed .flow-yaml-toggle { transform: rotate(180deg); }

/* ── Panel derecho: pestañas YAML | Asistente IA ── */
.flow-pane-tabs { display: flex; gap: 4px; }
.flow-pane-tab {
  padding: 3px 10px; border: 1px solid transparent; border-radius: 6px;
  background: transparent; color: var(--text-2); cursor: pointer;
  font: inherit; font-size: 0.72rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.04em;
}
.flow-pane-tab:hover { color: var(--text); }
.flow-pane-tab.is-active { background: var(--surface); color: var(--accent); border-color: var(--border); }
/* Resaltar la pestaña del Asistente IA para que se note que está ahí. */
.flow-pane-tab[data-pane-tab="assistant"] {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-color: color-mix(in srgb, var(--accent) 30%, transparent);
}
.flow-pane-tab[data-pane-tab="assistant"]:hover { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.flow-pane-tab[data-pane-tab="assistant"].is-active {
  background: var(--accent); color: #fff; border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.yaml-collapsed .flow-pane-tabs { display: none; }
.yaml-collapsed .flow-assistant { display: none; }

/* ── Asistente IA: chat ── */
/* El atributo [hidden] debe ganar a `display:flex/block` de la clase, si no el
   panel oculto se ve igual (debajo del YAML). */
.flow-yaml-textarea[hidden], .flow-assistant[hidden] { display: none !important; }
.flow-assistant { flex: 1; min-height: 520px; display: flex; flex-direction: column; min-width: 0; overflow: hidden; }
/* min-height:0 es CLAVE: sin él un hijo flex no encoge y overflow:auto nunca
   hace scroll (el panel crecía sin parar en vez de hacer scroll). */
.fa-messages { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 14px; display: flex; flex-direction: column; gap: 12px; }
.fa-intro { color: var(--text-2); font-size: 0.82rem; line-height: 1.5; }
.fa-intro p { margin: 0 0 10px; }
.fa-chips { display: flex; flex-direction: column; gap: 6px; }
.fa-chip { text-align: left; padding: 7px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-soft); color: var(--text); cursor: pointer; font: inherit; font-size: 0.8rem; }
.fa-chip:hover { border-color: var(--accent); color: var(--accent); }
.fa-msg { font-size: 0.84rem; line-height: 1.45; border-radius: 10px; padding: 8px 11px; max-width: 92%; overflow-wrap: anywhere; }
.fa-msg.user { align-self: flex-end; background: var(--accent); color: #fff; }
.fa-msg.bot { align-self: flex-start; background: var(--bg-soft); color: var(--text); border: 1px solid var(--border); }
.fa-msg.bot.err { border-color: #ef4444; color: #ef4444; background: color-mix(in srgb, #ef4444 8%, transparent); }
.fa-msg.bot.ok { border-color: var(--accent); }
.fa-dots { opacity: 0.7; }
.fa-timer { opacity: 0.65; font-variant-numeric: tabular-nums; font-size: 0.78rem; }
.fa-summary { font-weight: 500; margin-bottom: 8px; }
.fa-note { font-size: 0.76rem; color: var(--muted); margin-bottom: 6px; }
/* Lista de cambios: con muchas ops no debe estirar el mensaje hasta el infinito;
   se capa con scroll interno para que el botón "Aplicar" siga a la vista. */
.fa-ops { display: flex; flex-direction: column; gap: 5px; margin-bottom: 8px; max-height: 38vh; overflow-y: auto; padding-right: 2px; }
.fa-ops-count { font-size: 0.74rem; color: var(--muted); margin-bottom: 5px; font-weight: 600; }
.fa-op { display: flex; align-items: center; gap: 8px; padding: 5px 8px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); cursor: pointer; }
.fa-op input { accent-color: var(--accent); }
.fa-op-meta { font-size: 0.8rem; }
.fa-op-meta code { font-family: ui-monospace, monospace; font-size: 0.76rem; }
.fa-op-kind { font-weight: 700; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.03em; padding: 1px 6px; border-radius: 5px; margin-right: 3px; }
.fa-op-kind.fa-add { background: color-mix(in srgb, #22c55e 18%, transparent); color: #16a34a; }
.fa-op-kind.fa-update { background: color-mix(in srgb, #3b82f6 18%, transparent); color: #2563eb; }
.fa-op-kind.fa-delete { background: color-mix(in srgb, #ef4444 18%, transparent); color: #dc2626; }
.fa-op-kind.fa-set_start { background: color-mix(in srgb, #a855f7 18%, transparent); color: #9333ea; }
.fa-op-kind.fa-set_flow_field { background: color-mix(in srgb, #64748b 20%, transparent); color: #475569; }
.fa-issues { font-size: 0.76rem; color: #b45309; background: color-mix(in srgb, #f59e0b 10%, transparent); border: 1px solid color-mix(in srgb, #f59e0b 35%, transparent); border-radius: 8px; padding: 6px 9px; margin-bottom: 8px; }
.fa-issue { margin-top: 3px; }
.fa-apply { width: 100%; padding: 8px; border: none; border-radius: 8px; background: var(--accent); color: #fff; font-weight: 600; font-size: 0.82rem; cursor: pointer; }
.fa-apply:hover { opacity: 0.92; }
.fa-apply.done { background: #16a34a; }
.fa-apply:disabled { opacity: 0.6; cursor: default; }
.fa-inputrow { display: flex; align-items: flex-end; gap: 8px; padding: 10px; border-top: 1px solid var(--border); background: var(--bg-soft); }
.fa-input { flex: 1; resize: none; border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; font: inherit; font-size: 0.86rem; line-height: 1.4; background: var(--bg); color: var(--text); outline: none; min-height: 44px; max-height: 180px; overflow-y: auto; }
.fa-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent); }
.fa-send { align-self: stretch; padding: 0 16px; border: none; border-radius: 10px; background: var(--accent); color: #fff; font-weight: 600; cursor: pointer; font: inherit; font-size: 0.84rem; }
.fa-send:disabled { opacity: 0.6; cursor: default; }

/* ── Modo fullscreen del editor (botón ⛶ / tecla Esc) ── */
body.flow-fullscreen { overflow: hidden; }
body.flow-fullscreen .topbar,
body.flow-fullscreen .back-link,
body.flow-fullscreen .page-head,
body.flow-fullscreen .alert,
body.flow-fullscreen .actions {
  display: none !important;
}
body.flow-fullscreen .content,
body.flow-fullscreen .content-wide {
  max-width: none !important;
  padding: 0 !important;
  margin: 0 !important;
}
body.flow-fullscreen .settings-card {
  border: none !important;
  border-radius: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  background: var(--surface);
  box-shadow: none !important;
}
body.flow-fullscreen .settings-card > header {
  display: none !important;
}
body.flow-fullscreen .form {
  padding: 0 !important;
  margin: 0 !important;
  border: none !important;
  background: transparent !important;
  height: 100vh;
}
/* El editor en fullscreen es un OVERLAY FIJO que tapa todo el viewport. Así no
   pelea con la cadena de alturas (.app flex, .content, settings-card) ni con
   las otras secciones de la página (Validación, DDIs, Historial) que antes se
   colaban por debajo. position:fixed + inset:0 = cubre la pantalla entera. */
body.flow-fullscreen .flow-editor-layout {
  position: fixed !important;
  inset: 0 !important;
  z-index: 9999 !important;
  height: 100vh !important;
  width: 100vw !important;
  max-height: 100vh !important;
  background: var(--surface) !important;
  /* minmax(0,1fr): la fila del grid llena toda la altura; sin esto los paneles
     colapsan (canvas en blanco, YAML cortado). */
  grid-template-rows: minmax(0, 1fr) !important;
  gap: 8px !important;
  padding: 8px !important;
  box-sizing: border-box !important;
  align-items: stretch !important;
  overflow: hidden !important;
}
/* 3 columnas: paleta (añadir nodo) · canvas (flujos) · YAML. Las tres cosas
   que interesan, visibles y a pantalla completa. */
body.flow-fullscreen .flow-editor-layout:not(.yaml-collapsed) {
  grid-template-columns: 210px minmax(0, 1fr) minmax(340px, 32%) !important;
}
/* Cada panel ocupa toda la altura y hace su propio scroll (min-height:0 es lo
   que permite encoger dentro del grid en vez de desbordar). */
body.flow-fullscreen .flow-palette,
body.flow-fullscreen .flow-canvas-card,
body.flow-fullscreen .flow-yaml-pane {
  height: 100% !important;
  max-height: calc(100vh - 16px) !important;
  min-height: 0 !important;
}
/* Forzar la paleta visible en fullscreen: el @media (max-width:1280px) la
   oculta (display:none) y, sin esto, en una ventana no maximizada el panel
   "añadir nodo" desaparecía justo en pantalla completa. */
body.flow-fullscreen .flow-palette {
  display: flex !important;
  flex-direction: column !important;
  overflow-y: auto !important;
}
body.flow-fullscreen .flow-canvas-card {
  display: flex !important;
  flex-direction: column !important;
}
body.flow-fullscreen #flow-canvas {
  flex: 1 1 auto !important;
  min-height: 0 !important;
  height: auto !important;
}
body.flow-fullscreen .flow-yaml-textarea {
  min-height: 0 !important;
  height: auto !important;
}
body.flow-fullscreen [data-tool="fullscreen"] {
  background: var(--accent-soft, color-mix(in srgb, var(--accent) 14%, transparent));
  color: var(--accent);
}
/* En pantalla completa, la barra de acciones del editor (Guardar/Publicar draft
   + Probar) NO se oculta: flota como pastilla fija abajo a la derecha, siempre
   accesible. Mantiene la regla genérica que oculta otras `.actions` de la página
   (Validación, DDIs…), porque esta lleva su propia clase y va después → gana. */
/* En pantalla completa el dock del webphone se oculta SIEMPRE (aunque haya
   llamada): comparte esquina con la pastilla de acciones (Guardar/Publicar) y
   se solapaban. El editor es un modo enfocado; el teléfono no pinta aquí. */
body.flow-fullscreen #phone-dock { display: none !important; }
body.flow-fullscreen .flow-edit-actions {
  display: flex !important;
  position: fixed !important;
  right: 16px;
  bottom: 14px;
  z-index: 10001;
  margin: 0 !important;
  padding: 6px 8px;
  gap: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
}

/* ════════════════════════════════════════════════════════════════════════
   Revamp 2026 — capa glass para las CARDS. Va sin @layer a propósito: así
   gana a las utilidades `bg-surface`/`border-border` de Tailwind (que viven
   en @layer utilities) que muchas cards llevan también en su class.
   Solo cards: los 101 `bg-surface` sueltos (dropdowns, paneles, inputs)
   siguen sólidos.
   ════════════════════════════════════════════════════════════════════════ */
.settings-card,
.card,
.dash-card,
.stat-card,
.setup-card,
.empty-state,
.auth-card {
  background: var(--glass-bg) !important;
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.3);
  backdrop-filter: blur(var(--glass-blur)) saturate(1.3);
  border-color: color-mix(in oklab, var(--border) 72%, transparent) !important;
  box-shadow: var(--shadow-md), inset 0 1px 0 color-mix(in oklab, white 7%, transparent);
  transition: transform var(--transition) var(--ease-out),
              box-shadow var(--transition) var(--ease-out),
              border-color var(--transition);
}
.dash-card:hover,
.stat-card:hover {
  transform: translateY(-2px);
  border-color: color-mix(in oklab, var(--accent) 30%, var(--border)) !important;
  box-shadow: var(--shadow-lg), inset 0 1px 0 color-mix(in oklab, white 10%, transparent);
}

/* KPIs premium: número grande con el gradiente de marca + tipografía tabular y
   apretada. Una línea de acento arriba que se enciende al hover. */
.stat-card { position: relative; overflow: hidden; animation: vx-fade-up .5s var(--ease-out) backwards; }

/* ── Barra de neón superior de los 4 KPIs, estilo LOADING-BAR ──
   6px de alto + glow. La clave para que el movimiento SE VEA: destellos claros
   (lila/rosa pálido) intercalados con el violeta/magenta → contraste de
   luminosidad que el ojo sí sigue al desplazarse en bucle. */
.stat-card::before {
  content: '';
  position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background-image: linear-gradient(90deg,
    var(--accent), var(--accent-2), var(--accent), var(--accent-2), var(--accent));
  background-size: 200% 100%;
  animation: vx-load 6s linear infinite;
  filter: drop-shadow(0 0 6px color-mix(in oklab, var(--accent) 70%, transparent));
  pointer-events: none;
}
@keyframes vx-load { to { background-position: -200% 0; } }
.stat-card:hover::before { animation-duration: 3.5s; }

/* ── Botón primario: el gradiente FLUYE como líquido al hacer hover (lento, sin
   pasarse). En reposo, gradiente quieto. ── */
.btn-primary,
button.bg-accent, a.bg-accent {
  background-image: linear-gradient(125deg,
    var(--accent) 0%, var(--accent-2) 38%,
    color-mix(in oklab, #fff 45%, var(--accent-2)) 50%,
    var(--accent-2) 62%, var(--accent) 100%) !important;
  background-size: 220% 100%;
  background-position: 0% 50%;
  border-color: transparent;
}
.btn-primary:hover,
button.bg-accent:hover, a.bg-accent:hover {
  animation: vx-btn-flow 3.2s ease-in-out infinite;
}
/* Vaivén diagonal suave (vuelve al inicio → bucle sin saltos): el color "fluye"
   como líquido, sin la franja horizontal que se cortaba. */
@keyframes vx-btn-flow {
  0%   { background-position: 0% 50%; }
  50%  { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

/* ── Controles CUADRADOS a juego con los inputs de texto: botones, botones
   utility (bg-accent), chips/tabs de filtro y buscadores. Las cards y los
   contenedores conservan su radio. ── */
.btn,
button.bg-accent, a.bg-accent,
button[type="submit"],
input[type="search"], input[name="q"], input[name="search"] {
  border-radius: 0.5rem !important;
}

/* ── Modal reutilizable (nuevo contacto, importar CSV, nuevo flujo…) ──
   <div class="vx-modal" hidden> + .vx-modal-card. Abrir con [data-modal="id"],
   cerrar con [data-close], backdrop o Esc (JS por página o global). ── */
.vx-modal {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  padding: 1.25rem;
  background: color-mix(in oklab, var(--bg) 40%, rgba(6,4,14,.7));
  -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px);
  animation: vx-modal-in .18s ease both;
}
.vx-modal[hidden] { display: none; }
.vx-modal-card {
  width: 100%; max-width: 640px; max-height: 88vh; overflow: auto;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg), 0 0 0 1px color-mix(in oklab, var(--accent) 12%, transparent);
  animation: vx-modal-pop .22s var(--ease-out) both;
}
.vx-modal-card.wide { max-width: 860px; }
@keyframes vx-modal-in { from { opacity: 0 } to { opacity: 1 } }
@keyframes vx-modal-pop { from { opacity: 0; transform: translateY(14px) scale(.985) } to { opacity: 1; transform: none } }
/* Salida (cierre) — el JS global añade .is-closing y espera a que termine. */
.vx-modal.is-closing { animation: vx-modal-out .16s ease both; }
.vx-modal.is-closing .vx-modal-card { animation: vx-modal-pop-out .16s ease both; }
@media (prefers-reduced-motion: reduce) { .vx-modal.is-closing, .vx-modal.is-closing .vx-modal-card { animation: none } }
.vx-modal-head {
  position: sticky; top: 0; z-index: 1;
  display: flex; align-items: center; gap: .75rem;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.vx-modal-head h2 { flex: 1; font-size: 1.05rem; font-weight: 600; }
.vx-modal-close {
  display: grid; place-items: center; width: 32px; height: 32px;
  border: 1px solid transparent; background: transparent; cursor: pointer;
  color: var(--muted); border-radius: var(--radius-sm);
  transition: all var(--transition);
}
.vx-modal-close:hover { background: var(--surface-2); color: var(--text); border-color: var(--border); }
.vx-modal-body { padding: 1.25rem; }
@media (prefers-reduced-motion: reduce) { .vx-modal, .vx-modal-card { animation: none } }

/* ── Inputs de texto: CUADRADOS (sin esquinas redondeadas) con borde que sigue
   el gradiente de marca — sutil en reposo, vivo + glow al enfocar. Sin @layer
   para ganar a las utilidades rounded-*/border-* de Tailwind. ── */
.field input, .field select, .field textarea,
input:not([type]), input[type="text"], input[type="email"], input[type="password"],
input[type="tel"], input[type="number"], input[type="search"],
input[type="url"], input[type="datetime-local"], input[type="date"],
input[type="time"], input[type="month"], textarea, select {
  border-radius: 0.5rem !important;
  border: 1px solid color-mix(in oklab, var(--accent) 24%, var(--border)) !important;
}
.field input:focus, .field select:focus, .field textarea:focus,
input[type="text"]:focus, input[type="email"]:focus, input[type="password"]:focus,
input[type="tel"]:focus, input[type="number"]:focus, input[type="search"]:focus,
input[type="url"]:focus, input[type="datetime-local"]:focus, input[type="date"]:focus,
input[type="time"]:focus, input[type="month"]:focus, textarea:focus, select:focus {
  outline: none;
  border-color: var(--accent) !important;
  box-shadow:
    0 0 0 3px color-mix(in oklab, var(--accent) 20%, transparent),
    0 8px 26px -12px color-mix(in oklab, var(--accent) 45%, transparent);
}
.stat-card:nth-child(2) { animation-delay: .05s; }
.stat-card:nth-child(3) { animation-delay: .1s; }
.stat-card:nth-child(4) { animation-delay: .15s; }
.stat-card .value {
  font-size: 2rem; line-height: 1.05; font-weight: 700;
  letter-spacing: -0.03em; font-variant-numeric: tabular-nums;
  background: var(--accent-grad);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  width: fit-content;
}
.stat-card .label { font-weight: 500; letter-spacing: .01em; }


/* ════════════════════════════════════════════════════════════════════════
   Tablero REAL-TIME (live): agentes como tarjetas, llamadas como flujo, cola.
   ════════════════════════════════════════════════════════════════════════ */
.agent-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: .75rem; }
.agent-card {
  position: relative; display: flex; align-items: center; gap: .7rem;
  padding: .8rem .9rem; border-radius: var(--radius-sm);
  background: var(--surface-2); border: 1px solid var(--border);
  transition: transform var(--transition) var(--ease-out), box-shadow var(--transition), border-color var(--transition);
}
.agent-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.agent-card.busy {
  border-color: color-mix(in oklab, var(--accent) 45%, var(--border));
  box-shadow: 0 0 0 1px color-mix(in oklab, var(--accent) 22%, transparent), 0 10px 26px -14px color-mix(in oklab, var(--accent) 55%, transparent);
}
.agent-avatar {
  width: 42px; height: 42px; border-radius: 13px; flex-shrink: 0;
  display: grid; place-items: center; font-weight: 700; font-size: .92rem; color: #fff;
  background: var(--accent-grad);
  box-shadow: 0 4px 12px -4px color-mix(in oklab, var(--accent) 60%, transparent);
}
.agent-card.free .agent-avatar {
  background: linear-gradient(135deg, var(--surface-2), var(--border-strong));
  color: var(--text-2); box-shadow: none;
}
.agent-info { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.agent-info strong { font-size: .9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.agent-info small { font-size: .76rem; color: var(--muted); line-height: 1.35; margin-top: 1px; }
.agent-status { align-self: flex-start; font-size: .64rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; padding: .14rem .5rem; border-radius: 999px; white-space: nowrap; }
.agent-status.free { background: color-mix(in oklab, var(--success) 16%, transparent); color: var(--success); }
.agent-status.busy { background: color-mix(in oklab, var(--accent) 20%, transparent); color: var(--accent); }
.agent-status.busy::before { content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 999px; background: var(--accent); margin-right: 4px; vertical-align: middle; animation: vx-pulse 1.4s ease-in-out infinite; }

.cf-card, .wq-card { display: flex; align-items: center; gap: .7rem; padding: .7rem .85rem; border-radius: var(--radius-sm); background: var(--surface-2); border: 1px solid var(--border); transition: border-color var(--transition), transform var(--transition); }
.cf-card:hover, .wq-card:hover { border-color: color-mix(in oklab, var(--accent) 30%, var(--border)); transform: translateY(-1px); }
.cf-dir { width: 36px; height: 36px; border-radius: 11px; display: grid; place-items: center; flex-shrink: 0; font-size: 1.05rem; background: color-mix(in oklab, var(--accent) 14%, transparent); color: var(--accent); }
.cf-dir.outbound { background: color-mix(in oklab, var(--accent-2) 14%, transparent); color: var(--accent-2); }
.cf-route { display: flex; flex-direction: column; gap: .15rem; flex: 1; min-width: 0; font-variant-numeric: tabular-nums; }
.cf-line { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.cf-agent { display: inline-flex; align-items: center; gap: .35rem; font-size: .72rem; font-weight: 600; color: var(--accent-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cf-agent.muted { color: var(--muted); font-weight: 500; font-style: italic; }
.cf-agent-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--success, #22c55e); box-shadow: 0 0 0 3px color-mix(in oklab, var(--success, #22c55e) 22%, transparent); flex-shrink: 0; }
.cf-num { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 42%; }
.cf-arrow { color: var(--muted); flex-shrink: 0; }
.cf-meta { display: flex; flex-direction: column; align-items: flex-end; gap: .1rem; margin-left: auto; }
.cf-timer { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--accent); }
.cf-status { font-size: .68rem; color: var(--muted); text-transform: capitalize; }
.cf-acts { display: flex; gap: .25rem; }
.cf-acts button { display: grid; place-items: center; width: 32px; height: 32px; border-radius: 8px; border: 1px solid transparent; background: transparent; cursor: pointer; transition: all var(--transition); }
.cf-acts button { color: var(--muted); }
.cf-acts button svg { display: block; }
.cf-acts button:hover { background: var(--surface); border-color: var(--border); }
.cf-acts .btn-inspect:hover { color: var(--accent); border-color: color-mix(in oklab, var(--accent) 40%, var(--border)); }
.cf-acts .btn-listen:hover { color: var(--accent-2); border-color: color-mix(in oklab, var(--accent-2) 40%, var(--border)); }

.wq-icon { width: 36px; height: 36px; border-radius: 11px; display: grid; place-items: center; flex-shrink: 0; font-size: 1rem; background: color-mix(in oklab, var(--accent-2) 14%, transparent); color: var(--accent-2); animation: vx-pulse 1.6s ease-in-out infinite; }
.wq-info { display: flex; flex-direction: column; min-width: 0; }
.wq-info strong { font-size: .88rem; }
.wq-info small { font-size: .72rem; color: var(--muted); }
.wq-time { margin-left: auto; font-variant-numeric: tabular-nums; font-weight: 700; font-size: 1.05rem; color: var(--accent-2); }
@keyframes vx-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .4 } }

/* ════════ Fixes globales (sin capa → ganan a las utilidades de Tailwind) ════════ */
/* Tailwind va SIN preflight: los <button> sin clase de fondo heredan el aspecto
   nativo del navegador (fondo gris/blanco + borde outset). Reset: transparentes
   por defecto; los que llevan .btn / bg-* mantienen su fondo. */
button {
  -webkit-appearance: none;
  appearance: none;
  background-color: transparent;
}
/* Selects: reservar sitio para la flechita (el px-3 de las plantillas se comía
   el padding derecho y el texto se solapaba con el chevron). */
select { padding-right: 2.1rem !important; }

/* Completar reset: el borde outset nativo de <button>/<summary> (Tailwind sin
   preflight). Las utilidades .border lo re-aplican donde se quiere. */
button, summary { border: 0; }
summary { list-style: none; }
summary::-webkit-details-marker { display: none; }

/* Spinner + estado de carga del filtro de periodo del dashboard (swap in-place). */
.dash-spin {
  display: inline-block; width: 14px; height: 14px;
  border: 2px solid color-mix(in oklab, var(--accent) 28%, transparent);
  border-top-color: var(--accent); border-radius: 50%;
  animation: vx-spin .7s linear infinite;
}
.dash-spin[hidden] { display: none; }
@keyframes vx-spin { to { transform: rotate(360deg); } }
#dash-charts.is-loading { opacity: .5; pointer-events: none; transition: opacity .15s; }

/* ── Esqueletos de carga diferida (dashboard, extensiones, …) ── */
.skel-line, .skel-block {
  border-radius: 8px;
  background: linear-gradient(90deg,
    color-mix(in oklab, var(--text) 7%, transparent) 25%,
    color-mix(in oklab, var(--text) 14%, transparent) 37%,
    color-mix(in oklab, var(--text) 7%, transparent) 63%);
  background-size: 400% 100%;
  animation: vx-load 1.4s ease infinite;
}
.skel-line { height: .75rem; }
.dash-skel { /* contenedor: solo para semántica/aria */ }
@media (prefers-reduced-motion: reduce) { .skel-line, .skel-block { animation: none; } }

/* Native controls (date pickers, etc.) según el tema → el icono del <input type=date>
   ya no sale negro sobre negro en oscuro, y el popup del calendario va oscuro. */
[data-theme="dark"] { color-scheme: dark; }
[data-theme="light"] { color-scheme: light; }
/* Date inputs dentro del control de rango (.vx-date): sin borde propio (lo pone el
   label contenedor), transparentes y compactos. input.vx-date para ganar al
   input[type=date] global. */
input.vx-date {
  border: 0 !important;
  background: transparent !important;
  padding: 0 !important;
  outline: none;
  color: var(--text-2);
  width: auto; min-width: 0;
  font: inherit;
}
input.vx-date::-webkit-calendar-picker-indicator { cursor: pointer; opacity: .8; }
input.vx-date::-webkit-calendar-picker-indicator:hover { opacity: 1; }

/* Celdas de log recortadas a una línea con "…"; click para expandir. Evita que
   URIs SIP / motivos largos rompan la fila en 15 líneas. */
.cell-clip {
  display: inline-block;
  max-width: 24ch;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: bottom;
  cursor: pointer;
  position: relative;
  padding-right: .9rem;
}
.cell-clip::after {
  content: "▾";
  position: absolute;
  right: 0;
  opacity: .45;
  font-size: .8em;
}
.cell-clip:hover { color: var(--text); }
.cell-clip.expanded {
  white-space: normal;
  overflow: visible;
  max-width: 38ch;
  word-break: break-all;
}
.cell-clip.expanded::after { content: "▴"; }
.cell-clip:empty { padding-right: 0; }
.cell-clip:empty::after { content: ""; }

/* ── Entrada de página CONSISTENTE (staggered) ──
   Cada bloque de primer nivel del <main> (cabecera, filtros, tarjetas, tablas)
   entra con un fade-up ESCALONADO — el mismo efecto bonito que tenían las
   settings-cards, pero ahora en TODAS las páginas, también las de tablas
   (contactos, llamadas). Se re-dispara en cada render: carga inicial y cada swap
   del SPA (replaceWith inserta un #spa-root nuevo → la animación CSS arranca de
   cero). Reemplaza las entradas por-tarjeta para que no se dupliquen y para que
   el ritmo sea idéntico en todo el panel. */
.app > main > * {
  animation: vx-fade-up .45s var(--ease-out) backwards;
}
.app > main > *:nth-child(1) { animation-delay: 0s; }
.app > main > *:nth-child(2) { animation-delay: .05s; }
.app > main > *:nth-child(3) { animation-delay: .10s; }
.app > main > *:nth-child(4) { animation-delay: .15s; }
.app > main > *:nth-child(5) { animation-delay: .20s; }
.app > main > *:nth-child(n+6) { animation-delay: .24s; }
/* Modales (display:none inicial, animación propia vx-modal-in) y stat-cards (van
   dentro de su grid, que ya es el bloque animado): que no re-animen. El neón del
   stat-card (::before) y todos los hovers quedan intactos. */
.app > main > .vx-modal { animation: none; }
.app > main .stat-card { animation: none; }

/* Barra de progreso de carga del SPA: feedback claro de "cargando" en cada
   navegación (la controla el JS del SPA-boost en _layout). */
#spa-progress {
  position: fixed; top: 0; left: 0; height: 3px; width: 0;
  background: var(--accent-grad, linear-gradient(120deg, var(--accent), var(--accent-2)));
  box-shadow: 0 0 12px color-mix(in oklab, var(--accent) 70%, transparent);
  border-radius: 0 3px 3px 0;
  z-index: 99999; opacity: 0; pointer-events: none;
  transition: width .25s ease, opacity .35s ease;
}
#spa-progress.active { opacity: 1; }

/* ══════════════════════════════════════════════════════════════════════════
   Llamada de prueba — revamp (fases, etapas IA con spinner, diálogo+latencias)
   ══════════════════════════════════════════════════════════════════════════ */
.fc-card { width: 940px; }
.fc-head { display: flex; align-items: center; justify-content: space-between;
  padding: 0.7rem 1rem; border-bottom: 1px solid var(--border);
  background: var(--surface-2, var(--bg-soft)); }
.fc-head strong { font-size: 0.98rem; }
.fc-head-sub { display: block; font-size: 0.72rem; color: var(--muted); margin-top: 1px; }
.fc-body { display: grid; grid-template-columns: 290px 1fr; gap: 1rem; padding: 1rem; overflow: auto; }
@media (max-width: 760px) { .fc-body { grid-template-columns: 1fr; } }

/* ── Columna de controles ── */
.fc-side { display: flex; flex-direction: column; gap: 0.7rem; }
.fc-field { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.8rem; }
.fc-field > span { color: var(--muted); font-weight: 600; display: flex; gap: .4rem; align-items: baseline; }
.fc-field em { font-style: normal; font-size: 0.7rem; color: var(--accent); font-weight: 500; }
.fc-field input { padding: 0.45rem 0.55rem; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg); color: var(--text); font-size: 0.85rem; }
.fc-seg { display: inline-flex; background: var(--bg-soft); border: 1px solid var(--border);
  border-radius: 8px; padding: 3px; gap: 3px; }
.fc-seg label { flex: 1; text-align: center; font-size: 0.78rem; padding: 0.3rem 0.5rem;
  border-radius: 6px; cursor: pointer; color: var(--muted); }
.fc-seg input { display: none; }
.fc-seg label:has(input:checked) { background: var(--accent); color: #fff; font-weight: 600; }
.fc-actions { display: flex; gap: 0.5rem; }
.fc-actions .btn { flex: 1; }

/* ── Indicador "audio en tiempo real" ── */
/* Indicador "Live" compacto en la cabecera, junto a la cruceta. Verde pulsante. */
.fc-head-right { display: flex; align-items: center; gap: 0.5rem; }
/* Estado de la llamada junto al botón — SIEMPRE visible, punto ESTÁTICO (sin pulso
   ni "bola" que llamaba la atención). Color por estado via data-state. */
.fc-callstate { display: inline-flex; align-items: center; gap: 0.4rem; margin-top: 8px;
  font-size: 0.72rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: 0.2rem 0.6rem; border-radius: 999px; border: 1px solid var(--border);
  background: var(--bg-soft); color: var(--text-2); width: fit-content; }
.fc-callstate-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: 0 0 auto; }
.fc-callstate[data-state="idle"] .fc-callstate-dot { background: hsl(220 8% 60%); }
.fc-callstate[data-state="connecting"] { color: hsl(38 70% 40%); border-color: hsl(38 60% 78%); background: hsl(38 80% 96%); }
.fc-callstate[data-state="connecting"] .fc-callstate-dot { background: hsl(38 85% 50%); }
.fc-callstate[data-state="live"] { color: hsl(155 55% 36%); border-color: hsl(155 50% 78%); background: hsl(155 60% 96%); }
.fc-callstate[data-state="live"] .fc-callstate-dot { background: hsl(155 65% 42%); }
.fc-callstate[data-state="ended"] .fc-callstate-dot { background: hsl(0 60% 55%); }
[data-theme="dark"] .fc-callstate[data-state="connecting"] { background: hsl(38 40% 14%); border-color: hsl(38 30% 30%); color: hsl(38 70% 62%); }
[data-theme="dark"] .fc-callstate[data-state="live"] { background: hsl(155 40% 14%); border-color: hsl(155 30% 30%); color: hsl(155 60% 60%); }
/* Total de latencia bajo las cajas STT/LLM/TTS — pequeño, a la derecha, sin repetir chips. */
.fc-total { font-size: 0.7rem; color: var(--muted); text-align: right; margin-top: 0.2rem;
  font-variant-numeric: tabular-nums; }
.fc-total b { color: var(--text); font-weight: 700; }
.fc-total-barge { color: hsl(30 80% 48%); font-weight: 600; }
/* VU dual en la cabecera: mic (lo que envías, azul) + voz del agente (lo que llega,
   violeta = LLM/TTS) → se ve "cómo fluye" el audio. */
.fc-vus { display: inline-flex; align-items: center; gap: 8px; }
/* Barras HORIZONTALES de segmentos que se encienden de izquierda a derecha según el
   nivel — como el VU de la escucha de llamada. Mic azul, voz del agente violeta. */
.fc-vu { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: 2px; width: 46px; height: 9px; }
.fc-vu i { border-radius: 1px; background: var(--border, #d8d8e0);
  transition: background-color .06s linear; }
.fc-vu-mic i[data-on="1"] { background: hsl(210 70% 55%); }
.fc-vu-ai  i[data-on="1"] { background: hsl(275 60% 62%); }
/* Icono antes de cada barra (mic = tú, bot = agente) → se ve quién es quién. */
.fc-vu-cell { display: inline-flex; align-items: center; gap: 5px; }
.fc-vu-ico { width: 13px; height: 13px; flex: 0 0 13px; }
.fc-vu-cell:nth-child(1) .fc-vu-ico { color: hsl(210 70% 55%); }
.fc-vu-cell:nth-child(2) .fc-vu-ico { color: hsl(275 60% 62%); }
/* Latencias en UNA línea (compacto): STT/LLM/TTS + total. */
.fc-lat-line { display: flex; flex-wrap: wrap; align-items: center; gap: .55rem;
  margin-top: .2rem; font-size: .7rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.fc-lat-i b { color: var(--text); font-weight: 700; }
.fc-lat-i.stt { color: hsl(210 55% 50%); } .fc-lat-i.stt b { color: hsl(210 55% 45%); }
.fc-lat-i.llm { color: hsl(275 45% 55%); } .fc-lat-i.llm b { color: hsl(275 45% 50%); }
.fc-lat-i.tts { color: hsl(30 70% 48%); }  .fc-lat-i.tts b { color: hsl(30 75% 44%); }
.fc-lat-total { margin-left: auto; color: var(--text); font-weight: 600; }
.fc-lat-barge { color: hsl(0 70% 55%); font-weight: 600; }

.fc-keypad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.fc-keypad button { padding: 0.5rem; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg); color: var(--text); cursor: pointer; font-size: 0.9rem; }
.fc-keypad button:hover { border-color: var(--accent); }
.fc-audio { width: 100%; height: 32px; }

/* ── Columna principal: fases + conversación ── */
.fc-main { display: flex; flex-direction: column; gap: 0.7rem; min-height: 420px; }
.fc-steps { display: flex; list-style: none; padding: 0; margin: 0; gap: 0; }
.fc-steps li { flex: 1; position: relative; font-size: 0.72rem; text-align: center;
  color: var(--muted); padding: 0.35rem 0.2rem 0.35rem 1.3rem; }
.fc-steps li::before { content: "○"; position: absolute; left: 0.45rem; top: 50%; transform: translateY(-50%);
  font-size: 0.8rem; }
.fc-steps li.active { color: var(--accent); font-weight: 700; }
.fc-steps li.active::before { content: "◉"; }
.fc-steps li.done { color: hsl(155 55% 42%); }
.fc-steps li.done::before { content: "✓"; }
.fc-steps li.err { color: hsl(0 75% 55%); }
.fc-steps li.err::before { content: "✕"; }

.fc-status { padding: 0.5rem 0.7rem; border-radius: 8px; font-size: 0.85rem;
  background: var(--bg-soft); border: 1px solid var(--border); }
.fc-status.ok { color: hsl(155 60% 38%); background: hsl(155 55% 96%); border-color: hsl(155 45% 82%); }
.fc-status.err { color: hsl(0 72% 52%); background: hsl(0 85% 97%); border-color: hsl(0 60% 85%); }
/* Modelo/voz del agente en la prueba (bajo el marcador). */
.fc-agent { display: flex; flex-wrap: wrap; gap: 6px 12px; padding: 6px 2px 0;
  font-size: 0.72rem; color: var(--muted); }
.fc-agent-item { display: inline-flex; align-items: center; gap: 5px; }
.fc-agent-k { font-weight: 700; letter-spacing: .03em; color: var(--text-2); }
.fc-agent code { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: .95em;
  background: var(--bg-soft); border: 1px solid var(--border); padding: 1px 6px; border-radius: 5px; color: var(--text); }
[data-theme="dark"] .fc-status.ok { background: hsl(155 40% 14%); border-color: hsl(155 30% 28%); color: hsl(155 60% 62%); }
[data-theme="dark"] .fc-status.err { background: hsl(0 45% 16%); border-color: hsl(0 40% 32%); color: hsl(0 75% 66%); }

.fc-convo { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 0.6rem;
  padding: 0.6rem; background: var(--bg-soft); border: 1px solid var(--border); border-radius: 10px; min-height: 200px; }
.fc-empty { color: var(--muted); font-size: 0.82rem; text-align: center; margin: auto; }

/* ── Turno ── */
.fc-turn { border: 1px solid var(--border); border-radius: 10px; background: var(--bg);
  padding: 0.55rem 0.65rem; display: flex; flex-direction: column; gap: 0.4rem; }
.fc-turn-live { border-color: var(--accent); box-shadow: 0 0 0 2px hsl(from var(--accent) h s l / .15); }
.fc-turn-head { display: flex; align-items: center; justify-content: space-between; }
.fc-turn-badge { font-size: 0.75rem; font-weight: 700; }
.fc-turn-live-tag { font-size: 0.72rem; color: var(--accent); }

/* ── Etapas STT/LLM/TTS con spinner ── */
.fc-stages { display: flex; gap: 0.4rem; }
.fc-stage { flex: 1; display: flex; align-items: center; gap: 0.3rem; justify-content: center;
  padding: 0.35rem 0.4rem; border: 1px solid var(--border); border-radius: 8px;
  font-size: 0.76rem; color: var(--muted); background: var(--bg-soft); }
.fc-stage-lb { font-weight: 600; }
.fc-stage.active { color: var(--accent); border-color: var(--accent); background: hsl(from var(--accent) h s l / .08); }
.fc-stage.done { color: hsl(155 55% 42%); border-color: hsl(155 45% 75%); }
.fc-stage-state { min-width: 14px; text-align: center; }
.fc-spin { display: inline-block; width: 11px; height: 11px; border: 2px solid currentColor;
  border-top-color: transparent; border-radius: 50%; animation: fc-rot 0.7s linear infinite; vertical-align: middle; }
@keyframes fc-rot { to { transform: rotate(360deg); } }

/* ── Mensajes de diálogo ── */
.fc-msg { display: flex; flex-direction: column; gap: 1px; font-size: 0.84rem; }
.fc-msg-who { font-size: 0.68rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); font-weight: 700; }
.fc-msg-txt { line-height: 1.35; }
.fc-msg-user .fc-msg-txt { color: var(--text); }
.fc-msg-ai { padding: 0.35rem 0.5rem; background: hsl(from var(--accent) h s l / .08); border-radius: 8px; }
.fc-msg-ai .fc-msg-who { color: var(--accent); }
.fc-msg-sys { color: var(--muted); font-style: italic; font-size: 0.78rem; }
.fc-msg-tool { font-size: 0.78rem; color: var(--muted); }
.fc-msg-tool code { color: var(--accent); }

/* ── Chips de latencia ── */
.fc-lat { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.15rem; }
.fc-chip { font-size: 0.7rem; padding: 0.12rem 0.4rem; border-radius: 999px;
  background: var(--bg-soft); border: 1px solid var(--border); color: var(--text); white-space: nowrap; }
.fc-chip.muted { color: var(--muted); }
.fc-chip.stt { border-color: hsl(210 60% 70%); color: hsl(210 65% 48%); }
.fc-chip.llm { border-color: hsl(275 55% 72%); color: hsl(275 55% 55%); }
.fc-chip.tts { border-color: hsl(30 75% 65%); color: hsl(30 80% 48%); }
.fc-chip.total { font-weight: 700; border-color: var(--accent); color: var(--accent); }
.fc-chip.warn { border-color: hsl(0 60% 75%); color: hsl(0 70% 55%); }

.fc-tracewrap { font-size: 0.75rem; }
.fc-tracewrap summary { cursor: pointer; color: var(--muted); font-size: 0.72rem; text-transform: uppercase; letter-spacing: .04em; }
.fc-tracewrap .ft-trace { margin-top: 0.4rem; max-height: 120px; overflow-y: auto; }

/* ══════════════════════════════════════════════════════════════════════════
   Unificación visual: "Probar visual" (.flow-test-* / .ft-*) hereda el mismo
   lenguaje que "Probar llamada" (.fc-*). Scoped al modal (no toca .field global).
   ══════════════════════════════════════════════════════════════════════════ */
#flow-test-modal .flow-test-card { width: 940px; }
#flow-test-modal .flow-test-card > header { padding: 0.55rem 0.7rem 0.55rem 1rem; }
.flow-test-body { grid-template-columns: 290px 1fr; gap: 1rem; padding: 1rem; }
.flow-test-form { display: flex; flex-direction: column; gap: 0.7rem; }
.flow-test-output { display: flex; flex-direction: column; gap: 0.6rem; min-height: 420px; }

/* Campos del modal → mismo input redondeado que fc- */
.flow-test-form .field { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.8rem; }
.flow-test-form .field > span { color: var(--muted); font-weight: 600; }
.flow-test-form .field input[type="text"],
.flow-test-form .field input[type="datetime-local"] {
  padding: 0.45rem 0.55rem; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg); color: var(--text); font-size: 0.85rem; }
.flow-test-form .field code { background: var(--bg-soft); padding: 0 3px; border-radius: 4px; }

/* Pestañas sync/interactivo → control segmentado como .fc-seg */
.ft-tabs { display: inline-flex; background: var(--bg-soft); border: 1px solid var(--border);
  border-radius: 8px; padding: 3px; gap: 3px; }
.ft-tab { border: 0; background: transparent; color: var(--muted); cursor: pointer;
  font-size: 0.8rem; padding: 0.3rem 0.7rem; border-radius: 6px; }
.ft-tab.active { background: var(--accent); color: #fff; font-weight: 600; }

/* Keypad compartido (ambos modales) */
.ft-keypad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; margin-top: 0.4rem; }
.ft-keypad button { padding: 0.5rem; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg); color: var(--text); cursor: pointer; font-size: 0.9rem; }
.ft-keypad button:hover { border-color: var(--accent); }

/* Estado + salida como fc- */
.ft-status { padding: 0.5rem 0.7rem; border-radius: 8px; font-size: 0.85rem;
  background: var(--bg-soft); border: 1px solid var(--border); }
.flow-test-output h4 { margin: 0.3rem 0 0.15rem; font-size: 0.68rem; text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted); }
.ft-trace, .ft-audio { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column;
  gap: 2px; font-size: 0.78rem; max-height: 180px; overflow-y: auto;
  background: var(--bg-soft); border: 1px solid var(--border); border-radius: 8px; padding: 0.4rem 0.5rem; }
.ft-trace li, .ft-audio li { display: flex; gap: 0.5rem; align-items: baseline;
  padding: 2px 0; border-bottom: 1px dashed var(--border); }
.ft-trace li:last-child, .ft-audio li:last-child { border-bottom: 0; }

/* ── Refinamientos fc- (mejor jerarquía, sin depender de emojis) ── */
.fc-turn-badge { text-transform: uppercase; letter-spacing: .04em; font-size: 0.68rem;
  color: var(--accent); }
.fc-turn-live-tag::before { content: "● "; color: var(--accent); }
.fc-stage { flex-direction: column; gap: 2px; padding: 0.4rem 0.3rem; }
.fc-stage-lb { font-weight: 700; letter-spacing: .03em; }
.fc-stage-state { min-height: 14px; font-size: 0.8rem; }
.fc-chip b { font-weight: 700; }
.fc-chip { font-variant-numeric: tabular-nums; }

/* ── Fixes UI dashboard/carga ──────────────────────────────────────────────
   (1) Reserva SIEMPRE el hueco de la scrollbar → sin salto horizontal cuando
       aparece al cargar el contenido (main centrado ya no se desplaza).
   (2) La tarjeta de onboarding ("Pon en marcha tu centralita") entra con el
       mismo fade que el resto → deja de aparecer de golpe rompiendo la carga. */
html { scrollbar-gutter: stable; }
.setup-card { animation: vx-fade-up .5s var(--ease-out) backwards; animation-delay: .04s; }

/* ══════════════════════════════════════════════════════════════════════════
   Editor de flujos — pulido UX
   ══════════════════════════════════════════════════════════════════════════ */
/* Paleta: fuera glifos/emoji; punto de color por categoría (= color del nodo). */
.flow-palette .pi-icon { display: none !important; }
.flow-palette .palette-item { display: flex; align-items: center; gap: 0.55rem; }
.flow-palette .palette-item::before {
  content: ""; width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto;
  background: var(--nd, #64748b);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--nd, #64748b) 20%, transparent);
}
.flow-palette [data-node-type="start"],
.flow-palette [data-node-type="terminal"],
.flow-palette [data-node-type="on_transfer"] { --nd: #10b981; }
.flow-palette [data-node-type="hangup"] { --nd: #ef4444; }
.flow-palette [data-node-type="business_hours_gate"],
.flow-palette [data-node-type="menu"],
.flow-palette [data-node-type="collect_digits"],
.flow-palette [data-node-type="listen"],
.flow-palette [data-node-type="ask_input"],
.flow-palette [data-node-type="amd_detect"] { --nd: #f59e0b; }
.flow-palette [data-node-type="from_match"],
.flow-palette [data-node-type="var_match"],
.flow-palette [data-node-type="switch"],
.flow-palette [data-node-type="if"] { --nd: #3b82f6; }
.flow-palette [data-node-type="play_audio"],
.flow-palette [data-node-type="tts"],
.flow-palette [data-node-type="beep"],
.flow-palette [data-node-type="silence"],
.flow-palette [data-node-type="evaluate"] { --nd: #8b5cf6; }
.flow-palette [data-node-type="ring_extension"],
.flow-palette [data-node-type="ring_group"],
.flow-palette [data-node-type="queue"] { --nd: #06b6d4; }
.flow-palette [data-node-type="request_callback"] { --nd: #eab308; }
.flow-palette [data-node-type="forward"],
.flow-palette [data-node-type="voicemail"],
.flow-palette [data-node-type="transfer"] { --nd: #ec4899; }
.flow-palette [data-node-type="set_var"],
.flow-palette [data-node-type="http_call"],
.flow-palette [data-node-type="log_event"],
.flow-palette [data-node-type="delay"] { --nd: #64748b; }
.flow-palette [data-node-type="call_script"],
.flow-palette [data-node-type="end_script"] { --nd: #0ea5e9; }
.flow-palette [data-node-type="ai_agent"],
.flow-palette [data-node-type="return_to_agent"] { --nd: #a855f7; }

/* Cabecera del panel YAML: import/export solo cuando la pestaña YAML está activa. */
.flow-yaml-hdr-actions { display: flex; align-items: center; gap: 0.3rem; }
.flow-yaml-io { display: none; gap: 0.3rem; }
.flow-yaml-header:has(.flow-pane-tab[data-pane-tab="yaml"].is-active) .flow-yaml-io { display: inline-flex; }
.flow-yaml-io button {
  font-size: 0.72rem; padding: 0.2rem 0.5rem; border-radius: 6px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text-2, var(--muted));
  cursor: pointer; transition: border-color .12s, color .12s;
}
.flow-yaml-io button:hover { border-color: var(--accent); color: var(--text); }

/* Bindings DID como <details> plegable (deja de ocupar). */
.flow-did-details > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 0.5rem; }
.flow-did-details > summary::-webkit-details-marker { display: none; }
.flow-did-details > summary::before { content: "▸"; color: var(--muted); transition: transform .15s; font-size: 0.8rem; }
.flow-did-details[open] > summary::before { transform: rotate(90deg); }
.flow-did-summary h2 { margin: 0; }
.flow-did-help { margin: 0.5rem 0 0.75rem; }

/* Base de conocimiento por agente (modal cerebro del editor de flujos) */
.agent-docs-list { list-style: none; margin: 8px 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.agent-docs-item { display: flex; align-items: center; gap: 8px; padding: 6px 8px; background: var(--bg-soft, #f4f4f5); border-radius: 8px; font-size: .85rem; }
.agent-docs-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: ui-monospace, monospace; }
.agent-docs-size { color: var(--muted, #888); font-size: .75rem; white-space: nowrap; }
.agent-docs-del { border: 0; background: transparent; color: #dc2626; cursor: pointer; font-size: .9rem; line-height: 1; }
.agent-docs-del:disabled { opacity: .4; cursor: default; }
.agent-docs-form { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }

/* Base de conocimiento por agente — rediseño por secciones (modal cerebro) */
.agent-docs-warn { font-size: .82rem; color: #b45309; background: hsl(38 92% 95%); border: 1px solid hsl(38 80% 85%); border-radius: 8px; padding: 8px 10px; margin-top: 4px; }
.agent-docs-sub { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: .85rem; color: var(--text, #111); margin: 4px 0 8px; }
.agent-docs-count { font-size: .72rem; font-weight: 600; background: var(--bg-soft, #eee); color: var(--muted, #666); border-radius: 999px; padding: 1px 8px; }
.agent-docs-ico { width: 16px; height: 16px; color: var(--muted, #888); flex-shrink: 0; }
.agent-docs-empty { font-size: .82rem; color: var(--muted, #888); padding: 6px 0; }
.agent-docs-pills { display: inline-flex; gap: 4px; background: var(--bg-soft, #f1f1f5); border-radius: 10px; padding: 3px; margin-bottom: 8px; }
.agent-docs-pill { border: 0; background: transparent; color: var(--text-2, #555); font-size: .8rem; padding: 5px 12px; border-radius: 8px; cursor: pointer; }
.agent-docs-pill.active { background: var(--surface, #fff); color: var(--text, #111); box-shadow: 0 1px 2px rgba(0,0,0,.08); font-weight: 600; }
.agent-docs-drop { display: block; border: 1.5px dashed var(--border, #ccc); border-radius: 10px; padding: 18px; text-align: center; cursor: pointer; transition: border-color .12s, background .12s; }
.agent-docs-drop:hover { border-color: var(--accent, #6d5efc); background: var(--bg-soft, #f7f7fb); }
.agent-docs-file { position: absolute; width: 1px; height: 1px; opacity: 0; }
.agent-docs-drop-txt { font-size: .84rem; color: var(--muted, #888); }
.agent-docs-drop-file { color: var(--text, #111); font-weight: 500; }
.agent-docs-lbl { display: block; font-size: .78rem; font-weight: 600; color: var(--text-2, #555); margin-bottom: 3px; }
.agent-docs-req { color: #dc2626; }
.agent-docs-ta { font-family: ui-monospace, monospace; font-size: .8rem; width: 100%; }
.agent-docs-err { color: #dc2626; font-size: .8rem; margin-top: 6px; }
.agent-docs-add { margin-top: 10px; border: 0; background: var(--accent, #6d5efc); color: #fff; border-radius: 9px; padding: 8px 16px; font-size: .84rem; font-weight: 600; cursor: pointer; }
.agent-docs-add:disabled { opacity: .5; cursor: default; }

/* Pestañas del modal del agente (con icono) */
.agent-tabs { flex-wrap: wrap; gap: 2px; }
.agent-tabs .fe-tab { display: inline-flex; align-items: center; }
.agent-tab-ico { width: 15px; height: 15px; margin-right: 5px; flex-shrink: 0; }

/* Base de conocimiento — lista compacta + cuadradito de subida */
.kb-list { list-style:none; margin:4px 0 0; padding:0; display:flex; flex-direction:column; gap:3px; }
.kb-item { display:flex; align-items:center; gap:7px; padding:4px 8px; background:var(--bg-soft,#f5f5f7); border-radius:7px; }
.kb-item-ico { width:14px; height:14px; color:var(--muted,#999); flex-shrink:0; }
.kb-item-name { flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-family:ui-monospace,monospace; font-size:.76rem; color:var(--text,#111); }
.kb-item-size { color:var(--muted,#999); font-size:.7rem; white-space:nowrap; }
.kb-item-del { border:0; background:transparent; color:var(--muted,#aaa); cursor:pointer; display:grid; place-items:center; padding:3px; border-radius:5px; }
.kb-item-del:hover { color:#dc2626; background:rgba(0,0,0,.06); }
.kb-add { display:flex; align-items:center; gap:12px; margin-top:8px; }
.kb-drop { position:relative; width:60px; height:60px; border:1.5px dashed var(--border,#ccc); border-radius:10px; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1px; cursor:pointer; color:var(--muted,#888); transition:border-color .12s,color .12s,background .12s; }
.kb-drop:hover { border-color:var(--accent,#6d5efc); color:var(--accent,#6d5efc); background:var(--bg-soft,#f7f7fb); }
.kb-file { position:absolute; inset:0; opacity:0; cursor:pointer; }
.kb-drop-ico { width:20px; height:20px; }
.kb-drop-lbl { font-size:.66rem; font-weight:600; }
.kb-textbtn { border:0; background:transparent; color:var(--accent,#6d5efc); font-size:.8rem; cursor:pointer; }
.kb-textbtn:hover { text-decoration:underline; }
.kb-textform { display:flex; flex-direction:column; gap:6px; margin-top:8px; }
.kb-ta { font-family:ui-monospace,monospace; font-size:.78rem; resize:vertical; }
.kb-textadd { align-self:flex-start; border:0; background:var(--accent,#6d5efc); color:#fff; border-radius:8px; padding:6px 16px; font-size:.8rem; font-weight:600; cursor:pointer; }
.kb-err { color:#dc2626; font-size:.78rem; margin-top:6px; }

/* Reglas estrictas del agente (qué NO hacer) — estilo plano, integrado */
.agent-rules { margin:10px 0 0; }
.agent-rules-lbl { display:flex; align-items:center; gap:6px; font-weight:600; font-size:.8rem; color:var(--text-2,#555); margin-bottom:2px; }
.agent-rules-lbl svg { width:14px; height:14px; flex-shrink:0; color:var(--muted,#999); }
.agent-rules-hint { font-size:.74rem; color:var(--muted,#888); margin:0 0 6px; line-height:1.4; }
.agent-rules-ta { width:100%; font-size:.82rem; border:1px solid var(--border,#ddd); border-radius:8px; padding:8px; background:var(--bg,#fff); color:var(--text,#111); resize:vertical; font-family:inherit; box-sizing:border-box; }
.agent-rules-ta:focus { outline:none; border-color:var(--accent,#6d5efc); }

/* Selector de idioma de la voz (TTS) — al lado del picker */
.tts-lang-row { display:flex; align-items:center; gap:8px; margin-bottom:10px; }
.tts-lang-lbl { font-size:.8rem; font-weight:600; color:var(--text-2,#555); }
.tts-lang-sel { max-width:220px; }

/* Pestañas del editor de agentes (/agents) */
.ag-tabs { display:flex; gap:2px; border-bottom:1px solid var(--border,#e5e7eb); margin:2px 0 8px; flex-wrap:wrap; }
.ag-tab { border:0; background:transparent; padding:7px 14px; font-size:.85rem; color:var(--text-2,#666); cursor:pointer; border-bottom:2px solid transparent; margin-bottom:-1px; }
.ag-tab:hover { color:var(--text,#111); }
.ag-tab.active { color:var(--accent,#6d5efc); border-bottom-color:var(--accent,#6d5efc); font-weight:600; }

/* Voz del agente (ancha) + idioma (estrecho) en la misma fila */
.tts-voice-row { display:flex; gap:10px; align-items:flex-end; }
.tts-voice-main { flex:2 1 0; min-width:0; }
.tts-voice-main .mdd-trigger { width:100%; }
.tts-voice-lang { flex:1 1 0; max-width:170px; display:flex; flex-direction:column; gap:4px; }
