/* ═══════════════════════════════════════════════════════════
   LOGIN
   Es una herramienta de trabajo que se abre todos los días, no
   una landing. Criterio: el movimiento responde a acciones del
   usuario; no decora de fondo. Las ondas quedan (son la firma
   visual y van detrás), pero la tarjeta ya no flota para siempre:
   entra una vez y se queda quieta.
═══════════════════════════════════════════════════════════ */
:root {
  --color-fondo-principal: #42aa58;
  --color-fondo-boton:     #42aa58;
  --color-login-bg:        #ffffff;
  --color-login-text:      #111827;
  --color-onda-1:          rgba(69, 105, 144, 0.15);
  --color-onda-2:          rgba(2, 128, 144, 0.2);
  --font-main:             'Poppins', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* Escala de radios: cada nivel de anidamiento sube un paso */
  /* Cuánto se difuminan las ondas. Lo pisa el tema desde la hoja
     `configuracion`; este valor es el que se ve mientras el tema no cargó. */
  --login-onda-blur: 1px;

  --radio-campo:  10px;
  --radio-card:   16px;
}

html, body {
  margin: 0;
  padding: 0;
  min-height: 100dvh;
  background-color: var(--color-fondo-principal);
  font-family: var(--font-main);
  overflow-x: hidden;
}

/* La tarjeta se centra con grid en vez de position:absolute + translate.
   Así puede crecer sin desbordar y el scroll funciona solo si hace falta. */
body {
  display: grid;
  place-items: center;
  padding: 24px 16px;
  box-sizing: border-box;
}

.login-container {
  position: relative;
  width: min(400px, 100%);
  box-sizing: border-box;
  padding: 40px 32px 32px;
  background-color: var(--color-login-bg);
  border-radius: var(--radio-card);
  box-shadow: 0 25px 45px rgba(0,0,0,.28), 0 10px 20px rgba(0,0,0,.16);
  overflow: hidden;
  z-index: 10;
  color: var(--color-login-text);
  animation: cardEntra .45s cubic-bezier(.16,1,.3,1) both;
}

/* Ondas decorativas — la firma visual del login. Van detrás de todo. */
.login-container::before,
.login-container::after {
  content: "";
  position: absolute;
  border-radius: 40% 45% 35% 40%;
  z-index: -1;
  pointer-events: none;
}
/* ── La geometría ORIGINAL, y por qué volvió ────────────────────────────────

   Estos cuatro números —600px, `left: 35%`, `left: 30%`, y los dos `bottom`—
   son los de siempre, recuperados de git. En el medio se probó centrarlas y
   achicarlas, con el argumento de que «arrancaban corridas»: era un argumento
   correcto sobre un problema que no existía. **Estar corridas a la derecha y
   abajo ERA el diseño**, y es lo que hace que se vea una ola subiendo en
   diagonal en vez de una banda simétrica.

   Lo que de verdad las había arruinado era otra cosa: el desenfoque. Ver abajo.

   Nota para el que venga: si alguna vez hay que centrarlas, va con `margin-left`
   y NO con `transform: translateX` — el `transform` ya lo usa la animación de
   rotación y el segundo pisa al primero sin avisar. */
.login-container::before,
.login-container::after {
  width: 600px;
  height: 600px;
}
.login-container::before {
  left: 35%; bottom: -90%;
  background-color: var(--color-onda-1);
  animation: waves 6s linear infinite;
}
.login-container::after {
  left: 30%; bottom: -85%;
  background-color: var(--color-onda-2);
  animation: waves 7s linear infinite;
}

/* ═══ EL CANTO DE VIDRIO ══════════════════════════════════════════════════════

   Primer intento, y el error vale anotarlo: se puso una lámina translúcida
   ENCIMA de las ondas. La cuenta del contraste daba bien, pero las ondas por
   defecto son `rgba(...,.15)` —ya son suaves— y un velo al 65% las borró. Quedó
   una tarjeta blanca y plana: **peor que antes**, y encima no era lo que se
   había pedido, que era el canto.

   La lección: el vidrio no se hace tapando lo que hay detrás. Se hace en el
   BORDE —donde el material tiene espesor y la luz pega— y difundiendo lo de
   atrás, no cubriéndolo.

   Nada de acá toca un color configurable: son luces y sombras neutras sobre lo
   que el cliente ya eligió. `node scripts/probar-vidrio.js` comprueba las dos
   mitades: que el canto exista, y que **nada cubra las ondas**.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Las ondas dejan de ser manchas y pasan a ser LUZ adentro del material.

   El `blur` fue 36, después 26, 9, 3, y terminó en 1. Cada bajada mejoró la
   pantalla, lo cual dice bastante: **el desenfoque era el problema desde el
   primer intento**, y las dos veces que se movió la geometría se estaba
   arreglando lo que no era.

   El borde ES la ola. El `border-radius` irregular que al rotar deforma el
   contorno es todo el efecto; difuminarlo hasta que solo quede el relleno la
   convierte en una banda de color.

   El 1px que queda no difumina nada: solo le saca el filo de calcomanía contra
   el vidrio. **Poner 0 también es válido** — es la ola exacta de antes.

   Y el `saturate` es por otra cosa: las ondas por defecto son azul-gris y
   verde-azulado, y sobre una tarjeta que ahora tiene el tinte de la página se
   apagan a gris sucio. Saturar **no cambia el color que eligió el cliente**: lo
   hace leer como color y no como suciedad. */
