/* ============================================================================
   Crecer e Innovar — capa web
   ----------------------------------------------------------------------------
   app.css es el sistema aprobado y se copia del APK sin tocar. Aquí va sólo lo
   que una app táctil de 390px de ancho no necesita y un navegador sí:

     1. foco visible por teclado
     2. un respaldo para los WebViews sin backdrop-filter
     3. hover — la app sólo tiene :active
     4. el shell de escritorio a partir de 768px

   Se carga DESPUÉS de app.css. Nada de esto vuelve al APK.
   ========================================================================== */

/* ── 1. Base de navegador ─────────────────────────────────────────────────── */

/* La app se maneja con el dedo y no tiene foco de teclado. Un sitio sí, y sin
   esto la navegación con Tab es invisible. */
:focus-visible {
  outline: 2px solid var(--brand-500);
  outline-offset: 2px;
  border-radius: 6px;
}
:focus:not(:focus-visible) { outline: none; }

::selection { background: var(--brand-100); color: var(--navy-800); }

/* El atributo `hidden` del HTML lo pisa cualquier regla de autor que fije
   `display`, y varias lo hacen: `.lista-op a` y `.drawer__item` son `display:flex`.
   Por eso `<a data-salir hidden>` («Cerrar sesión») seguía a la vista. La app
   nunca lo notó —sus filas de sesión sólo aparecen con sesión—; en la web el
   invitado sí llega a esas pantallas. Con esto `hidden` vuelve a esconder de
   verdad, y con él todo el patrón data-salir / data-si-anonimo / data-solo-sesion
   que reparte `pintarSesion()`. */
[hidden] { display: none !important; }

/* Un formulario que no ocupa lugar (B-18). «Cerrar sesión» y «Explorar como
   invitado» eran enlaces, y un GET que cambia estado lo dispara cualquiera desde
   afuera con un `<img src>`. Ahora son botones dentro de un `<form method="post">`
   —que funciona también con el JavaScript apagado—, y para que el formulario no
   agregue una caja donde antes había un enlace suelto, se disuelve: sus hijos
   quedan exactamente donde estaba el `<a>`, así que el `:last-child` de la fila y
   los `display: flex` de alrededor siguen resolviendo igual. Es el mismo recurso
   que ya usan `.header__buscar-fila` y `.compra__que`. */
