/* =============================================================================
   WebFramework — hoja de estilos
   Tema azul y blanco. Todo pasa por variables CSS: para re-marcar el framework
   en otro proyecto basta redefinir :root, sin tocar una sola regla.
   ============================================================================= */

:root {
    --mas-fuente: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --mas-fuente-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    --mas-radio: 8px;
    --mas-radio-sm: 5px;
    --mas-espacio: 16px;

    /* --- Azules de la marca --- */
    --mas-primario-900: #0b2e6f;
    --mas-primario-800: #10399322;   /* solo para sombras teñidas */
    --mas-primario-700: #14418f;
    --mas-primario:     #1257c7;
    --mas-primario-600: #0f4bb0;
    --mas-primario-hover: #0f4bb0;
    --mas-primario-300: #8fb6f0;
    --mas-primario-100: #dbe8fb;
    --mas-primario-50:  #eef4fd;
    --mas-primario-suave: var(--mas-primario-100);

    /* --- Superficies: blanco dominante, azul apenas insinuado --- */
    --mas-fondo:        #f2f6fc;
    --mas-superficie:   #ffffff;
    --mas-superficie-2: #f6f9fe;
    --mas-borde:        #dce6f4;
    --mas-borde-fuerte: #b9cbe6;

    --mas-texto:        #14243d;
    --mas-texto-suave:  #4c6183;
    --mas-texto-tenue:  #7e91ad;
    --mas-texto-inverso:#ffffff;

    --mas-exito: #0f7a43;
    --mas-exito-suave: #e4f6ec;
    --mas-advertencia: #a35a06;
    --mas-advertencia-suave: #fdf1e0;
    --mas-peligro: #b3261e;
    --mas-peligro-suave: #fdeae9;
    --mas-info: #0b6b8a;
    --mas-info-suave: #e3f3f9;

    --mas-sombra:    0 1px 2px rgba(11, 46, 111, .06), 0 1px 3px rgba(11, 46, 111, .09);
    --mas-sombra-md: 0 6px 18px rgba(11, 46, 111, .12);
    --mas-foco:      0 0 0 3px rgba(18, 87, 199, .28);
}

/*
   Modo oscuro por elección explícita (<html data-tema="oscuro">), no por
   prefers-color-scheme: la identidad de la aplicación es azul y blanco, y no
   corresponde que cambie sola porque el sistema operativo del usuario esté en oscuro.
*/
[data-tema="oscuro"] {
    --mas-fondo: #0d1626;
    --mas-superficie: #152238;
    --mas-superficie-2: #1c2c47;
    --mas-borde: #27395a;
    --mas-borde-fuerte: #3a5077;
    --mas-texto: #e8eefa;
    --mas-texto-suave: #a8bad6;
    --mas-texto-tenue: #7e91ad;
    --mas-primario: #4d8ef7;
    --mas-primario-hover: #6ea3f9;
    --mas-primario-100: #16305c;
    --mas-primario-50: #122745;
    --mas-primario-suave: #16305c;
    --mas-exito-suave: #10301f;
    --mas-advertencia-suave: #35270f;
    --mas-peligro-suave: #3a1917;
    --mas-info-suave: #0e2f3b;
}

*, *::before, *::after { box-sizing: border-box; }

body {
    margin: 0;
    font-family: var(--mas-fuente);
    font-size: 14px;
    line-height: 1.5;
    color: var(--mas-texto);
    background: var(--mas-fondo);
    -webkit-font-smoothing: antialiased;
}

/* ---------- Botones ----------
   Cada tono define su propio :hover con la MISMA especificidad. Antes el hover
   genérico llevaba dos :not() y le ganaba al del tono, dejando fondo claro con
   texto blanco: el botón se volvía ilegible al pasar el mouse. */
/* [hidden] contra display: el navegador aplica `[hidden]{display:none}` con
   especificidad de elemento, y cualquier clase que declare display —como la de
   abajo— le gana. Sin esta regla, un botón con hidden se sigue viendo. Es el
   mismo error que tenía la capa de carga de la grilla. */
.mas-btn[hidden] { display: none; }

.mas-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 8px 16px;
    font: inherit;
    font-weight: 500;
    line-height: 1.2;
    color: var(--mas-texto);
    background: var(--mas-superficie);
    border: 1px solid var(--mas-borde-fuerte);
    border-radius: var(--mas-radio-sm);
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background .12s, border-color .12s, color .12s, box-shadow .12s;
}
.mas-btn:focus-visible { outline: none; box-shadow: var(--mas-foco); }
.mas-btn[disabled], .mas-btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
.mas-btn:active:not([disabled]):not([aria-disabled="true"]) { transform: translateY(1px); }
.mas-btn-sm { padding: 4px 10px; font-size: 13px; }

.mas-btn-neutro { color: var(--mas-primario); border-color: var(--mas-borde-fuerte); }
.mas-btn-neutro:hover:not([disabled]):not([aria-disabled="true"]) {
    background: var(--mas-primario-50); border-color: var(--mas-primario-300);
}

