/* =================================================================
   lab34 — sistema visual del sitio.

   Implementa lab/design_handoff_lab34/README.md: estética de sala de
   control, fondo oscuro, una sola familia tipográfica, cero radios y
   cero sombras. La jerarquía se hace con valor de fondo y borde.

   El verde --accent está reservado para "activo / al aire / seleccionado".
   No usarlo para nada más.
   ================================================================= */


/* -----------------------------------------------------------------
   Tipografía

   Una sola familia: JetBrains Mono, la misma del logo. El handoff la
   pide desde Google Fonts; acá va auto-hospedada porque el servidor es
   interno y no sale a internet. Es la variable font, así que un solo
   archivo cubre los pesos 400, 500 y 700 que usa el sistema.
   ----------------------------------------------------------------- */

@font-face {
    font-family: 'JetBrains Mono';
    src: url('../tipografias/JetBrainsMono-VariableFont_wght.ttf') format('truetype');
    font-weight: 100 800;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'JetBrains Mono';
    src: url('../tipografias/JetBrainsMono-Italic-VariableFont_wght.ttf') format('truetype');
    font-weight: 100 800;
    font-style: italic;
    font-display: swap;
}


/* -----------------------------------------------------------------
   Tokens
   ----------------------------------------------------------------- */

:root {
    --bg:               #101211;
    --surface:          #151815;
    --surface-active:   #141a13;
    --surface-hover:    #181c17;

    --border:           #23281f;
    --border-bar:       #22261f;
    --border-hover:     #3d4a39;
    --border-underline: #3a4238;

    --text:             #e6e6e1;
    --text-value:       #c9cec6;
    --text-muted:       #8d938a;
    --text-dim:         #79837a;
    --text-meta:        #6f7a68;
    --text-faint:       #5f6a5f;
    --text-ghost:       #4d5449;

    --divider-faint:    #3a4238;
    --dot-off:          #2c322a;

    /* Reservado: activo / al aire / seleccionado. Nada más. */
    --accent:           #8fd44a;
    --accent-underline: #3f5a2c;

    --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--mono);
    -webkit-font-smoothing: antialiased;
}

a {
    color: inherit;
    text-decoration: none;
}

/* La única animación del sistema. No agregar más. */
@keyframes lab34pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: .25; }
}


/* -----------------------------------------------------------------
   Barra de estado — va arriba de todas las pantallas
   ----------------------------------------------------------------- */

/* El alto se fija acá y no lo decide el contenido: la barra es la misma
   franja en todas las páginas, y una que meta controles en el centro no
   puede engordarla. 46px es lo que medía con el padding de 16 y el texto
   de 12px, así que nada se mueve. */
.barra {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 46px;
    padding: 0 40px;
    border-bottom: 1px solid var(--border-bar);
    font-size: 12px;
    letter-spacing: .06em;
    color: var(--text-meta);
}

.barra-derecha {
    display: flex;
    align-items: center;
    gap: 26px;
}

/* El hueco del medio de la barra, para las páginas que ponen controles ahí
   en vez de gastar una franja propia. Con flex:1 y centrado queda al medio
   de la pantalla y no al medio del espacio sobrante, que se movería según
   cuánto mida el reloj. */
.barra-centro {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    min-width: 0;
}

/* Lo que va en el centro tiene que caber en la barra sin estirarla: nada
   ahí adentro puede pasar de su alto. */
.barra-centro > * { max-height: 100%; }

.barra-estado {
    display: flex;
    align-items: center;
    gap: 8px;
}


/* -----------------------------------------------------------------
   Tablero de engines — una caja por sala, un punto por canal de aire

   Habla el mismo idioma que el Mapa Viz, que es donde uno termina
   cuando algo está rojo: los mismos colores y los mismos puntos
   redondos. Un verde acá significa lo mismo que allá — que el puerto
   acepta conexiones—, ni más ni menos.

   Solo entran los engines de aire. El engine local de un Trio cerrado
   es lo normal fuera del programa y en rojo enseñaría a ignorar el
   rojo. El criterio completo está en vizmapa/php/config.php.

   El contenedor se dibuja vacío y solo aparece cuando el sondeo trajo
   algo: sin la clase .visible no ocupa lugar, así la barra no muestra
   una fila de cajas grises cuando no se pudo consultar.
   ----------------------------------------------------------------- */

.engines {
    display: none;
    align-items: flex-end;
    gap: 12px;
}

.engines.visible { display: flex; }

.engine-sala {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 3px 6px;
    border: 1px solid var(--border-bar);
    line-height: 1;
}

.engine-sala:hover { border-color: var(--border-hover); }

/* La sala con algo caído se marca en el borde, no solo en el punto:
   de reojo se ve la caja antes que el punto de 5 píxeles. */
