/*
 * landing.css — pantallas públicas de Gestión Fácil: landing e inicio de sesión.
 *
 * Se carga SOLO en esas dos pantallas (ver templates/base_publico.html). La
 * app autenticada no paga por este peso, y así app.css se mantiene bajo el
 * techo de líneas que fija docs/marca-frontend.md.
 *
 * Depende de app.css: los tokens, la tipografía, el anillo de foco y los
 * componentes base (.boton, .campo, .badge) salen de ahí y no se redefinen.
 * Acá van solo las piezas que no existen dentro de la app.
 *
 * Territorio visual: campo blanco, tinta azul acero, filetes finos, y dos
 * losas de azul hondo que abren y cierran la página. El crema deja de ser el
 * campo (llenaba la pantalla y apagaba el azul) y queda donde rinde: como
 * tinta clara encima del azul. Tema claro único y a propósito: la marca no
 * tiene paleta oscura definida, así que no se inventa una acá.
 */

:root {
    /* Filete sobre blanco: gris frío de la misma familia del texto. Es
     * decorativo (no es borde de control), así que su contraste no cae bajo
     * el criterio 1.4.11. */
    --color-filete: #e3e7ed;

    /* Azul hondo: el campo de la portada, del cierre y del pie. Es el azul
     * acero de la marca bajado dos pasos, no un negro: así la página entra y
     * sale por el mismo color y el azul manda de punta a punta. Crema encima
     * da 13,4:1. */
    --color-azul-hondo: #0f2537;
    --color-filete-oscuro: rgba(242, 237, 228, 0.18);

    --ancho-publico: 1120px;
}

.publico {
    background: var(--color-superficie);
}

/* El único movimiento que no depende de GSAP: la respuesta al dedo y al
 * cursor. Va acá y no en app.css porque la app no lo necesita. */
@media (prefers-reduced-motion: no-preference) {
    .publico .boton {
        transition: background-color 0.18s ease, transform 0.12s ease;
    }
    .publico .boton:active { transform: translateY(1px); }
}

.publico__contenedor {
    width: 100%;
    max-width: var(--ancho-publico);
    margin: 0 auto;
    padding: 0 var(--espacio);
}

/* --- Barra pública --------------------------------------------------------
 * Una sola línea en escritorio, alto contenido. Acá sí va el lockup completo
 * (marca-frontend.md §5.5 lo reserva para login, landing y exportes). */

/* Pegada arriba: la acción principal ("Entrar") queda a un clic en cualquier
 * punto del scroll. El filete va siempre puesto y no atado a un gatillo de
 * scroll: sin JS la barra igual se despega del contenido que pasa debajo. */
.barra-publica {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--color-superficie);
    border-bottom: 1px solid var(--color-filete);
}

.barra-publica__fila {
    display: flex;
    align-items: center;
    gap: var(--espacio);
    min-height: 68px;
}

.barra-publica__lockup { display: block; width: 150px; height: auto; }

.barra-publica__nav {
    display: none;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
}

.barra-publica__enlace {
    display: inline-flex;
    align-items: center;
    min-height: var(--toque-minimo);
    padding: 0 0.75rem;
    color: var(--color-texto);
    text-decoration: none;
}

.barra-publica__enlace:hover { text-decoration: underline; }

.barra-publica__acceso { margin-left: auto; }

@media (min-width: 52rem) {
    .barra-publica__nav { display: flex; }
    /* Con el menú visible, es el menú el que empuja hacia la derecha; el
     * botón solo se separa de él. La regla vive dentro de la media query
     * porque el <nav> sigue en el DOM cuando está oculto, y afuera le
     * quitaba el `margin-left: auto` al botón también en celular. */
    .barra-publica__acceso { margin-left: 0.5rem; }
}

/* --- Portada ---------------------------------------------------------------
 *
 * Losa de azul hondo a sangre, con la promesa apoyada abajo a la izquierda y
 * una trama de puntos moviéndose detrás. La trama es un campo de plasma
 * tramado (dither ordenado de Bayer) que dibuja `landing.js` sobre un canvas
 * de baja resolución: son dos colores y un patrón de puntos, no un degradado,
 * así que se lee como impresión y no como fondo de plantilla.
 *
 * El texto va sobre un velo que oscurece el lado izquierdo: la trama tiene
 * zonas claras y sin velo el titular perdería contraste al pasar una. */

.portada {
    position: relative;
    isolation: isolate;
    display: flex;
    /* El contenido ocupa la losa entera y reparte el aire adentro (ver
     * `.portada .publico__contenedor`), en vez de apoyarse en un borde. */
    align-items: stretch;
    min-height: 60dvh;
    /* Simétrico arriba y abajo: mientras el bloque estuvo apoyado en el borde
     * inferior, el relleno de abajo era menor a propósito. Centrado, esa
     * diferencia se lee como un centrado mal hecho. */
    padding: 3.5rem 0;
    background: var(--color-azul-hondo);
    color: var(--color-crema);
    overflow: hidden;
}

/* La misma trama abre y cierra la página: portada arriba, cierre abajo. */
.trama {
    position: absolute;
    inset: 0;
    z-index: -2;
    width: 100%;
    height: 100%;
    /* El canvas mide una fracción del alto real: cada punto suyo se sirve
     * como un cuadrado nítido, sin la interpolación que lo convertiría en un
     * degradado borroso. */
    image-rendering: pixelated;
}

.portada::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(
        100deg,
        rgba(15, 37, 55, 0.94) 0%,
        rgba(15, 37, 55, 0.86) 42%,
        rgba(15, 37, 55, 0.35) 100%
    );
}

