/*
 * Asistencia — hoja única de la app de fichaje.
 *
 * Habla el idioma visual del ERP (Nunito, el color de marca de la empresa, el
 * degradé de dos capas de .bg-gradient-primary) pero SIN cargar nada del ERP:
 * en producción esta app vive en otro subdominio con docroot propio, así que
 * cualquier ruta a vistas/dist/ estaría rota. Los tokens están replicados acá.
 *
 * Si alguien cambia el degradé en vistas/plantilla.php, hay que cambiarlo acá
 * también. El síntoma sería que el fichaje y el backoffice de la MISMA
 * empresa se ven de distinto color.
 *
 * Contexto de uso, que manda sobre cualquier gusto: alguien parado en la
 * puerta de un local, con una mano ocupada, a veces al sol, a las 6 de la
 * mañana o a las 10 de la noche, haciendo esto dos veces por día durante
 * años. Todo lo tocable pasa los 56px, el reloj se lee de lejos y la
 * confirmación se entiende de un vistazo.
 */

:root {
  /* --primary / --primary-hover las inyecta index.php con el color de la
     empresa. Estos son el fallback del ERP por si ese bloque no llegara. */
  --primary: #002a45;
  --primary-hover: #001d30;

  --tinta: #f8fafc;
  --tinta-tenue: rgba(248, 250, 252, 0.62);
  --tinta-debil: rgba(248, 250, 252, 0.38);

  --vidrio: rgba(255, 255, 255, 0.09);
  --vidrio-borde: rgba(255, 255, 255, 0.16);
  --pozo: rgba(0, 0, 0, 0.26);

  --ok: #22c55e;
  --alerta: #fbbf24;
  --error: #f87171;

  --radio: 22px;
  --sombra: 0 24px 60px -12px rgba(0, 0, 0, 0.55);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  color: var(--tinta);
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
}

/*
 * El campo de marca. Es la misma receta que .bg-gradient-primary del ERP
 * (vistas/plantilla.php): una capa de brillo blanco->transparente->negro a
 * 180deg encima de la rampa de color a 135deg. Encima va un halo radial que
 * levanta el centro, para que la tarjeta no flote sobre un plano muerto.
 */
body {
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(255, 255, 255, 0.16) 0%, rgba(255, 255, 255, 0) 60%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0) 50%, rgba(0, 0, 0, 0.15) 100%),
    linear-gradient(135deg, var(--primary) 55%, var(--primary-hover) 100%);
  background-attachment: fixed;
  transition: background 420ms ease;
}

/* Grano finísimo. Le saca el aspecto plástico al degradé en pantallas
   grandes, donde un gradiente limpio se bandea. Va en ::before para no
   costar un nodo. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E");
}

/*
 * La tarjeta va ARRIBA, no centrada.
 *
 * Centrada verticalmente se veía mejor en el simulador y peor en un celular
 * real: la barra de direcciones y la barra de gestos de iOS/Android se comen
 * el borde inferior, y lo primero que desaparece es el pie de la tarjeta
 * ("Cambiar mi PIN"). Con 100dvh eso mejora pero no se arregla, porque dvh
 * cambia al hacer scroll y el usuario no llega a scrollear en una pantalla
 * de un solo golpe.
 *
 * `margin-bottom: auto` sin `margin-top: auto` empuja todo el sobrante hacia
 * abajo: la tarjeta queda pegada arriba y el pie siempre entra. El
 * padding-top con clamp le da aire en pantallas altas sin bajarla en las
 * chicas.
 */
.pantalla {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: clamp(0.75rem, 3.5vh, 2.25rem) 1.25rem 1.25rem;
  padding-bottom: max(1.25rem, env(safe-area-inset-bottom));
  overflow-y: auto;
}

.pantalla > .tarjeta { margin-bottom: auto; }

/* ================= tarjeta de vidrio ================= */

.tarjeta {
  width: 100%;
  max-width: 25rem;
  padding: 1.75rem 1.5rem 1.25rem;
  text-align: center;

  background: var(--vidrio);
  border: 1px solid var(--vidrio-borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
  /* saturate() recupera el color que el blur le come al degradé de atrás. */
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
}

/* El navegador que no soporta backdrop-filter mostraría un panel casi
   transparente e ilegible: ahí se cae a un relleno opaco. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .tarjeta { background: rgba(0, 0, 0, 0.42); }
}

.tarjeta--error { border-color: rgba(248, 113, 113, 0.45); }

.oculto { display: none; }

/* ================= cabecera ================= */

.empresa {
  margin: 0;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--tinta-debil);
}

