/* =============================================================================
   Login y creación de cuenta — rediseño 2026-08 (Figma "yose-mobile", Desktop 1-4).
   Estilos de `login.html`, que sirve LAS DOS rutas (/login y /crear-cuenta):
   ya no hay dos páginas que mantener en paralelo.
   Los colores viven en yose.css; aquí solo va el armado.
   ========================================================================== */

/* Tokens propios de estas pantallas. No van en yose.css a propósito: ahí un
   cambio repinta 12 páginas, y estos nacieron para resolver contraste AQUÍ.

   🔑 `--label-ink` es la tinta y NO el gris medio de la paleta: desde que la
   tarjeta es de vidrio, el texto chico ya no se lee sobre blanco sino sobre
   blanco-al-56%-encima-del-trazo-verde. Medido contra el trazo más oscuro de la
   "Yose", que compuesto da #97B4AB: `#6B6B6B` cae a 2.39:1 y `#1A1814` da
   7.96:1. (Antes eran #5C6B5E → 2.99 y #3E4A40 → 4.92; la paleta oficial no
   tiene esos grises verdosos, y su reemplazo mejora el peor punto.)
   Si algún día la tarjeta vuelve a ser opaca, este token puede aclararse.

   🔑 El BORDE del campo va con alpha sobre el verde de la paleta, no con un hex
   sólido: 1.4.11 pide 3:1 para el contorno de un control y ningún verde claro de
   la paleta llega —#8BC695 da 1.98 sobre blanco—. Con `rgba(18,84,64,0.60)` son
   3.20:1, por encima del 3.05 que tenía el #B4DCB8 anterior.
   ⚠️ Sobre el PEOR punto del vidrio ese borde da 2.21 y sigue sin cumplir. El
   #B4DCB8 de antes daba menos todavía (es más claro que el propio vidrio), así
   que esto mejora sin resolverlo: arreglarlo de verdad es rediseñar la tarjeta,
   no el borde. */
:root {
  --field-line: rgba(18, 84, 64, 0.60);        /* 3.20:1 sobre blanco */
  --field-line-hover: rgba(18, 84, 64, 0.80);  /* 5.24:1 sobre blanco */
  --field-fill: rgba(255, 255, 255, 0.55);  /* el campo también deja pasar el fondo */
  --field-fill-solid: #F8F7F2;  /* para el foco y el autofill: ahí sí manda el campo */
  --label-ink: #1A1814;         /* 4.92:1 sobre el peor punto del vidrio */
  --focus-ring: rgba(18, 84, 64, 0.28);

  /* El vidrio. Un solo lugar donde subirle o bajarle.
     🚨 EL 56% NO ES UN GUSTO: ES EL PISO MEDIDO. Se barrió el valor contra el
     contraste REAL en pantalla (fotografiando lo que queda detrás de cada
     línea de texto chico, en 4 tamaños × los 2 modos):
        62% → 5.20:1 ✅   56% → 4.67:1 ✅   50% → 4.23:1 ❌   44% → 3.77:1 ❌
     El peor punto siempre es "Tu número de WhatsApp" en 1440x700, que es donde
     el trazo de la "o" pasa justo por debajo de la etiqueta.
     Bajar de aquí sin volver a medir deja el formulario por debajo de AA. */
  --vidrio: rgba(255, 255, 255, 0.56);
  --vidrio-blur: blur(34px) saturate(1.45);
  --vidrio-borde: rgba(255, 255, 255, 0.55);
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--parchment);
  font-family: var(--body);
  color: var(--ink);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: clamp(1rem, 4vw, 3rem) 1rem;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

/* --- La "Yose" gigante del fondo -------------------------------------------
   En el Figma es una imagen de 1532x1010. Aquí va como texto: escala a
   cualquier pantalla, no pesa un solo byte y ya cargamos esa tipografía. */
