/* Componentes. Reglas duras del manual (cap. 10):
   radio 0, sin sombras, filetes de 1px, sin iconografía decorativa. */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--lienzo);
  color: var(--tinta);
  font-family: var(--fuente-texto);
  font-size: var(--texto-base);
  line-height: var(--interlineado-cuerpo);
  /* Evita el zoom de iOS al enfocar inputs: nada baja de 16px. */
  -webkit-font-smoothing: antialiased;
}

/* Regla dura de la app: ningún control enfocable baja de 16px. Safari en iOS
   hace zoom al enfocar cualquier input por debajo de ese tamaño y deja la
   pantalla descuadrada a media captura. Heredan del body, que es 16px; si
   algún componente necesita verse más chico, se ajusta con color o peso,
   nunca con font-size. */
button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
  border-radius: 0;
  appearance: none;
  -webkit-appearance: none;
}

a {
  color: inherit;
}

/* --- Estructura -------------------------------------------------------- */

.app {
  max-width: 34rem;
  margin: 0 auto;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  /* Con viewport-fit=cover el contenido llega hasta el borde físico: en
     horizontal, el notch se comería la primera columna sin esto. */
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

.contenido {
  flex: 1;
  /* Espacio para la barra inferior fija. */
  padding-bottom: calc(var(--barra-inferior) + env(safe-area-inset-bottom) + var(--e4));
}

.seccion {
  padding: var(--e5) var(--e4);
  border-top: 1px solid var(--filete);
}

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

/* --- Tipografía -------------------------------------------------------- */

.etiqueta {
  font-size: var(--texto-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--tracking-etiqueta);
  color: var(--tinta-suave);
  line-height: 1.4;
}

.cifra {
  font-family: var(--fuente-display);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-display);
}

.titulo-pantalla {
  font-family: var(--fuente-display);
  font-size: var(--texto-xl);
  font-weight: 500;
  letter-spacing: var(--tracking-display);
  line-height: 1.2;
  /* En 390px el título compite con la fecha editable: nunca parte en dos. */
  white-space: nowrap;
}

.secundario {
  color: var(--tinta-suave);
  font-size: var(--texto-sm);
}

.tenue {
  color: var(--tinta-suave);
  font-size: var(--texto-sm);
}

/* --- Encabezado -------------------------------------------------------- */

.encabezado {
  display: flex;
  /* En teléfonos angostos las acciones bajan a un segundo renglón en vez de
     encogerse: la fecha es un input y no puede bajar de 16px sin disparar el
     zoom automático de Safari en iOS. */
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--e1) var(--e3);
  min-height: var(--toque-alto);
  padding: var(--e2) var(--e4);
  border-bottom: 1px solid var(--filete);
  background: var(--lienzo);
}

.encabezado__acciones {
  display: flex;
  align-items: center;
  gap: var(--e2);
  margin-left: auto;
}

@media (max-width: 420px) {
  .encabezado {
    padding-inline: var(--e3);
  }

  .boton--texto {
    padding-inline: var(--e2);
  }
}

/* Fecha y hora editables en el propio encabezado (§5.3, captura post-hoc). */
.campo-fecha {
  border: 1px solid transparent;
  background: transparent;
  color: var(--tinta-suave);
  /* 16px exactos: por debajo de eso Safari en iOS hace zoom al enfocar y deja
     la pantalla descuadrada a media captura. */
  font-size: var(--texto-base);
  padding: var(--e1) var(--e2);
  min-height: var(--toque);
  min-width: 0;
  text-align: right;
}

.campo-fecha:focus-visible {
  outline: 0;
  border-color: var(--filete-fuerte);
  color: var(--tinta);
}

/* --- Campos ------------------------------------------------------------ */

.campo {
  display: block;
  width: 100%;
  min-height: var(--toque);
  padding: var(--e2) var(--e3);
  background: var(--superficie);
  border: 1px solid var(--niebla);
  color: var(--tinta);
  transition: border-color var(--dur-tap) var(--ease-salida);
}

