/* GENERADO por features/id/web/tools/install-auth-ui.mjs — no editar aqui. */
/* ============================================================================
   features/id — la superficie de autenticacion, una sola para todo el taller.

   ENTRAR, CREAR CUENTA, RECUPERAR LA CLAVE Y EL SEGUNDO FACTOR SON LA MISMA
   PANTALLA EN CINCO PRODUCTOS. Lo unico que cambia entre ellos es el color, la
   tipografia y la marca. Esto es esa pantalla; el producto solo declara sus
   tokens.

   EL CONTRATO, Y POR QUE TODO TIENE VALOR POR OMISION

   Cada token lleva `var(--x, valor)`. Un producto que no declare NINGUNO
   obtiene una pantalla neutra, correcta y accesible en claro y en oscuro. Sin
   esa red, olvidar un token deja un color vacio -- que el navegador resuelve
   como negro o como transparente -- y el defecto aparece en la pantalla por la
   que pasa el 100% de la gente.

   Se declara en un `auth-theme.css` del producto, y son once:

     --auth-font            tipografia del texto
     --auth-font-display    titulos (por omision, la misma)
     --auth-bg              fondo de la pagina
     --auth-surface         fondo de tarjeta y campos
     --auth-sunk            fondo de bloques secundarios
     --auth-ink             texto principal
     --auth-ink-2           texto secundario
     --auth-line            bordes
     --auth-accent          color de accion
     --auth-accent-ink      texto SOBRE el color de accion
     --auth-danger          error
     --auth-ok              acierto
     --auth-radius          radio de esquina

   `--auth-accent-ink` existe aparte a proposito: el contraste del texto sobre
   el boton no se puede derivar del acento, y calcularlo con `color-mix` acierta
   en los acentos oscuros y falla justo en los claros -- amarillos y verdes --,
   que es donde un boton queda ilegible.

   ESTA HOJA NO NOMBRA NINGUNA MARCA. Si aparece aqui un color literal de un
   producto, deja de servirle a los otros cuatro.
   ============================================================================ */

/* ── Valores por omision ───────────────────────────────────────────────────
   Neutros de verdad: grises y un azul de accion sobrio. No son "la marca por
   defecto", son lo que se ve mientras un producto todavia no declaro la suya. */
:root {
  --auth-font-fb:         system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --auth-bg-fb:           #f6f7f9;
  --auth-surface-fb:      #ffffff;
  --auth-sunk-fb:         #f1f3f6;
  --auth-ink-fb:          #14171c;
  --auth-ink-2-fb:        #5b6472;
  --auth-line-fb:         #d9dee6;
  --auth-accent-fb:       #1d4ed8;
  --auth-accent-ink-fb:   #ffffff;
  --auth-danger-fb:       #b42318;
  --auth-ok-fb:           #157347;
  --auth-radius-fb:       10px;
}

/* El modo oscuro por omision. Un producto que declare sus tokens pisa esto; uno
   que no, sigue siendo legible de noche en vez de quedar en blanco cegador. */
@media (prefers-color-scheme: dark) {
  :root {
    --auth-bg-fb:         #0f1216;
    --auth-surface-fb:    #171b21;
    --auth-sunk-fb:       #1d222a;
    --auth-ink-fb:        #e8ebef;
    --auth-ink-2-fb:      #9aa4b2;
    --auth-line-fb:       #2b323c;
    --auth-accent-fb:     #5b8cff;
    --auth-accent-ink-fb: #0b0f14;
    --auth-danger-fb:     #ff6b5e;
    --auth-ok-fb:         #4ade80;
  }
}

/* ── Pagina ────────────────────────────────────────────────────────────────── */

/* border-box PRIMERO y para todo.
   Sin esto, `width: 100%` mas `padding` suman por encima del contenedor y la
   tarjeta se sale por la derecha. Medido a 375px: la tarjeta cortada y su borde
   derecho fuera de pantalla. Es el defecto mas comun del CSS y no se ve en
   escritorio, que es donde uno mira. */
*, *::before, *::after { box-sizing: border-box; }

.auth-page {
  /* dvh y no vh: en movil la barra del navegador se retrae y `vh` deja un salto
     que mueve la tarjeta mientras se escribe. */
  min-height: 100dvh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  /* minmax(0, 1fr) y no la columna implicita: una columna `auto` se dimensiona
     al min-content del hijo mas ancho, y un solo elemento indivisible saca
     scroll horizontal a toda la pagina. Medido a 320px: 346px de scrollWidth. */
  grid-template-columns: minmax(0, 1fr);

  margin: 0;
  background: var(--auth-bg, var(--auth-bg-fb));
  color: var(--auth-ink, var(--auth-ink-fb));
  font-family: var(--auth-font, var(--auth-font-fb));
  font-size: 16px;
  line-height: 1.6;
  -webkit-text-size-adjust: 100%;
}

