﻿/* =============================================================================
   Massignal — estilos propios de la aplicación.

   Aquí va solo el armazón: barra lateral, cabecera y las dos o tres piezas que no
   son reutilizables. Todo lo genérico (controles, grilla, paneles, alertas) vive
   en mas.css y se usa tal cual, con sus mismas variables --mas-*.
   ============================================================================= */

/* --- Armazón ------------------------------------------------------------- */

.app {
    display: grid;
    grid-template-columns: 232px 1fr;
    min-height: 100vh;
}

/* Menú plegado: la barra queda del ancho de un icono. La transición es de la
   rejilla, no de cada pieza, para que la lateral y el contenido se muevan juntos. */
.menu-plegado .app { grid-template-columns: 64px 1fr; }
.app { transition: grid-template-columns .16s ease; }

.app-lateral {
    background: linear-gradient(180deg, var(--mas-primario-900), var(--mas-primario-700));
    color: #dce9fb;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 18px 12px;
}

.app-principal {
    display: flex;
    flex-direction: column;
    min-width: 0; /* sin esto una grilla ancha desborda la rejilla en vez de scrollear */
}

.app-contenido {
    padding: var(--mas-espacio);
    display: flex;
    flex-direction: column;
    gap: var(--mas-espacio);
}

/* --- Marca --------------------------------------------------------------- */

.app-marca,
.acceso-marca {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 4px 10px 14px;
    font-weight: 600;
    letter-spacing: .2px;
}

.app-lateral .app-marca { color: #ffffff; font-size: 15px; }

/* La M. El alto se fija aquí y el ancho sale de la proporción del propio dibujo
   (48/50), así que nunca se deforma aunque cambie el tamaño.

   Toma el color por «currentColor»: blanca en la barra lateral porque ese es el color
   del contenedor, azul en las pantallas de acceso por lo mismo. No hay una regla de
   color para la marca en ningún lado, y es a propósito: una sola verdad. */
.marca-simbolo {
    height: 21px;
    width: auto;
    flex: none;
}

/* En el acceso la marca es la protagonista: en vertical, grande y centrada. */
.acceso-marca {
    flex-direction: column;
    gap: 10px;
    padding: 2px 0 16px;
    color: var(--mas-primario-900);
}

.acceso-marca .marca-simbolo { height: 44px; }

/* El texto de la marca en el acceso imita el bloque del logo: versales y muy
   espaciado. En la barra lateral se deja como estaba —a 15 px las versales
   espaciadas se leen peor que la palabra normal. */
.acceso-marca .app-marca-texto {
    text-transform: uppercase;
    letter-spacing: 2.4px;
    font-size: 13.5px;
    color: var(--mas-primario-900);
}

/* --- Botón de plegar ------------------------------------------------------ */

.app-plegar {
    margin-left: auto;
    display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 26px; flex: none;
    padding: 0; border: 0; border-radius: var(--mas-radio-sm);
    background: rgba(255, 255, 255, .10); color: #dce9fb;
    cursor: pointer; transition: background .12s, color .12s;
}

.app-plegar:hover { background: rgba(255, 255, 255, .22); color: #ffffff; }
.app-plegar svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* La flecha es la misma: se da vuelta según el estado, así siempre apunta hacia
   donde va a moverse la barra. */
.menu-plegado .app-plegar svg { transform: rotate(180deg); }

/* Plegado no caben marca, palabra y botón en una fila de 48 px útiles: se apilan y
   cae la palabra. La M se queda —es lo que hace que la barra angosta siga siendo de
   algo y no una columna de iconos sueltos— y el botón sigue debajo, que es lo único
   accionable y no puede desaparecer o no habría cómo volver a desplegar. */
.menu-plegado .app-marca {
    padding: 4px 0 14px;
    flex-direction: column;
    justify-content: center;
    gap: 8px;
}

.menu-plegado .app-marca-texto { display: none; }
.menu-plegado .app-plegar { margin-left: 0; width: 30px; height: 30px; }

/* --- Navegación ---------------------------------------------------------- */

.app-nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.app-nav-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    border-radius: var(--mas-radio-sm);
    color: #c3d8f5;
    text-decoration: none;
    font-size: 13.5px;
    white-space: nowrap;
    transition: background .12s, color .12s;
}

.app-nav-item:hover { background: rgba(255, 255, 255, .12); color: #ffffff; }

/* El icono hereda el color del ítem —incluido el activo— porque el trazo es
   currentColor: un solo juego de iconos sirve para los tres estados. */
.app-nav-icono {
    width: 18px; height: 18px; flex: none;
    fill: none; stroke: currentColor;
    stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
    opacity: .9;
}

.app-nav-activo .app-nav-icono { opacity: 1; stroke-width: 1.9; }

.app-nav-texto { overflow: hidden; text-overflow: ellipsis; }

/* Plegado: solo el icono, centrado. El texto se oculta en vez de achicarse
   —a medio tamaño no se lee y ensucia la columna—, y el nombre queda en el
   title, que el script pone al plegar. */
.menu-plegado .app-nav-item { justify-content: center; padding: 10px 0; gap: 0; }
.menu-plegado .app-nav-texto { display: none; }
.menu-plegado .app-lateral { padding: 18px 8px; }

/* La hoja de símbolos no se dibuja: solo alimenta a los <use>. */
.app-iconos { display: none; }

.app-nav-activo,
.app-nav-activo:hover {
    background: #ffffff;
    color: var(--mas-primario-900);
    font-weight: 600;
}

/* --- Cabecera ------------------------------------------------------------ */

.app-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--mas-espacio);
    padding: 12px var(--mas-espacio);
    background: var(--mas-superficie);
    border-bottom: 1px solid var(--mas-borde);
}

