/* =====================================================================
   mobile.css — la capa que adapta la app al teléfono
   =====================================================================

   POR QUÉ EXISTE ESTA HOJA Y POR QUÉ SE CARGA LA ÚLTIMA
   -----------------------------------------------------
   En este proyecto el CSS por página no va en el <head>: cada página y
   cada componente enlaza su hoja dentro del <body> (account.css desde
   /aplicacion, search.css desde Classify, support.css desde NewTicket).
   El desempate por orden, entonces, lo gana el que se enlaza más abajo.

   Eso tenía una consecuencia concreta: search.css ya traía reglas de
   móvil correctas —`.liq-submit { width: 100% }` y compañía— pero
   account.css se carga después con un bloque que unifica TODOS los
   botones de la cuenta a `width: 200px` (y varios con `!important`).
   Resultado en un teléfono: píldoras de 200px centradas en mitad de la
   pantalla, botones cuyo texto no cabe y se sale, y los pulgares de
   valoración convertidos en dos barras que se salían de la tarjeta.

   Por eso esta hoja se enlaza justo antes de `</body>` en
   `src/layouts/Layout.astro`: es la última palabra sobre la geometría
   en pantallas pequeñas. Los `!important` de aquí no son pereza —
   están midiéndose contra los `!important` y las cadenas de `:not()`
   de account.css, que puntúan altísimo.

   ORDEN DE LAS SECCIONES
   ----------------------
     1. Base táctil (tipografía, zonas de toque, zonas seguras)
     2. Armazón de /aplicacion
     3. Botones
     4. Clasificador
     5. Modales como hojas inferiores
     6. Tablas convertidas en tarjetas
     7. Portada, acceso y pie

   Los cortes son 768px (tableta en vertical y menos) y 640px (teléfono).
   Se respetan los que ya usaban account.css (768) y search.css (640).

   TODOS van acotados a `screen`, y eso importa: sin el `screen`, una
   media query se aplica también AL IMPRIMIR. El reporte en PDF se
   maqueta con las reglas de `@media print` de search.css y tiene que
   salir idéntico se pida desde donde se pida; si además le llegaran las
   adaptaciones de teléfono de esta hoja, el mismo documento saldría de
   una forma desde un móvil y de otra desde un escritorio. Acotar a
   `screen` lo hace imposible por construcción, no por vigilancia.
   ===================================================================== */


/* =====================================================================
   1. BASE TÁCTIL
   ===================================================================== */

@media screen and (max-width: 768px) {

    /* iOS hace zoom automático al enfocar un campo cuyo texto mide menos
       de 16px, y después NO vuelve al zoom anterior: el usuario se queda
       con la página ampliada y con scroll lateral que no pidió. Es la
       causa número uno de "la web se descuadra sola al escribir".
       16px exactos es el umbral; no es un capricho estético. */
    input,
    select,
    textarea {
        font-size: 16px;
    }

    /* Los campos de sólo lectura o los que hacen de etiqueta no reciben
       el foco, así que no disparan el zoom y pueden seguir pequeños. */
    input[readonly],
    input[type="checkbox"],
    input[type="radio"] {
        font-size: inherit;
    }

    /* Zona de toque mínima cómoda. Apple recomienda 44x44 puntos; por
       debajo de eso el dedo falla y la app se siente imprecisa. */
    button,
    a.btn,
    [role="button"],
    select,
    input[type="submit"] {
        min-height: 44px;
    }

    /* El scroll dentro de contenedores (modales, listas) con inercia. */
    .modal-container,
    .hmodal-panel,
    .new-ticket-modal-body,
    .nav-links {
        -webkit-overflow-scrolling: touch;
    }

    /* Barra superior siempre a la vista, como la de una app.
       `sticky` y no `fixed`: `fixed` obligaría a compensar el alto del
       header con relleno en cada página, y además crearía un bloque
       contenedor que recortaría el cajón del menú.

       Sólo en móvil. En escritorio el header sigue desplazándose con la
       página: la barra lateral de /aplicacion está calibrada con
       `top: 120px` contando con que la cabecera se va, y fijarla también
       ahí es un cambio de comportamiento que nadie pidió.

       El cajón del menú va por ENCIMA (z-index 1101, en
       Navigation.astro) junto con su velo (1100): cubre la pantalla
       entera, cabecera incluida, y se cierra con su propia X. */
    header {
        position: sticky;
        top: 0;
        z-index: 1000;
        border-bottom: 1px solid rgba(226, 232, 240, 0.9);
    }
}


/* =====================================================================
   2. ARMAZÓN DE /aplicacion
   ===================================================================== */

