:root {
    --bg: #0f1115; --panel: #171a21; --panel-2: #1e222b; --borde: #2a2f3a;
    --texto: #e6e8ec; --texto-suave: #9aa2b1; --acento: #5b8cff; --acento-2: #7c5bff;
    --ok: #3ecf8e; --error: #ff5d6c; --aviso: #ffb648;
  }
  * { box-sizing: border-box; }
  body {
    margin: 0; min-height: 100vh; background: radial-gradient(1200px 600px at 10% -10%, #1c2333 0%, var(--bg) 55%);
    color: var(--texto); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
    padding: 24px 20px;
  }
  h1 { font-size: 20px; font-weight: 600; margin: 0 0 4px; }
  .subtitulo { color: var(--texto-suave); font-size: 13px; margin: 0 0 28px; }
  .contenedor { max-width: 1600px; margin: 0 auto; width: 100%; }
  @media (max-width: 1680px) { .contenedor { max-width: 96vw; } }
  .cabecera-tarjeta { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 4px; flex-wrap: wrap; }
  .cabecera-tarjeta h2 { font-size: 15px; font-weight: 600; margin: 0; }
  button.icono { background: #262b36; padding: 8px 12px; display: inline-flex; align-items: center; gap: 6px; }
  button.icono:hover { background: #323a48; opacity: 1; }
  button.icono .girando { display: inline-block; animation: girar .6s linear; }
  @keyframes girar { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
  table { table-layout: fixed; width: 100%; }
  th, td { overflow: hidden; text-overflow: ellipsis; }
  .contenedor-tabla { overflow-x: hidden; }

  .app-shell {
    display: flex; width: 100%; max-width: 1600px; margin: 0 auto;
    height: calc(100vh - 48px); min-height: 520px;
    background: linear-gradient(180deg, var(--panel), var(--panel-2));
    border: 1px solid var(--borde); border-radius: 16px;
    box-shadow: 0 8px 24px rgba(0,0,0,.35); overflow: hidden;
  }
  .barra-lateral {
    width: 200px; flex-shrink: 0; display: flex; flex-direction: column; gap: 3px;
    padding: 20px 14px; border-right: 1px solid var(--borde); overflow-y: auto;
  }
  .barra-lateral .logo { font-size: 13px; font-weight: 700; letter-spacing: .03em; color: var(--texto-suave); text-transform: uppercase; padding: 6px 8px 16px; }
  /* Marco blanco con esquinas redondeadas para el logo de la app -- se
     usa donde se muestre el logo (barra lateral, Configuración, Créditos)
     para que respire y no quede "pegado" al fondo oscuro del panel,
     independientemente de que el logo original tenga fondo transparente. */
  .logo-marco {
    display: inline-block; background: #fff; border-radius: 10px; padding: 8px 10px;
    box-shadow: 0 2px 8px rgba(0,0,0,.25);
    /* content-box a proposito: el resto de la pagina usa border-box, pero
       aqui el "max-height"/"max-width" de cada uso (barra lateral, vista
       previa, creditos) tiene que medir la imagen en si -- con border-box
       el padding se comia parte de esa altura y el logo se veia encogido. */
    box-sizing: content-box;
  }
  .barra-lateral .logo-app { display: block; max-width: 100%; max-height: 40px; margin: 8px 8px 12px; object-fit: contain; }
  .panel-group {
    border: 1px solid var(--borde); border-radius: 12px; padding: 18px 20px;
    margin-bottom: 20px; background: rgba(255,255,255,.015);
  }
  .panel-group:last-child { margin-bottom: 0; }
  .nav-separador {
    font-size: 11px; font-weight: 700; letter-spacing: .04em; color: var(--texto-suave);
    text-transform: uppercase; padding: 14px 8px 4px; border-top: 1px solid var(--borde); margin-top: 6px;
  }
  .nav-separador:first-child { border-top: none; margin-top: 0; }
  .nav-boton {
    display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
    background: transparent; color: var(--texto-suave); border: none; border-radius: 8px;
    padding: 10px 8px; font-size: 13px; font-weight: 600; cursor: pointer;
  }
  .nav-boton:hover { background: rgba(255,255,255,.05); color: var(--texto); opacity: 1; }
  .nav-boton.activo { background: rgba(91,140,255,.15); color: var(--acento); }
  /* Iconos SVG minimalistas de la barra lateral (sustituyen a los emojis
     de antes) -- "stroke=currentColor" en el SVG hace que el icono tome
     siempre el mismo color que el texto del boton (var(--texto-suave) en
     reposo, var(--texto) al pasar el raton, var(--acento) si esta activo),
     sin tener que duplicar esos colores aqui. */
  .nav-icono { display: inline-flex; flex-shrink: 0; }
  .nav-icono svg { display: block; }
  .barra-lateral-pie { border-top: 1px solid var(--borde); padding-top: 12px; margin-top: auto; }
  .contenido-principal {
    flex: 1; min-width: 0; padding: 20px 24px; overflow: hidden;
    display: flex; flex-direction: column;
  }

  /* Las secciones ya no van dentro de una "tarjeta" propia (con su
     borde/fondo/sombra) -- viven directamente sobre el panel general,
     asi el titulo de cada seccion queda alineado con el nav de la
     barra lateral en vez de quedar desplazado por un marco extra.
     Cada seccion es tambien una columna flex que ocupa toda la altura
     disponible, para que la lista interna pueda extenderse hasta el
     final del panel (como el menu de la barra lateral) en vez de
     quedarse con un hueco vacio debajo. */
  .vista-seccion {
    background: none; border: none; box-shadow: none; padding: 0; margin-bottom: 0;
    flex: 1; display: flex; flex-direction: column; min-height: 0;
  }
  .vista-seccion.oculto { display: none !important; }

  @media (max-width: 860px) {
    .app-shell { flex-direction: column; height: auto; min-height: 0; }
    .barra-lateral { width: 100%; flex-direction: row; flex-wrap: wrap; border-right: none; border-bottom: 1px solid var(--borde); overflow: visible; }
    .barra-lateral .logo { display: none; }
    .barra-lateral-pie { border-top: none; border-left: 1px solid var(--borde); padding-top: 0; padding-left: 12px; margin-top: 0; display: flex; align-items: center; gap: 8px; }
    .barra-lateral-pie button { width: auto !important; margin-top: 0 !important; }
  }

  /* Scroll "profesional" (delgado, con el acento del tema) en vez del
     scrollbar por defecto del navegador. Va en "*" (TODO elemento), no
     solo en .scroll-fino -- si no, cada textarea/div nuevo con overflow
     (p.ej. los textareas de los modales de "Campos") se queda con la
     barra "cutre" del navegador hasta que alguien se acuerda de añadirle
     la clase. .scroll-fino se mantiene igual (mismo aspecto) por si en
     algun sitio se necesita la clase explicitamente (p.ej. para el
     "sticky thead" de mas abajo, que si depende de ella). */
  * { scrollbar-width: thin; scrollbar-color: var(--borde) transparent; }
  *::-webkit-scrollbar { width: 10px; height: 10px; }
  *::-webkit-scrollbar-track { background: transparent; }
  *::-webkit-scrollbar-thumb { background: var(--borde); border-radius: 999px; border: 2px solid transparent; background-clip: padding-box; }
  *::-webkit-scrollbar-thumb:hover { background: var(--acento); background-clip: padding-box; }
  .scroll-fino { scrollbar-width: thin; scrollbar-color: var(--borde) transparent; }
  .scroll-fino::-webkit-scrollbar { width: 10px; height: 10px; }
  .scroll-fino::-webkit-scrollbar-track { background: transparent; }
  .scroll-fino::-webkit-scrollbar-thumb { background: var(--borde); border-radius: 999px; border: 2px solid transparent; background-clip: padding-box; }
  .scroll-fino::-webkit-scrollbar-thumb:hover { background: var(--acento); background-clip: padding-box; }

  .lista-ficheros-scroll { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; margin-top: 10px; }
  .pie-lista {
    display: flex; justify-content: space-between; align-items: center; gap: 12px;
    padding: 14px 4px 6px;
  }
  .pie-lista button { background: #262b36; }

  .acciones-fila { display: flex; flex-wrap: nowrap; gap: 6px; align-items: center; white-space: nowrap; }
  .acciones-fila button.secundario { padding: 7px 10px; font-size: 12px; flex: none; }

  .boton-x {
    background: rgba(255,93,108,.12); color: var(--error); border: 1px solid rgba(255,93,108,.35);
    width: 28px; height: 28px; padding: 0; font-weight: 800; font-size: 15px; line-height: 1;
    border-radius: 6px; display: inline-flex; align-items: center; justify-content: center;
  }
  .boton-x:hover { background: rgba(255,93,108,.22); opacity: 1; }

  .celda-truncada { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tarjeta {
    background: linear-gradient(180deg, var(--panel), var(--panel-2));
    border: 1px solid var(--borde); border-radius: 14px; padding: 22px; margin-bottom: 20px;
    box-shadow: 0 8px 24px rgba(0,0,0,.35);
  }
  .fila { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
  label { font-size: 12px; color: var(--texto-suave); display: block; margin-bottom: 6px; }
  input, select, textarea {
    background: #0d1015; border: 1px solid var(--borde); color: var(--texto);
    border-radius: 8px; padding: 9px 11px; font-size: 13px; outline: none;
    font-family: inherit;
  }
  input:focus, select:focus, textarea:focus { border-color: var(--acento); }
  /* El texto de placeholder es SOLO una invitacion a elegir/editar, nunca
     un dato de ejemplo -- para no confundirlo con el valor ya escrito,
     tiene que quedar claramente mas apagado que el texto real (var(--texto))
     e incluso algo mas apagado que las labels (var(--texto-suave)). Se basa
     en variables de tema, asi que si en el futuro se añade un modo claro
     (hoy la app solo tiene el oscuro de arriba) se adapta solo, sin tocar
     esta regla. Cubre TODOS los placeholders de la app (inputs normales,
     inputs con datalist tipo combobox, etc.) porque no lleva selector de id.*/
  ::placeholder { color: var(--texto-suave); opacity: .35; }
  button {
    background: linear-gradient(135deg, var(--acento), var(--acento-2)); color: white; border: none;
    border-radius: 8px; padding: 9px 16px; font-size: 13px; font-weight: 600; cursor: pointer;
    transition: opacity .15s;
  }
  button:hover { opacity: .88; }
  button.secundario { background: #262b36; }
  button.peligro { background: linear-gradient(135deg, #ff5d6c, #c73f4c); }
  button:disabled { opacity: .45; cursor: not-allowed; }
  table { width: 100%; border-collapse: collapse; font-size: 13px; margin-top: 14px; }
  th, td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--borde); white-space: nowrap; }
  .scroll-fino thead th { position: sticky; top: 0; background: var(--panel-2); z-index: 1; }
  th { color: var(--texto-suave); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; }
  tr:hover td { background: rgba(255,255,255,.02); }
  .pill { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11px; background: #262b36; color: var(--texto-suave); }
  .pill.si { background: rgba(62,207,142,.15); color: var(--ok); }
  .pill.no { background: rgba(255,93,108,.12); color: var(--error); }
  .mensaje { font-size: 13px; padding: 10px 12px; border-radius: 8px; margin-top: 12px; display: none; }
  .mensaje.error { background: rgba(255,93,108,.1); color: var(--error); border: 1px solid rgba(255,93,108,.3); }
  .mensaje.ok { background: rgba(62,207,142,.1); color: var(--ok); border: 1px solid rgba(62,207,142,.3); }
  .oculto { display: none !important; }

  #toast-contenedor {
    position: fixed; right: 20px; bottom: 20px; z-index: 100;
    display: flex; flex-direction: column; gap: 10px; max-width: 420px;
  }
  .toast {
    display: flex; align-items: flex-start; gap: 10px;
    background: rgba(62,207,142,.14); color: var(--ok); border: 1px solid rgba(62,207,142,.4);
    border-radius: 8px; padding: 12px 14px; font-size: 13px; line-height: 1.4;
    box-shadow: 0 8px 24px rgba(0,0,0,.35);
    animation: toast-entrada .18s ease-out;
  }
  .toast-texto { flex: 1; word-break: break-word; }
  .toast-cerrar {
    background: transparent; border: none; color: inherit; opacity: .7; cursor: pointer;
    font-size: 15px; line-height: 1; padding: 0; margin: 0;
  }
  .toast-cerrar:hover { opacity: 1; }
  @keyframes toast-entrada { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
  /* Variante roja del toast (errores) -- a diferencia del toast verde de
     "todo ok" (que se autodescarta a los 10s), este NUNCA se autodescarta:
     normalmente hay que corregir algo antes de repetir, asi que el propio
     boton de cerrar (heredado de .toast-cerrar) es la unica forma de
     quitarlo de en medio. */
  .toast.error { background: rgba(255,93,108,.14); color: var(--error); border-color: rgba(255,93,108,.4); }

  /* Fila clicable de la tabla de "Campos" -- toda la fila abre el modal
     de edicion (salvo los botones de Duplicar/Eliminar, que paran la
     propagacion del clic). */
  .fila-clicable { cursor: pointer; }
  .fila-clicable:hover { background: rgba(255,255,255,.03); }
  /* Resaltado sutil de fila cuando hay una busqueda activa y esta fila
     coincide -- deliberadamente tenue (nada de amarillo chillon), solo
     para que destaque un poco sobre el resto mientras se busca. */
  .fila-coincide { background: rgba(255,182,72,.05); }
  .fila-coincide:hover { background: rgba(255,182,72,.09); }
  /* Resaltado del texto que coincide dentro de la celda -- mismo tono
     (--aviso) que la fila, pero mas visible al ser un fondo solido sobre
     texto puntual en vez de sobre toda la fila. */
  mark.resaltado-busqueda {
    background: rgba(255,182,72,.32); color: inherit; border-radius: 3px; padding: 0 2px;
  }

  /* Panel de referencia (campos de origen + funciones) dentro del editor
     grande de expresiones -- lista de consulta rapida, clicable para
     insertar en el cursor del textarea sin tener que escribirlo a mano. */
  .ref-item {
    cursor: pointer; padding: 6px 8px; border-radius: 6px; font-family: monospace;
    font-size: 11.5px; word-break: break-all; margin-bottom: 2px; color: var(--texto-suave);
  }
  .ref-item:hover { background: rgba(255,255,255,.06); color: var(--texto); }
  .ref-separador { border: none; border-top: 1px solid var(--borde); margin: 12px 0; }
  .ref-titulo {
    font-weight: 600; color: var(--texto-suave); text-transform: uppercase;
    font-size: 11px; letter-spacing: .03em; margin-bottom: 8px;
  }
  .cabecera-app { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
  .badge-usuario { font-size: 12px; color: var(--texto-suave); }
  .paginacion { display: flex; gap: 8px; align-items: center; margin-top: 14px; font-size: 12px; color: var(--texto-suave); }
  a.enlace-descarga { color: var(--acento); text-decoration: none; font-size: 12px; margin-right: 10px; cursor: pointer; }
  a.enlace-descarga:hover { text-decoration: underline; }
  .boton-copiar {
    background: transparent; border: none; color: var(--texto-suave); cursor: pointer;
    padding: 2px 4px; display: inline-flex; align-items: center; vertical-align: middle;
    border-radius: 4px; margin-left: 4px;
  }
  .boton-copiar:hover { color: var(--acento); background: rgba(255,255,255,.06); }
  .boton-copiar svg { display: block; }
  button.descarga {
    background: #1a2032; color: var(--acento); border: 1px solid rgba(91, 140, 255, .35);
    padding: 6px 10px; font-size: 11px; font-weight: 700; letter-spacing: .03em; border-radius: 6px;
  }
  button.descarga:hover { background: #212a42; opacity: 1; }
  .checkbox-linea { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--texto); }

  .selector-fichero {
    display: flex; align-items: center; gap: 12px; background: #0d1015; border: 1px solid var(--borde);
    border-radius: 8px; padding: 10px 12px;
  }
  .selector-fichero input[type=file] { display: none; }
  .selector-fichero label {
    background: #262b36; color: var(--texto); padding: 8px 16px; border-radius: 7px; cursor: pointer;
    font-size: 12px; font-weight: 600; white-space: nowrap; transition: background .15s;
  }
  .selector-fichero label:hover { background: #323a48; }
  .selector-fichero .nombre-fichero {
    font-size: 12px; color: var(--texto-suave); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  #barra-progreso-contenedor {
    background: #0d1015; border: 1px solid var(--borde); border-radius: 999px; height: 10px;
    overflow: hidden; margin-bottom: 10px;
  }
  #barra-progreso {
    height: 100%; width: 0%; background: linear-gradient(135deg, var(--acento), var(--acento-2));
    transition: width .15s ease;
  }
  #texto-progreso { font-size: 12px; color: var(--texto-suave); margin-bottom: 10px; }

  #json-subida {
    background: #0d1015; border: 1px solid var(--borde); border-radius: 8px; padding: 12px;
    font-size: 11px; line-height: 1.5; max-height: 240px; overflow: auto; white-space: pre-wrap;
    word-break: break-all; color: var(--texto-suave); margin-top: 4px;
  }