.titulo {
  margin: 0.4rem 0 0;
  font-size: 1.45rem;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.015em;
}

/* ================= el reloj ================= */

.reloj-bloque { margin: 1.25rem 0 1rem; }

.reloj {
  margin: 0;
  font-size: clamp(3.25rem, 17vw, 4.5rem);
  font-weight: 800;
  line-height: 0.95;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  /* El degradé sobre el texto le da el mismo brillo que tienen las barras
     del ERP, sin necesidad de una imagen. */
  background: linear-gradient(180deg, #fff 30%, rgba(255, 255, 255, 0.72) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Los dos puntos laten con el segundero: es la señal de que la pantalla
   está viva y la hora que muestra es la de ahora, no una captura vieja. */
.reloj-sep {
  animation: latido 2s ease-in-out infinite;
  -webkit-text-fill-color: currentColor;
  color: rgba(255, 255, 255, 0.8);
}

@keyframes latido {
  0%, 45% { opacity: 1; }
  55%, 100% { opacity: 0.25; }
}

/* Sin text-transform: capitalize. PHP ya arma "Lunes 24 de agosto" con la
   capitalización correcta del castellano; capitalize lo rompía a
   "Lunes 24 De Agosto". */
.fecha {
  margin: 0.5rem 0 0;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--tinta-tenue);
}

/* ================= chip de ubicación ================= */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0 0 1rem;
  padding: 0.35rem 0.8rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--tinta-tenue);
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid var(--vidrio-borde);
  border-radius: 999px;
}

.chip-punto {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.22);
}

.chip--ok { margin-top: 0.9rem; }

/* ================= campos ================= */

.campos { display: grid; gap: 0.75rem; margin-bottom: 1rem; }

.campo { display: block; text-align: left; }

.campo-rotulo {
  display: block;
  margin-bottom: 0.4rem;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--tinta-debil);
}

.campo > input {
  width: 100%;
  height: 3.4rem;
  padding: 0 1rem;
  background: var(--pozo);
  border: 1px solid var(--vidrio-borde);
  border-radius: 14px;
  color: var(--tinta);
  /* 1.5rem y no menos: por debajo de 16px, iOS hace zoom al enfocar y
     descuadra la pantalla entera. */
  font-family: inherit;
  font-size: 1.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.16em;
  text-align: center;
  transition: border-color 160ms ease, box-shadow 160ms ease, background 160ms ease;
}

.campo > input::placeholder { color: var(--tinta-debil); }

.campo > input:focus {
  outline: none;
  background: rgba(0, 0, 0, 0.34);
  border-color: rgba(255, 255, 255, 0.55);
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.12);
}

/* ================= botones ================= */

/*
 * Blanco sólido, no el color de marca. Sobre un fondo que YA es el color de
 * marca, un botón de marca desaparece. Acá el botón tiene que ser lo más
 * evidente de la pantalla.
 */
.boton {
  width: 100%;
  min-height: 3.75rem;
  padding: 0 1rem;
  background: #fff;
  border: 0;
  border-radius: 14px;
  color: var(--primary);
  font-family: inherit;
  font-size: 1.2rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  cursor: pointer;
  box-shadow: 0 10px 24px -8px rgba(0, 0, 0, 0.5);
  transition: transform 120ms ease, box-shadow 160ms ease, opacity 160ms ease;
}

.boton:active { transform: translateY(2px); box-shadow: 0 4px 12px -6px rgba(0, 0, 0, 0.5); }
.boton:disabled { opacity: 0.5; cursor: default; transform: none; }

.boton:focus-visible {
  outline: 3px solid rgba(255, 255, 255, 0.9);
  outline-offset: 3px;
}

.boton--fantasma {
  margin-top: 1.5rem;
  background: transparent;
  border: 1px solid var(--vidrio-borde);
  color: var(--tinta);
  box-shadow: none;
  font-size: 1rem;
}

.enlace {
  margin-top: 1.1rem;
  padding: 0.5rem;
  background: none;
  border: 0;
  color: var(--tinta-debil);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.enlace:hover { color: var(--tinta-tenue); }

/* ================= textos de apoyo ================= */

.ayuda {
  margin: 0.9rem 0 0;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--tinta-tenue);
}