@media screen and (max-width: 768px) {

    /* Margen lateral de la app. Es UN solo margen, el de aquí: la tarjeta
       exterior se retira justo debajo, así que este valor es la distancia
       real entre cualquier contenido y el borde de la pantalla.

       1.25rem (20px) y no menos: por debajo de eso los campos y las
       tarjetas se leen pegados al canto del teléfono. Es la medida que
       usan iOS y Android para el margen de contenido, y la razón por la
       que una app se ve asentada y una web se ve apretada.

       Va en dos variables, y no escrito a mano en el `padding`, porque
       los bloques que se muestran a sangre (el resultado, el buscador)
       lo cancelan con un margen negativo del MISMO valor. Declarado en
       un solo sitio, los dos números no pueden desincronizarse; escrito
       dos veces, cualquier retoque futuro en uno de ellos deja al otro
       sobresaliendo y devuelve el scroll lateral. Izquierda y derecha
       por separado porque en horizontal la muesca del teléfono sólo
       afecta a un lado. */
    .account-content {
        --margen-izq: max(1.25rem, env(safe-area-inset-left));
        --margen-der: max(1.25rem, env(safe-area-inset-right));
        padding: 0.75rem var(--margen-der) 2rem var(--margen-izq);
        gap: 0;
    }

    /* La tarjeta exterior desaparece en móvil. No es sólo ganar ancho:
       dentro ya hay tarjetas propias (el resultado, las calculadoras,
       los planes) y una tarjeta dentro de otra tarjeta es un marco que
       no significa nada. Sin ella, cada bloque flota sobre el degradado
       de fondo, que es como se ven las apps de iOS y Android. */
    .settings-content {
        padding: 0;
        border: none;
        border-radius: 0;
        background: transparent;
        overflow: visible;
    }

    /* El alto mínimo del 75% de la pantalla dibujaba un rectángulo blanco
       vacío bajo el buscador. Con la tarjeta fuera ya no hace falta
       sostener nada. */
    .settings-content:has(#content-classify:not(.hidden)) {
        min-height: 0;
    }

    /* ── /aplicacion#nueva-clasificacion: fondo blanco a secas ──

       El degradado de `body::before` (blanco → gris muy claro, con los
       halos redondos) es el fondo de la app entera. En la pestaña de
       clasificar no tiene sobre qué lucirse: el buscador y la tarjeta de
       resultado ya van a sangre —los saca del contenedor la sección 4—,
       así que ocupan el ancho completo y son blancos. Lo único que queda
       del degradado son las franjas de arriba, de abajo y los huecos
       entre bloques, y ahí se lee como un gris sucio pegado a un blanco
       puro, no como un fondo.

       Se apaga la CAPA, no se tapa con otra: `body::before` es la propia
       capa del degradado, y dejarla en blanco liso es un repintado menos
       en cada scroll.

       El `:has()` es lo que ata la regla a esta pestaña y no a toda
       /aplicacion: las secciones son hermanas y el JS de AccountMenu les
       pone `.hidden` a todas menos a la activa, así que la única sin
       `.hidden` es la que se está viendo. En Historial, Facturación o
       Reclamos el fondo sigue siendo el degradado, que ahí sí tiene
       márgenes donde verse. Si el navegador no soporta `:has()` la regla
       se descarta entera y queda el degradado de siempre. */
    body:has(#content-classify:not(.hidden))::before {
        background-image: none;
        background-color: #ffffff;
    }

}


/* =====================================================================
   3. BOTONES
   ===================================================================== */