/* Un solo bloque centrado en la losa: titular, bajada, carrusel y botones
 * separados por un ritmo fijo. Antes cada tramo se estiraba con `margin-top:
 * auto` y en pantalla alta el aire sobrante abría zanjas entre las partes;
 * el aire que sobra ahora queda arriba y abajo del bloque, no adentro. */
.portada .publico__contenedor {
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.portada__titulo {
    margin: 0;
    font-size: clamp(2.1rem, 5.6vw, 3.5rem);
    font-weight: 600;
    line-height: 1.06;
    letter-spacing: -0.02em;
    max-width: 17ch;
}

/* Cada línea es su propia ventana: el reveal sube el texto desde abajo del
 * borde. El relleno inferior es la holgura de las colas de la "g"; sin él,
 * `overflow: hidden` las corta. */
.portada__linea {
    display: block;
    overflow: hidden;
    padding-bottom: 0.14em;
    margin-bottom: -0.14em;
}

.portada__linea > span { display: block; }

.portada__bajada {
    margin: var(--espacio) 0 0;
    font-size: 1.125rem;
    color: rgba(242, 237, 228, 0.85);
    max-width: 44ch;
}

/* Los tres puntos del hero: viñeta de guion, no de disco. El disco es el
 * default del navegador y se lee como lista de sistema; el guion es el mismo
 * signo que usa la prosa de la página. */
.portada__puntos {
    margin: var(--espacio) 0 0;
    padding: 0;
    max-width: 46ch;
    list-style: none;
    color: rgba(242, 237, 228, 0.9);
}

.portada__puntos li {
    position: relative;
    padding-left: 1.1rem;
    margin-bottom: 0.4rem;
}

.portada__puntos li::before {
    content: "—";
    position: absolute;
    left: 0;
    color: rgba(242, 237, 228, 0.55);
}

/* Modo carrusel: las viñetas ocupan la MISMA celda y se turnan, entrando y
 * saliendo de lado. La clase la pone `landing.js`, nunca el CSS: sin JS (o con
 * movimiento reducido) la lista se ve completa y apilada, como cualquier lista.
 * Al compartir celda, la fila mide lo que la viñeta más alta, así que el bloque
 * no cambia de alto al cambiar de mensaje y los botones de abajo no se mueven.
 *
 * Acá el mensaje sube de rango: más grande que la bajada, en crema pleno y
 * centrado en su propia caja. Es la única promesa que se está leyendo en ese
 * segundo, así que deja de ser una viñeta de lista y pasa a ser la línea que
 * compite con el titular. Por eso también se le saca el guion: una lista
 * centrada con marca de viñeta se lee como un error de maqueta.
 *
 * `overflow: hidden` es lo que convierte el desplazamiento en carrusel: la
 * viñeta que sale se corta contra el borde en vez de irse difuminando por
 * encima del texto vecino. El relleno inferior es la holgura de las colas de la
 * "g", que ese mismo recorte se comería. */
.portada__puntos--rotando {
    display: grid;
    overflow: hidden;
    /* Ancho para que cada promesa entre en UNA línea en escritorio: la más
     * larga son 68 caracteres. En pantalla angosta el tope no alcanza a
     * mandar, la promesa parte en dos y `text-wrap: balance` la equilibra. */
    max-width: 66ch;
    padding-bottom: 0.16em;
    /* Centrado en el ancho de la página, no bajo la columna de texto: el
     * bloque es su propia franja y por eso se despega del titular y de la
     * bajada, que son de alineación izquierda. Es a propósito — el carrusel
     * es lo único que se mueve en la portada y tiene su propio eje. */
    margin-inline: auto;
    margin-bottom: -0.16em;
    /* Separación fija de la bajada: el carrusel es la línea que sigue, no un
     * bloque aparte al fondo de la losa. */
    padding-top: var(--espacio-lg);
    text-align: center;
    /* Sin esto la primera línea llena el ancho y solo la segunda se ve
     * centrada, que es exactamente cómo se ve una sangría mal puesta.
     * Equilibrando las líneas, el centrado se lee como decisión. */
    text-wrap: balance;
    font-size: clamp(1.2rem, 2.7vw, 1.65rem);
    font-weight: 500;
    line-height: 1.28;
    letter-spacing: -0.01em;
    color: var(--color-crema);
}

.portada__puntos--rotando li {
    grid-area: 1 / 1;
    padding-left: 0;
    margin-bottom: 0;
}

/* Va después del guion a propósito: las dos reglas pesan lo mismo, así que
 * la que manda es la última escrita. Si esto sube, vuelve a aparecer el
 * guion en el carrusel. */
.portada__puntos--rotando li::before { content: none; }

/* El microcopy es el pie de los botones: se centra con ellos, no con el
 * titular. */
.portada__microcopy {
    margin: 0.75rem 0 0;
    text-align: center;
    font-size: 0.85rem;
    color: rgba(242, 237, 228, 0.7);
}

/* Los dos botones, centrados bajo el carrusel y del MISMO ancho aunque digan
 * cosas de distinto largo. La reja lo hace sin números a mano: `fit-content`
 * mide la caja por el botón más ancho y `1fr` reparte ese ancho en partes
 * iguales, así que "Entrar" queda tan ancho como "Pedir una demo" y sigue
 * calzando si mañana cambia el texto. Con flex habría que fijar un
 * `min-width` inventado que se rompe al primer cambio de copy. */
.portada__acciones {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: var(--espacio-sm);
    width: fit-content;
    margin: 0 auto;
    padding-top: var(--espacio-lg);
}

/* Bajo ~26rem los dos botones lado a lado se salen del contenedor. Apilados y
 * a todo el ancho quedan además más fáciles de tocar con el pulgar. */
@media (max-width: 26rem) {
    .portada__acciones {
        grid-auto-flow: row;
        width: 100%;
    }
}

@media (min-width: 56rem) {
    /* Alta, pero no tanto como para que el bloque centrado quede nadando: con
     * el contenido ya junto, 82dvh dejaba media losa vacía. */
    .portada { min-height: 72dvh; padding: 5rem 0; }
}

/* --- Sección genérica ------------------------------------------------------ */

/* La barra pegada mide 68px y tapaba la primera línea de la sección a la que
 * apuntaba el enlace del menú. Va sobre todas las anclas, no sobre una: el
 * problema es la barra, no la sección. */
main > section[id] { scroll-margin-top: 4.5rem; }

.seccion {
    padding: 3rem 0;
    border-top: 1px solid var(--color-filete);
}

/* Campo gris. Existe para una sola cosa: cortar la corrida de secciones
 * blancas seguidas sin usar tinta, que en el cuerpo de la página está
 * reservada a la banda del medio. Al tener fondo propio no necesita el filete
 * de arriba — el cambio de campo ya es el corte. */
.seccion--campo {
    background: var(--color-fondo);
    border-top: 0;
}

.seccion__titulo {
    margin: 0 0 var(--espacio);
    font-size: clamp(1.4rem, 3vw, 1.9rem);
    font-weight: 600;
    line-height: 1.15;
    color: var(--color-primario);
    max-width: 22ch;
}

.seccion__cuerpo { max-width: 62ch; }

.seccion__cuerpo p { margin: 0 0 var(--espacio); }

.rotulo {
    display: block;
    margin: 0 0 var(--espacio-sm);
    font-family: var(--fuente-mono);
    font-size: 0.75rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--color-texto-suave);
}