.campo::placeholder {
  color: var(--tinta-suave);
}

.campo:focus-visible {
  outline: 0;
  border-color: var(--filete-fuerte);
  border-width: 2px;
  padding: calc(var(--e2) - 1px) calc(var(--e3) - 1px);
}

.campo--error {
  border-color: var(--oxido);
}

.campo-linea {
  width: 100%;
  border: 0;
  border-bottom: 1px solid var(--niebla);
  background: transparent;
  padding: var(--e1) 0;
  min-height: 2rem;
}

.campo-linea:focus-visible {
  outline: 0;
  border-bottom-color: var(--filete-fuerte);
  border-bottom-width: 2px;
}

.grupo-campo {
  display: grid;
  gap: var(--e2);
  margin-bottom: var(--e4);
}

/* --- Botones ----------------------------------------------------------- */

.boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--e2);
  min-height: var(--toque);
  padding: var(--e2) var(--e4);
  border: 1px solid var(--filete-fuerte);
  background: transparent;
  color: var(--tinta);
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
  transition: transform var(--dur-tap) var(--ease-salida),
    background-color var(--dur-tap) var(--ease-salida);
}

/* Único feedback que importa en captura: confirma el tap antes de que
   llegue la respuesta del servidor. */
.boton:active {
  transform: scale(0.97);
}

.boton--primario {
  background: var(--carbon);
  color: var(--marfil);
  border-color: var(--carbon);
  text-transform: uppercase;
  letter-spacing: var(--tracking-etiqueta);
  font-size: var(--texto-sm);
}

.boton--fantasma {
  border-color: var(--niebla);
}

.boton--destructivo {
  border-color: var(--oxido);
  color: var(--oxido);
}

.boton--texto {
  border-color: transparent;
  padding: var(--e2);
  font-size: var(--texto-sm);
  color: var(--tinta-suave);
}

/* Un botón de texto destructivo sigue siendo destructivo. Sin esta regla gana
   `.boton--texto` por venir después con la misma especificidad, y "Eliminar"
   quedaba idéntico a "Historial" al lado: el óxido es la única señal
   inequívoca que tiene la marca (brand-tokens §1). */
.boton--texto.boton--destructivo {
  color: var(--oxido);
}

.boton--ancho {
  width: 100%;
}

.boton[disabled] {
  /* Único gris sin contraste de texto: un control deshabilitado está exento
     de WCAG 1.4.3 y tiene que verse apagado. */
  color: var(--carbon-55);
  border-color: var(--niebla);
  cursor: not-allowed;
}

.boton--primario[disabled] {
  background: var(--niebla);
  color: var(--tinta-suave);
}

@media (hover: hover) and (pointer: fine) {
  .boton:hover:not([disabled]) {
    background: var(--carbon-12);
  }

  .boton--primario:hover:not([disabled]) {
    background: var(--carbon-80);
  }
}

/* --- Listas de filas --------------------------------------------------- */

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

.fila {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e3);
  width: 100%;
  min-height: var(--toque-alto);
  padding: var(--e2) 0;
  border: 0;
  border-bottom: 1px solid var(--filete);
  background: transparent;
  text-align: left;
  cursor: pointer;
  transition: transform var(--dur-tap) var(--ease-salida);
}

.fila:active {
  transform: scale(0.99);
}

.fila__principal {
  min-width: 0;
}