@media screen and (max-width: 640px) {

    /* Regla general: en el teléfono una acción de formulario ocupa el
       ancho disponible. Es lo que hacen los botones de una app nativa y
       lo que evita que un texto largo ("Revisar Impuesto al Lujo") se
       salga de una píldora de 200px.

       `!important` porque enfrente está la cadena de `:not()` de
       account.css, que suma una decena de clases de especificidad. */
    .account-content button,
    .account-content a.btn,
    .account-content a.new-ticket-button,
    .account-content a.plan-cta,
    .account-content a.tickets-link-button,
    .account-content .submit-button,
    .account-content .primary-button,
    .account-content button.primary-button,
    .account-content .search-btn,
    .account-content button.search-btn,
    .account-content .set-password-link-btn,
    .account-content button.set-password-link-btn,
    .account-content .reports-table .btn.btn-primary,
    /* Estos dos llevan selector de ID en account.css (`#update-profile-btn`
       a 250px, `#save-privacy-btn` a 200px). Un ID puntúa por encima de
       cualquier cantidad de clases, así que hay que nombrarlos igual o la
       regla de arriba no les llega. */
    .account-content #update-profile-btn,
    .account-content #save-privacy-btn {
        /* `fit-content` es la clave: el botón mide lo que mide su texto,
           ni más ni menos. Un botón al ancho completo de la pantalla es
           una barra, no un botón, y hace que todas las acciones parezcan
           igual de importantes.

           Los tres límites juntos son los que hacen que nunca corte el
           texto: `fit-content` pide el ancho natural de la etiqueta,
           `max-width: 100%` impide que se salga del contenedor, y
           `white-space: normal` deja que una etiqueta larga se parta en
           dos líneas en vez de desbordarse. Antes account.css fijaba
           200px y "Revisar Impuesto al Lujo" se salía por los lados.

           NO se toca `display` aquí, por mucho que un `display: flex`
           facilitara el centrado con márgenes automáticos: un `display`
           con `!important` en la hoja le gana al `style="display: none"`
           en línea del marcado, y eso DESTAPA todo lo que el JavaScript
           tiene escondido — "Nueva Búsqueda", que sólo aparece con una
           clasificación terminada, salía desde el primer momento.

           El centrado se resuelve sin tocar `display`: `align-self` para
           cuando el contenedor es flex y lo estiraría, y el `text-align`
           del contenedor para cuando es de bloque, que es como ya se
           centraban estos botones antes. */
        width: fit-content !important;
        min-width: min(9rem, 100%) !important;
        max-width: 100% !important;
        white-space: normal !important;
        align-self: center;
        padding-left: 1.5rem !important;
        padding-right: 1.5rem !important;
    }

    /* Excepciones: lo que no es una acción de formulario. Un icono, una
       cruz de cerrar o un pulgar tienen su propia geometría y estirarlos
       al ancho de la pantalla los rompe. */
    .account-content .likes-btn,
    .account-content .file-remove,
    .account-content .action-btn,
    .account-content .modal-close,
    .account-content .new-ticket-modal-close,
    .account-content .hmodal-close,
    .account-content .hmodal-download,
    .account-content .password-toggle,
    .account-content .filter-input-clear,
    .account-content .uso-upgrade-link,
    .account-content .plan-cta-current,
    .account-content button.plan-cta-current,
    .account-content .plan-cta.plan-cta-current,
    .account-content .billing-pagination-btn,
    .account-content .billing-pagination-page {
        width: auto !important;
        max-width: none !important;
        min-width: 0 !important;
    }

    /* Los redondos, con su medida exacta. El `padding: 0` no es
       decorativo: la regla general de arriba les mete 1.5rem por lado y,
       con `box-sizing` sumando el borde, el círculo salía ovalado. */
    .account-content .likes-btn,
    .account-content .action-btn,
    .account-content .file-remove,
    .account-content .modal-close,
    .account-content .new-ticket-modal-close,
    .account-content .hmodal-close,
    .account-content .hmodal-download {
        padding: 0 !important;
        flex: 0 0 auto;
    }

    /* El clip de adjuntos. En el teléfono `.search-input-wrapper` se parte
       en columna, así que el clip deja de ser el sufijo de la barra y se
       queda en una fila propia bajo el input: search.css lo maqueta ahí
       como píldora con etiqueta ("Adjuntar ficha técnica o imagen").

       La regla general de arriba lo desmontaba y ESE era el error de
       maquetación que se veía: `width: fit-content` con `min-width: 9rem`
       lo dejaba a media fila, sin llegar a los bordes del input ni a los
       de los botones, y el candado —posicionado contra la esquina del
       botón— acababa a un dedo del clip, suelto en el aire. Con la fila
       entera la píldora se alinea con el resto de la barra. */
    .account-content .adj-btn {
        width: 100% !important;
        min-width: 0 !important;
        max-width: none !important;
        padding-left: 0.875rem !important;
        padding-right: 0.875rem !important;
        align-self: stretch;
    }

    .account-content .likes-btn {
        width: 48px !important;
        height: 48px;
        min-height: 48px;
    }

    /* Los pulgares del reporte no son un widget suelto: comparten fila con
       "Descargar PDF" y tienen que medir lo mismo que él. Suben los dos un
       punto respecto del escritorio para que el dedo tenga dónde caer. */
    .account-content .likes-feedback--acciones .likes-btn {
        width: 38px !important;
        height: 38px;
        min-height: 38px;
    }

    .account-content .report-btn {
        height: 38px;
    }

    .account-content .file-remove,
    .account-content .modal-close,
    .account-content .new-ticket-modal-close,
    .account-content .hmodal-close,
    .account-content .hmodal-download {
        width: 44px !important;
        height: 44px;
        min-height: 44px;
    }

    /* El aspa de limpiar del buscador del historial va DENTRO del campo,
       en el hueco que le reserva su relleno derecho: no puede medir 44px
       como las demás o se sale de la píldora. 28px es el mayor círculo que
       cabe en un campo de 44px con aire a los lados, y sigue por encima
       del mínimo de 24px de área pulsable. La medida tiene que estar aquí
       —y no sólo en Historial.astro— porque la excepción de más arriba le
       pone `width: auto !important` y ésta se enlaza después. */
    .account-content .filter-input-clear {
        width: 28px !important;
        height: 28px !important;
        min-height: 28px !important;
        padding: 0 !important;
        flex: 0 0 auto;
    }

    /* `.nav-item` del cajón sí quiere el ancho completo, pero con su
       alineación a la izquierda y sin el aspecto de píldora. */
    .account-content .nav-item {
        width: 100% !important;
        max-width: 100% !important;
    }

    /* El icono y la etiqueta de un botón necesitan separación: sin ella
       la "ⓘ" quedaba pegada a la "R" de "Revisar". account.css la anula
       con `gap: 0 !important` para `.search-btn`; aquí se restituye para
       todos, que en móvil ya no compiten por el ancho. */
    .account-content button,
    .account-content a.btn {
        gap: 0.5rem !important;
    }

    /* "Crear Nuevo Reclamo" va alineado a la derecha porque en escritorio
       comparte franja con el título de la sección. En móvil el título ya
       está en su propia línea, así que a la derecha queda descolgado: al
       centro, como el resto de acciones principales de la app. */
    .pre-header {
        justify-content: center;
    }

    /* Las acciones secundarias ("Editar", "Recalcular") viven en la
       cabecera de su tarjeta y no deben pesar como la acción principal:
       al ancho de su etiqueta y alineadas a la derecha, donde el pulgar
       no las confunde con el botón principal de la tarjeta. */
    .account-content .liq-edit-btn {
        width: fit-content !important;
        min-width: 0 !important;
        align-self: flex-end;
        padding-left: 1.125rem !important;
        padding-right: 1.125rem !important;
        justify-content: center;
    }
}


