/* Pie anclado al fondo. Con la sesion abierta y sin resultados aun, la pagina es
   corta y el pie se quedaba flotando a media altura con hueco vacio debajo. El
   cuerpo es una columna que ocupa como minimo la ventana entera, y #contenido crece
   para empujar el pie hacia abajo. */
#html_body{
    background-color: #EEF5FF;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

#contenido{
    flex: 1 0 auto;
}

.d-none{
    display: none;
}

/* min-w-0 NO es una utilidad de Bootstrap: existe en Tailwind, no aqui. Se usaba en la
   cabecera de la tarjeta (nombre de archivo original) dando por hecho que el framework
   la traia, y sin ella no hacia nada -la clase no coincidia con ninguna regla-. Un hijo
   flex sin min-width:0 no se encoge por debajo del ancho de su contenido, y el nombre
   de archivo (que no tiene espacios donde partir la linea) empujaba la tarjeta entera
   en vez de recortarse con .text-truncate. Se define aqui, a mano, con el mismo nombre
   por si el HTML vuelve a usarla en otro sitio. */
.min-w-0{
    min-width: 0;
}

/* Los desplegables de Bootstrap (menu de cuenta, "Para mi plataforma") se abrian y
   cerraban de golpe: su CSS solo alterna display:none <-> block con la clase .show,
   sin transicion ninguna.

   Deliberadamente SIN @starting-style/allow-discrete: la primera version las usaba, y
   tras desplegarla el salto seguia viendose en Chrome real (confirmado con Ctrl+F5,
   siempre) aunque aqui, probando a mano, no se conseguia reproducir. Son funciones
   CSS relativamente nuevas y no se pudo confirmar que el entorno de pruebas las este
   pintando exactamente igual que un Chrome de verdad, asi que se sustituyen por la
   tecnica de toda la vida -doble requestAnimationFrame en app.js-, que no depende de
   nada que no lleve funcionando igual en todos los navegadores desde hace años. De
   paso se quita el scale(): por especificacion transform no participa en el calculo
   de scrollable overflow, pero promocionar el elemento a su propia capa de composicion
   es justo el tipo de cosa que se comporta distinto entre GPUs, y no hacia falta
   correr ese riesgo por un efecto que apenas se notaba.

   LA ENTRADA usa una clase, .entrando (la pone y la quita app.js en
   show.bs.dropdown/shown.bs.dropdown): se anade ANTES de que Bootstrap ponga .show,
   asi que el primer frame en el que el menu existe ya se pinta con el aspecto
   cerrado -sin eso, el navegador no tiene "un antes" del que partir la transicion, y
   el fundido no se juega, salta directo a visible-. Un doble rAF fuerza que ese frame
   cerrado se pinte de verdad antes de quitar la clase y que la transicion arranque.

   LA SALIDA no puede quitar .show directamente para animarse: Bootstrap decide si el
   desplegable "esta abierto" mirando esa misma clase EN EL MENU (Dropdown._isShown()
   comprueba this._menu, no el boton), asi que retirarla ANTES de que Bootstrap
   termine de cerrar de verdad -popper.destroy(), aria-expanded, quitar el atributo
   del popper- hace que su propio hide() se vuelva un no-operacion. Se probo tal cual:
   el menu se quedaba con el Popper vivo para siempre -y de ahi el salto hacia la
   derecha con scroll horizontal, porque a medio desvanecer el menu se quedaba sin
   quien lo posicionara-, aunque a la vista ya pareciera cerrado. Por eso usa OTRA
   clase, .cerrando, que fuerza el aspecto cerrado SIN tocar .show hasta que Bootstrap
   ha terminado su propio cierre de verdad. */
.dropdown-menu{
    transition: opacity .15s ease, transform .15s ease;
    opacity: 0;
    transform: translateY(-6px);
}
.dropdown-menu.show{
    opacity: 1;
    transform: translateY(0);
}
.dropdown-menu.show.entrando,
.dropdown-menu.show.cerrando{
    opacity: 0;
    transform: translateY(-6px);
}