.ayuda--bloque {
  padding: 0.85rem 1rem;
  margin-bottom: 1.25rem;
  text-align: left;
  background: rgba(255, 255, 255, 0.06);
  border-radius: 12px;
}

/* Cuenta regresiva de la confirmación. Discreta a propósito: informa que la
   pantalla se va a reiniciar sola, sin competir con el nombre y la hora. */
.cuenta {
  margin: 0.75rem 0 0;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--tinta-debil);
  font-variant-numeric: tabular-nums;
  min-height: 1.1rem;
}

.estado {
  margin: 1rem 0 0;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--tinta-debil);
  min-height: 1.1rem;
}

.error {
  margin: 0.75rem 0 0;
  font-size: 0.92rem;
  font-weight: 700;
  line-height: 1.4;
  color: var(--error);
  min-height: 1.2rem;
}

/* ================= sello (confirmación / error) ================= */

.sello {
  width: 4.5rem;
  height: 4.5rem;
  margin: 0 auto 1rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid var(--vidrio-borde);
}

.sello svg { width: 2.1rem; height: 2.1rem; }
.sello--error { color: var(--error); border-color: rgba(248, 113, 113, 0.4); }

/* ================= confirmación ================= */

/*
 * La confirmación cambia el color del CAMPO ENTERO, no sólo un ícono. El
 * empleado mira de reojo mientras guarda el celular: el color tiene que
 * decir "entraste" o "saliste" antes de que llegue a leer nada.
 */
body.es-entrada { --primary: #14532d; --primary-hover: #052e16; }
body.es-salida  { --primary: #78350f; --primary-hover: #451a03; }

body.es-entrada .sello { color: #86efac; }
body.es-salida  .sello { color: #fcd34d; }

.ok-tipo {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--tinta-tenue);
}

.ok-nombre {
  margin: 0.5rem 0 0;
  font-size: 1.7rem;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.02em;
}

.ok-hora {
  margin: 0.75rem 0 0;
  font-size: clamp(3rem, 16vw, 4rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
}

/* ================= movimiento ================= */

@media (prefers-reduced-motion: no-preference) {
  /* Entrada escalonada: la tarjeta sube y sus partes aparecen en orden de
     lectura. Un solo momento coreografiado al abrir vale más que diez
     micro-animaciones sueltas. */
  .tarjeta { animation: subir 480ms cubic-bezier(0.16, 1, 0.3, 1) both; }

  .tarjeta > * { animation: aparecer 420ms cubic-bezier(0.16, 1, 0.3, 1) both; }
  .tarjeta > *:nth-child(1) { animation-delay: 90ms; }
  .tarjeta > *:nth-child(2) { animation-delay: 150ms; }
  .tarjeta > *:nth-child(3) { animation-delay: 210ms; }
  .tarjeta > *:nth-child(4) { animation-delay: 270ms; }
  .tarjeta > *:nth-child(5) { animation-delay: 320ms; }
  .tarjeta > *:nth-child(n+6) { animation-delay: 370ms; }

  .tarjeta--ok .sello { animation: sellar 560ms cubic-bezier(0.34, 1.56, 0.64, 1) both 120ms; }
}

@keyframes subir {
  from { opacity: 0; transform: translateY(26px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}

@keyframes aparecer {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

@keyframes sellar {
  from { opacity: 0; transform: scale(0.4); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .reloj-sep { animation: none; }
  body { transition: none; }
}

/* ================= legibilidad al sol ================= */

/*
 * Un cartel de fichaje se usa afuera. Con contraste alto pedido por el
 * sistema, se sacrifica la sutileza del vidrio por poder leer: el panel se
 * opaca y los textos tenues suben.
 */
@media (prefers-contrast: more) {
  .tarjeta { background: rgba(0, 0, 0, 0.55); border-color: rgba(255, 255, 255, 0.5); }
  .ayuda, .estado, .fecha, .chip { color: #e8eef5; }
  .campo-rotulo, .empresa { color: #cfd9e4; }
  .campo > input { background: rgba(0, 0, 0, 0.6); }
}

/* Pantallas altas: recién ahí sobra alto para que el reloj respire. Por
   debajo de eso manda que la tarjeta entre entera de un golpe. */
@media (min-height: 800px) {
  .tarjeta { padding: 2.25rem 1.85rem 1.5rem; }
  .reloj-bloque { margin: 1.6rem 0 1.25rem; }
}