.login-container::before,
.login-container::after {
  filter: blur(var(--login-onda-blur, 1px)) saturate(1.7);
}

/* La tarjeta deja pasar un poco el fondo de la PÁGINA. Ojo con la diferencia,
   que es justo la que arruinó el intento anterior: las ondas se pintan ENCIMA
   del fondo de la tarjeta, así que esto no las toca — lo que asoma por detrás es
   el color de la página, no ellas.

   Cuánto deja pasar lo elige el cliente (Personalización → «Transparencia del
   cuadro»), y el servidor lo acota con SUS colores para que el texto se siga
   leyendo: la cuenta está en public/js/contraste-login.js. Lo que decide el
   tope son las etiquetas (#4b5563), no el título: con 18% —el 82% de opacidad
   de siempre— dan 5.87:1 sobre el verde de Data Studio y 4.95:1 en el peor caso
   imaginable (página negra). WCAG AA pide 4.5:1. Los campos del formulario,
   además, tienen fondo propio opaco: ahí se escribe y no se negocia. */
.login-container {
  background-color: color-mix(in srgb, var(--color-login-bg) var(--login-card-opacidad, 82%), transparent);

  /* El espesor del material. De afuera hacia adentro:
       · el halo, la luz que el vidrio derrama sobre la página;
       · las dos sombras de siempre, que dan la altura;
       · un borde interno tenue = el canto tiene grosor;
       · sombra bajo el filo de arriba, y resplandor abajo, que es por donde la
         luz "entra" al cristal.
     Va en UNA declaración sobre la tarjeta. Una versión anterior lo colgaba del
     `::before` del título y se rompía sola el día que alguien le diera
     `position` al `h1`. */
  box-shadow:
    0 0 40px rgba(255, 255, 255, .16),
    0 25px 45px rgba(0, 0, 0, .28),
    0 10px 20px rgba(0, 0, 0, .16),
    inset 0 0 14px 3px rgba(17, 24, 39, .06),
    inset 0 10px 16px -12px rgba(17, 24, 39, .16),
    inset 0 -30px 38px -16px rgba(255, 255, 255, .50);
}

/* ── EL ARO ESPECULAR ───────────────────────────────────────────────────────
   Esto es lo que de verdad hace que se lea como vidrio, y es lo que faltaba.

   Un anillo blanco uniforme se lee como BORDE. Uno que es brillante arriba y
   abajo y tenue a los lados se lee como la LUZ DOBLÁNDOSE en un canto — que es
   lo que hace el vidrio de verdad. Por eso el color del aro va en un
   `conic-gradient` y no en un `border`.

   La máscara recorta el centro y deja solo el filo: no cubre nada. Esa es toda
   la diferencia con el velo que se probó antes. */