.form-fila { display: contents; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* Reemplaza a .hide-scrollbar del viejo style.css. */
.sin-scroll { scrollbar-width: none; -ms-overflow-style: none; }
.sin-scroll::-webkit-scrollbar { display: none; }

/* Los WebViews de Android 8 son comunes en Venezuela y no implementan
   backdrop-filter: en vez de desenfocar, dejan pasar el contenido y el header
   queda como un borrón ilegible. Sin translucidez se ve peor, pero se lee. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .header, .nav, .barra-compra { background: var(--fondo); }
  .fav-btn { background: var(--fondo); }
}

/* El botón de icono, al mínimo que un dedo necesita.

   `app.css` lo declara en 42px literales y es intocable, así que la medida se
   corrige aquí — que es lo que manda, por ir después. El valor no se escribe:
   sale de `--icon-btn`, que emite `app/src/tema/medidas.ts`, así que la app y la
   web no pueden separarse. Eran 42 y aparecían 124 veces en el recuento de
   objetivos tocables chicos; con 44 desaparecen todas. */
.icon-btn { width: var(--icon-btn); height: var(--icon-btn); }

/* El chip de filtro, por el mismo motivo y por el mismo camino: `app.css` lo
   declara en 36px y el valor manda desde `medidas.ts`. Con diez categorías el
   filtro tiene diez chips en una fila que se desliza, y ahí es donde más se
   falla el toque. */
.chip { height: var(--chip-h); border-radius: calc(var(--chip-h) / 2); }

/* Las categorías, de a cinco también en el teléfono.
   `app.css` pide cuatro, y con diez eso deja una tercera fila de dos. Cinco las
   reparte en dos filas parejas, y a 390 son 70px por baldosa — el mismo ancho
   que ya tiene la fila que se desliza en la portada. */
.cats { grid-template-columns: repeat(5, 1fr); }

/* ── 2. Hover ─────────────────────────────────────────────────────────────── */
/* Espeja el feedback :active que app.css ya define para el dedo. Va detrás de
   pointer:fine para que un teléfono no herede estados pegajosos al tocar. */

@media (hover: hover) and (pointer: fine) {
  .btn:hover            { filter: brightness(1.06); }
  .btn--primario:hover  { box-shadow: var(--sombra-cta); }
  .btn[disabled]:hover  { filter: none; }
  .icon-btn:hover       { background: var(--superficie-2); }
  .cat:hover            { background: var(--superficie-2); transform: translateY(-2px); }
  .chip:hover           { border-color: var(--borde-fuerte); }
  .seccion__link:hover  { color: var(--brand-700); }
  .drawer__item:hover   { background: var(--superficie); }
  .vendedor-fila:hover  { background: var(--superficie-2); }
  .fav-btn:hover        { transform: scale(1.08); }
  .nav-web a:hover      { color: var(--brand-600); background: var(--superficie); }
  .linea__foto img      { transition: transform var(--transicion); }
  .linea:hover .linea__foto img { transform: scale(1.05); }
}

/* Cursor: la app no tiene puntero, así que app.css no lo declara en ningún
   lado. Aquí todo lo clicable tiene que anunciarse. */
.btn, .icon-btn, .chip, .cat, .fav-btn, .nav__item,
.drawer__item, .seccion__link, .tarjeta, .vendedor-fila,
.stepper button, .opcion { cursor: pointer; }
.btn[disabled] { cursor: not-allowed; }

/* ── 2a. Listas de opciones ───────────────────────────────────────────────── */
/* En el APK las filas de .lista-op son <button> porque todo navega por router.
   Aquí son enlaces de verdad —se pueden abrir en otra pestaña, se pueden
   copiar— así que la misma regla tiene que alcanzar a los <a>. */

.lista-op a {
  display: flex; align-items: center; gap: 14px; width: 100%;
  padding: 15px 17px; text-align: left; font-size: 14px; font-weight: 600;
  border-bottom: 1px solid var(--borde); letter-spacing: -.015em;
  color: var(--texto);
  transition: background var(--transicion);
}
.lista-op a:last-child { border-bottom: 0; }
.lista-op a:active { background: var(--superficie); }
.lista-op a .ico:first-child { color: var(--brand-500); }
@media (hover: hover) and (pointer: fine) {
  .lista-op a:hover, .lista-op button:hover { background: var(--superficie); }
}

/* ── 2b. Drawer del carrito ───────────────────────────────────────────────── */
/* En el APK el carrito es una pantalla completa (#/carrito), así que app.css
   sólo define el drawer izquierdo del menú. En la web conviene que agregar al
   carrito no te saque de la página donde estabas comprando, así que el mismo
   componente se ancla a la derecha. */

.drawer--der {
  left: auto; right: 0;
  transform: translateX(100%);
}
.drawer--der.abierto { transform: none; }

/* ── 3. Qué se ve en cada tamaño ──────────────────────────────────────────── */

/* Los enlaces de escritorio no existen en móvil: ahí manda la barra inferior. */
.nav-web { display: none; }

/* ── 3a. La cabecera, en dos filas que se vuelven una ─────────────────────────
   Había DOS buscadores: la lupa de la cabecera y el campo de la página de
   resultados, dos puertas a lo mismo. El campo sube a la cabecera y la lupa se
   va (ADR 0006).

   El marcado es uno solo. En móvil las dos filas caen una debajo de la otra; a
   partir de 768 las dos se vuelven `display: contents` y sus hijos reaparecen
   en la fila única de escritorio. Es el criterio de `.detalle-web`: el DOM va
   en orden de móvil y la retícula ancha coloca a mano.

   Y el orden de la fila ancha sale del DOM tal cual, sin recolocar nada: los
   enlaces de escritorio viven entre el buscador y el carrito, que es donde
   caen bien en las dos formas. */

/* Acotado a `.header--principal`, que es la única cabecera de dos filas. Una
   cabecera de una sola fila —volver, título, carrito— no tiene nada que apilar,
   y sin el acote `flex-direction: column` le pondría los tres elementos uno
   debajo del otro. */
.header--principal .header__fila {
  height: auto;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
}
.header__marca-fila {
  display: flex; align-items: center; gap: 10px;
  height: var(--header-h);
  overflow: hidden;
}
.header__buscar-fila {
  display: flex; align-items: center; gap: 6px;
  padding-bottom: 9px;
}
.header__buscar-fila .buscador { flex: 1; min-width: 0; }

/* El pliegue: al bajar queda sólo la fila de buscar. El buscador y el carrito
   son lo que se usa mientras recorres el catálogo; el lockup se mira al llegar
   y no otra vez. Se va hacia arriba mientras se pliega en vez de sólo
   achicarse, así parece que se mete detrás de la fila de abajo y no que se
   desinfla. Lo enciende `ui.js`. */
.header--principal .header__marca-fila {
  transition: height var(--transicion), opacity var(--transicion), transform var(--transicion);
}
.header--principal.es-plegada .header__marca-fila {
  height: 0;
  opacity: 0;
  transform: translateY(-10px);
}

/* El filete de abajo existe para decir «hay algo debajo pasando por detrás», y
   con la página en el tope no dice nada: dibuja una línea contra el vacío. Es
   la misma regla que `Cabecera.tsx` aplica en la app. Sólo en la principal —una
   cabecera interna no se pliega y su filete siempre tiene algo que separar. */
.header--principal {
  border-bottom-color: transparent;
  transition: border-color var(--transicion);
}
.header--principal.es-plegada { border-bottom-color: var(--borde); }

@media (prefers-reduced-motion: reduce) {
  .header--principal,
  .header--principal .header__marca-fila { transition: none; }
}

/* ── 3b. La portada la manda el catálogo ─────────────────────────────────────
   Las seis decisiones del ADR 0006, bajadas de la app. Van aquí y no en
   app.css por el mismo motivo que el Programa Crecer: app.css es copia
   intocable del APK (ADR 0001) y lo que nació en React Native se escribe donde
   la web es la web.

   Dos de las seis son quitar algo que app.css pone. Se desarma desde aquí,
   igual que `.pago-caja > .opcion` le desarma a `.opcion` el marco que trae. */

/* ── El ritmo sale de una escala ──────────────────────────────────────────── */
/* Había un solo `margin-top: 30px` entre todas las secciones, así que las ocho
   pesaban lo mismo y nada guiaba el ojo: con un único valor no hay jerarquía
   posible — la jerarquía es la diferencia entre dos separaciones, no una
   separación. Los cuatro escalones los emite la app en `tokens.css`. */

.seccion { margin-top: var(--espacio-seccion); }

/* La entrada —promoción y Programa Crecer— se lee junta, así que va junta y
   apretada: un escalón menos que el de las secciones. */
.inicio-entrada {
  margin-top: 16px;
  display: flex; flex-direction: column;
  gap: var(--espacio-bloque);
}

/* El banner de la portada, que se desliza de a uno con la punta del siguiente
   asomando. Estaba como estilo suelto en el marcado, y de ahí no se lo puede
   cambiar por anchura.

   **2,2:1 y no el 16:9 de app.css.** El 16:9 es la proporción del video, no la
   de un aviso: se elige por costumbre. Costaba 194 px de la primera pantalla a
   390, y la foto no dice nada más por ser más alta —el texto vive abajo a la
   izquierda de todos modos—. A 606 de ancho la diferencia es 341 contra 275.
   Gemelo de `Banner.tsx`, que lleva el mismo número. */
.banner--entrada { flex: 0 0 88%; max-width: 520px; aspect-ratio: 2.2; }

/* Un cambio de registro, de comprar a leer. */
.seccion--respaldo { margin-top: var(--espacio-corte); }
.inicio-firma { margin: var(--espacio-pieza) 0 0; padding-bottom: 8px; }

/* ── Se fue la decoración que no decía nada ───────────────────────────────── */

/* El filete degradado entre el título de sección y su enlace, cinco veces en la
   misma pantalla. Lo que conseguía era que las cinco secciones se vieran
   idénticas. Lo reemplaza una bajada, que sí cambia con el contenido. */
.seccion__cab::after { content: none; }
.seccion__cab { align-items: flex-start; }
.seccion__que { flex: 1; min-width: 0; }
.seccion__bajada {
  margin: 2px 0 0;
  font-size: 12.5px; font-weight: 500; line-height: 1.35;
  letter-spacing: -.01em; color: var(--texto-3);
}
.seccion__link { padding-top: 3px; }

/* El arco de acento alrededor de cada disco de categoría. Era el guiño al
   isotipo, pero repetido ocho veces con ocho colores distintos dejaba de ser un
   guiño: quedaba como ruido de color en el bloque que menos lo necesita. */
.cat__ico::after { content: none; }

/* ── Las categorías, a una fila que se desliza ────────────────────────────── */
/* La rejilla de cuatro por dos se llevaba 207 px de la primera pantalla para
   navegación que se toca una vez por sesión. En fila ocupa 95 y la quinta queda
   cortada, que es cómo se dice «hay más» sin escribirlo.

   620px es el mismo corte que usa la app (`columnas(width) > 2`): de ahí para
   arriba vuelve a ser rejilla y manda la regla de app.css sin tocarla.

   Y va acotado a la portada. **La rejilla completa sigue existiendo en la
   pantalla de búsqueda**, que es adonde va alguien que de verdad quiere elegir
   por categoría — eso es parte de la decisión, no un detalle: la fila se puede
   permitir mostrar cuatro y media justamente porque las ocho están a un toque
   en otro lado. */

@media (max-width: 619.98px) {
  .pantalla--inicio .cats {
    display: flex; gap: 9px;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    margin-inline: calc(var(--margen) * -1);
    padding-inline: var(--margen);
  }
  .pantalla--inicio .cats::-webkit-scrollbar { display: none; }
  /* 74 de ancho: entran cuatro y media a 393 px, así que la quinta se ve
     cortada y el pulgar sabe que puede seguir. */
  .pantalla--inicio .cat { flex: 0 0 74px; scroll-snap-align: start; }
}

/* ── «Ofertas del día» se apoya en una superficie propia ──────────────────── */
/* Antes las cinco secciones eran título + carrusel sobre el mismo fondo:
   ninguna podía pesar más que otra aunque una sea la oferta del día y otra un
   listado cualquiera.

   El sangrado se hace con el margen negativo del contenedor, igual que
   `.carrusel`, y NO con `100vw`: `100vw` incluye la barra de desplazamiento y
   dispararía la invariante de `npm run vista` que dice que nada se desborda a
   lo ancho.

   Y va sobre la superficie, no sobre el fondo. Iba en `--fondo`, que es el
   mismo blanco de la página: quedaban dos filetes separando el blanco del
   blanco, o sea nada — medido sobre la página pintada, la banda era invisible,
   que es justo lo contrario de lo que tenía que conseguir. En gris las tarjetas
   blancas resaltan solas y la banda se lee como otra superficie sin pedir una
   sombra. Gemela del estilo `destacada` de la pantalla de inicio de la app. */
.seccion--destacada {
  margin-inline: calc(var(--margen) * -1);
  padding: var(--espacio-bloque) var(--margen);
  background: var(--superficie);
  border-block: 1px solid var(--borde);
}

/* ── La marca de AeroCuota ────────────────────────────────────────────────────
   Gemelas de `MarcaAeroCuota.tsx` y `LockupAeroCuota.tsx`. La geometría del
   símbolo está generada desde la app; aquí sólo va cómo se apoya.

   La pastilla blanca es para fondo oscuro: la hoja derecha es `--aero-tinta` y
   sobre el degradado de la submarca desaparece. Repintarla de blanco
   convertiría un símbolo de dos colores en uno de uno, que es lo que lo hace
   reconocible — así que se lo mete en una pastilla, como en su propio favicon.
   Su radio, 14, es `--r-md`: la coincidencia es real, AeroCuota usa el mismo
   radio y la misma tipografía que nosotros (ADR 0008). */

.marca-aero { flex: none; display: inline-grid; place-items: center; }
.marca-aero--pastilla { border-radius: var(--r-md); background: var(--fondo); }

.lockup-aero { font-weight: 800; letter-spacing: -.02em; color: var(--aero-tinta); }
.lockup-aero span { color: var(--aero); }
.lockup-aero--oscuro { color: var(--sobre-marca); }
.lockup-aero--oscuro span { color: var(--aero-suave); }

/* ── AeroCuota en la portada ──────────────────────────────────────────────────
   Gemela de `TarjetaAeroCuota.tsx`, donde está escrito el porqué largo. En
   corto: era una franja de 63 px en azul pálido, y el cupo es un número que a
   11,5 px dentro de una frase no se lee. A 30 px con su riel debajo es un
   saldo. Cuesta 88 px más y los paga la franja de aliados, que baja debajo de
   «Ofertas del día» (ADR 0009). */

.aero-tarjeta {
  position: relative; overflow: hidden;
  display: block; padding: 15px;
  border-radius: var(--r-lg);
  background: var(--aerocuota);
  text-decoration: none;
  transition: transform var(--presion);
}
.aero-tarjeta:active { transform: scale(.985); }
/* El anillo, recortado por el `overflow: hidden`. */
.aero-tarjeta::before {
  content: ''; position: absolute; right: -48px; top: -54px;
  width: 210px; height: 210px; border-radius: 50%;
  border: 26px solid rgba(255, 255, 255, .07);
  pointer-events: none;
}
.aero-tarjeta__marca {
  position: relative;
  display: flex; align-items: center; gap: 9px;
}
/* La punta va a la derecha del todo en la fila de la marca. */
.aero-tarjeta__marca .aero-tarjeta__ver { margin-left: auto; }
/* Los dos datos en la misma fila, empujados a los extremos: el usado manda
   sobre el riel que tiene debajo, y el disponible cierra por la derecha.
   Alineados por la base y no por la caja: con 30 px y 14 px en el mismo
   renglón, centrarlos deja el chico flotando a media altura del grande. */
.aero-tarjeta__cupo {
  position: relative;
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  margin-top: 8px;
}
.aero-tarjeta__usado { display: flex; align-items: baseline; gap: 6px; }
.aero-tarjeta__cifra {
  font-size: 30px; line-height: 34px; font-weight: 800; letter-spacing: -.03em;
  color: var(--sobre-marca);
}
.aero-tarjeta__coletilla { font-size: 13px; font-weight: 600; color: rgba(255, 255, 255, .66); }
/* El disponible **no** va en el gris lavado del resto de la letra chica: es el
   dato que trae al comprador hasta aquí, y si hay que elegir entre que se vea y
   que no compita, tiene que verse. */
.aero-tarjeta__de {
  min-width: 0;
  font-size: 14px; font-weight: 700; letter-spacing: -.01em;
  color: rgba(255, 255, 255, .92);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.aero-tarjeta__riel { position: relative; margin-top: 10px; }
.aero-tarjeta__pie {
  position: relative;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 9px;
}
/* En la angosta la punta vive en la fila de la marca; en la acostada, en el
   pie. Se emite en los dos sitios y aquí se apaga la que no toca — mover un
   solo nodo entre dos esquinas pedía una rejilla con áreas nombradas para
   ahorrar cuatro palabras de marcado. */
.aero-tarjeta__pie .aero-tarjeta__ver { display: none; }
.aero-tarjeta__promesa {
  min-width: 0;
  font-size: 12.5px; font-weight: 600; letter-spacing: -.015em;
  color: rgba(255, 255, 255, .88);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.aero-tarjeta__ver {
  flex: none; display: inline-flex; align-items: center; gap: 3px;
  font-size: 12.5px; font-weight: 700; letter-spacing: -.015em;
  color: var(--sobre-marca);
}

/* A partir de tablet se acuesta en una fila, que es lo que la franja ya hacía a
   1280. Un bloque de 151 px de alto en una pantalla ancha es un cartel. */
@media (min-width: 760px) {
  .aero-tarjeta {
    display: flex; align-items: center; gap: 16px;
    padding: 13px 16px;
  }
  .aero-tarjeta__cupo, .aero-tarjeta__pie { margin-top: 0; }
  .aero-tarjeta__riel { flex: 1; min-width: 120px; margin-top: 0; }
  .aero-tarjeta__cifra { font-size: 22px; line-height: 26px; }
  /* Acostada, el bloque del cupo no se estira: los dos datos van juntos y el
     riel es el que se lleva el ancho sobrante. */
  .aero-tarjeta__cupo { justify-content: flex-start; }
  .aero-tarjeta__coletilla, .aero-tarjeta__de { font-size: 12.5px; }
  /* Acostada, la punta cierra la fila por la derecha y la marca la deja ir. */
  .aero-tarjeta__marca .aero-tarjeta__ver { display: none; }
  .aero-tarjeta__pie .aero-tarjeta__ver { display: inline-flex; }
}

/* ── La tarjeta se ordena por jerarquía ───────────────────────────────────── */
/* Iba título → precio → Bs → reputación → una banda verde de ENVÍO GRATIS.
   Cinco datos apilados con pesos parecidos: una lista, no una jerarquía.

   Ahora manda el precio y debajo va la cuota. La foto ya dice qué es la cosa,
   así que el título baja un escalón; lo que la foto no puede decir es cuánto
   cuesta y de a cuánto queda.

   El `gap` uniforme de app.css se apaga: con una sola separación entre las
   cinco piezas del cuerpo volvíamos al mismo problema en chico. */

.tarjeta__cuerpo { padding: 10px 12px 12px; gap: 0; }

/* En el azul de la marca y no en verde: la cuota es algo que la app ofrece
   hacer, no una confirmación de algo que ya pasó. El renglón queda reservado
   aunque esté vacío —sólo se promete si entra en el cupo—, o las tarjetas de
   una grilla terminan desparejas. */
.tarjeta__cuota { height: 17px; display: flex; align-items: center; }
.tarjeta__cuota span {
  font-size: 11.5px; font-weight: 700; letter-spacing: -.005em;
  color: var(--marca);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.tarjeta__titulo { margin-top: 5px; }
.tarjeta .precio-bs { margin-top: 3px; }

/* ── Quién vende, en la tarjeta (ADR 0022) ───────────────────────────────────
   QA pidió ver quién vende antes de abrir la publicación. Va entre el precio en
   bolívares y la reputación, y es el único trozo de la tarjeta que no lleva a
   la publicación.

   El ancho es la restricción y está medido: a 360 px el cuerpo útil es de
   131,5 px en la grilla de dos columnas y 132 en el carrusel, así que al nombre
   le quedan 109,5 px descontando la miniatura y su separación. El nombre más
   largo de los 18 vendedores de la API pide unos 110, o sea que el ellipsis es
   parte del diseño y no un accidente.

   El color es `--texto2` y no el `--texto3` del precio en bolívares. Dos
   renglones grises seguidos de letra chica se leen como un solo bloque, y lo
   único que los separa —junto con la miniatura— es ese medio tono. */
.tarjeta__vendedor {
  display: flex; align-items: center; gap: 6px;
  margin-top: 6px; min-width: 0;
  color: inherit; text-decoration: none;
}
/* La miniatura mide 16 px tenga logo o iniciales. Si midiera distinto en cada
   caso, la grilla se desalinearía según qué vendedores caigan en cada fila.
   El barrido es el mismo de `.avatar`: el vendedor tiene que leerse como la
   misma identidad aquí, en su ficha y en el directorio. */
.tarjeta__vendedor-ava {
  flex: none; width: 16px; height: 16px; border-radius: 50%;
  display: grid; place-items: center; overflow: hidden;
  background: var(--barrido); color: var(--blanco);
  font-size: 8px; font-weight: 800; letter-spacing: -.02em; line-height: 1;
}
.tarjeta__vendedor-ava img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tarjeta__vendedor-nom {
  min-width: 0;
  font-size: 11px; font-weight: 600; letter-spacing: -.011em; line-height: 1.35;
  color: var(--texto2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.tarjeta__pie {
  margin-top: auto; padding-top: 7px;
  flex-direction: row; align-items: center; gap: 7px;
}

/* El envío gratis, que estaba en una banda verde con el texto en versalitas,
   pasa a ser un camión de trece puntos. Se llevaba el 14 % del cuerpo estando
   en siete de cada ocho tarjetas: un dato que tienen casi todas no distingue
   nada. Lo que importa es poder notar la que NO lo tiene. */
.tarjeta__envio {
  flex: none; display: grid; place-items: center;
  width: 22px; height: 22px; border-radius: 11px;
  background: var(--ok-tenue); color: var(--ok-fuerte);
}

/* ── Editar el perfil (obs 8 y 17) ──────────────────────────────────────────
   Gemelo de `perfil-editar.tsx`. El marco es el mismo cuadrado redondeado que
   la cabecera de Perfil usa para el avatar, en grande y centrado: aquí la foto
   es el tema de la pantalla y no una insignia al lado del nombre. */
.perfil-editar__foto { text-align: center; margin-top: 8px; }
.perfil-editar__marco {
  position: relative; display: inline-grid; place-items: center;
  width: 96px; height: 96px; border-radius: 30px;
  background: var(--barrido); color: var(--blanco);
}
.perfil-editar__avatar {
  display: grid; place-items: center;
  width: 100%; height: 100%; border-radius: inherit; overflow: hidden;
  font-weight: 800; font-size: 32px; letter-spacing: -.03em; color: var(--blanco);
}
/* El botón que dice que esto se toca. Sin él, un avatar presionable es un
   avatar: nadie prueba a tocar su propia foto para ver si pasa algo. */
.perfil-editar__lapiz {
  position: absolute; right: -4px; bottom: -4px;
  display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: 15px;
  background: var(--marca); color: var(--blanco);
  border: 2.5px solid var(--fondo); cursor: pointer;
}
.perfil-editar__aviso {
  display: flex; gap: 11px; align-items: flex-start;
  margin-top: 18px; padding: 14px;
  border-radius: var(--r-lg); background: var(--superficie); color: var(--texto-2);
}
.perfil-editar__aviso p { margin: 0; }

/* La vista previa antes de guardar (punto 13 de las correcciones de QA del
   01-08). Se ve a 140 px y no a 96 como el avatar: aquí la pregunta es «¿te
   gusta cómo quedó?», y a 96 no se contesta. Redonda, porque redonda es como se
   va a ver en las tres cabeceras donde aparece. */
.perfil-editar__previa {
  margin-top: 16px; padding: 16px;
  border-radius: var(--r-lg); background: var(--superficie);
}
.perfil-editar__previa img {
  width: 140px; height: 140px; border-radius: 50%;
  object-fit: cover; display: block; margin: 0 auto;
}

/* El distintivo de cámara en el pie de la tarjeta (obs 3). Las mismas medidas
   que el globo del envío, que vive al lado: uno más grande que el otro se leería
   como más importante. Gemelo de `s.marca` en `SelloCamara.tsx`. */
.sello-camara {
  flex: none; display: grid; place-items: center;
  width: 22px; height: 22px; border-radius: 11px;
  background: var(--marca-tenue); color: var(--marca-fuerte);
}

/* ── El distintivo de «se paga en cuotas» (obs 18, ADR 0021) ──────────────────
   Abajo a la derecha de la foto: arriba a la izquierda vive el descuento, arriba
   a la derecha el favorito y abajo a la izquierda la etiqueta de impulsada. Era
   la única esquina libre y resulta ser la que menos tapa lo que se vende.

   Pastilla blanca y no una etiqueta teñida: la foto puede ser blanca, negra o un
   collage, y el símbolo de dos azules se pierde sobre la mitad de ellas. Es la
   forma que el ADR 0008 definió para fondo impredecible, y es su propio favicon.
   Gemelo de `SelloAeroCuota.tsx`. */
.sello-aero {
  position: absolute; right: 9px; bottom: 9px; z-index: 2;
  display: flex; align-items: center; gap: 6px;
  padding: 4px; border-radius: var(--r-md);
  background: var(--fondo); box-shadow: var(--sombra-1);
  pointer-events: none;
}
.sello-aero--chip { padding-right: 10px; }
.sello-aero__txt {
  font-size: 12px; font-weight: 700; letter-spacing: -.01em; color: var(--aero-tinta);
}
/* El marco existe para colgar el distintivo **fuera** de `.galeria`: dentro se lo
   llevaría la lupa de zoom.js, que amplía lo que hay en ese contenedor. */
.det-foto__marco { position: relative; }

/* Aquí vivía `.tarjeta__agregar`, que escondía el botón «Agregar» en el
   teléfono y lo devolvía en escritorio. El botón se fue entero con el ADR 0022:
   su sitio es el del renglón del vendedor, y la app nunca lo tuvo, así que
   además cierra una divergencia entre las dos superficies. Al carrito se llega
   abriendo la publicación, que sí tiene su botón. */

/* ── 4. Shell de escritorio ───────────────────────────────────────────────── */
/* 768px es el corte que ya usaba el sitio (md: de Tailwind). */

@media (min-width: 768px) {
  /* Sin barra de pestañas: recuperamos el espacio que la app le reserva. */
  .nav { display: none; }
  .pantalla { padding-bottom: 56px; }

  /* Header de una sola fila. Las dos filas de móvil se disuelven y sus hijos
     vuelven a ser hijos directos de `.header__fila`, que es lo que hace que el
     marcado no tenga que existir dos veces. */
  .header__fila { height: 70px; gap: 20px; }
  /* El alto y el hueco van repetidos aquí y no sólo arriba: la regla de móvil
     los pone en `auto` y en `0` con dos clases, así que le ganan por
     especificidad a `.header__fila` a secas. La cabecera ancha quedaba en 47 px
     —el alto del buscador— y con el lockup pegado al campo, sin un píxel de
     separación. Ninguna de las dos cosas se ve como un error de CSS: se ven
     como una cabecera apretada. */
  .header--principal .header__fila {
    height: 70px; gap: 20px;
    flex-direction: row; align-items: center;
  }
  .header__marca-fila,
  .header__buscar-fila { display: contents; }
  /* El `min-width` no es cinturón y tirantes: un `flex: 1` se encoge hasta el
     tamaño de su contenido, y con la barra de enlaces al lado el campo llegó a
     medir 32 px de ancho —medido a 768 y a 900—. Un buscador de 32 px no es un
     buscador. Antes que encogerse por debajo de esto, que se vaya otra cosa. */
  .header .buscador { flex: 1; min-width: 200px; max-width: 560px; }
  /* El buscador crece y el lockup no se achica. Sin esto el logo cede ancho
     —`flex-shrink` vale 1 por omisión— y el nombre de la marca se metía debajo
     del campo, que tiene fondo propio y lo tapaba. Parecía un recorte de texto
     y era una caja encogida. */
  .header__logo { flex: none; }
  .header__logo img { width: 38px; height: 38px; }
  .header__marca { font-size: 13.5px; white-space: nowrap; }

  /* Nada que plegar donde no hay dos filas, y el filete vuelve a estar siempre:
     el header ancho se apoya en el contenido desde el primer píxel. */
  .header--principal { border-bottom-color: var(--borde); }

  /* El menú lateral sigue existiendo —lleva a las 8 categorías— pero deja de
     ser la única puerta: .nav-web ya expone lo principal. */
  .header .icon-btn[data-menu] { order: -1; }

  .nav-web {
    align-items: center; gap: 2px;
    margin-left: auto;
  }
  .nav-web a {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 9px 13px; border-radius: 12px;
    font-size: 13.5px; font-weight: 700; letter-spacing: -.015em;
    color: var(--texto-2); white-space: nowrap;
    transition: color var(--transicion), background var(--transicion);
  }
  .nav-web a.activo { color: var(--brand-600); background: var(--brand-050); }
}

/* ── El riel abre desplazado, y se come el margen ────────────────────────────
   `scroll-snap-type` ancla al borde del scroller, **no al de su `padding`**.
   Un riel con `padding-inline` abre ya movido: el navegador lo corre solo para
   pegar la primera tarjeta al canto. Medido en Chrome el 1 de septiembre de
   2026, a 390 px: la portada, la banda destacada y la ficha abrían con
   `scrollLeft: 18` y su primera tarjeta en x=0, cuando lo correcto es
   `scrollLeft: 0` con la tarjeta en x=18. A 1200 px, con el padding en 28, el
   desvío era de 28.

   **Ninguna puerta lo ve**: no es desborde ni recorte, y a ojo no parece un
   error de scroll sino un margen mal escrito. `.crecer-carrusel` y
   `.crecer-riel` ya lo declaraban cada uno por su lado; esto lo lleva al riel
   genérico, que es el que usan casi todas las secciones.

   Vive aquí y no junto a la regla porque `.carrusel` se declara en `app.css`,
   que es intocable. */

.carrusel { scroll-padding-inline: var(--margen); }

/* Sin snap el anclaje no ocurre, pero `scrollIntoView` sí usa el scroll-padding,
   y este riel no tiene sangrado que respetar. */
.inicio-entrada__promo .carrusel[data-hero] { scroll-padding-inline: 0; }

/* ── 4a. Los seis enlaces sólo cuando entran ─────────────────────────────────
   Los seis miden 631 px con sus iconos y sus nombres. Sumados al menú, al
   lockup y al carrito no dejan sitio para el buscador hasta pasados los 1120:
   a 768 el campo quedaba en 32 px de ancho. Aparecían desde 768 porque el
   escritorio se pensó cuando el buscador todavía vivía en otra página.

   Debajo de eso no se pierde nada: el menú lateral lleva a los mismos seis
   sitios y además a las ocho categorías. Se pierde un atajo, no un destino. */

@media (min-width: 1120px) {
  .nav-web { display: flex; }

  .contenedor { padding-inline: 28px; }
  .carrusel { margin-inline: -28px; padding-inline: 28px; }

  /* El sangrado de la banda destacada sigue al del contenedor, que aquí crece
     de 18 a 28. Si no, la banda se quedaría corta y asomarían diez píxeles de
     página a cada lado. */
  .seccion--destacada { margin-inline: -28px; padding-inline: 28px; }

  /* El carrusel de la banda deja de sangrar por segunda vez.
     Sangraba él y sangraba la banda que lo contiene, así que sus tarjetas
     arrancaban 28 px a la izquierda de todas las grillas de la página —medido:
     x=23 contra x=51—. En el teléfono ese sangrado es la señal de «hay más»
     debajo del pulgar; en escritorio, donde nada se arrastra con el dedo, es
     una fila desalineada. La banda ya pone el margen. */
  .seccion--destacada .carrusel { margin-inline: 0; padding-inline: 0; }

  /* El sangrado del riel cambia aquí, así que su scroll-padding lo sigue: si no,
     el riel abriría corrido 28 px en escritorio y 0 en la banda destacada, que
     es justo la que ya no sangra. */
  .carrusel { scroll-padding-inline: 28px; }
  .seccion--destacada .carrusel { scroll-padding-inline: 0; }

  /* Detalle a dos columnas.
     ────────────────────────────────────────────────────────────────────────
     El marcado es UNO solo, en tres bloques, y el orden del DOM es el que
     necesita el móvil —que es el orden del APK—:

        .det-foto   galería
        .det-compra tags, título, precio, envío, vendedor, barra de compra
        .det-info   características, descripción, compra protegida

     En móvil no hay grid, así que caen en ese orden y la barra de compra se
     ancla al fondo como en la app. Aquí se colocan a mano en la retícula para
     que .det-compra suba a la derecha y .det-info quede bajo la foto. Sin la
     colocación explícita, la caja de compra flotaría arriba a la derecha
     lejos del precio, que es lo único que tiene que estar cerca. */
  .detalle-web {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 360px;
    grid-template-rows: auto 1fr;
    gap: 24px 36px;
    align-items: start;
  }
  .detalle-web > .det-foto   { grid-column: 1; grid-row: 1; }
  .detalle-web > .det-compra { grid-column: 2; grid-row: 1; }
  /* La zona de abajo cruza las dos columnas.
     ────────────────────────────────────────────────────────────────────────
     Con `.det-compra` ocupando las dos filas, la derecha quedaba **473 px
     vacíos** —medidos— desde que terminaba la caja de compra: se acaba a la
     altura del vendedor y debajo no hay nada que poner. Al cruzar, esos 473 px
     dejan de existir y la página se acorta. Es lo mismo que se hizo en el
     detalle de compra. */
  .detalle-web > .det-info   { grid-column: 1 / -1; grid-row: 2; }

  /* La foto llena su columna.
     ────────────────────────────────────────────────────────────────────────
     Estaba en 4:3 con tope de 460 px de alto, y el tope ganaba: sobre una
     columna de 828 px la galería se quedaba en **613** y dejaba 215 px muertos
     a su derecha, dentro de la propia columna. En 16:10 ese mismo ancho pide
     517 px de alto —57 más que el tope viejo— y no sobra nada. */
  .detalle-web .galeria { aspect-ratio: 16 / 10; max-height: none; }

  /* Características a un lado, el texto al otro.
     ────────────────────────────────────────────────────────────────────────
     Estirada a los 828 px de la columna, «Autonomía · · · · · 30 h» ponía la
     etiqueta y su valor en extremos opuestos y había que barrer la línea con la
     vista para juntarlos. En una columna angosta vuelven a leerse de un vistazo,
     y el texto largo se queda con el resto del ancho. */
  .det-info--dos {
    display: grid;
    grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
    gap: 0 36px;
    align-items: start;
  }

  .detalle-web .barra-compra {
    position: sticky;
    top: calc(var(--header-h) + 20px);
    left: auto; right: auto; bottom: auto;
    z-index: 1;
    /* El corazón comparte fila con "Agregar"; "Comprar ahora" ocupa el ancho
       completo debajo. En columna simple el corazón quedaba solo, colgado. */
    display: grid;
    grid-template-columns: 48px 1fr;
    gap: 10px;
    padding: 18px;
    border: 1px solid var(--borde);
    border-radius: var(--r-lg);
    background: var(--fondo);
    box-shadow: var(--sombra-1);
  }
  .detalle-web .barra-compra > :last-child { grid-column: 1 / -1; }
  .detalle-web .barra-compra .btn {
    height: 48px; padding: 0 18px; font-size: 14.5px; gap: 9px;
  }

  /* Carrito y checkout: resumen sticky al costado. */
  .col-resumen { position: sticky; top: calc(var(--header-h) + 20px); }

  .drawer { width: min(440px, 100%); }
  .galeria { border-radius: var(--r-lg); overflow: hidden; }

  /* La grilla de categorías respira: una sola fila de baldosas es demasiado
     apretada por encima de tablet.

     Y son cinco por fila, no ocho. `app.css` pide ocho y con diez categorías
     eso deja una segunda fila de dos, que se lee como un sobrante y no como el
     final de una lista. Cinco reparte diez en dos filas parejas. */
  .cats { gap: 14px; grid-template-columns: repeat(5, 1fr); }
}

/* ── 5. Escritorio ancho ──────────────────────────────────────────────────────
   Hasta aquí esto eran dos líneas: la portada medía 3.175 px de alto a 1280 y
   no tenía una sola regla propia.

   La primera versión puso el Programa Crecer como tarjeta de pie a la derecha
   de los banners, para llenar los 168 px de canaleta muerta que dejaban. Ganaba
   el pliegue y perdía todo lo demás: **medida sobre la página pintada, esa
   tarjeta era 82 % de aire** —un disco, dos líneas y una punta huérfana en
   300 × 250— y al lado de dos fotos a sangre se leía como un hueco sin llenar,
   no como lo único que este marketplace tiene y los demás no.

   Así que la canaleta no se llena: se elimina. Los dos banners se reparten el
   ancho entero y el Programa Crecer cruza la página debajo, que es también como
   está en el teléfono. Una franja que va de borde a borde dice «esto vale para
   todo el sitio»; una tarjeta en una esquina dice «este es un aviso más». */

@media (min-width: 1280px) {
  .contenedor { width: min(100%, 1280px); }
  .carrusel > * { flex-basis: 214px; }

  /* Los dos banners dejan de ser un carrusel: son dos y los dos entran. Un
     carrusel cortado dice «hay más», y aquí no hay más. */
  .inicio-entrada__promo .carrusel {
    display: grid; grid-template-columns: 1fr 1fr;
    margin-inline: 0; padding-inline: 0; padding-bottom: 0;
    overflow: visible;
  }
  .banner--entrada { max-width: none; }

  /* La tarjeta de AeroCuota, con el ancho aprovechado.
     Ya se acostó en una fila a 760; aquí sólo se le da aire lateral. A 1224 de
     ancho el riel es lo que crece: es el único elemento de la tarjeta que gana
     algo con ser más largo, y llenar el medio con espaciado en vez de con el
     dato era el defecto que `.crecer-web-ayuda` ya tuvo que corregir. */
  .aero-tarjeta { padding: 14px 18px; }

  /* Las diez categorías dejan de estirarse.
     A 1224 de ancho, las baldosas a `1fr` miden 141 × 91 para un disco de 46 y
     una etiqueta de once puntos: más de la mitad de cada caja es aire, y diez
     cajas idénticas estiradas son el primer rastro de los seis que el ADR 0006
     enumera. Con el ancho fijo se leen como diez cosas puestas en fila y no
     como una rejilla rellenando el hueco que le tocó.

     Eran ocho a 118px. Con diez, ese ancho suma 1180 de los 1224 y deja las
     baldosas a cinco píxeles unas de otras —pegadas, no espaciadas—; 112 las
     devuelve a once, que es donde se leen como piezas sueltas. */
  .cats { grid-template-columns: repeat(10, 112px); justify-content: space-between; }
  .cat { padding: 11px 4px 9px; }
  .cat__ico { width: 42px; height: 42px; }

  /* El ritmo de escritorio NO sube, ni aquí ni en la banda destacada.
     Las dos veces fue lo primero que se me ocurrió y las dos veces la medición
     lo desmintió: con las secciones a `--espacio-corte` la primera publicación
     se iba de 607 a 657, peor que antes de empezar. La primera pantalla es del
     catálogo, y eso vale también a 1280. */
}

/* ── 4c. Las empresas aliadas ─────────────────────────────────────────────────
   En gris y sin color, a propósito: el ADR 0006 decidió que la primera pantalla
   es del catálogo y que todo lo demás entra sólo si deja lugar. Una fila de
   logos de colores compitiendo con las fotos de las publicaciones sería lo
   contrario de eso.

   La fila se desliza en vez de envolverse. Cinco aliados hoy caben, diez no, y
   una segunda fila costaría otro tanto de la primera pantalla — que es
   exactamente lo que esta sección no puede permitirse. */

.aliados__rotulo {
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--texto-3); margin: 0 0 10px;
}
.aliados__fila {
  display: flex; gap: 10px; overflow-x: auto;
  margin-inline: calc(var(--margen) * -1); padding-inline: var(--margen);
}
.aliado {
  flex: none;
  display: flex; align-items: center; gap: 8px;
  padding: 8px 11px;
  border: 1px solid var(--borde); border-radius: var(--r-md);
  background: var(--fondo);
}
.aliado__marca {
  display: grid; place-items: center;
  width: 28px; height: 28px; border-radius: 8px;
  background: var(--superficie-2);
  font-size: 11px; font-weight: 800; letter-spacing: .02em; color: var(--texto-3);
}
.aliado__nombre { font-size: 12px; font-weight: 600; color: var(--texto-2); white-space: nowrap; }

/* A 1280 dejan de deslizarse: entran las cinco y el ancho sobra. Se maquetan como
   una grilla de cinco columnas con el mismo gap que las categorías de abajo, así
   cada chip cae justo sobre su columna (Metalúrgica sobre Electrónica…) y el
   primero queda pegado al borde izquierdo, alineado con el rótulo. Antes, sueltos
   en un flex, quedaban metidos hacia adentro y no alineaban con nada. */
@media (min-width: 1120px) {
  .aliados__fila {
    overflow: visible; margin-inline: 0; padding-inline: 0;
    display: grid; grid-template-columns: repeat(5, 1fr); gap: 14px;
  }
}

/* ── 5a. Los dos caminos de la afiliación ─────────────────────────────────────
   Empresa y emprendedor son dos tarjetas con la misma forma y distinto
   contenido, que es justo lo que el ADR 0006 llama sospechoso cuando el
   contenido no cambia. Aquí cambia: distinto icono, distinto lema y distinta
   lista de lo que promete cada una — es la elección misma, no un adorno
   repetido.

   Una sola columna en el teléfono y dos en cuanto entran: son alternativas, y
   dos alternativas apiladas se leen como pasos de una secuencia. */

/* El corazón: 44 para el dedo, 33 para el ojo.

   `app.css` lo declara en 33 × 33 y era la deuda más grande que quedaba —150
   apariciones, una por tarjeta en cada pantalla que las pinta—. Pero agrandarlo
   a 44 a secas engorda el disco blanco sobre la foto, y ese disco está en 33
   porque a 44 le come la esquina a la publicación.

   Así que crecen cosas distintas: el `<button>` mide 44 y no pinta nada, y el
   disco pasa a un `::before` de 33 centrado dentro. El área que se toca es la
   que pide la norma; la que se ve es la que se diseñó. Sin tocar el marcado,
   que existe por triplicado — el PHP, el JS del carrito y la copia que
   `favoritos.php` pinta desde `localStorage`.

   El `transform` de los estados queda en el botón y no en el disco: la
   animación del latido tiene que mover el conjunto, y moverla al `::before`
   dejaría el icono quieto mientras el fondo salta.

   **La app ya lo tenía resuelto** y por eso no se toca: `BotonFavorito.tsx` usa
   `hitSlop={8}`, que en React Native agranda el área que responde sin tocar el
   layout. En CSS no hay hitSlop, así que hace falta este rodeo — es la misma
   decisión con dos herramientas distintas, no una divergencia. */
.fav-btn {
  width: 44px; height: 44px;
  background: none;
  backdrop-filter: none;
  box-shadow: none;
}
.fav-btn::before {
  content: '';
  position: absolute;
  inset: 5.5px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .94);
  backdrop-filter: blur(6px);
  box-shadow: 0 2px 8px -2px rgba(12, 32, 67, .28);
}
.fav-btn .ico { position: relative; }

/* El campo de texto ocupa el alto de su caja.
   `app.css` le da 52 a `.campo__caja` y deja el `<input>` en los 23 que mide su
   línea, así que el objetivo tocable era la línea y no la caja — se ve igual y
   se toca peor. `align-self: stretch` lo estira sin mover un píxel de lo que se
   ve, y saca cincuenta objetivos del recuento de una vez.

   El `<select>` entró después —la validación estricta de cédula, teléfono y RIF
   los trajo— y nació con el mismo defecto ya resuelto: 21 px de alto dentro de
   una caja de 52. Once objetivos nuevos por una regla que ya existía y no lo
   nombraba. Si mañana aparece otro control dentro de `.campo__caja`, va aquí. */
.campo__caja input,
.campo__caja select,
.campo__caja textarea { align-self: stretch; }

/* El desplegable de código telefónico se lo comía todo, y medido da miedo: 278 px
   de `<select>` y **4 px** de `<input>` a 390, 14 a 1280. O sea que el campo donde
   se escriben los siete dígitos no se podía usar, en las cuatro pantallas que
   piden teléfono (registro, checkout con pago móvil, editar perfil y afiliación).
   No se veía roto: se veía como una raya.

   La causa es que un `<select>` con `flex: none` lo dimensiona su opción MÁS
   ANCHA, no la elegida — y desde que la lista trae los cuarenta códigos fijos con
   su ciudad, la más ancha es «0265 — Los Puertos de Altagracia». Por eso medía
   278 con `0414` puesto: el ancho no depende de lo que se ve.

   Se le fija el ancho, que es lo único que rompe esa regla. Va por clase y no en
   `CI_SELECT_CAJA`, que comparte con la cédula (V/E) y el RIF (J/V/E…): ésos se
   dimensionan bien solos y fijarles un ancho los ensancharía sin motivo.

   La ciudad se sigue leyendo entera al desplegar —la lista la pinta el sistema y
   no la recorta este ancho—; cerrado se ve el código, que es lo que se guarda. */
.campo__caja select.campo__codigo { width: 5.4em; text-overflow: ellipsis; }

/* Y el del buscador, por lo mismo. Quedó afuera de aquella pasada: su caja mide
   46 y el `<input>` seguía en 23, o sea que el objetivo era la línea de texto y
   no la caja, en **todas** las pantallas, porque el buscador va en la cabecera.
   Se pagó al entrar el detalle de una compra (ADR 0014): el armazón se cuenta
   una vez por pantalla, así que una pantalla nueva sube el recuento y la regla
   es buscar la pieza chica, no subir el tope. */
.buscador input { align-self: stretch; }

/* Volver a elegir camino: es una acción, así que mide como acción. */
.afiliarse-volver {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px; margin-bottom: 4px;
  font-size: 13px; font-weight: 700; color: var(--brand-600);
}

.afiliarse-caminos { display: grid; gap: 14px; }

.afiliarse-camino {
  display: block;
  padding: 18px;
  border: 1px solid var(--borde);
  border-radius: var(--r-lg);
  background: var(--fondo);
  transition: border-color var(--transicion), transform 140ms ease;
}
.afiliarse-camino:active { transform: scale(.99); }

.afiliarse-camino__disco {
  display: grid; place-items: center;
  width: 44px; height: 44px; border-radius: 22px;
  background: var(--brand-050); color: var(--brand-600);
  margin-bottom: 12px;
}
.afiliarse-camino strong {
  display: block; font-size: 17px; font-weight: 800; letter-spacing: -.03em;
}
.afiliarse-camino__lema {
  display: block; margin-top: 3px; font-size: 12.5px; font-weight: 500; color: var(--texto-3);
}

.afiliarse-camino__lista { margin: 14px 0 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.afiliarse-camino__lista li {
  display: flex; gap: 8px; align-items: flex-start;
  font-size: 12.5px; font-weight: 500; line-height: 1.4; color: var(--texto-2);
}
.afiliarse-camino__lista .ico { flex: none; margin-top: 1px; color: var(--ok-600); }

/* El pie es la acción, y va como acción: 44 de alto para que sea un objetivo y
   no un renglón que resulta que se toca. */
.afiliarse-camino__ir {
  display: flex; align-items: center; justify-content: space-between;
  min-height: 44px; margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--borde);
  font-size: 13.5px; font-weight: 700; color: var(--brand-600);
}

@media (hover: hover) and (pointer: fine) {
  .afiliarse-camino:hover { border-color: var(--brand-300); }
}

@media (min-width: 768px) {
  .afiliarse-caminos { grid-template-columns: 1fr 1fr; align-items: start; }
}

/* Modo «ver mi solicitud» (enlace mágico): estado + documentos + contrato */
.afiliarse-estado {
  display: grid; gap: 4px;
  padding: 18px;
  border: 1px solid var(--borde);
  border-radius: var(--r-lg);
  background: var(--fondo);
}
.afiliarse-estado__disco {
  display: grid; place-items: center;
  width: 44px; height: 44px; border-radius: 22px;
  background: var(--brand-050); color: var(--brand-600);
  margin-bottom: 8px;
}
.afiliarse-estado strong { font-size: 18px; font-weight: 800; letter-spacing: -.03em; }
.afiliarse-estado.es-lista .afiliarse-estado__disco { background: var(--ok-050); color: var(--ok-600); }
.afiliarse-estado.es-no .afiliarse-estado__disco { background: var(--dinero-tenue); color: var(--dinero-texto); }

.afiliarse-docs__ayuda { display: block; margin: -2px 0 8px; }
/* El input de archivo va como campo con borde y ≥44 px de alto: es un objetivo tocable. */
#ci-afiliarse-docs {
  display: block; width: 100%; box-sizing: border-box;
  min-height: 44px; padding: 11px 12px;
  border: 1px solid var(--borde); border-radius: var(--r-md);
  background: var(--fondo); color: var(--texto);
  font-size: 13px; font-weight: 500;
}
.afiliarse-docs { display: grid; gap: 6px; }
.afiliarse-doc {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 40px; padding: 8px 12px;
  border: 1px solid var(--borde); border-radius: var(--r-md);
  font-size: 13px; font-weight: 600; color: var(--texto);
  background: var(--fondo);
}
.afiliarse-doc .ico { flex: none; color: var(--brand-600); }

/* ── Qué es cada documento que subes (punto 7 de QA 01-08) ───────────────────
 *
 * Una fila por archivo elegido: su nombre y un desplegable con la clase. Se
 * llama `afiliarse-clase` y no `afiliarse-doc` a propósito: ése ya existe justo
 * arriba y es otra cosa —el enlace al documento ya subido, en el acuse—, y dos
 * significados en un nombre se pisan el día que uno de los dos cambie.
 *
 * El nombre del archivo se corta con puntos suspensivos: un PDF escaneado desde
 * el teléfono trae un nombre larguísimo y empujaría el desplegable fuera.
 */
.afiliarse-clases { display: grid; gap: 6px; margin: 8px 0 0; padding: 0; list-style: none; }
.afiliarse-clase {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 12px;
  border: 1px solid var(--borde); border-radius: var(--r-md);
  background: var(--fondo);
}
.afiliarse-clase__nombre {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12.5px; font-weight: 600; color: var(--texto-2);
}
.afiliarse-clase__tipo {
  flex: none; min-height: 44px;
  border: 0; outline: 0; background: none;
  font: inherit; font-size: 13px; font-weight: 700; color: var(--texto);
}

.afiliarse-contrato {
  white-space: pre-wrap; font-family: inherit;
  font-size: 12.5px; line-height: 1.55; color: var(--texto-2);
  border: 1px solid var(--borde); border-radius: var(--r-md);
  background: var(--fondo); padding: 14px 16px; margin: 0;
  max-height: 340px; overflow: auto;
}

/* ── 6. Impresión ─────────────────────────────────────────────────────────── */
/* La confirmación de compra es lo único que alguien va a querer imprimir. */

@media print {
  .header, .nav, .barra-compra, .drawer, .velo, .nav-web, .toast { display: none !important; }
  .pantalla { padding: 0; animation: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   EL ESCUDO
   Lo único que sobrevivió de «Mi progreso» (docs/adr/0004): la insignia era
   una pieza genérica, y el paisaje que llevaba adentro era del viaje. Las
   medidas salen de la app: el escudo mide 116 unidades de viewBox.
   ═══════════════════════════════════════════════════════════════════════════ */

.escudo { position: relative; flex: none; }
.escudo__cinta {
  position: absolute; display: flex; align-items: center; justify-content: center;
  font-weight: 800; text-transform: uppercase; white-space: nowrap; overflow: hidden;
}
.escudo__ico { position: absolute; display: flex; align-items: center; justify-content: center; }
.escudo__ico--centro { left: 0; right: 0; }

/* ═══════════════════════════════════════════════════════════════════════════
   8. PROGRAMA CRECER
   Port de app/src/componentes/crecer/. Las medidas salen de allá.

   Va en web.css y NO en app.css a propósito. app.css es una copia del APK de
   Capacitor, que la app de app/ reemplaza (ADR 0001): es un archivo con un
   origen que ya no se edita, y meterle reglas de algo que nació en React
   Native lo convertiría en un tercer lugar donde vive el diseño — el único que
   nadie regenera. Lo nuevo se escribe donde la web es la web.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── El banner ────────────────────────────────────────────────────────────── */

/* El degradado es el de la submarca y no el navy de la casa: éste es el banner
   de AeroCuota, y es una de las cuatro superficies que el ADR 0008 enumera. */
.crecer-banner {
  position: relative; overflow: hidden; display: block;
  border-radius: 20px; padding: 16px; color: var(--sobre-marca); text-decoration: none;
  background: var(--aerocuota);
}
/* El anillo decorativo de la app, en un pseudoelemento: no vale un <span>. */
.crecer-banner::before {
  content: ''; position: absolute; right: -48px; top: -54px;
  width: 210px; height: 210px; border-radius: 50%;
  border: 26px solid rgba(255,255,255,.07);
}
.crecer-banner--compacto { padding: 13px 16px; }
.crecer-banner__cab { position: relative; display: flex; align-items: center; gap: 10px; }
/* El símbolo y el lockup, las dos mismas piezas que `.aero-tarjeta`. Antes aquí
   iba «AEROCUOTA» en versalitas, que era todo lo que la submarca tenía antes
   del ADR 0008. Con el logo real disponible, la palabra dibujada a mano una
   pantalla después de la portada ya no se sostenía. */
.crecer-banner__marca { flex: 1; min-width: 0; display: flex; align-items: center; gap: 9px; }
.crecer-banner__lema { position: relative; margin: 9px 0 0; font-size: 13px; font-weight: 600; }
/* Sólo en el compacto, que es el de la ficha y sí enlaza. En el pegado el
   comprador ya está en el checkout, y una punta que lo saca de ahí es una
   fuga. Gemela de `.aero-tarjeta__ver`. */
.crecer-banner__ver {
  flex: none; display: inline-flex; align-items: center; gap: 3px;
  font-size: 12.5px; font-weight: 700; letter-spacing: -.015em;
  color: var(--sobre-marca);
}
.crecer-banner__cuota {
  position: relative; margin: 12px 0 0; font-size: 22px; font-weight: 800; letter-spacing: -.66px;
}
.crecer-banner--compacto .crecer-banner__cuota { margin-top: 6px; font-size: 18px; letter-spacing: -.54px; }
.crecer-banner__excede { position: relative; margin: 12px 0 0; font-size: 13.5px; font-weight: 700; line-height: 18px; }
.crecer-banner__pie { position: relative; margin: 6px 0 0; font-size: 11.5px; color: rgba(255,255,255,.72); }
.crecer-banner--compacto .crecer-banner__pie { margin-top: 2px; }

/* ── El avión de las barras ───────────────────────────────────────────────── */

/* El icono `plane` del set propio, no un emoji: de papel y no de fuselaje,
   porque a 14px un avión de perfil se convierte en una mancha. El triángulo es
   la geometría del isotipo.

   Inclinado 14° hacia arriba, que es todo el truco: un avión horizontal es un
   marcador de posición; uno que sube dice hacia dónde va la barra.

   El disco es más alto que el riel a propósito — la cabeza corre por encima de
   la barra, no dentro. Por eso ningún riel del programa lleva overflow:hidden. */
/* Cuelga del RIEL, con `left` puesto por PHP en la fracción exacta. El `top`
   sale de una resta —(8 − 22) / 2— y no de un `top: 50%`, que dependía de la
   altura de la caja que lo contenía. La variante `es-al-borde` es la de la
   barra del reparto, donde sí se pega al borde derecho de su tramo. */
.crecer-avion {
  position: absolute; top: -7px; margin-left: -11px;
  width: 22px; height: 22px; border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  background: var(--fondo); box-shadow: 0 2px 6px -1px rgba(12,32,67,.28);
  color: var(--aero-fuerte);
}
/* En la barra del reparto el avión se pega al borde derecho de su tramo, que es
   un `<span>` de 10 px de alto y no el riel de 8. */
.crecer-avion.es-al-borde { right: -11px; top: 50%; margin: -11px 0 0; }
.crecer-avion svg { transform: rotate(-14deg); }
/* Dentro de la tarjeta de AeroCuota el tramo lleno también es blanco: con el
   disco blanco encima se funden y deja de verse dónde termina el cupo usado. Invertido quedan tres cosas separables —relleno blanco, disco oscuro,
   riel al 25 %— y el borde del disco marca el corte en vez de esconderlo. Sin
   sombra: va 2 px hacia abajo y sobre azul sólo mancha, dejando el disco caído
   aunque esté centrado al píxel. */
.crecer-avion.es-oscuro {
  background: var(--aero-fuerte); color: var(--sobre-marca); box-shadow: none;
}

/* El banner como cabecera de la tarjeta que lo sigue: sin esquinas abajo, y la
   tarjeta sin esquinas arriba. Juntos son un solo bloque. */
.crecer-banner--pegado { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.crecer-zona__cuerpo { border-top-left-radius: 0; border-top-right-radius: 0; }

.crecer-rotulo { margin: 16px 0 9px; font-size: 13px; font-weight: 700; letter-spacing: -.26px; color: var(--texto-2); }

/* ── El reparto: qué pagas hoy y qué queda a cuotas ───────────────────────── */

.crecer-reparto__riel { display: flex; gap: 3px; height: 10px; }
.crecer-reparto__tramo { position: relative; border-radius: 5px; }
/* El azul es el de AeroCuota: esta barra sólo vive dentro de la zona de pago
   del checkout, que es la cuarta superficie del ADR 0008. El tramo de hoy
   estaba en `--brand-200` mientras la app lo tenía en `brand100`, así que las
   dos superficies llevaban dos claros distintos y ninguna puerta lo veía; al
   pasar las dos a `--aero-suave` se emparejaron. */
.crecer-reparto__tramo--hoy { background: var(--aero-suave); }
.crecer-reparto__tramo--cuotas { background: var(--aero); }
.crecer-reparto__pie { display: flex; justify-content: space-between; gap: 12px; margin-top: 11px; }
.crecer-reparto__der { text-align: right; }
.crecer-reparto__rot { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--texto-2); }
.crecer-reparto__der .crecer-reparto__rot { justify-content: flex-end; }
.crecer-reparto__punto { width: 8px; height: 8px; border-radius: 4px; background: var(--aero-suave); flex: none; }
.crecer-reparto__punto.es-cuotas { background: var(--aero); }
.crecer-reparto__pie strong { display: block; margin-top: 2px; font-size: 15px; font-weight: 800; letter-spacing: -.3px; color: var(--texto); }
/* Sin inicial, la afirmación y el monto comparten renglón en vez de ocupar dos
   columnas para enfrentar un 0% a un 100%. */
.crecer-reparto__pie.es-solo { align-items: center; }
.crecer-reparto__pie.es-solo .crecer-reparto__rot { flex: 1; min-width: 0; }
.crecer-reparto__pie.es-solo strong { margin-top: 0; }
.crecer-linea { margin: 18px 0; border: 0; border-top: 1px solid var(--borde); }

/* ── El cupo ──────────────────────────────────────────────────────────────── */

.crecer-cupo__cab { display: flex; align-items: center; gap: 11px; }
.crecer-cupo__disco {
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 20px;
  /* Aero y no marca: esta barra sólo vive en la pantalla de AeroCuota y en la
     zona del checkout, dos de las cuatro superficies del ADR 0008. */
  background: var(--aero-tenue); color: var(--aero-fuerte);
}
.crecer-cupo__rot { font-size: 11.5px; font-weight: 500; color: var(--texto-3); }
.crecer-cupo__linea { margin: 1px 0 0; font-size: 14.5px; line-height: 20px; color: var(--texto-2); }
.crecer-cupo__linea b { font-weight: 800; color: var(--texto); }
.crecer-cupo__linea span { color: var(--texto-3); }
/* El disponible en navy y no en cálido: el cálido es el color del dinero que se
   compromete —el tramo `es-nuevo` de la barra—, y usarlo también para la buena
   noticia hace que un saldo a favor se lea como una alerta. */
.crecer-cupo__cifra { display: block; font-size: 24px; font-weight: 800; letter-spacing: -.72px; color: var(--texto); }
.crecer-cupo__de { font-size: 12px; color: var(--texto-3); }
/* El margen va en la relación y no en el riel: desde que `cei_riel_cupo()` se
   usa suelto en la tarjeta de la portada, un `margin-top` propio lo seguía a
   todas partes y había que restarlo donde no hacía falta. */
/* `relative` porque el avión cuelga de aquí desde que dejó de ser hermano del
   tramo: es lo que hace que su `left` sea una fracción del riel entero. */
.crecer-cupo__riel { position: relative; display: flex; gap: 2px; height: 8px; border-radius: 4px; background: var(--superficie-2); }
.crecer-cupo > .crecer-cupo__riel { margin-top: 10px; }
/* Sobre el degradado de AeroCuota el gris del riel vacío se ve como una mancha
   sucia, y el azul de marca del tramo usado desaparece contra el fondo. */
.crecer-cupo__riel.es-oscuro { background: rgba(255, 255, 255, .25); }
.crecer-cupo__riel.es-oscuro .crecer-cupo__tramo.es-usado { background: var(--sobre-marca); }
.crecer-cupo__lleno { position: relative; display: flex; gap: 2px; }
.crecer-cupo__tramo { border-radius: 4px; }
/* El azul de AeroCuota y no el de la casa: el cupo es del trato, y las tres
   piezas que pintan este riel son tres de las cuatro superficies del ADR 0008. */
.crecer-cupo__tramo.es-usado { background: var(--aero); }
/* Lo que esta compra se lleva, en el color del dinero. **No se tiñe de aero
   aunque el tramo de al lado sí**: el cálido no es un color de marca sino de
   estado, y es la única distinción que esta barra existe para hacer. */
.crecer-cupo__tramo.es-nuevo { background: var(--calido-500); }
.crecer-cupo__pie { margin: 7px 0 0; font-size: 11.5px; font-weight: 600; color: var(--texto-3); }

/* ── Las cuotas por pagar, agrupadas por compra ───────────────────────────── */

.crecer-compras { display: flex; flex-direction: column; gap: 12px; }
.crecer-compra__cab {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 0 10px; border-bottom: 1px solid var(--borde);
}
.crecer-compra__cab strong { display: block; font-size: 13px; font-weight: 700; color: var(--texto); }
.crecer-compra__cab span { font-size: 11.5px; font-weight: 500; color: var(--texto-3); }
.crecer-compra__cab b { font-size: 14.5px; font-weight: 800; letter-spacing: -.29px; color: var(--texto); }
/* Los 14 px de `padding-block` no son aire: llevan el botón de 30 a 44 px de
   alto, que es lo que un dedo necesita. Medía 126 × 30 y estaba entre los 342
   objetivos chicos que el trinquete de `npm run vista` cuenta. La app ya lo
   tenía resuelto con `hitSlop`, que agranda el área sin tocar el layout. */
.crecer-compras__mas {
  align-self: center; padding: 14px 12px; border: 0; background: none;
  font-size: 12.5px; font-weight: 700; letter-spacing: -.13px; color: var(--brand-600);
  cursor: pointer;
}
.crecer-compras__mas:hover { text-decoration: underline; }
/* La clase la comparten dos botones que viven en dos programas distintos: el
   «Ver las N pagadas» de las cuotas, que es de AeroCuota, y el «Ver los 50» de
   la tabla de clasificación, que es de Crecer. Por eso el azul de la submarca
   entra por un modificador y no por la base — teñirla lo filtraría a la tabla.
   En la app no hace falta: allá son dos declaraciones ya separadas. */
.crecer-compras__mas.es-aero { color: var(--aero); }

/* ── El calendario de cuotas ──────────────────────────────────────────────── */

/* Sin filete entre filas: **el hilo es lo único que separa una cuota de la
   siguiente**. Llevaba además un `border-top` de borde a borde que lo cruzaba en
   ángulo recto justo en el medio, así que la línea de tiempo quedaba picada en
   tres trozos y las tres cuotas volvían a leerse como renglones iguales. Dos
   separadores para lo mismo, y el que sobraba se comía al que decía algo. Un
   punto más de aire hace ahora ese trabajo. Gemela de `Calendario.tsx`. */
.crecer-cal__fila { position: relative; display: flex; align-items: center; gap: 11px; padding: 11px 0; }
/* Los tres estados se distinguen por la marca y no por el color del texto: una
   fila gris entera se lee como deshabilitada, y una cuota pendiente no lo está
   — está por venir.

   Las marcas son una línea de tiempo y no radios. Antes la próxima era un
   anillo con un punto adentro, que es exactamente el dibujo del .opcion__radio:
   en el checkout quedaban seis cuotas con pinta de seleccionables, una de ellas
   «marcada», debajo de una lista de radios de verdad. El hilo vertical que las
   une dice lo que son —fechas en orden— y no se parece a nada que se pueda
   tocar. El hilo se dibuja con pseudo-elementos y no con marcado porque estas
   filas se emiten desde tres lugares: aquí, el IIFE del checkout y compras.php. */
.crecer-cal__marca {
  position: relative;
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; margin: 0 1px; border-radius: 8px;
  background: var(--fondo); border: 2px solid var(--borde-fuerte);
}
.crecer-cal__marca::before,
.crecer-cal__marca::after {
  content: ''; position: absolute; left: 50%; width: 2px; margin-left: -1px;
  background: var(--borde);
}
.crecer-cal__marca::before { bottom: 100%; height: 12px; }
.crecer-cal__marca::after { top: 100%; height: 12px; }
/* Una línea de tiempo que empieza antes de su primer hito promete algo que no
   está, y lo mismo al final. */
.crecer-cal__fila:first-child .crecer-cal__marca::before,
.crecer-cal__fila:last-child .crecer-cal__marca::after { display: none; }

/* El verde no se tiñe nunca, ni dentro de una superficie de AeroCuota:
   significa «pagada», que es un estado y no una marca. */
.es-pagada > .crecer-cal__marca { background: var(--ok-600); border-color: var(--ok-600); }
/* Maciza con halo, y no un anillo con un punto adentro: eso último es el radio. */
.es-proxima > .crecer-cal__marca {
  width: 18px; height: 18px; margin: 0;
  background: var(--brand-600); border: 3px solid var(--brand-050);
}
/* Este calendario es el único de las cuotas que también vive fuera de
   AeroCuota: `compras.php` lo pinta en el detalle de una compra. Por eso el
   azul de la submarca entra por `es-aero` y no por la base. Tres clases contra
   dos: gana por especificidad, no por orden. */
.crecer-cal.es-aero .es-proxima > .crecer-cal__marca {
  background: var(--aero); border-color: var(--aero-tenue);
}
.crecer-cal__que { flex: 1; min-width: 0; }
.crecer-cal__que strong { display: block; font-size: 13px; font-weight: 600; color: var(--texto); }
.crecer-cal__que span { font-size: 11.5px; color: var(--texto-3); }
.crecer-cal__monto { font-size: 14px; font-weight: 800; letter-spacing: -.28px; color: var(--texto); }
.es-pagada .crecer-cal__monto { color: var(--texto-3); }
.crecer-cal__restan { margin: 0; padding-top: 10px; border-top: 1px solid var(--borde); font-size: 12px; font-weight: 600; color: var(--texto-3); }

.crecer-aviso { display: flex; align-items: flex-start; gap: 8px; margin: 16px 0 0; font-size: 11.5px; line-height: 16px; color: var(--texto-3); }

/* ── Los seis niveles ───────────────────────────────────────────────────────
 *
 * Aquí vivía `.crecer-niveles` con sus seis filas apiladas, y se fue entera al
 * mudarse los niveles a AeroCuota (ADR 0018): la reemplazó `.crecer-riel`, más
 * abajo. Se borra en vez de dejarse por si acaso — un estilo que nadie pinta es
 * la promesa de que alguien lo va a volver a pintar, que es la regla del
 * ADR 0013 aplicada a una hoja en vez de a un dato. Está en el historial. */

/* ── La tarjeta del nivel actual ──────────────────────────────────────────── */

.crecer-nivel-t { display: flex; align-items: center; gap: 14px; }
.crecer-nivel-t__que { flex: 1; min-width: 0; }
.crecer-nivel-t__rot { font-size: 9.5px; font-weight: 800; letter-spacing: .95px; color: var(--texto-3); }
.crecer-nivel-t__nombre { display: block; font-size: 18px; font-weight: 800; letter-spacing: -.54px; color: var(--texto); }
.crecer-nivel-t__falta { margin: 2px 0 0; font-size: 12px; line-height: 16px; color: var(--texto-2); }
.crecer-anillo { position: relative; flex: none; display: flex; flex-direction: column; align-items: center; }
.crecer-anillo svg { display: block; }
.crecer-anillo__n { position: absolute; top: 14px; font-size: 19px; font-weight: 800; letter-spacing: -.5px; }
.crecer-anillo__de { position: absolute; top: 32px; font-size: 10px; font-weight: 600; color: var(--texto-3); }
/* La unidad, para que «1 de 8» no se lea como niveles. Gemela del `unidad` de
   `AnilloMeta.tsx`. */
.crecer-anillo__unidad { position: absolute; top: 42px; font-size: 8px; font-weight: 600; color: var(--texto-3); }

/* ── Las insignias ────────────────────────────────────────────────────────── */

/* ── El carrusel, que reemplazó a la rejilla ──────────────────────────────────
 *
 * Gemelo de `CarruselInsignias.tsx`, y la misma mecánica que `.crecer-riel`: si
 * dos piezas de esta pantalla se desplazan igual, se escriben igual.
 *
 * Seis insignias de dos en dos eran tres filas, y tres filas de escudo con dos
 * renglones debajo miden casi una pantalla de teléfono. Eso empujaba los méritos
 * fuera de la vista, y una sección que hay que buscar con el dedo pesa menos de
 * lo que vale. Ver ADR 0019. */

.crecer-carrusel {
  /* Sangrado hasta los dos bordes, con el margen puesto por las tarjetas: media
     insignia asomando es lo que dice que hay más. */
  margin-inline: calc(var(--margen) * -1);
  padding-inline: var(--margen);
  padding-block: 4px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* ⚠️ Lo mismo que en `.crecer-riel`, y por lo mismo: con `mandatory` el ancla
     es el borde del scroller y no el del padding, así que sin esto el navegador
     desplaza el carrusel solo al cargar y se come el margen de la pantalla.
     Ninguna puerta lo ve: no es desborde ni recorte, y a ojo parece un margen
     mal escrito. */
  scroll-padding-inline: var(--margen);
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.crecer-carrusel::-webkit-scrollbar { display: none; }
.crecer-carrusel__pista { display: flex; gap: 11px; }
/* Dos por pantalla en el teléfono, como en la app. El ancho es fijo y no `1fr`
   porque el salto del desplazamiento se calcula con él, en CSS y en `ui.js`. */
.crecer-carrusel .crecer-insignia { flex: none; width: 150px; scroll-snap-align: start; }

/* Los puntos. Sin ellos, un carrusel de seis parece una fila de dos que se
   cortó. El activo se estira en vez de sólo encenderse: dos estados de color a
   6 px se distinguen mal, y la forma se lee antes que el tono. */
.crecer-puntos { display: flex; justify-content: center; gap: 6px; margin-top: 12px; }
.crecer-puntos i {
  width: 6px; height: 6px; border-radius: 3px;
  background: var(--brand-500); opacity: .28;
  transition: width .25s ease, opacity .25s ease;
}
.crecer-puntos i.es-aqui { width: 18px; opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .crecer-puntos i { transition: none; }
}

.crecer-insignia { display: flex; flex-direction: column; align-items: center; }
/* Dos renglones reservados siempre: creciendo con su contenido, los «+N
   méritos» de una fila quedaban a alturas distintas según cuánto midiera el
   texto de arriba. */
.crecer-insignia__txt { margin-top: 8px; height: 30px; font-size: 11.5px; line-height: 15px; font-weight: 600; text-align: center; color: var(--texto-2); }
.crecer-insignia__meritos { margin-top: 4px; font-size: 11px; font-weight: 800; color: var(--calido-700); }

/* Aquí vivían `.crecer-insignias` —la rejilla— y `.crecer-insignias__meta`, la
   línea de «Por ganar:». Se fueron con el carrusel: la web mostraba sólo las
   ganadas más esa lista de texto y la app mostraba las seis, que era la misma
   pantalla contestando cosas distintas según la superficie (ADR 0003). Ahora las
   dos pintan las seis y ninguna necesita el renglón aparte. */

/* ── La tabla de clasificación ────────────────────────────────────────────── */

.crecer-tabla { border-radius: 20px; background: var(--fondo); overflow: hidden; box-shadow: var(--sombra-1); }
.crecer-tabla__fila { display: flex; align-items: center; gap: 11px; padding: 9px 14px; }
.crecer-tabla__fila + .crecer-tabla__fila { border-top: 1px solid var(--borde); }
.crecer-tabla__fila.es-propio { background: var(--brand-050); }
.crecer-tabla__puesto { flex: none; width: 22px; text-align: right; font-size: 13px; font-weight: 800; color: var(--texto-3); }
.crecer-tabla__puesto.es-podio { color: var(--calido-700); }
.crecer-tabla__avatar {
  flex: none; display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 15px; color: var(--sobre-marca); font-size: 11px; font-weight: 800;
}
.crecer-tabla__que { flex: 1; min-width: 0; }
.crecer-tabla-zona { display: flex; flex-direction: column; }
.crecer-tabla__fila.es-oculta { display: none; }
/* El salto en la numeración se dice con puntos, no con una línea maciza. */
.crecer-tabla__fila.es-cortada { border-top: 1.5px dashed var(--borde-fuerte); }
.crecer-tabla__nombre { display: block; font-size: 13px; font-weight: 600; color: var(--texto); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.es-propio .crecer-tabla__nombre { font-weight: 800; color: var(--brand-700); }
.crecer-tabla__nivel { display: flex; align-items: center; gap: 5px; margin-top: 2px; font-size: 10.5px; color: var(--texto-3); }
.crecer-tabla__nivel i { width: 7px; height: 7px; border-radius: 3.5px; flex: none; }
.crecer-tabla__meritos { flex: none; font-size: 13px; font-weight: 800; letter-spacing: -.26px; color: var(--texto); }

/* ── La puerta desde el perfil ────────────────────────────────────────────── */

.crecer-puerta {
  position: relative; overflow: hidden; display: flex; align-items: center; gap: 10px;
  border-radius: 20px; padding: 16px; color: var(--sobre-marca); text-decoration: none;
  background: var(--barrido);
}
.crecer-puerta::before {
  content: ''; position: absolute; right: -40px; top: -46px;
  width: 168px; height: 168px; border-radius: 50%; border: 22px solid rgba(255,255,255,.07);
}
.crecer-puerta > div { position: relative; flex: 1; min-width: 0; }
.crecer-puerta > svg { position: relative; flex: none; opacity: .8; }
.crecer-puerta__rot { font-size: 9.5px; font-weight: 800; letter-spacing: .86px; color: rgba(255,255,255,.78); }
.crecer-puerta__cifra { display: block; margin-top: 4px; font-size: 26px; font-weight: 800; letter-spacing: -.78px; }
.crecer-puerta__pie { font-size: 11.5px; color: rgba(255,255,255,.72); }

/* ── La cabecera de la pantalla ───────────────────────────────────────────── */

.crecer-cab { background: var(--barrido); color: var(--sobre-marca); }
/* La comparten `crecer.php` y `aerocuota.php`, y sólo la segunda es superficie
   de AeroCuota. Por eso el azul de la submarca entra por un modificador y no
   por la base: teñir `.crecer-cab` lo filtraría al Programa Crecer, que el ADR
   0008 deja fuera. Dos clases ganan por especificidad, no por orden — el mismo
   patrón que `.crecer-avion.es-oscuro`. */
.crecer-cab.es-aero { background: var(--aerocuota); }
/* `padding-block` y no `padding`, que es la corrección: el atajo ponía `0` a
   los lados y le comía a `.contenedor` su `padding-inline`. No se veía mientras
   la ventana fuera más ancha que el contenedor, porque el `margin-inline: auto`
   sobraba de los lados y hacía de margen; en el ancho exacto —1280 con el
   contenedor a 1280— ese margen es cero y el símbolo de AeroCuota quedaba
   cortado contra el borde. Es el ancho en que `npm run vista` captura, así que
   llevaba tiempo en las capturas: ninguna invariante lo mira porque no se
   desborda, se pega. Reponerlo a mano tampoco servía —el contenedor pasa de 18
   a 28 px al ensanchar— y dejaba la cabecera diez píxeles fuera de eje con el
   cuerpo. Lo único que hay que hacer es no tocarlo. */
.crecer-cab__caja { padding-block: 26px 24px; }
.crecer-cab__fila { display: flex; align-items: center; gap: 15px; }
.crecer-cab h1 { color: var(--sobre-marca); margin: 0; font-size: 22px; letter-spacing: -.6px; }
.crecer-cab p { margin: 3px 0 0; font-size: 12.5px; color: rgba(255,255,255,.72); }
.crecer-cab__stats { display: flex; margin-top: 20px; padding-top: 16px; border-top: 1px solid rgba(255,255,255,.14); }
.crecer-cab__stats > div { flex: 1; text-align: center; }
/* En ancho, las dos cifras dejan de repartirse la pantalla: con `flex: 1` sobre
   1200 px quedaban una a un cuarto y la otra a tres cuartos, dos números solos
   flotando en el vacío. Juntas y centradas se leen como un par. */
@media (min-width: 768px) {
  .crecer-cab__stats { justify-content: center; gap: 140px; }
  .crecer-cab__stats > div { flex: 0 0 auto; }
}
.crecer-cab__stats strong { display: block; font-size: 19px; font-weight: 800; letter-spacing: -.57px; }
.crecer-cab__stats span { font-size: 10.5px; font-weight: 600; color: rgba(255,255,255,.65); letter-spacing: .21px; }

/* El cupo y «Tu nivel», lado a lado en ancho. Apiladas a 460 px, las dos
   tarjetas dejaban la mitad derecha de la pantalla vacía — el hueco se leía
   como maquetado a medias, no como aire. En móvil el par se apila solo. */
.aero-par { display: grid; grid-template-columns: 1fr; gap: var(--gap); margin-top: 20px; }
@media (min-width: 900px) {
  /* `stretch` y las dos tarjetas al 100 %: con `start`, la más corta terminaba
     antes y el par se veía desnivelado por abajo. */
  .aero-par { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: stretch; }
  .aero-par > .bloque { height: 100%; }
  .aero-par .crecer-nivel-t { height: 100%; box-sizing: border-box; align-items: center; }
}

/* El trato, en una línea, para la cabecera de AeroCuota.
   Reemplaza a los tres números: el disponible se repetía 227 px más abajo con
   su total y su riel, y la inicial y el plazo son constantes de la plataforma
   —el ADR 0007 decidió que no hay selector— que no se comparan con nada. Tres
   columnas de 427 px a 1280, una cifra en cada una, era el primero y el sexto
   de los rastros del ADR 0006 a la vez. Gemela del prop `pie` de
   `CabeceraMarca.tsx`. Ver el ADR 0012. */
.crecer-cab__trato {
  margin: 18px 0 0; padding-top: 14px;
  border-top: 1px solid rgba(255,255,255,.14);
  font-size: 13px; font-weight: 600; line-height: 18px;
  letter-spacing: -.13px; color: rgba(255,255,255,.92);
}
/* Más apagado que lo que separa: tiene que dejar leer los tres trozos como
   tres, no competir con ellos. */
.crecer-cab__punto { color: rgba(255,255,255,.45); }

/* ── El pie: el puente a la otra pantalla, y la ayuda ─────────────────────── */
/* Lo usan AeroCuota y el Programa Crecer, y cada una es la salida de la otra:
   «Más cupo» allá, «Tu cupo en AeroCuota» aquí. Eran una sección más, con
   título de 18 px y la misma separación de 34 px que el resto. No son capítulos
   de su pantalla: son la puerta a la otra, y el ADR 0007 la pide en los dos
   sentidos. Como rótulo de pie siguen estando y dejan de competir.

   `--espacio-corte` y no `--espacio-seccion`: es el cambio de registro que
   `.seccion--respaldo` ya marca en la portada. Con una sola separación no hay
   jerarquía posible — la jerarquía es la diferencia entre dos separaciones.

   Nacieron como `.aero-pie` en el ADR 0012 y se destiñeron al llegar la
   segunda: el enlace era `var(--aero)`, y Crecer no es ninguna de las cuatro
   superficies del ADR 0008. El azul entra ahora por `.es-aero`, que es el mismo
   patrón de `.crecer-compras__mas.es-aero`: modificador de dos clases, que gana
   por especificidad y no por orden. */
.pie { margin-top: var(--espacio-corte); }
.pie__rotulo {
  margin: 0; font-size: 13px; font-weight: 700;
  letter-spacing: .26px; text-transform: uppercase; color: var(--texto-2);
}
.pie__ayuda {
  margin: 4px 0 14px; font-size: 12.5px; font-weight: 500; line-height: 17px;
  color: var(--texto-3);
}

/* Ayuda, no acción. Era el segundo botón a ancho completo, con el mismo peso
   que el puente, para algo que hoy contesta «todavía no está disponible». Darle
   el botón más pesado de la pantalla a lo único que no existe es al revés.

   El `padding` no es cosmético: le da los 44 px de área que un dedo necesita
   sin agrandar el texto, igual que `.crecer-compras__mas`. */
.pie-ayuda { margin: 20px 0 0; text-align: center; }
.pie-ayuda__enlace {
  padding: 13px 12px; border: 0; background: none; cursor: pointer;
  font-size: 12.5px; font-weight: 700; letter-spacing: -.13px; color: var(--brand-600);
}
.pie-ayuda__enlace.es-aero { color: var(--aero); }
.pie-ayuda__enlace:hover { text-decoration: underline; }

/* ── El Programa Crecer en escritorio ─────────────────────────────────────── */
/* Hasta ahora no había una sola regla .crecer-* en un media query: todo estaba
   diseñado para un teléfono de 390px y nunca se miró ancho. En 1280 la tabla de
   cincuenta filas, la lista de niveles y el calendario se estiraban de borde a
   borde con el contenido pegado a los extremos.

   El patrón no se inventa: es el mismo `.col-resumen` sticky que ya usan
   carrito y checkout — una columna fluida y una fija que acompaña el scroll. */

@media (min-width: 768px) {
  /* Aquí vivía `.crecer-web__par`, la rejilla de dos columnas que ponía «Mi
     nivel» a la izquierda y la escalera a la derecha. Las dos secciones se
     fueron a AeroCuota (ADR 0018) y la rejilla con ellas; lo que queda de Crecer
     —eventos, insignias y tabla— son bloques de ancho completo, que es lo que
     `.contenedor` ya hace. */

  /* Las cuotas por pagar, una compra al lado de la otra. Dos columnas fijas y
     no `auto-fit`: con `minmax(280px,1fr)` el navegador arma cuatro pistas de
     280px en 1120 y las dos compras se apretaban en la mitad izquierda con
     media pantalla vacía al lado. */
  .crecer-compras { display: grid; grid-template-columns: 1fr 1fr; align-items: start; }
  .crecer-compras__mas { grid-column: 1 / -1; }

  /* ── AeroCuota: el cupo y las cuotas, lado a lado ──────────────────────────
     A 1280 esto era una columna estirada a todo el ancho, y lo que fallaba no
     era la posición sino el vacío: la fila superior del bloque de cupo
     terminaba en el píxel 228 de 1252 —el 84 % de la tarjeta vacío— y el riel
     medía 1192 px para pintar 204.

     El reparto es **asimétrico** a propósito, y ésa es la diferencia con
     `.crecer-web__alto`. El cupo es una cifra y un riel: no gana nada con 612
     px, y con `1fr 1fr` repetía su propio defecto a media escala. Las cuotas sí
     crecen — son dos compras con su calendario.

     Y el pie cae debajo del cupo, no debajo de todo. No es relleno: el ADR 0007
     dice que el puente entre las dos pantallas *es el cupo*, así que «de cuánto
     dispongo» y «cómo consigo más» se leen juntas. Con el pie fuera, la columna
     izquierda dejaba 312 px vacíos. Las áreas hacen falta porque el orden del
     marcado es el del teléfono —cupo, cuotas, pie— y ahí manda ése. */
  .aero-web__par {
    display: grid;
    grid-template-columns: minmax(320px, .72fr) 1fr;
    grid-template-areas: "cupo cuotas" "pie cuotas";
    grid-template-rows: auto 1fr;
    gap: 0 36px;
    align-items: start;
  }
  .aero-web__par > .seccion { margin-top: 20px; }
  .aero-web__par > .seccion:first-child { grid-area: cupo; }
  .aero-web__par > .seccion--destacada { grid-area: cuotas; }
  .aero-web__par > .pie { grid-area: pie; }

  /* Dentro del par, las dos compras vuelven a apilarse: la columna derecha ya
     no tiene 1224 px que repartir. */
  .aero-web__par .crecer-compras { grid-template-columns: 1fr; }

  /* La banda deja de sangrar cuando deja de ir de borde a borde: dentro de una
     columna, un fondo que se escapa por los lados es un error de caja, no un
     sangrado. Se cierra con el radio y el borde de las demás superficies. */
  .aero-web__par .seccion--destacada {
    margin-inline: 0;
    padding: var(--espacio-bloque);
    border: 1px solid var(--borde);
    border-radius: var(--r-lg);
  }

  /* Las insignias ganadas y, en la última celda, la línea de las que faltan.
     Eran seis escudos idénticos en seis columnas de 204 px para dibujar 96 —el
     defecto del riel de AeroCuota a media escala—.

     En escritorio las seis entran a la vez, así que el carrusel deja de
     desplazarse y se reparte: **un carrusel cortado dice «hay más», y aquí no
     hay más.** Es la misma corrección que ya se le hizo a los dos banners de la
     portada. Los puntos se van con él — no cuentan nada si no hay páginas.

     **Tres columnas y no seis**, aunque las seis quepan de ancho: el escudo mide
     112 px fijos —lo dibuja `cei_escudo()`, no el CSS—, y a 768 px seis columnas
     dan 109,5 px cada una. Dos píxeles y medio de escudo asomando por celda es
     justo el tipo de desborde que se ve como un error de alineación. */
  .crecer-carrusel { overflow-x: visible; margin-inline: 0; padding-inline: 0; }
  .crecer-carrusel__pista {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: 18px;
  }
  .crecer-carrusel .crecer-insignia { width: auto; }
  .crecer-puntos { display: none; }
}

/* Y en escritorio de verdad, las seis en una fila: a 1024 la columna ya mide más
   que el escudo de 112, así que dos filas de tres eran aire de sobra apilado. */
@media (min-width: 1024px) {
  .crecer-carrusel__pista { grid-template-columns: repeat(6, minmax(0, 1fr)); }

  /* La tabla en dos columnas: veinticinco y veinticinco cuando está desplegada,
     seis y seis mientras asoman los diez y tu vecindario. El corte por columnas
     lo hace el navegador, así que el orden se lee hacia abajo y después a la
     derecha —que es como se lee una clasificación. */
  /* Un botón de 1120px de ancho no se lee como un botón. */
  .crecer-web-ayuda { max-width: 420px; margin-inline: auto; }

  .crecer-tabla { columns: 2; column-gap: 0; }
  .crecer-tabla__fila { break-inside: avoid; }
  .crecer-tabla__fila:nth-child(1) { border-top: 0; }
}

/* ── Las formas de pago: la elegida se abre, las otras se encogen ─────────── */
/* Gemela de `Opcion` en la app. La caja de afuera se lleva el borde, el fondo y
   el radio; la .opcion de adentro queda como pura fila de cabecera. Por eso hay
   que desarmarle a .opcion —que vive en app.css y no se toca— el marco que trae
   para la lista de entrega, donde sigue usándose tal cual. */
.pago-caja {
  border: 1.5px solid var(--borde); border-radius: 16px;
  background: var(--fondo); margin-bottom: 10px; overflow: hidden;
  transition: border-color var(--transicion), background var(--transicion);
}
.pago-caja > .opcion { border: 0; border-radius: 0; background: none; margin: 0; }
.pago-caja.es-activa { border-color: var(--brand-500); background: var(--brand-050); }
.pago-caja.es-activa > .opcion.activa { background: none; }

/* Encogida: una línea. El detalle se va y el alto baja de 74 a 46. */
.pago-caja.es-compacta > .opcion { padding: 12px 15px; gap: 11px; }
.pago-caja.es-compacta .opcion__texto span,
.pago-caja.es-compacta .etq { display: none; }
.pago-caja.es-compacta .opcion__texto strong { font-size: 13.5px; font-weight: 600; color: var(--texto-2); }
.pago-caja.es-compacta .ico { width: 19px; height: 19px; }
/* Comprimir una tarjeta abierta la despega del detalle que la acompaña. Ya está
   elegida: no hay nada que confirmar con un rebote. */
.pago-caja.es-activa > .opcion:active { transform: none; }

/* El detalle, sobre el fondo de la tarjeta y no sobre el teñido: es contenido,
   no parte del estado elegido. */
.pago-caja__desplegado { padding: 4px 13px 13px; }
.pago-caja.es-compacta .pago-caja__desplegado { display: none; }

/* La forma de pago que queremos que se vea antes que las otras. Sólo el borde:
   el fondo teñido es de «elegida», y confundir los dos estados haría que la
   destacada pareciera ya seleccionada.

   **Se queda en el azul de la casa aunque la destacada sea la de AeroCuota.**
   Es el único estado que puede verse al lado de otra caja elegida, y
   `--aero-clara` contra `--brand-500` están a un tono: las dos se leerían como
   elegidas. `--brand-400` es más claro que los dos y se lee como «resaltada». */
.opcion--destacada { border-color: var(--brand-400); }
.opcion--destacada .etq { flex: none; margin-left: auto; }
/* Sobre la opción elegida el fondo ya es el tenue, que es el de la etiqueta: en
   tenue sobre tenue la píldora desaparece y queda el texto flotando. Elegida,
   la etiqueta se pone maciza. */
.pago-caja.es-activa .etq--nuevo { background: var(--brand-600); color: var(--sobre-marca); }

/* ── AeroCuota elegida: la cuarta superficie del ADR 0008 ─────────────────────
   Sólo esta caja, y sólo estando elegida. Tres clases contra las dos de
   `.pago-caja.es-activa`: gana por especificidad y no por orden.

   `--aero-tenue` es el sexto tono que este repositorio deriva y la marca no
   publica: con `--aero-100` esta caja queda más oscura que las otras cinco y
   «elegida» pasa a significar dos cosas según el método de pago. Ver ADR 0010. */
.pago-caja.es-activa.opcion--destacada {
  border-color: var(--aero-clara); background: var(--aero-tenue);
}
.pago-caja.es-activa.opcion--destacada .opcion.activa .opcion__radio { border-color: var(--aero-clara); }
.pago-caja.es-activa.opcion--destacada .opcion.activa .opcion__radio::after { background: var(--aero-clara); }
.pago-caja.es-activa.opcion--destacada .etq--nuevo { background: var(--aero); }
/* Sin elegir la píldora también es de AeroCuota: es la única «Nuevo» que hay, y
   vive sobre esta opción. Pisa a `app.css:299`, que se enlaza antes. */
.opcion--destacada .etq--nuevo { background: var(--aero-tenue); color: var(--aero-fuerte); }
/* El avión, en el azul de la submarca. Sólo éste: los otros cinco iconos siguen
   en navy heredado, que es lo que ya hacían. (Y ahí hay una divergencia vieja
   que este trabajo no toca: la app los pinta a los seis en `marcaClara`.) */
.opcion--destacada > .opcion > .ico { color: var(--aero-clara); }

/* ── La lupa sobre la foto de la publicación ─────────────────────────────────
   Gemela de `VisorFoto.tsx` y de `assets/js/zoom.js`, que explica los porqués.

   `overflow: hidden` es el mecanismo y no un adorno: es lo que recorta la foto
   ampliada dentro de su caja. `.galeria` ya venía con `position: relative` desde
   `app.css`; el recorte se suma aquí porque `app.css` es intocable.

   La transición va sólo en la ENTRADA de la lente. Al salir el `transform` se
   borra de golpe a propósito: animar la vuelta deja la foto encogiéndose bajo
   un cursor que ya se fue, y se lee como que la página se quedó pensando. */

.galeria[data-zoom] { overflow: hidden; }
.galeria[data-zoom] img { transition: transform var(--transicion); }
.galeria[data-zoom].es-lente img { transition: none; }
/* `con-lente` la pone `zoom.js`, y no un media query, porque no basta con el
   puntero fino: el aumento tiene que valer la pena, y eso depende del ancho de
   la galería contra el lado de la foto. Ver el bloque de AUMENTO_MINIMO allá. */
.galeria[data-zoom].con-lente { cursor: zoom-in; }
.galeria[data-zoom]:not(.con-lente) { cursor: pointer; }

/* ── Miniaturas de la galería (obs 10) ───────────────────────────────────────
   Sólo aparecen cuando el vendedor subió más de una foto. La activa se marca
   con el borde de marca; al tocar una, `detalles.php` cambia el `src` de la
   foto grande, que es la que ve la lupa. */
.miniaturas {
  display: flex; gap: 8px; margin-top: 10px;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scroll-padding-inline: 0;
}
.miniatura {
  flex: 0 0 auto; width: 64px; height: 64px; padding: 0;
  border: 1.5px solid var(--borde); border-radius: var(--r-sm);
  background: var(--superficie); overflow: hidden; cursor: pointer;
}
.miniatura img { width: 100%; height: 100%; object-fit: cover; display: block; }
.miniatura.es-activa { border-color: var(--marca); }

/* ── Chips de variante (obs 10): tallas, colores… ───────────────────────────
   Selección visual dentro de cada grupo. No viaja al checkout todavía. */
.chip-opcion {
  border: 1.5px solid var(--borde-fuerte); border-radius: var(--r-sm);
  background: var(--fondo); color: var(--texto-2);
  padding: 8px 14px; font-size: 13.5px; font-weight: 600; cursor: pointer;
}
.chip-opcion.es-activa {
  border-color: var(--marca); background: var(--brand-050); color: var(--marca);
}

/* ── Preguntas y reseñas (obs 11 / 12) ──────────────────────────────────────── */
.pregunta-form { display: flex; gap: 8px; align-items: flex-start; }
.pregunta-form textarea {
  flex: 1; min-width: 0; resize: vertical; font: inherit; font-size: 14px;
  padding: 10px 12px; border: 1.5px solid var(--borde); border-radius: var(--r-sm);
  background: var(--fondo); color: var(--texto);
}
.pregunta-form button { flex: 0 0 auto; }
.pregunta { padding: 12px 0; border-bottom: 1px solid var(--borde); }
.pregunta:last-child { border-bottom: 0; }
.pregunta__q { margin: 0; font-weight: 600; font-size: 14px; color: var(--texto); display: flex; gap: 6px; }
.pregunta__r { margin: 6px 0 0 21px; font-size: 13.5px; color: var(--texto-2); line-height: 1.5; }
.pregunta__pend { margin: 4px 0 0 21px; }

.resena { padding: 12px 0; border-bottom: 1px solid var(--borde); }
.resena:last-child { border-bottom: 0; }
.resena__cab { display: flex; gap: 8px; align-items: center; }
.resena__estrellas { color: var(--dinero); letter-spacing: 1px; }
.resena__autor { font-weight: 700; font-size: 13.5px; color: var(--texto); }
.resena__texto { margin: 6px 0 0; font-size: 13.5px; color: var(--texto-2); line-height: 1.5; }
.resenas-cab { display: flex; gap: 10px; align-items: baseline; margin-bottom: 10px; }
.resenas-cab__prom { font-size: 26px; font-weight: 800; color: var(--texto); }
.resenas-cab__estrellas { color: var(--dinero); letter-spacing: 1px; font-size: 15px; }

/* Formulario para dejar una reseña (compra entregada) */
.resena-form { padding: 12px 0; border-bottom: 1px solid var(--borde); }
.resena-form:last-child { border-bottom: 0; }
.resena-form__quien { margin: 0 0 8px; font-size: 14px; color: var(--texto); }
.resena-estrellas { display: flex; gap: 2px; margin-bottom: 8px; }
.resena-estrella {
  border: 0; background: none; cursor: pointer; padding: 0 2px;
  font-size: 24px; line-height: 1; color: var(--borde-fuerte);
}
.resena-estrella.es-activa { color: var(--dinero); }
.resena-coment {
  width: 100%; resize: vertical; font: inherit; font-size: 14px; box-sizing: border-box;
  padding: 10px 12px; border: 1.5px solid var(--borde); border-radius: var(--r-sm);
  background: var(--fondo); color: var(--texto); margin-bottom: 8px;
}
.resena-form__gracias { margin: 0; font-weight: 700; color: var(--ok-600); }

/* El visor: la foto sola, encima de todo. Negro y no el navy de la casa —lo que
   tiene que verse es la foto, y cualquier tinte se le mete por el borde—. */
.visor {
  position: fixed; inset: 0; z-index: 61;
  display: none; align-items: center; justify-content: center;
  padding: 20px;
}
.visor.abierto { display: flex; }
.visor img { max-width: 100%; max-height: 100%; object-fit: contain; }
.visor__cerrar {
  position: absolute; top: 16px; right: 16px;
  width: 44px; height: 44px; border: 0; border-radius: 22px;
  display: grid; place-items: center;
  background: rgba(255,255,255,.16); color: var(--sobre-marca);
  cursor: pointer;
}

/* ── Mis compras y el detalle de una compra ───────────────────────────────────

   Gemelas de `(tabs)/compras.tsx` y `compra/[numero].tsx`. Todo el porqué está
   en el ADR 0014; lo que importa para leer estas reglas es una sola frase: **la
   pantalla la manda lo que todavía te compromete**, así que la línea de lo
   pendiente es lo único con peso propio dentro de la tarjeta.

   Lo que había antes, medido: a 390 la ficha era 497 px con **79 % de aire**, y
   a 1280 medía 1224 de ancho con **94 %** — la fila «Fecha … 18 de agosto»
   dejaba 1085 px de canaleta entre la etiqueta y el valor, peor que el riel de
   1192-para-204 que el ADR 0012 midió en AeroCuota. Una lista etiqueta/valor no
   se estira: se le pone contenido a las tres zonas o se le acota el ancho. */

.compras { display: grid; gap: 12px; }

.compra { display: block; padding: 16px; color: inherit; text-decoration: none; }
.compra__que { display: flex; align-items: flex-start; gap: 12px; }

/* El borde no es adorno: la mitad del catálogo son fotos de estudio con fondo
   blanco, y `--superficie` es un gris de dos puntos. En 62 px eso deja un
   recuadro que no se lee —los audífonos blancos parecen un hueco en la tarjeta—
   y la foto se pierde. Se vio en el teléfono, y aquí pasaba igual. */
.compra__foto {
  flex: none; width: 62px; height: 62px; border-radius: 13px;
  overflow: hidden; background: var(--superficie); display: block;
  border: 1px solid var(--borde);
}
.compra__foto img { width: 100%; height: 100%; object-fit: cover; display: block; }

.compra__texto { flex: 1; min-width: 0; display: block; }
.compra__titulo {
  display: block; font-size: 12.5px; font-weight: 600; line-height: 1.35;
  color: var(--texto); letter-spacing: -.01em;
}
.compra__extras,
.compra__fecha { display: block; font-size: 12.5px; font-weight: 500; color: var(--texto-3); }
/* En qué va el pago de la compra (spec 0006). Cálido y no rojo cuando falta
   reportar: es dinero pendiente, no un error — y el ADR 0010 reserva el cálido
   justo para eso. Sin `--falta` se lee como un dato más, que es lo que es
   mientras nadie tenga que hacer nada. */
.compra__pago { display: block; margin-top: 4px; font-size: 12.5px; font-weight: 600; color: var(--texto-3); }
.compra__pago--falta { color: var(--dinero-texto); }
.compra__extras { margin-top: 1px; }
.compra__fecha { margin-top: 4px; }

.compra__plata { flex: none; display: block; text-align: right; }
.compra__plata b { font-size: 16px; font-weight: 800; letter-spacing: -.02em; }
/* El número de compra: 11,5 y `texto-3`. Es con lo que se reclama, no con lo
   que se decide, y estaba arriba compitiendo con la etiqueta de estado. */
.compra__numero {
  display: block; margin-top: 3px;
  font-size: 11.5px; font-weight: 500; color: var(--texto-3);
}

.compra__pendiente {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 13px; padding-top: 12px; border-top: 1px solid var(--borde);
}
/* En dos renglones y no en uno: «Faltan 3 cuotas · $42,68 el 31 de agosto» no
   entra a 390 al lado de la etiqueta, y al envolverse partía también la etiqueta
   en dos líneas. Apilado se lee mejor de todos modos — el conteo manda y el
   detalle queda debajo en tenue— y a 1280 sigue cabiendo de sobra. */
.compra__debe {
  margin: 0; min-width: 0;
  font-size: 13px; font-weight: 700; color: var(--texto);
}
.compra__cuando {
  display: block; margin-top: 2px;
  font-size: 12.5px; font-weight: 500; color: var(--texto-3);
}
/* La etiqueta de estado no se parte: es una pastilla, y una pastilla en dos
   líneas se lee como un error de la página. */
.compra__pendiente .etq { flex: none; white-space: nowrap; }

/* El detalle. Las dos columnas reparten por lo que se hace con cada una: a la
   izquierda lo que se consulta —el seguimiento y las cuotas—, a la derecha lo
   que se comprueba una vez. No es el reparto de AeroCuota copiado: allá eran un
   cupo y un calendario, aquí es consultar contra comprobar. */
.compra-det { display: grid; gap: var(--espacio-seccion); }
.compra-det__ref { display: flex; align-items: center; gap: 10px; margin: 10px 0 0; }
.compra-det__bs { margin: 2px 0 0; text-align: center; }

/* ── Cuántas cuotas pagas de una (observación 38) ─────────────────────────────
   Envuelven en vez de deslizarse: son tres o seis y caben en dos filas, y un
   riel que casi nunca se desliza esconde opciones sin avisar. Los 54 px de alto
   salen de las dos líneas y de paso dejan el objetivo táctil bien por encima de
   los 44. Gemelo de los chips de `compra/[numero].tsx`. */
.pago-cuotas { margin-bottom: 15px; }
.pago-cuotas__chips { display: flex; flex-wrap: wrap; gap: 8px; }
.pago-chip {
  flex: 0 0 auto; min-width: 96px; min-height: 54px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  padding: 9px 13px; cursor: pointer;
  border: 1.5px solid var(--borde); border-radius: 13px; background: var(--fondo);
}
.pago-chip strong { font-size: 13px; font-weight: 700; letter-spacing: -.01em; color: var(--texto-2); }
.pago-chip span { font-size: 12px; font-weight: 600; color: var(--texto-3); }
/* Encendido se pinta entero de marca: con la cifra en `--texto-3` sobre el azul
   lavado quedaba más apagada que la del chip de al lado, y la cifra es
   justamente lo que se compara entre chips. */
.pago-chip.es-activa { border-color: var(--marca); background: var(--brand-050); }
.pago-chip.es-activa strong, .pago-chip.es-activa span { color: var(--marca); }
.pago-cuotas__ayuda { margin: 9px 0 0; font-size: 11.5px; line-height: 1.39; color: var(--texto-3); }

.compra-linea {
  display: flex; gap: 13px; align-items: flex-start;
  padding: 15px 0; border-bottom: 1px solid var(--borde);
  color: inherit; text-decoration: none;
}
.compra-linea__foto {
  flex: none; width: 80px; height: 80px; border-radius: 15px;
  overflow: hidden; background: var(--superficie); display: block;
  border: 1px solid var(--borde);
}
.compra-linea__foto img { width: 100%; height: 100%; object-fit: cover; display: block; }
.compra-linea__que { flex: 1; min-width: 0; display: grid; gap: 5px; }
.compra-linea__que strong {
  font-size: 13px; font-weight: 500; line-height: 1.32; color: var(--texto-2);
}
.compra-linea__que .tenue { font-size: 12.5px; }

@media (min-width: 1120px) {
  /* La tarjeta pasa de dos filas a una, y lo pendiente se mete **entre** el
     título y el precio.

     Se probó antes acotarla a 720 px y no sirvió: dejaba 532 px muertos a la
     derecha, más que los 280 que el ADR 0013 corrigió en Crecer, y la tarjeta
     seguía con 84 % de aire. El defecto de la ficha vieja no era el ancho sino
     que sólo tenía dos cosas que decir en 1224 px; con cuatro zonas de contenido
     real —qué compraste, qué falta, cuánto, en qué estado— el ancho se usa en
     vez de repartirse en canaletas.

     `display: contents` sobre `.compra__que` sube sus tres hijos al flex de la
     tarjeta, que es lo que permite ordenar la línea de pendiente delante del
     precio sin tocar el marcado que el teléfono necesita apilado. */
  .compra { display: flex; align-items: center; gap: 18px; }
  .compra__que { display: contents; }
  .compra__foto { order: 1; }
  .compra__texto { order: 2; }
  .compra__pendiente {
    order: 3; flex: none; width: 290px;
    margin: 0; padding: 0; border-top: 0;
  }
  .compra__plata { order: 4; }

  .compra-det { grid-template-columns: minmax(320px, .72fr) 1fr; align-items: start; }
  /* El pie de ayuda cae debajo de la columna derecha y no centrado en 1224 px,
     que lo dejaba flotando lejos de todo. */
  .compra-det + .pie-ayuda { max-width: 720px; }

  /* ── Las zonas del detalle (revisión del 31-08) ──────────────────────────
     A este ancho la mitad de las secciones tenía caja y la otra mitad flotaba
     sobre el fondo — el quinto rastro del ADR 0006. Cada zona gana la tarjeta
     del sistema (la receta de .bloque) SOLO aquí: en el teléfono la página
     queda apilada y sin cajas, que es como la tiene la app. */
  .compra-det__sigue, .compra-det__que { display: grid; gap: var(--espacio-seccion); align-content: start; }
  /* El ritmo entre zonas lo pone el gap; el margen que las secciones traían
     pasa al par entero, que lo separa de la cabecera de la página. */
  .compra-det__sigue > .seccion, .compra-det__que > .seccion { margin-top: 0; }
  .compra-det { margin-top: 30px; }

  .compra-det__zona, .compra-det__compra {
    background: var(--blanco); border-radius: 20px;
    box-shadow: var(--sombra-1), inset 0 0 0 1px rgba(12, 32, 67, .07);
  }
  .compra-det__zona { padding: 20px 20px 0; }

  /* «Tu compra»: los artículos y su total en una sola tarjeta, con el resumen
     como pie de ticket. */
  .compra-det__compra { overflow: hidden; }
  .compra-det__compra > #compra-articulos { padding: 2px 20px 0; }
  .compra-det__compra .compra-linea:last-child { border-bottom: 0; }
  .compra-det__compra > .resumen { border-radius: 0; border-top: 1px solid var(--borde); }

  /* La fila del artículo usa el ancho: el precio a la derecha, no apilado
     bajo el título con el resto de la fila vacía. El mismo movimiento que
     .compra hizo arriba con display: contents. */
  .compra-det__compra .compra-linea {
    display: grid; grid-template-columns: auto 1fr auto;
    column-gap: 16px; row-gap: 4px; align-items: center;
  }
  .compra-det__compra .compra-linea__que { display: contents; }
  .compra-det__compra .compra-linea__foto { grid-row: 1 / span 2; }
  .compra-det__compra .compra-linea__que strong { grid-column: 2; align-self: end; }
  .compra-det__compra .compra-linea__que .tenue { grid-column: 2; grid-row: 2; align-self: start; }
  .compra-det__compra .compra-linea__precio { grid-column: 3; grid-row: 1 / span 2; }

  /* El pie del ticket: etiqueta y valor juntos a la derecha, no en las dos
     puntas — esa canaleta de 700 px es la misma que esta pantalla ya había
     matado en la ficha vieja (ver el comentario del par, arriba). */
  .compra-det__compra .resumen__fila { justify-content: flex-end; gap: 16px; }
  .compra-det__compra .compra-det__bs { text-align: right; }
}

/* Publicación impulsada (plan del vendedor o impulso puntual). La etiqueta
   ('Destacado'/'Patrocinado') la decide el backend; el color es navy —marca
   neutra—, ni el azul de AeroCuota ni un estado. Vive aquí porque la base
   .etq es de app.css (intocable). */
.etq--destacado {
  background: var(--navy);
  color: var(--blanco);
  border-radius: 8px;
  letter-spacing: .01em;
}

/* Carrusel de la entrada: se desliza solo, sin fin y en todos los anchos (no se
   convierte en rejilla en escritorio). Se arrastra con el mouse o el dedo. La
   especificidad de [data-hero] le gana a la regla de escritorio de la sección 5.
   Sin scroll-snap: el deslizamiento es continuo, no de a saltos. */
.inicio-entrada__promo .carrusel[data-hero] {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: none;
  scroll-behavior: auto;
  margin-inline: 0;
  padding-inline: 0;
  cursor: grab;
  user-select: none;
}
.inicio-entrada__promo .carrusel[data-hero].arrastrando { cursor: grabbing; }
.inicio-entrada__promo .carrusel[data-hero] img { -webkit-user-drag: none; }
.inicio-entrada__promo .carrusel[data-hero] > .banner--entrada {
  flex: 0 0 86%;
  max-width: 560px;
  scroll-snap-align: none;
}

/* El corazón de la barra de compra se rediseñó como botón con borde y fondo
   propios (estilo inline). Pero .fav-btn arrastra un `::before` —el disco blanco
   de las tarjetas— posicionado en absoluto con `inset` + `border-radius:50%`. El
   inline le pone `position:static`, así que ese `::before` deja de anclarse al
   botón y se estira contra un ancestro grande: sale como un ÓVALO blanco borroso
   ENCIMA de "Agregar" y "Comprar ahora". Aquí el botón ya tiene su fondo, así que
   el disco sobra: se oculta (móvil y escritorio). */
.barra-compra .fav-btn::before { display: none; }

/* AeroCuota «Próximamente»: la pastilla del estado a la derecha de la marca, y
   el «Conócela ›» siempre a la vista (la tarjeta ya no muestra cupo). */
.aero-tarjeta__pronto-etq {
  margin-left: auto;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .18);
  color: var(--blanco);
}
.aero-tarjeta--pronto .aero-tarjeta__pie .aero-tarjeta__ver { display: inline-flex; }

/* AeroCuota «Próximamente» en el checkout: la forma de pago se anuncia pero no
   se puede elegir. Píldora neutra (ni el azul de AeroCuota ni un estado), y la
   caja atenuada y sin puntero para que se lea como deshabilitada. La base .etq
   es de app.css (intocable), así que la variante vive aquí. */
.etq--proximamente {
  background: var(--borde);
  color: var(--texto-2);
  border-radius: 999px;
  letter-spacing: .01em;
}
.pago-caja.es-proximamente { opacity: .62; }
.pago-caja.es-proximamente .opcion { cursor: default; pointer-events: none; }

/* ── Página legal (aviso de privacidad) ───────────────────────────────────── */
/* Texto largo para leer, no una pantalla de app: una columna angosta, jerarquía
   clara y aire entre bloques. Sólo la usa privacidad.php. */
.legal { max-width: 740px; margin: 0 auto; padding: 8px 0 12px; }
.legal__cab { padding-bottom: 14px; margin-bottom: 6px; border-bottom: 1px solid var(--borde); }
.legal__cab h1 { font-size: 25px; font-weight: 800; letter-spacing: -.03em; color: var(--texto); }
.legal__fecha { margin-top: 8px; font-size: 13px; color: var(--texto-3); }
.legal__fecha strong { color: var(--texto-2); font-weight: 600; }
.legal__cuerpo h2 {
  font-size: 16px; font-weight: 800; letter-spacing: -.02em; color: var(--texto);
  margin: 28px 0 8px;
}
.legal__cuerpo p { color: var(--texto-2); line-height: 1.72; margin: 0 0 12px; }
.legal__cuerpo ul { margin: 4px 0 14px; padding-left: 22px; }
.legal__cuerpo li { color: var(--texto-2); line-height: 1.7; margin-bottom: 7px; }
.legal__cuerpo strong { color: var(--texto); font-weight: 700; }
.legal__cuerpo em { font-style: italic; }
.legal__cuerpo code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px;
  background: var(--superficie); color: var(--texto);
  padding: 2px 7px; border-radius: 7px; word-break: break-word;
}
.legal__intro { font-size: 15px; }
.legal__pie {
  margin-top: 26px; padding-top: 16px; border-top: 1px solid var(--borde);
  font-size: 13px; color: var(--texto-3);
}

/* ── Los grupos plegables del menú lateral ──────────────────────────────────
   Las categorías eran diez filas sueltas —la mitad larga del menú— antes de
   llegar a cualquier otra cosa, y con eso el orden de lo demás no se podía leer.
   Ahora se pliegan.

   Va con `<details>` y no con JavaScript porque es exactamente lo que hace, y
   así sigue funcionando con el JS apagado. Su gemelo en la app es el componente
   `Grupo` de `Cajon.tsx`, que necesita estado porque ahí no hay `<details>`. */
.drawer__grupo > summary {
  cursor: pointer;
  list-style: none;          /* Firefox */
}
.drawer__grupo > summary::-webkit-details-marker { display: none; }

/* El chevron es el último hijo del summary y gira al abrirse: el mismo objeto
   moviéndose dice «esto se abre» sin escribirlo. `margin-left:auto` lo empuja al
   borde sin necesidad de un contenedor más. */
.drawer__grupo > summary > .ico:last-child {
  margin-left: auto;
  color: var(--texto-3);
  transition: transform var(--transicion);
}
.drawer__grupo[open] > summary > .ico:last-child { transform: rotate(90deg); }

/* La línea a la izquierda ata los hijos a su grupo: sin ella, al desplegarse
   parecen filas sueltas que aparecieron en medio del menú. */
.drawer__hijos {
  margin-left: 22px;
  padding-left: 4px;
  border-left: 1.5px solid var(--borde);
}
.drawer__item--hijo { padding-left: 14px; font-weight: 500; }

/* ── Quién está adentro, en la cabecera ─────────────────────────────────────
   Gemela de la pieza de sesión de `CabeceraPrincipal` en la app. Sin sesión es
   la puerta de entrada; con sesión, el atajo al perfil. */
/* El área llega a 44 sin que el avatar crezca, que es lo mismo que se le hizo a
   `.fav-btn`: a 44 el disco le comería la fila. */
.header__sesion {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  flex: 1;
  min-width: 0;
  min-height: 44px;
  padding: 0 5px;
  border-radius: 999px;
  transition: background var(--transicion);
}
/* El nombre se acorta antes de empujar nada: la marca no cede espacio, y un
   nombre largo no puede romper la fila. */
/* El nombre se queda con lo que sobra y sólo se acorta si de verdad no entra.
   Tenía un `max-width` fijo y recortaba nombres que sí cabían. La causa de fondo
   está pedida a Alberto: `/auth/me` no devuelve el nombre, así que quien entra
   por login se ve saludado con la parte de su correo. */
.header__saludo {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--texto-2);
  letter-spacing: -.015em;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.header__avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--marca);
  color: var(--blanco);
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: -.01em;
}
.header__avatar.es-anonimo { background: var(--superficie); color: var(--texto-2); }

/* En escritorio la fila se disuelve con `display: contents` y los enlaces ya
   dicen «Perfil»: el atajo sobraría y se lleva 130 px que el buscador necesita. */
@media (min-width: 768px) {
  .header__sesion { display: none; }
}

/* ── Eventos de las empresas aliadas ─────────────────────────────────────────
 *
 * Gemelas de `BannerEvento.tsx` y de la pantalla 20 de la app.
 *
 * **La imagen va arriba y el texto debajo**, y no un velo oscuro con el texto
 * encima, que fue la primera idea. La imagen la manda una empresa aliada y lo
 * que manda no es una foto limpia: el primer evento llegó como un flyer blanco
 * con el título impreso y veinte logos alrededor. Un velo lo ensucia y pone el
 * título de la tarjeta sobre el título del flyer. Con la imagen entera arriba
 * aguantan las tres cosas que pueden llegar — foto, flyer o arte con texto. */

.crecer-eventos {
  display: grid;
  gap: var(--gap);
  grid-template-columns: 1fr;
}
@media (min-width: 768px) {
  /* `auto-fit` y no `repeat(2)`: con un solo evento, la grilla de dos columnas
     fijas dejaba media pantalla vacía a la derecha — el hueco se leía como un
     error de maquetado, no como una decisión. Con las pistas ajustadas al
     contenido y centradas, una tarjeta sola queda al medio y dos quedan a los
     lados, y las dos formas se ven a propósito. */
  .crecer-eventos {
    grid-template-columns: repeat(auto-fit, minmax(440px, 620px));
    justify-content: center;
  }
}

.evento {
  display: block;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--fondo);
  box-shadow: var(--sombra-1);
  color: inherit;
  text-decoration: none;
  transition: var(--transicion);
}
.evento:hover { box-shadow: var(--sombra-2); }

.evento__foto {
  position: relative;
  /* **La relación de la imagen y no un alto fijo.** Con 168 px la caja era
     2,11:1 y la imagen es 2,4:1, así que `cover` le comía los costados: la sala
     se veía cortada por los dos lados y nadie podía saber cuánto faltaba.

     El alto fijo existía para que dos eventos seguidos se leyeran como una lista
     y no como dos alturas distintas. Sigue valiendo: la relación es la misma
     para todos, así que a igual ancho todas miden igual. */
  aspect-ratio: 2.4;
  background: var(--superficie);
}
/* Aquí `.evento--chica` bajaba el alto a 116 px. Se fue con el alto fijo: con la
   relación puesta, achicarle la caja a uno le cambiaría el recorte, y recortar
   más una foto por su fecha es castigar la imagen en vez de jerarquizar la
   tarjeta. Lo que pesa menos lo dice el título y el sello YA PASÓ. */
.evento__foto img {
  display: block;
  width: 100%;
  height: 100%;
  /* `cover` y no `contain`: con la caja en la relación de la imagen, `cover`
     llena sin recortar nada, y sigue cubriendo el caso de la que llega con otra
     relación —el flyer que manda una empresa aliada— sin dejar franjas. */
  object-fit: cover;
}

/* El rótulo del que ya pasó. Sobre la foto y no debajo: es lo primero que hay
   que saber, antes de leer el título. */
.evento__paso {
  position: absolute;
  top: 10px;
  left: 10px;
  padding: 4px 8px;
  border-radius: 7px;
  background: rgba(12, 20, 32, .72);
  color: var(--blanco);
  font-size: 8.5px;
  font-weight: var(--peso-extrabold);
  letter-spacing: .1em;
}

.evento__que { padding: 14px; }
.evento__titulo {
  display: block;
  font-size: 17px;
  font-weight: var(--peso-extrabold);
  letter-spacing: -.03em;
  color: var(--texto);
  /* Con `nowrap` hace falta el `ellipsis`: `npm run vista` falla si un texto se
     recorta sin decirlo. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.evento--chica .evento__titulo { font-size: 15px; }
.evento__bajada {
  display: block;
  margin-top: 2px;
  font-size: 12.5px;
  font-weight: var(--peso-medium);
  color: var(--texto-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.evento__meta {
  display: block;
  margin-top: 6px;
  font-size: 12px;
  font-weight: var(--peso-semibold);
  color: var(--texto-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* El separador, más apagado que lo que separa: tiene que dejar leer los dos
   trozos como dos, no competir con ellos. */
.evento__punto { color: var(--borde); }

.evento__organizan {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
}
.evento__logo { display: block; width: auto; height: 22px; object-fit: contain; }
/* Sin logo va el nombre en texto: un logo que no llegó no se dibuja vacío. Es
   lo mismo que hacen los cinco aliados de la portada con sus siglas. */
.evento__marca {
  font-size: 11.5px;
  font-weight: var(--peso-bold);
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--texto-2);
}

/* ── La pantalla del evento ──────────────────────────────────────────────── */

.evento-cab { background: var(--superficie); }
.evento-cab__foto {
  display: block;
  width: 100%;
  /* La relación de la imagen y no un `max-height`: a 1280 px de ancho, 380 px de
     alto son 3,37:1 contra los 2,4:1 de la foto, y `cover` se comía el 29 % del
     ancho. Ésta es la pantalla donde el evento se ve entero — recortarlo aquí
     era dejarlo sin ningún lugar donde verlo completo. */
  aspect-ratio: 2.4;
  object-fit: cover;
}

.evento-pag { padding-top: 18px; }
.evento-pag__rotulo {
  margin: 0;
  font-size: 9.5px;
  font-weight: var(--peso-extrabold);
  letter-spacing: .1em;
  color: var(--texto-3);
}
.evento-pag__titulo {
  margin: 4px 0 0;
  font-size: 24px;
  font-weight: var(--peso-extrabold);
  letter-spacing: -.03em;
  color: var(--texto);
}
.evento-pag__bajada {
  margin: 4px 0 0;
  font-size: 13.5px;
  line-height: 1.45;
  font-weight: var(--peso-medium);
  color: var(--texto-2);
}

.evento-pag__cuando { margin-top: 18px; max-width: 460px; }
.evento-pag__fila {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px;
}
.evento-pag__fila.es-linea { border-top: 1px solid var(--borde); }
.evento-pag__etq {
  flex: none;
  font-size: 9.5px;
  font-weight: var(--peso-extrabold);
  letter-spacing: .1em;
  color: var(--texto-3);
}
.evento-pag__val {
  font-size: 13px;
  font-weight: var(--peso-semibold);
  color: var(--texto);
  text-align: right;
}

.evento-pag__organizan { display: flex; gap: 10px; }
/* `justify-content: flex-end` y un alto mínimo: los dos nombres tienen que
   apoyarse en la misma línea aunque uno de los dos no tenga logo todavía. Con
   el centrado, «Banco R4» flotaba a media altura al lado de un isotipo, y se
   leía como un descuido en vez de como un logo que falta. */
.evento-pag__organiza {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  min-height: 96px;
  padding: 16px 10px;
  border-radius: var(--r-md);
  background: var(--superficie);
  font-size: 12.5px;
  font-weight: var(--peso-bold);
  color: var(--texto-2);
  text-align: center;
}
.evento-pag__organiza img { display: block; width: auto; height: 30px; object-fit: contain; }

.evento-pag__parrafo {
  margin: 0 0 12px;
  font-size: 13.5px;
  line-height: 1.6;
  font-weight: var(--peso-medium);
  color: var(--texto-2);
}
.evento-pag__parrafo:last-child { margin-bottom: 0; }

/* En escritorio el cuerpo se acota a un ancho de lectura. `.contenedor` llega a
   1.280 px, y un párrafo de ese ancho son ciento cincuenta caracteres por línea:
   el ojo pierde el renglón al volver. Los bloques de dato ya venían acotados —es
   lo mismo que `aerocuota.php` hace con su tarjeta de cupo. */
@media (min-width: 768px) {
  .evento-pag__bajada,
  .evento-pag__parrafo,
  .evento-pag__organizan { max-width: 720px; }
  .evento-pag .btn--bloque { max-width: 460px; }
}

/* ── El riel de niveles ──────────────────────────────────────────────────────
 *
 * Gemelo de `ListaNiveles.tsx`, que dejó de ser una lista apilada al mudarse a
 * AeroCuota. Seis filas apiladas contestan «¿cómo es la escalera?»; al lado del
 * cupo la pregunta es «¿por qué tengo éste y cómo lo agrando?», y ésa la
 * contesta el escalón que sigue, no los seis. Ver ADR 0018. */

.crecer-riel {
  /* Sangrado: el riel llega hasta los dos bordes de la pantalla, y el margen lo
     ponen las tarjetas. Media tarjeta asomando por la derecha es lo que dice
     que hay más — un riel que termina justo en el borde parece completo. */
  margin-inline: calc(var(--margen) * -1);
  padding-inline: var(--margen);
  /* `padding-block` no es cosmético: sin él la sombra de las tarjetas queda
     cortada contra el borde del contenedor que hace scroll. */
  padding-block: 4px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* `scroll-padding` no es opcional con `mandatory`: el punto de anclaje es el
     borde del scroller, no el del padding, así que al cargar el navegador
     desplaza el riel 18 px solo para pegar la primera tarjeta al canto y se come
     el margen de la pantalla. Medido: la tarjeta quedaba en x=0 con
     `padding-left: 18px` puesto. */
  scroll-padding-inline: var(--margen);
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.crecer-riel::-webkit-scrollbar { display: none; }
.crecer-riel__pista { display: flex; gap: 11px; }

.crecer-nt {
  flex: none;
  width: 208px;
  padding: 14px;
  border-radius: var(--r-lg);
  /* Transparente y no ausente: sin borde de base, la tarjeta actual mediría tres
     píxeles más que las otras y la fila daría un salto al deslizar. */
  border: 1.5px solid transparent;
  background: var(--fondo);
  box-shadow: var(--sombra-1);
  scroll-snap-align: start;
}
.crecer-nt__cab { display: flex; align-items: center; gap: 8px; }
.crecer-nt__num {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  color: var(--blanco);
  font-size: 13.5px;
  font-weight: var(--peso-extrabold);
}
.crecer-nt__aqui {
  font-size: 8.5px;
  font-weight: var(--peso-extrabold);
  font-style: normal;
  letter-spacing: .08em;
  color: var(--marca-fuerte);
}
.crecer-nt__nombre {
  display: block;
  margin-top: 8px;
  font-size: 15.5px;
  font-weight: var(--peso-extrabold);
  letter-spacing: -.03em;
  color: var(--texto-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.crecer-nt.es-actual .crecer-nt__nombre { color: var(--texto); }
.crecer-nt__rot {
  display: block;
  margin-top: 10px;
  font-size: 9px;
  font-weight: var(--peso-extrabold);
  letter-spacing: .1em;
  color: var(--texto-3);
}
/* El cálido del dinero, como la cifra del cupo de arriba: es plata, y el
   ADR 0010 dice que lo que es estado no se tiñe de la marca. */
.crecer-nt__cupo {
  display: block;
  margin-top: 2px;
  font-size: 15px;
  font-weight: var(--peso-extrabold);
  letter-spacing: -.02em;
  color: var(--dinero-texto);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.crecer-nt__req {
  display: block;
  margin-top: 8px;
  font-size: 11.5px;
  line-height: 16px;
  font-weight: var(--peso-medium);
  color: var(--texto-3);
}
.crecer-nt__ins {
  display: block;
  margin-top: 6px;
  font-size: 11px;
  font-weight: var(--peso-semibold);
  color: var(--marca-fuerte);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Crecer: el aviso del invitado y el vacío de eventos ─────────────────────
 *
 * Dos piezas chicas que nacieron con el panel (ADR 0018). Van aquí y no como
 * `.destacada`, que no existe en esta hoja: la caja es `.bloque bloque--pad`, la
 * misma de todas las superficies blancas, y esto sólo le pone el texto. */

.crecer-aviso__titulo {
  margin: 0;
  font-size: 14.5px;
  font-weight: var(--peso-extrabold);
  letter-spacing: -.02em;
  color: var(--texto);
}
.crecer-aviso__texto {
  margin: 3px 0 0;
  font-size: 12.5px;
  line-height: 1.45;
  font-weight: var(--peso-medium);
  color: var(--texto-3);
}

/* El vacío honesto de la sección de eventos. Un renglón sobre superficie y no
   un `.vacio` con su anillo: el vacío grande es para una pantalla entera que no
   tiene nada, y aquí la pantalla sigue teniendo insignias y tabla. */
.crecer-sin-eventos {
  margin: 0;
  padding: 14px 16px;
  border-radius: var(--r-md);
  background: var(--superficie);
  font-size: 12.5px;
  line-height: 1.5;
  font-weight: var(--peso-medium);
  color: var(--texto-3);
}

/* El icono del programa en la cabecera, donde antes iba el escudo de tu nivel.
   El nivel se fue a AeroCuota y esta cabecera dejó de hablar de él. */
.crecer-cab__ico {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 62px;
  height: 62px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .14);
  color: var(--blanco);
}

/* El pie de Crecer y de AeroCuota, en escritorio. Vivían dentro de
   `.crecer-web__par` y `.aero-web__par`, que les daban una columna; al irse la
   rejilla de Crecer con los niveles (ADR 0018), su botón se estiraba a los 1.252
   px del contenedor. Un botón de ese ancho no se lee como un botón. */
@media (min-width: 768px) {
  .pie__ayuda { max-width: 720px; }
  .pie .btn--bloque { max-width: 460px; }
}

/* El anillo verde del vendedor con buena reputación.
   ────────────────────────────────────────────────────────────────────────────
   Es **el arco del logo**, con su punta maciza, y no un borde recortado. Lo
   pinta `cei_arco()` dentro del avatar (ver `cei_avatar()`), con la misma
   geometría que la app emite desde `rutas.ts`.

   El `::after` de `app.css` abría un círculo con `clip-path` sobre un borde —el
   rodeo que hacía falta para dibujar un arco sin SVG— y salía **liso, sin
   punta**: el mismo vendedor se veía distinto en cada superficie. Se apaga aquí
   porque `app.css` es intocable y sólo lo declarado después manda.

   El SVG toma el tamaño de su caja en vez de los 54px que trae escritos, así
   que el mismo arco sirve para el avatar de 44 de la fila y para el de 60 de la
   ficha. El grosor va en unidades del viewBox, o sea que escala con él. */
.avatar--top::after { content: none; }
.perfil__avatar { position: relative; }
.avatar__arco {
  position: absolute;
  inset: -5px;
  color: var(--ok-500);
  line-height: 0;
  pointer-events: none;
}
.avatar__arco svg { width: 100%; height: 100%; display: block; }

/* El QR al medio de la barra inferior (ADR 0020).
   ────────────────────────────────────────────────────────────────────────────
   Un círculo que sobresale por encima del borde, como el de Cashea: es la forma
   más fuerte que puede tener una barra de pestañas, y escanear pasó a ser una
   acción de primer nivel cuando el QR por vendedor entró en producción.

   No es una pestaña y nunca se marca activa: `escanear` es algo que haces, no un
   sitio donde te quedas.

   El `.nav__hueco` mide lo mismo que un icono para que la etiqueta «QR» caiga a
   la altura de las otras cuatro; el círculo va `absolute` encima. Si estuviera en
   el flujo empujaría el texto y esta pestaña quedaría desalineada con sus
   vecinas. Va aquí y no en `app.css`, que es intocable. */
.nav__item--qr { position: relative; }
.nav__hueco { display: block; width: 23px; height: 23px; }
.nav__qr {
  position: absolute;
  top: -22px;
  left: 50%;
  transform: translateX(-50%);
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--fondo);
  border: 2px solid var(--brand-500);
  color: var(--brand-500);
  display: grid;
  place-items: center;
  /* La sombra no es adorno: el círculo se monta sobre el contenido de la página,
     y sin ella se lee como un agujero recortado en la barra en vez de como un
     botón que flota encima. */
  box-shadow: 0 3px 10px rgba(12, 32, 67, .14);
}

/* El visor del escáner de QR (escanear.php).
   ────────────────────────────────────────────────────────────────────────────
   Mismo dibujo que el de la app: el vídeo a pantalla ancha, un marco de cuatro
   esquinas y la ayuda debajo. El marco no recorta ni limita la lectura —el
   decodificador mira el cuadro entero—: es para que la persona sepa dónde
   apuntar, que es la mitad de que un escáner funcione. */
.escaner {
  position: relative;
  aspect-ratio: 3 / 4;
  max-height: 68vh;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: #000;
}
.escaner video { width: 100%; height: 100%; object-fit: cover; display: block; }
.escaner__velo {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  pointer-events: none;
}
.escaner__marco { position: relative; width: 240px; height: 240px; }
.escaner__esq { position: absolute; width: 34px; height: 34px; border: 0 solid var(--blanco); }
.escaner__esq--tl { top: 0; left: 0; border-top-width: 3px; border-left-width: 3px; border-top-left-radius: 12px; }
.escaner__esq--tr { top: 0; right: 0; border-top-width: 3px; border-right-width: 3px; border-top-right-radius: 12px; }
.escaner__esq--bl { bottom: 0; left: 0; border-bottom-width: 3px; border-left-width: 3px; border-bottom-left-radius: 12px; }
.escaner__esq--br { bottom: 0; right: 0; border-bottom-width: 3px; border-right-width: 3px; border-bottom-right-radius: 12px; }
.escaner__ayuda {
  margin: 0;
  padding: 0 40px;
  text-align: center;
  font-size: 14px;
  font-weight: 600;
  color: var(--blanco);
}
/* En escritorio el visor no tiene por qué ocupar toda la fila. */
@media (min-width: 768px) {
  .escaner { max-width: 460px; aspect-ratio: 4 / 3; }
}

/* ── Conectar con un vendedor (spec 0001) ───────────────────────────────────
   La hoja de solicitud de la ficha, gemela de `Conectar.tsx` en la app. La
   pinta `assets/js/conexiones.js` sobre el armazón oculto de `vendedor.php`.

   Reusa `.opcion` de `app.css` —la misma pieza del checkout— y sólo agrega lo
   que la hoja tiene de propio: el campo de texto que crece, el contador y la
   línea del precio. */

/* Las que no están elegidas se encogen a una línea, como hace `Opcion` con
   `compacta` en la app: tres opciones a alto completo comen media pantalla
   para explicar dos que nadie va a tocar. Nada se esconde, siguen a un clic. */
.conectar .opcion:not(.activa) .opcion__texto span { display: none; }

.conectar__cab { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.conectar__codigo { font-size: 12px; font-weight: 500; color: var(--texto-3); }
.conectar__texto { margin: 10px 0 0; font-size: 13.5px; color: var(--texto-2); line-height: 1.5; }
.conectar__nota { margin: 2px 0 0; font-size: 12px; color: var(--texto-3); line-height: 1.45; }

/* `.campo__caja` mide 52 px de alto porque nació para un `<input>`. El área de
   texto crece con lo que se escribe, así que aquí el alto lo pone el contenido. */
.conectar__caja-texto { height: auto; padding: 12px 15px; }
.conectar__caja-texto textarea {
  flex: 1; min-width: 0; border: 0; outline: 0; background: none; resize: vertical;
  font: inherit; font-size: 14.5px; font-weight: 500; color: var(--texto);
}
.conectar__contador { display: block; text-align: right; margin-top: 6px; }

.conectar__total {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--borde);
}
.conectar__total-etq { font-size: 13.5px; font-weight: 600; color: var(--texto-2); }
.conectar__total-val { font-size: 19px; font-weight: 800; color: var(--texto); }

/* El precio, en su propia caja. Dentro de la bajada se perdía: ese gris es el
   más claro de la escala y la cifra salía del mismo cuerpo que la frase. */
.conectar__precio {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 15px; border-radius: var(--r-lg); background: var(--brand-050);
}
.conectar__precio-val { font-size: 20px; font-weight: 800; color: var(--marca-fuerte); }
.conectar__precio-nota { flex: 1; font-size: 12.5px; font-weight: 600; color: var(--texto-2); }

/* ── Mis conexiones y el detalle de una conexión (spec 0001, fase 3) ─────────
 *
 * La mitad de quien pide: la lista dentro de Networking y la pantalla donde se
 * paga, aparece el contacto y se cancela. Gemelas de `MisConexiones.tsx` y de
 * `app/(comprador)/conexion/[codigo].tsx`.
 *
 * Reusa lo que ya existe y no se inventa nada: `.bloque`, `.etq--*` de
 * `app.css` —las cuatro variantes son las mismas que usa `Etiqueta` en la app—,
 * `.opcion` del checkout y los botones. Lo propio es la fila de la lista y las
 * tres cajas del detalle. */

.cx-fila {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 14px; border-bottom: 1px solid var(--borde);
  color: inherit; text-decoration: none;
}
.cx-fila:last-child { border-bottom: 0; }
.cx-fila__cuerpo { flex: 1; min-width: 0; }
.cx-fila__nombre {
  display: block; font-size: 14px; font-weight: 700;
  letter-spacing: -0.28px; color: var(--texto);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cx-fila__etqs { display: flex; gap: 6px; margin-top: 6px; }
/* El reloj en el cálido, que en este sistema es el color del dinero y de la
   urgencia. No se tiñe de azul: el azul es marca y acciones. */
.cx-fila__reloj {
  display: block; margin-top: 6px;
  font-size: 11.5px; font-weight: 600; color: var(--dinero-texto);
}
.cx-fila__lado { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.cx-fila__monto { font-size: 15px; font-weight: 800; letter-spacing: -0.3px; color: var(--texto); }
.cx-fila__codigo { font-size: 11px; font-weight: 500; color: var(--texto-3); }

/* `min-height` porque es un botón: con 12 de relleno y una línea de 13 quedaba
   en 43, a un píxel del mínimo para un dedo. Lo encontró `npm run vista
   --tocables` al sumar esta pantalla a las puertas (fase 4 de la spec 0001). El
   gemelo de la app lleva el mismo 44 en `MisConexiones.tsx` → `masCaja`. */
.cx-mas {
  display: block; width: 100%; padding: 12px; min-height: 44px; border: 0; background: none;
  font: inherit; font-size: 13px; font-weight: 700; color: var(--marca); cursor: pointer;
}

/* ── El detalle ──────────────────────────────────────────────────────────── */

.cx-cab { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.cx-codigo { font-size: 12px; font-weight: 500; color: var(--texto-3); }
.cx-vendedor {
  display: block; margin-top: 10px;
  font-size: 18px; font-weight: 800; letter-spacing: -0.45px; color: var(--texto);
}
a.cx-vendedor { color: var(--marca-fuerte); text-decoration: underline; }
.cx-meta { margin: 2px 0 0; font-size: 12.5px; font-weight: 500; color: var(--texto-3); }
.cx-texto { margin: 10px 0 0; font-size: 13.5px; font-weight: 500; color: var(--texto-2); line-height: 1.5; }
.cx-mensaje { margin: 10px 0 0; font-size: 13.5px; font-weight: 500; color: var(--texto-2); line-height: 1.5; }
.cx-nota-fuerte { margin: 8px 0 0; font-size: 12.5px; font-weight: 600; color: var(--texto-2); }
.cx-nota { margin: 8px 0 0; font-size: 12px; font-weight: 500; color: var(--texto-3); line-height: 1.45; }

/* El reloj: el cálido del dinero, y la urgencia sube el fondo en vez de cambiar
   de color. Este sistema no tiene un token de error, y no se inventa uno para
   esto — el cálido ya es el color de la urgencia (ADR 0010). */
.cx-reloj {
  display: flex; align-items: center; gap: 8px;
  margin-top: 12px; padding: 10px 12px; border-radius: var(--r-md);
  background: var(--dinero-tenue); color: var(--dinero-texto);
  font-size: 12.5px; font-weight: 600; line-height: 1.4;
}
.cx-reloj.es-urgente { background: var(--dinero-suave); font-weight: 800; }
.cx-reloj .ico { flex: none; }

.cx-monto {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 10px;
  margin-top: 12px;
}
.cx-monto__etq { font-size: 13.5px; font-weight: 600; color: var(--texto-2); }
.cx-monto__val { font-size: 20px; font-weight: 800; letter-spacing: -0.5px; color: var(--texto); }

.cx-contacto {
  margin: 4px 0 0;
  font-size: 20px; font-weight: 800; letter-spacing: -0.4px; color: var(--texto);
  overflow-wrap: anywhere;
}

/* Lo que hay que transferir, en su propia caja y arriba de todo del formulario.
   El monto NO se puede editar: se congela al crear la conexión y el backend
   rechaza cualquier otra cifra, así que un campo escribible sería una trampa. */
.cx-transferir {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 14px; border-radius: var(--r-lg); background: var(--superficie-2);
}
.cx-transferir__etq { display: block; font-size: 12px; font-weight: 600; color: var(--texto-3); }
.cx-transferir__bs {
  display: block; margin-top: 2px;
  font-size: 18px; font-weight: 800; letter-spacing: -0.4px; color: var(--texto);
}
.cx-transferir__usd { font-size: 15px; font-weight: 700; color: var(--texto-2); }

/* ── Recuperar la contraseña, en la pantalla de entrar (punto 4 de QA 01-08) ──
 *
 * La fila que la app ya tenía —la pregunta a la izquierda, la salida a la
 * derecha—, para que las dos superficies contesten igual (ADR 0003). Gemela de
 * `s.recuperar` en `app/src/app/login.tsx`: mismo cuerpo, mismo peso, mismo
 * color de marca.
 *
 * Es un `<button>` y no un `<a>` porque hoy no lleva a ninguna parte: avisa por
 * dónde se pide. Al no ser enlace no hereda nada de `app.css`, así que los seis
 * restos del botón de navegador se apagan aquí.
 */
.recuperar-fila {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin: -10px 0 2px;
}
/* 44 px de alto, que es el mínimo para un dedo. El texto sigue midiendo 12,5 px
   —la fila no puede pesar más que el campo de arriba—, así que el alto lo pone
   la caja y el margen negativo de la fila se lo devuelve al espaciado. */
.recuperar-fila__btn {
  display: inline-flex; align-items: center; min-height: 44px;
  border: 0; background: none; padding: 0; margin: 0; cursor: pointer;
  font: inherit; font-size: 12.5px; font-weight: 700; color: var(--marca-fuerte);
}
.recuperar-fila__btn:hover { text-decoration: underline; }

/**
 * A-05 · la línea que dice qué estás aceptando, con los dos documentos
 * enlazados. Existe en las dos pantallas de entrada, y su gemela en la app es
 * `componentes/base/AvisoLegal.tsx`.
 *
 * Los enlaces miden 44 px de alto —el mínimo para un dedo— sin que el párrafo
 * engorde: la caja crece y el margen negativo se lo devuelve al espaciado. Es el
 * mismo recurso de `.recuperar-fila__btn`, unas líneas más arriba, y hace falta
 * por lo mismo: un enlace de texto legal mide 15 px, que para un pulgar no es
 * un objetivo, es una lotería.
 */
.acepta { text-align: center; margin: 20px 0 -12px; line-height: 1.5; }
.acepta a {
  display: inline-flex; align-items: center; min-height: 44px;
  margin-block: -14px;
  font-weight: 700; color: var(--marca-fuerte);
}
.acepta a:hover { text-decoration: underline; }
