/* ============================================================
   AppsHub UAI — Específico de pantalla
   Lo que todavía no se usa en dos lugares. Un patrón que aparece
   en una segunda pantalla sube a components.css.
   ============================================================ */

/* ── Identidad por sección ───────────────────────────────────
   Una sola familia —violeta— en tres intensidades, en el mismo
   orden que la jerarquía real de la página:

     · esenciales   violeta profundo, emparentado con la marca
     · ecosistema   el acento estándar; NO lleva clase, es la
                    línea base
     · adicionales  gris violáceo apagado: enlaces externos,
                    de apoyo

   Power BI queda como la única sección con otro tono porque es
   contenido de otra naturaleza, no un escalón más de la misma
   jerarquía.

   Se redefinen las tres variables del acento, así todo lo que ya
   las usa —ícono, contador, hover, foco, «Abrir»— cambia sin una
   sola regla nueva.

   Los valores viven en tokens.css, uno por tema: acá sólo se dice
   qué sección usa cuál. Un color escrito a mano en este archivo
   sería el que rompa el modo oscuro dentro de seis meses.

   Se llaman `acento-*` y no `seccion-*` porque **el color viaja
   con la tarjeta**, no con la sección: en «Mis accesos» conviven
   las cuatro procedencias, y atado al contenedor de origen se
   verían todas del mismo violeta — el color perdería sentido
   justo donde más se mezcla. La clase va en la sección (para el
   título y el contador) y también en cada envoltorio de tarjeta,
   que es lo que la deja funcionar fuera de casa. */

.acento-esenciales {
    --accent: var(--esencial-accent);
    --accent-bg: var(--esencial-bg);
    --accent-fg: var(--esencial-fg);
    /* Repetidas a propósito: `var(--accent)` se resuelve en el bloque donde se
       escribe, así que heredarlas de `:root` traería el violeta base. */
    --realce: var(--esencial-accent);
    --acento-texto: var(--esencial-accent);
}

.acento-adicionales {
    --accent: var(--adicional-accent);
    --accent-bg: var(--adicional-bg);
    --accent-fg: var(--adicional-fg);
    --realce: var(--adicional-accent);
    --acento-texto: var(--adicional-accent);
}

/* Más aire abajo que entre secciones: «Mis accesos» es de otra naturaleza —la
   elección de cada uno, no el catálogo institucional— y con la misma separación
   se leía como una sección más del hub. */
.seccion-favoritos {
    margin-bottom: 52px;
}

/* ── Sección de reportes ─────────────────────────────────────
   El amarillo de Power BI va sólo de fondo: como texto es ilegible. Los tonos
   de acento viven en `--bi-*` para no pisar el violeta de las otras secciones,
   y los componentes los leen a través de `--realce` y `--acento-texto`. */

/* Las dos variables de realce. Todo lo demás las lee, así que el ámbar entra
   por acá y no regla por regla. */
.acento-reportes {
    --realce: var(--bi);
    --acento-texto: var(--bi-fg);
}

.acento-reportes .contador {
    color: var(--bi-fg);
    background: var(--bi-soft);
}

.acento-reportes .icono {
    background: var(--bi);
    color: var(--bi-ink);
}

.acento-reportes .tarjeta:hover {
    border-color: var(--bi);
}

.acento-reportes .tarjeta:focus-visible {
    outline-color: var(--bi);
}

.acento-reportes .accion-abrir {
    color: var(--bi-fg);
}

.acento-reportes .tarjeta.bloqueada:hover {
    border-color: var(--border-default);
}

/* Reporte anunciado que todavía no existe: se ve, atenuado, y su enlace lleva
   al espacio de Power BI en lugar de a un informe que daría 404. */
.tarjeta.reservado {
    opacity: .72;
}

/* ── Pantalla de ingreso ─────────────────────────────────────
   Por la puerta web, sin sesión no se ve nada del catálogo: ni los títulos ni
   los nombres de los sistemas. Es la diferencia con la pestaña de Teams, donde
   la identidad ya está confirmada por el entorno.

   Es la primera pantalla del sistema y durante un tiempo va a ser la única que
   vea quien todavía no entró, así que se sostiene sola: una tarjeta con la
   marca, el estado y una sola acción posible. */