.app-cabecera-titulo { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.app-cabecera-titulo h1 { margin: 0; font-size: 17px; font-weight: 600; }

.app-organizacion b { font-weight: 600; color: var(--mas-texto-suave); }

.app-organizacion {
    font-size: 12.5px;
    color: var(--mas-texto-tenue);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.app-usuario { display: flex; align-items: center; gap: 18px; }

.app-usuario-datos {
    display: flex; flex-direction: column; align-items: flex-end;
    line-height: 1.2; min-width: 0;
}
.app-usuario-nombre {
    font-size: 13.5px; font-weight: 600; color: var(--mas-texto);
    text-decoration: none; white-space: nowrap;
}
.app-usuario-nombre:hover { color: var(--mas-primario); text-decoration: underline; }
.app-usuario-rol {
    font-size: 11.5px; color: var(--mas-texto-tenue);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 220px;
}

/* Separadores verticales entre nombre, reloj y estado: ordenan el bloque sin
   agregar cajas ni bordes que compitan con la cabecera. */
.app-usuario > .mas-reloj,
.app-usuario > .mas-conexion { position: relative; }
.app-usuario > .mas-reloj::before,
.app-usuario > .mas-conexion::before {
    content: ""; position: absolute; left: -9px; top: 50%; transform: translateY(-50%);
    width: 1px; height: 26px; background: var(--mas-borde);
}

.app-salir { margin: 0; }

@media (max-width: 900px) {
    .app-usuario > .mas-reloj .mas-reloj-fecha { display: none; }
    .app-usuario-rol { display: none; }
}
@media (max-width: 700px) {
    .app-usuario > .mas-conexion { display: none; }
}

/* --- Accesos rápidos del inicio ------------------------------------------ */

.inicio-accesos {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 12px;
    margin-top: var(--mas-espacio);
}

.inicio-acceso {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 14px;
    border: 1px solid var(--mas-borde);
    border-radius: var(--mas-radio);
    background: var(--mas-superficie-2);
    text-decoration: none;
    color: inherit;
}

.inicio-acceso:hover { border-color: var(--mas-primario); box-shadow: var(--mas-sombra); }
.inicio-acceso span { font-size: 12.5px; color: var(--mas-texto-tenue); }

/* La ocupación como una tarjeta más de la rejilla de accesos. No es un enlace:
   no se ilumina al pasar por encima ni cambia el cursor, para que se lea como
   información y no como algo que se puede pulsar. */

/* El almacenamiento se mudó a la fila de fichas: es un NÚMERO, y entre
   «Organizaciones» y «Clientes» se leía como un sitio al que ir. */
.inicio-almacenamiento { cursor: default; }

/* --- Estado del parque en Inicio -----------------------------------------
   EL ROJO ES UN RECURSO QUE SE GASTA.

   Antes esto era una tarjeta de ancho completo con el fondo rojo. Si está roja
   todos los días porque siempre hay una pantalla apagada, en dos semanas deja
   de significar algo, y el día que importe nadie la mira. Ahora el rojo vive en
   una franja delgada que aparece SOLO cuando hay algo que hacer y desaparece
   sola cuando se resuelve.

   El tono nunca decide solo: lo que la franja dice está escrito —«2 sin
   señal»—, así que quien no distingue el matiz lee exactamente lo mismo. Misma
   regla que la leyenda en un gráfico: la identidad no depende del color. */

.inicio-aviso {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    padding: 11px 14px;
    margin-bottom: 14px;
    background: var(--mas-peligro-suave);
    border: 1px solid color-mix(in srgb, var(--mas-peligro) 30%, transparent);
    border-left: 3px solid var(--mas-peligro);
    border-radius: var(--mas-radio);
    font-size: 13.5px;
}

.inicio-aviso-icono { width: 16px; height: 16px; flex: 0 0 auto; margin-top: 2px; fill: var(--mas-peligro); }
.inicio-aviso-texto { display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; }
.inicio-aviso-texto strong { color: var(--mas-peligro); }
.inicio-aviso-texto span { color: var(--mas-texto-suave); }
.inicio-aviso-texto b { color: var(--mas-texto); }

/* El enlace se va al extremo y no se parte: es la salida de la franja, y
   buscarla entre el texto cada vez cuesta más que el espacio que ocupa. */
.inicio-aviso-enlace {
    margin-left: auto;
    align-self: center;
    white-space: nowrap;
    font-size: 13px;
    font-weight: 600;
    color: var(--mas-peligro);
}

/* LAS FICHAS Y LOS ACCESOS SON DOS REJILLAS CON LA MISMA MEDIDA.

   Misma columna de 230px que los accesos, para que las dos filas se alineen y
   la página se lea como una sola cosa. Lo que cambia es el contenido: una ficha
   dice CUÁNTO HAY, un acceso es una PUERTA. */
.inicio-indicadores {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 12px;
    margin-bottom: 14px;
}

/* --- Resumen sobre una grilla ---------------------------------------------

   CLASES PROPIAS Y NO LAS DE `inicio-ficha`, aunque el aspecto sea pariente. Aquellas
   llevan el nombre de una pantalla: reusarlas en otra obliga a quien lea el CSS a
   averiguar si la regla es de Inicio o de todos, y el día que Inicio quiera cambiar sus
   fichas se arrastra a quien no pidió nada.

   ES UNA TIRA Y NO UNA REJILLA DE FICHAS, a diferencia de Inicio: encima de una lista, un
   bloque alto empuja las filas fuera de la pantalla, que es lo que uno vino a mirar. Dos
   cifras y una línea de detalle caben en una sola altura de fila.

   EL COLOR VA EN EL BORDE IZQUIERDO Y EN LA SEGUNDA CIFRA, nunca en el fondo: un fondo
   rojo encima de la lista grita, y lo que hace falta es que se note sin tapar nada. */
.grilla-resumen {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 6px 26px;
    padding: 11px 15px;
    margin-bottom: 12px;
    border: 1px solid var(--mas-borde);
    border-left: 3px solid var(--mas-borde);
    border-radius: var(--mas-radio);
    background: var(--mas-superficie-2);
}

/* `hidden` NO ALCANZA POR SÍ SOLO, Y ESTO ERA UN ERROR REAL.

   El `display: none` de `[hidden]` lo trae la hoja del navegador, que pierde contra
   cualquier regla del autor: `.grilla-resumen { display: flex }` la pisaba, y la tarjeta se
   mostraba igual —vacía, con dos guiones— mientras se suponía que estaba oculta. Es la
   trampa clásica de combinar `hidden` con una clase que declara `display`. */
.grilla-resumen[hidden] { display: none; }

/* Dentro de la fila de acciones: a la izquierda del todo y sin su margen inferior, que
   ahí lo pone el contenedor. */
.pagina-acciones .grilla-resumen { margin-right: auto; margin-bottom: 0; }

/* EL AIRE SE PONE EN LA COMBINACIÓN Y NO EN NINGUNA DE LAS DOS CLASES. `pagina-acciones`
   vive en media docena de pantallas y `atajos-actividad` en dos: darle un margen a
   cualquiera de ellas movería cosas que nadie pidió mover. El selector de hermano adyacente
   toca exactamente el caso que lo necesita —una fila de acciones seguida de una de
   atajos— y ningún otro. */
.pagina-acciones + .atajos-actividad { margin-top: 12px; }

.grilla-resumen-dato { display: flex; align-items: baseline; gap: 7px; }
.grilla-resumen-cifra { font-size: 22px; font-weight: 600; line-height: 1.1; color: var(--mas-texto); }
.grilla-resumen-rotulo { font-size: 12.5px; color: var(--mas-texto-suave); }

/* El detalle se va al extremo opuesto: es contexto, no titular. */
.grilla-resumen-detalle { margin-left: auto; font-size: 12.5px; color: var(--mas-texto-tenue); }

.grilla-resumen-mala { border-left-color: var(--mas-peligro); }
.grilla-resumen-mala .grilla-resumen-dato:last-of-type .grilla-resumen-cifra { color: var(--mas-peligro); }

@media (max-width: 640px) {
    /* El detalle deja de empujarse a la derecha y pasa a su propia línea: en un teléfono,
       `margin-left: auto` lo deja pegado al borde y partido en tres renglones. */
    .grilla-resumen-detalle { margin-left: 0; flex-basis: 100%; }
}

/* El color va en el borde izquierdo y en la cifra, nunca en el fondo: un fondo
   de color en cuatro fichas seguidas convierte la fila en un semáforo y deja de
   poder leerse de un vistazo, que es justo para lo que existe. */
.inicio-ficha {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 13px 14px;
    border: 1px solid var(--mas-borde);
    border-left: 3px solid var(--mas-borde);
    border-radius: var(--mas-radio);
    background: var(--mas-superficie-2);
}

.inicio-ficha-cifra { font-size: 27px; font-weight: 600; line-height: 1.15; color: var(--mas-texto); }
.inicio-ficha-cifra small { font-size: 14px; font-weight: 400; color: var(--mas-texto-tenue); }
.inicio-ficha-rotulo { font-size: 12.5px; color: var(--mas-texto-suave); }

.inicio-ficha-mala { border-left-color: var(--mas-peligro); }
.inicio-ficha-mala .inicio-ficha-cifra { color: var(--mas-peligro); }
.inicio-ficha-ojo  { border-left-color: var(--mas-advertencia); }
.inicio-ficha-ojo .inicio-ficha-cifra { color: var(--mas-advertencia); }
.inicio-ficha-bien { border-left-color: var(--mas-exito); }
.inicio-ficha-bien .inicio-ficha-cifra { color: var(--mas-exito); }

.inicio-ficha .almacenamiento-barra { width: 100%; margin-top: 6px; }

/* --- Indicador de almacenamiento ----------------------------------------
   Vive DENTRO de la barra de acciones y se empuja a la izquierda con el
   margin auto: así comparte línea con los botones —que es donde se mira—
   sin necesidad de otra fila ni de posicionarlo a mano. */

.almacenamiento {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-right: auto;        /* empuja los botones al otro extremo */
    font-size: 13px;
    color: var(--mas-texto-suave);
}

.almacenamiento-titulo {
    color: var(--mas-texto-tenue);
    text-transform: uppercase;
    font-size: 11px;
    letter-spacing: .4px;
}

.almacenamiento-detalle strong { color: var(--mas-texto); font-weight: 600; }

.almacenamiento-barra {
    width: 140px; height: 6px; overflow: hidden;
    background: var(--mas-primario-100); border-radius: 999px;
}

.almacenamiento-relleno {
    width: 0; height: 100%; background: var(--mas-primario);
    border-radius: 999px; transition: width .2s linear;
}

/* El color cambia solo cuando ya conviene mirarlo. Un indicador siempre rojo
   deja de decir nada; uno que solo se enciende cerca del tope se nota. */
.almacenamiento-relleno.almacenamiento-alerta { background: var(--mas-advertencia); }
.almacenamiento-relleno.almacenamiento-critico { background: var(--mas-peligro); }

/* En pantalla angosta el indicador se va a su propia línea antes que apretar
   los botones: la barra de acciones ya envuelve. */
@media (max-width: 780px) {
    .almacenamiento { margin-right: 0; width: 100%; }
}

/* Barra de acciones de una pantalla de listado. Vive fuera de <mas-grilla>
   porque su barra interna no admite tag helpers como hijos. */
.pagina-acciones { display: flex; align-items: center; justify-content: flex-end; gap: 10px; flex-wrap: wrap; }

/* --- Acciones destructivas en la ficha ----------------------------------- */

.usuario-acciones { display: flex; flex-wrap: wrap; gap: 10px; }
.usuario-acciones form { margin: 0; }

.mas-lista-errores { margin: 4px 0 0; padding-left: 18px; }

/* --- Pantallas de acceso -------------------------------------------------- */

body.acceso {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: var(--mas-espacio);
}

.acceso-caja {
    width: 100%;
    max-width: 380px;
    padding: 26px;
    background: var(--mas-superficie);
    border: 1px solid var(--mas-borde);
    border-radius: var(--mas-radio);
    box-shadow: var(--mas-sombra-md);
}

.acceso-marca { justify-content: center; padding-bottom: 6px; }
.acceso-titulo { margin: 0 0 18px; font-size: 18px; font-weight: 600; text-align: center; }
.acceso-boton { width: 100%; justify-content: center; }
.acceso-pie { margin: 20px 0 0; text-align: center; font-size: 12px; color: var(--mas-texto-tenue); }

/* Enlace de salida de las pantallas de acceso: recuperar clave, volver al login.
   Discreto y centrado bajo el botón — es la alternativa, no la acción principal. */
.acceso-secundario { margin: 14px 0 0; text-align: center; font-size: 13px; }
.acceso-secundario a { color: var(--mas-texto-suave); text-decoration: none; }
.acceso-secundario a:hover { color: var(--mas-primario); text-decoration: underline; }

/* --- Pantallas angostas --------------------------------------------------- */

@media (max-width: 820px) {
    .app { grid-template-columns: 1fr; }

    .app-lateral {
        border-right: none;
        border-bottom: 1px solid var(--mas-borde);
    }

    .app-nav { flex-direction: row; flex-wrap: wrap; }
}

/* Texto explicativo de las pantallas de acceso (instalación, recuperación). */
.acceso-ayuda {
    margin: 0 0 var(--mas-espacio);
    color: var(--mas-texto-suave);
    font-size: 13.5px;
}

/* --- Franja de organización activa ---------------------------------------
   El administrador global puede estar operando sobre datos de un cliente sin
   darse cuenta. Esta franja es deliberadamente llamativa: el riesgo de crear
   un usuario en la organización equivocada es real. */

.app-contexto {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 9px var(--mas-espacio);
    background: var(--mas-advertencia-suave);
    border-bottom: 1px solid color-mix(in srgb, var(--mas-advertencia) 30%, transparent);
    color: var(--mas-advertencia);
    font-size: 13px;
}

.app-contexto form { margin: 0; }

/* --- Pantalla de parámetros ----------------------------------------------
   La grilla agrupada y el diálogo de edición salen del framework; lo único
   propio de esta pantalla es cómo se ven la clave técnica y la descripción. */

.parametro-clave {
    margin: 0 0 4px;
}

.parametro-descripcion {
    margin: 0 0 var(--mas-espacio);
    color: var(--mas-texto-suave);
    font-size: 13px;
    line-height: 1.5;
}

/* En la celda la descripción se recorta: es un apoyo de lectura, y el texto
   completo se ve en el diálogo de edición. Sin el recorte, una descripción
   larga estira la fila y descuadra la agrupación visual. */
.parametro-descripcion-celda {
    display: block;
    color: var(--mas-texto-suave);
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
}

.parametro-valor {
    font-family: var(--mas-fuente-mono);
    font-size: 12.5px;
    word-break: break-all;
}

/* ==========================================================================
   Biblioteca de contenido
   ========================================================================== */

.contenido-filtros {
    display: flex;
    gap: var(--mas-espacio);
    flex-wrap: wrap;
    padding: 12px 14px;
    border-bottom: 1px solid var(--mas-borde);
    background: var(--mas-superficie-2);
}

.contenido-filtro {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 170px;
}

.contenido-filtro > span {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--mas-texto-suave);
}

/* La grilla vive dentro de un panel sin relleno: sin esto tendría borde y sombra
   propios dentro de otro borde. */
.contenido-filtros + .mas-grilla {
    border: none;
    border-radius: 0;
    box-shadow: none;
}

/* Miniatura de la celda. Tamaño FIJO en los dos ejes con object-fit: cover para
   que una imagen vertical y una panorámica ocupen lo mismo; si el alto variara,
   cada fila de la tabla tendría una altura distinta. */
.contenido-mini {
    display: block;
    width: 64px;
    height: 40px;
    margin: 0 auto;
    object-fit: cover;
    border-radius: var(--mas-radio-sm);
    background: var(--mas-superficie-2);
    border: 1px solid var(--mas-borde);
}

/* Marcador mientras no hay miniatura: la inicial del tipo sobre el mismo hueco,
   para que la columna no se descuadre al aparecer la imagen real. */
.contenido-mini-vacia {
    display: grid;
    place-items: center;
    font-size: 15px;
    font-weight: 700;
    color: var(--mas-texto-tenue);
    background: var(--mas-primario-50);
}

.contenido-nombre {
    display: block;
    color: var(--mas-primario);
    text-decoration: none;
    font-weight: 500;
}
.contenido-nombre:hover { text-decoration: underline; }

.contenido-dimensiones {
    display: block;
    font-size: 11.5px;
    color: var(--mas-texto-tenue);
    font-variant-numeric: tabular-nums;
}

/* Ficha de solo lectura del diálogo de edición. */
.contenido-ficha {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 10px 16px;
    margin: 0 0 var(--mas-espacio);
    padding: 12px 14px;
    background: var(--mas-superficie-2);
    border: 1px solid var(--mas-borde);
    border-radius: var(--mas-radio-sm);
}
.contenido-ficha dt {
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--mas-texto-tenue);
}
.contenido-ficha dd {
    margin: 2px 0 0;
    font-size: 13px;
    word-break: break-word;
}