.mas-btn-primario { color: var(--mas-texto-inverso); background: var(--mas-primario); border-color: var(--mas-primario); }
.mas-btn-primario:hover:not([disabled]):not([aria-disabled="true"]) {
    color: var(--mas-texto-inverso); background: var(--mas-primario-hover); border-color: var(--mas-primario-hover);
}

.mas-btn-peligro { color: var(--mas-texto-inverso); background: var(--mas-peligro); border-color: var(--mas-peligro); }
.mas-btn-peligro:hover:not([disabled]):not([aria-disabled="true"]) {
    color: var(--mas-texto-inverso); background: #8f1d17; border-color: #8f1d17;
}

.mas-btn-exito { color: var(--mas-texto-inverso); background: var(--mas-exito); border-color: var(--mas-exito); }
.mas-btn-exito:hover:not([disabled]):not([aria-disabled="true"]) {
    color: var(--mas-texto-inverso); background: #0b6134; border-color: #0b6134;
}

.mas-btn-advertencia { color: var(--mas-texto-inverso); background: var(--mas-advertencia); border-color: var(--mas-advertencia); }
.mas-btn-advertencia:hover:not([disabled]):not([aria-disabled="true"]) {
    color: var(--mas-texto-inverso); background: #874a05; border-color: #874a05;
}

.mas-btn-info { color: var(--mas-texto-inverso); background: var(--mas-info); border-color: var(--mas-info); }
.mas-btn-info:hover:not([disabled]):not([aria-disabled="true"]) {
    color: var(--mas-texto-inverso); background: #095870; border-color: #095870;
}

/* ---------- Campos ---------- */
.mas-campo { display: flex; flex-direction: column; gap: 5px; margin-bottom: var(--mas-espacio); }
.mas-campo-oculto { display: none; }
.mas-campo-etiqueta { font-weight: 600; font-size: 12.5px; color: var(--mas-texto-suave); }
.mas-requerido { color: var(--mas-peligro); margin-left: 3px; }

.mas-control {
    width: 100%;
    padding: 9px 11px;
    font: inherit;
    color: var(--mas-texto);
    background: var(--mas-superficie);
    border: 1px solid var(--mas-borde-fuerte);
    border-radius: var(--mas-radio-sm);
    transition: border-color .12s, box-shadow .12s;
}
.mas-control:focus { outline: none; border-color: var(--mas-primario); box-shadow: var(--mas-foco); }
.mas-control:disabled, .mas-control[readonly] { background: var(--mas-superficie-2); color: var(--mas-texto-suave); }
select.mas-control { cursor: pointer; }
textarea.mas-control { resize: vertical; min-height: 70px; }

.mas-campo-ayuda { font-size: 12px; color: var(--mas-texto-tenue); }
.mas-campo-error { font-size: 12px; color: var(--mas-peligro); min-height: 0; }
.mas-campo-error:empty { display: none; }
.mas-campo-invalido .mas-control { border-color: var(--mas-peligro); }
.mas-campo-invalido .mas-control:focus { box-shadow: 0 0 0 3px rgba(179, 38, 30, .22); }

.mas-check { display: inline-flex; align-items: flex-start; gap: 8px; cursor: pointer; padding: 3px 0; }
.mas-check input { margin: 3px 0 0; width: 15px; height: 15px; accent-color: var(--mas-primario); cursor: pointer; }
.mas-check span { display: flex; flex-direction: column; }
.mas-check small { color: var(--mas-texto-tenue); font-size: 12px; }
.mas-check-deshabilitado { opacity: .45; cursor: not-allowed; }
.mas-check-deshabilitado input { cursor: not-allowed; }

/* ---------- Lista de casillas ---------- */
.mas-check-lista { border: 1px solid var(--mas-borde); border-radius: var(--mas-radio); background: var(--mas-superficie); }
.mas-check-grupo { border-bottom: 1px solid var(--mas-borde); }
.mas-check-grupo:last-child { border-bottom: none; }
.mas-check-cabecera {
    width: 100%; padding: 9px 14px; background: var(--mas-primario-50);
    font-weight: 600; font-size: 13px; text-transform: capitalize; color: var(--mas-primario-700);
}
.mas-check-items { padding: 8px 14px 12px; display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 2px 16px; }

/* ---------- Panel ---------- */
.mas-panel {
    background: var(--mas-superficie);
    border: 1px solid var(--mas-borde);
    border-radius: var(--mas-radio);
    box-shadow: var(--mas-sombra);
    margin-bottom: var(--mas-espacio);
    overflow: hidden;
}
.mas-panel-encabezado {
    padding: 13px 18px; border-bottom: 1px solid var(--mas-borde);
    background: var(--mas-primario-50);
}
.mas-panel-titulo { margin: 0; font-size: 15px; font-weight: 600; color: var(--mas-primario-900); }
.mas-panel-subtitulo { margin: 3px 0 0; font-size: 13px; color: var(--mas-texto-suave); }
.mas-panel-cuerpo { padding: 18px; }
.mas-panel-cuerpo.mas-sin-relleno { padding: 0; }