/* --- Problema: dos columnas de prosa -------------------------------------- */

@media (min-width: 56rem) {
    .problema__cuerpo {
        max-width: none;
        columns: 2;
        column-gap: 3rem;
    }
    .problema__cuerpo p { break-inside: avoid; }
}

/* --- Oficios: la fotografía del ICP multi-rubro --------------------------- */

.oficios {
    display: grid;
    gap: var(--espacio);
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    margin: 0;
    padding: 0;
    list-style: none;
}

.oficio { margin: 0; }

.oficio__foto {
    display: block;
    width: 100%;
    height: 13rem;
    object-fit: cover;
    border-radius: var(--radio);
}

.oficio__nombre {
    margin: 0.6rem 0 0.2rem;
    font-size: 1rem;
    font-weight: 600;
    color: var(--color-primario);
}

.oficio__detalle { margin: 0; color: var(--color-texto-suave); font-size: 0.95rem; }

/* --- Pasos ---------------------------------------------------------------- */

.pasos { margin: 0; padding: 0; list-style: none; counter-reset: paso; }

.paso {
    display: grid;
    gap: 0.2rem var(--espacio);
    padding: var(--espacio) 0;
    border-top: 1px solid var(--color-filete);
    counter-increment: paso;
}

.paso:first-child { border-top: 0; }

.paso::before {
    content: counter(paso, decimal-leading-zero);
    font-family: var(--fuente-mono);
    font-size: 1.6rem;
    line-height: 1;
    color: var(--color-primario);
}

.paso__titulo { margin: 0; font-size: 1.15rem; font-weight: 600; }

.paso__texto { margin: 0.3rem 0 0; color: var(--color-texto); max-width: 60ch; }

@media (min-width: 44rem) {
    .paso { grid-template-columns: 4rem 1fr; align-items: start; }
    .paso::before { padding-top: 0.15rem; }
}

/* --- El panel del recorrido -----------------------------------------------
 * Un solo dibujo al lado de los cuatro pasos, que cambia de escena según el
 * paso que se está leyendo. Cuatro demos animándose a la vez compiten con el
 * texto y ninguna se mira entera; así siempre hay una sola cosa en
 * movimiento, y es la que corresponde.
 *
 * El panel va PRIMERO en el marcado. En celular eso lo deja pegado arriba con
 * los pasos corriendo por debajo, que es la única forma de que el dibujo y su
 * texto se vean juntos en una sola columna. En escritorio el CSS lo manda a la
 * segunda columna y ahí queda fijo mientras el recorrido pasa por delante. */

.pasos__reja { position: relative; display: grid; gap: var(--espacio); }

.pasos__panel {
    position: sticky;
    /* La barra pública también es sticky y mide 68 px: por debajo de eso el
     * panel se metería detrás de ella. */
    top: 4.75rem;
    z-index: 1;
    display: grid;
    /* El marco es el mismo de `.plan`: un filete y el radio del sistema, nada
     * más. Sin él las escenas flotan sueltas en el blanco de la página y no se
     * leen como una pantalla, que es lo que son.
     *
     * Por dentro va blanco y no el gris de `.plan`: los dibujos están hechos de
     * cajas con filete gris, y sobre un campo gris esas cajas se pierden. Acá
     * el marco es solo la línea. */
    padding: var(--espacio);
    background: var(--color-superficie);
    border: 1px solid var(--color-filete);
    border-radius: var(--radio);
}