/* Aqui vivia la regla que pintaba en otro color la ultima letra de "ALT-AI" (un <span
   id="I"> en el logotipo de la barra). Se retiro el 28-ago al centralizar el nombre en una
   variable -colorear una letra concreta solo funciona si el nombre es ese, y el objetivo
   era justo poder cambiarlo-, con la nota de que el logotipo del nombre definitivo seria
   una decision de diseno aparte. Llegado el nombre definitivo (30-ago, "NAURYS"), la
   decision es la misma idea: la "Y" en un azul propio. Atada al nombre actual a proposito,
   igual que antes -static/index.html solo aplica esta clase si `marca == "NAURYS"`, así
   que un cambio de marca futuro no deja una letra pintada de un color que ya no pinta
   nada-. El !important es necesario: antes la regla vivia en un selector de ID (maxima
   especificidad, ganaba a cualquier cosa de Bootstrap sin necesitarlo); una clase sencilla
   no basta, porque bootstrap.min.css se carga DESPUES de este fichero y su propio color
   para .navbar-brand gana el empate.

   El color, #1EC0FF, NO es el #00F7FF que llevaba "ALT-AI": ese cian venia heredado y el
   logo (media/hexagon.png) nunca lo usa. #1EC0FF es el azul claro que de verdad domina el
   degradado del logo -sacado muestreando la imagen pixel a pixel, no a ojo-, así que la
   letra y la marca comparten el mismo azul real en vez de uno inventado aparte. Desde el
   1-sep vive en `--marca-acento` (bloque MARCA, al final del fichero): lo usan tambien el
   lema de la portada, la rayita y el resplandor del fondo, y tecleado a mano en cinco
   sitios acaba siendo cinco azules distintos. */
.letra-marca{
    color: var(--marca-acento) !important;
}

/* El logo grande de la cabecera del producto se retiro (el de la barra ya cumple).
   Se conserva la regla por si se reutiliza el identificador. */
#alt_ai_main_logo{
    cursor: pointer;
}
#alt_ai_main_logo_toast{
    width: 50px;
    height: 50px;
}

.summary_card{
    background-color: #ECB65F;
}

/* "Salir" vive ahora dentro del menu de cuenta. El scale(1.05) que tenia antes,
   cuando era un boton suelto en la barra, haria crecer una fila entera del menu:
   se queda solo el cambio de color, que en una lista si se lee bien. */
#logoutBtn {
    transition: color 0.2s ease;
}

#logoutBtn:hover {
    color: #ef4444 !important;
}

#header_text{
    overflow: hidden;
    min-width: 0;
}

/* Barra de descargas anclada al fondo mientras se leen los resultados.

   Le FALTABA el fondo: solo tenia sombra, asi que el contenido de la pagina se veia
   pasar por detras de la pastilla oscura de los botones y la sombra parecia salir de
   la nada. Se le pone el mismo color que la pagina, translucido y con desenfoque,
   para que se lea como una barra de herramientas y no como un elemento suelto. */
#csv_excel_results.sticky-downloads {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1030;
    padding: 12px 0;
    background-color: rgba(238, 245, 255, 0.94);   /* #EEF5FF, el fondo de la pagina */
    backdrop-filter: blur(6px);
    border-top: 1px solid rgba(13, 27, 62, 0.12);
    box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.12);
}

/* Sitio para que la barra fija no tape el pie cuando se llega al final. El relleno va
   aqui y no en el body: body es el contenedor flex y su relleno inferior quedaria
   DESPUES del pie, dejando una franja vacia debajo. Al ponerlo en el pie, que ya es
   oscuro, el hueco se ve como un pie algo mas alto. */