.login-canto {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  border-radius: inherit;
  padding: 1.5px;                 /* el grosor del aro */
  background: conic-gradient(
    rgba(255, 255, 255, 1)   0deg,     /* arriba: el reflejo fuerte */
    rgba(255, 255, 255, .22) 80deg,    /* costado derecho: casi nada */
    rgba(255, 255, 255, .88) 180deg,   /* abajo: la luz que entra */
    rgba(255, 255, 255, .26) 275deg,   /* costado izquierdo */
    rgba(255, 255, 255, 1)   360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}

/* Sin `mask` el aro sería un rectángulo blanco sólido tapando la tarjeta
   entera: mucho peor que no tenerlo. Si el navegador no la soporta, no existe. */
@supports not ((-webkit-mask-composite: xor) or (mask-composite: exclude)) {
  .login-canto { display: none; }
}

@keyframes waves     { to { transform: rotate(360deg); } }
@keyframes cardEntra { from { opacity: 0; transform: translateY(12px); } }

.login-title {
  text-align: center;
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: -.01em;
  margin: 0 0 1.75rem;
}

.form-login { position: relative; z-index: 1; }

.login__label {
  display: block;
  margin-bottom: 6px;
  font-size: 0.72rem;
  font-weight: 600;
  /* Era #6b7280, y sobre el cuadro translúcido daba 3.7:1 con el verde de Data
     Studio: debajo de AA, y nadie lo medía porque la cuenta miraba solo el
     título. Un tono más oscuro pasa en todos los casos (2026-10-06). */
  color: #4b5563;
  text-transform: uppercase;
  letter-spacing: .08em;
}

.login__field { margin-bottom: 1.1rem; }

/* Envoltorio para poder meter el botón de ver contraseña adentro */
.login__input-wrap { position: relative; display: block; }

.login__input {
  width: 100%;
  padding: 12px 14px;
  font-size: 0.95rem;
  border-radius: var(--radio-campo);
  border: 1.5px solid #e5e7eb;
  background: #f8fafc;
  font-family: inherit;
  color: #111827;
  outline: none;
  transition: border-color .18s ease, box-shadow .18s ease, background .18s ease;
  box-sizing: border-box;
}
.login__input--con-boton { padding-right: 46px; }

.login__input::placeholder { color: #9ca3af; }

.login__input:hover:not(:focus) { border-color: #d1d5db; }

.login__input:focus-visible {
  border-color: var(--color-fondo-principal);
  background: #fff;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-fondo-boton) 18%, transparent);
}

/* Botón mostrar/ocultar contraseña */
.login__ojo {
  position: absolute;
  right: 6px; top: 50%;
  transform: translateY(-50%);
  display: grid; place-items: center;
  width: 34px; height: 34px;
  border: none; background: none; padding: 0;
  border-radius: 8px;
  color: #9ca3af;
  cursor: pointer;
  transition: color .18s ease, background .18s ease;
}
/* `hidden` tiene que ganar: con `display: grid` el botón se dibujaba sin JS,
   encima del campo y sin hacer nada — lo contrario de lo que promete el
   marcado. Ver scripts/revisar-ocultos.js. */
.login__ojo[hidden] { display: none; }
.login__ojo:hover { color: #4b5563; background: #f1f5f9; }
.login__ojo:focus-visible {
  outline: none;
  color: #4b5563;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-fondo-boton) 22%, transparent);
}

.login__submit {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  margin-top: .5rem;
  padding: 12px;
  background-color: var(--color-fondo-boton);
  color: #fff;
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  border: none;
  border-radius: var(--radio-campo);
  cursor: pointer;
  transition: background-color .18s ease, transform .08s ease, box-shadow .18s ease;
}

/* El hover del botón se deriva del mismo color. Antes dependía de
   --color-hover-boton, que buildTemaCSS emite con el MISMO valor que el
   fondo: el hover no se notaba. */
.login__submit:hover {
  background-color: color-mix(in srgb, var(--color-fondo-boton) 88%, #000);
}
.login__submit:active { transform: translateY(1px); }
.login__submit:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px #fff, 0 0 0 6px color-mix(in srgb, var(--color-fondo-boton) 55%, transparent);
}

/* Estado enviando: evita el doble submit cuando Sheets tarda */
.login__submit[data-enviando] { cursor: progress; opacity: .85; }
.login__submit[data-enviando] .login__submit-texto::after {
  content: '';
  display: inline-block;
  width: 13px; height: 13px;
  margin-left: 9px;
  vertical-align: -2px;
  border: 2px solid rgba(255,255,255,.45);
  border-top-color: #fff;
  border-radius: 50%;
  animation: girar .6s linear infinite;
}
@keyframes girar { to { transform: rotate(360deg); } }

.logo-container { text-align: center; margin-top: 1.5rem; }
.logo { max-width: 150px; height: auto; }

.error {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin-top: 1rem;
  padding: 11px 13px;
  background-color: #fef2f2;
  border: 1px solid #fecaca;
  border-radius: var(--radio-campo);
  color: #991b1b;
  font-size: 0.875rem;
  line-height: 1.45;
  animation: cardEntra .25s ease both;
}
.error::before { content: '⚠'; flex-shrink: 0; font-size: 0.95rem; line-height: 1.3; }

@media (max-width: 480px) {
  .login-container { padding: 32px 22px 26px; }
  .login-title     { font-size: 1.3rem; }
  .logo            { max-width: 120px; }
}

/* Respeta a quien pidió menos movimiento: se va TODO lo ambiental.
   El spinner del botón se mantiene porque comunica un estado real. */
@media (prefers-reduced-motion: reduce) {
  .login-container,
  .login-container::before,
  .login-container::after,
  .error { animation: none; }
  .login__input, .login__submit, .login__ojo { transition: none; }
}

/* ═══ EL BOTÓN, COMO VIDRIO ═══════════════════════════════════════════════════

   ── Lo que acá NO se hace ──────────────────────────────────────────────────
   El botón no se vuelve translúcido y no lleva un brillo encima del texto.
   Medido sobre cuatro colores de marca, para el texto blanco:

     marca        opaco   al 88%   con brillo blanco encima
     verde         2.95     2.64          2.61
     rojo          5.53     5.16          5.14
     azul          5.70     4.73          4.67
     amarillo      1.61     1.55          1.54

   Cualquier cosa que aclare el fondo bajo un texto blanco resta, y este botón es
   LA acción de la pantalla. (El verde y el amarillo ya no pasan hoy, sin tocar
   nada: eso está anotado aparte en docs/tareas.md — no lo introduce esto.)

   ── Lo que sí ──────────────────────────────────────────────────────────────
   Solo canto, que es luz en los bordes y no toca el fondo del texto. Y acá el
   aro SÍ puede ser blanco puro, al revés que en las tarjetas del portal: el
   botón es un color fuerte, así que un filo blanco se recorta contra él. Es la
   misma razón por la que funciona en la tarjeta del login y no en una tarjeta
   blanca sobre gris claro.
   ═══════════════════════════════════════════════════════════════════════════ */
/* ── LAS SOMBRAS SON NEGRAS. SIEMPRE. ───────────────────────────────────────
   La primera versión tiraba un halo del color del botón
   (`color-mix(var(--color-fondo-boton) 32%)`). Dos cosas mal:

     · no sabemos qué color va a elegir el cliente, y un halo del color de marca
       se ve distinto —a veces mal— con cada uno;
     · y una sombra de color no es una sombra: es un RESPLANDOR. El botón parecía
       encendido, no de vidrio. El vidrio no emite luz: la dobla en el canto y
       tapa la que hay detrás.

   La distinción que ordena esto, y que el resto del portal ya respetaba: un
   ANILLO DE FOCO (`0 0 0 3px`, sin desplazamiento ni desenfoque) es un contorno
   y va del color de marca. Una SOMBRA —con desplazamiento o desenfoque— es luz
   bloqueada, y va negra con alfa. */
.login__submit {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, .16),
    0 5px 14px rgba(0, 0, 0, .16),
    inset 0 1px 0 rgba(255, 255, 255, .26),
    inset 0 -1px 0 rgba(0, 0, 0, .22);
  transition: background-color .18s ease, transform .08s ease, box-shadow .18s ease;
}

/* El aro especular. Brillante arriba y abajo, tenue a los lados: la luz
   doblándose en el canto, no un borde. Masked, así que es SOLO el filo. */
.login__submit::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  border-radius: inherit;
  padding: 1px;
  /* Bajado de .85/.55 a .50/.30: con el aro fuerte el botón se leía encendido.
     El filo del vidrio es un reflejo, no una lámpara. */
  background: conic-gradient(
    rgba(255, 255, 255, .50)   0deg,
    rgba(255, 255, 255, .10)  90deg,
    rgba(255, 255, 255, .30) 180deg,
    rgba(255, 255, 255, .12) 270deg,
    rgba(255, 255, 255, .50) 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}
/* Sin `mask-composite` el aro sería un bloque blanco tapando el texto del botón:
   mucho peor que no tenerlo. */
@supports not ((-webkit-mask-composite: xor) or (mask-composite: exclude)) {
  .login__submit::before { display: none; }
}

/* Al pasar el mouse el fondo se oscurece —eso ya estaba y es lo que sostiene el
   texto blanco— y el material se levanta: más halo, más filo. */
.login__submit:hover {
  box-shadow:
    0 2px 4px rgba(0, 0, 0, .18),
    0 9px 22px rgba(0, 0, 0, .20),
    inset 0 1px 0 rgba(255, 255, 255, .32),
    inset 0 -1px 0 rgba(0, 0, 0, .24);
}
/* Al apretarlo se hunde: la sombra proyectada se achica y aparece una interior.
   Negras las dos — es la misma luz bloqueada, desde el otro lado. */
.login__submit:active {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, .14),
    inset 0 2px 5px rgba(0, 0, 0, .24);
}