.engine-sala.con-caido { border-color: #5c2020; }

.engine-abrev {
    font-size: 9px;
    letter-spacing: .08em;
    color: var(--text-meta);
}

.engine-sala:hover .engine-abrev { color: var(--text-dim); }

.engine-puntos {
    display: flex;
    gap: 4px;
}

.engine-punto {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--dot-off);
}

/* Verde: el mismo --accent del sistema. Acá "responde" es la versión
   de "activo" que corresponde a una máquina, así que no es una
   excepción a la regla del verde reservado. */
.engine-punto.ok    { background: var(--accent); }
.engine-punto.caido { background: #e1121c; }

.punto {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent);
}

.punto.late { animation: lab34pulse 2.4s ease-in-out infinite; }
.punto.apagado { background: var(--dot-off); }


/* -----------------------------------------------------------------
   Portada
   ----------------------------------------------------------------- */

.pagina {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

.contenedor {
    flex: 1;
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    padding: 0 40px 64px;
}

/* El índice compara datos en horizontal, así que va más ancho. */
.contenedor.ancho { max-width: 1400px; padding-bottom: 72px; }

.encabezado {
    padding-top: 72px;
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 40px;
    flex-wrap: wrap;
}

/* El wordmark sale de php/logo.php: la geometría del set de marca,
   partida en tres trazos para pintar corchetes, "lab" y "34" por
   separado. No se rehace con texto — los archivos llevan correcciones
   de trazo que la fuente no tiene. */
.wordmark { display: block; }

/* -----------------------------------------------------------------
   Portada: wordmark a la izquierda, accesos de color a la derecha

   Los dos arrancan arriba, pegados a la barra. Antes iban en dos
   bloques apilados y se iba media pantalla en llegar a las tarjetas,
   que es a lo que la gente entra.
   ----------------------------------------------------------------- */

.portada-encabezado {
    padding-top: 28px;
    align-items: flex-start;
}

.encabezado-lado {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 18px;
}

/* La fila es relativa porque el nombre del hover se posiciona contra
   ella: así los siete nombres aparecen en el mismo renglón y ninguno
   empuja el layout al aparecer. */
.accesos {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 22px;
    flex-wrap: wrap;
    padding-bottom: 22px;
}

.acceso {
    display: block;
    line-height: 0;
}

.acceso svg { display: block; }

/* Las secciones cerradas se apagan igual que sus tarjetas. */
.acceso.apagado { opacity: .4; }

.acceso-nombre {
    position: absolute;
    right: 0;
    bottom: 0;
    white-space: nowrap;
    font-size: 12px;
    line-height: 1;
    opacity: 0;
    transition: opacity .12s linear;
    pointer-events: none;
}

.acceso:hover .acceso-nombre,
.acceso:focus-visible .acceso-nombre { opacity: 1; }

.acceso-pendiente { color: var(--text-ghost); }

/* Solo el logo se apaga en hover; el nombre que aparece debajo tiene que
   quedar a plena opacidad, que es justo lo que uno fue a leer. */
a.acceso:hover svg { opacity: .75; }

.bajada {
    margin-top: 14px;
    font-size: 14px;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-dim);
}

.meta {
    text-align: right;
    font-size: 12px;
    line-height: 2;
    color: var(--text-faint);
}

/* Grilla de secciones: tres tarjetas de uso diario arriba, dos de
   apoyo abajo. La asimetría es intencional. */
.secciones {
    margin-top: 56px;
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 14px;
}

.seccion {
    background: var(--surface);
    border: 1px solid var(--border);
    padding: 28px 26px 24px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    transition: border-color .15s ease, background-color .15s ease;
}

.seccion:hover,
.seccion:focus-visible {
    background: var(--surface-hover);
    /* el borde toma el color de la sección, que viene en el style inline */
    border-color: var(--sect, var(--border-hover));
    outline: none;
}

.seccion.grande { grid-column: span 2; min-height: 176px; }
.seccion.ancha  { grid-column: span 3; min-height: 150px; }

.seccion-kicker {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 11px;
    letter-spacing: .14em;
}

.seccion-nombre {
    font-size: 27px;
    font-weight: 500;
    letter-spacing: -.01em;
}

.seccion-desc {
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--text-muted);
}

/* margin-top:auto ancla el pie al fondo, para que las cinco tarjetas
   alineen esa línea aunque tengan distinto texto */
.seccion-pie {
    margin-top: auto;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    font-size: 12px;
    color: var(--text-faint);
}

.seccion-pie .accion,
.seccion-pie .pendiente {
    font-size: 11px;
    letter-spacing: .14em;
}

.seccion-pie .accion   { color: var(--text-ghost); }
.seccion-pie .pendiente { color: var(--text-ghost); opacity: .8; }