.auth-bg {
  position: fixed;
  inset: 0;
  display: flex;
  /* Arriba y no al centro: en el Figma la palabra ocupa los dos tercios de
     arriba y la frase cae LIBRE debajo de su remate. Centrada, la frase queda
     encima del trazo y no se lee. */
  align-items: flex-start;
  justify-content: center;
  /* Sube MUCHO más que el -5vh original. Con aquel valor el remate de la "o" y
     la "s" terminaba a ~20px de la leyenda, y como las dos son del MISMO verde
     no se distinguía una de otra: se leían como una sola mancha.
     Va en vh y no en px porque lo que hay que despejar —la leyenda— cuelga de
     una tarjeta centrada verticalmente: si crece el alto de la ventana, la
     leyenda baja y el remate tiene que bajar con ella. */
  transform: translateY(-14vh);
  font-family: var(--display);
  font-weight: 500;
  /* El tope en vh es lo que de verdad arregla el choque. Con `60vw` a secas, en
     una pantalla ancha y baja (1440x700, 1920x1080) la palabra medía MÁS que la
     ventana: su remate caía 45-60px por DEBAJO de donde empieza la leyenda, y
     subirla no servía de nada —no cabía—. Medido: con este tope el hueco entre
     el remate y la leyenda queda >90px en todos los tamaños probados.
     En pantallas altas no aplica: ahí manda el 60vw y la palabra sigue saliendo
     por los lados como en el Figma. */
  font-size: min(60vw, 92vh);
  line-height: 1;
  color: var(--chip-ink);
  white-space: nowrap;
  user-select: none;
  pointer-events: none;
  z-index: 0;
}

/* --- Tarjeta ---------------------------------------------------------------- */
/* Vidrio esmerilado: la "Yose" de atrás se ve a través de la tarjeta.
   El desenfoque no es decoración — es lo que hace legible la transparencia:
   convierte el filo del trazo en un degradado, y sin él el borde duro de la
   letra cruza el texto y el ojo salta a media línea.
   El borde claro de arriba es lo que separa la tarjeta del fondo cuando el
   trazo pasa justo por su canto; sin él, en esa zona el canto desaparece. */
.auth-card {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 419px;
  background: var(--vidrio);
  -webkit-backdrop-filter: var(--vidrio-blur);
  backdrop-filter: var(--vidrio-blur);
  border: 1px solid var(--vidrio-borde);
  border-radius: 26px;
  padding: clamp(1.5rem, 4vw, 2.25rem) clamp(1.25rem, 3.5vw, 1.9rem);
  box-shadow: 0 18px 50px rgba(18, 84, 64, 0.22);
}

/* Sin `backdrop-filter` (Firefox con el flag apagado, WebViews viejas) NO hay
   desenfoque: el trazo quedaría crudo y con filo detrás del texto. Ahí la
   tarjeta se vuelve casi opaca. Se pierde el efecto, nunca la lectura. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .auth-card { background: rgba(255, 255, 255, 0.94); }
  .field input[type="text"],
  .field input[type="tel"],
  .field input[type="email"],
  .phone-field,
  .auth-social,
  .otp-inputs input { background: var(--field-fill-solid); }
}

.auth-card h1 {
  font-family: var(--body);
  font-weight: 600;
  font-size: clamp(1.3rem, 3vw, 1.55rem);
  line-height: 1.15;
  color: #1A1814;
  text-align: center;
  margin: 0 0 0.3rem;
  letter-spacing: -0.015em;
}
.auth-card h1 .hand { font-size: 0.9em; }

/* Bajada de una línea. Existe para bajarle peso al título: lo primero que debe
   pesar en la pantalla es el campo, no el saludo. */
.auth-sub {
  text-align: center;
  font-size: 0.875rem;
  color: var(--label-ink);
  margin: 0 0 1.5rem;
}

/* --- Pestañas Crear cuenta / Iniciar sesión ---------------------------------
   Siguen siendo enlaces reales (hay 22 apuntándoles en la web y el backend, y
   los correos de referidos mandan a /crear-cuenta?ref=), pero el clic lo
   intercepta la página: cambia de modo con pushState en vez de recargar.
   Cmd/Ctrl/rueda siguen abriendo la otra URL en pestaña nueva.

   26px de alto era un objetivo táctil de 32 con el padding, por debajo del
   mínimo de 44, en el control más importante de la pantalla. Ahora 40 + 4 de
   padding = 48. */
.auth-tabs {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
  background: rgba(255, 255, 255, 0.42);
  border: 1px solid var(--field-line);
  border-radius: 14px;
  padding: 4px;
  margin: 0 auto 1.35rem;
  isolation: isolate;
}
/* La pastilla es UN elemento que se desliza, no dos fondos que se prenden y
   apagan: así el cambio se lee como un movimiento y no como un parpadeo. */