/* El hilo solo tiene sentido con los pasos AL LADO del panel. En celular están
 * debajo, no al lado, y no hay canaleta por donde tenderlo. */
.pasos__hilo { display: none; }

@media (min-width: 64rem) {
    /* El texto se corta en 60ch (~500 px) y el número ocupa 4rem: con el
     * contenedor de 1120 px quedan ~300 px libres, que es lo que pide el
     * panel. Bajo este ancho no caben lado a lado sin ahogar el párrafo.
     *
     * La canaleta es de 3rem y no de 2: por ahí pasa el hilo, y en 32 px no
     * caben el punto, la curva y la flecha sin quedar amontonados. Los 16 px
     * extra salen de la holgura de la columna de texto, que ya está topada en
     * 60ch y no reflowea. */
    .pasos__reja {
        grid-template-columns: minmax(0, 1fr) 20rem;
        gap: 3rem;
        align-items: start;
    }

    .pasos__panel {
        /* Repetido a propósito: NO poner `position: relative` acá. Pisa el
         * `sticky` de la regla base —misma especificidad, gana esta— y el panel
         * se va con el scroll sin que nada avise. */
        position: sticky;
        grid-column: 2;
        grid-row: 1;
        /* Centrado en la ventana, no pegado arriba. El paso activo es el que
         * cruza la mitad de la pantalla (ver `mandarPanel`), así que centrando
         * el panel los dos quedan a la misma altura y el hilo entre ellos sale
         * casi horizontal. Pegado arriba, en una ventana alta el paso quedaba
         * 200 px más abajo y el hilo era una horquilla.
         *
         * El 6.2rem es la mitad del alto del panel: 1rem de relleno arriba y
         * abajo más el dibujo, que a 288 px de ancho mide 165. */
        top: calc(50vh - 6.2rem);
    }

    .pasos { grid-column: 1; grid-row: 1; }

    /* Cubre la reja entera y no estorba: las coordenadas del hilo se miden
     * contra esta caja. `overflow: visible` porque el punto de arranque queda
     * justo en el borde y con recorte se vería a medias. */
    .pasos__hilo {
        position: absolute;
        inset: 0;
        display: block;
        width: 100%;
        height: 100%;
        overflow: visible;
        pointer-events: none;
    }

    .hilo__curva,
    .hilo__punta {
        fill: none;
        stroke: var(--color-primario);
        stroke-width: 1.4;
        stroke-linecap: butt;
        stroke-linejoin: miter;
    }

    /* La curva va más apagada que sus dos extremos: lo que tiene que leerse es
     * de dónde sale y adónde llega, no el trazo del medio. */
    .hilo__curva { opacity: 0.4; }
    .hilo__punto { fill: var(--color-primario); }
}

/* El hilo es decorativo y su gracia es seguir el scroll cuadro a cuadro. Sin
 * eso apuntaría al lugar equivocado apenas te muevas, así que con movimiento
 * reducido no se dibuja: el panel cambiando de escena ya dice lo mismo. */
@media (prefers-reduced-motion: reduce) {
    .pasos__hilo { display: none; }
}

/* Las cuatro escenas viven apiladas en la misma celda y se turnan por
 * opacidad: nada entra ni sale del layout, así que el cambio no mueve un solo
 * píxel de la página. La transición la hace el CSS y no GSAP para que el panel
 * siga funcionando aunque el JS no cargue. */
.escena {
    grid-area: 1 / 1;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.45s ease;
}

.escena--activa { opacity: 1; }

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

.escena svg { display: block; width: 100%; height: auto; }

/* Dibujo plano, dos tintas y nada más: los mismos trazos de los íconos de los
 * módulos, para que se lea como la misma mano. Sin relleno de color, sin
 * sombra, sin degradado (marca-identidad.md prohíbe la estética de IA).
 *
 * Las cajas y los filetes son la estructura y van en gris. Lo que se pinta de
 * azul es lo que el usuario mandó o lo que el sistema resolvió: esa es toda la
 * jerarquía que estas escenas necesitan.
 *
 * Las medidas van en unidades del viewBox, no en px: el SVG escala con la
 * columna y el dibujo no se recalcula nunca. */
.d-caja { fill: none; stroke: var(--color-filete); stroke-width: 1.2; }
.d-tinta { fill: var(--color-primario); }
/* Los filetes que barren son <rect>, no <line>: `transform-box: fill-box` sobre
 * una línea sin caja propia no tiene origen del que agarrarse, y el barrido
 * salía desde cualquier parte. */
.d-regla {
    fill: var(--color-filete);
    transform-box: fill-box;
    transform-origin: left center;
}
/* Los tildes se dibujan de un trazo (stroke-dashoffset), no aparecen: es el
 * gesto de "quedó hecho" y es lo único que se traza en toda la página. */
.d-marca,
.d-tilde {
    fill: none;
    stroke: var(--color-primario);
    stroke-width: 1.6;
    stroke-linecap: square;
    stroke-linejoin: miter;
}
.d-tilde { stroke-width: 1.3; }
.e3-punto { fill: var(--color-texto-suave); }

/* Todo el texto de las escenas va en mono: es dato de pantalla, no prosa. */
.escena text { font-family: var(--fuente-mono); }
.d-texto { fill: var(--color-texto); font-size: 10px; }
.d-suave { fill: var(--color-texto-suave); font-size: 9px; }
.d-clara { fill: var(--color-crema); font-size: 10px; }
.d-cifra { fill: var(--color-crema); font-size: 13px; }
.d-cuenta { fill: var(--color-primario); font-size: 15px; }
/* Las versalitas van escritas en mayúscula en el marcado: `text-transform` no
 * es de fiar en <text> de SVG. */