footer.hueco-barra-fija {
    /* La altura la mide el JavaScript y la escribe en --hueco-barra: estaba clavada en
       104 px y la barra crece cuando sus botones se reparten en dos filas (pantalla
       estrecha, o una etiqueta mas larga). Entonces tapaba el pie y sus enlaces, que es
       exactamente lo que este hueco venia a evitar. Los 104 px se quedan de respaldo por
       si el calculo no llega a ejecutarse. */
    /* !important porque el pie lleva la utilidad `py-4` de Bootstrap, y Bootstrap emite
       las utilidades de espaciado CON !important:
           .py-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; }
       Sin esta marca la regla no llega a aplicarse nunca -ni con el valor medido ni con
       los 104 px de antes-, y la barra seguia tapando los enlaces del pie. Comprobado
       contra el fichero de bootstrap 5.3.8, no supuesto. */
    padding-bottom: var(--hueco-barra, 104px) !important;
}

/* PLEGAR LA BARRA DE DESCARGAS.
   La barra ocupa el borde inferior entero, y en un movil eso es bastante pantalla. Se
   puede apartar; vuelve con la pestana #abrirDescargas.

   NO se pliega sola nunca, y menos la primera vez: justo despues de analizar, esa barra ES
   el producto. Si el cliente tuviera que descubrir un boton flotante para encontrar lo que
   acaba de pagar, lo habriamos escondido. */
#csv_excel_results.sticky-downloads {
    transition: transform .28s ease, opacity .22s ease;
}

#csv_excel_results.sticky-downloads.plegada {
    /* Fuera de la pantalla, no `display:none`: hace falta que siga ocupando su sitio
       durante la transicion para que se vea deslizarse en vez de desaparecer de golpe. */
    transform: translateY(115%);
    opacity: 0;
    pointer-events: none;
}

#abrirDescargas {
    position: fixed;
    right: 16px;
    bottom: 16px;
    z-index: 1031;   /* por encima de la barra (1030), que al plegarse pasa por debajo */
    border-radius: 999px;
    transition: transform .28s ease, opacity .22s ease;
}

/* Aparece creciendo desde la esquina. La clase la quita el JavaScript en el fotograma
   siguiente a mostrarla: con las dos cosas a la vez el navegador no anima nada. */
#abrirDescargas.entrando {
    transform: translateY(12px) scale(.9);
    opacity: 0;
}

/* Quien pide menos movimiento en su sistema lo pide para todo. La barra sigue
   apartandose y volviendo; lo que se quita es el viaje. */
@media (prefers-reduced-motion: reduce) {
    #csv_excel_results.sticky-downloads,
    #abrirDescargas {
        transition: none;
    }
}


/* ============ VISTA DE LISTA DE RESULTADOS ============
   table-layout: fixed reparte las columnas por los anchos del <colgroup> y no por el
   contenido. Es lo que permite recortar el texto con puntos suspensivos: para recortar
   hace falta un ancho conocido, y con el reparto automatico no lo hay. */
.tabla-resultados {
    table-layout: fixed;
}

/* La miniatura de la fila. A 40 px no se distinguia una foto de otra en un monitor
   grande, que es justo donde se usa la lista. */
.tabla-resultados .miniatura-fila {
    width: 64px;
    height: 64px;
    object-fit: cover;
}


/* ============ ZONA DE SUBIDA DESTACADA ============
   Se enciende un momento cuando se llega desde el escaner ("subir esas 37 imagenes"):
   tras cerrarse un modal y desplazarse la pagina, hace falta algo que diga DONDE hay que
   mirar. Dos latidos y se apaga; un destacado permanente seria ruido en cada visita. */
@keyframes latido-zona {
    0%, 100% { box-shadow: 0 0 0 0 rgba(13, 110, 253, 0); }
    50%      { box-shadow: 0 0 0 8px rgba(13, 110, 253, 0.35); }
}

.zona-destacada {
    animation: latido-zona 1.1s ease-in-out 2;
}

/* Quien haya pedido menos animacion no recibe latidos: se marca con un borde fijo, que
   informa igual sin moverse. */
@media (prefers-reduced-motion: reduce) {
    .zona-destacada {
        animation: none;
        outline: 3px solid rgba(13, 110, 253, 0.55);
        outline-offset: 4px;
    }
}