.fila__nombre {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fila__meta {
  color: var(--tinta-suave);
  font-size: var(--texto-sm);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

/* --- Paciente seleccionado --------------------------------------------- */

.paciente {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e3);
  padding: var(--e3) var(--e4);
  background: var(--superficie);
  border-bottom: 1px solid var(--filete);
}

.paciente__nombre {
  font-weight: 500;
}

/* --- Segmentado de tarifa ---------------------------------------------- */

.segmentado {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border: 1px solid var(--filete-fuerte);
}

.segmentado__opcion {
  min-height: var(--toque);
  border: 0;
  background: transparent;
  color: var(--tinta);
  font-size: var(--texto-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--tracking-etiqueta);
  cursor: pointer;
  transition: background-color var(--dur-tap) ease, color var(--dur-tap) ease;
}

.segmentado__opcion + .segmentado__opcion {
  border-left: 1px solid var(--filete-fuerte);
}

.segmentado__opcion[aria-pressed="true"] {
  background: var(--carbon);
  color: var(--marfil);
}

/* Segmentado de N opciones (método de pago, §5.6). El separador se dibuja con
   el fondo del contenedor y un gap de 1px, no con border-left: así, cuando el
   control envuelve a dos renglones, no quedan filetes sueltos a media fila.
   Sin versalitas ni tracking: los nombres de método vienen del catálogo y
   "Transferencia" en mayúsculas espaciadas no cabe en un teléfono. */
.segmentado--auto {
  display: flex;
  flex-wrap: wrap;
  gap: 1px;
  background: var(--filete-fuerte);
}

.segmentado--auto .segmentado__opcion {
  flex: 1 1 5.5rem;
  background: var(--superficie);
  padding-inline: var(--e2);
  font-size: var(--texto-sm);
  text-transform: none;
  letter-spacing: normal;
  border-left: 0;
}

.segmentado--auto .segmentado__opcion[aria-pressed="true"] {
  background: var(--carbon);
  color: var(--marfil);
}

/* Dropdown de verdad: caja, fondo y chevron. Sin esto un select se lee como
   campo de texto (el subrayado solo no basta). */
.campo-select {
  width: 100%;
  min-height: var(--toque);
  padding: var(--e2) var(--e8) var(--e2) var(--e3);
  background-color: var(--superficie);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%234b4b4d' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--e3) center;
  border: 1px solid var(--filete-fuerte);
  color: var(--tinta);
  /* 16px exactos: por debajo, Safari en iOS hace zoom al enfocar. */
  font-size: var(--texto-base);
  appearance: none;
}

.campo-select:focus-visible {
  outline: 0;
  border-width: 2px;
  padding: calc(var(--e2) - 1px) calc(var(--e8) - 1px) calc(var(--e2) - 1px)
    calc(var(--e3) - 1px);
}

/* --- Banner de bonificación -------------------------------------------- */
/* Único bloque de arena en toda la app (ver brand-tokens.md §3). */

.bonificacion {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e3);
  padding: var(--e3) var(--e4);
  background: var(--arena);
  color: var(--carbon);
}

.bonificacion__texto {
  font-size: var(--texto-sm);
}

.bonificacion__boton {
  flex-shrink: 0;
  background: var(--carbon);
  color: var(--marfil);
  border-color: var(--carbon);
}

/* --- Chips de tratamientos --------------------------------------------- */

/* Los filetes los dibuja cada chip, no el fondo de la rejilla: con un número
   impar de tratamientos, el hueco sobrante queda vacío en vez de aparecer
   como un bloque gris fantasma. */
.chips {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  border-top: 1px solid var(--filete);
  border-left: 1px solid var(--filete);
}

.chip {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--e1);
  min-height: 72px;
  padding: var(--e2) var(--e3);
  border: 0;
  border-right: 1px solid var(--filete);
  border-bottom: 1px solid var(--filete);
  background: var(--superficie);
  text-align: left;
  cursor: pointer;
  transition: transform var(--dur-tap) var(--ease-salida),
    background-color var(--dur-tap) var(--ease-salida);
}

.chip:active {
  transform: scale(0.97);
}

.chip__nombre {
  font-size: var(--texto-sm);
  font-weight: 500;
  line-height: 1.3;
}

.chip__precio {
  font-family: var(--fuente-display);
  font-size: var(--texto-lg);
  font-variant-numeric: tabular-nums;
}