.d-rotulo { fill: var(--color-texto-suave); font-size: 8px; letter-spacing: 0.08em; }

/* El pie del recorrido va en gris suave y sin número: no es un paso más, es
 * quién sostiene los cuatro de arriba. */
.pasos__pie {
    margin: var(--espacio) 0 0;
    max-width: 60ch;
    color: var(--color-texto-suave);
    font-size: 0.95rem;
}

/* --- Consultas: lo que le preguntas al negocio ----------------------------
 *
 * Las preguntas van en mono y con un filete a la izquierda: es la marca de
 * cita de la página, y sirve para que se lean como palabras del cliente y no
 * como una lista de funciones. Sin comillas dibujadas: el signo de pregunta
 * ya dice que es habla. */

.consultas {
    display: grid;
    gap: var(--espacio-sm);
    margin: 0 0 var(--espacio);
    padding: 0;
    max-width: 60ch;
    list-style: none;
}

.consulta {
    padding-left: var(--espacio);
    border-left: 2px solid var(--color-primario);
    font-family: var(--fuente-mono);
    font-size: 0.95rem;
    line-height: 1.45;
    color: var(--color-primario);
}

/* --- Banda: el trabajo que se hace solo -------------------------------------
 *
 * La única losa de tinta en el medio de la página. Entre la portada y el
 * cierre había siete secciones blancas seguidas con el mismo padding y el
 * mismo filete: nada pesaba más que lo demás. Esta banda es el clímax, y por
 * eso es la única que cambia de campo.
 *
 * El campo NO es la trama de la portada. Esa abre y cierra la página, y con
 * una tercera aparición dejaba de leerse como un par de tapas para pasar a
 * ser, simplemente, el fondo azul. Acá van tres manchas difusas paseándose.
 *
 * Cada trabajo son dos turnos separados por un filete. El filete es el que
 * convierte dos párrafos apilados en un intercambio; sin él se leen como una
 * lista más. */

.banda {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding: 4rem 0;
    background: var(--color-azul-hondo);
    color: var(--color-crema);
}

/* El campo del efecto. Se pasa del borde para que las manchas puedan salirse
 * sin que aparezca el canto de ninguna; `overflow: hidden` en `.banda` las
 * recorta.
 *
 * Va con prefijo de bloque y no como `.campo` a secas: `.campo` ya es, en
 * app.css, el envoltorio de cada campo de formulario. Mientras se llamó igual,
 * todo formulario servido con landing.css (el login entero y el de demo de
 * esta misma página) veía sus campos absolutos y fuera de pantalla. */
.banda__campo {
    position: absolute;
    inset: -25%;
    z-index: -1;
    pointer-events: none;
}

/* Una mancha difusa. Sin `filter: blur()` a propósito: el degradado radial YA
 * es la difusión, y así el navegador no vuelve a desenfocar la capa en cada
 * cuadro —que es lo que ahoga a un Android de gama media, que es el aparato
 * del que mira esto—. `landing.js` les anima solo `x` e `y`.
 *
 * `will-change` va puesto y no se saca: mientras la banda está en pantalla la
 * deriva no termina nunca, así que las tres capas se quedan promovidas todo
 * ese rato a propósito. */
/* `lighten` frena el apilamiento de los cruces, pero NO lo elimina: con alfa
 * menor que 1 la fórmula sigue siendo (1-α)·fondo + α·max(fondo, mancha), así
 * que dos manchas encimadas igual acercan el resultado a su color. Frena, no
 * tapa. Por eso el techo del campo se mide sobre la página andando y no se
 * calcula sobre una mancha sola —esa cuenta daba #1a3b55 y lo que de verdad
 * aparece es #2f4d68—. */
.mancha {
    position: absolute;
    border-radius: 50%;
    mix-blend-mode: lighten;
    will-change: transform;
}

/* La mancha nace redonda y `landing.js` la deforma: escala distinta en cada
 * eje más un giro lento. Que la deformación viva en el `transform` y no en el
 * `border-radius` no es un detalle de estilo —animar el radio repinta la capa
 * entera en cada cuadro, y son manchas de 650 px—. El alfa no cambia con la
 * deformación, así que el techo de contraste de más abajo se mantiene aunque
 * la mancha crezca. */

/* Dos cosas están calibradas acá y conviene no tocarlas por separado.
 *
 * El TAMAÑO y la CAÍDA hacen que el movimiento se vea. Con manchas de 46-54%
 * y caída hasta el 72% eran lavados de 770 px sin un borde que se notara
 * cruzar: se movían de verdad y aun así la banda se leía como fondo estático.
 * Achicadas a 26-34% y con la caída cortada en el 62%, la mancha tiene un
 * frente reconocible, y un frente que se traslada sí se ve.
 *
 * El ALFA es contraste, no estética, y su techo lo fija el texto MÁS TENUE que
 * le pase por encima. Estos valores NO se calcularon sobre una mancha suelta:
 * esa cuenta daba #1a3b55, y midiendo la página andando el punto más claro que
 * de verdad aparece es #2f4d68, porque los cruces apilan. Contra ese punto
 * real, el texto de la banda tuvo que subir de 0,62 a 0,72 (4,01:1 → 4,81:1).
 *
 * Regla, entonces: el techo del campo se mide sobre la página corriendo, no en
 * una hoja de cálculo. Y si se quiere un campo más marcado, el orden es primero
 * el texto y después el campo, nunca el campo solo — aunque la palanca barata
 * sigue siendo el RECORRIDO y la VELOCIDAD, que no cuestan contraste. */