/* ============ ACCESIBILIDAD: AREA TACTIL MINIMA ============
   Los botones pequenos de las tarjetas (Copiar, Editar, Guardar...) iban con py-0 a
   0.7rem: unos 20px de alto, por debajo del minimo tactil de 24x24 (WCAG 2.5.8), y se
   repiten por decenas en pantalla. Una sola regla en vez de tocar los ~12 sitios que
   los generan: amplia el area de toque sin cambiar el diseno. */
.btn-sm.py-0 {
    min-height: 24px;
    min-width: 24px;
}


/* ============ MARCA: LA FRANJA OSCURA Y LA PORTADA ============

   LOS COLORES NO SON INVENTADOS. Son los mismos que `generar_cartel.py` usa para el
   cartel de `media/marca/`, y aquellos salieron de muestrear `media/hexagon.png` pixel
   a pixel. Tenerlos aqui como variables evita lo de siempre: el mismo azul tecleado en
   cinco sitios y cuatro de ellos quedandose viejos. Si algun dia se retoca la paleta,
   se retoca en estas cuatro lineas y en las constantes del script del cartel -que son
   los dos unicos sitios donde vive-.

     --marca-fondo         el azul de la marca llevado casi al negro (FONDO_ALTO)
     --marca-fondo-hondo   su version mas oscura (FONDO)
     --marca-acento        el azul que de verdad domina el degradado del logo
     --marca-tinta-suave   el gris azulado de los textos secundarios del cartel

   POR QUE LA WEB PASA DEL GRIS DE BOOTSTRAP AL AZUL DE LA MARCA: las franjas oscuras
   de la portada usaban `.bg-dark`, o sea el #212529 que trae Bootstrap de serie. Es un
   gris neutro que no significa nada y que NO es el fondo del cartel de la marca, asi
   que el material de presentacion y la web parecian de dos productos distintos. Ahora
   comparten fondo.

   COMO SE APLICA, Y POR QUE ASI: quitando `bg-dark` del elemento y poniendo
   `franja-marca` en su lugar, NO superponiendo una regla encima. Este fichero se carga
   ANTES que bootstrap.min.css, y las utilidades de fondo de Bootstrap se emiten con
   `!important`: intentar ganarle el color desde aqui obligaria a otro `!important`, y
   se acaba con dos reglas peleandose por cada franja. Si alguna vuelve a llevar
   `bg-dark`, el gris gana en silencio. */
:root{
    --marca-fondo: #0A1526;
    --marca-fondo-hondo: #050B18;
    --marca-acento: #1EC0FF;
    /* El mismo azul en componentes sueltos, para poder darle transparencia: el
       resplandor del fondo, la sombra del logo y los extremos de la rayita lo usan a
       distintas opacidades, y `rgba()` no acepta un color hexadecimal en una variable.
       Los dos valores se cambian JUNTOS o dejan de ser el mismo azul. */
    --marca-acento-rgb: 30, 192, 255;
    --marca-tinta-suave: #7E97B8;
}

.franja-marca{
    background-color: var(--marca-fondo);
}

/* LA PORTADA DE MARCA: lo primero que se ve al entrar.

   Antes la pagina abria directamente con el argumentario -antetitulo, titular a dos
   lineas, parrafo, dos botones, letra pequenia y el escaner-, todo pegado y alineado a
   la izquierda. Cabia entero en la primera pantalla, y esa es justo la pega: se veia
   apretado y no habia un solo momento en el que la marca se presentara sola.

   Ahora hay un compas antes del argumentario: logo, nombre y lema centrados, y nada
   mas. La altura esta ELEGIDA para que no llene la ventana del todo -el arranque de la
   franja siguiente asoma por abajo-, que es lo que dice "sigue bajando" sin tener que
   escribirlo. Con `100vh` la promesa y el boton de registro quedarian fuera de la
   primera pantalla entera, y eso en una pagina que vende es caro. */
