login-tsi 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { NgClass } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { signal, Injectable, inject, input, output, Component, computed, model, HostListener, InjectionToken, viewChild, DestroyRef, effect, untracked, afterRenderEffect } from '@angular/core';
3
+ import { InjectionToken, signal, Injectable, inject, input, output, Component, computed, viewChild, DestroyRef, effect, untracked, afterRenderEffect, model, HostListener } from '@angular/core';
4
4
  import * as i1 from '@angular/forms';
5
5
  import { ReactiveFormsModule, FormBuilder, Validators, FormsModule } from '@angular/forms';
6
6
  import { trigger, transition, style, animate } from '@angular/animations';
@@ -15,6 +15,33 @@ const fadeInOut = trigger('fadeInOut', [
15
15
  ]),
16
16
  ]);
17
17
 
18
+ const AUTH_API = new InjectionToken('AUTH_API');
19
+ function provideAuthApi(servicio) {
20
+ return { provide: AUTH_API, useExisting: servicio };
21
+ }
22
+
23
+ const textoValido = (valor) => typeof valor == 'string' && !!valor.trim();
24
+ const mensajeDe = (err, defecto) => {
25
+ if (textoValido(err))
26
+ return err;
27
+ if (err && typeof err == 'object' && 'error' in err) {
28
+ const body = err.error;
29
+ if (textoValido(body))
30
+ return body;
31
+ const mensaje = body?.message;
32
+ return textoValido(mensaje) ? mensaje : defecto;
33
+ }
34
+ const mensaje = err?.message;
35
+ return textoValido(mensaje) && !/^\d+$/.test(mensaje) ? mensaje : defecto;
36
+ };
37
+
38
+ function isMfaChallenge(body) {
39
+ return body?.mfaRequerido === true && !!body?.preauthToken;
40
+ }
41
+ function isPushPendiente(body) {
42
+ return body?.result === 'waiting' || body?.result === 'deny' || body?.result === 'expired';
43
+ }
44
+
18
45
  class PwaInstallService {
19
46
  isAndroid = /Android/i.test(navigator.userAgent);
20
47
  isIOS = /iPad|iPhone|iPod/i.test(navigator.userAgent);
@@ -107,11 +134,204 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
107
134
  args: [{ selector: 'app-refresh-floating', template: "<div class=\"refresh-wrap\">\r\n\r\n @if (showGuide()) {\r\n <div class=\"refresh-guide\">\r\n <button class=\"refresh-guide__close\" (click)=\"toggleGuide()\">\r\n <i class=\"fas fa-xmark\"></i>\r\n </button>\r\n\r\n <p class=\"refresh-guide__title\">Actualizar aplicaci\u00F3n</p>\r\n\r\n <button class=\"refresh-guide__option\" (click)=\"actualizar()\">\r\n <i class=\"fas fa-rotate\"></i> Actualizar\r\n </button>\r\n\r\n <button class=\"refresh-guide__option refresh-guide__option--force\" (click)=\"actualizarTotal()\">\r\n <i class=\"fas fa-rotate-right\"></i> Forzar actualizaci\u00F3n\r\n </button>\r\n </div>\r\n }\r\n\r\n <button class=\"refresh-chip\" (click)=\"toggleGuide()\" title=\"Actualizar\">\r\n <i class=\"fas fa-rotate\"></i>\r\n </button>\r\n\r\n</div>\r\n", styles: [".refresh-wrap{position:fixed;bottom:24px;right:24px;z-index:9000;display:flex;flex-direction:column;align-items:flex-end;gap:10px}.refresh-chip{display:flex;align-items:center;justify-content:center;width:40px;height:40px;padding:0;border-radius:50%;border:1px solid rgba(255,255,255,.13);background:#0d6efd;backdrop-filter:blur(12px);color:#fff;font-size:15px;cursor:pointer;box-shadow:0 4px 18px #0006;transition:transform .15s ease,box-shadow .15s ease,background .15s ease;animation:refreshIn .3s cubic-bezier(.25,.46,.45,.94) both}.refresh-chip:hover{transform:translateY(-2px);background:#0b5ed7;box-shadow:0 6px 22px #0d6efd80}.refresh-chip:active{transform:translateY(0)}.refresh-guide{position:relative;width:240px;background:#08122af5;backdrop-filter:blur(16px);border:1px solid rgba(255,255,255,.1);border-radius:16px;padding:18px 18px 20px;box-shadow:0 8px 32px #00000080;animation:refreshIn .25s cubic-bezier(.25,.46,.45,.94) both}.refresh-guide__close{position:absolute;top:12px;right:12px;background:#ffffff14;border:none;border-radius:50%;width:26px;height:26px;display:flex;align-items:center;justify-content:center;color:#fff9;cursor:pointer;transition:background .15s;font-size:12px}.refresh-guide__close:hover{background:#ffffff26}.refresh-guide__title{font-size:13.5px;font-weight:600;color:#fff;margin:0 24px 14px 0}.refresh-guide__option{display:flex;align-items:center;justify-content:center;gap:7px;width:100%;margin-top:8px;padding:9px;border-radius:10px;border:none;background:#ffffff14;color:#fff;font-size:12.5px;font-weight:500;white-space:nowrap;cursor:pointer;transition:background .15s}.refresh-guide__option:hover{background:#ffffff26}.refresh-guide__option--force{background:#c50048d9}.refresh-guide__option--force:hover{background:#c50048}@keyframes refreshIn{0%{transform:translateY(12px);opacity:0}to{transform:translateY(0);opacity:1}}\n"] }]
108
135
  }] });
109
136
 