.ingreso {
    /* Las dos alturas, y en este orden.

       `100vh` en iOS no es lo que se ve: es el viewport **sin** las barras del
       navegador, o sea más alto que la pantalla útil. La tarjeta se centra
       dentro de esa caja, así que queda más abajo del centro y en un teléfono
       chico su parte inferior —el enlace para cerrar la sesión de Microsoft—
       cae debajo del pliegue. En la única pantalla que ve quien todavía no
       entró.

       `svh` es el viewport **con** las barras visibles, o sea el más chico: el
       contenido entra siempre y no hay salto cuando las barras aparecen o se
       van. Con `dvh` entraría igual, pero la caja cambiaría de alto al
       scrollear y algo centrado se movería solo.

       El `100vh` queda primero como respaldo: un navegador que no entienda
       `svh` descarta la segunda línea y se queda con la primera. */
    min-height: 100vh;
    min-height: 100svh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-8);
    padding: var(--space-6);
    text-align: center;
}

.ingreso-tarjeta {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    max-width: 420px;
    padding: var(--space-10) var(--space-8);
    background: var(--surface-card);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-2xl);
    box-shadow: var(--shadow-lg);
}

/* Más grande que en el encabezado del hub: acá no compite con nada y es lo
   único que identifica el sitio antes de que la persona sepa dónde está. */
.ingreso-marca {
    width: 76px;
    height: 76px;
    border-radius: var(--radius-xl);
}

.ingreso-marca img {
    width: 52px;
    height: 52px;
}

.ingreso h1 {
    margin: var(--space-2) 0 0;
    font-size: var(--text-2xl);
    font-weight: var(--weight-semibold);
}

.ingreso-sub {
    margin: 0;
    font-size: var(--text-md);
    color: var(--text-muted);
}

.boton-ingresar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    width: 100%;
    margin-top: var(--space-3);
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    color: var(--text-inverse);
    background: var(--accent);
    border-radius: var(--radius-lg);
    padding: var(--space-3) var(--space-6);
    text-decoration: none;
    transition: filter var(--transition-fast);
}

.boton-ingresar:hover {
    filter: brightness(1.08);
}

.boton-ingresar .ti {
    width: 18px;
    height: 18px;
}

[data-theme="dark"] .boton-ingresar,
[data-theme="contrast"] .boton-ingresar {
    color: var(--bg);
}

/* Y lo mismo para quien no eligió tema, que es el caso por omisión.

   Sin este bloque, la regla de arriba sólo alcanza a quien tocó el selector: en
   «seguir al sistema» —el modo en el que está casi todo el mundo— el botón
   quedaba con texto claro sobre el violeta claro del acento oscuro, **2,07:1**
   contra el 4,5 que pide AA. No lo veía el verificador de contraste porque mide
   pares de tokens y esto sale de la combinación de dos reglas. */
@media (prefers-color-scheme: dark) {
    html:not([data-theme="light"]):not([data-theme="contrast"]) .boton-ingresar {
        color: var(--bg);
    }
}

/* El mensaje sobre el botón: por qué falló el ingreso, o que la sesión se
   cerró. Las dos variantes comparten todo menos el color. */
.ingreso-aviso {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    width: 100%;
    margin: var(--space-2) 0 0;
    padding: var(--space-3) 14px;
    font-size: var(--text-base);
    font-weight: var(--weight-medium);
    line-height: 1.5;
    text-align: left;
    border: 1px solid transparent;
    border-radius: var(--radius-lg);
}

.ingreso-aviso .ti {
    flex: none;
    width: 18px;
    height: 18px;
    margin-top: 2px;
}

.ingreso-aviso-falla {
    color: var(--nota-acceso-fg);
    background: var(--nota-acceso-bg);
}

.ingreso-aviso-listo {
    color: var(--aviso-info-fg);
    background: var(--aviso-info-bg);
}

.ingreso-nota {
    margin: var(--space-2) 0 0;
    font-size: var(--text-sm);
    color: var(--text-muted);
    line-height: 1.5;
}

.ingreso-enlace {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    color: var(--text-secondary);
    text-decoration: none;
    border-bottom: 1px solid var(--border-default);
    padding-bottom: 2px;
    transition: color var(--transition-fast);
}

.ingreso-enlace:hover {
    color: var(--text-primary);
}

.ingreso-enlace .ti {
    width: 15px;
    height: 15px;
}

.ingreso-pie .logo-uai {
    height: 58px;
    width: auto;
    max-width: 100%;
    opacity: .95;
}

/* ── Salir ───────────────────────────────────────────────────
   Es un formulario y no un enlace: con GET, cualquier página externa podría
   cerrarle la sesión a quien la visite con una etiqueta de imagen. */