/* =====================================================================
   4. CLASIFICADOR
   ===================================================================== */

@media screen and (max-width: 640px) {

    /* El padding lateral ya lo pone `.account-content`; repetirlo aquí
       era la tercera capa de márgenes anidados. */
    .container {
        padding: 0.5rem 0 1.5rem;
        max-width: 100%;
    }

    /* ── A sangre: el buscador y el resultado son PÁGINA, no tarjetas ──

       Los dos venían como tarjeta blanca con borde y esquinas redondeadas
       flotando sobre el degradado. En una pantalla de teléfono eso son
       marcos dentro de marcos: el borde de la tarjeta, a 20px del borde
       de la pantalla, y el contenido a otros tantos del borde de la
       tarjeta. Se leen como recortes pegados encima de la página en vez
       de como la página misma.

       A sangre, ocupando el ancho completo y sin contorno, cada uno pasa
       a ser una franja de la hoja. El texto no se mueve ni un píxel: el
       margen que pierde el contenedor lo recupera su relleno interior,
       tomado de las mismas variables.

       El margen negativo cancela EXACTAMENTE el relleno de
       `.account-content` porque sale de la misma variable. Si algún día
       cambias el margen lateral, cámbialo allí y esto sigue cuadrando
       solo. */
    .search-input-wrapper,
    .result-card {
        margin-left: calc(var(--margen-izq) * -1);
        margin-right: calc(var(--margen-der) * -1);
        width: auto;
        /* `max-width: none` es imprescindible. Un `max-width: 100%` mide
           el 100% del CONTENEDOR (350px con el margen puesto), y con un
           tope por debajo del ancho que pide la caja los márgenes
           negativos dejan de ensancharla: sólo la corren hacia la
           izquierda. El resultado era una franja blanca desplazada, con
           una banda gris pegada al lado derecho. */
        max-width: none;
        border: none;
        border-radius: 0;
        box-shadow: none;
    }

    /* El relleno interior recoge el margen que se le quitó al
       contenedor, así que el contenido sigue alineado con el resto de la
       app. */
    .search-input-wrapper {
        padding: 0.875rem var(--margen-der) 0.875rem var(--margen-izq);
    }

    .result-header {
        padding: 1rem var(--margen-der) 1rem var(--margen-izq);
        border-radius: 0;
    }

    .result-body {
        padding: 1.25rem var(--margen-der) 1.5rem var(--margen-izq);
    }

    .search-section {
        margin-bottom: 1.75rem;
    }

    .search-header {
        margin-bottom: 1.25rem;
    }

    .search-title {
        font-size: 1.5rem;
        line-height: 1.25;
        letter-spacing: -0.01em;
    }

    .search-subtitle {
        font-size: 0.9375rem;
    }

    /* La píldora de la cuota mide lo que mide su texto, no el ancho de
       la pantalla.

       Estaba en `display: flex`, que es de bloque: se estiraba de borde a
       borde y quedaba como una barra gris cruzando la pantalla. Con
       `inline-flex` vuelve a ser una etiqueta, y el `text-align: center`
       de `.search-header` la centra. `flex-wrap` + `max-width` siguen
       ahí por si la cuota y los créditos no caben en una línea. */
    .uso-indicator {
        display: inline-flex;
        flex-wrap: wrap;
        justify-content: center;
        gap: 0.375rem 0.5rem;
        max-width: 100%;
        padding: 0.375rem 0.75rem;
        font-size: 0.75rem;
    }

    /* "12/50 clasificaciones este mes" no cabe holgado en 390px por mucho
       que se encoja la fuente. En el móvil la palabra sobra: el número ya
       está junto a "este mes" y el contexto es la pantalla de clasificar.
       Queda "12/50 este mes", que es la mitad de ancho. */
    .uso-palabra-larga {
        display: none;
    }

    .uso-bonus {
        font-size: 0.6875rem;
    }

    /* Tarjeta de resultado: menos marco, más contenido. */
    .result-header {
        gap: 0.75rem;
    }

    /* Al apilarse en columna (search.css, 768px) hereda el
       `align-items: center` de la fila y deja la descripción centrada
       mientras todo lo demás de la tarjeta va a la izquierda. */
    .tariff-display {
        align-items: stretch;
        margin-bottom: 1.5rem;
        padding-bottom: 1.5rem;
    }

    .tariff-meta {
        text-align: left;
    }

    /* El código es el dato que la persona copia al DUA: a pantalla
       completa y centrado se lee de un vistazo. */
    .tariff-code-wrapper {
        width: 100%;
        text-align: center;
        padding: 0.875rem 1rem;
    }

    .tariff-code {
        font-size: 1.375rem;
    }

    /* Los botones de esta pantalla traen el icono en `position: absolute;
       left: 1rem` y la etiqueta en un `span` al 100% del ancho. Ese montaje
       da por hecho que el botón es ancho: el icono se ancla a la izquierda
       y el texto se centra en el hueco entero. Al pasar el botón a
       `fit-content` el hueco es justo el del texto y el icono se le monta
       encima.

       Devolviendo el icono al flujo, el `gap` que ya declara cada botón
       vuelve a hacer su trabajo y los dos elementos se separan solos, mida
       lo que mida la etiqueta. */
    .liq-submit svg,
    .liq-edit-btn svg {
        position: static;
        left: auto;
    }

    .liq-submit span {
        width: auto;
    }

    .liq-card,
    .permits-section,
    .suggestions-section {
        margin-top: 1rem;
    }

    /* Los pulgares en una fila que no se desborda. */
    .likes-buttons {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        gap: 0.75rem;
    }

    /* El aviso legal es texto largo: sin este ajuste el bloque del icono
       le robaba casi un tercio del ancho a la lectura. */
    .disclaimer {
        flex-direction: column;
    }

    /* El aviso flotante se pega al borde inferior, sobre la zona segura,
       en vez de a una esquina donde tapa contenido. */
    .feedback-toast {
        left: 1rem;
        right: 1rem;
        bottom: calc(1rem + env(safe-area-inset-bottom));
        text-align: center;
    }
}