.auth-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  padding: 18px clamp(16px, 5vw, 32px);
}

.auth-brand {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--auth-font-display, var(--auth-font, var(--auth-font-fb)));
  font-weight: 600; font-size: 18px; letter-spacing: -0.01em;
  color: inherit; text-decoration: none;
}
.auth-brand img { display: block; height: 26px; width: auto; }

/* "Volver" solo existe cuando se llego aqui desde algun sitio. Nace `hidden` y
   el JS lo revela unicamente si el `?next=` paso la validacion: un boton de
   volver que no sabe a donde es peor que no tenerlo.

   La flecha es CSS y no parte del texto. Dentro de la cadena viajaria a los
   diccionarios de cinco productos, y el primero que traduzca "← Back" sin
   copiar la flecha la pierde en su idioma nada mas. */
.auth-back {
  font-size: 14px;
  color: var(--auth-ink-2, var(--auth-ink-2-fb));
  text-decoration: none;
}
.auth-back::before { content: "\2190"; margin-right: 6px; }
.auth-back:hover { color: var(--auth-ink, var(--auth-ink-fb)); }

.auth-main {
  display: grid; place-items: center;
  padding: clamp(24px, 6vw, 56px) clamp(16px, 5vw, 32px) 64px;
}

.auth-card {
  width: 100%; max-width: 420px;
  background: var(--auth-surface, var(--auth-surface-fb));
  border: 1px solid var(--auth-line, var(--auth-line-fb));
  border-radius: calc(var(--auth-radius, var(--auth-radius-fb)) * 1.6);
  padding: clamp(24px, 5vw, 36px);
}
.auth-card.wide { max-width: 560px; }

.auth-title {
  margin: 0;
  font-family: var(--auth-font-display, var(--auth-font, var(--auth-font-fb)));
  font-size: clamp(24px, 5vw, 28px);
  letter-spacing: -0.025em; font-weight: 600; line-height: 1.2;
}
.auth-sub { margin: 8px 0 0; font-size: 15px; color: var(--auth-ink-2, var(--auth-ink-2-fb)); }

/* ── Campos ────────────────────────────────────────────────────────────────── */

.auth-fields { display: grid; gap: 18px; margin-top: 26px; }
.auth-field  { display: grid; gap: 6px; }

/* El hueco donde el producto mete sus campos. `display: contents` lo saca del
   medio: los campos generados pasan a ser hijos directos de la rejilla del
   formulario y el espacio entre ellos es el mismo que entre los fijos. Con un
   contenedor de verdad ahi, el primero quedaba con doble separacion y se veia
   como un bloque aparte -- que es justo lo que no es. */
.auth-slot { display: contents; }

.auth-field label { font-size: 14px; font-weight: 550; }

/* Las pistas van ENCIMA del control. Debajo quedan tapadas por el popover de
   autocompletado y por el teclado del telefono, justo cuando hacen falta. */
.auth-hint { font-size: 13px; color: var(--auth-ink-2, var(--auth-ink-2-fb)); }

.auth-field input {
  font: inherit;
  /* 16px exactos: por debajo, iOS hace zoom al enfocar y descuadra la pagina. */
  font-size: 16px;
  padding: 12px 14px;
  width: 100%;
  color: var(--auth-ink, var(--auth-ink-fb));
  background: var(--auth-surface, var(--auth-surface-fb));
  border: 1px solid var(--auth-line, var(--auth-line-fb));
  border-radius: var(--auth-radius, var(--auth-radius-fb));
}
.auth-field input::placeholder { color: var(--auth-ink-2, var(--auth-ink-2-fb)); }

/* El foco se ve SIEMPRE y no se quita nunca: es la unica pista de donde esta
   quien navega con teclado. `outline-offset` lo separa del borde para que no se
   confunda con el estado de error. */
.auth-field input:focus-visible,
.auth-btn:focus-visible,
.auth-link:focus-visible,
.auth-back:focus-visible,
.auth-reveal:focus-visible {
  outline: 2px solid var(--auth-accent, var(--auth-accent-fb));
  outline-offset: 2px;
}

/* :user-invalid y no :invalid. `:invalid` marca en rojo un campo vacio nada mas
   cargar la pagina y mientras se escribe; `:user-invalid` espera a que la
   persona termine con el campo o intente enviar. */
.auth-field input:user-invalid {
  border-color: var(--auth-danger, var(--auth-danger-fb));
}
.auth-field input:user-valid { border-color: var(--auth-ok, var(--auth-ok-fb)); }