/* Cuadrado como el engranaje y el avatar, sin la palabra «Salir».

   El texto se fue al `title` y a un `.solo-lectores` adentro: era el nombre
   accesible del botón, y sacarlo sin reemplazo lo dejaba anónimo para un lector
   de pantalla. Un `title` no cubre eso — no todos los lectores lo anuncian.

   Medidas propias y no heredadas de `.volver-al-hub` aunque se vean iguales:
   este botón tiene su propio estado de hover y compartir la clase obligaría a
   deshacerlo con un selector más específico. */
.boton-salir {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--alto-control);
    height: var(--alto-control);
    flex: none;
    font: inherit;
    color: var(--text-muted);
    background: transparent;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-lg);
    padding: 0;
    cursor: pointer;
    transition: color var(--transition-fast), border-color var(--transition-fast),
        background-color var(--transition-fast);
}

.boton-salir .ti {
    width: 16px;
    height: 16px;
}

/* **El rojo aparece sólo al pasar por encima**, y ésa es la decisión.

   Puesto siempre gastaría el único rojo del sistema: `--aviso-mant-*` significa
   «algo anda mal», y con un botón rojo permanente en el encabezado el cartel de
   un aviso de mantenimiento deja de destacarse — el rojo de la alerta compite
   con un rojo que ya estaba.

   En hover no compite con nada: la alerta no aparece bajo el mouse, y quien está
   por cerrar la sesión ve que ese botón no es como los otros tres. */
.boton-salir:hover,
.boton-salir:focus-visible {
    color: var(--aviso-mant-fg);
    background: var(--aviso-mant-bg);
    border-color: var(--aviso-mant-fg);
}

/* ── Pantalla de bloqueo ─────────────────────────────────────
   Fuera de Teams no hay token, así que el catálogo nunca llega. Deja de ser un
   cartel evadible desde las herramientas de desarrollo y pasa a ser el estado
   real de la página: no hay tarjetas que ocultar. */

.bloqueo {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    background: var(--bg);
    color: var(--text-muted);
    text-align: center;
    padding: var(--space-6);
}

.bloqueo-candado {
    width: 64px;
    height: 64px;
    border-radius: var(--radius-2xl);
    flex: none;
    background: var(--accent-bg);
    color: var(--accent-fg);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 32px;
}

.bloqueo p {
    margin: 0;
    font-size: 15px;
    max-width: 320px;
    line-height: 1.5;
}

/* Salida del candado. Discreta a propósito: la mayoría de las veces que se ve
   esta pantalla el bloqueo es correcto, y esto es para la minoría en que se
   llegó por una demora. */
.bloqueo-reintentar {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    font: inherit;
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    color: var(--accent-fg);
    background: var(--accent-bg);
    border: 1px solid transparent;
    border-radius: var(--radius-lg);
    padding: var(--space-2) var(--space-4);
    cursor: pointer;
}

.bloqueo-reintentar:hover {
    filter: brightness(.97);
}

.bloqueo-reintentar .ti {
    font-size: var(--text-lg);
}

/* La segunda línea de la pantalla: dice qué hacer, no qué pasó. Va debajo
   del mensaje y más chica, para que quien ya sabe lo que pasa no tenga que
   leerla. */
.bloqueo-detalle {
    max-width: 34rem;
    margin: calc(var(--space-4) * -1) 0 0;
    padding: 0 var(--space-4);
    font-size: var(--text-base);
    line-height: 1.5;
    text-align: center;
    color: var(--text-muted);
}

/* La salida hacia el hub web. Mismo tamaño y misma forma que «Reintentar»
   —nunca aparecen juntos— pero sin relleno: no es la acción esperada de esta
   pantalla, es la que queda cuando la esperada no puede funcionar. */
.bloqueo-web {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    color: var(--accent);
    text-decoration: none;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-lg);
    padding: var(--space-2) var(--space-4);
}

.bloqueo-web:hover {
    border-color: var(--accent);
}

.bloqueo-web .ti {
    font-size: var(--text-lg);
}

[data-theme="contrast"] .bloqueo-reintentar {
    border-color: #ffff01;
}

/* ── Logotipo del pie ────────────────────────────────────────
   Dos archivos, uno por tema: el logo es de un solo color y sobre el fondo
   contrario desaparece. */

.logo-oscuro {
    display: none;
}

[data-theme="dark"] .logo-claro,
[data-theme="contrast"] .logo-claro {
    display: none;
}

[data-theme="dark"] .logo-oscuro,
[data-theme="contrast"] .logo-oscuro {
    display: block;
}

@media (prefers-color-scheme: dark) {
    html:not([data-theme="light"]):not([data-theme="contrast"]) .logo-claro {
        display: none;
    }

    html:not([data-theme="light"]):not([data-theme="contrast"]) .logo-oscuro {
        display: block;
    }
}