/* =====================================================================
   5. MODALES COMO HOJAS INFERIORES
   =====================================================================
   Un diálogo centrado con márgenes a los cuatro lados es un patrón de
   escritorio: en un teléfono deja franjas muertas arriba y abajo y el
   contenido queda estrecho. El patrón nativo es la hoja que sube desde
   abajo, pegada a los bordes, con las esquinas superiores redondeadas.
   Además queda al alcance del pulgar.

   QUÉ MODALES ENTRAN AQUÍ Y CUÁL NO
   ---------------------------------
   Entran los del clasificador (`.modal-overlay` / `.modal-container`):
   la pregunta de desambiguación y la confirmación. Son un paso de un
   flujo, salen y entran varias veces seguidas y lo único que el pulgar
   tiene que alcanzar es una lista de opciones. La hoja les va.

   NO entra el de "Crear Nuevo Reclamo" (`.new-ticket-modal*`). Es un
   formulario que se abre una vez, con un <select> y un <textarea>: al
   enfocar cualquiera de los dos sube el teclado, y una hoja anclada
   abajo se queda con el poco alto que el teclado no ocupa. Centrado
   reparte ese hueco arriba y abajo y el campo enfocado queda a la
   vista. Se queda con el diálogo centrado de `Tickets.astro`.

   Ojo si algún día se quiere meter: los estilos de ese modal viven en el
   <style> de `Tickets.astro` y Astro los acota con un selector de
   atributo (`.new-ticket-modal[data-astro-cid-…]`), que puntúa como dos
   clases. Una regla de esta hoja con una sola clase NO le gana, aunque
   se enlace después. Es lo que pasaba con el asidero de arrastre de más
   abajo, que sí llegaba porque no tenía rival: salía la rayita de
   "arrástrame" sobre un diálogo centrado que no se arrastra. Por eso el
   asidero también se limita a los del clasificador. */

@media screen and (max-width: 640px) {

    .modal-overlay {
        align-items: flex-end;
        padding: 0;
    }

    .modal-overlay .modal-container,
    .modal-container {
        margin: 0;
        width: 100%;
        max-width: 100%;
        border-radius: 20px 20px 0 0;
        /* `dvh` y no `vh`: con la barra de direcciones desplegada, `vh`
           empuja el botón de confirmar fuera de la pantalla. */
        max-height: 92dvh;
        animation: hoja-sube 0.28s cubic-bezier(0.22, 1, 0.36, 1);
    }

    /* El último elemento de la hoja no puede quedar bajo la barra de
       gestos del teléfono. */
    .modal-body {
        padding-bottom: calc(1.5rem + env(safe-area-inset-bottom));
    }

    /* Asidero: la rayita gris que anuncia "esto se arrastra". Es la
       señal que hace que una hoja se lea como hoja y no como un cuadro
       de diálogo recortado. Sólo para las que de verdad son hojas. */
    .modal-container::before {
        content: '';
        display: block;
        width: 36px;
        height: 4px;
        margin: 0.625rem auto 0;
        border-radius: 999px;
        background: #d8dee7;
        flex: 0 0 auto;
    }

    .modal-header {
        padding: 0.875rem 1.25rem 1rem;
    }

    /* ── "Crear Nuevo Reclamo": centrado, pero con aire de teléfono ──

       El diálogo lo maqueta `Tickets.astro`; aquí sólo se ajusta lo que
       en un móvil no puede quedarse en su valor de escritorio. Las dos
       reglas llevan la clase repetida para igualar la especificidad del
       selector acotado de Astro (ver la cabecera de esta sección).

       El relleno del velo respeta la muesca y la barra de gestos, y el
       alto máximo baja de 90dvh a 86dvh: con 90 el modal casi rozaba los
       dos bordes y volvía a leerse como una hoja pegada abajo, que es
       justo lo que no queremos. El `margin: auto` es el que lo mantiene
       centrado aunque el contenido crezca. */
    .new-ticket-modal-overlay.new-ticket-modal-overlay {
        padding: 1rem max(1rem, env(safe-area-inset-right))
                 calc(1rem + env(safe-area-inset-bottom))
                 max(1rem, env(safe-area-inset-left));
    }

    .new-ticket-modal.new-ticket-modal {
        margin: auto;
        max-height: 86dvh;
    }

    /* Las opciones de la pregunta son el control principal del flujo:
       al ancho completo y con altura de toque cómoda. */
    #questionModal .modal-option-btn,
    #confirmModal .confirm-option-card {
        width: 100%;
        min-height: 48px;
    }
}