/* El error nunca va SOLO por color: color, texto y simbolo. Quien no distingue
   rojo de gris tiene que poder leer que paso. */
.auth-err { display: none; font-size: 13px; color: var(--auth-danger, var(--auth-danger-fb)); }
.auth-field input:user-invalid ~ .auth-err { display: block; }
.auth-err::before { content: "⚠ "; }

/* Las reglas de la clave se ATENUAN cuando ya se cumplen, no desaparecen: si
   desaparecen, quien vuelve a editar pierde la referencia de que tenia que
   cumplir. */
.auth-rules { font-size: 13px; color: var(--auth-ink-2, var(--auth-ink-2-fb)); display: grid; gap: 2px; margin: 0; padding-left: 18px; }
.auth-field:has(input:user-invalid) .auth-rules { color: var(--auth-danger, var(--auth-danger-fb)); }
.auth-field:has(input:user-valid)   .auth-rules { opacity: 0.55; }

/* Ver la clave. Es un boton de verdad -- enfocable y anunciable --, no un icono
   con un listener encima. */
.auth-pw { position: relative; display: grid; }
.auth-reveal {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 13px; padding: 8px 10px;
  color: var(--auth-ink-2, var(--auth-ink-2-fb));
  border-radius: var(--auth-radius, var(--auth-radius-fb));
}

/* ── Acciones ──────────────────────────────────────────────────────────────── */

.auth-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%;
  font: inherit; font-size: 16px; font-weight: 600;
  padding: 13px 18px;
  border: 1px solid transparent;
  border-radius: var(--auth-radius, var(--auth-radius-fb));
  background: var(--auth-accent, var(--auth-accent-fb));
  color: var(--auth-accent-ink, var(--auth-accent-ink-fb));
  cursor: pointer;
}
.auth-btn[disabled] { opacity: 0.6; cursor: progress; }

.auth-alt { margin-top: 22px; font-size: 15px; color: var(--auth-ink-2, var(--auth-ink-2-fb)); text-align: center; }
.auth-link { color: var(--auth-accent, var(--auth-accent-fb)); }

/* La fila de "olvide mi clave" va junto al campo, no al pie: quien no puede
   entrar la busca ahi y no debajo del boton que acaba de fallarle. */
.auth-row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.auth-row .auth-hint { margin: 0; }

/* ── Resultado del envio ───────────────────────────────────────────────────── */

/* `hidden` de HTML lo oculta y el JS solo lo revela. Sin JS el formulario postea
   de verdad y el servidor responde: ese es el degradado correcto. */
.auth-result {
  margin-top: 18px;
  border: 1px solid var(--auth-line, var(--auth-line-fb));
  border-left: 3px solid var(--auth-accent, var(--auth-accent-fb));
  border-radius: var(--auth-radius, var(--auth-radius-fb));
  background: var(--auth-sunk, var(--auth-sunk-fb));
  padding: 14px 16px;
  font-size: 15px;
}
.auth-result[hidden] { display: none; }
.auth-result[data-tone="error"] { border-left-color: var(--auth-danger, var(--auth-danger-fb)); }
.auth-result[data-tone="ok"]    { border-left-color: var(--auth-ok, var(--auth-ok-fb)); }

/* Los mensajes viven en el HTML con su clave de i18n y ocultos; el JS los copia
   por clave. Un texto escrito dentro de un .js se queda sin traducir para
   siempre. */
.auth-msgs { display: none; }

/* ── Segundo factor ────────────────────────────────────────────────────────── */

/* El paso del codigo NO es otra pagina: es el mismo formulario que cambia. Ir a
   otra URL pierde el reto si alguien recarga, y obliga a guardar el token del
   reto en algun sitio. */
.auth-step[hidden] { display: none; }

.auth-code {
  font-size: 24px; letter-spacing: 0.35em; text-align: center;
  font-variant-numeric: tabular-nums;
}

/* ── Pie ───────────────────────────────────────────────────────────────────── */

.auth-foot {
  border-top: 1px solid var(--auth-line, var(--auth-line-fb));
  padding: 20px clamp(16px, 5vw, 32px);
  font-size: 13px; color: var(--auth-ink-2, var(--auth-ink-2-fb));
  display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between;
}

/* Un pie vacio no se dibuja. El producto puede no tener nada que poner ahi, y
   una linea horizontal sobre nada es ruido que quien mira intenta interpretar.
   `:has()` lo resuelve sin JS y sin que el HTML tenga que saberlo. */
.auth-foot:not(:has(*:not(:empty))) { display: none; }

/* Quien pidio menos movimiento no recibe ninguno. No es un detalle de gusto: el
   movimiento provoca mareo real en personas con trastornos vestibulares. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}