/* ── Gestión del catálogo ────────────────────────────────────
   En /gestion y nunca en /admin: el WAF del balanceador bloquea cualquier ruta
   que contenga esa palabra antes de que llegue al servidor, y el 403 no lo
   emite la aplicación ni aparece en ningún log de acá.

   **Sin ancho propio.** Tenía `max-width: 960px` contra los 1120 del hub, y
   como se va y se vuelve con el engranaje y la flecha varias veces por sesión,
   el logotipo y el borde del contenido saltaban 80px hacia adentro en cada
   viaje. Cada pantalla se veía bien sola; juntas parecían dos sitios pegados
   con un enlace. El tope lo pone `--ancho-contenido` y nadie más. */

.volver-al-hub {
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--alto-control);
    height: var(--alto-control);
    flex: none;
    border-radius: var(--radius-lg);
    color: var(--text-muted);
    background: var(--surface-card);
    border: 1px solid var(--border-default);
    /* Explícito porque la clase la usan `<a>` y `<button>`. Los enlaces traen la
       manito del navegador y los botones no, así que sin esta línea el de grupos
       se ve idéntico a los otros dos y no parece cliqueable. */
    cursor: pointer;
    transition: color var(--transition-fast), border-color var(--transition-fast);
}

.volver-al-hub .ti {
    width: 16px;
    height: 16px;
}

.volver-al-hub:hover {
    color: var(--accent);
    border-color: var(--accent);
}

.boton-nuevo {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    margin-left: auto;
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    color: var(--accent-fg);
    background: var(--accent-bg);
    border-radius: var(--radius-lg);
    padding: var(--space-1) var(--space-3);
    text-decoration: none;
}

.boton-nuevo:hover {
    filter: brightness(.97);
}

/* `inline-flex` con `gap` y no un botón de texto a secas: los que llevan ícono
   —«Publicar ahora», «Releer el catálogo»— lo pegaban al texto sin un píxel de
   aire, porque un SVG en línea no trae separación propia como sí la traía el
   glifo del webfont que se usaba antes. Los que no llevan ícono no cambian: el
   `gap` de un solo hijo no separa nada. */
.boton-estado {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font: inherit;
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--text-muted);
    background: transparent;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    padding: 3px var(--space-2);
    cursor: pointer;
    white-space: nowrap;
}

.boton-estado:hover {
    color: var(--text-primary);
    border-color: var(--border-strong);
}

/* Dada de baja: se ve, atenuada, con su botón para volver a ponerla. No se
   borra nada — el historial de cambios sigue teniendo a qué referirse. */
.fila-de-baja {
    opacity: .55;
}

.marca-baja {
    margin-left: var(--space-2);
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    text-transform: uppercase;
    letter-spacing: .4px;
    color: var(--text-muted);
}

.marca-restringida {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--nota-acceso-fg);
    background: var(--nota-acceso-bg);
    border-radius: var(--radius-full);
    /* Sin esto, «Del entorno» se partía en dos renglones en la columna de
       Administración y el redondeo completo sobre una caja de dos líneas
       dibujaba un rectángulo con las esquinas muy redondeadas, con el candado
       arriba y media palabra abajo.

       No era falta de lugar: la pastilla pide 97px en una línea y la celda
       tenía 106. Se partía porque el ancho de la columna lo calcula el
       navegador con el min-content de la celda —la palabra más larga,
       «entorno»—, así que la columna quedaba dimensionada para la versión
       partida y la pastilla se acomodaba a ella. Con `nowrap` el min-content
       pasa a ser la pastilla entera y la columna se abre lo necesario. */
    white-space: nowrap;
    padding: 2px var(--space-2);
}

.marca-abierta {
    font-size: var(--text-sm);
    color: var(--text-muted);
}

/* ── Barra de desarrollo ─────────────────────────────────────
   Sólo con APP_ENV=development. Reemplaza a la barra DEV que tenía el
   `dev/local.html` del hub estático, que era una copia entera del hub que había
   que mergear a mano contra la de producción cada vez. */

.barra-dev {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-4);
    background: repeating-linear-gradient(
        45deg,
        var(--nota-dev-bg),
        var(--nota-dev-bg) 10px,
        var(--surface-sunken) 10px,
        var(--surface-sunken) 20px
    );
    color: var(--nota-dev-fg);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    border-bottom: 1px solid var(--border-default);
}

.barra-dev code {
    font-size: var(--text-xs);
}