@keyframes hoja-sube {
    from { transform: translateY(100%); }
    to   { transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .modal-container,
    .new-ticket-modal {
        animation: none !important;
    }
}


/* =====================================================================
   6. TABLAS CONVERTIDAS EN TARJETAS
   =====================================================================
   Una tabla de cuatro o seis columnas no cabe en 390px de ninguna
   manera: o se sale de la pantalla (scroll lateral) o se comprime hasta
   que cada celda parte por letras. La salida es dejar de tratarla como
   tabla en móvil y apilar cada fila como una tarjeta, con la cabecera
   de columna convertida en etiqueta de cada dato (`data-label`).

   Historial ya lo hacía así; esto lleva el mismo patrón a Reclamos
   (support.css) y a Facturación (account.css), que se salían. */

@media screen and (max-width: 768px) {

    /* ── Reclamos ─────────────────────────────────────────────── */

    /* El contenedor es la hoja sobre la que se apoyan las tarjetas, y
       tiene que ser blanco.

       Antes decía `background: transparent`, y su valor de escritorio
       —`background: var(--surface)` en support.css— tampoco pintaba
       nada: `--surface` no la declara ningún `:root` de los que carga
       /aplicacion, y una `var()` sin valor y sin respaldo no cae al
       color anterior, invalida la declaración entera y deja la caja
       transparente. Resultado: el degradado gris de la página asomando
       entre tarjeta y tarjeta, con las tarjetas blancas encima. Blanco
       literal, que es lo que se ve en la pantalla y no depende de que
       alguien declare la variable.

       Va a sangre, como el buscador y el resultado de la sección 4: una
       hoja blanca con 20px de página gris a cada lado sería una tarjeta
       más, y las tarjetas ya están dentro. El relleno recupera por
       dentro el margen que se le quita por fuera, así que el texto no se
       mueve. Los márgenes negativos salen de las mismas variables que el
       relleno de `.account-content`, para que no puedan desincronizarse
       (ver sección 2). */
    .tickets-table-container {
        border: none;
        background: #ffffff;
        border-radius: 0;
        overflow: visible;
        margin-left: calc(var(--margen-izq) * -1);
        margin-right: calc(var(--margen-der) * -1);
        width: auto;
        max-width: none;
        padding: 0.75rem var(--margen-der) 1rem var(--margen-izq);
    }

    .tickets-table,
    .tickets-table thead,
    .tickets-table tbody,
    .tickets-table tr {
        display: block;
        width: 100%;
        max-width: 100%;
    }

    /* La celda NO lleva `width: 100%`: dentro de la tarjeta es un elemento
       más de la fila de metadatos y tiene que ocupar sólo lo suyo. */
    .tickets-table td {
        display: block;
        max-width: 100%;
    }

    .tickets-table {
        min-width: 0;
        border-collapse: separate;
        border-spacing: 0;
    }

    /* Fuera de la vista pero presente para el lector de pantalla: la
       cabecera sigue describiendo la tabla aunque no se dibuje. */
    .tickets-table thead {
        position: absolute;
        left: -9999px;
        width: 1px;
        height: 1px;
        overflow: hidden;
    }

    /* La tarjeta: asunto arriba, y debajo una sola fila con fecha,
       estado y prioridad. Apilar cada dato con su rótulo daba cinco
       renglones por reclamo y hacía falta hacer scroll para ver tres.
       Fecha e insignias se explican solas, así que el rótulo sobra. */
    .tickets-table tbody tr {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 0.5rem 0.75rem;
        border: 1px solid #e2e8f0;
        border-radius: 14px;
        background: #ffffff;
        padding: 0.9rem 1rem;
        margin-bottom: 0.75rem;
        box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
    }

    .tickets-table tbody tr:last-child {
        margin-bottom: 0;
    }

    .tickets-table td {
        flex: 0 0 auto;
        border: none;
        padding: 0;
        text-align: left;
    }

    /* El asunto ocupa la fila entera y hace de titular. */
    .tickets-table td:first-child {
        flex: 1 1 100%;
    }

    /* Gana a `.tickets-table td:last-child { text-align: center }` de
       support.css, pensada para la última columna de una tabla. */
    .tickets-table td:last-child {
        text-align: left;
    }

    .tickets-table .ticket-topico {
        display: block;
        font-weight: 600;
        font-size: 1rem;
        line-height: 1.35;
        color: #0f172a;
    }

    .tickets-table .ticket-id-cell {
        display: block;
        margin-top: 0.15rem;
        font-size: 0.8125rem;
        color: #94a3b8;
    }

    /* La fecha se queda a la izquierda y empuja las insignias al borde
       derecho: la tarjeta se lee como una fila de lista, no como una pila. */
    .tickets-table td[data-label="Fecha"] {
        margin-right: auto;
    }

    /* ── Restos de cuando esto era una tabla con scroll lateral ──

       support.css le pone a la columna «Fecha» `min-width: 160px` (140px
       por debajo de 600px) para que la fecha no se partiera dentro de una
       tabla de 700px de ancho mínimo. Aquí ya no hay tabla ni columnas
       que alinear: ese mínimo se lleva 140 de los ~316px útiles de la
       tarjeta y empuja «PRIORIDAD» a un tercer renglón, que era la fila
       descuadrada que se veía en el teléfono. La celda mide lo que mide
       su fecha.

       Hay que nombrar `:nth-child(2)` igual que allí: `.tickets-table td`
       a secas puntúa por debajo y no le llega. */
    .tickets-table th:nth-child(2),
    .tickets-table td:nth-child(2) {
        min-width: 0;
    }

    /* Y el otro resto: a partir de 600px support.css le da a cada celda
       fondo blanco propio y un borde de 1px, que dentro de la tarjeta
       dibujaba un recuadro alrededor de cada dato. */
    .tickets-table th,
    .tickets-table td {
        background-color: transparent;
    }

    .tickets-table .ticket-date {
        font-size: 0.8125rem;
        color: #64748b;
    }

    /* Fecha + estado + prioridad tienen que caber en el renglón de la
       tarjeta, que en un teléfono de 390px son ~316px útiles. Con el
       relleno de escritorio (0.75rem por lado, 12px de letra) el peor
       caso —«EN PROCESO» junto a «MEDIA»— se pasaba por unos pocos
       píxeles y la prioridad caía sola a un tercer renglón, descolgada
       a la izquierda debajo de la fecha. Un punto menos de letra y un
       cuarto de rem menos de relleno por lado dan el margen que falta
       sin que la insignia deje de leerse. */
    .tickets-table .status-badge,
    .tickets-table .priority-badge {
        padding: 0.25rem 0.5rem;
        font-size: 0.6875rem;
        white-space: nowrap;
    }

    .tickets-table td[colspan] {
        flex: 1 1 100%;
        text-align: center;
    }

    /* ── Facturación ──────────────────────────────────────────── */

    .data-table {
        border: none;
        background: transparent;
        border-radius: 0;
        overflow: visible;
    }

    .data-table table,
    .data-table thead,
    .data-table tbody,
    .data-table tr,
    .data-table td {
        display: block;
        width: 100%;
        max-width: 100%;
    }

    .data-table thead {
        position: absolute;
        left: -9999px;
        width: 1px;
        height: 1px;
        overflow: hidden;
    }

    /* Dos columnas: seis datos apilados uno bajo otro daban una tarjeta de
       más de 300px de alto por cada cobro. Monto/Estado y Tarjeta/Número
       son pares cortos y caben de dos en dos. */
    .data-table tbody tr {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 0.5rem 0.75rem;
        border: 1px solid #e2e8f0;
        border-radius: 14px;
        background: #ffffff;
        padding: 0.85rem 1rem;
        margin-bottom: 0.75rem;
        box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
    }

    /* Fecha y descripción a fila completa: son el titular del cobro. */
    .data-table tbody td:nth-child(1),
    .data-table tbody td:nth-child(2) {
        grid-column: 1 / -1;
    }

    /* La columna Factura cierra la tarjeta con el botón de descarga a lo
       ancho: en media columna el botón quedaba apretado contra el borde. La
       etiqueta "FACTURA" sobra porque el propio botón dice "Descargar". */
    .data-table tbody td[data-label="Factura"] {
        grid-column: 1 / -1;
        padding-top: 0.6rem !important;
    }

    .data-table tbody td[data-label="Factura"]::before {
        content: none;
    }

    .data-table tbody td[data-label="Factura"] .billing-invoice-btn {
        width: 100%;
        justify-content: center;
        padding: 0.6rem 0.75rem;
    }

    .data-table tbody tr:last-child {
        margin-bottom: 0;
    }

    /* Gana a la regla de `@media screen and (max-width: 768px)` de account.css, que
       le devuelve borde y relleno de celda a cada `td`. */
    .data-table td {
        border: none !important;
        padding: 0.3rem 0 !important;
        background: transparent !important;
    }

    .data-table td::before {
        content: attr(data-label);
        display: block;
        margin-bottom: 0.15rem;
        font-size: 0.6875rem;
        font-weight: 700;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: #64748b;
    }

    /* La fecha encabeza la tarjeta de un cobro. */
    .data-table td:first-child {
        font-weight: 600;
        color: #0f172a;
    }

    /* El buscador de facturación pedía 300px fijos de ancho mínimo. */
    .controls-section,
    .search-box {
        width: 100%;
        min-width: 0;
    }
}


/* =====================================================================
   7. PORTADA, ACCESO Y PIE
   ===================================================================== */

@media screen and (max-width: 768px) {

    /* Los halos difuminados de /acceso y /registro (`.auth-aurora`) se
       posicionan con desplazamientos negativos —`right: -140px`— para que
       el degradado sangre por el borde. En un monitor eso queda dentro del
       ancho de la página; en un telefono sobresalía 124px y ensanchaba el
       documento. Recortarlos en el contenedor conserva el efecto y devuelve
       el ancho: `clip` y no `hidden` porque `hidden` convertiría el <main>
       en un contenedor de scroll. */
    .main-wrapper {
        overflow-x: clip;
    }

    /* Las secciones de la portada respetan la muesca en horizontal. */
    .page-index-content > section,
    .auth-page,
    .checkout-page {
        padding-left: max(1rem, env(safe-area-inset-left));
        padding-right: max(1rem, env(safe-area-inset-right));
    }

    /* Ninguna rejilla de la portada debe quedar en dos columnas: a 390px
       una columna de 175px no sostiene ni un título. */
    .features-annotated,
    .banner-container,
    .steps-grid,
    .pricing-grid {
        grid-template-columns: 1fr;
    }

    /* Los botones de /acceso, /registro y /recuperar piden `min-width:
       150px` y `white-space: nowrap`. Puestos de dos en dos con separación,
       más su relleno de 2rem por lado, el par no baja de ~364px: en una
       pantalla de 320 (iPhone SE, Android de gama de entrada) la tarjeta
       del formulario se ensanchaba más que el teléfono. Que puedan
       encogerse y, si no caben, apilarse. */
    /* El botón principal de cada paso al ancho del formulario, como el
       de /acceso, en vez de una píldora centrada: los tres formularios
       de autenticación se ven entonces como el mismo formulario. */
    .email-block-buttons,
    .reg-email-block-buttons {
        align-items: stretch;
    }

    .reg-email-block-buttons > button,
    .reg-email-block-buttons > .next-btn {
        flex-grow: 1;
    }

    .reg-psw-block-buttons {
        flex-wrap: wrap;
    }

    .reg-psw-block-buttons > .reg-submit-button,
    .reg-psw-block-buttons > .reg-back-btn,
    .reg-psw-block-buttons > .next-btn {
        /* `flex-grow` sí, `flex-basis` no: `.email-block-buttons` es una
           columna, y ahí la base de flex es la ALTURA — un `flex: 1 1 9rem`
           convertía el botón de "Recuperar" en un óvalo de 144px de alto. */
        flex-grow: 1;
    }

    .reg-submit-button,
    .reg-back-btn,
    .next-btn {
        min-width: 0;
        max-width: 100%;
        padding-left: 1rem;
        padding-right: 1rem;
        white-space: normal;
    }

    /* El pie con los enlaces apilados y aire suficiente para el dedo. */
    .footer-section a {
        display: inline-block;
        padding: 0.35rem 0;
    }
}

/* Una tarjeta jamás debe sobresalir por el lado: pase lo que pase con
   su contenido, el ancho de la pantalla manda. Es la red de seguridad
   para el contenido que llega del backend (descripciones largas,
   códigos sin espacios) que ninguna media query puede prever. */
@media screen and (max-width: 768px) {
    /* `.result-card` NO entra aquí: va a sangre y su tope lo pone la
       regla de la sección 4. Un `max-width: 100%` la volvería a encerrar
       en el ancho del contenedor. */
    .info-card,
    .stat-card,
    .plan-card,
    .billing-card,
    .export-card,
    .suggestion-card {
        max-width: 100%;
        min-width: 0;
    }

    /* Si algún día vuelve a colarse un bloque más ancho que la pantalla
       (una tabla del backend, un bloque de código), que se desplace
       dentro de su caja y no arrastre la página entera.

       Aquí estuvo `.pdf-table`, y no debía: esa tabla sólo existe dentro
       del reporte impreso. Un `overflow-x: auto` no tiene sentido en papel
       —no hay a dónde desplazarse— y lo único que podía hacer era recortar
       columnas en el PDF. */
    pre {
        max-width: 100%;
        overflow-x: auto;
    }
}

/* =====================================================================
   8. PANTALLAS MUY ESTRECHAS (iPhone SE y gama de entrada, 320-380px)
   =====================================================================
   A 320px de ancho ya no se trata de reordenar: hay piezas con una
   anchura mínima que sencillamente no cabe. */

@media screen and (max-width: 420px) {

    /* La tarjeta de acceso gastaba 2rem de relleno por lado (64px) más
       1rem del contenedor (32px): casi 100px de los 320 disponibles
       antes de pintar el formulario. */
    .main-wrapper {
        padding: 0.75rem;
    }

    .form-panel {
        padding: 1.75rem 1.25rem;
    }
}

@media screen and (max-width: 380px) {

    /* El widget de Turnstile mide 300x65 fijos: no es CSS nuestro, es el
       iframe que inyecta Cloudflare, y por eso ninguna media query lo
       encoge. Con 300px inamovibles dentro, la tarjeta del formulario no
       podía bajar de 364px y se salía de la pantalla.

       Se le da al hueco la medida que sí cabe y se escala el iframe para
       que la ocupe. Escalar el contenido y NO sólo el contenedor es lo
       que importa: `transform` no cambia la caja de maquetación, así que
       sin fijar el ancho del hueco el desbordamiento seguiría ahí aunque
       se viera más pequeño. El área pulsable se escala con la
       transformación, así que el reto sigue siendo usable. */
    #turnstile-widget {
        width: 250px;
        height: 55px;
        overflow: hidden;
    }

    #turnstile-widget > * {
        transform: scale(0.8333);
        transform-origin: top left;
    }
}