.mancha--a {
    top: 2%;
    left: 4%;
    width: 30%;
    aspect-ratio: 1;
    background: radial-gradient(circle,
        rgba(47, 100, 141, 0.35) 0%,
        rgba(47, 100, 141, 0.18) 38%,
        transparent 62%);
}

.mancha--b {
    top: 26%;
    right: 2%;
    width: 34%;
    aspect-ratio: 1;
    background: radial-gradient(circle,
        rgba(63, 124, 168, 0.32) 0%,
        rgba(47, 100, 141, 0.16) 40%,
        transparent 64%);
}

.mancha--c {
    bottom: 0;
    left: 38%;
    width: 26%;
    aspect-ratio: 1;
    background: radial-gradient(circle,
        rgba(38, 86, 124, 0.34) 0%,
        rgba(38, 86, 124, 0.17) 38%,
        transparent 62%);
}

.banda__rotulo { color: rgba(242, 237, 228, 0.72); }

.banda__titulo {
    margin: 0 0 var(--espacio-lg);
    font-size: clamp(1.4rem, 3vw, 1.9rem);
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: -0.01em;
    max-width: 20ch;
}

.trabajos {
    display: grid;
    gap: var(--espacio-lg) 2.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.trabajo__nombre {
    margin: 0 0 var(--espacio-sm);
    font-family: var(--fuente-mono);
    font-size: 0.78rem;
    font-weight: 400;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(242, 237, 228, 0.72);
}

.turno { margin: 0; max-width: 46ch; }

/* "Tú" y "Queda hecho" son la etiqueta del turno, no adorno: son las que
 * dicen de quién es cada mitad cuando el filete no se ve (movimiento
 * reducido, lector de pantalla, impresión).
 *
 * El alfa es 0,62 y no menos: el peor fondo posible acá no es el azul hondo
 * sino un punto de la trama bajo el velo de 0,86, que sube a #132e43. Contra
 * ese, 0,55 daba 4,49:1 —bajo el mínimo, y a 12,8px no califica como texto
 * grande—; 0,62 da 5,36:1. */
.turno__quien {
    display: block;
    margin-bottom: 0.1rem;
    font-size: 0.8rem;
    font-weight: 600;
    color: rgba(242, 237, 228, 0.72);
}

.turno--tu { color: rgba(242, 237, 228, 0.88); }
.turno--hecho { color: var(--color-crema); }

/* El relevo. Nace entero y `landing.js` lo dibuja de izquierda a derecha si
 * hay movimiento; sin JS queda puesto, que es el estado correcto. */
.relevo {
    height: 1px;
    margin: 0.85rem 0;
    background: rgba(242, 237, 228, 0.32);
    transform-origin: left center;
}

.banda__pie {
    margin: var(--espacio-lg) 0 0;
    max-width: 60ch;
    color: rgba(242, 237, 228, 0.72);
    font-size: 0.95rem;
}

@media (min-width: 44rem) {
    .trabajos { grid-template-columns: 1fr 1fr; }
}

/* --- Módulos: qué trae, en su propia sección ------------------------------
 *
 * Nacieron adentro de la tarjeta de precio y salieron de ahí: son la respuesta
 * a "¿qué me van a instalar?", y adentro del precio llegaban a los 4.000 px,
 * cuando el lector ya está calculando plata. Ahora van pegados al paso que los
 * promete ("quedan puestos los módulos que necesitas") y en el precio queda
 * solo la línea de que no se cobran aparte.
 *
 * Cada uno es un ícono, un nombre y una línea de qué resuelve. El filete de
 * arriba los separa sin encerrarlos en tarjetas: ocho cajas con borde en una
 * sección gris serían ocho cajas dentro de otra caja. */

.planes__intro {
    margin: 0 0 var(--espacio);
    max-width: 62ch;
    color: var(--color-texto);
}

.modulos__pie {
    margin: var(--espacio-lg) 0 0;
    max-width: 62ch;
    color: var(--color-texto-suave);
    font-size: 0.95rem;
}

.modulos {
    display: grid;
    gap: var(--espacio);
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    margin: 0;
    padding: 0;
    list-style: none;
}

.modulo {
    padding-top: var(--espacio-sm);
    border-top: 1px solid var(--color-filete);
    color: var(--color-texto-suave);
    font-size: 0.95rem;
}

.modulo__nombre {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin-bottom: 0.15rem;
    color: var(--color-primario);
    font-size: 1rem;
    font-weight: 600;
}

/* Un solo lugar fija el trazo de los ocho dibujos: así ninguno puede quedar
 * más grueso o más redondeado que sus vecinos, que es como un set dibujado a
 * mano se desarma. `flex-shrink: 0` porque "Cuenta corriente" envuelve en
 * pantalla angosta y sin esto el cuadrado se aplasta. */
.modulo__icono {
    flex-shrink: 0;
    width: 1.35rem;
    height: 1.35rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: square;
    stroke-linejoin: miter;
}

/* --- Planes --------------------------------------------------------------- */

.planes {
    display: grid;
    gap: var(--espacio);
    align-items: start;   /* cada plan mide lo que necesita, sin relleno vacío */
    margin: 0 0 var(--espacio);
}

.plan {
    padding: var(--espacio-lg) var(--espacio);
    /* Gris apenas, no blanco: sobre el campo blanco de la página un plan en
     * blanco desaparecería y quedaría solo el borde. */
    background: var(--color-fondo);
    border: 1px solid var(--color-filete);
    border-radius: var(--radio);
}

.plan--destacado { border-color: var(--color-primario); }

.plan__nombre { margin: 0; font-size: 1.05rem; font-weight: 600; }

.plan__precio {
    margin: 0.4rem 0 0;
    font-family: var(--fuente-mono);
    font-variant-numeric: tabular-nums;
    font-size: 1.9rem;
    line-height: 1.1;
    color: var(--color-primario);
}

.plan__periodo { font-family: var(--fuente-ui); font-size: 0.9rem; color: var(--color-texto-suave); }

.plan__incluye { margin: var(--espacio) 0 0; padding: 0; list-style: none; }

.plan__incluye li {
    padding: 0.4rem 0;
    border-top: 1px solid var(--color-filete);
    font-size: 0.95rem;
}

/* La garantía va con filete al costado, no dentro de una tarjeta: es una
 * afirmación de la página, no un tercer plan que haya que comparar. */
.planes__garantia {
    margin: var(--espacio) 0;
    padding-left: var(--espacio);
    border-left: 3px solid var(--color-primario);
    max-width: 62ch;
}

.planes__nota { margin: 0; color: var(--color-texto-suave); font-size: 0.95rem; max-width: 62ch; }

@media (min-width: 48rem) {
    .planes { grid-template-columns: 1fr 1fr; }
}

/* --- Quién está detrás ----------------------------------------------------- */

.autor__reja { display: grid; gap: var(--espacio-lg); align-items: start; }

/* El título manda sobre las dos columnas y la foto empieza debajo de él. */
.autor__titulo { grid-column: 1 / -1; margin-bottom: 0; }

/* Mismo radio que las fotos de oficio: es una foto duotono, no un dibujo suelto. */
/* 13rem, no 9: el retrato es de cabeza y torso, y a 9rem la cara quedaba chica. */
.autor__sello { display: block; width: 13rem; height: auto; border-radius: var(--radio); }

.autor__texto { max-width: 60ch; }

.autor__texto p { margin: 0 0 var(--espacio); }

.autor__firma { color: var(--color-texto-suave); }

@media (min-width: 48rem) {
    /* El bloque va centrado en la página, no pegado al margen izquierdo: la
     * columna de texto mide 60ch y contra un contenedor de 1120px dejaba un
     * vacío grande a la derecha que hacía ver la sección desbalanceada.
     * `justify-content` centra el par de columnas dentro de la reja. */
    .autor__reja {
        grid-template-columns: 13rem minmax(0, 60ch);
        justify-content: center;
        gap: 2.5rem;
    }
}

/* --- Preguntas ------------------------------------------------------------- */

.preguntas { max-width: 68ch; }

.pregunta {
    border-top: 1px solid var(--color-filete);
}

.pregunta:last-child { border-bottom: 1px solid var(--color-filete); }

.pregunta__titulo {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--espacio);
    min-height: var(--toque-minimo);
    padding: var(--espacio-sm) 0;
    font-weight: 600;
    cursor: pointer;
    list-style: none;
}