.auth-tabs::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 4px;
  bottom: 4px;
  left: 4px;
  width: calc(50% - 4px);
  border-radius: 10px;
  background: #FFFFFF;
  box-shadow: 0 2px 6px rgba(18, 84, 64, 0.14);
  transition: transform 0.32s var(--ease);
}
.auth-tabs[data-modo="login"]::before { transform: translateX(100%); }
.auth-tabs a {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 40px;
  border-radius: 10px;
  font-weight: 500;
  font-size: 0.86rem;
  color: var(--label-ink);
  text-decoration: none;
  text-transform: none;
  letter-spacing: normal;
  transition: color 0.2s var(--ease);
}
.auth-tabs a[aria-current="page"] { color: var(--forest-ink); font-weight: 600; }

/* --- Lo que cambia entre modos ---------------------------------------------
   Los campos que sobran no desaparecen de golpe: se colapsan. `grid-template-
   rows: 1fr → 0fr` anima la altura sin tener que saber cuánto mide el
   contenido (un `max-height` a ojo se queda corto en cuanto crece el texto).
   `inert` —atributo nativo— saca lo colapsado del tabulador y del lector de
   pantalla; sin él, Tab se metería a campos invisibles. */
.auth-swap {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 0.34s var(--ease), opacity 0.22s var(--ease);
}
.auth-swap > div { overflow: hidden; min-height: 0; }
/* …salvo mientras el selector de país está abierto. El popup es `absolute`
   dentro de este bloque, así que el `overflow: hidden` de arriba —que existe
   para el colapso— le cortaba la lista: se abría y no se veía nada, y quien no
   fuera de México no podía ni entrar ni registrarse. Se levanta solo en ese
   estado, que nunca coincide con la animación de colapso. */
.auth-swap > div:has(.country-pop:not([hidden])) { overflow: visible; }
.auth-swap[data-abierto="false"] { grid-template-rows: 0fr; opacity: 0; }

/* Título, bajada y texto del botón cambian por crossfade. */
.fade { display: inline-block; transition: opacity 0.16s var(--ease); }
.fade.out { opacity: 0; }

/* --- Campos ----------------------------------------------------------------- */
.field { margin-bottom: 0.9rem; }
.field > label {
  display: block;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--label-ink);
  margin-bottom: 0.4rem;
  text-transform: none;
  letter-spacing: normal;
}
/* 46px y no los 35 del Figma: por debajo de 44 el objetivo táctil queda
   fuera de norma y en móvil se falla el toque.

   El borde era `1.5px solid transparent`: la caja NO tenía contorno y lo único
   que la delataba era el relleno verde `--field-bg` sobre blanco, que da 1.15:1
   —WCAG 1.4.11 pide 3:1 para el contorno de un control—. Ahora el borde es real
   y el relleno pasa a casi neutro, para que el que defina la caja sea el borde. */
.field input[type="text"],
.field input[type="tel"],
.field input[type="email"] {
  width: 100%;
  height: 46px;
  border: 1.5px solid var(--field-line);
  border-radius: 15px;
  background: var(--field-fill);
  padding: 0 1rem;
  font-family: var(--body);
  font-size: 1rem;
  color: var(--ink);
  outline: none;
  transition: border-color 0.18s var(--ease), box-shadow 0.18s var(--ease),
              background 0.18s var(--ease);
}
/* El gris medio de la paleta, no el claro: el campo deja pasar el fondo, así
   que el placeholder ya no se lee sobre casi-blanco. */