.portada-marca{
    /* Solo la IMAGEN de fondo: el color plano lo pone .franja-marca. El resplandor se
       desvanece a transparente antes del borde, asi que no hay costura visible con la
       franja de abajo, que es del mismo color liso. */
    background-image:
        radial-gradient(58% 54% at 50% 42%,
                        rgba(var(--marca-acento-rgb), .18), rgba(var(--marca-acento-rgb), 0) 70%);
    display: flex;
    align-items: center;
    text-align: center;
    /* La linea con `vh` es el respaldo y va PRIMERA: si el navegador no entiende `svh`
       descarta la segunda entera (un clamp con una unidad desconocida es invalido) y se
       queda con esta. `svh` es la ventana SIN contar la barra del navegador movil, que
       aparece y desaparece al desplazarse: con `vh` la portada cambia de alto a mitad
       de scroll y el contenido pega un salto. */
    min-height: clamp(360px, 72vh, 640px);
    min-height: clamp(360px, 72svh, 640px);
    padding-block: 3rem 2rem;
}

.portada-logo{
    /* Tres tamanios en una linea: nunca menos de 96 px (en un movil estrecho tiene que
       seguir leyendose como un logo, no como un icono) y nunca mas de 190 px. El tope se
       midio contra el nombre: por debajo de ~170 px el logo se veia como un adorno del
       texto en vez de como la pieza principal, y por encima de ~200 px se come el
       espacio que necesita el lema para respirar. El fichero es el SVG
       (`media/hexagon.svg`, 3-sep), asi que a cualquier densidad de pantalla se pinta
       nitido; antes iban dos WebP con `srcset` y el de 256 px de la barra se quedaba
       corto a este tamanio. */
    width: clamp(96px, 19vw, 190px);
    height: auto;
    display: block;
    margin: 0 auto 1rem;
    /* El mismo azul del logo, desenfocado por debajo: lo despega del fondo sin ponerle
       un marco. */
    filter: drop-shadow(0 12px 32px rgba(var(--marca-acento-rgb), .28));
}

.portada-nombre{
    font-weight: 900;
    font-size: clamp(2.6rem, 10vw, 5.25rem);
    line-height: 1;
    letter-spacing: .06em;
    /* El espaciado entre letras se aniade TAMBIEN despues de la ultima, asi que la caja
       del texto es .06em mas ancha que lo que se ve y el bloque centrado queda medio
       espacio corrido a la izquierda. Con el texto centrado, un `text-indent` de X lo
       devuelve X/2 a la derecha, que es exactamente la compensacion que hace falta. */
    text-indent: .06em;
    color: #fff;
}

/* La rayita entre el nombre y el lema. Bootstrap da estilo al `hr` (borde superior y
   opacidad .25), pero lo hace con un selector de ELEMENTO: esta clase gana el empate
   aunque su hoja se cargue despues. */
.portada-regla{
    width: 72px;
    height: 2px;
    border: 0;
    margin: 1.25rem auto 1rem;
    opacity: 1;
    background: linear-gradient(90deg,
                rgba(var(--marca-acento-rgb), 0), var(--marca-acento), rgba(var(--marca-acento-rgb), 0));
}

/* EL LEMA. Va en OTRA FAMILIA a proposito: el logotipo es una sans muy pesada y el lema
   pide contraste, no mas de lo mismo en pequenio.

   Y va en una pila de fuentes DEL SISTEMA, sin descargar nada. No es pereza: la CSP de
   esta aplicacion solo admite fuentes propias (`font-src 'self' data:`), asi que Google
   Fonts esta descartado de raiz, y alojar aqui una serif costaria una descarga mas en
   el primer pintado -justo en el elemento que se quiere que aparezca ya-, ademas del
   salto de tipografia mientras llega. Las candidatas van de la mejor a la peor: Iowan
   Old Style y Palatino en Apple, Palatino Linotype y Book Antiqua en Windows, Georgia
   en cualquier sitio.

   Son DOS clases y no una porque el lema sale en dos sitios: grande en la portada y
   pequenio en el pie. Lo que comparten -la familia, el espaciado, el color- vive en
   `.lema-marca`; el tamanio y la animacion de entrada, que solo tienen sentido en la
   portada, en `.portada-lema`. Con una sola clase, el lema del pie heredaria la
   animacion y se pondria a aparecer solo en un sitio donde nadie esta mirando. */