/* Botones de la columna de acciones: en una sola línea, pegados al borde derecho. */
/* --- Ficha de contenido (diálogo de vista previa) ------------------------

   El visor tiene alto máximo y no fijo: un afiche vertical y un video 16:9 no
   pueden ocupar la misma caja sin que a uno le sobren bandas negras. */

.contenido-visor {
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: var(--mas-espacio);
    padding: 8px;
    background: #0f172a;               /* fondo oscuro: es lo que no compite con la imagen */
    border-radius: var(--mas-radio);
}

.contenido-visor img,
.contenido-visor video {
    max-width: 100%;
    max-height: 46vh;                  /* deja ver los datos sin tener que scrollear */
    border-radius: var(--mas-radio-sm);
}

/* DOS PARES POR FILA: etiqueta-valor, etiqueta-valor. Con un par por fila la
   ficha crecía hacia abajo hasta dejar el video y los botones fuera de la
   pantalla; los valores son cortos (un tamaño, una fecha) y desperdiciaban
   media línea cada uno.

   minmax(0, 1fr) y no 1fr: sin el mínimo en cero, un valor largo —el nombre de
   un archivo— ensancha su columna y descuadra las otras. */
.contenido-datos {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto minmax(0, 1fr);
    gap: 6px 14px;
    margin: 0;
    font-size: 13.5px;
}