.pregunta__titulo::-webkit-details-marker { display: none; }

/* El signo es decorativo: el estado abierto/cerrado ya lo anuncia <details>
 * a los lectores de pantalla. */
.pregunta__titulo::after {
    content: "+";
    font-family: var(--fuente-mono);
    color: var(--color-primario);
}

.pregunta[open] .pregunta__titulo::after { content: "\2212"; }

.pregunta__respuesta { margin: 0 0 var(--espacio); color: var(--color-texto); }

/* --- Cierre y pie: la losa de azul hondo -----------------------------------
 *
 * El cierre y el pie son UN solo bloque oscuro, no dos franjas de colores
 * distintos, y es el mismo azul hondo de la portada: la página abre y cierra
 * con el mismo campo, y en el medio el blanco deja respirar el contenido.
 *
 * El bloque de cierre va centrado a propósito: es el único momento de la
 * página donde el mensaje ES la composición, y centrarlo evita el vacío a la
 * derecha que dejaba la versión a una columna. */

.losa {
    background: var(--color-azul-hondo);
    color: var(--color-crema);
}

/* El cierre repite la trama de la portada: la página termina en el mismo
 * campo con que empezó. Acá el velo es parejo y no diagonal, porque el texto
 * va centrado y ocupa todo el ancho. */
.cierre {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding: 5rem 0 4rem;
    text-align: center;
}

/* La trama del cierre se apaga hacia abajo: sin esto el canvas termina en un
 * corte recto justo encima del pie y se ve el borde del rectángulo. */
.cierre .trama {
    -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
}

.cierre::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: rgba(15, 37, 55, 0.82);
}

.cierre__titulo {
    margin: 0 auto;
    font-size: clamp(1.75rem, 4vw, 2.6rem);
    font-weight: 600;
    line-height: 1.12;
    letter-spacing: -0.015em;
    max-width: 18ch;
}

.cierre__texto {
    margin: var(--espacio) auto 0;
    max-width: 52ch;
    color: rgba(242, 237, 228, 0.82);
}

.cierre__acciones {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--espacio-sm);
    margin-top: var(--espacio-lg);
}

/* La caja del formulario es blanca sobre el azul: los controles de app.css
 * (.campo, .boton--primario) están hechos para fondo claro, y reteñirlos para
 * que sobrevivan encima de la losa sería mantener dos sistemas de formulario
 * por una sola pantalla. */