.field input::placeholder { color: #6B6B6B; }
.field input:hover { border-color: var(--field-line-hover); }
/* El foco antes solo ponía el borde verde… sobre un campo que YA era verde.
   El anillo es lo que de verdad se ve. */
.field input:focus {
  background: #FFFFFF;
  border-color: var(--green-btn);
  box-shadow: 0 0 0 3px var(--focus-ring);
}
.field.has-error input,
.field.has-error .phone-field { border-color: var(--error); }

/* Sin esto Chrome repinta el campo autocompletado de azul/amarillo y se pierde
   el diseño justo en el campo que más se autocompleta (el teléfono). */
.field input:-webkit-autofill,
.field input:-webkit-autofill:hover,
.field input:-webkit-autofill:focus {
  /* Opaco a propósito: un `box-shadow` no puede ser translúcido "sobre el
     fondo real", y con el color de vidrio el campo autocompletado se veía de
     otro tono que sus vecinos. */
  -webkit-box-shadow: 0 0 0 40px var(--field-fill-solid) inset;
  -webkit-text-fill-color: var(--ink);
}

.input-hint {
  font-size: 0.78rem;
  font-weight: 300;
  color: var(--label-ink);
  margin: 0.4rem 0 0;
  text-align: left;
}

/* --- Cuando el código no sirve ----------------------------------------------
   Vive pegado al campo del código y NO es una tarjeta: la pantalla ya es una
   tarjeta de vidrio, y otra dentro compite con ella. Es un bloque con la línea
   del error a la izquierda, del ancho del campo, con las dos salidas debajo.
   Sale antes de mandar el OTP: después del alta ya no hay nada que elegir. */
.ref-aviso {
  margin-top: 0.55rem;
  padding: 0.7rem 0.85rem;
  border-left: 3px solid var(--error);
  border-radius: 0 12px 12px 0;
  background: rgba(230, 70, 70, 0.07);
}
.ref-aviso-msg {
  margin: 0 0 0.65rem;
  font-size: 0.8rem;
  font-weight: 300;
  line-height: 1.45;
  color: var(--label-ink);
}
.ref-aviso-acciones { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.ref-aviso-btn {
  flex: 1 1 auto;
  min-height: 38px;
  padding: 0 0.9rem;
  border-radius: 19px;
  border: 1.5px solid var(--green-btn);
  background: var(--green-btn);
  color: var(--parchment);
  font-family: var(--body);
  font-size: 0.8rem;
  font-weight: 500;
  cursor: pointer;
  transition: opacity 0.18s var(--ease);
}
.ref-aviso-btn.alt { background: transparent; color: var(--green-btn); }
.ref-aviso-btn:hover { opacity: 0.85; }
.ref-aviso-btn:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }

/* --- Teléfono con selector de país ------------------------------------------
   Esto NO viene en el Figma —dibuja el número pelón— pero se conserva: sin él
   solo se puede entrar con lada de México. */
.phone-field {
  display: flex;
  align-items: center;
  height: 46px;
  border: 1.5px solid var(--field-line);
  border-radius: 15px;
  background: var(--field-fill);
  transition: border-color 0.18s var(--ease), box-shadow 0.18s var(--ease),
              background 0.18s var(--ease);
}
.phone-field:hover { border-color: var(--field-line-hover); }
.phone-field:focus-within {
  background: #FFFFFF;
  border-color: var(--green-btn);
  box-shadow: 0 0 0 3px var(--focus-ring);
}
.phone-code {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  background: none;
  border: 0;
  cursor: pointer;
  padding: 0 0.5rem 0 0.85rem;
  font-family: var(--body);
  font-size: 0.95rem;
  color: var(--ink);
}
.phone-code .flag { font-size: 1.25rem; line-height: 1; }
.phone-code .chev { font-size: 0.7rem; opacity: 0.6; }
.phone-div { width: 1px; height: 22px; background: rgba(33, 95, 63, 0.25); }
.phone-field input[type="tel"] {
  flex: 1;
  min-width: 0;
  height: 100%;
  border: 0;
  background: transparent;
  padding: 0 0.85rem;
}
.phone-wrap { position: relative; }

.country-pop {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 30;
  background: #FFFFFF;
  border: 1px solid var(--rule);
  border-radius: 14px;
  box-shadow: 0 16px 40px rgba(18, 84, 64, 0.16);
  padding: 0.6rem;
}
.country-pop[hidden] { display: none; }
.country-search {
  width: 100%;
  height: 38px;
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 0 0.75rem;
  font-family: var(--body);
  font-size: 0.9rem;
  outline: none;
  margin-bottom: 0.5rem;
}
.country-search:focus { border-color: var(--green-btn); }
.country-list { max-height: 240px; overflow-y: auto; }
.country-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  padding: 0.5rem 0.6rem;
  border: 0;
  border-radius: 10px;
  background: none;
  cursor: pointer;
  font-family: var(--body);
  font-size: 0.9rem;
  text-align: left;
}
.country-row:hover { background: var(--field-bg); }
.country-row.active { background: var(--sage); }
.country-row .c-name { flex: 1; }
.country-row .c-dial { color: var(--label); font-variant-numeric: tabular-nums; }
.country-empty { padding: 0.8rem; text-align: center; color: var(--label); font-size: 0.9rem; }

/* --- Consentimiento de edad -------------------------------------------------
   Checkbox y no el radio del Figma: un radio no se puede desmarcar, y un
   consentimiento que no se puede retirar no es un consentimiento. */