.seccion:hover .accion { color: var(--sect, var(--text)); }


/* Sección todavía no abierta: misma tarjeta, sin enlace y en voz baja.
   No se atenúa entera con opacity para que el color de la sección siga
   leyéndose en el kicker y el nombre — la sección existe, solo no se
   entra todavía. */
.seccion.apagada {
    background: transparent;
    cursor: default;
}

.seccion.apagada .seccion-nombre { opacity: .55; }
.seccion.apagada .seccion-desc   { color: var(--text-meta); }
.seccion.apagada .seccion-kicker { opacity: .55; }

.seccion.apagada:hover {
    background: transparent;
    border-color: var(--border);
}

.pie {
    margin-top: 28px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 12px;
    color: var(--text-faint);
    flex-wrap: wrap;
    gap: 16px;
}

.pie-derecha {
    display: flex;
    gap: 22px;
}

.pie a:hover { color: #ffffff; }

/* El sistema no subraya nada, así que un enlace metido en un texto
   corrido necesita una marca propia: una línea inferior tenue. Nació
   en el pie de la portada; ahora también lo usan las notas al pie de
   las secciones, que se mandan de una a otra. */
.subrayado {
    border-bottom: 1px solid var(--border-underline);
    padding-bottom: 3px;
}

a.subrayado:hover {
    color: #ffffff;
    border-bottom-color: var(--border-hover);
}


/* -----------------------------------------------------------------
   Índice de aplicaciones y de herramientas
   ----------------------------------------------------------------- */

.miga {
    padding-top: 40px;
    display: flex;
    align-items: center;
    /* más aire que el gap de 10px del handoff: con el wordmark grande,
       10px dejaba la barra pegada a los corchetes */
    gap: 16px;
    font-size: 12px;
    letter-spacing: .06em;
    color: var(--text-faint);
}

/* El nombre de sección va al tamaño del wordmark que tiene al lado.
   El 0.94 sale de la geometría: las letras del logo ocupan 73 de las
   106 unidades de su caja, y la altura de mayúscula de JetBrains Mono
   es ~0.73em. Así los dos [ ] quedan del mismo alto. */
.miga .nivel {
    font-size: calc(var(--miga-alto, 54px) * .94);
    font-weight: 500;
    letter-spacing: -.01em;
    line-height: 1;
}

.miga .sep {
    color: var(--divider-faint);
    font-size: calc(var(--miga-alto, 54px) * .42);
    line-height: 1;
}

.miga a:hover { color: #ffffff; }
.miga a.nivel:hover { opacity: .8; color: inherit; }

/* El wordmark hace de primer nivel del breadcrumb, en el color de la
   sección. El alto lo fija php/cabecera.php (36px por defecto), así que
   acá solo se alinea con el texto que lo sigue. */
.logo-miga {
    display: flex;
    align-items: center;
    /* el logo trae sus propios colores; el hover del breadcrumb no los toca */
    transition: opacity .15s ease;
}

.miga a.logo-miga:hover { opacity: .75; }

.titulo {
    margin: 44px 0 0;
    font-size: 54px;
    font-weight: 700;
    letter-spacing: -.02em;
    line-height: 1;
}

.titulo-desc {
    margin-top: 16px;
    font-size: 14px;
    line-height: 1.7;
    color: var(--text-muted);
    max-width: 62ch;
}

.nota {
    margin-top: 36px;
    padding-top: 20px;
    border-top: 1px solid var(--border-bar);
    font-size: 13px;
    line-height: 1.7;
    color: var(--text-meta);
}


/* -----------------------------------------------------------------
   Página de sección — grilla de apps

   El patrón es el mismo para las cinco secciones: barra → breadcrumb →
   título con corchetes → grilla de tarjetas → nota al pie. Cambia el
   color de la sección y el pie de la tarjeta según qué hace.
   ----------------------------------------------------------------- */

.seccion-encabezado {
    padding-top: 0;
    /* El breadcrumb hace de título, así que esto es la bajada pegada a
       él: menos aire que cuando había un h1 en medio. */
    margin-top: 20px;
    gap: 48px;
}

.seccion-encabezado .titulo-desc { margin-top: 0; }

/* Dos columnas, no tres. El nombre de la app va a 30px y es el dato
   que manda: partido en dos líneas deja de leerse de un vistazo. A
   este ancho entran 33 caracteres, que cubre hasta el nombre más largo.

   auto-fit en vez de repeat(2,...) para que colapse a una columna sin
   necesitar un media query. */
.apps {
    margin-top: 44px;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(480px, 1fr));
    gap: 14px;
}

/* [Descargas]: una ficha por fila en vez de la grilla de a dos, porque
   son pocos archivos y conviene leerlos como una lista, no como mosaico. */
.apps.lista {
    grid-template-columns: 1fr;
}

.app {
    position: relative;
    overflow: hidden;
    /* encierra el mix-blend-mode de ::after dentro de la tarjeta, para
       que no se mezcle con el fondo de la página */
    isolation: isolate;
    background: var(--surface);
    border: 1px solid var(--border);
    padding: 24px 26px 20px;
    display: flex;
    flex-direction: column;
    min-height: 168px;
    transition: border-color .15s ease, background-color .15s ease;
}

.app:hover,
.app:focus-visible {
    background: var(--surface-hover);
    border-color: var(--sect);
    outline: none;
}

/* Ilustración de fondo, opcional: la trae el catálogo en --img.

   Va con mix-blend-mode:screen porque las ilustraciones son líneas
   claras sobre casi negro. En modo screen el fondo oscuro de la imagen
   no aporta nada y solo se suman las líneas, así que la ilustración se
   funde con la tarjeta sin recortarla ni dejar un rectángulo visible.

   La máscara la apaga hacia la izquierda, que es donde va el texto: a
   la altura del nombre y la descripción la imagen ya no existe. */
.app::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: var(--img);
    background-size: cover;
    background-position: right center;
    background-repeat: no-repeat;
    mix-blend-mode: screen;
    opacity: .55;
    pointer-events: none;
    transition: opacity .15s ease;
    -webkit-mask-image: linear-gradient(to right, transparent 30%, #000 95%);
            mask-image: linear-gradient(to right, transparent 30%, #000 95%);
}

.app:hover::after { opacity: .8; }

/* El contenido va por encima de la ilustración. */
.app > * {
    position: relative;
    z-index: 1;
}

.app-kicker {
    font-size: 11px;
    letter-spacing: .14em;
    color: var(--text-meta);
}

.app-nombre {
    margin-top: 10px;
    font-size: 30px;
    font-weight: 500;
    letter-spacing: -.01em;
}

/* Fila nombre + versión, solo en [Descargas]: el nombre solo no basta
   para saber qué archivo tiene alguien ya copiado en su PC. */
.app-nombre-fila {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 10px;
}

.app-nombre-fila .app-nombre { margin-top: 10px; }

.app-version {
    font-size: 12px;
    letter-spacing: .04em;
    color: var(--text-faint);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 2px 10px;
    white-space: nowrap;
}

.app-desc {
    margin-top: 12px;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--text-muted);
    /* la tarjeta es más ancha que antes: el texto puede correr más
       antes de cortar, y así ocupa menos líneas */
    max-width: 56ch;
}

.app-datos {
    margin-top: 18px;
    margin-bottom: 20px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    font-size: 13px;
}

/* La columna fija de 104px es lo que permite comparar las tarjetas en
   horizontal. Es un requisito del diseño, no un detalle: se mantiene
   incluso cuando la grilla colapsa a una columna. */
.dato {
    display: grid;
    grid-template-columns: 104px 1fr;
    gap: 14px;
}

.dato-etiqueta {
    color: var(--text-faint);
    text-transform: uppercase;
}

.dato-valor {
    color: var(--text-value);
    line-height: 1.6;
}

/* margin-top:auto ancla el pie al fondo, para que las líneas divisorias
   de todas las tarjetas coincidan aunque el texto tenga distinto largo */
.app-pie {
    margin-top: auto;
    padding-top: 16px;
    border-top: 1px solid var(--border);
    font-size: 11px;
    letter-spacing: .14em;
    color: var(--text-ghost);
}

.app:hover .app-pie { color: var(--sect); }



/* -----------------------------------------------------------------
   Responsive

   Pensado para monitores de control (1400–1920px). Bajo ~1100px la
   grilla de 6 columnas colapsa a 2, y después a 1.
   ----------------------------------------------------------------- */

@media (max-width: 1100px) {

    .secciones { grid-template-columns: repeat(2, 1fr); }

    .apps { grid-template-columns: 1fr; }

    .seccion.grande,
    .seccion.ancha { grid-column: span 1; }
}

@media (max-width: 760px) {

    .barra,
    .contenedor,
    .contenedor.ancho { padding-left: 24px; padding-right: 24px; }

    .encabezado { padding-top: 48px; }

    .wordmark { height: 60px; }

    .meta { text-align: left; }

    .secciones { grid-template-columns: 1fr; margin-top: 40px; }

    .titulo { font-size: 34px; }

    .apps { grid-template-columns: 1fr; }
}

/* En pantalla chica el tablero no cabe al lado del reloj y la barra se
   parte en dos líneas. Se esconde: quien mira engines desde el teléfono
   entra al Mapa Viz, que sí está pensado para eso. */
@media (max-width: 900px) {
    .engines.visible { display: none; }
}