@media (hover: hover) and (pointer: fine) {
  .chip:hover {
    background: var(--carbon-05);
  }
}

/* --- Acordeón de categorías -------------------------------------------- */
/* <details> nativo: cero JavaScript, instantáneo, accesible por teclado. */

.categoria {
  border-bottom: 1px solid var(--filete);
}

.categoria > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--toque);
  padding: var(--e2) 0;
  cursor: pointer;
  list-style: none;
  font-size: var(--texto-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--tracking-etiqueta);
}

.categoria > summary::-webkit-details-marker {
  display: none;
}

.categoria > summary::after {
  content: "+";
  font-size: var(--texto-lg);
  color: var(--tinta-suave);
  line-height: 1;
}

.categoria[open] > summary::after {
  content: "\2212"; /* signo menos */
}

.categoria__cuerpo {
  padding-bottom: var(--e3);
}

/* --- Producto «Otro» (§5, Corrección v1.5) ----------------------------- */
/* Otro <details>: abre al instante, igual que el acordeón. Va debajo de la
   rejilla y a todo lo ancho porque, abierto, lleva dos campos que no caben en
   una celda de chip. Continúa los filetes de la rejilla para leerse como su
   último renglón. */

.otro {
  border: 1px solid var(--filete);
  border-top: 0;
  background: var(--superficie);
}

.categoria__cuerpo > .otro:first-child {
  border-top: 1px solid var(--filete);
}

.otro > summary {
  display: flex;
  align-items: center;
  gap: var(--e3);
  min-height: var(--toque);
  padding: var(--e2) var(--e3);
  cursor: pointer;
  list-style: none;
}

.otro > summary::-webkit-details-marker {
  display: none;
}

.otro > summary::after {
  content: "+";
  font-size: var(--texto-lg);
  color: var(--tinta-suave);
  line-height: 1;
}

.otro[open] > summary::after {
  content: "\2212";
}

.otro__nota {
  margin-left: auto;
  font-size: var(--texto-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-etiqueta);
  color: var(--tinta-suave);
}

.otro__form {
  padding: 0 var(--e3) var(--e3);
}

.otro__renglon {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: var(--e3);
}

.otro__renglon .grupo-campo {
  margin-bottom: 0;
}

/* --- Líneas de la venta ------------------------------------------------ */

.linea {
  padding: var(--e3) 0;
  border-bottom: 1px solid var(--filete);
}

/* Entrada de una línea recién agregada. Transición y no keyframe: se agregan
   rápido y deben poder interrumpirse. */
@media (prefers-reduced-motion: no-preference) {
  .linea {
    transition: opacity var(--dur-linea) var(--ease-salida),
      transform var(--dur-linea) var(--ease-salida);
  }

  /* @starting-style va al primer nivel a propósito: anidado dependería
     también de CSS Nesting, y en Safari anteriores a 17.5 basta con que la
     línea aparezca sin animar. El estado base ya es el visible. */
  @starting-style {
    .linea {
      opacity: 0;
      transform: translateY(4px);
    }
  }
}

.linea__cabeza {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--e2);
}

.linea__nombre {
  font-weight: 500;
  min-width: 0;
}

.linea__sesion {
  flex-shrink: 0;
  color: var(--tinta-suave);
  font-size: var(--texto-sm);
  font-variant-numeric: tabular-nums;
}

.linea__campos {
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  align-items: end;
  gap: var(--e3);
  margin-top: var(--e2);
}

.linea__tipo {
  display: inline-block;
  margin-top: var(--e1);
  font-size: var(--texto-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-etiqueta);
  color: var(--tinta-suave);
}

.linea__aviso {
  margin-top: var(--e2);
  padding-left: var(--e2);
  border-left: 2px solid var(--carbon);
  font-size: var(--texto-sm);
  color: var(--tinta-suave);
}

/* Menú "⋯" de la línea, también con <details>. */
.menu {
  position: relative;
}