.age-check {
  display: flex;
  gap: 0.55rem;
  align-items: flex-start;
  margin: 1rem 0 0.35rem;
  font-size: 0.85rem;
  color: var(--green-btn);
  cursor: pointer;
  text-transform: none;
  letter-spacing: normal;
}
.age-check input { margin-top: 0.15rem; accent-color: var(--green-btn); flex: none; }
.legal-note {
  font-size: 0.72rem;
  color: var(--label-ink);
  text-align: center;
  margin: 0.5rem 0 0;
  line-height: 1.45;
}
.legal-note a { color: var(--green-btn); text-decoration: underline; }

/* --- Botón ------------------------------------------------------------------ */
/* El CTA del Figma (`Botón / CTA`, nodo 24:88), el MISMO que la app pinta en
   `YoseButton`: pill de 52 de alto y radio 26, etiqueta DM Mono Medium 12 en
   MAYÚSCULAS con tracking 1.8. Antes era Jost 600 en caja normal, 50 de alto y
   radio 14 — o sea, el mismo botón se veía de dos productos distintos según
   entraras por el teléfono o por la laptop.

   El `padding-left` compensa el tracking: `letter-spacing` mete el espacio
   DESPUÉS de la última letra, así que sin esto el texto se ve corrido a la
   izquierda dentro de un botón centrado. Es el mismo truco que el
   `marginLeft: 1.8` de `YoseButton.tsx`. */
.auth-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 52px;
  margin-top: 1.15rem;
  border: 0;
  border-radius: 26px;
  background: var(--green-btn);
  color: var(--parchment);
  font-family: 'DM Mono', monospace;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  text-transform: uppercase;
  letter-spacing: 1.8px;
  padding-left: 1.8px;
  box-shadow: 0 6px 16px rgba(18, 84, 64, 0.22);
  transition: opacity 0.18s var(--ease), transform 0.15s var(--ease),
              box-shadow 0.18s var(--ease);
}
.auth-btn:hover:not(:disabled) { transform: translateY(-1px); }
.auth-btn:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }
.auth-btn:disabled { opacity: 0.5; box-shadow: none; cursor: default; }

/* --- Los otros caminos de entrada -------------------------------------------
   Correo y Google. Mismo alto (52) y mismo radio (26) que `.auth-btn`: son tres
   caminos del mismo rango, no un primario con dos notas al pie, así que el
   correo va con tratamiento de botón y no como enlace. La geometría se movió
   junto con el CTA (era 50/14); si se mueve uno solo, dejan de leerse como tres.

   La ETIQUETA aquí NO va en mono mayúsculas como en el CTA: "Continuar con
   Google" es texto de marca de un tercero y sus lineamientos piden respetarlo
   tal cual. El Figma solo dibuja el CTA, así que esto es criterio, no diseño.

   🚨 El contraste se midió contra el MISMO peor punto que el resto de la
   tarjeta: estos botones caen sobre el vidrio al 56% encima del trazo de la
   "Yose" (#125440), no sobre blanco. `--ink` sobre ese fondo da 12.6:1. El borde
   `--field-line` da 3.20:1 sobre blanco —lo que pide WCAG 1.4.11 para el
   contorno de un control— pero 2.21 sobre el peor punto del vidrio; ver la nota
   de arriba. Cambiar el relleno a algo más claro que `--field-fill` vuelve a
   dejar la caja sin contorno visible, que es el bug que ya se arregló en los
   campos. */
.auth-social {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  width: 100%;
  height: 52px;
  margin-top: 0.6rem;
  border: 1.5px solid var(--field-line);
  border-radius: 26px;
  background: var(--field-fill);
  color: var(--ink);
  font-family: var(--body);
  font-size: 0.95rem;
  font-weight: 500;
  cursor: pointer;
  text-transform: none;
  letter-spacing: normal;
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease),
              transform 0.15s var(--ease);
}
.auth-social:hover { border-color: var(--field-line-hover); background: #FFFFFF; }
.auth-social:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }
.auth-social svg { flex: none; }

/* Separador con etiqueta. La línea NO cruza por detrás del texto: son dos
   mitades que crecen, así que no hay que pintarle un fondo a la etiqueta para
   taparla — y sobre vidrio ese fondo se notaría. */