.contenido-datos dt { color: var(--mas-texto-tenue); white-space: nowrap; }
.contenido-datos dd { margin: 0; word-break: break-word; }

/* Lo que no cabe en media fila —una descripción— se lleva el ancho completo. */
.contenido-datos dd.contenido-dato-ancho { grid-column: 2 / -1; }

@media (max-width: 900px) {
    .contenido-datos { grid-template-columns: auto minmax(0, 1fr); }
    .contenido-datos dd.contenido-dato-ancho { grid-column: 2; }
}

@media (max-width: 560px) {
    .contenido-datos { grid-template-columns: 1fr; gap: 2px; }
    .contenido-datos dd { margin-bottom: 8px; }
    .contenido-datos dd.contenido-dato-ancho { grid-column: 1; }
}

/* El nombre de la grilla es un <button> —abre un diálogo, no navega— pero se lee
   como un enlace, que es lo que la gente espera de un nombre pinchable. */
button.contenido-nombre {
    display: block;
    padding: 0;
    border: none;
    background: none;
    color: var(--mas-primario);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

button.contenido-nombre:hover { text-decoration: underline; }

/* Botones de acción de una fila. Contenedor propio para que se mantengan en una
   sola línea aunque la columna quede justa, en vez de apilarse y estirar la fila. */
.contenido-acciones,
.fila-acciones {
    display: inline-flex;
    gap: 6px;
    justify-content: flex-end;
    white-space: nowrap;
}

/* -------------------------------------------------------------------------------------
   EL ASPECTO DE ESOS BOTONES, Y POR QUÉ NO SON COMO LOS DEMÁS DEL PANEL.

   Un botón suelto en una pantalla puede ir relleno de color: es uno, y llama la atención
   una vez. Estos aparecen CUATRO POR FILA y cincuenta veces en la misma pantalla. Con el
   rojo macizo que tenían, la columna de «Baja» se convertía en una franja de alarma que
   tapaba lo único que de verdad hay que mirar de un vistazo: el estado del player.

   Así que aquí el color es un TINTE y no un bloque. La jerarquía sigue estando —el azul
   es acción, el rojo es cuidado— pero dicha en voz baja, que es como hay que decir algo
   que se repite doscientas veces.

   TODO SALE DE LAS VARIABLES DEL TEMA. Ni un color escrito a mano: el día que se cambie
   el azul de la aplicación, o que un cliente traiga el suyo, estos botones lo siguen sin
   que nadie se acuerde de venir a tocarlos.
   ------------------------------------------------------------------------------------- */

/* EL ANCHO MÍNIMO ES 88px Y ESE NÚMERO ESTÁ MEDIDO, no elegido.

   Igualar el ancho es lo que alinea las columnas de acciones de una fila con las de la
   siguiente. Lo fija «Sucursales», que con la tipografía de la grilla ocupa 86px y es la
   palabra más larga que queda en un botón; 88 le deja un punto a cada lado.

   Cuando TODOS los botones eran de palabra, este número no podía pasar de 84: a partir
   de 86 la columna de acciones le robaba ancho a la del nombre, el nombre se partía en
   dos líneas y la tabla crecía un 20% de alto. Ahora la mayoría son iconos de 34px y la
   columna entera es mucho más estrecha, así que hay sitio de sobra — pero si algún día
   se vuelve al texto en todas, hay que volver a mirar el alto de las filas.

   Se aplica a TODOS los hijos, incluido el primero. Antes se excluía el primero porque
   todos eran de palabra y el de la izquierda no tenía con qué desalinearse; ahora que
   una fila mezcla palabras e iconos, el de palabra puede caer en cualquier posición y
   tiene que medir siempre lo mismo. Al de icono no le afecta: la regla de «.mas-accion»
   de más abajo tiene más peso y lo devuelve a 34px. */
.fila-acciones > *,
.contenido-acciones > * {
    min-width: 88px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* EL TINTE. «mas-btn-tenue» existe para poder pedirlo fuera de una fila de grilla —el
   «Quitar» de una zona, por ejemplo—: el aspecto se define UNA vez y los dos sitios lo
   comparten, en vez de copiar los mismos cuatro colores en otra regla que después nadie
   se acuerda de actualizar. Dentro de una fila de acciones se aplica solo, sin pedirlo. */
.mas-btn-tenue,
.fila-acciones .mas-btn,
.contenido-acciones .mas-btn {
    /* Medio punto menos que el texto de la fila. Lo justo para que el botón se lea como
       acción y no como contenido, sin que «Revincular» empiece a costar de leer. */
    font-size: 12.5px;
    padding: 5px 8px;

    /* Más rectangular que el resto del panel: a este tamaño, una esquina muy redonda hace
       que cuatro botones seguidos parezcan pastillas sueltas en vez de una barra. */
    border-radius: 4px;

    background: var(--mas-primario-50);
    color: var(--mas-primario-700);
    border-color: var(--mas-primario-100);
}

.mas-btn-tenue:hover:not([disabled]):not([aria-disabled="true"]),
.fila-acciones .mas-btn:hover:not([disabled]):not([aria-disabled="true"]),
.contenido-acciones .mas-btn:hover:not([disabled]):not([aria-disabled="true"]) {
    background: var(--mas-primario-100);
    border-color: var(--mas-primario-300);
    color: var(--mas-primario-700);
}

/* Un botón de icono es CUADRADO. El ancho mínimo de arriba es para las palabras; si se
   le aplicara a un dibujo de 16px lo dejaría perdido en medio de un rectángulo vacío. */
.fila-acciones .mas-accion,
.contenido-acciones .mas-accion {
    min-width: 34px;
    width: 34px;
    padding: 5px 0;
}

/* El icono se centra ópticamente: un SVG en línea se apoya en la línea base del texto y
   queda un par de píxeles bajo del centro si no se le dice lo contrario. */
.fila-acciones .mas-accion svg,
.contenido-acciones .mas-accion svg { display: block; }

.fila-acciones > :first-child,
.contenido-acciones > :first-child { border-radius: 4px; }

/* El que da de baja. El borde se calcula desde el mismo token del peligro en vez de
   escribir un tercer rojo a mano: si algún día se ajusta ese color, el borde lo sigue.
   Un navegador que no entienda color-mix se queda con el borde base, que es correcto. */
.mas-btn-tenue.mas-btn-peligro,
.fila-acciones .mas-btn-peligro,
.contenido-acciones .mas-btn-peligro {
    background: var(--mas-peligro-suave);
    color: var(--mas-peligro);
    border-color: color-mix(in srgb, var(--mas-peligro) 22%, transparent);
}

.mas-btn-tenue.mas-btn-peligro:hover:not([disabled]):not([aria-disabled="true"]),
.fila-acciones .mas-btn-peligro:hover:not([disabled]):not([aria-disabled="true"]),
.contenido-acciones .mas-btn-peligro:hover:not([disabled]):not([aria-disabled="true"]) {
    background: color-mix(in srgb, var(--mas-peligro) 14%, var(--mas-superficie));
    border-color: color-mix(in srgb, var(--mas-peligro) 40%, transparent);
    color: var(--mas-peligro);
}

/* Barra de acciones de Contenido: filtro a la izquierda, botón a la derecha. */
.pagina-acciones .contenido-filtro { margin-right: auto; }
.pagina-acciones .contenido-filtro .mas-control { min-width: 200px; }

/* Aviso de proceso fallido bajo el nombre. No ocupa columna propia porque solo
   aparece cuando algo salió mal. */
.contenido-problema {
    display: block;
    font-size: 12px;
    color: var(--mas-peligro);
    cursor: help;
}

/* Barra de contexto: organización y cliente, más el selector para cambiar de cliente. */
.app-contexto-texto { display: flex; gap: 18px; flex-wrap: wrap; }
/* EL SELECTOR SE VA A LA DERECHA, PEGADO AL BOTÓN DE SALIR.

   La franja es un flex con `justify-content: space-between` y tres hijos: el aviso, el
   selector y el botón. Repartidos, el selector quedaba suelto en el medio, lejos de lo
   que hay a su lado y lejos del texto.

   `margin-left: auto` se come todo el espacio sobrante antes de él, así que el aviso se
   queda a la izquierda y el selector y el botón viajan juntos a la derecha, separados
   solo por el `gap` de la franja. Son los dos controles de la barra: juntos se leen como
   un grupo, y lo que queda a la izquierda es información. */
/* EL SELECTOR SE EMPUJA A LA DERECHA CON `form.` DELANTE, y no es un capricho.

   `.app-contexto form { margin: 0 }`, unas líneas más arriba, vale (0,1,1) por llevar un
   tipo además de la clase; `.app-contexto-cliente` sola vale (0,1,0). La más específica
   gana aunque esté antes, así que el `margin-left: auto` no se aplicaba nunca y el
   selector seguía repartido en el medio por el `space-between` de la franja.

   Con `form.app-contexto-cliente` la regla vale (0,1,1) también, y al ir después, gana. */
.app-contexto form.app-contexto-cliente {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 0 auto;
}
/* La etiqueta es de dos palabras y en un flex se parte en dos líneas, dejando el
   selector descolgado. Cabe de sobra: lo que hay que impedir es el salto. */
.app-contexto-cliente label { white-space: nowrap; }
.app-contexto-cliente .mas-control { padding: 4px 8px; font-size: 13px; min-width: 180px; }

/* --- Código de vinculación de un player -----------------------------------
   Se muestra una sola vez y alguien lo va a copiar a mano o dictarlo por
   teléfono: grande, monoespaciado y con las letras separadas, que es lo que
   evita confundir un 8 con una B al leerlo de lejos. */

.codigo-vinculacion {
    margin: 14px 0 10px;
    padding: 16px 12px;
    text-align: center;
    font-family: Consolas, "SF Mono", monospace;
    font-size: 30px;
    font-weight: 700;
    letter-spacing: 7px;
    color: var(--mas-primario-900, #10275e);
    background: var(--mas-primario-100);
    border: 1px dashed var(--mas-primario);
    border-radius: var(--mas-radio);
    user-select: all;   /* un clic selecciona el código entero */
}

/* --- Pantalla de reposo (screensaver) -------------------------------------
   Editor y vista previa lado a lado: se escribe HTML mirando el resultado,
   que es la única forma de iterar sin volverse loco. */

.screensaver { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--mas-espacio); align-items: start; }

@media (max-width: 1100px) { .screensaver { grid-template-columns: 1fr; } }

/* El selector lleva el tipo (textarea.…) para ganarle a la regla del framework, que
   fija min-height: 70px para cualquier textarea. Sin eso, el editor sale de tres
   líneas y escribir HTML ahí es un castigo. */
textarea.screensaver-editor {
    min-height: 460px;
    font-family: Consolas, "SF Mono", monospace;
    font-size: 12.5px;
    line-height: 1.5;
    tab-size: 2;
    white-space: pre;      /* sin ajuste de línea: el HTML se lee por columnas */
    overflow: auto;
}

/* 16:9, que es la proporción de casi cualquier pantalla de local. El fondo
   oscuro deja claro dónde termina el diseño y empieza el panel. */
.screensaver-marco {
    position: relative;
    aspect-ratio: 16 / 9;
    background: #0b1b3a;
    border: 1px solid var(--mas-borde);
    border-radius: var(--mas-radio);
    overflow: hidden;
}

.screensaver-iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: #000; }

/* --- Plataforma del player ------------------------------------------------
   Un icono por marca en la grilla. Los dibujos se distinguen por FORMA
   —televisor, tableta, torre— y no por color: en una grilla de cincuenta
   filas, mirada de reojo, la forma se lee y el color no tanto. */

.plataforma { display: inline-flex; align-items: center; justify-content: center; }

.plataforma-icono {
    width: 19px; height: 19px;
    fill: none;
    /* El color lo pone cada icono con el de su marca; este es solo el respaldo. */
    stroke: var(--mas-texto-suave);
    stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}

/* Para lectores de pantalla y para la exportación: el nombre de la marca
   está en el DOM aunque no se vea. Un icono sin texto no lo lee nadie. */
.mas-oculto-visual {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --- Listas de reproducción ----------------------------------------------

   El editor: tarjetas de resumen arriba, los ítems a la izquierda y la biblioteca a la
   derecha. En pantallas angostas la biblioteca pasa abajo en vez de encogerse: con
   menos de 380 px el nombre de un archivo no se lee y el panel deja de servir. */

/* Rejilla y no flex: con flex, la última tarjeta de una fila incompleta se estira
   sola y queda del ancho de tres. Con auto-fit todas miden lo mismo, quepan cinco o
   dos por fila. */
.lst-resumen {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(142px, 1fr));
    gap: 10px;
    margin-bottom: var(--mas-espacio);
}

.lst-tarjeta {
    background: var(--mas-superficie);
    border: 1px solid var(--mas-borde);
    border-radius: var(--mas-radio);
    padding: 12px 14px;
}

.lst-tarjeta-rotulo {
    font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;
    color: var(--mas-texto-tenue); font-weight: 600;
}

.lst-tarjeta-valor {
    font-size: 21px; font-weight: 600; color: var(--mas-primario-900);
    font-variant-numeric: tabular-nums; margin-top: 2px;
}

.lst-tarjeta-pie { font-size: 12px; color: var(--mas-texto-suave); }

.lst-columnas {
    display: grid;
    grid-template-columns: 1fr 380px;
    gap: var(--mas-espacio);
    align-items: start;
}

@media (max-width: 1200px) {
    .lst-columnas { grid-template-columns: 1fr; }
}

/* --- Un ítem de la lista --- */

.lst-item {
    display: flex; align-items: center; gap: 11px;
    padding: 9px 12px;
    border-bottom: 1px solid var(--mas-borde);
    background: var(--mas-superficie);
}

.lst-item:last-child { border-bottom: none; }
.lst-item:hover { background: var(--mas-primario-50); }

/* La fila que se está arrastrando se atenúa en vez de desaparecer: hay que seguir
   viendo cuál es mientras las demás se corren. */
.lst-item.lst-arrastrando { opacity: .45; }

.lst-asa {
    cursor: grab; color: var(--mas-texto-tenue);
    font-size: 15px; line-height: 1; user-select: none; flex: none; width: 14px;
}
.lst-asa:active { cursor: grabbing; }

.lst-pos {
    width: 22px; text-align: right; flex: none;
    font-variant-numeric: tabular-nums; color: var(--mas-texto-tenue); font-size: 12.5px;
}

.lst-mini {
    width: 54px; height: 34px; flex: none;
    border-radius: 4px; object-fit: cover;
    border: 1px solid var(--mas-borde);
}

/* Sin miniatura, la inicial del tipo: distingue una imagen de un video de un vistazo
   aunque el procesamiento todavía no haya generado el cuadro. */
.lst-mini-vacia {
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--mas-primario-50); color: var(--mas-primario-700);
    font-weight: 600; font-size: 12px;
}

.lst-nombre { flex: 1; min-width: 0; }
.lst-nombre strong {
    display: block; font-weight: 600; font-size: 13.5px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lst-nombre span { font-size: 12px; color: var(--mas-texto-tenue); }

/* El tipo de archivo, como icono. Reemplazó a una insignia de texto que decía lo mismo
   en sesenta píxeles — justo lo que le faltaba a la columna del nombre. */
.lst-tipo { flex: none; width: 20px; height: 20px; color: var(--mas-texto-tenue); }
.lst-tipo svg {
    width: 20px; height: 20px;
    fill: none; stroke: currentColor;
    stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}

/* --- Cuándo aparece ---

   ANCHO FIJO, Y ES LO QUE ARREGLA LA FILA. En un contenedor flex, el único hijo con
   `flex: 1` —el nombre— es el que cede cuando otro crece. Sin ancho declarado, una
   ventana larga como «Fines de semana · 13:40–15:42» empujaba hasta dejar el nombre del
   archivo reducido a un paréntesis, y la fila medía el triple de alto que las demás.

   DOS RENGLONES, CADA UNO CORTADO CON PUNTOS SUSPENSIVOS. Así todas las filas miden lo
   mismo aunque una tenga programación y las otras no — y lo que se corta no se pierde:
   la frase entera va en el `title`, y completa en el diálogo. */
.lst-ventana {
    width: 140px; flex: none; min-width: 0;
    font-size: 12px; line-height: 1.35;
}
.lst-ventana strong,
.lst-ventana > span {
    display: block;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lst-ventana strong { font-weight: 600; }
.lst-ventana > span { color: var(--mas-texto-tenue); font-variant-numeric: tabular-nums; }

/* Vencido NO es rojo: el contenido sigue en la lista a propósito —para el año que
   viene— y no hay nada que arreglar. Un rojo acá manda a alguien a corregir algo que
   está bien. */
.lst-ventana-vencido {
    display: inline-block !important; margin-top: 2px;
    padding: 0 7px; border-radius: 999px; font-size: 11px;
    background: var(--mas-superficie-2); color: var(--mas-texto-suave);
    border: 1px solid var(--mas-borde-fuerte);
}

.lst-dur { width: 92px; flex: none; text-align: right; font-size: 13px; font-variant-numeric: tabular-nums; }
.lst-dur-campo { width: 100%; text-align: right; padding: 4px 8px; font-size: 13px; }
.lst-dur small { display: block; font-size: 11px; color: var(--mas-texto-tenue); }

.lst-mover { display: flex; gap: 2px; flex: none; }
.lst-mover .mas-btn { padding: 3px 8px; line-height: 1.1; }

.lst-vacio { padding: 26px; text-align: center; color: var(--mas-texto-tenue); font-size: 13px; }

/* =====================================================================================
   LA FILA EN PANTALLA ANGOSTA.

   Una fila tiene ocho cosas —asa, número, miniatura, nombre, tipo, ventana, duración,
   mover, quitar, programar— y por debajo de unos 1000 px dejan de caber. Flexbox no
   avisa: empieza a encoger al único que puede encogerse, que es el nombre, y lo deja en
   una letra y media mientras los botones siguen enteros. Lo que se ve es una fila rota,
   y lo que la rompió fue el elemento que MÁS texto tenía, no el que sobraba.

   SE PARTE EN DOS RENGLONES, y la línea de corte no es arbitraria: arriba queda lo que
   identifica el ítem —qué es y cómo se llama—, abajo lo que se hace con él. Alineado a
   la miniatura, para que el segundo renglón se lea como parte de la misma fila y no como
   una fila nueva.
   ===================================================================================== */

@media (max-width: 1000px) {
    .lst-item { flex-wrap: wrap; row-gap: 8px; }

    /* El nombre se lleva todo lo que sobre del primer renglón. */
    .lst-nombre { flex: 1 1 100%; order: 2; }
    .lst-asa    { order: 0; }
    .lst-pos    { order: 0; }
    .lst-mini   { order: 1; }
    .lst-tipo   { order: 3; }

    /* Lo accionable baja, sangrado a la altura de la miniatura. */
    .lst-ventana { order: 4; flex: 1 1 auto; width: auto; margin-left: 90px; }
    .lst-dur     { order: 5; }
    .lst-mover   { order: 6; }
    .lst-item > .mas-btn { order: 7; }
}

/* Más angosto todavía: el nombre ya no comparte renglón con nada. */
@media (max-width: 620px) {
    .lst-ventana { margin-left: 0; flex: 1 1 100%; }
    .lst-ventana strong, .lst-ventana > span { display: inline; white-space: normal; }
    .lst-ventana > span::before { content: " · "; }
}

/* --- La biblioteca de la derecha ---
   La grilla del framework pinta una celda por fila; el contenido de esa celda es este
   bloque, así que el relleno de la celda se anula para que la fila se vea como una
   lista y no como una tabla de una columna. */
.lst-bib-item { display: flex; align-items: center; gap: 10px; width: 100%; }
#grBiblioteca .mas-tabla thead { display: none; }
#grBiblioteca .mas-tabla td { padding: 8px 12px; }

/* --- Plantillas de pantalla ----------------------------------------------

   El editor de zonas y la vista de programación comparten el lienzo: son el mismo
   dibujo, uno editable y otro no, y separarlos en dos juegos de estilos habría dejado
   dos pantallas que se parecen pero no se ven igual. */

/* =============================================================================
   LOS COLORES DE LAS SERIES — las listas en las tiras de tiempo.

   VIVEN ACA Y NO EN CADA VISTA porque los usan DOS pantallas: la línea de tiempo
   del canal y la tira del día del simulador. Dos copias de una paleta se separan
   en el primer ajuste, y entonces la misma lista sale de dos colores distintos
   según desde dónde la mires.

   ESTAN MEDIDOS, NO ELEGIDOS A OJO. Pasan separación bajo deuteranopía y
   tritanopía y contraste contra el blanco, comparando TODOS los pares y no sólo
   los vecinos — en una tira dos listas cualesquiera pueden quedar una sobre otra
   en días distintos. Un quinto tono verde se descartó: quedaba a ΔE 14 del cian
   con visión normal, por debajo del piso de 15.

   DE LA QUINTA LISTA EN ADELANTE va `--mas-serie-otras` con el nombre escrito.
   Inventar un quinto tono sería dar identidad a algo que el ojo ya no separa.

   NINGUNO ES VERDE, AMBAR NI ROJO: en este panel esos colores ya significan
   «bien», «ojo» y «mal». Un bloque verde se leería como un estado, no como una
   lista.
   ============================================================================= */
:root {
    --mas-serie-1: #6B4FD8;
    --mas-serie-2: #BB2D80;
    --mas-serie-3: #9A5B13;
    --mas-serie-4: #0E86AC;
    --mas-serie-otras: #46556B;
}

.lay-columnas {
    display: grid;
    grid-template-columns: 1fr 400px;
    gap: var(--mas-espacio);
    align-items: start;
}

@media (max-width: 1200px) {
    .lay-columnas { grid-template-columns: 1fr; }
}

/* El lienzo mantiene la PROPORCIÓN de la plantilla, no su resolución: las zonas van en
   porcentaje, así que lo que se dibuja aquí se ve igual en un 4K y en un panel viejo.
   El ancho máximo evita que una plantilla vertical ocupe tres pantallas de alto. */
.lay-lienzo-caja { display: flex; justify-content: center; }

.lay-lienzo {
    position: relative;
    width: 100%;
    max-width: 100%;
    max-height: 62vh;
    border: 1px solid var(--mas-borde-fuerte);
    border-radius: var(--mas-radio-sm);
    overflow: hidden;
    touch-action: none;   /* sin esto, arrastrar una zona hace scroll en una tablet */
}

.lay-zona {
    position: absolute;
    box-sizing: border-box;
    border: 1.5px solid var(--mas-primario);
    background: rgba(29, 78, 216, .28);
    border-radius: 3px;
    padding: 5px 7px;
    color: #ffffff;
    cursor: grab;
    overflow: hidden;
    user-select: none;
}

.lay-zona:active { cursor: grabbing; }
.lay-zona:focus-visible { outline: 2px solid #ffffff; outline-offset: -4px; }

.lay-zona-activa {
    border-color: #ffffff;
    background: rgba(29, 78, 216, .5);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, .35);
}

/* Zona sin lista asignada: se raya para que se lea como un hueco y no como contenido.
   En la pantalla real ese trozo se vería del color de fondo. */
.lay-zona-vacia {
    background: repeating-linear-gradient(45deg,
        rgba(255, 255, 255, .13) 0 8px, rgba(255, 255, 255, .03) 8px 16px);
    border-style: dashed;
    border-color: rgba(255, 255, 255, .6);
}

.lay-zona-nombre {
    display: block;
    font-size: 12.5px; font-weight: 600; line-height: 1.25;
    text-shadow: 0 1px 2px rgba(0, 0, 0, .55);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.lay-zona-medida {
    display: block;
    font-size: 11px; opacity: .9;
    text-shadow: 0 1px 2px rgba(0, 0, 0, .55);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* El asa de redimensionar. Cuadrada y en la esquina inferior derecha, que es donde
   todo el mundo la busca. */
.lay-asa {
    position: absolute; right: 0; bottom: 0;
    width: 14px; height: 14px;
    background: #ffffff;
    border: 1px solid var(--mas-primario);
    border-radius: 2px 0 3px 0;
    cursor: nwse-resize;
}

/* --- Panel de la derecha --- */

.lay-fila { padding: 11px 14px; border-bottom: 1px solid var(--mas-borde); }
.lay-fila:last-child { border-bottom: none; }
.lay-fila-activa { background: var(--mas-primario-50); }

.lay-fila-cabecera { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.lay-fila-cabecera .lay-nombre { flex: 1; padding: 5px 9px; font-size: 13px; }

.lay-medidas { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }

.lay-medida { display: flex; flex-direction: column; gap: 2px; }
.lay-medida span { font-size: 11px; color: var(--mas-texto-tenue); }
.lay-medida input { padding: 4px 6px; font-size: 12.5px; text-align: right; }

.lay-programa { display: flex; gap: 8px; align-items: center; }
.lay-programa .lay-lista { flex: 1; }

.lay-vacio { padding: 22px; text-align: center; color: var(--mas-texto-tenue); font-size: 13px; }

/* Miniatura de la grilla: solo la proporción, sin las zonas. A 34 px de alto los
   rectángulos internos serían manchas. */
.lay-mini {
    display: inline-block;
    border: 1px solid var(--mas-borde-fuerte);
    border-radius: 2px;
    background: linear-gradient(135deg, var(--mas-primario-100), var(--mas-superficie-2));
}

/* =====================================================================================
   Publicación con aprobación
   -------------------------------------------------------------------------------------
   Reutiliza el lienzo y las zonas del editor de plantillas (.lay-*): la ficha de
   aprobación pinta exactamente el mismo dibujo, y dos juegos de estilos para el mismo
   rectángulo se separan al primer ajuste.
   ===================================================================================== */

/* Los ítems congelados de una lista. Numerados porque el orden ES el contenido: quien
   aprueba tiene que poder decir «el tercero está mal». */
/* Los cambios programados de una zona, en la ficha de aprobación. Van SANGRADOS y con
   una línea a la izquierda: son algo que se monta ENCIMA de la lista de arriba, no otra
   lista al mismo nivel. Al mismo nivel se leerían como que todas suenan a la vez. */
.pub-cambios { margin: 12px 0 0 0; padding-left: 13px;
               border-left: 3px solid var(--mas-primario-300); }
.pub-cambios-rotulo { font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase;
                      color: var(--mas-texto-tenue); margin-bottom: 7px; }
.pub-cambio + .pub-cambio { margin-top: 13px; padding-top: 13px;
                            border-top: 1px dashed var(--mas-borde); }

/* El pie del historial: cuántas versiones hay y cómo moverse. Va en una sola línea con
   el conteo a la izquierda, porque el dato que falta cuando se corta una lista no es
   «¿hay más?» sino «¿cuántas más?». */
.pub-paginas { display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
               justify-content: space-between; padding: 11px 14px;
               border-top: 1px solid var(--mas-borde); }

.pub-items {
    margin: 6px 0 0; padding-left: 26px;
    display: flex; flex-direction: column; gap: 2px;
    font-size: 13px;
}

.pub-items li {
    display: flex; align-items: center; gap: 8px;
    padding: 3px 0;
}

.pub-item-nombre {
    flex: 1 1 auto; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* La fila del historial que corresponde a la publicación abierta. Sin esto hay que
   comparar números para saber dónde está uno parado. */
.pub-fila-actual { background: var(--mas-fondo-suave, rgba(0, 0, 0, .035)); }
.pub-fila-actual td { font-weight: 600; }

.pub-rechazo { margin-bottom: 14px; }

/* Los impedimentos para publicar, como lista: son frases largas —«tal archivo todavía se
   está procesando»— y una detrás de otra no se distinguen. */
.pub-problemas { margin: 4px 0 0; padding-left: 20px; }
.pub-problemas li { margin: 2px 0; }

/* =====================================================================================
   «En pantalla»: la única tarjeta del resumen de una lista que lleva color
   -------------------------------------------------------------------------------------
   Las otras dos —duración e ítems— son aritmética: siempre son ciertas y nunca son una
   noticia. Esta puede decirte que lo que estás editando NO es lo que se está viendo en la
   calle, y ese es el único dato de la pantalla que merece que uno levante la vista.

   El color va en un filete a la izquierda y en un fondo apenas teñido, no en el texto:
   así se distingue de un vistazo sin competir con el número, que es lo que se lee.
   ===================================================================================== */

.lst-tarjeta-aviso {
    border-left: 3px solid var(--mas-advertencia);
    background: var(--mas-advertencia-suave);
}

.lst-tarjeta-aviso .lst-tarjeta-rotulo,
.lst-tarjeta-aviso .lst-tarjeta-pie { color: var(--mas-advertencia); }

.lst-tarjeta-bien { border-left: 3px solid var(--mas-exito); }
.lst-tarjeta-bien .lst-tarjeta-pie { color: var(--mas-exito); }

/* Sin canal no es bueno ni malo: es una lista que todavía nadie programó, que es el
   estado normal de una lista recién armada. Pintarla de rojo sería inventar un problema. */
.lst-tarjeta-inerte .lst-tarjeta-nada { color: var(--mas-texto-tenue); font-weight: 400; }

.lst-canales {
    display: flex; flex-wrap: wrap; gap: 4px;
    margin-top: 8px; padding-top: 8px;
    border-top: 1px solid var(--mas-borde);
}

/* Cada canal es un enlace a su programación: desde aquí uno ve que algo está
   desactualizado, y el paso siguiente es siempre ir a publicarlo. */
.lst-canal {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: 12px; text-decoration: none; color: inherit;
    padding: 2px 6px; border-radius: var(--mas-radio-sm, 4px);
}

.lst-canal:hover { background: rgba(0, 0, 0, .05); }
.lst-canal-nombre { font-weight: 600; }

/* El «+N canales más». Se ve como los demás pero sin insignia: no es un estado, es una
   salida hacia la grilla de canales, que es donde sí caben treinta filas. */
.lst-canal-mas { color: var(--mas-texto-suave); font-size: 11.5px; }


/* =====================================================================================
   EL DIÁLOGO DE «CUÁNDO SE VE ESTO»

   LO USAN DOS PANTALLAS: la ventana por ítem dentro de una lista (doc 29) y los cambios
   programados de un canal (doc 57). Son la misma pregunta —entre qué fechas, qué días, en
   qué franja— a dos niveles distintos, y tienen que verse igual.

   VIVÍA EN UN <style> DENTRO DE `Listas/Contenido.cshtml`, y por eso el segundo diálogo
   nació sin estilo: reusó los nombres de clase y no había nada que los definiera. Los
   botones de día quedaron todos del mismo gris —no se distinguía el marcado del que no—,
   que es justo el control donde eso importa.

   Es el mismo error de siempre con otra ropa: dos sitios que dicen representar lo mismo
   sin que nada compruebe que coinciden. Acá hay uno.
   ===================================================================================== */

    .dlg-prog { border: none; border-radius: 8px; padding: 0; max-width: 580px; width: calc(100% - 32px); }
    .dlg-prog::backdrop { background: rgba(11, 36, 61, .45); }
    .dlg-prog header { padding: 15px 20px; border-bottom: 1px solid var(--mas-borde); }
    .dlg-prog header h2 { margin: 0; font-size: 16px; }
    .dlg-prog header p { margin: 3px 0 0; font-size: 12.5px; }
    .dlg-prog-cuerpo { padding: 18px 20px; }
    .dlg-prog fieldset { border: none; padding: 0; margin: 0 0 18px; }
    .dlg-prog legend { padding: 0 0 6px; font-size: 12.5px; font-weight: 650; }
    /* EL ATRIBUTO `hidden` TIENE QUE GANAR, Y SIN ESTO NO GANA.
       `hidden` aplica `display:none` desde la hoja del NAVEGADOR, y cualquier regla de
       autor con `display` —las dos de aquí abajo— la pisa por especificidad. El resultado
       era que los bloques de fechas y de días del diálogo no se ocultaban nunca: las
       casillas «Solo entre dos fechas» y «Solo algunos días» no hacían nada visible, y se
       llegaba a ver un día marcado en azul con su casilla apagada. */
    .dlg-prog [hidden] { display: none !important; }

    .dlg-prog-par { display: grid; grid-template-columns: 1fr 1fr; gap: 13px; }
    .dlg-prog label { display: block; }
    .dlg-prog label > span { display: block; font-size: 12px; font-weight: 600; margin-bottom: 4px; }
    .dlg-prog label > small { display: block; margin-top: 4px; font-size: 11.5px; }
    .dlg-prog-dias { display: flex; gap: 5px; flex-wrap: wrap; }
    .dlg-prog-dias button { width: 40px; height: 38px; border-radius: 5px; cursor: pointer;
        border: 1px solid var(--mas-borde-fuerte); background: var(--mas-superficie);
        color: var(--mas-texto-suave); font: inherit; font-weight: 600; }
    .dlg-prog-dias button[aria-pressed="true"] { background: var(--mas-primario);
        border-color: var(--mas-primario); color: #fff; }
    .dlg-prog-frase { margin: 0; padding: 11px 13px; border-radius: 5px; font-size: 13px;
        background: var(--mas-primario-50); border: 1px solid var(--mas-primario-100); }
    .dlg-prog footer { padding: 13px 20px; border-top: 1px solid var(--mas-borde);
        background: var(--mas-superficie-2); display: flex; gap: 9px; align-items: center; flex-wrap: wrap; }
    .dlg-prog-relleno { flex: 1 1 auto; }
    @media (max-width: 560px) { .dlg-prog-par { grid-template-columns: 1fr; } }

/* ======================================================================== campana

   El número rojo del encabezado y su desplegable. Cuenta PROBLEMAS, no eventos: si
   todo está bien no se pinta nada, y esa es la razón por la que alguien le va a seguir
   haciendo caso en el mes tres.

   El desplegable es angosto a propósito —330 px, cinco líneas—: no es una pantalla,
   es un aviso con una puerta a la pantalla. */
.app-campana { position: relative; display: inline-flex; }

.app-campana-boton {
    background: none; border: 0; padding: 6px; cursor: pointer;
    color: inherit; display: inline-flex; position: relative; border-radius: 6px;
}
.app-campana-boton:hover { background: rgba(255, 255, 255, .12); }

.app-campana-globo {
    position: absolute; top: 0; right: 0;
    background: var(--mas-peligro, #b42318); color: #fff;
    font-size: 10px; font-weight: 700; line-height: 15px;
    border-radius: 9px; padding: 0 5px; min-width: 16px; text-align: center;
}

.app-campana-panel {
    position: absolute; top: calc(100% + 8px); right: 0; width: 330px; z-index: 60;
    background: var(--mas-superficie, #fff); color: var(--mas-texto, #1f2430);
    border: 1px solid var(--mas-borde, #e3e7ee); border-radius: 10px;
    box-shadow: 0 12px 32px rgba(20, 26, 38, .18); overflow: hidden;
}

.app-campana-titulo {
    padding: 10px 13px; border-bottom: 1px solid var(--mas-borde, #e3e7ee);
    font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
    color: var(--mas-texto-suave, #5a6372);
}

.app-campana-lista { max-height: 320px; overflow-y: auto; min-width: 0; }

.app-campana-linea {
    display: flex; flex-direction: column; gap: 2px;
    padding: 10px 13px; border-bottom: 1px solid var(--mas-borde, #e3e7ee);
    text-decoration: none; color: inherit;
}
.app-campana-linea:hover { background: var(--mas-fondo, #fafbfd); }
.app-campana-linea-titulo { font-size: 13px; font-weight: 600; }

/* Se permite que envuelva: un detalle cortado con puntos suspensivos obliga a abrir la
   página para saber de qué pantalla hablamos, que es justo lo que el desplegable
   intenta evitar. Dos líneas de texto caben; una elipsis no dice nada. */
.app-campana-linea-detalle {
    font-size: 12px; color: var(--mas-texto-suave, #5a6372);
    line-height: 1.35; overflow-wrap: anywhere;
}

.app-campana-vacio {
    padding: 16px 13px; font-size: 13px; text-align: center;
    color: var(--mas-texto-tenue, #8a92a1);
}

.app-campana-pie { padding: 10px 13px; text-align: center; }
.app-campana-pie a {
    color: var(--mas-primario, #1f6feb); text-decoration: none;
    font-size: 13px; font-weight: 600;
}

/* ===================================================================== sesiones

   El panel de «conectados ahora», colgado de la píldora de en línea. Solo lo ve el
   administrador global: para el resto esa píldora sigue siendo un número que no se
   pulsa, y por eso el cursor de mano se pone desde el script y no desde aquí. */

.app-sesiones { position: relative; display: inline-flex; }

.app-sesiones-panel {
    position: absolute; top: calc(100% + 8px); right: 0; width: 320px; z-index: 60;
    background: var(--mas-superficie, #fff); color: var(--mas-texto, #1f2430);
    border: 1px solid var(--mas-borde, #e3e7ee); border-radius: 10px;
    box-shadow: 0 12px 32px rgba(20, 26, 38, .18); overflow: hidden;
    text-align: left;
}

.app-sesiones-titulo {
    padding: 10px 13px; border-bottom: 1px solid var(--mas-borde, #e3e7ee);
    font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
    color: var(--mas-texto-suave, #5a6372);
}

.app-sesiones-lista { max-height: 300px; overflow-y: auto; min-width: 0; }

.app-sesiones-fila {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 13px; border-bottom: 1px solid var(--mas-borde, #e3e7ee);
}

.app-sesiones-quien { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.app-sesiones-quien strong { font-size: 13px; font-weight: 600; }

/* El correo se parte si hace falta en vez de cortarse con puntos: un correo a medias
   no identifica a nadie, que es lo único para lo que está puesto. */
.app-sesiones-quien small {
    font-size: 11.5px; color: var(--mas-texto-tenue, #8a92a1);
    line-height: 1.3; overflow-wrap: anywhere;
}

.app-sesiones-cerrar {
    flex: 0 0 auto; background: none; cursor: pointer;
    border: 1px solid var(--mas-peligro, #b42318); color: var(--mas-peligro, #b42318);
    border-radius: 6px; padding: 2px 7px; font-size: 13px; line-height: 1.4;
}
.app-sesiones-cerrar:hover { background: var(--mas-peligro-suave, #fdeceb); }
.app-sesiones-cerrar:disabled { opacity: .5; cursor: default; }

.app-sesiones-vacio {
    padding: 16px 13px; font-size: 13px; text-align: center;
    color: var(--mas-texto-tenue, #8a92a1);
}

.app-sesiones-pie { padding: 10px 13px; display: flex; flex-direction: column; gap: 6px; }

.app-sesiones-todos {
    width: 100%; cursor: pointer; background: none;
    border: 1px solid var(--mas-peligro, #b42318); color: var(--mas-peligro, #b42318);
    border-radius: 8px; padding: 7px 10px; font-size: 13px; font-weight: 600;
}
.app-sesiones-todos:hover { background: var(--mas-peligro-suave, #fdeceb); }
.app-sesiones-todos:disabled { opacity: .5; cursor: default; }

/* La nota NO es letra chica decorativa: dice a quién no alcanza el botón y en cuánto
   tiempo surte efecto. Las dos cosas se preguntan justo después de pulsarlo. */
.app-sesiones-nota {
    font-size: 11.5px; line-height: 1.35;
    color: var(--mas-texto-tenue, #8a92a1);
}