137
+ const INTERVALO_ESTADO_MS = 2000;
138
+ const MAXIMO_ESPERA_MS = 120000;
139
+ const CAMPOS_CODIGO = {
140
+ totp: {
141
+ label: 'Código de verificación', placeholder: '000000', icon: 'fa-mobile-alt', inputmode: 'numeric',
142
+ patron: /^\d{6}$/,
143
+ descri: 'Ingresa el código de 6 dígitos que muestra tu app de autenticación.',
144
+ mensajeInvalido: 'Ingresa el código de 6 dígitos de tu app.',
145
+ mensajeIncorrecto: 'Código incorrecto. Verifica la hora de tu dispositivo.'
146
+ },
147
+ respaldo: {
148
+ label: 'Código de respaldo', placeholder: 'XXXX-XXXX', icon: 'fa-key', inputmode: 'text',
149
+ patron: /^[A-Z0-9]{4}-[A-Z0-9]{4}$/,
150
+ descri: 'Ingresa uno de tus códigos de respaldo. Cada código sirve una sola vez.',
151
+ mensajeInvalido: 'Ingresa un código de respaldo válido (XXXX-XXXX).',
152
+ mensajeIncorrecto: 'Código de respaldo incorrecto o ya utilizado.'
153
+ }
154
+ };
155
+ const limpiarCodigo = (valor, tipo) => {
156
+ if (tipo == 'totp')
157
+ return valor.replace(/\D/g, '').slice(0, 6);
158
+ const base = valor.toUpperCase().replace(/[^A-Z0-9]/g, '').slice(0, 8);
159
+ return base.length > 4 ? `${base.slice(0, 4)}-${base.slice(4)}` : base;
160
+ };
161
+ const esperar = (ms, signal) => new Promise(resolve => {
162
+ const id = setTimeout(resolve, ms);
163
+ signal.addEventListener('abort', () => { clearTimeout(id); resolve(); }, { once: true });
164
+ });
165
+ class MdVerificarMfaComponent {
166
+ api = inject(AUTH_API);
167
+ challenge = input.required();
168
+ titulo = input('Verificación en dos pasos');
169
+ showCancelar = input(true);
170
+ verificado = output();
171
+ cancelado = output();
172
+ tienePush = computed(() => (this.challenge().tipos ?? []).includes('PUSH'));
173
+ tieneTotp = computed(() => {
174
+ const tipos = this.challenge().tipos ?? [];
175
+ return tipos.length == 0 || tipos.includes('TOTP');
176
+ });
177
+ modo = signal('codigo');
178
+ tipoCodigo = signal('totp');
179
+ campo = computed(() => CAMPOS_CODIGO[this.tipoCodigo()]);
180
+ codigo = signal('');
181
+ codigoError = signal('');
182
+ isEnviando = signal(false);
183
+ estadoPush = signal('idle');
184
+ isPushEnCurso = computed(() => this.estadoPush() == 'enviando' || this.estadoPush() == 'esperando');
185
+ pushError = signal('');
186
+ numberMatching = signal(null);
187
+ inputCodigo = viewChild('inputCodigo');
188
+ pushCtrl;
189
+ constructor() {
190
+ inject(DestroyRef).onDestroy(() => this.cancelarPush());
191
+ effect(() => {
192
+ this.challenge();
193
+ untracked(() => this.iniciar());
194
+ });
195
+ afterRenderEffect(() => {
196
+ if (this.modo() != 'codigo' || this.isEnviando())
197
+ return;
198
+ this.tipoCodigo();
199
+ this.codigoError();
200
+ this.inputCodigo()?.nativeElement.focus();
201
+ });
202
+ }
203
+ iniciar() {
204
+ this.cancelarPush();
205
+ this.pushError.set('');
206
+ if (this.tienePush() && !this.tieneTotp()) {
207
+ this.usarPush();
208
+ return;
209
+ }
210
+ this.usarCodigo('totp');
211
+ }
212
+ onCodigoInput(event) {
213
+ const input = event.target;
214
+ const limpio = limpiarCodigo(input.value, this.tipoCodigo());
215
+ input.value = limpio;
216
+ this.codigo.set(limpio);
217
+ if (this.codigoError())
218
+ this.codigoError.set('');
219
+ }
220
+ usarCodigo(tipo) {
221
+ this.cancelarPush();
222
+ this.modo.set('codigo');
223
+ this.tipoCodigo.set(tipo);
224
+ this.codigo.set('');
225
+ this.codigoError.set('');
226
+ }
227
+ async verificar() {
228
+ if (this.modo() == 'push' || this.isEnviando())
229
+ return;
230
+ const campo = this.campo();
231
+ if (!campo.patron.test(this.codigo())) {
232
+ this.codigoError.set(campo.mensajeInvalido);
233
+ return;
234
+ }
235
+ this.isEnviando.set(true);
236
+ this.codigoError.set('');
237
+ try {
238
+ await this.api.verificarCodigo({ preauthToken: this.challenge().preauthToken, codigo: this.codigo() });
239
+ this.verificado.emit();
240
+ }
241
+ catch (err) {
242
+ this.codigo.set('');
243
+ this.codigoError.set(mensajeDe(err, campo.mensajeIncorrecto));
244
+ }
245
+ finally {
246
+ this.isEnviando.set(false);
247
+ }
248
+ }
249
+ usarPush() {
250
+ this.modo.set('push');
251
+ this.codigoError.set('');
252
+ this.enviarPush();
253
+ }
254
+ async enviarPush() {
255
+ this.cancelarPush();
256
+ const ctrl = new AbortController();
257
+ this.pushCtrl = ctrl;
258
+ this.pushError.set('');
259
+ this.estadoPush.set('enviando');
260
+ this.numberMatching.set(null);
261
+ const preauthToken = this.challenge().preauthToken;
262
+ try {
263
+ const { solicitudId, numberMatching } = await this.api.enviarPush(preauthToken);
264
+ if (ctrl.signal.aborted)
265
+ return;
266
+ this.numberMatching.set(numberMatching ?? null);
267
+ this.estadoPush.set('esperando');
268
+ const limite = Date.now() + MAXIMO_ESPERA_MS;
269
+ while (Date.now() < limite) {
270
+ const estado = await this.api.estadoPush({ preauthToken, solicitudId });
271
+ if (ctrl.signal.aborted)
272
+ return;
273
+ if (estado != 'waiting') {
274
+ this.resolverPush(estado);
275
+ return;
276
+ }
277
+ await esperar(INTERVALO_ESTADO_MS, ctrl.signal);
278
+ if (ctrl.signal.aborted)
279
+ return;
280
+ }
281
+ this.numberMatching.set(null);
282
+ this.estadoPush.set('expirado');
283
+ this.pushError.set('No respondiste a tiempo la notificación. Vuelve a enviarla.');
284
+ }
285
+ catch (err) {
286
+ if (ctrl.signal.aborted)
287
+ return;
288
+ this.estadoPush.set('idle');
289
+ this.pushError.set(mensajeDe(err, 'No se pudo enviar la notificación.'));
290
+ }
291
+ }
292
+ cancelar() {
293
+ this.cancelarPush();
294
+ this.cancelado.emit();
295
+ }
296
+ resolverPush(estado) {
297
+ this.numberMatching.set(null);
298
+ if (estado == 'aprobado') {
299
+ this.estadoPush.set('idle');
300
+ this.verificado.emit();
301
+ return;
302
+ }
303
+ if (estado == 'expired') {
304
+ this.estadoPush.set('expirado');
305
+ this.pushError.set('La solicitud expiró. Vuelve a enviarla.');
306
+ return;
307
+ }
308
+ this.estadoPush.set('rechazado');
309
+ this.pushError.set('Rechazaste la notificación en tu teléfono.');
310
+ }
311
+ cancelarPush() {
312
+ this.pushCtrl?.abort();
313
+ this.pushCtrl = undefined;
314
+ this.numberMatching.set(null);
315
+ if (this.isPushEnCurso())
316
+ this.estadoPush.set('idle');
317
+ }
318
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: MdVerificarMfaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
319
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: MdVerificarMfaComponent, isStandalone: true, selector: "lib-md-verificar-mfa", inputs: { challenge: { classPropertyName: "challenge", publicName: "challenge", isSignal: true, isRequired: true, transformFunction: null }, titulo: { classPropertyName: "titulo", publicName: "titulo", isSignal: true, isRequired: false, transformFunction: null }, showCancelar: { classPropertyName: "showCancelar", publicName: "showCancelar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { verificado: "verificado", cancelado: "cancelado" }, viewQueries: [{ propertyName: "inputCodigo", first: true, predicate: ["inputCodigo"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"verificar-mfa\">\n <div class=\"auth-card-title mb-3\">{{ titulo() }}</div>\n\n <div class=\"d-flex align-items-center gap-3 mb-3\">\n <span class=\"verificar-mfa__icono\"><i class=\"fas fa-user-shield\"></i></span>\n <div>\n <div class=\"fw-semibold\">{{ challenge().coduser }}</div>\n @if (challenge().empresa) {\n <div class=\"verificar-mfa__muted\">{{ challenge().empresa }}</div>\n }\n </div>\n </div>\n\n @if (modo() == 'push') {\n @switch (estadoPush()) {\n @case ('enviando') {\n <div class=\"duo-push\">\n <span class=\"spinner-border spinner-border-sm text-primary\"></span>\n <div class=\"flex-grow-1\">Enviando notificaci\u00F3n a tu tel\u00E9fono\u2026</div>\n </div>\n }\n @case ('esperando') {\n <div class=\"duo-push duo-push--esperando\">\n <span class=\"duo-push__icono duo-push__icono--pulso\"><i class=\"fas fa-mobile-alt\"></i></span>\n <div class=\"flex-grow-1\">\n <div class=\"fw-semibold\">Revisa tu tel\u00E9fono</div>\n <div class=\"verificar-mfa__muted\">Aprueba la notificaci\u00F3n en TSI Autenticador para ingresar.</div>\n </div>\n </div>\n @if (numberMatching() != null) {\n <div class=\"number-matching\" role=\"status\" aria-live=\"polite\">\n <div class=\"verificar-mfa__muted\">Confirma que tu tel\u00E9fono muestre este n\u00FAmero</div>\n <div class=\"number-matching__valor\">{{ numberMatching() }}</div>\n </div>\n }\n }\n @default {\n <div class=\"duo-push\">\n <span class=\"duo-push__icono\"><i class=\"fas fa-bell\"></i></span>\n <div class=\"flex-grow-1\">\n <div class=\"fw-semibold\">TSI Autenticador</div>\n <div class=\"verificar-mfa__muted\">Te enviaremos una notificaci\u00F3n para que la apruebes.</div>\n </div>\n </div>\n }\n }\n @if (pushError() && !isPushEnCurso()) {\n <div class=\"codigo-field__error\"><i class=\"fas fa-exclamation-circle\"></i> {{ pushError() }}</div>\n }\n\n <div class=\"verificar-mfa__opciones\">\n @if (tieneTotp()) {\n <button type=\"button\" class=\"verificar-mfa__link\" (click)=\"usarCodigo('totp')\">\n Usar c\u00F3digo de mi app de autenticaci\u00F3n\n </button>\n }\n <button type=\"button\" class=\"verificar-mfa__link verificar-mfa__link--secundario\"\n (click)=\"usarCodigo('respaldo')\">\n \u00BFNo tienes tu tel\u00E9fono? Usa un c\u00F3digo de respaldo\n </button>\n </div>\n } @else {\n <p class=\"verificar-mfa__muted mb-4\">\n @if (tipoCodigo() == 'totp') {\n {{ challenge().mensaje || campo().descri }}\n } @else {\n {{ campo().descri }}\n }\n </p>\n\n <div class=\"codigo-field\" [class.has-error]=\"codigoError()\">\n <span class=\"codigo-field__icon\"><i class=\"fas\" [class]=\"campo().icon\"></i></span>\n <input #inputCodigo id=\"mfa-codigo\" class=\"codigo-field__input\" type=\"text\"\n [placeholder]=\"campo().placeholder\" [value]=\"codigo()\" (input)=\"onCodigoInput($event)\"\n (keydown.enter)=\"verificar()\" [attr.inputmode]=\"campo().inputmode\" autocomplete=\"one-time-code\"\n autocorrect=\"off\" autocapitalize=\"characters\" spellcheck=\"false\" [disabled]=\"isEnviando()\">\n <label for=\"mfa-codigo\" class=\"codigo-field__label\">{{ campo().label }}</label>\n </div>\n @if (codigoError()) {\n <div class=\"codigo-field__error\"><i class=\"fas fa-exclamation-circle\"></i> {{ codigoError() }}</div>\n }\n\n <div class=\"verificar-mfa__opciones\">\n @if (tienePush()) {\n <button type=\"button\" class=\"verificar-mfa__link\" (click)=\"usarPush()\">\n <i class=\"fas fa-bell me-1\"></i>Mejor env\u00EDame una notificaci\u00F3n push\n </button>\n }\n @if (tieneTotp() && tipoCodigo() != 'totp') {\n <button type=\"button\" class=\"verificar-mfa__link\" (click)=\"usarCodigo('totp')\">\n Usar c\u00F3digo de mi app de autenticaci\u00F3n\n </button>\n }\n @if (tipoCodigo() != 'respaldo') {\n <button type=\"button\" class=\"verificar-mfa__link verificar-mfa__link--secundario\"\n (click)=\"usarCodigo('respaldo')\">\n \u00BFNo tienes tu tel\u00E9fono? Usa un c\u00F3digo de respaldo\n </button>\n }\n </div>\n }\n\n <div class=\"verificar-mfa__acciones\">\n @if (modo() == 'push') {\n <button type=\"button\" class=\"auth-btn\" [disabled]=\"isPushEnCurso()\" (click)=\"enviarPush()\">\n <i class=\"fas fa-paper-plane me-1\"></i>\n {{ isPushEnCurso() ? 'Esperando aprobaci\u00F3n\u2026' : 'Reenviar notificaci\u00F3n' }}\n </button>\n } @else {\n <button type=\"button\" class=\"auth-btn\" [disabled]=\"isEnviando()\" (click)=\"verificar()\">\n <i class=\"fas fa-check me-1\"></i>\n {{ isEnviando() ? 'Verificando\u2026' : 'Verificar' }}\n </button>\n }\n @if (showCancelar()) {\n <button type=\"button\" class=\"auth-btn auth-btn--outline\" (click)=\"cancelar()\">Cancelar</button>\n }\n </div>\n</div>\n", styles: [".verificar-mfa{color:var(--text-color)}.verificar-mfa__icono{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:44px;height:44px;border-radius:12px;color:var(--bs-primary);background:rgba(var(--bs-primary-rgb),.1);font-size:20px}.verificar-mfa__muted{font-size:13px;line-height:1.5;color:var(--bs-secondary-color)}.verificar-mfa__link:hover{text-decoration:underline}.verificar-mfa__link{padding:0;border:0;background:none;font-size:13px;font-weight:600;color:var(--bs-primary)}.codigo-field{position:relative}.codigo-field__icon{position:absolute;left:14px;top:50%;transform:translateY(-50%);z-index:2;font-size:15px;color:var(--placeholder-color);pointer-events:none;transition:color .2s}.codigo-field__input{width:100%;height:56px;padding:0 44px;border:1.5px solid var(--font-border-input);border-radius:10px;outline:none;background:var(--background-input);color:var(--color-input);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:22px;font-weight:600;letter-spacing:.45em;text-align:center;transition:border-color .2s,box-shadow .2s,background .2s}.codigo-field__input::placeholder{color:var(--placeholder-color);opacity:.45}.codigo-field__input:focus{border-color:var(--bs-primary);box-shadow:0 0 0 3.5px rgba(var(--bs-primary-rgb),.15);background:var(--background-focus-input)}.codigo-field__input:disabled{opacity:.7}.codigo-field__label{position:absolute;left:12px;top:0;transform:translateY(-50%);z-index:1;margin:0!important;padding:0 4px;font-size:11px!important;font-weight:500!important;line-height:1.2;color:var(--placeholder-color);background:var(--background-card);pointer-events:none;transition:color .15s ease}.codigo-field:focus-within .codigo-field__label,.codigo-field:focus-within .codigo-field__icon{color:var(--bs-primary)}.codigo-field.has-error .codigo-field__input{border-color:var(--bs-danger);box-shadow:0 0 0 3.5px rgba(var(--bs-danger-rgb),.12)}.codigo-field.has-error .codigo-field__icon,.codigo-field.has-error .codigo-field__label{color:var(--bs-danger)}.codigo-field__error{display:flex;align-items:center;gap:6px;margin-top:8px;font-size:13px;font-weight:500;color:var(--bs-danger)}.duo-push{display:flex;align-items:center;gap:12px;padding:14px;border:1.5px solid var(--font-border-input);border-radius:10px;background:var(--background-input);color:var(--text-color);font-size:14px}.duo-push--esperando{border-color:rgba(var(--bs-primary-rgb),.45);background:rgba(var(--bs-primary-rgb),.06)}.duo-push__icono{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;color:var(--bs-primary);background:rgba(var(--bs-primary-rgb),.1);font-size:18px}.duo-push__icono--pulso{animation:duo-pulso 1.4s ease-in-out infinite}.number-matching{margin-top:12px;padding:16px;border:1.5px dashed rgba(var(--bs-primary-rgb),.45);border-radius:10px;text-align:center}.number-matching__valor{margin-top:4px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:40px;font-weight:700;line-height:1.1;letter-spacing:.12em;color:var(--bs-primary)}@keyframes duo-pulso{0%,to{box-shadow:0 0 rgba(var(--bs-primary-rgb),.35)}50%{box-shadow:0 0 0 8px rgba(var(--bs-primary-rgb),0)}}@media(prefers-reduced-motion:reduce){.duo-push__icono--pulso{animation:none}}.verificar-mfa__opciones{display:flex;flex-direction:column;align-items:flex-start;gap:8px;margin-top:16px}.verificar-mfa__link--secundario{font-weight:500;color:var(--bs-secondary-color)}.verificar-mfa__acciones{margin-top:24px}\n", "@charset \"UTF-8\";.red_contrasena,.blue_contrasena{position:relative;display:inline-block;font-size:13px;text-decoration:none;padding-bottom:2px;transition:color .3s ease;cursor:pointer}.red_contrasena:after,.blue_contrasena:after{content:\"\";position:absolute;bottom:0;left:50%;width:0;height:1px;background-color:currentColor;transition:all .3s ease;transform:translate(-50%)}.red_contrasena:hover:after,.blue_contrasena:hover:after{width:60%}.red_contrasena{color:#d1326f}.red_contrasena:hover{color:#a82859}.blue_contrasena{color:#398bf7}.blue_contrasena:hover{color:#1e5fc4}.auth-wrapper-login{position:fixed;inset:0;display:grid;grid-template-columns:1.15fr .85fr;overflow:hidden;background:#060d1f}.auth-panel-left{position:relative;overflow:hidden;background:linear-gradient(145deg,#040a18,#0b1a3d 55%,#040e22);display:flex;align-items:center;justify-content:center;padding:48px 40px}.auth-panel-left:before{content:\"\";position:absolute;inset:0;background-image:radial-gradient(circle,rgba(255,255,255,.055) 1px,transparent 1px);background-size:26px 26px;z-index:1;pointer-events:none}.auth-panel-left:after{content:\"\";position:absolute;top:0;left:-120%;width:60%;height:100%;background:linear-gradient(90deg,transparent,rgba(57,139,247,.04),transparent);animation:panelSweep 7s ease-in-out infinite;z-index:1;pointer-events:none}.auth-blob{position:absolute;border-radius:50%;filter:blur(72px);z-index:0;pointer-events:none}.auth-blob-1{width:340px;height:340px;background:radial-gradient(circle,rgba(57,139,247,.45) 0%,transparent 70%);top:-90px;right:-70px;animation:blobDrift 11s ease-in-out infinite}.auth-blob-2{width:240px;height:240px;background:radial-gradient(circle,rgba(124,58,237,.4) 0%,transparent 70%);bottom:60px;left:-50px;animation:blobDrift 14s ease-in-out infinite reverse}.auth-blob-3{width:180px;height:180px;background:radial-gradient(circle,rgba(14,165,233,.35) 0%,transparent 70%);bottom:-50px;right:40px;animation:blobDrift 9s ease-in-out infinite;animation-delay:-4s}.auth-blob-4{width:120px;height:120px;background:radial-gradient(circle,rgba(209,50,111,.25) 0%,transparent 70%);top:50%;left:50%;transform:translate(-50%,-50%);animation:blobDrift 16s ease-in-out infinite;animation-delay:-8s}@keyframes blobDrift{0%,to{transform:translate(0) scale(1)}33%{transform:translate(14px,-20px) scale(1.05)}66%{transform:translate(-10px,12px) scale(.96)}}@keyframes panelSweep{0%{left:-120%}50%{left:160%}to{left:160%}}.auth-brand-panel{position:relative;z-index:2;text-align:center;color:#fff;max-width:340px}.auth-brand-logo{width:100px;height:100px;border-radius:50%;background:#ffffff0d;border:1px solid rgba(255,255,255,.1);display:flex;align-items:center;justify-content:center;margin:0 auto 28px;box-shadow:0 0 0 14px #398bf70f,0 0 50px #398bf733;backdrop-filter:blur(8px)}.auth-brand-logo img{width:64px;height:64px;object-fit:contain;filter:brightness(1.05) drop-shadow(0 0 8px rgba(57,139,247,.4))}.auth-brand-title{font-size:30px;font-weight:700;letter-spacing:-.5px;margin-bottom:10px;background:linear-gradient(135deg,#fff 20%,#93c5fd 80%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.auth-brand-subtitle{font-size:14px;color:#ffffff73;line-height:1.65;margin-bottom:40px;letter-spacing:.2px}.auth-brand-features{display:flex;flex-direction:column;gap:14px;text-align:left}.auth-brand-feature{display:flex;align-items:center;gap:12px;font-size:13px;color:#fff9}.auth-brand-feature .feat-dot{flex-shrink:0;width:7px;height:7px;border-radius:50%;background:#398bf7;box-shadow:0 0 10px #398bf7b3}.auth-brand-divider{width:60px;height:2px;background:linear-gradient(90deg,transparent,#398bf7,transparent);margin:28px auto 32px;border-radius:2px}.auth-panel-left--dev{background:linear-gradient(145deg,#18040b,#3d0b1d 55%,#220409)}.auth-panel-left--dev:after{background:linear-gradient(90deg,transparent,rgba(209,50,111,.05),transparent)}.auth-panel-left--dev .auth-blob-1{background:radial-gradient(circle,rgba(220,38,38,.52) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-2{background:radial-gradient(circle,rgba(219,39,119,.44) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-3{background:radial-gradient(circle,rgba(239,68,68,.38) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-4{background:radial-gradient(circle,rgba(249,115,22,.28) 0%,transparent 70%)}.auth-panel-left--dev .auth-brand-logo{box-shadow:0 0 0 14px #d1326f12,0 0 50px #d1326f38}.auth-panel-left--dev .auth-brand-logo img{filter:brightness(1.05) drop-shadow(0 0 8px rgba(209,50,111,.45))}.auth-panel-left--dev .auth-brand-title{background:linear-gradient(135deg,#fff 20%,#fca5a5 80%);-webkit-background-clip:text;background-clip:text}.auth-panel-left--dev .auth-brand-divider{background:linear-gradient(90deg,transparent,rgb(209,50,111),transparent)}.auth-panel-left--dev .feat-dot{background:#d1326f;box-shadow:0 0 10px #d1326fb8}.auth-panel-right{position:relative;overflow:hidden;background:var(--background-login)}.auth-panel-right:before{content:\"\";position:absolute;inset:0;background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(57,139,247,.045) 22px,rgba(57,139,247,.045) 23px);animation:authLinesMove 10s linear infinite;pointer-events:none;z-index:0}.auth-panel-right:after{content:\"\";position:absolute;top:0;bottom:0;left:-25%;width:25%;background:linear-gradient(90deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLine 7s ease-in-out infinite;animation-delay:3.5s;pointer-events:none;z-index:0}@keyframes authLinesMove{0%{transform:translate(0)}to{transform:translate(46px,46px)}}@keyframes authScanLine{0%{left:-25%}50%{left:120%}to{left:120%}}.auth-panel-bg{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:hidden}.auth-deco{position:absolute;border-radius:50%;pointer-events:none;filter:blur(70px)}.auth-deco-tl{width:300px;height:300px;top:0;left:-120px;transform:translateY(-40%);background:radial-gradient(circle,rgba(57,139,247,.12) 0%,transparent 70%);animation:authOrbPulse 6s ease-in-out infinite}.auth-deco-br{width:340px;height:340px;bottom:0;right:-120px;transform:translateY(40%);background:radial-gradient(circle,rgba(124,58,237,.1) 0%,transparent 70%);animation:authOrbPulse 8s ease-in-out infinite;animation-delay:-4s}@keyframes authOrbPulse{0%,to{opacity:.7}50%{opacity:1}}.auth-form-wrapper{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;align-items:center;z-index:1}.auth-form-wrapper>div{width:100%;max-width:420px;margin:auto;padding:36px 16px;box-sizing:border-box}.auth-panel-right--dev:before{background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(209,50,111,.05) 22px,rgba(209,50,111,.05) 23px)}.auth-panel-right--dev:after{background:linear-gradient(90deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}.auth-panel-right--dev .auth-deco-tl{background:radial-gradient(circle,rgba(209,50,111,.12) 0%,transparent 70%)}.auth-panel-right--dev .auth-deco-br{background:radial-gradient(circle,rgba(239,68,68,.1) 0%,transparent 70%)}.auth-test-badge{display:inline-flex;align-items:center;gap:7px;background:#d1326f14;border:1px solid rgba(209,50,111,.25);color:#d1326f;font-size:10.5px;font-weight:700;padding:5px 12px;border-radius:20px;margin-bottom:18px;letter-spacing:.8px}.auth-test-badge .badge-dot{width:6px;height:6px;border-radius:50%;background:#d1326f;animation:badgePulse 1.6s ease-in-out infinite;flex-shrink:0}@keyframes badgePulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.75)}}.auth-card{background:var(--background-card);border-radius:20px;padding:36px 32px 28px;box-shadow:0 4px 28px #00000014;border:1px solid var(--border-color-modal)}.auth-card-title{font-size:22px;font-weight:700;color:var(--text-color);margin-bottom:4px;letter-spacing:-.3px}.auth-card-subtitle{font-size:13px;color:var(--placeholder-color);margin-bottom:26px}.auth-field{position:relative;margin-bottom:1rem}.auth-field .auth-field-icon{position:absolute;left:13px;top:50%;transform:translateY(-50%);color:var(--placeholder-color);font-size:13px;z-index:2;pointer-events:none;transition:color .2s}.auth-field .auth-input{width:100%;padding:15px 40px 15px 37px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s,background .2s}.auth-field .auth-input::placeholder{color:transparent}.auth-field .auth-input:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721;background:var(--background-focus-input)}.auth-field .auth-input:focus~.auth-label{top:0;font-size:11px!important;color:#398bf7!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-input:focus~.auth-field-icon{color:#398bf7}.auth-field .auth-input:not(:placeholder-shown)~.auth-label{top:0;font-size:11px!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-label{position:absolute;left:35px;top:50%;transform:translateY(-50%);color:var(--placeholder-color)!important;font-size:13px!important;font-weight:400!important;pointer-events:none;transition:top .15s ease,font-size .15s ease,color .15s ease,padding .15s ease,background .15s ease;background:transparent;z-index:1;text-align:left!important}.auth-field .auth-toggle-pw{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;color:var(--placeholder-color);cursor:pointer;padding:4px 6px;font-size:13px;z-index:2;line-height:1;transition:color .2s}.auth-field .auth-toggle-pw:hover{color:#398bf7}.auth-field.has-error .auth-input{border-color:#dc3545;box-shadow:none}.auth-field.has-error .auth-field-icon{color:#dc3545}.auth-select{width:100%;padding:13px 14px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s;margin-bottom:1rem;cursor:pointer}.auth-select:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721}.auth-btn{width:100%;padding:13px;border:none;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:transform .15s ease,box-shadow .2s ease,opacity .2s;background:linear-gradient(135deg,#398bf7,#1e5fc4);color:#fff;letter-spacing:.3px;margin-bottom:10px;display:block}.auth-btn:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 5px 18px #398bf761}.auth-btn:active:not(:disabled){transform:translateY(0)}.auth-btn:disabled{opacity:.55;cursor:not-allowed}.auth-btn.auth-btn--red{background:linear-gradient(135deg,#d1326f,#a82859)}.auth-btn.auth-btn--red:hover:not(:disabled){box-shadow:0 5px 18px #d1326f61}.auth-btn.auth-btn--outline{background:transparent;border:1.5px solid var(--font-border-input);color:var(--text-color)}.auth-btn.auth-btn--outline:hover:not(:disabled){background:var(--background-btn-light-hover);box-shadow:none;transform:none}.auth-links{display:flex;flex-direction:column;align-items:center;gap:10px;margin-top:16px;padding-top:16px;border-top:1px solid var(--border-color-modal)}.auth-version{text-align:right;margin-top:14px;padding-top:12px;border-top:1px solid var(--border-color-modal)}.auth-version span{font-size:11px;color:var(--placeholder-color)}.auth-error{font-size:11.5px;color:#dc3545;margin:-6px 0 10px 2px;padding:0}.auth-hint{display:flex;align-items:flex-start;gap:6px;font-size:11.5px;color:var(--placeholder-color);margin:-6px 0 14px 2px;padding:0;line-height:1.35}.auth-hint i{margin-top:2px;flex-shrink:0}.auth-validation-list{margin:-4px 0 12px;padding:0;list-style:none}.auth-validation-list li{font-size:11.5px;color:#dc3545;padding:2px 0}.auth-validation-list li:before{content:\"\\2715 \";font-size:10px}.auth-desc{font-size:13px;color:var(--placeholder-color);margin-bottom:20px;line-height:1.65}.auth-section-title{font-size:15px;font-weight:600;color:var(--text-color);margin-bottom:20px}.font-12{font-size:12px}.form-control:focus{border-color:#0199ff9a!important;box-shadow:0 0 5px .2px #65befa44!important}@media(max-width:900px){.auth-wrapper-login{grid-template-columns:1fr;grid-template-rows:auto 1fr;overflow-y:auto;overflow-x:hidden}.auth-panel-left{padding:14px 24px;justify-content:center}.auth-panel-left .auth-brand-subtitle,.auth-panel-left .auth-brand-features,.auth-panel-left .auth-brand-divider{display:none!important}.auth-panel-left .auth-brand-panel{display:flex!important;flex-direction:row!important;align-items:center;gap:0;text-align:left;max-width:none;width:100%;justify-content:center}.auth-panel-left .auth-brand-logo{width:52px;height:52px;margin:0;flex-shrink:0}.auth-panel-left .auth-brand-logo img{width:34px;height:34px}.auth-panel-left .auth-brand-title{font-size:20px;margin-bottom:0;margin-left:.5rem;flex-shrink:1}.auth-panel-right:after{inset:-25% 0 auto;width:100%;height:25%;background:linear-gradient(180deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLineV 7s ease-in-out infinite;animation-delay:3.5s}.auth-panel-right--dev:after{background:linear-gradient(180deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}}@keyframes authScanLineV{0%{top:-25%}50%{top:120%}to{top:120%}}@media(max-width:480px){.auth-panel-left{padding:12px 16px}.auth-panel-left .auth-brand-logo{width:44px;height:44px}.auth-panel-left .auth-brand-logo img{width:28px;height:28px}.auth-panel-left .auth-brand-title{font-size:17px}.auth-form-wrapper>div{padding:20px 12px}.auth-card{padding:24px 18px 20px;border-radius:16px}.font-12{font-size:10px!important}}\n"] });
320
+ }
321
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: MdVerificarMfaComponent, decorators: [{
322
+ type: Component,
323
+ args: [{ selector: 'lib-md-verificar-mfa', template: "<div class=\"verificar-mfa\">\n <div class=\"auth-card-title mb-3\">{{ titulo() }}</div>\n\n <div class=\"d-flex align-items-center gap-3 mb-3\">\n <span class=\"verificar-mfa__icono\"><i class=\"fas fa-user-shield\"></i></span>\n <div>\n <div class=\"fw-semibold\">{{ challenge().coduser }}</div>\n @if (challenge().empresa) {\n <div class=\"verificar-mfa__muted\">{{ challenge().empresa }}</div>\n }\n </div>\n </div>\n\n @if (modo() == 'push') {\n @switch (estadoPush()) {\n @case ('enviando') {\n <div class=\"duo-push\">\n <span class=\"spinner-border spinner-border-sm text-primary\"></span>\n <div class=\"flex-grow-1\">Enviando notificaci\u00F3n a tu tel\u00E9fono\u2026</div>\n </div>\n }\n @case ('esperando') {\n <div class=\"duo-push duo-push--esperando\">\n <span class=\"duo-push__icono duo-push__icono--pulso\"><i class=\"fas fa-mobile-alt\"></i></span>\n <div class=\"flex-grow-1\">\n <div class=\"fw-semibold\">Revisa tu tel\u00E9fono</div>\n <div class=\"verificar-mfa__muted\">Aprueba la notificaci\u00F3n en TSI Autenticador para ingresar.</div>\n </div>\n </div>\n @if (numberMatching() != null) {\n <div class=\"number-matching\" role=\"status\" aria-live=\"polite\">\n <div class=\"verificar-mfa__muted\">Confirma que tu tel\u00E9fono muestre este n\u00FAmero</div>\n <div class=\"number-matching__valor\">{{ numberMatching() }}</div>\n </div>\n }\n }\n @default {\n <div class=\"duo-push\">\n <span class=\"duo-push__icono\"><i class=\"fas fa-bell\"></i></span>\n <div class=\"flex-grow-1\">\n <div class=\"fw-semibold\">TSI Autenticador</div>\n <div class=\"verificar-mfa__muted\">Te enviaremos una notificaci\u00F3n para que la apruebes.</div>\n </div>\n </div>\n }\n }\n @if (pushError() && !isPushEnCurso()) {\n <div class=\"codigo-field__error\"><i class=\"fas fa-exclamation-circle\"></i> {{ pushError() }}</div>\n }\n\n <div class=\"verificar-mfa__opciones\">\n @if (tieneTotp()) {\n <button type=\"button\" class=\"verificar-mfa__link\" (click)=\"usarCodigo('totp')\">\n Usar c\u00F3digo de mi app de autenticaci\u00F3n\n </button>\n }\n <button type=\"button\" class=\"verificar-mfa__link verificar-mfa__link--secundario\"\n (click)=\"usarCodigo('respaldo')\">\n \u00BFNo tienes tu tel\u00E9fono? Usa un c\u00F3digo de respaldo\n </button>\n </div>\n } @else {\n <p class=\"verificar-mfa__muted mb-4\">\n @if (tipoCodigo() == 'totp') {\n {{ challenge().mensaje || campo().descri }}\n } @else {\n {{ campo().descri }}\n }\n </p>\n\n <div class=\"codigo-field\" [class.has-error]=\"codigoError()\">\n <span class=\"codigo-field__icon\"><i class=\"fas\" [class]=\"campo().icon\"></i></span>\n <input #inputCodigo id=\"mfa-codigo\" class=\"codigo-field__input\" type=\"text\"\n [placeholder]=\"campo().placeholder\" [value]=\"codigo()\" (input)=\"onCodigoInput($event)\"\n (keydown.enter)=\"verificar()\" [attr.inputmode]=\"campo().inputmode\" autocomplete=\"one-time-code\"\n autocorrect=\"off\" autocapitalize=\"characters\" spellcheck=\"false\" [disabled]=\"isEnviando()\">\n <label for=\"mfa-codigo\" class=\"codigo-field__label\">{{ campo().label }}</label>\n </div>\n @if (codigoError()) {\n <div class=\"codigo-field__error\"><i class=\"fas fa-exclamation-circle\"></i> {{ codigoError() }}</div>\n }\n\n <div class=\"verificar-mfa__opciones\">\n @if (tienePush()) {\n <button type=\"button\" class=\"verificar-mfa__link\" (click)=\"usarPush()\">\n <i class=\"fas fa-bell me-1\"></i>Mejor env\u00EDame una notificaci\u00F3n push\n </button>\n }\n @if (tieneTotp() && tipoCodigo() != 'totp') {\n <button type=\"button\" class=\"verificar-mfa__link\" (click)=\"usarCodigo('totp')\">\n Usar c\u00F3digo de mi app de autenticaci\u00F3n\n </button>\n }\n @if (tipoCodigo() != 'respaldo') {\n <button type=\"button\" class=\"verificar-mfa__link verificar-mfa__link--secundario\"\n (click)=\"usarCodigo('respaldo')\">\n \u00BFNo tienes tu tel\u00E9fono? Usa un c\u00F3digo de respaldo\n </button>\n }\n </div>\n }\n\n <div class=\"verificar-mfa__acciones\">\n @if (modo() == 'push') {\n <button type=\"button\" class=\"auth-btn\" [disabled]=\"isPushEnCurso()\" (click)=\"enviarPush()\">\n <i class=\"fas fa-paper-plane me-1\"></i>\n {{ isPushEnCurso() ? 'Esperando aprobaci\u00F3n\u2026' : 'Reenviar notificaci\u00F3n' }}\n </button>\n } @else {\n <button type=\"button\" class=\"auth-btn\" [disabled]=\"isEnviando()\" (click)=\"verificar()\">\n <i class=\"fas fa-check me-1\"></i>\n {{ isEnviando() ? 'Verificando\u2026' : 'Verificar' }}\n </button>\n }\n @if (showCancelar()) {\n <button type=\"button\" class=\"auth-btn auth-btn--outline\" (click)=\"cancelar()\">Cancelar</button>\n }\n </div>\n</div>\n", styles: [".verificar-mfa{color:var(--text-color)}.verificar-mfa__icono{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:44px;height:44px;border-radius:12px;color:var(--bs-primary);background:rgba(var(--bs-primary-rgb),.1);font-size:20px}.verificar-mfa__muted{font-size:13px;line-height:1.5;color:var(--bs-secondary-color)}.verificar-mfa__link:hover{text-decoration:underline}.verificar-mfa__link{padding:0;border:0;background:none;font-size:13px;font-weight:600;color:var(--bs-primary)}.codigo-field{position:relative}.codigo-field__icon{position:absolute;left:14px;top:50%;transform:translateY(-50%);z-index:2;font-size:15px;color:var(--placeholder-color);pointer-events:none;transition:color .2s}.codigo-field__input{width:100%;height:56px;padding:0 44px;border:1.5px solid var(--font-border-input);border-radius:10px;outline:none;background:var(--background-input);color:var(--color-input);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:22px;font-weight:600;letter-spacing:.45em;text-align:center;transition:border-color .2s,box-shadow .2s,background .2s}.codigo-field__input::placeholder{color:var(--placeholder-color);opacity:.45}.codigo-field__input:focus{border-color:var(--bs-primary);box-shadow:0 0 0 3.5px rgba(var(--bs-primary-rgb),.15);background:var(--background-focus-input)}.codigo-field__input:disabled{opacity:.7}.codigo-field__label{position:absolute;left:12px;top:0;transform:translateY(-50%);z-index:1;margin:0!important;padding:0 4px;font-size:11px!important;font-weight:500!important;line-height:1.2;color:var(--placeholder-color);background:var(--background-card);pointer-events:none;transition:color .15s ease}.codigo-field:focus-within .codigo-field__label,.codigo-field:focus-within .codigo-field__icon{color:var(--bs-primary)}.codigo-field.has-error .codigo-field__input{border-color:var(--bs-danger);box-shadow:0 0 0 3.5px rgba(var(--bs-danger-rgb),.12)}.codigo-field.has-error .codigo-field__icon,.codigo-field.has-error .codigo-field__label{color:var(--bs-danger)}.codigo-field__error{display:flex;align-items:center;gap:6px;margin-top:8px;font-size:13px;font-weight:500;color:var(--bs-danger)}.duo-push{display:flex;align-items:center;gap:12px;padding:14px;border:1.5px solid var(--font-border-input);border-radius:10px;background:var(--background-input);color:var(--text-color);font-size:14px}.duo-push--esperando{border-color:rgba(var(--bs-primary-rgb),.45);background:rgba(var(--bs-primary-rgb),.06)}.duo-push__icono{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;color:var(--bs-primary);background:rgba(var(--bs-primary-rgb),.1);font-size:18px}.duo-push__icono--pulso{animation:duo-pulso 1.4s ease-in-out infinite}.number-matching{margin-top:12px;padding:16px;border:1.5px dashed rgba(var(--bs-primary-rgb),.45);border-radius:10px;text-align:center}.number-matching__valor{margin-top:4px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:40px;font-weight:700;line-height:1.1;letter-spacing:.12em;color:var(--bs-primary)}@keyframes duo-pulso{0%,to{box-shadow:0 0 rgba(var(--bs-primary-rgb),.35)}50%{box-shadow:0 0 0 8px rgba(var(--bs-primary-rgb),0)}}@media(prefers-reduced-motion:reduce){.duo-push__icono--pulso{animation:none}}.verificar-mfa__opciones{display:flex;flex-direction:column;align-items:flex-start;gap:8px;margin-top:16px}.verificar-mfa__link--secundario{font-weight:500;color:var(--bs-secondary-color)}.verificar-mfa__acciones{margin-top:24px}\n", "@charset \"UTF-8\";.red_contrasena,.blue_contrasena{position:relative;display:inline-block;font-size:13px;text-decoration:none;padding-bottom:2px;transition:color .3s ease;cursor:pointer}.red_contrasena:after,.blue_contrasena:after{content:\"\";position:absolute;bottom:0;left:50%;width:0;height:1px;background-color:currentColor;transition:all .3s ease;transform:translate(-50%)}.red_contrasena:hover:after,.blue_contrasena:hover:after{width:60%}.red_contrasena{color:#d1326f}.red_contrasena:hover{color:#a82859}.blue_contrasena{color:#398bf7}.blue_contrasena:hover{color:#1e5fc4}.auth-wrapper-login{position:fixed;inset:0;display:grid;grid-template-columns:1.15fr .85fr;overflow:hidden;background:#060d1f}.auth-panel-left{position:relative;overflow:hidden;background:linear-gradient(145deg,#040a18,#0b1a3d 55%,#040e22);display:flex;align-items:center;justify-content:center;padding:48px 40px}.auth-panel-left:before{content:\"\";position:absolute;inset:0;background-image:radial-gradient(circle,rgba(255,255,255,.055) 1px,transparent 1px);background-size:26px 26px;z-index:1;pointer-events:none}.auth-panel-left:after{content:\"\";position:absolute;top:0;left:-120%;width:60%;height:100%;background:linear-gradient(90deg,transparent,rgba(57,139,247,.04),transparent);animation:panelSweep 7s ease-in-out infinite;z-index:1;pointer-events:none}.auth-blob{position:absolute;border-radius:50%;filter:blur(72px);z-index:0;pointer-events:none}.auth-blob-1{width:340px;height:340px;background:radial-gradient(circle,rgba(57,139,247,.45) 0%,transparent 70%);top:-90px;right:-70px;animation:blobDrift 11s ease-in-out infinite}.auth-blob-2{width:240px;height:240px;background:radial-gradient(circle,rgba(124,58,237,.4) 0%,transparent 70%);bottom:60px;left:-50px;animation:blobDrift 14s ease-in-out infinite reverse}.auth-blob-3{width:180px;height:180px;background:radial-gradient(circle,rgba(14,165,233,.35) 0%,transparent 70%);bottom:-50px;right:40px;animation:blobDrift 9s ease-in-out infinite;animation-delay:-4s}.auth-blob-4{width:120px;height:120px;background:radial-gradient(circle,rgba(209,50,111,.25) 0%,transparent 70%);top:50%;left:50%;transform:translate(-50%,-50%);animation:blobDrift 16s ease-in-out infinite;animation-delay:-8s}@keyframes blobDrift{0%,to{transform:translate(0) scale(1)}33%{transform:translate(14px,-20px) scale(1.05)}66%{transform:translate(-10px,12px) scale(.96)}}@keyframes panelSweep{0%{left:-120%}50%{left:160%}to{left:160%}}.auth-brand-panel{position:relative;z-index:2;text-align:center;color:#fff;max-width:340px}.auth-brand-logo{width:100px;height:100px;border-radius:50%;background:#ffffff0d;border:1px solid rgba(255,255,255,.1);display:flex;align-items:center;justify-content:center;margin:0 auto 28px;box-shadow:0 0 0 14px #398bf70f,0 0 50px #398bf733;backdrop-filter:blur(8px)}.auth-brand-logo img{width:64px;height:64px;object-fit:contain;filter:brightness(1.05) drop-shadow(0 0 8px rgba(57,139,247,.4))}.auth-brand-title{font-size:30px;font-weight:700;letter-spacing:-.5px;margin-bottom:10px;background:linear-gradient(135deg,#fff 20%,#93c5fd 80%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.auth-brand-subtitle{font-size:14px;color:#ffffff73;line-height:1.65;margin-bottom:40px;letter-spacing:.2px}.auth-brand-features{display:flex;flex-direction:column;gap:14px;text-align:left}.auth-brand-feature{display:flex;align-items:center;gap:12px;font-size:13px;color:#fff9}.auth-brand-feature .feat-dot{flex-shrink:0;width:7px;height:7px;border-radius:50%;background:#398bf7;box-shadow:0 0 10px #398bf7b3}.auth-brand-divider{width:60px;height:2px;background:linear-gradient(90deg,transparent,#398bf7,transparent);margin:28px auto 32px;border-radius:2px}.auth-panel-left--dev{background:linear-gradient(145deg,#18040b,#3d0b1d 55%,#220409)}.auth-panel-left--dev:after{background:linear-gradient(90deg,transparent,rgba(209,50,111,.05),transparent)}.auth-panel-left--dev .auth-blob-1{background:radial-gradient(circle,rgba(220,38,38,.52) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-2{background:radial-gradient(circle,rgba(219,39,119,.44) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-3{background:radial-gradient(circle,rgba(239,68,68,.38) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-4{background:radial-gradient(circle,rgba(249,115,22,.28) 0%,transparent 70%)}.auth-panel-left--dev .auth-brand-logo{box-shadow:0 0 0 14px #d1326f12,0 0 50px #d1326f38}.auth-panel-left--dev .auth-brand-logo img{filter:brightness(1.05) drop-shadow(0 0 8px rgba(209,50,111,.45))}.auth-panel-left--dev .auth-brand-title{background:linear-gradient(135deg,#fff 20%,#fca5a5 80%);-webkit-background-clip:text;background-clip:text}.auth-panel-left--dev .auth-brand-divider{background:linear-gradient(90deg,transparent,rgb(209,50,111),transparent)}.auth-panel-left--dev .feat-dot{background:#d1326f;box-shadow:0 0 10px #d1326fb8}.auth-panel-right{position:relative;overflow:hidden;background:var(--background-login)}.auth-panel-right:before{content:\"\";position:absolute;inset:0;background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(57,139,247,.045) 22px,rgba(57,139,247,.045) 23px);animation:authLinesMove 10s linear infinite;pointer-events:none;z-index:0}.auth-panel-right:after{content:\"\";position:absolute;top:0;bottom:0;left:-25%;width:25%;background:linear-gradient(90deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLine 7s ease-in-out infinite;animation-delay:3.5s;pointer-events:none;z-index:0}@keyframes authLinesMove{0%{transform:translate(0)}to{transform:translate(46px,46px)}}@keyframes authScanLine{0%{left:-25%}50%{left:120%}to{left:120%}}.auth-panel-bg{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:hidden}.auth-deco{position:absolute;border-radius:50%;pointer-events:none;filter:blur(70px)}.auth-deco-tl{width:300px;height:300px;top:0;left:-120px;transform:translateY(-40%);background:radial-gradient(circle,rgba(57,139,247,.12) 0%,transparent 70%);animation:authOrbPulse 6s ease-in-out infinite}.auth-deco-br{width:340px;height:340px;bottom:0;right:-120px;transform:translateY(40%);background:radial-gradient(circle,rgba(124,58,237,.1) 0%,transparent 70%);animation:authOrbPulse 8s ease-in-out infinite;animation-delay:-4s}@keyframes authOrbPulse{0%,to{opacity:.7}50%{opacity:1}}.auth-form-wrapper{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;align-items:center;z-index:1}.auth-form-wrapper>div{width:100%;max-width:420px;margin:auto;padding:36px 16px;box-sizing:border-box}.auth-panel-right--dev:before{background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(209,50,111,.05) 22px,rgba(209,50,111,.05) 23px)}.auth-panel-right--dev:after{background:linear-gradient(90deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}.auth-panel-right--dev .auth-deco-tl{background:radial-gradient(circle,rgba(209,50,111,.12) 0%,transparent 70%)}.auth-panel-right--dev .auth-deco-br{background:radial-gradient(circle,rgba(239,68,68,.1) 0%,transparent 70%)}.auth-test-badge{display:inline-flex;align-items:center;gap:7px;background:#d1326f14;border:1px solid rgba(209,50,111,.25);color:#d1326f;font-size:10.5px;font-weight:700;padding:5px 12px;border-radius:20px;margin-bottom:18px;letter-spacing:.8px}.auth-test-badge .badge-dot{width:6px;height:6px;border-radius:50%;background:#d1326f;animation:badgePulse 1.6s ease-in-out infinite;flex-shrink:0}@keyframes badgePulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.75)}}.auth-card{background:var(--background-card);border-radius:20px;padding:36px 32px 28px;box-shadow:0 4px 28px #00000014;border:1px solid var(--border-color-modal)}.auth-card-title{font-size:22px;font-weight:700;color:var(--text-color);margin-bottom:4px;letter-spacing:-.3px}.auth-card-subtitle{font-size:13px;color:var(--placeholder-color);margin-bottom:26px}.auth-field{position:relative;margin-bottom:1rem}.auth-field .auth-field-icon{position:absolute;left:13px;top:50%;transform:translateY(-50%);color:var(--placeholder-color);font-size:13px;z-index:2;pointer-events:none;transition:color .2s}.auth-field .auth-input{width:100%;padding:15px 40px 15px 37px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s,background .2s}.auth-field .auth-input::placeholder{color:transparent}.auth-field .auth-input:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721;background:var(--background-focus-input)}.auth-field .auth-input:focus~.auth-label{top:0;font-size:11px!important;color:#398bf7!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-input:focus~.auth-field-icon{color:#398bf7}.auth-field .auth-input:not(:placeholder-shown)~.auth-label{top:0;font-size:11px!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-label{position:absolute;left:35px;top:50%;transform:translateY(-50%);color:var(--placeholder-color)!important;font-size:13px!important;font-weight:400!important;pointer-events:none;transition:top .15s ease,font-size .15s ease,color .15s ease,padding .15s ease,background .15s ease;background:transparent;z-index:1;text-align:left!important}.auth-field .auth-toggle-pw{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;color:var(--placeholder-color);cursor:pointer;padding:4px 6px;font-size:13px;z-index:2;line-height:1;transition:color .2s}.auth-field .auth-toggle-pw:hover{color:#398bf7}.auth-field.has-error .auth-input{border-color:#dc3545;box-shadow:none}.auth-field.has-error .auth-field-icon{color:#dc3545}.auth-select{width:100%;padding:13px 14px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s;margin-bottom:1rem;cursor:pointer}.auth-select:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721}.auth-btn{width:100%;padding:13px;border:none;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:transform .15s ease,box-shadow .2s ease,opacity .2s;background:linear-gradient(135deg,#398bf7,#1e5fc4);color:#fff;letter-spacing:.3px;margin-bottom:10px;display:block}.auth-btn:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 5px 18px #398bf761}.auth-btn:active:not(:disabled){transform:translateY(0)}.auth-btn:disabled{opacity:.55;cursor:not-allowed}.auth-btn.auth-btn--red{background:linear-gradient(135deg,#d1326f,#a82859)}.auth-btn.auth-btn--red:hover:not(:disabled){box-shadow:0 5px 18px #d1326f61}.auth-btn.auth-btn--outline{background:transparent;border:1.5px solid var(--font-border-input);color:var(--text-color)}.auth-btn.auth-btn--outline:hover:not(:disabled){background:var(--background-btn-light-hover);box-shadow:none;transform:none}.auth-links{display:flex;flex-direction:column;align-items:center;gap:10px;margin-top:16px;padding-top:16px;border-top:1px solid var(--border-color-modal)}.auth-version{text-align:right;margin-top:14px;padding-top:12px;border-top:1px solid var(--border-color-modal)}.auth-version span{font-size:11px;color:var(--placeholder-color)}.auth-error{font-size:11.5px;color:#dc3545;margin:-6px 0 10px 2px;padding:0}.auth-hint{display:flex;align-items:flex-start;gap:6px;font-size:11.5px;color:var(--placeholder-color);margin:-6px 0 14px 2px;padding:0;line-height:1.35}.auth-hint i{margin-top:2px;flex-shrink:0}.auth-validation-list{margin:-4px 0 12px;padding:0;list-style:none}.auth-validation-list li{font-size:11.5px;color:#dc3545;padding:2px 0}.auth-validation-list li:before{content:\"\\2715 \";font-size:10px}.auth-desc{font-size:13px;color:var(--placeholder-color);margin-bottom:20px;line-height:1.65}.auth-section-title{font-size:15px;font-weight:600;color:var(--text-color);margin-bottom:20px}.font-12{font-size:12px}.form-control:focus{border-color:#0199ff9a!important;box-shadow:0 0 5px .2px #65befa44!important}@media(max-width:900px){.auth-wrapper-login{grid-template-columns:1fr;grid-template-rows:auto 1fr;overflow-y:auto;overflow-x:hidden}.auth-panel-left{padding:14px 24px;justify-content:center}.auth-panel-left .auth-brand-subtitle,.auth-panel-left .auth-brand-features,.auth-panel-left .auth-brand-divider{display:none!important}.auth-panel-left .auth-brand-panel{display:flex!important;flex-direction:row!important;align-items:center;gap:0;text-align:left;max-width:none;width:100%;justify-content:center}.auth-panel-left .auth-brand-logo{width:52px;height:52px;margin:0;flex-shrink:0}.auth-panel-left .auth-brand-logo img{width:34px;height:34px}.auth-panel-left .auth-brand-title{font-size:20px;margin-bottom:0;margin-left:.5rem;flex-shrink:1}.auth-panel-right:after{inset:-25% 0 auto;width:100%;height:25%;background:linear-gradient(180deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLineV 7s ease-in-out infinite;animation-delay:3.5s}.auth-panel-right--dev:after{background:linear-gradient(180deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}}@keyframes authScanLineV{0%{top:-25%}50%{top:120%}to{top:120%}}@media(max-width:480px){.auth-panel-left{padding:12px 16px}.auth-panel-left .auth-brand-logo{width:44px;height:44px}.auth-panel-left .auth-brand-logo img{width:28px;height:28px}.auth-panel-left .auth-brand-title{font-size:17px}.auth-form-wrapper>div{padding:20px 12px}.auth-card{padding:24px 18px 20px;border-radius:16px}.font-12{font-size:10px!important}}\n"] }]
324
+ }], ctorParameters: () => [] });
325
+
326
+ const MENSAJE_ERROR_LOGIN = 'No se pudo iniciar sesión.';
327
+ const CLASE_CERRANDO = 'auth-mfa-dialog--cerrando';
328
+ const MAXIMO_SALIDA_MS = 400;
110
329
  class AuthComponent {
330
+ api = inject(AUTH_API, { optional: true });
111
331
  production = input(true);
112
- module = input('ERP'); // DEFECTO ERP
113
- versionApp = input('1.0.0'); // DEFECTO 1.0.0
114
- product = input(); // DEFECTO NULL - ERP
332
+ module = input('ERP');
333
+ versionApp = input('1.0.0');
334
+ product = input();
115
335
  authForm = input.required();
116
336
  aboutList = input([
117
337
  'Gestión de compras y logística',
@@ -119,35 +339,96 @@ class AuthComponent {
119
339
  'Reportes y análisis en tiempo real',
120
340
  'Integración con inteligencia artificial'
121
341
  ]);
122
- /** Muestra el flotante de "instalar app" (app-pwa-floating). Por defecto siempre visible. */
123
342
  showFloatingApp = input(true);
124
- /** Muestra el flotante de "actualización disponible" (app-refresh-floating). Por defecto siempre visible. */
125
343
  showFloatingUpdate = input(true);
126
344
  loginEvent = output();
127
- /** Se dispara antes de instalar la PWA — el RUC/usuario ya están en authForm(), el consumidor decide qué guardar. */
128
345
  beforeInstall = output();
129
346
  showPassword = signal(false);
347
+ isIngresando = signal(false);
348
+ pasoMfa = signal(null);
349
+ dialogMfa = viewChild.required('dialogMfa');
130
350
  onBeforeInstall = () => this.beforeInstall.emit();
131
351
  recover = () => this.loginEvent.emit({ type: "RECOVER" });
132
352
  forget = () => this.loginEvent.emit({ type: "FORGET" });
133
353
  togglePassword = () => this.showPassword.set(!this.showPassword());
134
- login = () => {
135
- if (!this.validacionInit())
354
+ login = async () => {
355
+ if (this.isIngresando() || !this.validacionInit())
356
+ return;
357
+ const data = this.armarSender();
358
+ if (!this.api) {
359
+ this.loginEvent.emit({ type: "LOGIN", data });
136
360
  return;
361
+ }
362
+ this.isIngresando.set(true);
363
+ try {
364
+ const respuesta = await this.api.login(data);
365
+ if (isMfaChallenge(respuesta)) {
366
+ this.abrirMfa({ challenge: respuesta, data });
367
+ return;
368
+ }
369
+ this.loginEvent.emit({ type: "AUTENTICADO", data });
370
+ }
371
+ catch (err) {
372
+ this.returnError(mensajeDe(err, MENSAJE_ERROR_LOGIN));
373
+ }
374
+ finally {
375
+ this.isIngresando.set(false);
376
+ }
377
+ };
378
+ onMfaVerificado = async () => {
379
+ const paso = this.pasoMfa();
380
+ await this.cerrarMfa();
381
+ if (paso)
382
+ this.loginEvent.emit({ type: "AUTENTICADO", data: paso.data });
383
+ };
384
+ onMfaCancelado = async () => {
385
+ await this.cerrarMfa();
386
+ this.authForm().patchValue({ clave: '' });
387
+ };
388
+ abrirMfa(paso) {
389
+ const dialog = this.dialogMfa().nativeElement;
390
+ dialog.classList.remove(CLASE_CERRANDO);
391
+ this.pasoMfa.set(paso);
392
+ if (!dialog.open)
393
+ dialog.showModal();
394
+ }
395
+ cerrarMfa() {
396
+ const dialog = this.dialogMfa().nativeElement;
397
+ if (!dialog.open) {
398
+ this.pasoMfa.set(null);
399
+ return Promise.resolve();
400
+ }
401
+ return new Promise(resolve => {
402
+ let terminado = false;
403
+ const terminar = () => {
404
+ if (terminado)
405
+ return;
406
+ terminado = true;
407
+ clearTimeout(respaldo);
408
+ dialog.removeEventListener('animationend', alTerminarAnimacion);
409
+ dialog.close();
410
+ dialog.classList.remove(CLASE_CERRANDO);
411
+ this.pasoMfa.set(null);
412
+ resolve();
413
+ };
414
+ const alTerminarAnimacion = (event) => {
415
+ if (event.target == dialog)
416
+ terminar();
417
+ };
418
+ const respaldo = setTimeout(terminar, MAXIMO_SALIDA_MS);
419
+ dialog.addEventListener('animationend', alTerminarAnimacion);
420
+ dialog.classList.add(CLASE_CERRANDO);
421
+ });
422
+ }
423
+ armarSender() {
137
424
  const dataForm = this.authForm().value;
138
- const data = {
425
+ return {
139
426
  ruc: dataForm.ruc,
140
427
  coduser: dataForm.nomuser,
141
428
  clave: btoa(dataForm.clave),
142
429
  producto: this.product()
143
430
  };
144
- this.loginEvent.emit({ type: "LOGIN", data });
145
- };
146
- // authForm = this.formBuilder.group({
147
- // ruc: ['', Validators.required],
148
- // nomuser: ['', Validators.required],
149
- // clave: ['', Validators.required],
150
- // })
431
+ }
151
432
  validacion(value) {
152
433
  const authForm = this.authForm();
153
434
  if (authForm.get(value).touched && authForm.get(value).errors) {
@@ -171,11 +452,11 @@ class AuthComponent {
171
452
  return false;
172
453
  };
173
454
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AuthComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
174
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AuthComponent, isStandalone: true, selector: "lib-auth-tsi", inputs: { production: { classPropertyName: "production", publicName: "production", isSignal: true, isRequired: false, transformFunction: null }, module: { classPropertyName: "module", publicName: "module", isSignal: true, isRequired: false, transformFunction: null }, versionApp: { classPropertyName: "versionApp", publicName: "versionApp", isSignal: true, isRequired: false, transformFunction: null }, product: { classPropertyName: "product", publicName: "product", isSignal: true, isRequired: false, transformFunction: null }, authForm: { classPropertyName: "authForm", publicName: "authForm", isSignal: true, isRequired: true, transformFunction: null }, aboutList: { classPropertyName: "aboutList", publicName: "aboutList", isSignal: true, isRequired: false, transformFunction: null }, showFloatingApp: { classPropertyName: "showFloatingApp", publicName: "showFloatingApp", isSignal: true, isRequired: false, transformFunction: null }, showFloatingUpdate: { classPropertyName: "showFloatingUpdate", publicName: "showFloatingUpdate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loginEvent: "loginEvent", beforeInstall: "beforeInstall" }, ngImport: i0, template: "<div class=\"auth-wrapper-login\">\r\n @let produccion = production();\r\n <div class=\"auth-panel-left\" [class.auth-panel-left--dev]=\"!produccion\">\r\n <span class=\"auth-blob auth-blob-1\"></span>\r\n <span class=\"auth-blob auth-blob-2\"></span>\r\n <span class=\"auth-blob auth-blob-3\"></span>\r\n <span class=\"auth-blob auth-blob-4\"></span>\r\n\r\n <div class=\"auth-brand-panel\">\r\n <div class=\"auth-brand-logo\">\r\n <img src=\"assets/images/logo-tsi-tres.png\" alt=\"TSI\" />\r\n </div>\r\n <h1 class=\"auth-brand-title\">{{module()}}</h1>\r\n <p class=\"auth-brand-subtitle\">Plataforma integrada de gesti\u00F3n<br>empresarial</p>\r\n\r\n <div class=\"auth-brand-divider\"></div>\r\n\r\n <div class=\"auth-brand-features\">\r\n @for (item of aboutList(); track $index) {\r\n <div class=\"auth-brand-feature\">\r\n <span class=\"feat-dot\"></span> {{item}}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"auth-panel-right\" [class.auth-panel-right--dev]=\"!produccion\">\r\n <div class=\"auth-panel-bg\">\r\n <span class=\"auth-deco auth-deco-tl\"></span>\r\n <span class=\"auth-deco auth-deco-br\"></span>\r\n </div>\r\n\r\n <div class=\"auth-form-wrapper\">\r\n <div>\r\n @if (!produccion) {\r\n <div>\r\n <span class=\"auth-test-badge\">\r\n <span class=\"badge-dot\"></span> ENTORNO DE PRUEBAS\r\n </span>\r\n </div>\r\n }\r\n\r\n <div class=\"auth-card\">\r\n <h2 class=\"auth-card-title\">Bienvenido de vuelta</h2>\r\n <p class=\"auth-card-subtitle\">Ingresa tus credenciales para continuar</p>\r\n\r\n <form [formGroup]=\"authForm()\" id=\"loginform\">\r\n\r\n <p class=\"auth-hint\">\r\n <i class=\"fas fa-circle-info\"></i>\r\n Si piensas instalar la app, te recomendamos completar el RUC y Usuario antes, estos quedar\u00E1n guardados y siempre aparecer\u00E1n completos al abrirla.\r\n </p>\r\n\r\n <div class=\"auth-field\" [class.has-error]=\"validacion('ruc')\">\r\n <span class=\"auth-field-icon\"><i class=\"fas fa-building\"></i></span>\r\n <input type=\"text\" formControlName=\"ruc\" class=\"auth-input\" placeholder=\" \" maxlength=\"11\"\r\n id=\"f-ruc\" autocomplete=\"off\">\r\n <label for=\"f-ruc\" class=\"auth-label\">RUC</label>\r\n </div>\r\n @if (validacion('ruc')) {\r\n <p class=\"auth-error\" @fadeInOut>Ingresar RUC</p>\r\n }\r\n\r\n <div class=\"auth-field\" [class.has-error]=\"validacion('nomuser')\">\r\n <span class=\"auth-field-icon\"><i class=\"fas fa-user\"></i></span>\r\n <input type=\"text\" formControlName=\"nomuser\" class=\"auth-input\" placeholder=\" \" id=\"f-user\"\r\n autocomplete=\"off\">\r\n <label for=\"f-user\" class=\"auth-label\">Usuario</label>\r\n </div>\r\n @if (validacion('nomuser')) {\r\n <p class=\"auth-error\" @fadeInOut>Ingresar usuario</p>\r\n }\r\n\r\n <div class=\"auth-field\" [class.has-error]=\"validacion('clave')\">\r\n <span class=\"auth-field-icon\"><i class=\"fas fa-lock\"></i></span>\r\n <input [type]=\"showPassword() ? 'text' : 'password'\" formControlName=\"clave\"\r\n class=\"auth-input\" placeholder=\" \" id=\"f-clave\" autocomplete=\"off\" autocorrect=\"off\"\r\n autocapitalize=\"off\" spellcheck=\"false\">\r\n <label for=\"f-clave\" class=\"auth-label\">Contrase\u00F1a</label>\r\n <button type=\"button\" class=\"auth-toggle-pw\" (click)=\"togglePassword()\">\r\n <i [class]=\"showPassword() ? 'fas fa-eye' : 'fas fa-eye-slash'\"></i>\r\n </button>\r\n </div>\r\n @if (validacion('clave')) {\r\n <p class=\"auth-error\" @fadeInOut>Ingresar clave</p>\r\n }\r\n\r\n <button class=\"auth-btn mt-2\" [class.auth-btn--red]=\"!produccion\" (click)=\"login()\">\r\n Ingresar\r\n </button>\r\n\r\n <div class=\"auth-links\">\r\n <a [ngClass]=\"produccion ? 'blue_contrasena' : 'red_contrasena'\"\r\n (click)=\"recover()\">\u00BFOlvidaste tu contrase\u00F1a?</a>\r\n <a [ngClass]=\"produccion ? 'blue_contrasena' : 'red_contrasena'\"\r\n (click)=\"forget()\">\u00BFContrase\u00F1a vencida?</a>\r\n </div>\r\n\r\n </form>\r\n\r\n <div class=\"auth-version\">\r\n <span>v{{versionApp()}}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n@if (showFloatingApp()) {\r\n<app-pwa-floating [appName]=\"module()\" (beforeInstall)=\"onBeforeInstall()\" />\r\n}\r\n@if (showFloatingUpdate()) {\r\n<app-refresh-floating />\r\n}", styles: ["", "@charset \"UTF-8\";.red_contrasena,.blue_contrasena{position:relative;display:inline-block;font-size:13px;text-decoration:none;padding-bottom:2px;transition:color .3s ease;cursor:pointer}.red_contrasena:after,.blue_contrasena:after{content:\"\";position:absolute;bottom:0;left:50%;width:0;height:1px;background-color:currentColor;transition:all .3s ease;transform:translate(-50%)}.red_contrasena:hover:after,.blue_contrasena:hover:after{width:60%}.red_contrasena{color:#d1326f}.red_contrasena:hover{color:#a82859}.blue_contrasena{color:#398bf7}.blue_contrasena:hover{color:#1e5fc4}.auth-wrapper-login{position:fixed;inset:0;display:grid;grid-template-columns:1.15fr .85fr;overflow:hidden;background:#060d1f}.auth-panel-left{position:relative;overflow:hidden;background:linear-gradient(145deg,#040a18,#0b1a3d 55%,#040e22);display:flex;align-items:center;justify-content:center;padding:48px 40px}.auth-panel-left:before{content:\"\";position:absolute;inset:0;background-image:radial-gradient(circle,rgba(255,255,255,.055) 1px,transparent 1px);background-size:26px 26px;z-index:1;pointer-events:none}.auth-panel-left:after{content:\"\";position:absolute;top:0;left:-120%;width:60%;height:100%;background:linear-gradient(90deg,transparent,rgba(57,139,247,.04),transparent);animation:panelSweep 7s ease-in-out infinite;z-index:1;pointer-events:none}.auth-blob{position:absolute;border-radius:50%;filter:blur(72px);z-index:0;pointer-events:none}.auth-blob-1{width:340px;height:340px;background:radial-gradient(circle,rgba(57,139,247,.45) 0%,transparent 70%);top:-90px;right:-70px;animation:blobDrift 11s ease-in-out infinite}.auth-blob-2{width:240px;height:240px;background:radial-gradient(circle,rgba(124,58,237,.4) 0%,transparent 70%);bottom:60px;left:-50px;animation:blobDrift 14s ease-in-out infinite reverse}.auth-blob-3{width:180px;height:180px;background:radial-gradient(circle,rgba(14,165,233,.35) 0%,transparent 70%);bottom:-50px;right:40px;animation:blobDrift 9s ease-in-out infinite;animation-delay:-4s}.auth-blob-4{width:120px;height:120px;background:radial-gradient(circle,rgba(209,50,111,.25) 0%,transparent 70%);top:50%;left:50%;transform:translate(-50%,-50%);animation:blobDrift 16s ease-in-out infinite;animation-delay:-8s}@keyframes blobDrift{0%,to{transform:translate(0) scale(1)}33%{transform:translate(14px,-20px) scale(1.05)}66%{transform:translate(-10px,12px) scale(.96)}}@keyframes panelSweep{0%{left:-120%}50%{left:160%}to{left:160%}}.auth-brand-panel{position:relative;z-index:2;text-align:center;color:#fff;max-width:340px}.auth-brand-logo{width:100px;height:100px;border-radius:50%;background:#ffffff0d;border:1px solid rgba(255,255,255,.1);display:flex;align-items:center;justify-content:center;margin:0 auto 28px;box-shadow:0 0 0 14px #398bf70f,0 0 50px #398bf733;backdrop-filter:blur(8px)}.auth-brand-logo img{width:64px;height:64px;object-fit:contain;filter:brightness(1.05) drop-shadow(0 0 8px rgba(57,139,247,.4))}.auth-brand-title{font-size:30px;font-weight:700;letter-spacing:-.5px;margin-bottom:10px;background:linear-gradient(135deg,#fff 20%,#93c5fd 80%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.auth-brand-subtitle{font-size:14px;color:#ffffff73;line-height:1.65;margin-bottom:40px;letter-spacing:.2px}.auth-brand-features{display:flex;flex-direction:column;gap:14px;text-align:left}.auth-brand-feature{display:flex;align-items:center;gap:12px;font-size:13px;color:#fff9}.auth-brand-feature .feat-dot{flex-shrink:0;width:7px;height:7px;border-radius:50%;background:#398bf7;box-shadow:0 0 10px #398bf7b3}.auth-brand-divider{width:60px;height:2px;background:linear-gradient(90deg,transparent,#398bf7,transparent);margin:28px auto 32px;border-radius:2px}.auth-panel-left--dev{background:linear-gradient(145deg,#18040b,#3d0b1d 55%,#220409)}.auth-panel-left--dev:after{background:linear-gradient(90deg,transparent,rgba(209,50,111,.05),transparent)}.auth-panel-left--dev .auth-blob-1{background:radial-gradient(circle,rgba(220,38,38,.52) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-2{background:radial-gradient(circle,rgba(219,39,119,.44) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-3{background:radial-gradient(circle,rgba(239,68,68,.38) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-4{background:radial-gradient(circle,rgba(249,115,22,.28) 0%,transparent 70%)}.auth-panel-left--dev .auth-brand-logo{box-shadow:0 0 0 14px #d1326f12,0 0 50px #d1326f38}.auth-panel-left--dev .auth-brand-logo img{filter:brightness(1.05) drop-shadow(0 0 8px rgba(209,50,111,.45))}.auth-panel-left--dev .auth-brand-title{background:linear-gradient(135deg,#fff 20%,#fca5a5 80%);-webkit-background-clip:text;background-clip:text}.auth-panel-left--dev .auth-brand-divider{background:linear-gradient(90deg,transparent,rgb(209,50,111),transparent)}.auth-panel-left--dev .feat-dot{background:#d1326f;box-shadow:0 0 10px #d1326fb8}.auth-panel-right{position:relative;overflow:hidden;background:var(--background-login)}.auth-panel-right:before{content:\"\";position:absolute;inset:0;background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(57,139,247,.045) 22px,rgba(57,139,247,.045) 23px);animation:authLinesMove 10s linear infinite;pointer-events:none;z-index:0}.auth-panel-right:after{content:\"\";position:absolute;top:0;bottom:0;left:-25%;width:25%;background:linear-gradient(90deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLine 7s ease-in-out infinite;animation-delay:3.5s;pointer-events:none;z-index:0}@keyframes authLinesMove{0%{transform:translate(0)}to{transform:translate(46px,46px)}}@keyframes authScanLine{0%{left:-25%}50%{left:120%}to{left:120%}}.auth-panel-bg{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:hidden}.auth-deco{position:absolute;border-radius:50%;pointer-events:none;filter:blur(70px)}.auth-deco-tl{width:300px;height:300px;top:0;left:-120px;transform:translateY(-40%);background:radial-gradient(circle,rgba(57,139,247,.12) 0%,transparent 70%);animation:authOrbPulse 6s ease-in-out infinite}.auth-deco-br{width:340px;height:340px;bottom:0;right:-120px;transform:translateY(40%);background:radial-gradient(circle,rgba(124,58,237,.1) 0%,transparent 70%);animation:authOrbPulse 8s ease-in-out infinite;animation-delay:-4s}@keyframes authOrbPulse{0%,to{opacity:.7}50%{opacity:1}}.auth-form-wrapper{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;align-items:center;z-index:1}.auth-form-wrapper>div{width:100%;max-width:420px;margin:auto;padding:36px 16px;box-sizing:border-box}.auth-panel-right--dev:before{background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(209,50,111,.05) 22px,rgba(209,50,111,.05) 23px)}.auth-panel-right--dev:after{background:linear-gradient(90deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}.auth-panel-right--dev .auth-deco-tl{background:radial-gradient(circle,rgba(209,50,111,.12) 0%,transparent 70%)}.auth-panel-right--dev .auth-deco-br{background:radial-gradient(circle,rgba(239,68,68,.1) 0%,transparent 70%)}.auth-test-badge{display:inline-flex;align-items:center;gap:7px;background:#d1326f14;border:1px solid rgba(209,50,111,.25);color:#d1326f;font-size:10.5px;font-weight:700;padding:5px 12px;border-radius:20px;margin-bottom:18px;letter-spacing:.8px}.auth-test-badge .badge-dot{width:6px;height:6px;border-radius:50%;background:#d1326f;animation:badgePulse 1.6s ease-in-out infinite;flex-shrink:0}@keyframes badgePulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.75)}}.auth-card{background:var(--background-card);border-radius:20px;padding:36px 32px 28px;box-shadow:0 4px 28px #00000014;border:1px solid var(--border-color-modal)}.auth-card-title{font-size:22px;font-weight:700;color:var(--text-color);margin-bottom:4px;letter-spacing:-.3px}.auth-card-subtitle{font-size:13px;color:var(--placeholder-color);margin-bottom:26px}.auth-field{position:relative;margin-bottom:1rem}.auth-field .auth-field-icon{position:absolute;left:13px;top:50%;transform:translateY(-50%);color:var(--placeholder-color);font-size:13px;z-index:2;pointer-events:none;transition:color .2s}.auth-field .auth-input{width:100%;padding:15px 40px 15px 37px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s,background .2s}.auth-field .auth-input::placeholder{color:transparent}.auth-field .auth-input:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721;background:var(--background-focus-input)}.auth-field .auth-input:focus~.auth-label{top:0;font-size:11px!important;color:#398bf7!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-input:focus~.auth-field-icon{color:#398bf7}.auth-field .auth-input:not(:placeholder-shown)~.auth-label{top:0;font-size:11px!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-label{position:absolute;left:35px;top:50%;transform:translateY(-50%);color:var(--placeholder-color)!important;font-size:13px!important;font-weight:400!important;pointer-events:none;transition:top .15s ease,font-size .15s ease,color .15s ease,padding .15s ease,background .15s ease;background:transparent;z-index:1;text-align:left!important}.auth-field .auth-toggle-pw{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;color:var(--placeholder-color);cursor:pointer;padding:4px 6px;font-size:13px;z-index:2;line-height:1;transition:color .2s}.auth-field .auth-toggle-pw:hover{color:#398bf7}.auth-field.has-error .auth-input{border-color:#dc3545;box-shadow:none}.auth-field.has-error .auth-field-icon{color:#dc3545}.auth-select{width:100%;padding:13px 14px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s;margin-bottom:1rem;cursor:pointer}.auth-select:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721}.auth-btn{width:100%;padding:13px;border:none;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:transform .15s ease,box-shadow .2s ease,opacity .2s;background:linear-gradient(135deg,#398bf7,#1e5fc4);color:#fff;letter-spacing:.3px;margin-bottom:10px;display:block}.auth-btn:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 5px 18px #398bf761}.auth-btn:active:not(:disabled){transform:translateY(0)}.auth-btn:disabled{opacity:.55;cursor:not-allowed}.auth-btn.auth-btn--red{background:linear-gradient(135deg,#d1326f,#a82859)}.auth-btn.auth-btn--red:hover:not(:disabled){box-shadow:0 5px 18px #d1326f61}.auth-btn.auth-btn--outline{background:transparent;border:1.5px solid var(--font-border-input);color:var(--text-color)}.auth-btn.auth-btn--outline:hover:not(:disabled){background:var(--background-btn-light-hover);box-shadow:none;transform:none}.auth-links{display:flex;flex-direction:column;align-items:center;gap:10px;margin-top:16px;padding-top:16px;border-top:1px solid var(--border-color-modal)}.auth-version{text-align:right;margin-top:14px;padding-top:12px;border-top:1px solid var(--border-color-modal)}.auth-version span{font-size:11px;color:var(--placeholder-color)}.auth-error{font-size:11.5px;color:#dc3545;margin:-6px 0 10px 2px;padding:0}.auth-hint{display:flex;align-items:flex-start;gap:6px;font-size:11.5px;color:var(--placeholder-color);margin:-6px 0 14px 2px;padding:0;line-height:1.35}.auth-hint i{margin-top:2px;flex-shrink:0}.auth-validation-list{margin:-4px 0 12px;padding:0;list-style:none}.auth-validation-list li{font-size:11.5px;color:#dc3545;padding:2px 0}.auth-validation-list li:before{content:\"\\2715 \";font-size:10px}.auth-desc{font-size:13px;color:var(--placeholder-color);margin-bottom:20px;line-height:1.65}.auth-section-title{font-size:15px;font-weight:600;color:var(--text-color);margin-bottom:20px}.font-12{font-size:12px}.form-control:focus{border-color:#0199ff9a!important;box-shadow:0 0 5px .2px #65befa44!important}@media(max-width:900px){.auth-wrapper-login{grid-template-columns:1fr;grid-template-rows:auto 1fr;overflow-y:auto;overflow-x:hidden}.auth-panel-left{padding:14px 24px;justify-content:center}.auth-panel-left .auth-brand-subtitle,.auth-panel-left .auth-brand-features,.auth-panel-left .auth-brand-divider{display:none!important}.auth-panel-left .auth-brand-panel{display:flex!important;flex-direction:row!important;align-items:center;gap:0;text-align:left;max-width:none;width:100%;justify-content:center}.auth-panel-left .auth-brand-logo{width:52px;height:52px;margin:0;flex-shrink:0}.auth-panel-left .auth-brand-logo img{width:34px;height:34px}.auth-panel-left .auth-brand-title{font-size:20px;margin-bottom:0;margin-left:.5rem;flex-shrink:1}.auth-panel-right:after{inset:-25% 0 auto;width:100%;height:25%;background:linear-gradient(180deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLineV 7s ease-in-out infinite;animation-delay:3.5s}.auth-panel-right--dev:after{background:linear-gradient(180deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}}@keyframes authScanLineV{0%{top:-25%}50%{top:120%}to{top:120%}}@media(max-width:480px){.auth-panel-left{padding:12px 16px}.auth-panel-left .auth-brand-logo{width:44px;height:44px}.auth-panel-left .auth-brand-logo img{width:28px;height:28px}.auth-panel-left .auth-brand-title{font-size:17px}.auth-form-wrapper>div{padding:20px 12px}.auth-card{padding:24px 18px 20px;border-radius:16px}.font-12{font-size:10px!important}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: PwaFloatingComponent, selector: "app-pwa-floating", inputs: ["appName", "logo", "chipLabel"], outputs: ["beforeInstall", "guideClosed"] }, { kind: "component", type: RefreshFloatingComponent, selector: "app-refresh-floating" }], animations: [fadeInOut] });
455
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: AuthComponent, isStandalone: true, selector: "lib-auth-tsi", inputs: { production: { classPropertyName: "production", publicName: "production", isSignal: true, isRequired: false, transformFunction: null }, module: { classPropertyName: "module", publicName: "module", isSignal: true, isRequired: false, transformFunction: null }, versionApp: { classPropertyName: "versionApp", publicName: "versionApp", isSignal: true, isRequired: false, transformFunction: null }, product: { classPropertyName: "product", publicName: "product", isSignal: true, isRequired: false, transformFunction: null }, authForm: { classPropertyName: "authForm", publicName: "authForm", isSignal: true, isRequired: true, transformFunction: null }, aboutList: { classPropertyName: "aboutList", publicName: "aboutList", isSignal: true, isRequired: false, transformFunction: null }, showFloatingApp: { classPropertyName: "showFloatingApp", publicName: "showFloatingApp", isSignal: true, isRequired: false, transformFunction: null }, showFloatingUpdate: { classPropertyName: "showFloatingUpdate", publicName: "showFloatingUpdate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loginEvent: "loginEvent", beforeInstall: "beforeInstall" }, viewQueries: [{ propertyName: "dialogMfa", first: true, predicate: ["dialogMfa"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"auth-wrapper-login\">\r\n @let produccion = production();\r\n <div class=\"auth-panel-left\" [class.auth-panel-left--dev]=\"!produccion\">\r\n <span class=\"auth-blob auth-blob-1\"></span>\r\n <span class=\"auth-blob auth-blob-2\"></span>\r\n <span class=\"auth-blob auth-blob-3\"></span>\r\n <span class=\"auth-blob auth-blob-4\"></span>\r\n\r\n <div class=\"auth-brand-panel\">\r\n <div class=\"auth-brand-logo\">\r\n <img src=\"assets/images/logo-tsi-tres.png\" alt=\"TSI\" />\r\n </div>\r\n <h1 class=\"auth-brand-title\">{{module()}}</h1>\r\n <p class=\"auth-brand-subtitle\">Plataforma integrada de gesti\u00F3n<br>empresarial</p>\r\n\r\n <div class=\"auth-brand-divider\"></div>\r\n\r\n <div class=\"auth-brand-features\">\r\n @for (item of aboutList(); track $index) {\r\n <div class=\"auth-brand-feature\">\r\n <span class=\"feat-dot\"></span> {{item}}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"auth-panel-right\" [class.auth-panel-right--dev]=\"!produccion\">\r\n <div class=\"auth-panel-bg\">\r\n <span class=\"auth-deco auth-deco-tl\"></span>\r\n <span class=\"auth-deco auth-deco-br\"></span>\r\n </div>\r\n\r\n <div class=\"auth-form-wrapper\">\r\n <div>\r\n @if (!produccion) {\r\n <div>\r\n <span class=\"auth-test-badge\">\r\n <span class=\"badge-dot\"></span> ENTORNO DE PRUEBAS\r\n </span>\r\n </div>\r\n }\r\n\r\n <div class=\"auth-card\">\r\n <h2 class=\"auth-card-title\">Bienvenido de vuelta</h2>\r\n <p class=\"auth-card-subtitle\">Ingresa tus credenciales para continuar</p>\r\n\r\n <form [formGroup]=\"authForm()\" id=\"loginform\">\r\n\r\n <p class=\"auth-hint\">\r\n <i class=\"fas fa-circle-info\"></i>\r\n Si piensas instalar la app, te recomendamos completar el RUC y Usuario antes, estos quedar\u00E1n guardados y siempre aparecer\u00E1n completos al abrirla.\r\n </p>\r\n\r\n <div class=\"auth-field\" [class.has-error]=\"validacion('ruc')\">\r\n <span class=\"auth-field-icon\"><i class=\"fas fa-building\"></i></span>\r\n <input type=\"text\" formControlName=\"ruc\" class=\"auth-input\" placeholder=\" \" maxlength=\"11\"\r\n id=\"f-ruc\" autocomplete=\"off\">\r\n <label for=\"f-ruc\" class=\"auth-label\">RUC</label>\r\n </div>\r\n @if (validacion('ruc')) {\r\n <p class=\"auth-error\" @fadeInOut>Ingresar RUC</p>\r\n }\r\n\r\n <div class=\"auth-field\" [class.has-error]=\"validacion('nomuser')\">\r\n <span class=\"auth-field-icon\"><i class=\"fas fa-user\"></i></span>\r\n <input type=\"text\" formControlName=\"nomuser\" class=\"auth-input\" placeholder=\" \" id=\"f-user\"\r\n autocomplete=\"off\">\r\n <label for=\"f-user\" class=\"auth-label\">Usuario</label>\r\n </div>\r\n @if (validacion('nomuser')) {\r\n <p class=\"auth-error\" @fadeInOut>Ingresar usuario</p>\r\n }\r\n\r\n <div class=\"auth-field\" [class.has-error]=\"validacion('clave')\">\r\n <span class=\"auth-field-icon\"><i class=\"fas fa-lock\"></i></span>\r\n <input [type]=\"showPassword() ? 'text' : 'password'\" formControlName=\"clave\"\r\n class=\"auth-input\" placeholder=\" \" id=\"f-clave\" autocomplete=\"off\" autocorrect=\"off\"\r\n autocapitalize=\"off\" spellcheck=\"false\">\r\n <label for=\"f-clave\" class=\"auth-label\">Contrase\u00F1a</label>\r\n <button type=\"button\" class=\"auth-toggle-pw\" (click)=\"togglePassword()\">\r\n <i [class]=\"showPassword() ? 'fas fa-eye' : 'fas fa-eye-slash'\"></i>\r\n </button>\r\n </div>\r\n @if (validacion('clave')) {\r\n <p class=\"auth-error\" @fadeInOut>Ingresar clave</p>\r\n }\r\n\r\n <button class=\"auth-btn mt-2\" [class.auth-btn--red]=\"!produccion\" [disabled]=\"isIngresando()\"\r\n (click)=\"login()\">\r\n {{ isIngresando() ? 'Ingresando\u2026' : 'Ingresar' }}\r\n </button>\r\n\r\n <div class=\"auth-links\">\r\n <a [ngClass]=\"produccion ? 'blue_contrasena' : 'red_contrasena'\"\r\n (click)=\"recover()\">\u00BFOlvidaste tu contrase\u00F1a?</a>\r\n <a [ngClass]=\"produccion ? 'blue_contrasena' : 'red_contrasena'\"\r\n (click)=\"forget()\">\u00BFContrase\u00F1a vencida?</a>\r\n </div>\r\n\r\n </form>\r\n\r\n <div class=\"auth-version\">\r\n <span>v{{versionApp()}}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<dialog #dialogMfa class=\"auth-mfa-dialog\" (cancel)=\"$event.preventDefault()\">\r\n @if (pasoMfa(); as paso) {\r\n <lib-md-verificar-mfa [challenge]=\"paso.challenge\" (verificado)=\"onMfaVerificado()\"\r\n (cancelado)=\"onMfaCancelado()\" />\r\n }\r\n</dialog>\r\n\r\n@if (showFloatingApp()) {\r\n<app-pwa-floating [appName]=\"module()\" (beforeInstall)=\"onBeforeInstall()\" />\r\n}\r\n@if (showFloatingUpdate()) {\r\n<app-refresh-floating />\r\n}", styles: [".auth-mfa-dialog{width:min(440px,100vw - 32px);max-height:calc(100vh - 32px);padding:28px 28px 24px;border:1px solid var(--border-color-modal);border-radius:20px;background:var(--background-card);color:var(--text-color);box-shadow:0 20px 60px #0000004d}.auth-mfa-dialog::backdrop{background:#0f172a8c;backdrop-filter:blur(2px)}.auth-mfa-dialog[open]{animation:auth-mfa-entrar .26s cubic-bezier(.16,1,.3,1) both}.auth-mfa-dialog[open]::backdrop{animation:auth-mfa-fondo-entrar .26s ease-out both}.auth-mfa-dialog--cerrando[open]{animation:auth-mfa-salir .18s cubic-bezier(.4,0,1,1) both}.auth-mfa-dialog--cerrando[open]::backdrop{animation:auth-mfa-fondo-salir .18s ease-in both}@keyframes auth-mfa-entrar{0%{opacity:0;transform:translateY(16px) scale(.96)}to{opacity:1;transform:none}}@keyframes auth-mfa-salir{0%{opacity:1;transform:none}to{opacity:0;transform:translateY(8px) scale(.97)}}@keyframes auth-mfa-fondo-entrar{0%{opacity:0}to{opacity:1}}@keyframes auth-mfa-fondo-salir{0%{opacity:1}to{opacity:0}}@keyframes auth-mfa-fundido-entrar{0%{opacity:0}to{opacity:1}}@keyframes auth-mfa-fundido-salir{0%{opacity:1}to{opacity:0}}@media(prefers-reduced-motion:reduce){.auth-mfa-dialog[open]{animation:auth-mfa-fundido-entrar .12s linear both}.auth-mfa-dialog--cerrando[open]{animation:auth-mfa-fundido-salir .12s linear both}}\n", "@charset \"UTF-8\";.red_contrasena,.blue_contrasena{position:relative;display:inline-block;font-size:13px;text-decoration:none;padding-bottom:2px;transition:color .3s ease;cursor:pointer}.red_contrasena:after,.blue_contrasena:after{content:\"\";position:absolute;bottom:0;left:50%;width:0;height:1px;background-color:currentColor;transition:all .3s ease;transform:translate(-50%)}.red_contrasena:hover:after,.blue_contrasena:hover:after{width:60%}.red_contrasena{color:#d1326f}.red_contrasena:hover{color:#a82859}.blue_contrasena{color:#398bf7}.blue_contrasena:hover{color:#1e5fc4}.auth-wrapper-login{position:fixed;inset:0;display:grid;grid-template-columns:1.15fr .85fr;overflow:hidden;background:#060d1f}.auth-panel-left{position:relative;overflow:hidden;background:linear-gradient(145deg,#040a18,#0b1a3d 55%,#040e22);display:flex;align-items:center;justify-content:center;padding:48px 40px}.auth-panel-left:before{content:\"\";position:absolute;inset:0;background-image:radial-gradient(circle,rgba(255,255,255,.055) 1px,transparent 1px);background-size:26px 26px;z-index:1;pointer-events:none}.auth-panel-left:after{content:\"\";position:absolute;top:0;left:-120%;width:60%;height:100%;background:linear-gradient(90deg,transparent,rgba(57,139,247,.04),transparent);animation:panelSweep 7s ease-in-out infinite;z-index:1;pointer-events:none}.auth-blob{position:absolute;border-radius:50%;filter:blur(72px);z-index:0;pointer-events:none}.auth-blob-1{width:340px;height:340px;background:radial-gradient(circle,rgba(57,139,247,.45) 0%,transparent 70%);top:-90px;right:-70px;animation:blobDrift 11s ease-in-out infinite}.auth-blob-2{width:240px;height:240px;background:radial-gradient(circle,rgba(124,58,237,.4) 0%,transparent 70%);bottom:60px;left:-50px;animation:blobDrift 14s ease-in-out infinite reverse}.auth-blob-3{width:180px;height:180px;background:radial-gradient(circle,rgba(14,165,233,.35) 0%,transparent 70%);bottom:-50px;right:40px;animation:blobDrift 9s ease-in-out infinite;animation-delay:-4s}.auth-blob-4{width:120px;height:120px;background:radial-gradient(circle,rgba(209,50,111,.25) 0%,transparent 70%);top:50%;left:50%;transform:translate(-50%,-50%);animation:blobDrift 16s ease-in-out infinite;animation-delay:-8s}@keyframes blobDrift{0%,to{transform:translate(0) scale(1)}33%{transform:translate(14px,-20px) scale(1.05)}66%{transform:translate(-10px,12px) scale(.96)}}@keyframes panelSweep{0%{left:-120%}50%{left:160%}to{left:160%}}.auth-brand-panel{position:relative;z-index:2;text-align:center;color:#fff;max-width:340px}.auth-brand-logo{width:100px;height:100px;border-radius:50%;background:#ffffff0d;border:1px solid rgba(255,255,255,.1);display:flex;align-items:center;justify-content:center;margin:0 auto 28px;box-shadow:0 0 0 14px #398bf70f,0 0 50px #398bf733;backdrop-filter:blur(8px)}.auth-brand-logo img{width:64px;height:64px;object-fit:contain;filter:brightness(1.05) drop-shadow(0 0 8px rgba(57,139,247,.4))}.auth-brand-title{font-size:30px;font-weight:700;letter-spacing:-.5px;margin-bottom:10px;background:linear-gradient(135deg,#fff 20%,#93c5fd 80%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.auth-brand-subtitle{font-size:14px;color:#ffffff73;line-height:1.65;margin-bottom:40px;letter-spacing:.2px}.auth-brand-features{display:flex;flex-direction:column;gap:14px;text-align:left}.auth-brand-feature{display:flex;align-items:center;gap:12px;font-size:13px;color:#fff9}.auth-brand-feature .feat-dot{flex-shrink:0;width:7px;height:7px;border-radius:50%;background:#398bf7;box-shadow:0 0 10px #398bf7b3}.auth-brand-divider{width:60px;height:2px;background:linear-gradient(90deg,transparent,#398bf7,transparent);margin:28px auto 32px;border-radius:2px}.auth-panel-left--dev{background:linear-gradient(145deg,#18040b,#3d0b1d 55%,#220409)}.auth-panel-left--dev:after{background:linear-gradient(90deg,transparent,rgba(209,50,111,.05),transparent)}.auth-panel-left--dev .auth-blob-1{background:radial-gradient(circle,rgba(220,38,38,.52) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-2{background:radial-gradient(circle,rgba(219,39,119,.44) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-3{background:radial-gradient(circle,rgba(239,68,68,.38) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-4{background:radial-gradient(circle,rgba(249,115,22,.28) 0%,transparent 70%)}.auth-panel-left--dev .auth-brand-logo{box-shadow:0 0 0 14px #d1326f12,0 0 50px #d1326f38}.auth-panel-left--dev .auth-brand-logo img{filter:brightness(1.05) drop-shadow(0 0 8px rgba(209,50,111,.45))}.auth-panel-left--dev .auth-brand-title{background:linear-gradient(135deg,#fff 20%,#fca5a5 80%);-webkit-background-clip:text;background-clip:text}.auth-panel-left--dev .auth-brand-divider{background:linear-gradient(90deg,transparent,rgb(209,50,111),transparent)}.auth-panel-left--dev .feat-dot{background:#d1326f;box-shadow:0 0 10px #d1326fb8}.auth-panel-right{position:relative;overflow:hidden;background:var(--background-login)}.auth-panel-right:before{content:\"\";position:absolute;inset:0;background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(57,139,247,.045) 22px,rgba(57,139,247,.045) 23px);animation:authLinesMove 10s linear infinite;pointer-events:none;z-index:0}.auth-panel-right:after{content:\"\";position:absolute;top:0;bottom:0;left:-25%;width:25%;background:linear-gradient(90deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLine 7s ease-in-out infinite;animation-delay:3.5s;pointer-events:none;z-index:0}@keyframes authLinesMove{0%{transform:translate(0)}to{transform:translate(46px,46px)}}@keyframes authScanLine{0%{left:-25%}50%{left:120%}to{left:120%}}.auth-panel-bg{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:hidden}.auth-deco{position:absolute;border-radius:50%;pointer-events:none;filter:blur(70px)}.auth-deco-tl{width:300px;height:300px;top:0;left:-120px;transform:translateY(-40%);background:radial-gradient(circle,rgba(57,139,247,.12) 0%,transparent 70%);animation:authOrbPulse 6s ease-in-out infinite}.auth-deco-br{width:340px;height:340px;bottom:0;right:-120px;transform:translateY(40%);background:radial-gradient(circle,rgba(124,58,237,.1) 0%,transparent 70%);animation:authOrbPulse 8s ease-in-out infinite;animation-delay:-4s}@keyframes authOrbPulse{0%,to{opacity:.7}50%{opacity:1}}.auth-form-wrapper{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;align-items:center;z-index:1}.auth-form-wrapper>div{width:100%;max-width:420px;margin:auto;padding:36px 16px;box-sizing:border-box}.auth-panel-right--dev:before{background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(209,50,111,.05) 22px,rgba(209,50,111,.05) 23px)}.auth-panel-right--dev:after{background:linear-gradient(90deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}.auth-panel-right--dev .auth-deco-tl{background:radial-gradient(circle,rgba(209,50,111,.12) 0%,transparent 70%)}.auth-panel-right--dev .auth-deco-br{background:radial-gradient(circle,rgba(239,68,68,.1) 0%,transparent 70%)}.auth-test-badge{display:inline-flex;align-items:center;gap:7px;background:#d1326f14;border:1px solid rgba(209,50,111,.25);color:#d1326f;font-size:10.5px;font-weight:700;padding:5px 12px;border-radius:20px;margin-bottom:18px;letter-spacing:.8px}.auth-test-badge .badge-dot{width:6px;height:6px;border-radius:50%;background:#d1326f;animation:badgePulse 1.6s ease-in-out infinite;flex-shrink:0}@keyframes badgePulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.75)}}.auth-card{background:var(--background-card);border-radius:20px;padding:36px 32px 28px;box-shadow:0 4px 28px #00000014;border:1px solid var(--border-color-modal)}.auth-card-title{font-size:22px;font-weight:700;color:var(--text-color);margin-bottom:4px;letter-spacing:-.3px}.auth-card-subtitle{font-size:13px;color:var(--placeholder-color);margin-bottom:26px}.auth-field{position:relative;margin-bottom:1rem}.auth-field .auth-field-icon{position:absolute;left:13px;top:50%;transform:translateY(-50%);color:var(--placeholder-color);font-size:13px;z-index:2;pointer-events:none;transition:color .2s}.auth-field .auth-input{width:100%;padding:15px 40px 15px 37px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s,background .2s}.auth-field .auth-input::placeholder{color:transparent}.auth-field .auth-input:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721;background:var(--background-focus-input)}.auth-field .auth-input:focus~.auth-label{top:0;font-size:11px!important;color:#398bf7!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-input:focus~.auth-field-icon{color:#398bf7}.auth-field .auth-input:not(:placeholder-shown)~.auth-label{top:0;font-size:11px!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-label{position:absolute;left:35px;top:50%;transform:translateY(-50%);color:var(--placeholder-color)!important;font-size:13px!important;font-weight:400!important;pointer-events:none;transition:top .15s ease,font-size .15s ease,color .15s ease,padding .15s ease,background .15s ease;background:transparent;z-index:1;text-align:left!important}.auth-field .auth-toggle-pw{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;color:var(--placeholder-color);cursor:pointer;padding:4px 6px;font-size:13px;z-index:2;line-height:1;transition:color .2s}.auth-field .auth-toggle-pw:hover{color:#398bf7}.auth-field.has-error .auth-input{border-color:#dc3545;box-shadow:none}.auth-field.has-error .auth-field-icon{color:#dc3545}.auth-select{width:100%;padding:13px 14px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s;margin-bottom:1rem;cursor:pointer}.auth-select:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721}.auth-btn{width:100%;padding:13px;border:none;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:transform .15s ease,box-shadow .2s ease,opacity .2s;background:linear-gradient(135deg,#398bf7,#1e5fc4);color:#fff;letter-spacing:.3px;margin-bottom:10px;display:block}.auth-btn:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 5px 18px #398bf761}.auth-btn:active:not(:disabled){transform:translateY(0)}.auth-btn:disabled{opacity:.55;cursor:not-allowed}.auth-btn.auth-btn--red{background:linear-gradient(135deg,#d1326f,#a82859)}.auth-btn.auth-btn--red:hover:not(:disabled){box-shadow:0 5px 18px #d1326f61}.auth-btn.auth-btn--outline{background:transparent;border:1.5px solid var(--font-border-input);color:var(--text-color)}.auth-btn.auth-btn--outline:hover:not(:disabled){background:var(--background-btn-light-hover);box-shadow:none;transform:none}.auth-links{display:flex;flex-direction:column;align-items:center;gap:10px;margin-top:16px;padding-top:16px;border-top:1px solid var(--border-color-modal)}.auth-version{text-align:right;margin-top:14px;padding-top:12px;border-top:1px solid var(--border-color-modal)}.auth-version span{font-size:11px;color:var(--placeholder-color)}.auth-error{font-size:11.5px;color:#dc3545;margin:-6px 0 10px 2px;padding:0}.auth-hint{display:flex;align-items:flex-start;gap:6px;font-size:11.5px;color:var(--placeholder-color);margin:-6px 0 14px 2px;padding:0;line-height:1.35}.auth-hint i{margin-top:2px;flex-shrink:0}.auth-validation-list{margin:-4px 0 12px;padding:0;list-style:none}.auth-validation-list li{font-size:11.5px;color:#dc3545;padding:2px 0}.auth-validation-list li:before{content:\"\\2715 \";font-size:10px}.auth-desc{font-size:13px;color:var(--placeholder-color);margin-bottom:20px;line-height:1.65}.auth-section-title{font-size:15px;font-weight:600;color:var(--text-color);margin-bottom:20px}.font-12{font-size:12px}.form-control:focus{border-color:#0199ff9a!important;box-shadow:0 0 5px .2px #65befa44!important}@media(max-width:900px){.auth-wrapper-login{grid-template-columns:1fr;grid-template-rows:auto 1fr;overflow-y:auto;overflow-x:hidden}.auth-panel-left{padding:14px 24px;justify-content:center}.auth-panel-left .auth-brand-subtitle,.auth-panel-left .auth-brand-features,.auth-panel-left .auth-brand-divider{display:none!important}.auth-panel-left .auth-brand-panel{display:flex!important;flex-direction:row!important;align-items:center;gap:0;text-align:left;max-width:none;width:100%;justify-content:center}.auth-panel-left .auth-brand-logo{width:52px;height:52px;margin:0;flex-shrink:0}.auth-panel-left .auth-brand-logo img{width:34px;height:34px}.auth-panel-left .auth-brand-title{font-size:20px;margin-bottom:0;margin-left:.5rem;flex-shrink:1}.auth-panel-right:after{inset:-25% 0 auto;width:100%;height:25%;background:linear-gradient(180deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLineV 7s ease-in-out infinite;animation-delay:3.5s}.auth-panel-right--dev:after{background:linear-gradient(180deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}}@keyframes authScanLineV{0%{top:-25%}50%{top:120%}to{top:120%}}@media(max-width:480px){.auth-panel-left{padding:12px 16px}.auth-panel-left .auth-brand-logo{width:44px;height:44px}.auth-panel-left .auth-brand-logo img{width:28px;height:28px}.auth-panel-left .auth-brand-title{font-size:17px}.auth-form-wrapper>div{padding:20px 12px}.auth-card{padding:24px 18px 20px;border-radius:16px}.font-12{font-size:10px!important}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: PwaFloatingComponent, selector: "app-pwa-floating", inputs: ["appName", "logo", "chipLabel"], outputs: ["beforeInstall", "guideClosed"] }, { kind: "component", type: RefreshFloatingComponent, selector: "app-refresh-floating" }, { kind: "component", type: MdVerificarMfaComponent, selector: "lib-md-verificar-mfa", inputs: ["challenge", "titulo", "showCancelar"], outputs: ["verificado", "cancelado"] }], animations: [fadeInOut] });
175
456
  }
176
457
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AuthComponent, decorators: [{
177
458
  type: Component,
178
- args: [{ selector: 'lib-auth-tsi', imports: [NgClass, ReactiveFormsModule, PwaFloatingComponent, RefreshFloatingComponent], animations: [fadeInOut], template: "<div class=\"auth-wrapper-login\">\r\n @let produccion = production();\r\n <div class=\"auth-panel-left\" [class.auth-panel-left--dev]=\"!produccion\">\r\n <span class=\"auth-blob auth-blob-1\"></span>\r\n <span class=\"auth-blob auth-blob-2\"></span>\r\n <span class=\"auth-blob auth-blob-3\"></span>\r\n <span class=\"auth-blob auth-blob-4\"></span>\r\n\r\n <div class=\"auth-brand-panel\">\r\n <div class=\"auth-brand-logo\">\r\n <img src=\"assets/images/logo-tsi-tres.png\" alt=\"TSI\" />\r\n </div>\r\n <h1 class=\"auth-brand-title\">{{module()}}</h1>\r\n <p class=\"auth-brand-subtitle\">Plataforma integrada de gesti\u00F3n<br>empresarial</p>\r\n\r\n <div class=\"auth-brand-divider\"></div>\r\n\r\n <div class=\"auth-brand-features\">\r\n @for (item of aboutList(); track $index) {\r\n <div class=\"auth-brand-feature\">\r\n <span class=\"feat-dot\"></span> {{item}}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"auth-panel-right\" [class.auth-panel-right--dev]=\"!produccion\">\r\n <div class=\"auth-panel-bg\">\r\n <span class=\"auth-deco auth-deco-tl\"></span>\r\n <span class=\"auth-deco auth-deco-br\"></span>\r\n </div>\r\n\r\n <div class=\"auth-form-wrapper\">\r\n <div>\r\n @if (!produccion) {\r\n <div>\r\n <span class=\"auth-test-badge\">\r\n <span class=\"badge-dot\"></span> ENTORNO DE PRUEBAS\r\n </span>\r\n </div>\r\n }\r\n\r\n <div class=\"auth-card\">\r\n <h2 class=\"auth-card-title\">Bienvenido de vuelta</h2>\r\n <p class=\"auth-card-subtitle\">Ingresa tus credenciales para continuar</p>\r\n\r\n <form [formGroup]=\"authForm()\" id=\"loginform\">\r\n\r\n <p class=\"auth-hint\">\r\n <i class=\"fas fa-circle-info\"></i>\r\n Si piensas instalar la app, te recomendamos completar el RUC y Usuario antes, estos quedar\u00E1n guardados y siempre aparecer\u00E1n completos al abrirla.\r\n </p>\r\n\r\n <div class=\"auth-field\" [class.has-error]=\"validacion('ruc')\">\r\n <span class=\"auth-field-icon\"><i class=\"fas fa-building\"></i></span>\r\n <input type=\"text\" formControlName=\"ruc\" class=\"auth-input\" placeholder=\" \" maxlength=\"11\"\r\n id=\"f-ruc\" autocomplete=\"off\">\r\n <label for=\"f-ruc\" class=\"auth-label\">RUC</label>\r\n </div>\r\n @if (validacion('ruc')) {\r\n <p class=\"auth-error\" @fadeInOut>Ingresar RUC</p>\r\n }\r\n\r\n <div class=\"auth-field\" [class.has-error]=\"validacion('nomuser')\">\r\n <span class=\"auth-field-icon\"><i class=\"fas fa-user\"></i></span>\r\n <input type=\"text\" formControlName=\"nomuser\" class=\"auth-input\" placeholder=\" \" id=\"f-user\"\r\n autocomplete=\"off\">\r\n <label for=\"f-user\" class=\"auth-label\">Usuario</label>\r\n </div>\r\n @if (validacion('nomuser')) {\r\n <p class=\"auth-error\" @fadeInOut>Ingresar usuario</p>\r\n }\r\n\r\n <div class=\"auth-field\" [class.has-error]=\"validacion('clave')\">\r\n <span class=\"auth-field-icon\"><i class=\"fas fa-lock\"></i></span>\r\n <input [type]=\"showPassword() ? 'text' : 'password'\" formControlName=\"clave\"\r\n class=\"auth-input\" placeholder=\" \" id=\"f-clave\" autocomplete=\"off\" autocorrect=\"off\"\r\n autocapitalize=\"off\" spellcheck=\"false\">\r\n <label for=\"f-clave\" class=\"auth-label\">Contrase\u00F1a</label>\r\n <button type=\"button\" class=\"auth-toggle-pw\" (click)=\"togglePassword()\">\r\n <i [class]=\"showPassword() ? 'fas fa-eye' : 'fas fa-eye-slash'\"></i>\r\n </button>\r\n </div>\r\n @if (validacion('clave')) {\r\n <p class=\"auth-error\" @fadeInOut>Ingresar clave</p>\r\n }\r\n\r\n <button class=\"auth-btn mt-2\" [class.auth-btn--red]=\"!produccion\" (click)=\"login()\">\r\n Ingresar\r\n </button>\r\n\r\n <div class=\"auth-links\">\r\n <a [ngClass]=\"produccion ? 'blue_contrasena' : 'red_contrasena'\"\r\n (click)=\"recover()\">\u00BFOlvidaste tu contrase\u00F1a?</a>\r\n <a [ngClass]=\"produccion ? 'blue_contrasena' : 'red_contrasena'\"\r\n (click)=\"forget()\">\u00BFContrase\u00F1a vencida?</a>\r\n </div>\r\n\r\n </form>\r\n\r\n <div class=\"auth-version\">\r\n <span>v{{versionApp()}}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n@if (showFloatingApp()) {\r\n<app-pwa-floating [appName]=\"module()\" (beforeInstall)=\"onBeforeInstall()\" />\r\n}\r\n@if (showFloatingUpdate()) {\r\n<app-refresh-floating />\r\n}", styles: ["@charset \"UTF-8\";.red_contrasena,.blue_contrasena{position:relative;display:inline-block;font-size:13px;text-decoration:none;padding-bottom:2px;transition:color .3s ease;cursor:pointer}.red_contrasena:after,.blue_contrasena:after{content:\"\";position:absolute;bottom:0;left:50%;width:0;height:1px;background-color:currentColor;transition:all .3s ease;transform:translate(-50%)}.red_contrasena:hover:after,.blue_contrasena:hover:after{width:60%}.red_contrasena{color:#d1326f}.red_contrasena:hover{color:#a82859}.blue_contrasena{color:#398bf7}.blue_contrasena:hover{color:#1e5fc4}.auth-wrapper-login{position:fixed;inset:0;display:grid;grid-template-columns:1.15fr .85fr;overflow:hidden;background:#060d1f}.auth-panel-left{position:relative;overflow:hidden;background:linear-gradient(145deg,#040a18,#0b1a3d 55%,#040e22);display:flex;align-items:center;justify-content:center;padding:48px 40px}.auth-panel-left:before{content:\"\";position:absolute;inset:0;background-image:radial-gradient(circle,rgba(255,255,255,.055) 1px,transparent 1px);background-size:26px 26px;z-index:1;pointer-events:none}.auth-panel-left:after{content:\"\";position:absolute;top:0;left:-120%;width:60%;height:100%;background:linear-gradient(90deg,transparent,rgba(57,139,247,.04),transparent);animation:panelSweep 7s ease-in-out infinite;z-index:1;pointer-events:none}.auth-blob{position:absolute;border-radius:50%;filter:blur(72px);z-index:0;pointer-events:none}.auth-blob-1{width:340px;height:340px;background:radial-gradient(circle,rgba(57,139,247,.45) 0%,transparent 70%);top:-90px;right:-70px;animation:blobDrift 11s ease-in-out infinite}.auth-blob-2{width:240px;height:240px;background:radial-gradient(circle,rgba(124,58,237,.4) 0%,transparent 70%);bottom:60px;left:-50px;animation:blobDrift 14s ease-in-out infinite reverse}.auth-blob-3{width:180px;height:180px;background:radial-gradient(circle,rgba(14,165,233,.35) 0%,transparent 70%);bottom:-50px;right:40px;animation:blobDrift 9s ease-in-out infinite;animation-delay:-4s}.auth-blob-4{width:120px;height:120px;background:radial-gradient(circle,rgba(209,50,111,.25) 0%,transparent 70%);top:50%;left:50%;transform:translate(-50%,-50%);animation:blobDrift 16s ease-in-out infinite;animation-delay:-8s}@keyframes blobDrift{0%,to{transform:translate(0) scale(1)}33%{transform:translate(14px,-20px) scale(1.05)}66%{transform:translate(-10px,12px) scale(.96)}}@keyframes panelSweep{0%{left:-120%}50%{left:160%}to{left:160%}}.auth-brand-panel{position:relative;z-index:2;text-align:center;color:#fff;max-width:340px}.auth-brand-logo{width:100px;height:100px;border-radius:50%;background:#ffffff0d;border:1px solid rgba(255,255,255,.1);display:flex;align-items:center;justify-content:center;margin:0 auto 28px;box-shadow:0 0 0 14px #398bf70f,0 0 50px #398bf733;backdrop-filter:blur(8px)}.auth-brand-logo img{width:64px;height:64px;object-fit:contain;filter:brightness(1.05) drop-shadow(0 0 8px rgba(57,139,247,.4))}.auth-brand-title{font-size:30px;font-weight:700;letter-spacing:-.5px;margin-bottom:10px;background:linear-gradient(135deg,#fff 20%,#93c5fd 80%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.auth-brand-subtitle{font-size:14px;color:#ffffff73;line-height:1.65;margin-bottom:40px;letter-spacing:.2px}.auth-brand-features{display:flex;flex-direction:column;gap:14px;text-align:left}.auth-brand-feature{display:flex;align-items:center;gap:12px;font-size:13px;color:#fff9}.auth-brand-feature .feat-dot{flex-shrink:0;width:7px;height:7px;border-radius:50%;background:#398bf7;box-shadow:0 0 10px #398bf7b3}.auth-brand-divider{width:60px;height:2px;background:linear-gradient(90deg,transparent,#398bf7,transparent);margin:28px auto 32px;border-radius:2px}.auth-panel-left--dev{background:linear-gradient(145deg,#18040b,#3d0b1d 55%,#220409)}.auth-panel-left--dev:after{background:linear-gradient(90deg,transparent,rgba(209,50,111,.05),transparent)}.auth-panel-left--dev .auth-blob-1{background:radial-gradient(circle,rgba(220,38,38,.52) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-2{background:radial-gradient(circle,rgba(219,39,119,.44) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-3{background:radial-gradient(circle,rgba(239,68,68,.38) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-4{background:radial-gradient(circle,rgba(249,115,22,.28) 0%,transparent 70%)}.auth-panel-left--dev .auth-brand-logo{box-shadow:0 0 0 14px #d1326f12,0 0 50px #d1326f38}.auth-panel-left--dev .auth-brand-logo img{filter:brightness(1.05) drop-shadow(0 0 8px rgba(209,50,111,.45))}.auth-panel-left--dev .auth-brand-title{background:linear-gradient(135deg,#fff 20%,#fca5a5 80%);-webkit-background-clip:text;background-clip:text}.auth-panel-left--dev .auth-brand-divider{background:linear-gradient(90deg,transparent,rgb(209,50,111),transparent)}.auth-panel-left--dev .feat-dot{background:#d1326f;box-shadow:0 0 10px #d1326fb8}.auth-panel-right{position:relative;overflow:hidden;background:var(--background-login)}.auth-panel-right:before{content:\"\";position:absolute;inset:0;background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(57,139,247,.045) 22px,rgba(57,139,247,.045) 23px);animation:authLinesMove 10s linear infinite;pointer-events:none;z-index:0}.auth-panel-right:after{content:\"\";position:absolute;top:0;bottom:0;left:-25%;width:25%;background:linear-gradient(90deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLine 7s ease-in-out infinite;animation-delay:3.5s;pointer-events:none;z-index:0}@keyframes authLinesMove{0%{transform:translate(0)}to{transform:translate(46px,46px)}}@keyframes authScanLine{0%{left:-25%}50%{left:120%}to{left:120%}}.auth-panel-bg{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:hidden}.auth-deco{position:absolute;border-radius:50%;pointer-events:none;filter:blur(70px)}.auth-deco-tl{width:300px;height:300px;top:0;left:-120px;transform:translateY(-40%);background:radial-gradient(circle,rgba(57,139,247,.12) 0%,transparent 70%);animation:authOrbPulse 6s ease-in-out infinite}.auth-deco-br{width:340px;height:340px;bottom:0;right:-120px;transform:translateY(40%);background:radial-gradient(circle,rgba(124,58,237,.1) 0%,transparent 70%);animation:authOrbPulse 8s ease-in-out infinite;animation-delay:-4s}@keyframes authOrbPulse{0%,to{opacity:.7}50%{opacity:1}}.auth-form-wrapper{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;align-items:center;z-index:1}.auth-form-wrapper>div{width:100%;max-width:420px;margin:auto;padding:36px 16px;box-sizing:border-box}.auth-panel-right--dev:before{background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(209,50,111,.05) 22px,rgba(209,50,111,.05) 23px)}.auth-panel-right--dev:after{background:linear-gradient(90deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}.auth-panel-right--dev .auth-deco-tl{background:radial-gradient(circle,rgba(209,50,111,.12) 0%,transparent 70%)}.auth-panel-right--dev .auth-deco-br{background:radial-gradient(circle,rgba(239,68,68,.1) 0%,transparent 70%)}.auth-test-badge{display:inline-flex;align-items:center;gap:7px;background:#d1326f14;border:1px solid rgba(209,50,111,.25);color:#d1326f;font-size:10.5px;font-weight:700;padding:5px 12px;border-radius:20px;margin-bottom:18px;letter-spacing:.8px}.auth-test-badge .badge-dot{width:6px;height:6px;border-radius:50%;background:#d1326f;animation:badgePulse 1.6s ease-in-out infinite;flex-shrink:0}@keyframes badgePulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.75)}}.auth-card{background:var(--background-card);border-radius:20px;padding:36px 32px 28px;box-shadow:0 4px 28px #00000014;border:1px solid var(--border-color-modal)}.auth-card-title{font-size:22px;font-weight:700;color:var(--text-color);margin-bottom:4px;letter-spacing:-.3px}.auth-card-subtitle{font-size:13px;color:var(--placeholder-color);margin-bottom:26px}.auth-field{position:relative;margin-bottom:1rem}.auth-field .auth-field-icon{position:absolute;left:13px;top:50%;transform:translateY(-50%);color:var(--placeholder-color);font-size:13px;z-index:2;pointer-events:none;transition:color .2s}.auth-field .auth-input{width:100%;padding:15px 40px 15px 37px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s,background .2s}.auth-field .auth-input::placeholder{color:transparent}.auth-field .auth-input:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721;background:var(--background-focus-input)}.auth-field .auth-input:focus~.auth-label{top:0;font-size:11px!important;color:#398bf7!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-input:focus~.auth-field-icon{color:#398bf7}.auth-field .auth-input:not(:placeholder-shown)~.auth-label{top:0;font-size:11px!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-label{position:absolute;left:35px;top:50%;transform:translateY(-50%);color:var(--placeholder-color)!important;font-size:13px!important;font-weight:400!important;pointer-events:none;transition:top .15s ease,font-size .15s ease,color .15s ease,padding .15s ease,background .15s ease;background:transparent;z-index:1;text-align:left!important}.auth-field .auth-toggle-pw{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;color:var(--placeholder-color);cursor:pointer;padding:4px 6px;font-size:13px;z-index:2;line-height:1;transition:color .2s}.auth-field .auth-toggle-pw:hover{color:#398bf7}.auth-field.has-error .auth-input{border-color:#dc3545;box-shadow:none}.auth-field.has-error .auth-field-icon{color:#dc3545}.auth-select{width:100%;padding:13px 14px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s;margin-bottom:1rem;cursor:pointer}.auth-select:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721}.auth-btn{width:100%;padding:13px;border:none;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:transform .15s ease,box-shadow .2s ease,opacity .2s;background:linear-gradient(135deg,#398bf7,#1e5fc4);color:#fff;letter-spacing:.3px;margin-bottom:10px;display:block}.auth-btn:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 5px 18px #398bf761}.auth-btn:active:not(:disabled){transform:translateY(0)}.auth-btn:disabled{opacity:.55;cursor:not-allowed}.auth-btn.auth-btn--red{background:linear-gradient(135deg,#d1326f,#a82859)}.auth-btn.auth-btn--red:hover:not(:disabled){box-shadow:0 5px 18px #d1326f61}.auth-btn.auth-btn--outline{background:transparent;border:1.5px solid var(--font-border-input);color:var(--text-color)}.auth-btn.auth-btn--outline:hover:not(:disabled){background:var(--background-btn-light-hover);box-shadow:none;transform:none}.auth-links{display:flex;flex-direction:column;align-items:center;gap:10px;margin-top:16px;padding-top:16px;border-top:1px solid var(--border-color-modal)}.auth-version{text-align:right;margin-top:14px;padding-top:12px;border-top:1px solid var(--border-color-modal)}.auth-version span{font-size:11px;color:var(--placeholder-color)}.auth-error{font-size:11.5px;color:#dc3545;margin:-6px 0 10px 2px;padding:0}.auth-hint{display:flex;align-items:flex-start;gap:6px;font-size:11.5px;color:var(--placeholder-color);margin:-6px 0 14px 2px;padding:0;line-height:1.35}.auth-hint i{margin-top:2px;flex-shrink:0}.auth-validation-list{margin:-4px 0 12px;padding:0;list-style:none}.auth-validation-list li{font-size:11.5px;color:#dc3545;padding:2px 0}.auth-validation-list li:before{content:\"\\2715 \";font-size:10px}.auth-desc{font-size:13px;color:var(--placeholder-color);margin-bottom:20px;line-height:1.65}.auth-section-title{font-size:15px;font-weight:600;color:var(--text-color);margin-bottom:20px}.font-12{font-size:12px}.form-control:focus{border-color:#0199ff9a!important;box-shadow:0 0 5px .2px #65befa44!important}@media(max-width:900px){.auth-wrapper-login{grid-template-columns:1fr;grid-template-rows:auto 1fr;overflow-y:auto;overflow-x:hidden}.auth-panel-left{padding:14px 24px;justify-content:center}.auth-panel-left .auth-brand-subtitle,.auth-panel-left .auth-brand-features,.auth-panel-left .auth-brand-divider{display:none!important}.auth-panel-left .auth-brand-panel{display:flex!important;flex-direction:row!important;align-items:center;gap:0;text-align:left;max-width:none;width:100%;justify-content:center}.auth-panel-left .auth-brand-logo{width:52px;height:52px;margin:0;flex-shrink:0}.auth-panel-left .auth-brand-logo img{width:34px;height:34px}.auth-panel-left .auth-brand-title{font-size:20px;margin-bottom:0;margin-left:.5rem;flex-shrink:1}.auth-panel-right:after{inset:-25% 0 auto;width:100%;height:25%;background:linear-gradient(180deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLineV 7s ease-in-out infinite;animation-delay:3.5s}.auth-panel-right--dev:after{background:linear-gradient(180deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}}@keyframes authScanLineV{0%{top:-25%}50%{top:120%}to{top:120%}}@media(max-width:480px){.auth-panel-left{padding:12px 16px}.auth-panel-left .auth-brand-logo{width:44px;height:44px}.auth-panel-left .auth-brand-logo img{width:28px;height:28px}.auth-panel-left .auth-brand-title{font-size:17px}.auth-form-wrapper>div{padding:20px 12px}.auth-card{padding:24px 18px 20px;border-radius:16px}.font-12{font-size:10px!important}}\n"] }]
459
+ args: [{ selector: 'lib-auth-tsi', imports: [NgClass, ReactiveFormsModule, PwaFloatingComponent, RefreshFloatingComponent, MdVerificarMfaComponent], animations: [fadeInOut], template: "<div class=\"auth-wrapper-login\">\r\n @let produccion = production();\r\n <div class=\"auth-panel-left\" [class.auth-panel-left--dev]=\"!produccion\">\r\n <span class=\"auth-blob auth-blob-1\"></span>\r\n <span class=\"auth-blob auth-blob-2\"></span>\r\n <span class=\"auth-blob auth-blob-3\"></span>\r\n <span class=\"auth-blob auth-blob-4\"></span>\r\n\r\n <div class=\"auth-brand-panel\">\r\n <div class=\"auth-brand-logo\">\r\n <img src=\"assets/images/logo-tsi-tres.png\" alt=\"TSI\" />\r\n </div>\r\n <h1 class=\"auth-brand-title\">{{module()}}</h1>\r\n <p class=\"auth-brand-subtitle\">Plataforma integrada de gesti\u00F3n<br>empresarial</p>\r\n\r\n <div class=\"auth-brand-divider\"></div>\r\n\r\n <div class=\"auth-brand-features\">\r\n @for (item of aboutList(); track $index) {\r\n <div class=\"auth-brand-feature\">\r\n <span class=\"feat-dot\"></span> {{item}}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"auth-panel-right\" [class.auth-panel-right--dev]=\"!produccion\">\r\n <div class=\"auth-panel-bg\">\r\n <span class=\"auth-deco auth-deco-tl\"></span>\r\n <span class=\"auth-deco auth-deco-br\"></span>\r\n </div>\r\n\r\n <div class=\"auth-form-wrapper\">\r\n <div>\r\n @if (!produccion) {\r\n <div>\r\n <span class=\"auth-test-badge\">\r\n <span class=\"badge-dot\"></span> ENTORNO DE PRUEBAS\r\n </span>\r\n </div>\r\n }\r\n\r\n <div class=\"auth-card\">\r\n <h2 class=\"auth-card-title\">Bienvenido de vuelta</h2>\r\n <p class=\"auth-card-subtitle\">Ingresa tus credenciales para continuar</p>\r\n\r\n <form [formGroup]=\"authForm()\" id=\"loginform\">\r\n\r\n <p class=\"auth-hint\">\r\n <i class=\"fas fa-circle-info\"></i>\r\n Si piensas instalar la app, te recomendamos completar el RUC y Usuario antes, estos quedar\u00E1n guardados y siempre aparecer\u00E1n completos al abrirla.\r\n </p>\r\n\r\n <div class=\"auth-field\" [class.has-error]=\"validacion('ruc')\">\r\n <span class=\"auth-field-icon\"><i class=\"fas fa-building\"></i></span>\r\n <input type=\"text\" formControlName=\"ruc\" class=\"auth-input\" placeholder=\" \" maxlength=\"11\"\r\n id=\"f-ruc\" autocomplete=\"off\">\r\n <label for=\"f-ruc\" class=\"auth-label\">RUC</label>\r\n </div>\r\n @if (validacion('ruc')) {\r\n <p class=\"auth-error\" @fadeInOut>Ingresar RUC</p>\r\n }\r\n\r\n <div class=\"auth-field\" [class.has-error]=\"validacion('nomuser')\">\r\n <span class=\"auth-field-icon\"><i class=\"fas fa-user\"></i></span>\r\n <input type=\"text\" formControlName=\"nomuser\" class=\"auth-input\" placeholder=\" \" id=\"f-user\"\r\n autocomplete=\"off\">\r\n <label for=\"f-user\" class=\"auth-label\">Usuario</label>\r\n </div>\r\n @if (validacion('nomuser')) {\r\n <p class=\"auth-error\" @fadeInOut>Ingresar usuario</p>\r\n }\r\n\r\n <div class=\"auth-field\" [class.has-error]=\"validacion('clave')\">\r\n <span class=\"auth-field-icon\"><i class=\"fas fa-lock\"></i></span>\r\n <input [type]=\"showPassword() ? 'text' : 'password'\" formControlName=\"clave\"\r\n class=\"auth-input\" placeholder=\" \" id=\"f-clave\" autocomplete=\"off\" autocorrect=\"off\"\r\n autocapitalize=\"off\" spellcheck=\"false\">\r\n <label for=\"f-clave\" class=\"auth-label\">Contrase\u00F1a</label>\r\n <button type=\"button\" class=\"auth-toggle-pw\" (click)=\"togglePassword()\">\r\n <i [class]=\"showPassword() ? 'fas fa-eye' : 'fas fa-eye-slash'\"></i>\r\n </button>\r\n </div>\r\n @if (validacion('clave')) {\r\n <p class=\"auth-error\" @fadeInOut>Ingresar clave</p>\r\n }\r\n\r\n <button class=\"auth-btn mt-2\" [class.auth-btn--red]=\"!produccion\" [disabled]=\"isIngresando()\"\r\n (click)=\"login()\">\r\n {{ isIngresando() ? 'Ingresando\u2026' : 'Ingresar' }}\r\n </button>\r\n\r\n <div class=\"auth-links\">\r\n <a [ngClass]=\"produccion ? 'blue_contrasena' : 'red_contrasena'\"\r\n (click)=\"recover()\">\u00BFOlvidaste tu contrase\u00F1a?</a>\r\n <a [ngClass]=\"produccion ? 'blue_contrasena' : 'red_contrasena'\"\r\n (click)=\"forget()\">\u00BFContrase\u00F1a vencida?</a>\r\n </div>\r\n\r\n </form>\r\n\r\n <div class=\"auth-version\">\r\n <span>v{{versionApp()}}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<dialog #dialogMfa class=\"auth-mfa-dialog\" (cancel)=\"$event.preventDefault()\">\r\n @if (pasoMfa(); as paso) {\r\n <lib-md-verificar-mfa [challenge]=\"paso.challenge\" (verificado)=\"onMfaVerificado()\"\r\n (cancelado)=\"onMfaCancelado()\" />\r\n }\r\n</dialog>\r\n\r\n@if (showFloatingApp()) {\r\n<app-pwa-floating [appName]=\"module()\" (beforeInstall)=\"onBeforeInstall()\" />\r\n}\r\n@if (showFloatingUpdate()) {\r\n<app-refresh-floating />\r\n}", styles: [".auth-mfa-dialog{width:min(440px,100vw - 32px);max-height:calc(100vh - 32px);padding:28px 28px 24px;border:1px solid var(--border-color-modal);border-radius:20px;background:var(--background-card);color:var(--text-color);box-shadow:0 20px 60px #0000004d}.auth-mfa-dialog::backdrop{background:#0f172a8c;backdrop-filter:blur(2px)}.auth-mfa-dialog[open]{animation:auth-mfa-entrar .26s cubic-bezier(.16,1,.3,1) both}.auth-mfa-dialog[open]::backdrop{animation:auth-mfa-fondo-entrar .26s ease-out both}.auth-mfa-dialog--cerrando[open]{animation:auth-mfa-salir .18s cubic-bezier(.4,0,1,1) both}.auth-mfa-dialog--cerrando[open]::backdrop{animation:auth-mfa-fondo-salir .18s ease-in both}@keyframes auth-mfa-entrar{0%{opacity:0;transform:translateY(16px) scale(.96)}to{opacity:1;transform:none}}@keyframes auth-mfa-salir{0%{opacity:1;transform:none}to{opacity:0;transform:translateY(8px) scale(.97)}}@keyframes auth-mfa-fondo-entrar{0%{opacity:0}to{opacity:1}}@keyframes auth-mfa-fondo-salir{0%{opacity:1}to{opacity:0}}@keyframes auth-mfa-fundido-entrar{0%{opacity:0}to{opacity:1}}@keyframes auth-mfa-fundido-salir{0%{opacity:1}to{opacity:0}}@media(prefers-reduced-motion:reduce){.auth-mfa-dialog[open]{animation:auth-mfa-fundido-entrar .12s linear both}.auth-mfa-dialog--cerrando[open]{animation:auth-mfa-fundido-salir .12s linear both}}\n", "@charset \"UTF-8\";.red_contrasena,.blue_contrasena{position:relative;display:inline-block;font-size:13px;text-decoration:none;padding-bottom:2px;transition:color .3s ease;cursor:pointer}.red_contrasena:after,.blue_contrasena:after{content:\"\";position:absolute;bottom:0;left:50%;width:0;height:1px;background-color:currentColor;transition:all .3s ease;transform:translate(-50%)}.red_contrasena:hover:after,.blue_contrasena:hover:after{width:60%}.red_contrasena{color:#d1326f}.red_contrasena:hover{color:#a82859}.blue_contrasena{color:#398bf7}.blue_contrasena:hover{color:#1e5fc4}.auth-wrapper-login{position:fixed;inset:0;display:grid;grid-template-columns:1.15fr .85fr;overflow:hidden;background:#060d1f}.auth-panel-left{position:relative;overflow:hidden;background:linear-gradient(145deg,#040a18,#0b1a3d 55%,#040e22);display:flex;align-items:center;justify-content:center;padding:48px 40px}.auth-panel-left:before{content:\"\";position:absolute;inset:0;background-image:radial-gradient(circle,rgba(255,255,255,.055) 1px,transparent 1px);background-size:26px 26px;z-index:1;pointer-events:none}.auth-panel-left:after{content:\"\";position:absolute;top:0;left:-120%;width:60%;height:100%;background:linear-gradient(90deg,transparent,rgba(57,139,247,.04),transparent);animation:panelSweep 7s ease-in-out infinite;z-index:1;pointer-events:none}.auth-blob{position:absolute;border-radius:50%;filter:blur(72px);z-index:0;pointer-events:none}.auth-blob-1{width:340px;height:340px;background:radial-gradient(circle,rgba(57,139,247,.45) 0%,transparent 70%);top:-90px;right:-70px;animation:blobDrift 11s ease-in-out infinite}.auth-blob-2{width:240px;height:240px;background:radial-gradient(circle,rgba(124,58,237,.4) 0%,transparent 70%);bottom:60px;left:-50px;animation:blobDrift 14s ease-in-out infinite reverse}.auth-blob-3{width:180px;height:180px;background:radial-gradient(circle,rgba(14,165,233,.35) 0%,transparent 70%);bottom:-50px;right:40px;animation:blobDrift 9s ease-in-out infinite;animation-delay:-4s}.auth-blob-4{width:120px;height:120px;background:radial-gradient(circle,rgba(209,50,111,.25) 0%,transparent 70%);top:50%;left:50%;transform:translate(-50%,-50%);animation:blobDrift 16s ease-in-out infinite;animation-delay:-8s}@keyframes blobDrift{0%,to{transform:translate(0) scale(1)}33%{transform:translate(14px,-20px) scale(1.05)}66%{transform:translate(-10px,12px) scale(.96)}}@keyframes panelSweep{0%{left:-120%}50%{left:160%}to{left:160%}}.auth-brand-panel{position:relative;z-index:2;text-align:center;color:#fff;max-width:340px}.auth-brand-logo{width:100px;height:100px;border-radius:50%;background:#ffffff0d;border:1px solid rgba(255,255,255,.1);display:flex;align-items:center;justify-content:center;margin:0 auto 28px;box-shadow:0 0 0 14px #398bf70f,0 0 50px #398bf733;backdrop-filter:blur(8px)}.auth-brand-logo img{width:64px;height:64px;object-fit:contain;filter:brightness(1.05) drop-shadow(0 0 8px rgba(57,139,247,.4))}.auth-brand-title{font-size:30px;font-weight:700;letter-spacing:-.5px;margin-bottom:10px;background:linear-gradient(135deg,#fff 20%,#93c5fd 80%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.auth-brand-subtitle{font-size:14px;color:#ffffff73;line-height:1.65;margin-bottom:40px;letter-spacing:.2px}.auth-brand-features{display:flex;flex-direction:column;gap:14px;text-align:left}.auth-brand-feature{display:flex;align-items:center;gap:12px;font-size:13px;color:#fff9}.auth-brand-feature .feat-dot{flex-shrink:0;width:7px;height:7px;border-radius:50%;background:#398bf7;box-shadow:0 0 10px #398bf7b3}.auth-brand-divider{width:60px;height:2px;background:linear-gradient(90deg,transparent,#398bf7,transparent);margin:28px auto 32px;border-radius:2px}.auth-panel-left--dev{background:linear-gradient(145deg,#18040b,#3d0b1d 55%,#220409)}.auth-panel-left--dev:after{background:linear-gradient(90deg,transparent,rgba(209,50,111,.05),transparent)}.auth-panel-left--dev .auth-blob-1{background:radial-gradient(circle,rgba(220,38,38,.52) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-2{background:radial-gradient(circle,rgba(219,39,119,.44) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-3{background:radial-gradient(circle,rgba(239,68,68,.38) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-4{background:radial-gradient(circle,rgba(249,115,22,.28) 0%,transparent 70%)}.auth-panel-left--dev .auth-brand-logo{box-shadow:0 0 0 14px #d1326f12,0 0 50px #d1326f38}.auth-panel-left--dev .auth-brand-logo img{filter:brightness(1.05) drop-shadow(0 0 8px rgba(209,50,111,.45))}.auth-panel-left--dev .auth-brand-title{background:linear-gradient(135deg,#fff 20%,#fca5a5 80%);-webkit-background-clip:text;background-clip:text}.auth-panel-left--dev .auth-brand-divider{background:linear-gradient(90deg,transparent,rgb(209,50,111),transparent)}.auth-panel-left--dev .feat-dot{background:#d1326f;box-shadow:0 0 10px #d1326fb8}.auth-panel-right{position:relative;overflow:hidden;background:var(--background-login)}.auth-panel-right:before{content:\"\";position:absolute;inset:0;background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(57,139,247,.045) 22px,rgba(57,139,247,.045) 23px);animation:authLinesMove 10s linear infinite;pointer-events:none;z-index:0}.auth-panel-right:after{content:\"\";position:absolute;top:0;bottom:0;left:-25%;width:25%;background:linear-gradient(90deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLine 7s ease-in-out infinite;animation-delay:3.5s;pointer-events:none;z-index:0}@keyframes authLinesMove{0%{transform:translate(0)}to{transform:translate(46px,46px)}}@keyframes authScanLine{0%{left:-25%}50%{left:120%}to{left:120%}}.auth-panel-bg{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:hidden}.auth-deco{position:absolute;border-radius:50%;pointer-events:none;filter:blur(70px)}.auth-deco-tl{width:300px;height:300px;top:0;left:-120px;transform:translateY(-40%);background:radial-gradient(circle,rgba(57,139,247,.12) 0%,transparent 70%);animation:authOrbPulse 6s ease-in-out infinite}.auth-deco-br{width:340px;height:340px;bottom:0;right:-120px;transform:translateY(40%);background:radial-gradient(circle,rgba(124,58,237,.1) 0%,transparent 70%);animation:authOrbPulse 8s ease-in-out infinite;animation-delay:-4s}@keyframes authOrbPulse{0%,to{opacity:.7}50%{opacity:1}}.auth-form-wrapper{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;align-items:center;z-index:1}.auth-form-wrapper>div{width:100%;max-width:420px;margin:auto;padding:36px 16px;box-sizing:border-box}.auth-panel-right--dev:before{background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(209,50,111,.05) 22px,rgba(209,50,111,.05) 23px)}.auth-panel-right--dev:after{background:linear-gradient(90deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}.auth-panel-right--dev .auth-deco-tl{background:radial-gradient(circle,rgba(209,50,111,.12) 0%,transparent 70%)}.auth-panel-right--dev .auth-deco-br{background:radial-gradient(circle,rgba(239,68,68,.1) 0%,transparent 70%)}.auth-test-badge{display:inline-flex;align-items:center;gap:7px;background:#d1326f14;border:1px solid rgba(209,50,111,.25);color:#d1326f;font-size:10.5px;font-weight:700;padding:5px 12px;border-radius:20px;margin-bottom:18px;letter-spacing:.8px}.auth-test-badge .badge-dot{width:6px;height:6px;border-radius:50%;background:#d1326f;animation:badgePulse 1.6s ease-in-out infinite;flex-shrink:0}@keyframes badgePulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.75)}}.auth-card{background:var(--background-card);border-radius:20px;padding:36px 32px 28px;box-shadow:0 4px 28px #00000014;border:1px solid var(--border-color-modal)}.auth-card-title{font-size:22px;font-weight:700;color:var(--text-color);margin-bottom:4px;letter-spacing:-.3px}.auth-card-subtitle{font-size:13px;color:var(--placeholder-color);margin-bottom:26px}.auth-field{position:relative;margin-bottom:1rem}.auth-field .auth-field-icon{position:absolute;left:13px;top:50%;transform:translateY(-50%);color:var(--placeholder-color);font-size:13px;z-index:2;pointer-events:none;transition:color .2s}.auth-field .auth-input{width:100%;padding:15px 40px 15px 37px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s,background .2s}.auth-field .auth-input::placeholder{color:transparent}.auth-field .auth-input:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721;background:var(--background-focus-input)}.auth-field .auth-input:focus~.auth-label{top:0;font-size:11px!important;color:#398bf7!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-input:focus~.auth-field-icon{color:#398bf7}.auth-field .auth-input:not(:placeholder-shown)~.auth-label{top:0;font-size:11px!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-label{position:absolute;left:35px;top:50%;transform:translateY(-50%);color:var(--placeholder-color)!important;font-size:13px!important;font-weight:400!important;pointer-events:none;transition:top .15s ease,font-size .15s ease,color .15s ease,padding .15s ease,background .15s ease;background:transparent;z-index:1;text-align:left!important}.auth-field .auth-toggle-pw{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;color:var(--placeholder-color);cursor:pointer;padding:4px 6px;font-size:13px;z-index:2;line-height:1;transition:color .2s}.auth-field .auth-toggle-pw:hover{color:#398bf7}.auth-field.has-error .auth-input{border-color:#dc3545;box-shadow:none}.auth-field.has-error .auth-field-icon{color:#dc3545}.auth-select{width:100%;padding:13px 14px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s;margin-bottom:1rem;cursor:pointer}.auth-select:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721}.auth-btn{width:100%;padding:13px;border:none;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:transform .15s ease,box-shadow .2s ease,opacity .2s;background:linear-gradient(135deg,#398bf7,#1e5fc4);color:#fff;letter-spacing:.3px;margin-bottom:10px;display:block}.auth-btn:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 5px 18px #398bf761}.auth-btn:active:not(:disabled){transform:translateY(0)}.auth-btn:disabled{opacity:.55;cursor:not-allowed}.auth-btn.auth-btn--red{background:linear-gradient(135deg,#d1326f,#a82859)}.auth-btn.auth-btn--red:hover:not(:disabled){box-shadow:0 5px 18px #d1326f61}.auth-btn.auth-btn--outline{background:transparent;border:1.5px solid var(--font-border-input);color:var(--text-color)}.auth-btn.auth-btn--outline:hover:not(:disabled){background:var(--background-btn-light-hover);box-shadow:none;transform:none}.auth-links{display:flex;flex-direction:column;align-items:center;gap:10px;margin-top:16px;padding-top:16px;border-top:1px solid var(--border-color-modal)}.auth-version{text-align:right;margin-top:14px;padding-top:12px;border-top:1px solid var(--border-color-modal)}.auth-version span{font-size:11px;color:var(--placeholder-color)}.auth-error{font-size:11.5px;color:#dc3545;margin:-6px 0 10px 2px;padding:0}.auth-hint{display:flex;align-items:flex-start;gap:6px;font-size:11.5px;color:var(--placeholder-color);margin:-6px 0 14px 2px;padding:0;line-height:1.35}.auth-hint i{margin-top:2px;flex-shrink:0}.auth-validation-list{margin:-4px 0 12px;padding:0;list-style:none}.auth-validation-list li{font-size:11.5px;color:#dc3545;padding:2px 0}.auth-validation-list li:before{content:\"\\2715 \";font-size:10px}.auth-desc{font-size:13px;color:var(--placeholder-color);margin-bottom:20px;line-height:1.65}.auth-section-title{font-size:15px;font-weight:600;color:var(--text-color);margin-bottom:20px}.font-12{font-size:12px}.form-control:focus{border-color:#0199ff9a!important;box-shadow:0 0 5px .2px #65befa44!important}@media(max-width:900px){.auth-wrapper-login{grid-template-columns:1fr;grid-template-rows:auto 1fr;overflow-y:auto;overflow-x:hidden}.auth-panel-left{padding:14px 24px;justify-content:center}.auth-panel-left .auth-brand-subtitle,.auth-panel-left .auth-brand-features,.auth-panel-left .auth-brand-divider{display:none!important}.auth-panel-left .auth-brand-panel{display:flex!important;flex-direction:row!important;align-items:center;gap:0;text-align:left;max-width:none;width:100%;justify-content:center}.auth-panel-left .auth-brand-logo{width:52px;height:52px;margin:0;flex-shrink:0}.auth-panel-left .auth-brand-logo img{width:34px;height:34px}.auth-panel-left .auth-brand-title{font-size:20px;margin-bottom:0;margin-left:.5rem;flex-shrink:1}.auth-panel-right:after{inset:-25% 0 auto;width:100%;height:25%;background:linear-gradient(180deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLineV 7s ease-in-out infinite;animation-delay:3.5s}.auth-panel-right--dev:after{background:linear-gradient(180deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}}@keyframes authScanLineV{0%{top:-25%}50%{top:120%}to{top:120%}}@media(max-width:480px){.auth-panel-left{padding:12px 16px}.auth-panel-left .auth-brand-logo{width:44px;height:44px}.auth-panel-left .auth-brand-logo img{width:28px;height:28px}.auth-panel-left .auth-brand-title{font-size:17px}.auth-form-wrapper>div{padding:20px 12px}.auth-card{padding:24px 18px 20px;border-radius:16px}.font-12{font-size:10px!important}}\n"] }]
179
460
  }] });
180
461
 
181
462
  class ExpiredPasswordComponent {
@@ -319,201 +600,6 @@ class AuthSender {
319
600
  codsuc;
320
601
  }
321
602
 
322
- const MFA_API = new InjectionToken('MFA_API');
323
- function provideMfaApi(factory) {
324
- return { provide: MFA_API, useFactory: factory };
325
- }
326
- function isMfaChallenge(body) {
327
- return body?.mfaRequerido === true && !!body?.preauthToken;
328
- }
329
- function isPushPendiente(body) {
330
- return body?.result === 'waiting' || body?.result === 'deny' || body?.result === 'expired';
331
- }
332
-
333
- const INTERVALO_ESTADO_MS = 2000;
334
- const MAXIMO_ESPERA_MS = 120000;
335
- const CAMPOS_CODIGO = {
336
- totp: {
337
- label: 'Código de verificación', placeholder: '000000', icon: 'fa-mobile-alt', inputmode: 'numeric',
338
- patron: /^\d{6}$/,
339
- descri: 'Ingresa el código de 6 dígitos que muestra tu app de autenticación.',
340
- mensajeInvalido: 'Ingresa el código de 6 dígitos de tu app.',
341
- mensajeIncorrecto: 'Código incorrecto. Verifica la hora de tu dispositivo.'
342
- },
343
- respaldo: {
344
- label: 'Código de respaldo', placeholder: 'XXXX-XXXX', icon: 'fa-key', inputmode: 'text',
345
- patron: /^[A-Z0-9]{4}-[A-Z0-9]{4}$/,
346
- descri: 'Ingresa uno de tus códigos de respaldo. Cada código sirve una sola vez.',
347
- mensajeInvalido: 'Ingresa un código de respaldo válido (XXXX-XXXX).',
348
- mensajeIncorrecto: 'Código de respaldo incorrecto o ya utilizado.'
349
- }
350
- };
351
- const limpiarCodigo = (valor, tipo) => {
352
- if (tipo == 'totp')
353
- return valor.replace(/\D/g, '').slice(0, 6);
354
- const base = valor.toUpperCase().replace(/[^A-Z0-9]/g, '').slice(0, 8);
355
- return base.length > 4 ? `${base.slice(0, 4)}-${base.slice(4)}` : base;
356
- };
357
- const mensajeDe = (err, defecto) => typeof err == 'string' && err ? err : defecto;
358
- const esperar = (ms, signal) => new Promise(resolve => {
359
- const id = setTimeout(resolve, ms);
360
- signal.addEventListener('abort', () => { clearTimeout(id); resolve(); }, { once: true });
361
- });
362
- class MdVerificarMfaComponent {
363
- api = inject(MFA_API);
364
- challenge = input.required();
365
- titulo = input('Verificación en dos pasos');
366
- showCancelar = input(true);
367
- verificado = output();
368
- cancelado = output();
369
- tienePush = computed(() => (this.challenge().tipos ?? []).includes('PUSH'));
370
- tieneTotp = computed(() => {
371
- const tipos = this.challenge().tipos ?? [];
372
- return tipos.length == 0 || tipos.includes('TOTP');
373
- });
374
- modo = signal('codigo');
375
- tipoCodigo = signal('totp');
376
- campo = computed(() => CAMPOS_CODIGO[this.tipoCodigo()]);
377
- codigo = signal('');
378
- codigoError = signal('');
379
- isEnviando = signal(false);
380
- estadoPush = signal('idle');
381
- isPushEnCurso = computed(() => this.estadoPush() == 'enviando' || this.estadoPush() == 'esperando');
382
- pushError = signal('');
383
- inputCodigo = viewChild('inputCodigo');
384
- pushCtrl;
385
- constructor() {
386
- inject(DestroyRef).onDestroy(() => this.cancelarPush());
387
- effect(() => {
388
- this.challenge();
389
- untracked(() => this.iniciar());
390
- });
391
- afterRenderEffect(() => {
392
- if (this.modo() != 'codigo' || this.isEnviando())
393
- return;
394
- this.tipoCodigo();
395
- this.codigoError();
396
- this.inputCodigo()?.nativeElement.focus();
397
- });
398
- }
399
- iniciar() {
400
- this.cancelarPush();
401
- this.pushError.set('');
402
- if (this.tienePush() && !this.tieneTotp()) {
403
- this.usarPush();
404
- return;
405
- }
406
- this.usarCodigo('totp');
407
- }
408
- onCodigoInput(event) {
409
- const input = event.target;
410
- const limpio = limpiarCodigo(input.value, this.tipoCodigo());
411
- input.value = limpio;
412
- this.codigo.set(limpio);
413
- if (this.codigoError())
414
- this.codigoError.set('');
415
- }
416
- usarCodigo(tipo) {
417
- this.cancelarPush();
418
- this.modo.set('codigo');
419
- this.tipoCodigo.set(tipo);
420
- this.codigo.set('');
421
- this.codigoError.set('');
422
- }
423
- async verificar() {
424
- if (this.modo() == 'push' || this.isEnviando())
425
- return;
426
- const campo = this.campo();
427
- if (!campo.patron.test(this.codigo())) {
428
- this.codigoError.set(campo.mensajeInvalido);
429
- return;
430
- }
431
- this.isEnviando.set(true);
432
- this.codigoError.set('');
433
- try {
434
- await this.api.verificarCodigo({ preauthToken: this.challenge().preauthToken, codigo: this.codigo() });
435
- this.verificado.emit();
436
- }
437
- catch (err) {
438
- this.codigo.set('');
439
- this.codigoError.set(mensajeDe(err, campo.mensajeIncorrecto));
440
- }
441
- finally {
442
- this.isEnviando.set(false);
443
- }
444
- }
445
- usarPush() {
446
- this.modo.set('push');
447
- this.codigoError.set('');
448
- this.enviarPush();
449
- }
450
- async enviarPush() {
451
- this.cancelarPush();
452
- const ctrl = new AbortController();
453
- this.pushCtrl = ctrl;
454
- this.pushError.set('');
455
- this.estadoPush.set('enviando');
456
- const preauthToken = this.challenge().preauthToken;
457
- try {
458
- const solicitudId = await this.api.enviarPush(preauthToken);
459
- if (ctrl.signal.aborted)
460
- return;
461
- this.estadoPush.set('esperando');
462
- const limite = Date.now() + MAXIMO_ESPERA_MS;
463
- while (Date.now() < limite) {
464
- const estado = await this.api.estadoPush({ preauthToken, solicitudId });
465
- if (ctrl.signal.aborted)
466
- return;
467
- if (estado != 'waiting') {
468
- this.resolverPush(estado);
469
- return;
470
- }
471
- await esperar(INTERVALO_ESTADO_MS, ctrl.signal);
472
- if (ctrl.signal.aborted)
473
- return;
474
- }
475
- this.estadoPush.set('expirado');
476
- this.pushError.set('No respondiste a tiempo la notificación. Vuelve a enviarla.');
477
- }
478
- catch (err) {
479
- if (ctrl.signal.aborted)
480
- return;
481
- this.estadoPush.set('idle');
482
- this.pushError.set(mensajeDe(err, 'No se pudo enviar la notificación.'));
483
- }
484
- }
485
- cancelar() {
486
- this.cancelarPush();
487
- this.cancelado.emit();
488
- }
489
- resolverPush(estado) {
490
- if (estado == 'aprobado') {
491
- this.estadoPush.set('idle');
492
- this.verificado.emit();
493
- return;
494
- }
495
- if (estado == 'expired') {
496
- this.estadoPush.set('expirado');
497
- this.pushError.set('La solicitud expiró. Vuelve a enviarla.');
498
- return;
499
- }
500
- this.estadoPush.set('rechazado');
501
- this.pushError.set('Rechazaste la notificación en tu teléfono.');
502
- }
503
- cancelarPush() {
504
- this.pushCtrl?.abort();
505
- this.pushCtrl = undefined;
506
- if (this.isPushEnCurso())
507
- this.estadoPush.set('idle');
508
- }
509
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: MdVerificarMfaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
510
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: MdVerificarMfaComponent, isStandalone: true, selector: "lib-md-verificar-mfa", inputs: { challenge: { classPropertyName: "challenge", publicName: "challenge", isSignal: true, isRequired: true, transformFunction: null }, titulo: { classPropertyName: "titulo", publicName: "titulo", isSignal: true, isRequired: false, transformFunction: null }, showCancelar: { classPropertyName: "showCancelar", publicName: "showCancelar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { verificado: "verificado", cancelado: "cancelado" }, viewQueries: [{ propertyName: "inputCodigo", first: true, predicate: ["inputCodigo"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"verificar-mfa\">\n <div class=\"auth-card-title mb-3\">{{ titulo() }}</div>\n\n <div class=\"d-flex align-items-center gap-3 mb-3\">\n <span class=\"verificar-mfa__icono\"><i class=\"fas fa-user-shield\"></i></span>\n <div>\n <div class=\"fw-semibold\">{{ challenge().coduser }}</div>\n @if (challenge().empresa) {\n <div class=\"verificar-mfa__muted\">{{ challenge().empresa }}</div>\n }\n </div>\n </div>\n\n @if (modo() == 'push') {\n @switch (estadoPush()) {\n @case ('enviando') {\n <div class=\"duo-push\">\n <span class=\"spinner-border spinner-border-sm text-primary\"></span>\n <div class=\"flex-grow-1\">Enviando notificaci\u00F3n a tu tel\u00E9fono\u2026</div>\n </div>\n }\n @case ('esperando') {\n <div class=\"duo-push duo-push--esperando\">\n <span class=\"duo-push__icono duo-push__icono--pulso\"><i class=\"fas fa-mobile-alt\"></i></span>\n <div class=\"flex-grow-1\">\n <div class=\"fw-semibold\">Revisa tu tel\u00E9fono</div>\n <div class=\"verificar-mfa__muted\">Aprueba la notificaci\u00F3n en TSI Autenticador para ingresar.</div>\n </div>\n </div>\n }\n @default {\n <div class=\"duo-push\">\n <span class=\"duo-push__icono\"><i class=\"fas fa-bell\"></i></span>\n <div class=\"flex-grow-1\">\n <div class=\"fw-semibold\">TSI Autenticador</div>\n <div class=\"verificar-mfa__muted\">Te enviaremos una notificaci\u00F3n para que la apruebes.</div>\n </div>\n </div>\n }\n }\n @if (pushError() && !isPushEnCurso()) {\n <div class=\"codigo-field__error\"><i class=\"fas fa-exclamation-circle\"></i> {{ pushError() }}</div>\n }\n\n <div class=\"verificar-mfa__opciones\">\n @if (tieneTotp()) {\n <button type=\"button\" class=\"verificar-mfa__link\" (click)=\"usarCodigo('totp')\">\n Usar c\u00F3digo de mi app de autenticaci\u00F3n\n </button>\n }\n <button type=\"button\" class=\"verificar-mfa__link verificar-mfa__link--secundario\"\n (click)=\"usarCodigo('respaldo')\">\n \u00BFNo tienes tu tel\u00E9fono? Usa un c\u00F3digo de respaldo\n </button>\n </div>\n } @else {\n <p class=\"verificar-mfa__muted mb-4\">\n @if (tipoCodigo() == 'totp') {\n {{ challenge().mensaje || campo().descri }}\n } @else {\n {{ campo().descri }}\n }\n </p>\n\n <div class=\"codigo-field\" [class.has-error]=\"codigoError()\">\n <span class=\"codigo-field__icon\"><i class=\"fas\" [class]=\"campo().icon\"></i></span>\n <input #inputCodigo id=\"mfa-codigo\" class=\"codigo-field__input\" type=\"text\"\n [placeholder]=\"campo().placeholder\" [value]=\"codigo()\" (input)=\"onCodigoInput($event)\"\n (keydown.enter)=\"verificar()\" [attr.inputmode]=\"campo().inputmode\" autocomplete=\"one-time-code\"\n autocorrect=\"off\" autocapitalize=\"characters\" spellcheck=\"false\" [disabled]=\"isEnviando()\">\n <label for=\"mfa-codigo\" class=\"codigo-field__label\">{{ campo().label }}</label>\n </div>\n @if (codigoError()) {\n <div class=\"codigo-field__error\"><i class=\"fas fa-exclamation-circle\"></i> {{ codigoError() }}</div>\n }\n\n <div class=\"verificar-mfa__opciones\">\n @if (tienePush()) {\n <button type=\"button\" class=\"verificar-mfa__link\" (click)=\"usarPush()\">\n <i class=\"fas fa-bell me-1\"></i>Mejor env\u00EDame una notificaci\u00F3n push\n </button>\n }\n @if (tieneTotp() && tipoCodigo() != 'totp') {\n <button type=\"button\" class=\"verificar-mfa__link\" (click)=\"usarCodigo('totp')\">\n Usar c\u00F3digo de mi app de autenticaci\u00F3n\n </button>\n }\n @if (tipoCodigo() != 'respaldo') {\n <button type=\"button\" class=\"verificar-mfa__link verificar-mfa__link--secundario\"\n (click)=\"usarCodigo('respaldo')\">\n \u00BFNo tienes tu tel\u00E9fono? Usa un c\u00F3digo de respaldo\n </button>\n }\n </div>\n }\n\n <div class=\"verificar-mfa__acciones\">\n @if (modo() == 'push') {\n <button type=\"button\" class=\"auth-btn\" [disabled]=\"isPushEnCurso()\" (click)=\"enviarPush()\">\n <i class=\"fas fa-paper-plane me-1\"></i>\n {{ isPushEnCurso() ? 'Esperando aprobaci\u00F3n\u2026' : 'Reenviar notificaci\u00F3n' }}\n </button>\n } @else {\n <button type=\"button\" class=\"auth-btn\" [disabled]=\"isEnviando()\" (click)=\"verificar()\">\n <i class=\"fas fa-check me-1\"></i>\n {{ isEnviando() ? 'Verificando\u2026' : 'Verificar' }}\n </button>\n }\n @if (showCancelar()) {\n <button type=\"button\" class=\"auth-btn auth-btn--outline\" (click)=\"cancelar()\">Cancelar</button>\n }\n </div>\n</div>\n", styles: [".verificar-mfa{color:var(--text-color)}.verificar-mfa__icono{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:44px;height:44px;border-radius:12px;color:var(--bs-primary);background:rgba(var(--bs-primary-rgb),.1);font-size:20px}.verificar-mfa__muted{font-size:13px;line-height:1.5;color:var(--bs-secondary-color)}.verificar-mfa__link:hover{text-decoration:underline}.verificar-mfa__link{padding:0;border:0;background:none;font-size:13px;font-weight:600;color:var(--bs-primary)}.codigo-field{position:relative}.codigo-field__icon{position:absolute;left:14px;top:50%;transform:translateY(-50%);z-index:2;font-size:15px;color:var(--placeholder-color);pointer-events:none;transition:color .2s}.codigo-field__input{width:100%;height:56px;padding:0 44px;border:1.5px solid var(--font-border-input);border-radius:10px;outline:none;background:var(--background-input);color:var(--color-input);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:22px;font-weight:600;letter-spacing:.45em;text-align:center;transition:border-color .2s,box-shadow .2s,background .2s}.codigo-field__input::placeholder{color:var(--placeholder-color);opacity:.45}.codigo-field__input:focus{border-color:var(--bs-primary);box-shadow:0 0 0 3.5px rgba(var(--bs-primary-rgb),.15);background:var(--background-focus-input)}.codigo-field__input:disabled{opacity:.7}.codigo-field__label{position:absolute;left:12px;top:0;transform:translateY(-50%);z-index:1;margin:0!important;padding:0 4px;font-size:11px!important;font-weight:500!important;line-height:1.2;color:var(--placeholder-color);background:var(--background-card);pointer-events:none;transition:color .15s ease}.codigo-field:focus-within .codigo-field__label,.codigo-field:focus-within .codigo-field__icon{color:var(--bs-primary)}.codigo-field.has-error .codigo-field__input{border-color:var(--bs-danger);box-shadow:0 0 0 3.5px rgba(var(--bs-danger-rgb),.12)}.codigo-field.has-error .codigo-field__icon,.codigo-field.has-error .codigo-field__label{color:var(--bs-danger)}.codigo-field__error{display:flex;align-items:center;gap:6px;margin-top:8px;font-size:13px;font-weight:500;color:var(--bs-danger)}.duo-push{display:flex;align-items:center;gap:12px;padding:14px;border:1.5px solid var(--font-border-input);border-radius:10px;background:var(--background-input);color:var(--text-color);font-size:14px}.duo-push--esperando{border-color:rgba(var(--bs-primary-rgb),.45);background:rgba(var(--bs-primary-rgb),.06)}.duo-push__icono{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;color:var(--bs-primary);background:rgba(var(--bs-primary-rgb),.1);font-size:18px}.duo-push__icono--pulso{animation:duo-pulso 1.4s ease-in-out infinite}@keyframes duo-pulso{0%,to{box-shadow:0 0 rgba(var(--bs-primary-rgb),.35)}50%{box-shadow:0 0 0 8px rgba(var(--bs-primary-rgb),0)}}@media(prefers-reduced-motion:reduce){.duo-push__icono--pulso{animation:none}}.verificar-mfa__opciones{display:flex;flex-direction:column;align-items:flex-start;gap:8px;margin-top:16px}.verificar-mfa__link--secundario{font-weight:500;color:var(--bs-secondary-color)}.verificar-mfa__acciones{margin-top:24px}\n", "@charset \"UTF-8\";.red_contrasena,.blue_contrasena{position:relative;display:inline-block;font-size:13px;text-decoration:none;padding-bottom:2px;transition:color .3s ease;cursor:pointer}.red_contrasena:after,.blue_contrasena:after{content:\"\";position:absolute;bottom:0;left:50%;width:0;height:1px;background-color:currentColor;transition:all .3s ease;transform:translate(-50%)}.red_contrasena:hover:after,.blue_contrasena:hover:after{width:60%}.red_contrasena{color:#d1326f}.red_contrasena:hover{color:#a82859}.blue_contrasena{color:#398bf7}.blue_contrasena:hover{color:#1e5fc4}.auth-wrapper-login{position:fixed;inset:0;display:grid;grid-template-columns:1.15fr .85fr;overflow:hidden;background:#060d1f}.auth-panel-left{position:relative;overflow:hidden;background:linear-gradient(145deg,#040a18,#0b1a3d 55%,#040e22);display:flex;align-items:center;justify-content:center;padding:48px 40px}.auth-panel-left:before{content:\"\";position:absolute;inset:0;background-image:radial-gradient(circle,rgba(255,255,255,.055) 1px,transparent 1px);background-size:26px 26px;z-index:1;pointer-events:none}.auth-panel-left:after{content:\"\";position:absolute;top:0;left:-120%;width:60%;height:100%;background:linear-gradient(90deg,transparent,rgba(57,139,247,.04),transparent);animation:panelSweep 7s ease-in-out infinite;z-index:1;pointer-events:none}.auth-blob{position:absolute;border-radius:50%;filter:blur(72px);z-index:0;pointer-events:none}.auth-blob-1{width:340px;height:340px;background:radial-gradient(circle,rgba(57,139,247,.45) 0%,transparent 70%);top:-90px;right:-70px;animation:blobDrift 11s ease-in-out infinite}.auth-blob-2{width:240px;height:240px;background:radial-gradient(circle,rgba(124,58,237,.4) 0%,transparent 70%);bottom:60px;left:-50px;animation:blobDrift 14s ease-in-out infinite reverse}.auth-blob-3{width:180px;height:180px;background:radial-gradient(circle,rgba(14,165,233,.35) 0%,transparent 70%);bottom:-50px;right:40px;animation:blobDrift 9s ease-in-out infinite;animation-delay:-4s}.auth-blob-4{width:120px;height:120px;background:radial-gradient(circle,rgba(209,50,111,.25) 0%,transparent 70%);top:50%;left:50%;transform:translate(-50%,-50%);animation:blobDrift 16s ease-in-out infinite;animation-delay:-8s}@keyframes blobDrift{0%,to{transform:translate(0) scale(1)}33%{transform:translate(14px,-20px) scale(1.05)}66%{transform:translate(-10px,12px) scale(.96)}}@keyframes panelSweep{0%{left:-120%}50%{left:160%}to{left:160%}}.auth-brand-panel{position:relative;z-index:2;text-align:center;color:#fff;max-width:340px}.auth-brand-logo{width:100px;height:100px;border-radius:50%;background:#ffffff0d;border:1px solid rgba(255,255,255,.1);display:flex;align-items:center;justify-content:center;margin:0 auto 28px;box-shadow:0 0 0 14px #398bf70f,0 0 50px #398bf733;backdrop-filter:blur(8px)}.auth-brand-logo img{width:64px;height:64px;object-fit:contain;filter:brightness(1.05) drop-shadow(0 0 8px rgba(57,139,247,.4))}.auth-brand-title{font-size:30px;font-weight:700;letter-spacing:-.5px;margin-bottom:10px;background:linear-gradient(135deg,#fff 20%,#93c5fd 80%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.auth-brand-subtitle{font-size:14px;color:#ffffff73;line-height:1.65;margin-bottom:40px;letter-spacing:.2px}.auth-brand-features{display:flex;flex-direction:column;gap:14px;text-align:left}.auth-brand-feature{display:flex;align-items:center;gap:12px;font-size:13px;color:#fff9}.auth-brand-feature .feat-dot{flex-shrink:0;width:7px;height:7px;border-radius:50%;background:#398bf7;box-shadow:0 0 10px #398bf7b3}.auth-brand-divider{width:60px;height:2px;background:linear-gradient(90deg,transparent,#398bf7,transparent);margin:28px auto 32px;border-radius:2px}.auth-panel-left--dev{background:linear-gradient(145deg,#18040b,#3d0b1d 55%,#220409)}.auth-panel-left--dev:after{background:linear-gradient(90deg,transparent,rgba(209,50,111,.05),transparent)}.auth-panel-left--dev .auth-blob-1{background:radial-gradient(circle,rgba(220,38,38,.52) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-2{background:radial-gradient(circle,rgba(219,39,119,.44) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-3{background:radial-gradient(circle,rgba(239,68,68,.38) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-4{background:radial-gradient(circle,rgba(249,115,22,.28) 0%,transparent 70%)}.auth-panel-left--dev .auth-brand-logo{box-shadow:0 0 0 14px #d1326f12,0 0 50px #d1326f38}.auth-panel-left--dev .auth-brand-logo img{filter:brightness(1.05) drop-shadow(0 0 8px rgba(209,50,111,.45))}.auth-panel-left--dev .auth-brand-title{background:linear-gradient(135deg,#fff 20%,#fca5a5 80%);-webkit-background-clip:text;background-clip:text}.auth-panel-left--dev .auth-brand-divider{background:linear-gradient(90deg,transparent,rgb(209,50,111),transparent)}.auth-panel-left--dev .feat-dot{background:#d1326f;box-shadow:0 0 10px #d1326fb8}.auth-panel-right{position:relative;overflow:hidden;background:var(--background-login)}.auth-panel-right:before{content:\"\";position:absolute;inset:0;background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(57,139,247,.045) 22px,rgba(57,139,247,.045) 23px);animation:authLinesMove 10s linear infinite;pointer-events:none;z-index:0}.auth-panel-right:after{content:\"\";position:absolute;top:0;bottom:0;left:-25%;width:25%;background:linear-gradient(90deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLine 7s ease-in-out infinite;animation-delay:3.5s;pointer-events:none;z-index:0}@keyframes authLinesMove{0%{transform:translate(0)}to{transform:translate(46px,46px)}}@keyframes authScanLine{0%{left:-25%}50%{left:120%}to{left:120%}}.auth-panel-bg{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:hidden}.auth-deco{position:absolute;border-radius:50%;pointer-events:none;filter:blur(70px)}.auth-deco-tl{width:300px;height:300px;top:0;left:-120px;transform:translateY(-40%);background:radial-gradient(circle,rgba(57,139,247,.12) 0%,transparent 70%);animation:authOrbPulse 6s ease-in-out infinite}.auth-deco-br{width:340px;height:340px;bottom:0;right:-120px;transform:translateY(40%);background:radial-gradient(circle,rgba(124,58,237,.1) 0%,transparent 70%);animation:authOrbPulse 8s ease-in-out infinite;animation-delay:-4s}@keyframes authOrbPulse{0%,to{opacity:.7}50%{opacity:1}}.auth-form-wrapper{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;align-items:center;z-index:1}.auth-form-wrapper>div{width:100%;max-width:420px;margin:auto;padding:36px 16px;box-sizing:border-box}.auth-panel-right--dev:before{background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(209,50,111,.05) 22px,rgba(209,50,111,.05) 23px)}.auth-panel-right--dev:after{background:linear-gradient(90deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}.auth-panel-right--dev .auth-deco-tl{background:radial-gradient(circle,rgba(209,50,111,.12) 0%,transparent 70%)}.auth-panel-right--dev .auth-deco-br{background:radial-gradient(circle,rgba(239,68,68,.1) 0%,transparent 70%)}.auth-test-badge{display:inline-flex;align-items:center;gap:7px;background:#d1326f14;border:1px solid rgba(209,50,111,.25);color:#d1326f;font-size:10.5px;font-weight:700;padding:5px 12px;border-radius:20px;margin-bottom:18px;letter-spacing:.8px}.auth-test-badge .badge-dot{width:6px;height:6px;border-radius:50%;background:#d1326f;animation:badgePulse 1.6s ease-in-out infinite;flex-shrink:0}@keyframes badgePulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.75)}}.auth-card{background:var(--background-card);border-radius:20px;padding:36px 32px 28px;box-shadow:0 4px 28px #00000014;border:1px solid var(--border-color-modal)}.auth-card-title{font-size:22px;font-weight:700;color:var(--text-color);margin-bottom:4px;letter-spacing:-.3px}.auth-card-subtitle{font-size:13px;color:var(--placeholder-color);margin-bottom:26px}.auth-field{position:relative;margin-bottom:1rem}.auth-field .auth-field-icon{position:absolute;left:13px;top:50%;transform:translateY(-50%);color:var(--placeholder-color);font-size:13px;z-index:2;pointer-events:none;transition:color .2s}.auth-field .auth-input{width:100%;padding:15px 40px 15px 37px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s,background .2s}.auth-field .auth-input::placeholder{color:transparent}.auth-field .auth-input:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721;background:var(--background-focus-input)}.auth-field .auth-input:focus~.auth-label{top:0;font-size:11px!important;color:#398bf7!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-input:focus~.auth-field-icon{color:#398bf7}.auth-field .auth-input:not(:placeholder-shown)~.auth-label{top:0;font-size:11px!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-label{position:absolute;left:35px;top:50%;transform:translateY(-50%);color:var(--placeholder-color)!important;font-size:13px!important;font-weight:400!important;pointer-events:none;transition:top .15s ease,font-size .15s ease,color .15s ease,padding .15s ease,background .15s ease;background:transparent;z-index:1;text-align:left!important}.auth-field .auth-toggle-pw{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;color:var(--placeholder-color);cursor:pointer;padding:4px 6px;font-size:13px;z-index:2;line-height:1;transition:color .2s}.auth-field .auth-toggle-pw:hover{color:#398bf7}.auth-field.has-error .auth-input{border-color:#dc3545;box-shadow:none}.auth-field.has-error .auth-field-icon{color:#dc3545}.auth-select{width:100%;padding:13px 14px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s;margin-bottom:1rem;cursor:pointer}.auth-select:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721}.auth-btn{width:100%;padding:13px;border:none;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:transform .15s ease,box-shadow .2s ease,opacity .2s;background:linear-gradient(135deg,#398bf7,#1e5fc4);color:#fff;letter-spacing:.3px;margin-bottom:10px;display:block}.auth-btn:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 5px 18px #398bf761}.auth-btn:active:not(:disabled){transform:translateY(0)}.auth-btn:disabled{opacity:.55;cursor:not-allowed}.auth-btn.auth-btn--red{background:linear-gradient(135deg,#d1326f,#a82859)}.auth-btn.auth-btn--red:hover:not(:disabled){box-shadow:0 5px 18px #d1326f61}.auth-btn.auth-btn--outline{background:transparent;border:1.5px solid var(--font-border-input);color:var(--text-color)}.auth-btn.auth-btn--outline:hover:not(:disabled){background:var(--background-btn-light-hover);box-shadow:none;transform:none}.auth-links{display:flex;flex-direction:column;align-items:center;gap:10px;margin-top:16px;padding-top:16px;border-top:1px solid var(--border-color-modal)}.auth-version{text-align:right;margin-top:14px;padding-top:12px;border-top:1px solid var(--border-color-modal)}.auth-version span{font-size:11px;color:var(--placeholder-color)}.auth-error{font-size:11.5px;color:#dc3545;margin:-6px 0 10px 2px;padding:0}.auth-hint{display:flex;align-items:flex-start;gap:6px;font-size:11.5px;color:var(--placeholder-color);margin:-6px 0 14px 2px;padding:0;line-height:1.35}.auth-hint i{margin-top:2px;flex-shrink:0}.auth-validation-list{margin:-4px 0 12px;padding:0;list-style:none}.auth-validation-list li{font-size:11.5px;color:#dc3545;padding:2px 0}.auth-validation-list li:before{content:\"\\2715 \";font-size:10px}.auth-desc{font-size:13px;color:var(--placeholder-color);margin-bottom:20px;line-height:1.65}.auth-section-title{font-size:15px;font-weight:600;color:var(--text-color);margin-bottom:20px}.font-12{font-size:12px}.form-control:focus{border-color:#0199ff9a!important;box-shadow:0 0 5px .2px #65befa44!important}@media(max-width:900px){.auth-wrapper-login{grid-template-columns:1fr;grid-template-rows:auto 1fr;overflow-y:auto;overflow-x:hidden}.auth-panel-left{padding:14px 24px;justify-content:center}.auth-panel-left .auth-brand-subtitle,.auth-panel-left .auth-brand-features,.auth-panel-left .auth-brand-divider{display:none!important}.auth-panel-left .auth-brand-panel{display:flex!important;flex-direction:row!important;align-items:center;gap:0;text-align:left;max-width:none;width:100%;justify-content:center}.auth-panel-left .auth-brand-logo{width:52px;height:52px;margin:0;flex-shrink:0}.auth-panel-left .auth-brand-logo img{width:34px;height:34px}.auth-panel-left .auth-brand-title{font-size:20px;margin-bottom:0;margin-left:.5rem;flex-shrink:1}.auth-panel-right:after{inset:-25% 0 auto;width:100%;height:25%;background:linear-gradient(180deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLineV 7s ease-in-out infinite;animation-delay:3.5s}.auth-panel-right--dev:after{background:linear-gradient(180deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}}@keyframes authScanLineV{0%{top:-25%}50%{top:120%}to{top:120%}}@media(max-width:480px){.auth-panel-left{padding:12px 16px}.auth-panel-left .auth-brand-logo{width:44px;height:44px}.auth-panel-left .auth-brand-logo img{width:28px;height:28px}.auth-panel-left .auth-brand-title{font-size:17px}.auth-form-wrapper>div{padding:20px 12px}.auth-card{padding:24px 18px 20px;border-radius:16px}.font-12{font-size:10px!important}}\n"] });
511
- }
512
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: MdVerificarMfaComponent, decorators: [{
513
- type: Component,
514
- args: [{ selector: 'lib-md-verificar-mfa', template: "<div class=\"verificar-mfa\">\n <div class=\"auth-card-title mb-3\">{{ titulo() }}</div>\n\n <div class=\"d-flex align-items-center gap-3 mb-3\">\n <span class=\"verificar-mfa__icono\"><i class=\"fas fa-user-shield\"></i></span>\n <div>\n <div class=\"fw-semibold\">{{ challenge().coduser }}</div>\n @if (challenge().empresa) {\n <div class=\"verificar-mfa__muted\">{{ challenge().empresa }}</div>\n }\n </div>\n </div>\n\n @if (modo() == 'push') {\n @switch (estadoPush()) {\n @case ('enviando') {\n <div class=\"duo-push\">\n <span class=\"spinner-border spinner-border-sm text-primary\"></span>\n <div class=\"flex-grow-1\">Enviando notificaci\u00F3n a tu tel\u00E9fono\u2026</div>\n </div>\n }\n @case ('esperando') {\n <div class=\"duo-push duo-push--esperando\">\n <span class=\"duo-push__icono duo-push__icono--pulso\"><i class=\"fas fa-mobile-alt\"></i></span>\n <div class=\"flex-grow-1\">\n <div class=\"fw-semibold\">Revisa tu tel\u00E9fono</div>\n <div class=\"verificar-mfa__muted\">Aprueba la notificaci\u00F3n en TSI Autenticador para ingresar.</div>\n </div>\n </div>\n }\n @default {\n <div class=\"duo-push\">\n <span class=\"duo-push__icono\"><i class=\"fas fa-bell\"></i></span>\n <div class=\"flex-grow-1\">\n <div class=\"fw-semibold\">TSI Autenticador</div>\n <div class=\"verificar-mfa__muted\">Te enviaremos una notificaci\u00F3n para que la apruebes.</div>\n </div>\n </div>\n }\n }\n @if (pushError() && !isPushEnCurso()) {\n <div class=\"codigo-field__error\"><i class=\"fas fa-exclamation-circle\"></i> {{ pushError() }}</div>\n }\n\n <div class=\"verificar-mfa__opciones\">\n @if (tieneTotp()) {\n <button type=\"button\" class=\"verificar-mfa__link\" (click)=\"usarCodigo('totp')\">\n Usar c\u00F3digo de mi app de autenticaci\u00F3n\n </button>\n }\n <button type=\"button\" class=\"verificar-mfa__link verificar-mfa__link--secundario\"\n (click)=\"usarCodigo('respaldo')\">\n \u00BFNo tienes tu tel\u00E9fono? Usa un c\u00F3digo de respaldo\n </button>\n </div>\n } @else {\n <p class=\"verificar-mfa__muted mb-4\">\n @if (tipoCodigo() == 'totp') {\n {{ challenge().mensaje || campo().descri }}\n } @else {\n {{ campo().descri }}\n }\n </p>\n\n <div class=\"codigo-field\" [class.has-error]=\"codigoError()\">\n <span class=\"codigo-field__icon\"><i class=\"fas\" [class]=\"campo().icon\"></i></span>\n <input #inputCodigo id=\"mfa-codigo\" class=\"codigo-field__input\" type=\"text\"\n [placeholder]=\"campo().placeholder\" [value]=\"codigo()\" (input)=\"onCodigoInput($event)\"\n (keydown.enter)=\"verificar()\" [attr.inputmode]=\"campo().inputmode\" autocomplete=\"one-time-code\"\n autocorrect=\"off\" autocapitalize=\"characters\" spellcheck=\"false\" [disabled]=\"isEnviando()\">\n <label for=\"mfa-codigo\" class=\"codigo-field__label\">{{ campo().label }}</label>\n </div>\n @if (codigoError()) {\n <div class=\"codigo-field__error\"><i class=\"fas fa-exclamation-circle\"></i> {{ codigoError() }}</div>\n }\n\n <div class=\"verificar-mfa__opciones\">\n @if (tienePush()) {\n <button type=\"button\" class=\"verificar-mfa__link\" (click)=\"usarPush()\">\n <i class=\"fas fa-bell me-1\"></i>Mejor env\u00EDame una notificaci\u00F3n push\n </button>\n }\n @if (tieneTotp() && tipoCodigo() != 'totp') {\n <button type=\"button\" class=\"verificar-mfa__link\" (click)=\"usarCodigo('totp')\">\n Usar c\u00F3digo de mi app de autenticaci\u00F3n\n </button>\n }\n @if (tipoCodigo() != 'respaldo') {\n <button type=\"button\" class=\"verificar-mfa__link verificar-mfa__link--secundario\"\n (click)=\"usarCodigo('respaldo')\">\n \u00BFNo tienes tu tel\u00E9fono? Usa un c\u00F3digo de respaldo\n </button>\n }\n </div>\n }\n\n <div class=\"verificar-mfa__acciones\">\n @if (modo() == 'push') {\n <button type=\"button\" class=\"auth-btn\" [disabled]=\"isPushEnCurso()\" (click)=\"enviarPush()\">\n <i class=\"fas fa-paper-plane me-1\"></i>\n {{ isPushEnCurso() ? 'Esperando aprobaci\u00F3n\u2026' : 'Reenviar notificaci\u00F3n' }}\n </button>\n } @else {\n <button type=\"button\" class=\"auth-btn\" [disabled]=\"isEnviando()\" (click)=\"verificar()\">\n <i class=\"fas fa-check me-1\"></i>\n {{ isEnviando() ? 'Verificando\u2026' : 'Verificar' }}\n </button>\n }\n @if (showCancelar()) {\n <button type=\"button\" class=\"auth-btn auth-btn--outline\" (click)=\"cancelar()\">Cancelar</button>\n }\n </div>\n</div>\n", styles: [".verificar-mfa{color:var(--text-color)}.verificar-mfa__icono{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:44px;height:44px;border-radius:12px;color:var(--bs-primary);background:rgba(var(--bs-primary-rgb),.1);font-size:20px}.verificar-mfa__muted{font-size:13px;line-height:1.5;color:var(--bs-secondary-color)}.verificar-mfa__link:hover{text-decoration:underline}.verificar-mfa__link{padding:0;border:0;background:none;font-size:13px;font-weight:600;color:var(--bs-primary)}.codigo-field{position:relative}.codigo-field__icon{position:absolute;left:14px;top:50%;transform:translateY(-50%);z-index:2;font-size:15px;color:var(--placeholder-color);pointer-events:none;transition:color .2s}.codigo-field__input{width:100%;height:56px;padding:0 44px;border:1.5px solid var(--font-border-input);border-radius:10px;outline:none;background:var(--background-input);color:var(--color-input);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:22px;font-weight:600;letter-spacing:.45em;text-align:center;transition:border-color .2s,box-shadow .2s,background .2s}.codigo-field__input::placeholder{color:var(--placeholder-color);opacity:.45}.codigo-field__input:focus{border-color:var(--bs-primary);box-shadow:0 0 0 3.5px rgba(var(--bs-primary-rgb),.15);background:var(--background-focus-input)}.codigo-field__input:disabled{opacity:.7}.codigo-field__label{position:absolute;left:12px;top:0;transform:translateY(-50%);z-index:1;margin:0!important;padding:0 4px;font-size:11px!important;font-weight:500!important;line-height:1.2;color:var(--placeholder-color);background:var(--background-card);pointer-events:none;transition:color .15s ease}.codigo-field:focus-within .codigo-field__label,.codigo-field:focus-within .codigo-field__icon{color:var(--bs-primary)}.codigo-field.has-error .codigo-field__input{border-color:var(--bs-danger);box-shadow:0 0 0 3.5px rgba(var(--bs-danger-rgb),.12)}.codigo-field.has-error .codigo-field__icon,.codigo-field.has-error .codigo-field__label{color:var(--bs-danger)}.codigo-field__error{display:flex;align-items:center;gap:6px;margin-top:8px;font-size:13px;font-weight:500;color:var(--bs-danger)}.duo-push{display:flex;align-items:center;gap:12px;padding:14px;border:1.5px solid var(--font-border-input);border-radius:10px;background:var(--background-input);color:var(--text-color);font-size:14px}.duo-push--esperando{border-color:rgba(var(--bs-primary-rgb),.45);background:rgba(var(--bs-primary-rgb),.06)}.duo-push__icono{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;color:var(--bs-primary);background:rgba(var(--bs-primary-rgb),.1);font-size:18px}.duo-push__icono--pulso{animation:duo-pulso 1.4s ease-in-out infinite}@keyframes duo-pulso{0%,to{box-shadow:0 0 rgba(var(--bs-primary-rgb),.35)}50%{box-shadow:0 0 0 8px rgba(var(--bs-primary-rgb),0)}}@media(prefers-reduced-motion:reduce){.duo-push__icono--pulso{animation:none}}.verificar-mfa__opciones{display:flex;flex-direction:column;align-items:flex-start;gap:8px;margin-top:16px}.verificar-mfa__link--secundario{font-weight:500;color:var(--bs-secondary-color)}.verificar-mfa__acciones{margin-top:24px}\n", "@charset \"UTF-8\";.red_contrasena,.blue_contrasena{position:relative;display:inline-block;font-size:13px;text-decoration:none;padding-bottom:2px;transition:color .3s ease;cursor:pointer}.red_contrasena:after,.blue_contrasena:after{content:\"\";position:absolute;bottom:0;left:50%;width:0;height:1px;background-color:currentColor;transition:all .3s ease;transform:translate(-50%)}.red_contrasena:hover:after,.blue_contrasena:hover:after{width:60%}.red_contrasena{color:#d1326f}.red_contrasena:hover{color:#a82859}.blue_contrasena{color:#398bf7}.blue_contrasena:hover{color:#1e5fc4}.auth-wrapper-login{position:fixed;inset:0;display:grid;grid-template-columns:1.15fr .85fr;overflow:hidden;background:#060d1f}.auth-panel-left{position:relative;overflow:hidden;background:linear-gradient(145deg,#040a18,#0b1a3d 55%,#040e22);display:flex;align-items:center;justify-content:center;padding:48px 40px}.auth-panel-left:before{content:\"\";position:absolute;inset:0;background-image:radial-gradient(circle,rgba(255,255,255,.055) 1px,transparent 1px);background-size:26px 26px;z-index:1;pointer-events:none}.auth-panel-left:after{content:\"\";position:absolute;top:0;left:-120%;width:60%;height:100%;background:linear-gradient(90deg,transparent,rgba(57,139,247,.04),transparent);animation:panelSweep 7s ease-in-out infinite;z-index:1;pointer-events:none}.auth-blob{position:absolute;border-radius:50%;filter:blur(72px);z-index:0;pointer-events:none}.auth-blob-1{width:340px;height:340px;background:radial-gradient(circle,rgba(57,139,247,.45) 0%,transparent 70%);top:-90px;right:-70px;animation:blobDrift 11s ease-in-out infinite}.auth-blob-2{width:240px;height:240px;background:radial-gradient(circle,rgba(124,58,237,.4) 0%,transparent 70%);bottom:60px;left:-50px;animation:blobDrift 14s ease-in-out infinite reverse}.auth-blob-3{width:180px;height:180px;background:radial-gradient(circle,rgba(14,165,233,.35) 0%,transparent 70%);bottom:-50px;right:40px;animation:blobDrift 9s ease-in-out infinite;animation-delay:-4s}.auth-blob-4{width:120px;height:120px;background:radial-gradient(circle,rgba(209,50,111,.25) 0%,transparent 70%);top:50%;left:50%;transform:translate(-50%,-50%);animation:blobDrift 16s ease-in-out infinite;animation-delay:-8s}@keyframes blobDrift{0%,to{transform:translate(0) scale(1)}33%{transform:translate(14px,-20px) scale(1.05)}66%{transform:translate(-10px,12px) scale(.96)}}@keyframes panelSweep{0%{left:-120%}50%{left:160%}to{left:160%}}.auth-brand-panel{position:relative;z-index:2;text-align:center;color:#fff;max-width:340px}.auth-brand-logo{width:100px;height:100px;border-radius:50%;background:#ffffff0d;border:1px solid rgba(255,255,255,.1);display:flex;align-items:center;justify-content:center;margin:0 auto 28px;box-shadow:0 0 0 14px #398bf70f,0 0 50px #398bf733;backdrop-filter:blur(8px)}.auth-brand-logo img{width:64px;height:64px;object-fit:contain;filter:brightness(1.05) drop-shadow(0 0 8px rgba(57,139,247,.4))}.auth-brand-title{font-size:30px;font-weight:700;letter-spacing:-.5px;margin-bottom:10px;background:linear-gradient(135deg,#fff 20%,#93c5fd 80%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.auth-brand-subtitle{font-size:14px;color:#ffffff73;line-height:1.65;margin-bottom:40px;letter-spacing:.2px}.auth-brand-features{display:flex;flex-direction:column;gap:14px;text-align:left}.auth-brand-feature{display:flex;align-items:center;gap:12px;font-size:13px;color:#fff9}.auth-brand-feature .feat-dot{flex-shrink:0;width:7px;height:7px;border-radius:50%;background:#398bf7;box-shadow:0 0 10px #398bf7b3}.auth-brand-divider{width:60px;height:2px;background:linear-gradient(90deg,transparent,#398bf7,transparent);margin:28px auto 32px;border-radius:2px}.auth-panel-left--dev{background:linear-gradient(145deg,#18040b,#3d0b1d 55%,#220409)}.auth-panel-left--dev:after{background:linear-gradient(90deg,transparent,rgba(209,50,111,.05),transparent)}.auth-panel-left--dev .auth-blob-1{background:radial-gradient(circle,rgba(220,38,38,.52) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-2{background:radial-gradient(circle,rgba(219,39,119,.44) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-3{background:radial-gradient(circle,rgba(239,68,68,.38) 0%,transparent 70%)}.auth-panel-left--dev .auth-blob-4{background:radial-gradient(circle,rgba(249,115,22,.28) 0%,transparent 70%)}.auth-panel-left--dev .auth-brand-logo{box-shadow:0 0 0 14px #d1326f12,0 0 50px #d1326f38}.auth-panel-left--dev .auth-brand-logo img{filter:brightness(1.05) drop-shadow(0 0 8px rgba(209,50,111,.45))}.auth-panel-left--dev .auth-brand-title{background:linear-gradient(135deg,#fff 20%,#fca5a5 80%);-webkit-background-clip:text;background-clip:text}.auth-panel-left--dev .auth-brand-divider{background:linear-gradient(90deg,transparent,rgb(209,50,111),transparent)}.auth-panel-left--dev .feat-dot{background:#d1326f;box-shadow:0 0 10px #d1326fb8}.auth-panel-right{position:relative;overflow:hidden;background:var(--background-login)}.auth-panel-right:before{content:\"\";position:absolute;inset:0;background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(57,139,247,.045) 22px,rgba(57,139,247,.045) 23px);animation:authLinesMove 10s linear infinite;pointer-events:none;z-index:0}.auth-panel-right:after{content:\"\";position:absolute;top:0;bottom:0;left:-25%;width:25%;background:linear-gradient(90deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLine 7s ease-in-out infinite;animation-delay:3.5s;pointer-events:none;z-index:0}@keyframes authLinesMove{0%{transform:translate(0)}to{transform:translate(46px,46px)}}@keyframes authScanLine{0%{left:-25%}50%{left:120%}to{left:120%}}.auth-panel-bg{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:hidden}.auth-deco{position:absolute;border-radius:50%;pointer-events:none;filter:blur(70px)}.auth-deco-tl{width:300px;height:300px;top:0;left:-120px;transform:translateY(-40%);background:radial-gradient(circle,rgba(57,139,247,.12) 0%,transparent 70%);animation:authOrbPulse 6s ease-in-out infinite}.auth-deco-br{width:340px;height:340px;bottom:0;right:-120px;transform:translateY(40%);background:radial-gradient(circle,rgba(124,58,237,.1) 0%,transparent 70%);animation:authOrbPulse 8s ease-in-out infinite;animation-delay:-4s}@keyframes authOrbPulse{0%,to{opacity:.7}50%{opacity:1}}.auth-form-wrapper{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;align-items:center;z-index:1}.auth-form-wrapper>div{width:100%;max-width:420px;margin:auto;padding:36px 16px;box-sizing:border-box}.auth-panel-right--dev:before{background-image:repeating-linear-gradient(-55deg,transparent 0px,transparent 22px,rgba(209,50,111,.05) 22px,rgba(209,50,111,.05) 23px)}.auth-panel-right--dev:after{background:linear-gradient(90deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}.auth-panel-right--dev .auth-deco-tl{background:radial-gradient(circle,rgba(209,50,111,.12) 0%,transparent 70%)}.auth-panel-right--dev .auth-deco-br{background:radial-gradient(circle,rgba(239,68,68,.1) 0%,transparent 70%)}.auth-test-badge{display:inline-flex;align-items:center;gap:7px;background:#d1326f14;border:1px solid rgba(209,50,111,.25);color:#d1326f;font-size:10.5px;font-weight:700;padding:5px 12px;border-radius:20px;margin-bottom:18px;letter-spacing:.8px}.auth-test-badge .badge-dot{width:6px;height:6px;border-radius:50%;background:#d1326f;animation:badgePulse 1.6s ease-in-out infinite;flex-shrink:0}@keyframes badgePulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.75)}}.auth-card{background:var(--background-card);border-radius:20px;padding:36px 32px 28px;box-shadow:0 4px 28px #00000014;border:1px solid var(--border-color-modal)}.auth-card-title{font-size:22px;font-weight:700;color:var(--text-color);margin-bottom:4px;letter-spacing:-.3px}.auth-card-subtitle{font-size:13px;color:var(--placeholder-color);margin-bottom:26px}.auth-field{position:relative;margin-bottom:1rem}.auth-field .auth-field-icon{position:absolute;left:13px;top:50%;transform:translateY(-50%);color:var(--placeholder-color);font-size:13px;z-index:2;pointer-events:none;transition:color .2s}.auth-field .auth-input{width:100%;padding:15px 40px 15px 37px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s,background .2s}.auth-field .auth-input::placeholder{color:transparent}.auth-field .auth-input:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721;background:var(--background-focus-input)}.auth-field .auth-input:focus~.auth-label{top:0;font-size:11px!important;color:#398bf7!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-input:focus~.auth-field-icon{color:#398bf7}.auth-field .auth-input:not(:placeholder-shown)~.auth-label{top:0;font-size:11px!important;background:var(--background-card);padding:0 4px;transform:translateY(-50%)}.auth-field .auth-label{position:absolute;left:35px;top:50%;transform:translateY(-50%);color:var(--placeholder-color)!important;font-size:13px!important;font-weight:400!important;pointer-events:none;transition:top .15s ease,font-size .15s ease,color .15s ease,padding .15s ease,background .15s ease;background:transparent;z-index:1;text-align:left!important}.auth-field .auth-toggle-pw{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;color:var(--placeholder-color);cursor:pointer;padding:4px 6px;font-size:13px;z-index:2;line-height:1;transition:color .2s}.auth-field .auth-toggle-pw:hover{color:#398bf7}.auth-field.has-error .auth-input{border-color:#dc3545;box-shadow:none}.auth-field.has-error .auth-field-icon{color:#dc3545}.auth-select{width:100%;padding:13px 14px;background:var(--background-input);border:1.5px solid var(--font-border-input);border-radius:10px;font-size:14px;color:var(--color-input);outline:none;transition:border-color .2s,box-shadow .2s;margin-bottom:1rem;cursor:pointer}.auth-select:focus{border-color:#398bf7;box-shadow:0 0 0 3.5px #398bf721}.auth-btn{width:100%;padding:13px;border:none;border-radius:10px;font-size:14px;font-weight:600;cursor:pointer;transition:transform .15s ease,box-shadow .2s ease,opacity .2s;background:linear-gradient(135deg,#398bf7,#1e5fc4);color:#fff;letter-spacing:.3px;margin-bottom:10px;display:block}.auth-btn:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 5px 18px #398bf761}.auth-btn:active:not(:disabled){transform:translateY(0)}.auth-btn:disabled{opacity:.55;cursor:not-allowed}.auth-btn.auth-btn--red{background:linear-gradient(135deg,#d1326f,#a82859)}.auth-btn.auth-btn--red:hover:not(:disabled){box-shadow:0 5px 18px #d1326f61}.auth-btn.auth-btn--outline{background:transparent;border:1.5px solid var(--font-border-input);color:var(--text-color)}.auth-btn.auth-btn--outline:hover:not(:disabled){background:var(--background-btn-light-hover);box-shadow:none;transform:none}.auth-links{display:flex;flex-direction:column;align-items:center;gap:10px;margin-top:16px;padding-top:16px;border-top:1px solid var(--border-color-modal)}.auth-version{text-align:right;margin-top:14px;padding-top:12px;border-top:1px solid var(--border-color-modal)}.auth-version span{font-size:11px;color:var(--placeholder-color)}.auth-error{font-size:11.5px;color:#dc3545;margin:-6px 0 10px 2px;padding:0}.auth-hint{display:flex;align-items:flex-start;gap:6px;font-size:11.5px;color:var(--placeholder-color);margin:-6px 0 14px 2px;padding:0;line-height:1.35}.auth-hint i{margin-top:2px;flex-shrink:0}.auth-validation-list{margin:-4px 0 12px;padding:0;list-style:none}.auth-validation-list li{font-size:11.5px;color:#dc3545;padding:2px 0}.auth-validation-list li:before{content:\"\\2715 \";font-size:10px}.auth-desc{font-size:13px;color:var(--placeholder-color);margin-bottom:20px;line-height:1.65}.auth-section-title{font-size:15px;font-weight:600;color:var(--text-color);margin-bottom:20px}.font-12{font-size:12px}.form-control:focus{border-color:#0199ff9a!important;box-shadow:0 0 5px .2px #65befa44!important}@media(max-width:900px){.auth-wrapper-login{grid-template-columns:1fr;grid-template-rows:auto 1fr;overflow-y:auto;overflow-x:hidden}.auth-panel-left{padding:14px 24px;justify-content:center}.auth-panel-left .auth-brand-subtitle,.auth-panel-left .auth-brand-features,.auth-panel-left .auth-brand-divider{display:none!important}.auth-panel-left .auth-brand-panel{display:flex!important;flex-direction:row!important;align-items:center;gap:0;text-align:left;max-width:none;width:100%;justify-content:center}.auth-panel-left .auth-brand-logo{width:52px;height:52px;margin:0;flex-shrink:0}.auth-panel-left .auth-brand-logo img{width:34px;height:34px}.auth-panel-left .auth-brand-title{font-size:20px;margin-bottom:0;margin-left:.5rem;flex-shrink:1}.auth-panel-right:after{inset:-25% 0 auto;width:100%;height:25%;background:linear-gradient(180deg,transparent 0%,rgba(57,139,247,.02) 30%,rgba(57,139,247,.045) 50%,rgba(57,139,247,.02) 70%,transparent 100%);animation:authScanLineV 7s ease-in-out infinite;animation-delay:3.5s}.auth-panel-right--dev:after{background:linear-gradient(180deg,transparent 0%,rgba(209,50,111,.02) 30%,rgba(209,50,111,.045) 50%,rgba(209,50,111,.02) 70%,transparent 100%)}}@keyframes authScanLineV{0%{top:-25%}50%{top:120%}to{top:120%}}@media(max-width:480px){.auth-panel-left{padding:12px 16px}.auth-panel-left .auth-brand-logo{width:44px;height:44px}.auth-panel-left .auth-brand-logo img{width:28px;height:28px}.auth-panel-left .auth-brand-title{font-size:17px}.auth-form-wrapper>div{padding:20px 12px}.auth-card{padding:24px 18px 20px;border-radius:16px}.font-12{font-size:10px!important}}\n"] }]
515
- }], ctorParameters: () => [] });
516
-
517
603
  /*
518
604
  * Public API Surface of login-tsi
519
605
  */
@@ -522,5 +608,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
522
608
  * Generated bundle index. Do not edit.
523
609
  */
524
610
 
525
- export { AuthComponent, AuthSender, ExpiredPasswordComponent, MFA_API, MdVerificarMfaComponent, PwaFloatingComponent, PwaInstallService, RecoverPasswordComponent, RefreshFloatingComponent, SelectBranchComponent, isMfaChallenge, isPushPendiente, provideMfaApi };
611
+ export { AUTH_API, AuthComponent, AuthSender, ExpiredPasswordComponent, PwaFloatingComponent, PwaInstallService, RecoverPasswordComponent, RefreshFloatingComponent, SelectBranchComponent, isMfaChallenge, isPushPendiente, provideAuthApi };
526
612
  //# sourceMappingURL=login-tsi.mjs.map