/* ---------- Alertas ---------- */
.mas-alerta {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 12px 15px; margin-bottom: var(--mas-espacio);
    border: 1px solid transparent; border-left-width: 3px;
    border-radius: var(--mas-radio-sm);
}
.mas-alerta-cuerpo { flex: 1; }
.mas-alerta-titulo { display: block; margin-bottom: 2px; }
.mas-alerta-cerrar {
    background: none; border: none; cursor: pointer; font-size: 19px; line-height: 1;
    color: inherit; opacity: .55; padding: 0 2px;
}
.mas-alerta-cerrar:hover { opacity: 1; }
.mas-alerta-exito       { background: var(--mas-exito-suave);       border-left-color: var(--mas-exito);       color: var(--mas-exito); }
.mas-alerta-peligro     { background: var(--mas-peligro-suave);     border-left-color: var(--mas-peligro);     color: var(--mas-peligro); }
.mas-alerta-advertencia { background: var(--mas-advertencia-suave); border-left-color: var(--mas-advertencia); color: var(--mas-advertencia); }
.mas-alerta-info        { background: var(--mas-info-suave);        border-left-color: var(--mas-info);        color: var(--mas-info); }
.mas-alerta-neutro      { background: var(--mas-primario-50);       border-left-color: var(--mas-primario);    color: var(--mas-primario-900); }
.mas-lista-errores { margin: 4px 0 0; padding-left: 18px; }
.mas-lista-errores li { margin-bottom: 2px; }

/* ---------- Grilla ---------- */
.mas-grilla {
    background: var(--mas-superficie);
    border: 1px solid var(--mas-borde);
    border-radius: var(--mas-radio);
    box-shadow: var(--mas-sombra);
    overflow: hidden;
}
.mas-grilla-barra {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    padding: 12px 14px; border-bottom: 1px solid var(--mas-borde);
}
.mas-grilla-busqueda { flex: 1; min-width: 200px; max-width: 340px; }
.mas-grilla-buscar {
    width: 100%; padding: 8px 11px; font: inherit; color: var(--mas-texto);
    background: var(--mas-superficie); border: 1px solid var(--mas-borde-fuerte);
    border-radius: var(--mas-radio-sm);
}
.mas-grilla-buscar:focus { outline: none; border-color: var(--mas-primario); box-shadow: var(--mas-foco); }
.mas-grilla-acciones { display: flex; gap: 8px; margin-left: auto; }

/* --- Rótulo, contador y exportación de la barra ---------------------------
   El contador vive arriba y no solo en el pie: «cuántos hay» es la primera
   pregunta al abrir un listado, y el pie se va de pantalla en cuanto la
   grilla tiene diez filas. */

.mas-grilla-titulo { display: flex; align-items: center; gap: 8px; }

.mas-grilla-rotulo { font-weight: 600; color: var(--mas-texto); }