.cierre__caja {
    max-width: 26rem;
    margin: var(--espacio-lg) auto 0;
    padding: var(--espacio-lg);
    background: var(--color-superficie);
    border-radius: var(--radio);
    color: var(--color-texto);
    text-align: left;
}

.cierre__enviar { width: 100%; margin-top: var(--espacio-sm); }

.cierre__microcopy {
    margin: var(--espacio-sm) 0 0;
    font-size: 0.85rem;
    color: var(--color-texto-suave);
    text-align: center;
}

.cierre__gracias { margin: 0; text-align: center; font-weight: 600; }

.cierre__riesgo {
    margin: var(--espacio-lg) auto 0;
    max-width: 52ch;
    color: rgba(242, 237, 228, 0.72);
    font-size: 0.95rem;
}

.cierre__alterno {
    margin: var(--espacio) 0 0;
    font-size: 0.9rem;
    color: rgba(242, 237, 228, 0.72);
}

.cierre__alterno a { color: var(--color-crema); }

/* Trampa de robots: fuera de la pantalla, no `display: none`. Varios robots
 * saltan lo que está oculto con display, pero llenan lo que existe. */
.trampa {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* Sobre azul el botón primario se invierte: campo crema, texto azul hondo.
 * Contraste 13,4:1. */
.boton--invertido { background: var(--color-crema); color: var(--color-azul-hondo); }
.boton--invertido:hover { background: var(--color-superficie); }

.boton--contorno-claro {
    background: transparent;
    color: var(--color-crema);
    border-color: rgba(242, 237, 228, 0.42);
}
.boton--contorno-claro:hover { background: rgba(242, 237, 228, 0.1); }

/* --- Pie ------------------------------------------------------------------- */

.pie { padding: var(--espacio-lg) 0 2.5rem; }

.pie__reja {
    display: grid;
    gap: var(--espacio-lg);
    padding-top: var(--espacio-lg);
    border-top: 1px solid var(--color-filete-oscuro);
}

.pie__lockup { display: block; width: 140px; height: auto; }

.pie__lema {
    margin: var(--espacio-sm) 0 0;
    color: rgba(242, 237, 228, 0.72);
    font-size: 0.95rem;
}

.pie__nav {
    display: grid;
    gap: 0.1rem;
    align-content: start;
}

.pie__enlace {
    display: inline-flex;
    align-items: center;
    min-height: var(--toque-minimo);
    color: var(--color-crema);
    text-decoration: none;
}

.pie__enlace:hover { text-decoration: underline; }

.pie__base {
    display: flex;
    flex-wrap: wrap;
    gap: var(--espacio-sm) var(--espacio);
    margin-top: var(--espacio-lg);
    padding-top: var(--espacio);
    border-top: 1px solid var(--color-filete-oscuro);
}

.pie__nota {
    margin: 0;
    font-family: var(--fuente-mono);
    font-size: 0.8rem;
    color: rgba(242, 237, 228, 0.6);
}

.pie__nota + .pie__nota { margin-left: auto; }

@media (min-width: 44rem) {
    .pie__reja { grid-template-columns: 1fr auto; align-items: start; }
    .pie__nav { grid-auto-flow: column; gap: var(--espacio); }
}

/* --- Acceso (login) --------------------------------------------------------
 * Mismo par que la landing: campo blanco para el formulario y losa de azul
 * hondo para la marca, así entrar no se siente como salir del sitio. La marca
 * va en lockup completo, no en badge. */

.acceso {
    display: grid;
    min-height: 100dvh;
}

.acceso__marca {
    display: none;
    flex-direction: column;
    justify-content: space-between;
    padding: var(--espacio-lg);
    background: var(--color-azul-hondo);
    color: var(--color-crema);
    /* La losa lleva la trama de la portada. `isolation` encierra los z-index
     * negativos del canvas y del velo: sin esto se irían detrás del fondo de
     * la página en vez de quedarse detrás del texto de este panel. */
    position: relative;
    isolation: isolate;
    overflow: hidden;
}

/* El mismo velo diagonal de la portada, y por la misma razón: el texto vive
 * pegado al borde izquierdo (la frase corta a 18ch) y el velo lo protege ahí,
 * mientras destapa la trama hacia la derecha. Un velo plano deja el panel
 * parejo y la trama se lee como ruido en vez de como impresión. */
.acceso__marca::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(
        100deg,
        rgba(15, 37, 55, 0.94) 0%,
        rgba(15, 37, 55, 0.86) 42%,
        rgba(15, 37, 55, 0.35) 100%
    );
}

.acceso__lockup { display: block; width: 190px; height: auto; }

.acceso__frase {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 600;
    line-height: 1.2;
    max-width: 18ch;
}

.acceso__pie { margin: 0; font-family: var(--fuente-mono); font-size: 0.8rem; opacity: 0.85; }

.acceso__panel {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: var(--espacio-lg) var(--espacio);
}

.acceso__caja { width: 100%; max-width: 24rem; margin: 0 auto; }

.acceso__lockup-movil { display: block; width: 150px; height: auto; margin-bottom: var(--espacio-lg); }

.acceso__titulo { margin: 0 0 var(--espacio-sm); font-size: 1.4rem; }

.acceso__volver { display: inline-block; margin-top: var(--espacio-lg); font-size: 0.95rem; }

.acceso__enviar { width: 100%; }

@media (min-width: 56rem) {
    .acceso { grid-template-columns: 0.9fr 1.1fr; }
    .acceso__marca { display: flex; }
    .acceso__lockup-movil { display: none; }
}