.menu > summary {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--toque);
  height: var(--toque);
  cursor: pointer;
  list-style: none;
  color: var(--tinta-suave);
}

.menu > summary::-webkit-details-marker {
  display: none;
}

/* Se abre hacia ARRIBA y por encima de la barra inferior fija. Abriéndose hacia
   abajo, en la última línea de la venta la barra (z-index 30) tapaba la opción
   "Quitar línea" y no había scroll que la revelara: el panel está posicionado
   en absoluto, así que no alarga el documento. Quitar una línea agregada por
   error es de las correcciones más frecuentes al capturar. */
.menu__panel {
  position: absolute;
  right: 0;
  bottom: 100%;
  z-index: 40;
  min-width: 12rem;
  max-height: 60vh;
  overflow-y: auto;
  padding: var(--e2);
  background: var(--superficie);
  border: 1px solid var(--filete-fuerte);
}

.menu__opcion {
  display: block;
  width: 100%;
  min-height: var(--toque);
  padding: var(--e2);
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
  font-size: var(--texto-sm);
}

.menu__opcion[aria-pressed="true"] {
  font-weight: 500;
  background: var(--carbon-12);
}

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

/* --- Pago --------------------------------------------------------------- */

/* El método va en su propio renglón, a todo lo ancho: un segmentado de tres
   opciones no cabe junto al monto en un teléfono sin cortar "Transferencia". */
.pago {
  display: grid;
  gap: var(--e2);
  padding: var(--e2) 0;
  border-bottom: 1px solid var(--filete);
}

.pago__renglon {
  display: flex;
  align-items: center;
  gap: var(--e3);
}

.pago__renglon .etiqueta {
  margin-right: auto;
}

.pago__monto {
  width: 8rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* --- Barra inferior fija ------------------------------------------------ */

.barra-inferior {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e4);
  max-width: 34rem;
  margin: 0 auto;
  min-height: var(--barra-inferior);
  padding: var(--e3) var(--e4);
  /* El indicador de inicio del iPhone vive encima de esta barra. */
  padding-bottom: calc(var(--e3) + env(safe-area-inset-bottom));
  padding-left: calc(var(--e4) + env(safe-area-inset-left));
  padding-right: calc(var(--e4) + env(safe-area-inset-right));
  background: var(--superficie);
  border-top: 1px solid var(--filete-fuerte);
}

.barra-inferior__total {
  display: flex;
  flex-direction: column;
  gap: 2px;
  line-height: 1.1;
}

.barra-inferior__cifra {
  font-family: var(--fuente-display);
  font-size: var(--texto-2xl);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-display);
}

/* --- Hoja de confirmación ----------------------------------------------- */

.hoja__fondo {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--carbon) 40%, transparent);
}

.hoja {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 41;
  max-width: 34rem;
  margin: 0 auto;
  max-height: 92dvh;
  overflow-y: auto;
  padding: var(--e5) var(--e4);
  padding-bottom: calc(var(--e5) + env(safe-area-inset-bottom));
  padding-left: calc(var(--e4) + env(safe-area-inset-left));
  padding-right: calc(var(--e4) + env(safe-area-inset-right));
  background: var(--superficie);
  border-top: 1px solid var(--filete-fuerte);
}

@media (prefers-reduced-motion: no-preference) {
  .hoja {
    transition: transform var(--dur-hoja-entra) var(--ease-hoja);
  }

  .hoja__fondo {
    transition: opacity var(--dur-hoja-entra) ease;
  }

  @starting-style {
    .hoja {
      transform: translateY(100%);
    }

    .hoja__fondo {
      opacity: 0;
    }
  }
}

/* El paciente es lo más prominente de la hoja: el error que previene esta
   pantalla es "paciente equivocado", no "total equivocado". */
.hoja__paciente {
  font-family: var(--fuente-display);
  font-size: var(--texto-3xl);
  font-weight: 500;
  letter-spacing: var(--tracking-display);
  line-height: 1.1;
}