.mas-grilla-contador {
    padding: 1px 9px;
    border-radius: 999px;
    background: var(--mas-primario-100);
    color: var(--mas-primario-700, var(--mas-primario));
    font-size: 12px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.mas-grilla-contador[hidden] { display: none; }

/* El icono hereda el color del botón, como el resto del juego. */
.mas-icono {
    width: 15px; height: 15px; flex: none;
    fill: none; stroke: currentColor;
    stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}

/* Exportar un listado largo toma unos segundos: el botón se apaga mientras
   tanto para que no se pulse dos veces y salgan dos archivos. */
.mas-grilla-exportar.mas-cargando { opacity: .6; cursor: progress; }

/* ---------------------------------------------------------------- pestañas

   Barra de pestañas para partir un listado largo en secciones sin recargar la
   página: cada pestaña cambia un filtro de la grilla que tiene debajo.

   Sin scroll horizontal ni menú «más»: se envuelven en varias líneas. Con
   pocas secciones nunca pasa, y cuando pasa es preferible una segunda línea a
   esconder pestañas detrás de un gesto que no se ve.

   El subrayado va en la propia pestaña activa y no en un indicador aparte para
   que funcione igual al envolverse. */
.mas-pestanas {
    display: flex; flex-wrap: wrap; gap: 2px;
    margin-bottom: 14px;
    border-bottom: 1px solid var(--mas-borde);
}
.mas-pestana {
    padding: 8px 14px;
    font: inherit; font-size: 13.5px; font-weight: 500;
    color: var(--mas-texto-tenue);
    background: transparent;
    border: none;
    /* El borde inferior existe siempre, transparente: si apareciera solo en la
       activa, la barra saltaría dos píxeles al cambiar de pestaña. */
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    cursor: pointer;
    white-space: nowrap;
    /* Para que la clase también sirva en un <a>: hay pestañas que filtran sin recargar
       —y ahí el elemento correcto es un <button>— y pestañas que son páginas distintas,
       donde el elemento correcto es un enlace, con su URL propia y su botón «atrás». */
    text-decoration: none;
    transition: color .12s, border-color .12s;
}
.mas-pestana:hover { color: var(--mas-primario); }
.mas-pestana:focus-visible { outline: 2px solid var(--mas-primario); outline-offset: -2px; }
.mas-pestana-activa {
    color: var(--mas-primario);
    border-bottom-color: var(--mas-primario);
    font-weight: 600;
}

.mas-grilla-cuerpo { position: relative; overflow-x: auto; }

.mas-tabla { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.mas-tabla th {
    position: sticky; top: 0; z-index: 1;
    padding: 10px 14px; text-align: left; font-weight: 600; font-size: 12px;
    text-transform: uppercase; letter-spacing: .03em; color: var(--mas-primario-700);
    background: var(--mas-primario-50); border-bottom: 1px solid var(--mas-borde);
    white-space: nowrap; user-select: none;
}
.mas-tabla th.mas-ordenable { cursor: pointer; }
.mas-tabla th.mas-ordenable:hover { background: var(--mas-primario-100); }
.mas-orden-icono { display: inline-block; width: 12px; margin-left: 4px; opacity: .45; }
.mas-tabla th[data-dir="asc"]  .mas-orden-icono::after { content: "▲"; font-size: 8px; }
.mas-tabla th[data-dir="desc"] .mas-orden-icono::after { content: "▼"; font-size: 8px; }
.mas-tabla th[data-dir] { color: var(--mas-primario); }
.mas-tabla th[data-dir] .mas-orden-icono { opacity: 1; }

.mas-tabla td {
    padding: 9px 14px; border-bottom: 1px solid var(--mas-borde); vertical-align: middle;
    border-left: 3px solid transparent;
}
.mas-tabla td:not(:first-child) { border-left: none; }
.mas-tabla tbody tr { transition: background .1s; }
.mas-tabla tbody tr:last-child td { border-bottom: none; }

/* Fila bajo el cursor */
.mas-tabla tbody tr:hover { background: var(--mas-primario-50); }

/* Fila marcada al hacer clic: se mantiene aunque el mouse se vaya, para no perder
   de vista en cuál se estaba trabajando al ir y volver de un formulario. */
.mas-tabla tbody tr.mas-fila-activa { background: var(--mas-primario-100); }
.mas-tabla tbody tr.mas-fila-activa td:first-child { border-left-color: var(--mas-primario); }
.mas-tabla tbody tr.mas-fila-activa:hover { background: var(--mas-primario-100); }

/* Selección por casilla */
.mas-tabla tbody tr.mas-sel { background: var(--mas-primario-100); }

/* Encabezado de grupo (mas-grilla agrupar-por="Campo").
   Más compacto que una fila normal y con el mismo azul del <thead>: se lee como una
   subdivisión de la tabla, no como un registro más. No es seleccionable ni ordenable. */
.mas-tabla tbody tr.mas-grilla-grupo td {
    padding: 5px 14px;
    font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
    color: var(--mas-primario-700); background: var(--mas-primario-50);
    border-bottom: 1px solid var(--mas-borde); border-left: 3px solid var(--mas-primario);
}
.mas-tabla tbody tr.mas-grilla-grupo { cursor: default; }
.mas-tabla tbody tr.mas-grilla-grupo:hover { background: transparent; }

.mas-tabla tbody tr:focus-visible { outline: 2px solid var(--mas-primario); outline-offset: -2px; }

.mas-col-sel { width: 38px; text-align: center; }
.mas-al-izquierda { text-align: left; }
.mas-al-centro    { text-align: center; }
.mas-al-derecha   { text-align: right; font-variant-numeric: tabular-nums; }

.mas-grilla-vacio { padding: 44px 20px; text-align: center; color: var(--mas-texto-tenue); }
.mas-grilla-cargando {
    position: absolute; inset: 0; display: grid; place-items: center;
    align-content: center; gap: 10px;
    background: color-mix(in srgb, var(--mas-superficie) 70%, transparent);
}
/* Sin esta regla el `display: grid` de arriba anula el [hidden] del navegador: la capa
   queda invisible pero sigue sobre la grilla interceptando todos los clics, y no se
   puede marcar una fila ni una casilla. */
.mas-grilla-cargando[hidden] { display: none; }

.mas-grilla-cargando-texto { font-size: 13px; color: var(--mas-texto-suave); }

/* EL ALTO MÍNIMO EXISTE POR LA PRIMERA CARGA, que es justo la que más tarda.
   La capa es «inset: 0» sobre el cuerpo de la tabla; con el <tbody> todavía vacío ese
   cuerpo mide lo que mide su cabecera —39 px medidos— y el aviso queda aplastado entre la
   cabecera y el pie, invisible. Es el caso en que alguien concluye que la pantalla se
   cayó, que es exactamente lo contrario de lo que la capa existe para decir.
   La clase la pone el JavaScript al mostrar la capa y la quita al ocultarla. */
.mas-grilla-cuerpo.mas-cargando { min-height: 190px; }
.mas-spinner {
    width: 24px; height: 24px; border: 2.5px solid var(--mas-borde-fuerte);
    border-top-color: var(--mas-primario); border-radius: 50%;
    animation: mas-girar .7s linear infinite;
}
@keyframes mas-girar { to { transform: rotate(360deg); } }

/* ---------- Aviso de navegación ----------
   Una franja delgada arriba del todo mientras el servidor prepara la página siguiente.
   Va FIJA y con z-index alto porque tiene que verse sobre la pantalla vieja, que es la que
   sigue ahí hasta que llegue el HTML nuevo; y con pointer-events desactivados para no
   robarle el clic a nada, porque durante la espera la página anterior sigue siendo usable.

   El movimiento es indeterminado a propósito: nadie sabe cuánto falta —el servidor aún no
   ha contestado—, y una barra que avanza hasta el 90 % y se planta es una cifra inventada
   que deja de creerse a la segunda vez. */
.mas-navegando {
    position: fixed; top: 0; left: 0; right: 0; height: 3px;
    z-index: 2000; pointer-events: none;
    background: color-mix(in srgb, var(--mas-primario) 18%, transparent);
    overflow: hidden;
}
.mas-navegando::before {
    content: ""; position: absolute; top: 0; bottom: 0; width: 38%;
    background: var(--mas-primario);
    animation: mas-navegando-vaiven 1.1s ease-in-out infinite;
}
@keyframes mas-navegando-vaiven {
    from { left: -38%; }
    to   { left: 100%; }
}

/* Quien pidió menos movimiento no debe recibir una barra corriendo de lado a lado. Se
   queda quieta y llena: sigue diciendo «estoy trabajando», sin animación. */
@media (prefers-reduced-motion: reduce) {
    .mas-navegando::before { animation: none; left: 0; width: 100%; opacity: .55; }
    .mas-spinner { animation-duration: 2.4s; }
}

.mas-grilla-pie {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 10px 14px; border-top: 1px solid var(--mas-borde);
    font-size: 13px; color: var(--mas-texto-suave); flex-wrap: wrap;
}
.mas-grilla-pie-izquierda { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.mas-grilla-tamano-caja { display: inline-flex; align-items: center; gap: 6px; }
.mas-grilla-tamano {
    padding: 3px 6px; font: inherit; font-size: 13px; cursor: pointer;
    color: var(--mas-texto); background: var(--mas-superficie);
    border: 1px solid var(--mas-borde-fuerte); border-radius: var(--mas-radio-sm);
}
.mas-grilla-tamano:focus { outline: none; border-color: var(--mas-primario); box-shadow: var(--mas-foco); }
.mas-grilla-paginador { display: flex; gap: 4px; }
.mas-pag {
    min-width: 31px; padding: 5px 9px; font: inherit; font-size: 13px;
    color: var(--mas-primario); background: var(--mas-superficie);
    border: 1px solid var(--mas-borde-fuerte); border-radius: var(--mas-radio-sm); cursor: pointer;
}
.mas-pag:hover:not([disabled]) { background: var(--mas-primario-50); border-color: var(--mas-primario-300); }
.mas-pag[disabled] { opacity: .4; cursor: default; color: var(--mas-texto-tenue); }
.mas-pag.mas-pag-activa {
    color: var(--mas-texto-inverso); background: var(--mas-primario); border-color: var(--mas-primario);
}

/* ---------- Insignias ---------- */
.mas-badge {
    display: inline-block; padding: 2px 9px; font-size: 12px; font-weight: 500;
    border-radius: 999px; background: var(--mas-primario-50);
    border: 1px solid var(--mas-primario-100); color: var(--mas-primario-700); white-space: nowrap;
}
.mas-badge-exito       { background: var(--mas-exito-suave);       color: var(--mas-exito);       border-color: transparent; }
.mas-badge-peligro     { background: var(--mas-peligro-suave);     color: var(--mas-peligro);     border-color: transparent; }
.mas-badge-advertencia { background: var(--mas-advertencia-suave); color: var(--mas-advertencia); border-color: transparent; }
.mas-badge-info        { background: var(--mas-info-suave);        color: var(--mas-info);        border-color: transparent; }
.mas-badge-neutro      { background: var(--mas-superficie-2);      color: var(--mas-texto-suave); border-color: var(--mas-borde-fuerte); }

/* Una columna de estado se lee EN VERTICAL, no insignia por insignia. Si cada una mide
   lo que mide su palabra, el borde izquierdo y el derecho van dando saltos y el ojo
   tiene que releer cada fila para comparar. Con un ancho mínimo común quedan alineadas
   y la columna se lee de un vistazo.
   El «:only-child» es lo que acota la regla a la celda que ES el estado: donde la
   insignia acompaña a otra cosa dentro de la celda, manda el contenido. */
table td > .mas-badge:only-child {
    min-width: 100px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
/* La excepción: una marca de sí/no no es un estado, y estirarla a 96px deja una píldora
   casi vacía con dos letras perdidas en el medio. */
table td > .mas-badge.mas-badge-corta:only-child { min-width: 0; }

/* ---------- Reloj de cabecera ---------- */
.mas-reloj { display: flex; flex-direction: column; align-items: center; line-height: 1.15; }
.mas-reloj-hora {
    font-size: 22px; font-weight: 600; letter-spacing: .01em;
    font-variant-numeric: tabular-nums; color: var(--mas-primario-900);
}
.mas-reloj-fecha { font-size: 11.5px; color: var(--mas-texto-tenue); text-transform: lowercase; }
.mas-reloj-sm .mas-reloj-hora { font-size: 17px; }

/* ---------- Columna «Actividad» de los players ---------- */

/* La celda se lee EN VERTICAL: la palabra arriba y el detalle debajo. Puestos en la misma
   línea, el detalle —que cambia de largo entre filas— empuja la insignia de un lado a
   otro y la columna deja de poder compararse de un vistazo. */
.mas-actividad { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; }
.mas-actividad-edad { font-size: 11.5px; line-height: 1.3; }

/* La barra ocupa el sitio del detalle, no uno propio: así una fila que baja y una que no
   miden lo mismo y los bordes de la grilla no dan saltos. */
.mas-actividad-barra {
    width: 118px; height: 5px; margin-top: 2px; border-radius: 999px;
    background: var(--mas-borde); overflow: hidden;
}
.mas-actividad-barra i {
    display: block; height: 100%; border-radius: 999px; background: var(--mas-info);
}

/* ---------- Atajos de actividad (players del sistema) ---------- */
.atajos-actividad { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.atajos-actividad .atajo {
    padding: 5px 12px; border-radius: 999px; font: inherit; font-size: 12.5px;
    border: 1px solid var(--mas-borde-fuerte); background: var(--mas-superficie);
    color: var(--mas-texto-suave); cursor: pointer; white-space: nowrap;
}
.atajos-actividad .atajo:hover { background: var(--mas-primario-50); }
.atajos-actividad .atajo[aria-pressed="true"] {
    background: var(--mas-primario); border-color: var(--mas-primario);
    color: var(--mas-texto-inverso); font-weight: 500;
}

/* ---------- Barra de la grilla: actualizar ---------- */
.mas-grilla-edad {
    font-size: 12px; color: var(--mas-texto-tenue); white-space: nowrap;
    /* Ancho mínimo para que el texto al cambiar —«recién» → «actualizando…» → «hace 12 s»—
       no empuje el botón de al lado de un sitio a otro. Un botón que se mueve solo bajo el
       cursor es un clic perdido. */
    min-width: 128px; text-align: right;
}
.mas-grilla-auto {
    display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
    font-size: 12.5px; color: var(--mas-texto-suave); white-space: nowrap; user-select: none;
}
/* El icono gira SOLO mientras el botón está deshabilitado, que es exactamente mientras
   dura la petición. Atada al estado y no a una clase aparte, la animación no se puede
   desincronizar de lo que representa. */
.mas-grilla-actualizar[disabled] .mas-icono { animation: mas-giro .9s linear infinite; }
@keyframes mas-giro { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .mas-grilla-actualizar[disabled] .mas-icono { animation: none; }
}

/* ---------- Indicador de conexión ---------- */
.mas-conexion {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 4px 12px 4px 10px; border-radius: 999px;
    font-size: 12.5px; font-weight: 500; white-space: nowrap;
    background: var(--mas-exito-suave); color: var(--mas-exito);
}
.mas-conexion-punto {
    width: 8px; height: 8px; border-radius: 50%; background: currentColor;
    box-shadow: 0 0 0 0 currentColor; animation: mas-latido 2.4s ease-out infinite;
}
.mas-conexion[data-estado="offline"] { background: var(--mas-peligro-suave); color: var(--mas-peligro); }
.mas-conexion[data-estado="offline"] .mas-conexion-punto { animation: none; }
@keyframes mas-latido {
    0%   { box-shadow: 0 0 0 0 color-mix(in srgb, currentColor 55%, transparent); }
    70%  { box-shadow: 0 0 0 6px color-mix(in srgb, currentColor 0%, transparent); }
    100% { box-shadow: 0 0 0 0 color-mix(in srgb, currentColor 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
    .mas-conexion-punto { animation: none; }
}

/* ---------- Modal ---------- */
.mas-modal {
    width: 92%; padding: 0; color: var(--mas-texto);
    background: var(--mas-superficie); border: 1px solid var(--mas-borde);
    border-radius: var(--mas-radio); box-shadow: var(--mas-sombra-md);
}
.mas-modal::backdrop { background: rgba(11, 46, 111, .45); }
.mas-modal-encabezado {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 14px 18px; border-bottom: 1px solid var(--mas-borde);
    background: var(--mas-primario-50);
}
.mas-modal-encabezado h2 { margin: 0; font-size: 15px; font-weight: 600; color: var(--mas-primario-900); }
.mas-modal-cerrar { background: none; border: none; font-size: 22px; line-height: 1; cursor: pointer; color: var(--mas-texto-suave); }
.mas-modal-cuerpo { padding: 18px; }
.mas-modal-pie {
    display: flex; justify-content: flex-end; gap: 10px;
    padding: 13px 18px; border-top: 1px solid var(--mas-borde);
    background: var(--mas-superficie-2);
}

/* Diálogo de confirmación: reemplaza al confirm() del navegador. */
.mas-confirmar .mas-modal-cuerpo { font-size: 14px; line-height: 1.55; }
.mas-confirmar-detalle { margin: 10px 0 0; font-size: 13px; color: var(--mas-texto-suave); }

/* Confirmación tipeada: el escalón extra de lo irreversible. */
.mas-confirmar-tipeo {
    display: block; margin: 14px 0 0;
    font-size: 12.5px; font-weight: 600; color: var(--mas-texto-suave);
}
.mas-confirmar-tipeo .mas-control { margin-top: 6px; text-transform: uppercase; letter-spacing: .04em; }

/* Espera bloqueante: lo que se ve mientras corre algo que no se puede interrumpir. */
.mas-esperando-caja { display: grid; justify-items: center; gap: 12px; padding: 30px 22px; text-align: center; }
.mas-esperando-mensaje { margin: 0; font-size: 14px; font-weight: 600; }
.mas-esperando-detalle { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--mas-texto-suave); }

dialog.mas-modal[open] { animation: mas-aparecer .14s ease-out; }
dialog.mas-modal[open]::backdrop { animation: mas-fundir .14s ease-out; }
@keyframes mas-aparecer {
    from { opacity: 0; transform: translateY(-8px) scale(.98); }
    to   { opacity: 1; transform: none; }
}
@keyframes mas-fundir { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
    dialog.mas-modal[open], dialog.mas-modal[open]::backdrop { animation: none; }
}

/* ---------- Diálogo remoto ----------
   El fragmento que devuelve el servidor trae su propio .mas-modal-cuerpo y su
   .mas-modal-pie, así que aquí solo hace falta el estado de carga y el de error. */
.mas-dialogo-cargando { display: grid; place-items: center; padding: 34px 0; }
.mas-dialogo-error { margin: 0; color: var(--mas-peligro); }
.mas-dialogo-remoto .mas-modal-pie { margin: 0; }

/* ---------- Avisos flotantes (toast) ----------
   Arriba a la derecha, apilados, sobre el backdrop de un <dialog> (que usa la capa
   superior del navegador): de ahí el z-index alto y el position:fixed. */
.mas-avisos {
    position: fixed; top: 16px; right: 16px; z-index: 9999;
    display: flex; flex-direction: column; gap: 8px;
    max-width: min(380px, calc(100vw - 32px));
    pointer-events: none;
}
.mas-aviso {
    pointer-events: auto; cursor: pointer;
    padding: 11px 15px; font-size: 13.5px; line-height: 1.45;
    border: 1px solid transparent; border-left-width: 3px;
    border-radius: var(--mas-radio-sm); box-shadow: var(--mas-sombra-md);
    background: var(--mas-superficie); color: var(--mas-texto);
    animation: mas-aviso-entrar .18s ease-out;
}
.mas-aviso-exito       { background: var(--mas-exito-suave);       border-left-color: var(--mas-exito);       color: var(--mas-exito); }
.mas-aviso-peligro     { background: var(--mas-peligro-suave);     border-left-color: var(--mas-peligro);     color: var(--mas-peligro); }
.mas-aviso-advertencia { background: var(--mas-advertencia-suave); border-left-color: var(--mas-advertencia); color: var(--mas-advertencia); }
.mas-aviso-info        { background: var(--mas-info-suave);        border-left-color: var(--mas-info);        color: var(--mas-info); }
.mas-aviso-saliendo    { animation: mas-aviso-salir .18s ease-in forwards; }

@keyframes mas-aviso-entrar {
    from { opacity: 0; transform: translateX(18px); }
    to   { opacity: 1; transform: none; }
}
@keyframes mas-aviso-salir {
    from { opacity: 1; transform: none; }
    to   { opacity: 0; transform: translateX(18px); }
}
@media (prefers-reduced-motion: reduce) {
    .mas-aviso, .mas-aviso-saliendo { animation: none; }
}

/* ---------- Subida de archivos (<mas-subida>) ----------
   Todo con las variables del tema: el control se re-marca con el resto. */
.mas-subida { display: block; }

/* Compacta a propósito: la zona de arrastre es un objetivo grande, no un cartel.
   Con el diálogo abierto compite por altura con la lista de archivos, que es lo
   que uno mira mientras suben. */
.mas-subida-zona {
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    padding: 14px 16px; text-align: center; cursor: pointer;
    background: var(--mas-primario-50);
    border: 2px dashed var(--mas-borde-fuerte);
    border-radius: var(--mas-radio);
    transition: background .12s, border-color .12s;
}
.mas-subida-zona:hover { border-color: var(--mas-primario-300); background: var(--mas-primario-100); }
.mas-subida-zona:focus-visible { outline: none; box-shadow: var(--mas-foco); border-color: var(--mas-primario); }

/* Estado mientras hay un archivo sobrevolando la zona. */
.mas-subida-zona.mas-subida-encima {
    border-color: var(--mas-primario); background: var(--mas-primario-100);
}

/* Icono dibujado con CSS: una flecha hacia arriba sobre una bandeja. Evita
   depender de una fuente de iconos o de un SVG externo. */
.mas-subida-icono {
    width: 22px; height: 22px; position: relative; margin-bottom: 0;
    border-bottom: 2px solid var(--mas-primario); border-radius: 0 0 3px 3px;
}
.mas-subida-icono::before {
    content: ""; position: absolute; left: 50%; top: 1px;
    width: 2px; height: 13px; background: var(--mas-primario); transform: translateX(-50%);
}
.mas-subida-icono::after {
    content: ""; position: absolute; left: 50%; top: 1px;
    width: 9px; height: 9px; transform: translateX(-50%) rotate(45deg);
    border-top: 2px solid var(--mas-primario); border-left: 2px solid var(--mas-primario);
    border-radius: 2px;
}

.mas-subida-titulo { margin: 0; font-size: 13.5px; font-weight: 600; color: var(--mas-primario-900); }

/* El «o» entre arrastrar y elegir: se entiende sin él, y ocupaba una línea. */
.mas-subida-o { display: none; }

.mas-subida-pista { margin: 2px 0 0; font-size: 11.5px; color: var(--mas-texto-tenue); }

/* La lista tiene tope de alto y scrollea: diez archivos no pueden empujar el pie
   del diálogo —con sus botones— fuera de la pantalla. */
.mas-subida-lista {
    list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 4px;
    max-height: 260px; overflow-y: auto;
}
.mas-subida-lista:empty { margin: 0; }

.mas-subida-item {
    padding: 4px 9px;
    background: var(--mas-superficie);
    border: 1px solid var(--mas-borde);
    border-left: 3px solid var(--mas-borde-fuerte);
    border-radius: var(--mas-radio-sm);
}

/* Nombre, estado y tamaño en una sola línea. El nombre se lleva el espacio que
   sobra y se corta con puntos suspensivos; los otros dos no se encogen. */
.mas-subida-item-cabecera { display: flex; align-items: baseline; gap: 10px; }
.mas-subida-nombre {
    flex: 1; min-width: 0; font-size: 13.5px; font-weight: 500;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mas-subida-tamano {
    font-size: 12px; color: var(--mas-texto-tenue);
    font-variant-numeric: tabular-nums; white-space: nowrap; flex: none;
}

.mas-subida-barra {
    height: 3px; margin: 4px 0 1px; overflow: hidden;
    background: var(--mas-primario-100); border-radius: 999px;
}
.mas-subida-relleno {
    width: 0; height: 100%; background: var(--mas-primario);
    border-radius: 999px; transition: width .15s linear;
}

.mas-subida-estado {
    font-size: 12px; color: var(--mas-texto-suave);
    flex: none; max-width: 45%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Terminado: la barra al 100 % ya no informa nada y solo ocupa alto. */
.mas-subida-item[data-estado="listo"] .mas-subida-barra { display: none; }

/* Un archivo terminado no necesita seguir mostrando la barra al 100 %: ocupa
   espacio y ya no informa nada. */
.mas-subida-item[data-estado="listo"] { border-left-color: var(--mas-exito); }
.mas-subida-item[data-estado="listo"] .mas-subida-relleno { background: var(--mas-exito); }
.mas-subida-item[data-estado="listo"] .mas-subida-estado { color: var(--mas-exito); }

.mas-subida-item[data-estado="error"] { border-left-color: var(--mas-peligro); background: var(--mas-peligro-suave); }
.mas-subida-item[data-estado="error"] .mas-subida-barra { display: none; }
.mas-subida-item[data-estado="error"] .mas-subida-estado { color: var(--mas-peligro); font-weight: 500; }

.mas-subida-item[data-estado="subiendo"] { border-left-color: var(--mas-primario); }

@media (prefers-reduced-motion: reduce) {
    .mas-subida-relleno { transition: none; }
}

/* ---------- Utilidades ---------- */
.mas-fila { display: flex; gap: var(--mas-espacio); flex-wrap: wrap; }
.mas-fila > * { flex: 1 1 220px; min-width: 0; }
.mas-acciones-pie { display: flex; gap: 10px; justify-content: flex-end; margin-top: var(--mas-espacio); }
.mas-tenue { color: var(--mas-texto-tenue); }
.mas-mono { font-family: var(--mas-fuente-mono); font-size: 12.5px; }

/* Línea secundaria dentro de una celda: la descripción bajo el nombre. */
.mas-menor { font-size: 12px; }

/* Cifras que se comparan de arriba abajo en una columna: con tabular-nums todas las
   cifras ocupan lo mismo y los números quedan alineados aunque cambie el largo. */
.mas-numero { font-variant-numeric: tabular-nums; }