.auth-or {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 1.3rem 0 0;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 1.4px;
  color: var(--label-ink);
}
.auth-or::before,
.auth-or::after { content: ""; flex: 1; height: 1px; background: var(--field-line); }

/* El botón de Google es NUESTRO botón con el iframe de Google encima, a opacidad
   0: la librería no deja reestilizar lo que dibuja (llega con Roboto, alto 40 y
   radio 4), y un botón de otra forma al lado de los demás se ve como un injerto.
   El que recibe el clic y el foco es el de Google — el nuestro es la piel, por
   eso va `aria-hidden` y fuera del tabulador (ver login.html).
   ponytail: superposición; si Google cambia el tamaño de su iframe hay que
   volver a medir. La salida es soltar la piel y quedarse con su botón tal cual. */
.auth-social-wrap { position: relative; }
.auth-social-wrap .gis {
  position: absolute;
  inset: 0;
  opacity: 0;
  overflow: hidden;
  /* `colorScheme: normal` en el iframe evita que herede el esquema del sistema y
     cambie de alto; el clic tiene que caer sobre el botón, no al lado. */
  color-scheme: normal;
}
/* Sin la librería de Google no queda un botón muerto: se esconde el bloque
   entero. Un botón que no hace nada es peor que no ofrecerlo. */
.auth-social-wrap[hidden] { display: none !important; }

/* --- Código de 6 dígitos ---------------------------------------------------- */
.otp-inputs {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: clamp(0.35rem, 2vw, 0.6rem);
  margin: 1.1rem 0 0;
}
.otp-inputs input {
  width: 100%;
  height: 56px;
  border: 1.5px solid var(--field-line);
  border-radius: 16px;
  background: var(--field-fill);
  text-align: center;
  font-family: var(--body);
  font-weight: 500;
  font-size: 1.1rem;
  color: #1A1814;
  outline: none;
  transition: border-color 0.18s var(--ease), box-shadow 0.18s var(--ease),
              background 0.18s var(--ease);
}
.otp-inputs input:focus {
  background: #FFFFFF;
  border-color: var(--green-btn);
  box-shadow: 0 0 0 3px var(--focus-ring);
}

.resend { text-align: center; font-size: 0.85rem; color: var(--label-ink); margin: 0.9rem 0 0; }
.resend a { color: var(--green-btn); text-decoration: underline; cursor: pointer; }

/* --- Mensajes de error ------------------------------------------------------ */
.error-msg {
  display: none;
  color: var(--error);
  font-size: 0.82rem;
  margin: 0.5rem 0 0;
  text-align: center;
}
.error-msg.show { display: block; }

/* --- Pie de la tarjeta y frase ---------------------------------------------- */
.auth-alt { text-align: center; font-size: 0.85rem; color: var(--label-ink); margin: 0.9rem 0 0; }
.auth-alt a { color: var(--green-btn); text-decoration: underline; }

.auth-tagline {
  position: relative;
  z-index: 1;
  font-family: var(--display);
  font-weight: 500;
  font-style: italic;
  font-size: clamp(1.3rem, 2.8vw, 2.5rem);
  color: var(--forest-ink);
  text-align: center;
  /* El aire va en vh: es la distancia a un trazo que también se mide contra el
     alto de la ventana. En vw, una pantalla ancha y baja volvía a juntarlos. */
  margin: clamp(1.75rem, 6vh, 4rem) 0 0;
}

.auth-back {
  position: fixed;
  top: 1.25rem;
  left: 1.25rem;
  z-index: 2;
  font-size: 0.85rem;
  color: var(--green-btn);
  text-decoration: none;
}
.auth-back:hover { text-decoration: underline; }

[hidden] { display: none !important; }

@media (max-width: 520px) {
  /* En móvil la palabra es más grande pero cabe muy arriba, y la leyenda queda
     lejísimos: no hace falta subirla más (subirla le cortaría la "Y"). */
  .auth-bg { font-size: 110vw; transform: translateY(-5vh); }
  .auth-card { border-radius: 22px; }
  .otp-inputs input { height: 50px; border-radius: 13px; }
}

@media (prefers-reduced-motion: reduce) {
  .auth-btn:hover:not(:disabled) { transform: none; }
  /* El cambio de modo sigue funcionando: pasa de golpe, que es justo lo que
     pide quien activó esto. El crossfade del texto lo apaga el JS aparte. */
  .auth-tabs::before,
  .auth-swap,
  .fade { transition: none; }
}