.hoja__contexto {
  margin-top: var(--e1);
  color: var(--tinta-suave);
  font-size: var(--texto-sm);
}

.hoja__detalle {
  margin: var(--e5) 0;
  border-top: 1px solid var(--filete);
}

.hoja__renglon {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--e3);
  padding: var(--e3) 0;
  border-bottom: 1px solid var(--filete);
}

.hoja__total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: var(--e4) 0;
}

.hoja__total-cifra {
  font-family: var(--fuente-display);
  font-size: var(--texto-2xl);
  font-variant-numeric: tabular-nums;
}

.hoja__acciones {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--e3);
}

/* --- Franja de confirmación --------------------------------------------- */

/* Se ancla al borde inferior, no por encima de la barra: cuando aparece, la
   venta ya se guardó y el borrador está vacío, así que no hay barra que
   esquivar — dejaba 72px de marfil colgando debajo. */
.franja {
  position: fixed;
  left: 0;
  right: 0;
  bottom: env(safe-area-inset-bottom);
  z-index: 35;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e3);
  max-width: 34rem;
  margin: 0 auto;
  padding: var(--e3) var(--e4);
  background: var(--carbon);
  color: var(--marfil);
  font-size: var(--texto-sm);
}

.franja__enlace {
  color: var(--marfil);
  flex-shrink: 0;
}

/* Permanece 4s y sale (brand-tokens §4): un aviso que se queda para siempre
   deja de leerse como aviso. */
.franja--sale {
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .franja {
    transition: opacity 180ms var(--ease-salida), transform 180ms var(--ease-salida);
  }

  @starting-style {
    .franja {
      opacity: 0;
      transform: translateY(8px);
    }
  }
}

/* --- Mensajes ----------------------------------------------------------- */

.aviso {
  padding: var(--e3) var(--e4);
  border-left: 2px solid var(--carbon);
  background: var(--carbon-05);
  font-size: var(--texto-sm);
}

.aviso--error {
  border-left-color: var(--oxido);
  color: var(--oxido);
}

.vacio {
  padding: var(--e8) var(--e4);
  text-align: center;
  color: var(--tinta-suave);
  font-size: var(--texto-sm);
}

/* --- Indicador de carga de htmx ----------------------------------------- */
/* Solo aparece si la respuesta tarda: en local nunca se ve, en 4G sí. */

.cargando {
  opacity: 0;
  transition: opacity 120ms ease 220ms;
  font-size: var(--texto-xs);
  color: var(--tinta-suave);
  text-transform: uppercase;
  letter-spacing: var(--tracking-etiqueta);
}

.htmx-request .cargando,
.htmx-request.cargando {
  opacity: 1;
}

/* --- Ingreso ------------------------------------------------------------ */

.ingreso {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 100dvh;
  max-width: 22rem;
  margin: 0 auto;
  padding: var(--e6) var(--e4);
}

.ingreso__marca {
  font-family: var(--fuente-display);
  font-size: var(--texto-2xl);
  letter-spacing: var(--tracking-display);
  margin-bottom: var(--e8);
}

/* --- Visitas ------------------------------------------------------------ */

.dia {
  padding: var(--e4) var(--e4) var(--e2);
  font-size: var(--texto-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--tracking-etiqueta);
  color: var(--tinta-suave);
  border-bottom: 1px solid var(--filete);
}

.visita {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e3);
  padding: var(--e3) var(--e4);
  border-bottom: 1px solid var(--filete);
  text-decoration: none;
}

.visita__detalle {
  color: var(--tinta-suave);
  font-size: var(--texto-sm);
}

.visita__total {
  font-family: var(--fuente-display);
  font-size: var(--texto-lg);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

/* --- Utilidades --------------------------------------------------------- */

.solo-lectores {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.pila {
  display: grid;
  gap: var(--e3);
}

.entre {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e3);
}