.lema-marca{
    font-family: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua",
                 Georgia, "Times New Roman", serif;
    font-weight: 400;
    letter-spacing: .14em;
    color: rgba(255, 255, 255, .72);
}

.portada-lema{
    font-size: clamp(.95rem, 2.7vw, 1.3rem);
    text-indent: .14em;   /* mismo motivo que en .portada-nombre */
}

/* LA INVITACION A BAJAR. Es un enlace de verdad -no un adorno-: quien navegue con
   teclado llega a el, lo pulsa y aterriza en la propuesta. */
.portada-baja{
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    /* Bastante separacion: la invitacion tiene que caer cerca del borde de la
       primera pantalla, no pegada al lema. Es lo que la lee como "aqui sigue"
       en vez de como una tercera linea del bloque de marca. */
    margin-top: clamp(2.25rem, 8vh, 4.5rem);
    font-size: .8rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .62);
    text-decoration: none;
    transition: color .2s ease;
}

.portada-baja:hover,
.portada-baja:focus-visible{
    color: var(--marca-acento);
}

/* LA ENTRADA. Sin JavaScript: la CSP prohibe el codigo dentro del HTML y esto no
   merece un fichero aparte. `both` mantiene el estado inicial durante el retardo, que
   es lo que permite escalonar las cinco piezas; sin el, las cinco aparecerian de golpe
   y solo despues se animarian.

   OJO AL ESTADO DE PARTIDA: la opacidad 0 vive DENTRO del fotograma inicial, no en la
   regla del elemento. Si un navegador no llegara a jugar la animacion, la portada se ve
   igual; al reves -opacidad 0 en el elemento y confiar en la animacion para subirla-,
   un fallo la deja en blanco. */
@keyframes portada-entra{
    from{
        opacity: 0;
        transform: translateY(14px);
    }
}

.portada-logo   { animation: portada-entra .65s ease-out both; }
.portada-nombre { animation: portada-entra .65s ease-out .10s both; }
.portada-regla  { animation: portada-entra .65s ease-out .18s both; }
.portada-lema   { animation: portada-entra .65s ease-out .24s both; }
.portada-baja   { animation: portada-entra .65s ease-out .42s both; }

/* El cheuron respira despacio hacia abajo. Cuatro pixeles de viaje: lo justo para que
   el ojo lo pille por el rabillo, no un rebote. */
@keyframes portada-cheuron{
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(4px); }
}

.portada-cheuron{
    animation: portada-cheuron 2.4s ease-in-out infinite;
}

/* Quien pide menos movimiento en su sistema lo pide para todo: la portada se ve entera
   y quieta desde el primer fotograma. Mismo criterio que la barra de descargas y la
   zona de subida destacada, mas arriba en este fichero. */
@media (prefers-reduced-motion: reduce){
    .portada-logo,
    .portada-nombre,
    .portada-regla,
    .portada-lema,
    .portada-baja,
    .portada-cheuron{
        animation: none;
    }
}

/* El desplazamiento suave al pulsar la invitacion (y el "Ver un ejemplo" de al lado)
   SOLO para quien no ha pedido lo contrario.

   No se pone en `html` a secas a proposito: `app.js` ya decide por su cuenta si
   desplaza suave o de golpe (`desplazamiento()`, que mira esta misma preferencia) y
   pasa `behavior: "auto"` cuando toca saltar. Y `auto` significa "lo que diga el CSS":
   una regla global aqui le quitaria el efecto a ese cuidado sin que se notara. */
@media (prefers-reduced-motion: no-preference){
    html{
        scroll-behavior: smooth;
    }
}
