/* ============================================================================
   CYC FACTURACION — app.css
   DELTA de la pantalla logueada (app.html) y del splash (index.html).
   No redefine tokens ni componentes de base.css: solo agrega las piezas que
   esta pantalla necesita (barra superior, saludo, tarjetas, barra inferior,
   hoja de validacion y splash).

   Mobile-first: el CSS base es para celular; solo hay @media (min-width:768px)
   y (min-width:1200px).
   ========================================================================= */

/* ---------------------------------------------------------------------------
   0. ARMAZON
   La barra inferior es fija: el contenido reserva su alto + la safe area para
   que el ultimo bloque nunca quede tapado.
   ------------------------------------------------------------------------ */
.app{
  --tabbar-h: 64px;
  display:flex;
  flex-direction:column;
}

/* Con la hoja de validacion abierta el fondo no debe hacer scroll */
body.is-locked{ overflow:hidden; }

/* Icono generico de esta hoja (base.css solo estiliza los suyos) */
.ico{
  width:18px; height:18px;
  fill:none;                    /* iconos de trazo: sin esto una forma cerrada (círculo) se rellena */
  stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round;
}

/* ---------------------------------------------------------------------------
   1. BARRA SUPERIOR
   Pegada arriba con desenfoque: se siente nativa al hacer scroll.
   ------------------------------------------------------------------------ */
.appbar{
  position:sticky;
  top:0;
  z-index:var(--z-header);
  padding-top:var(--safe-top);
  background:color-mix(in srgb, var(--bg) 78%, transparent);
  border-bottom:1px solid var(--border);
  backdrop-filter:saturate(180%) blur(14px);
  -webkit-backdrop-filter:saturate(180%) blur(14px);
}

/* Sin color-mix (WebViews viejos) el fondo debe seguir siendo opaco */
@supports not (background: color-mix(in srgb, red 50%, transparent)){
  .appbar{ background:var(--bg); }
}

.appbar__inner{
  width:100%;
  max-width:var(--maxw-content);
  margin-inline:auto;
  min-height:var(--header-h);
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--sp-3);
  padding-inline:max(var(--sp-4), var(--safe-left)) max(var(--sp-4), var(--safe-right));
}

.appbar__brand{ min-width:0; }
.appbar__brand .brand__name{ white-space:nowrap; }

.appbar__actions{
  display:flex;
  align-items:center;
  gap:var(--sp-2);
  flex:0 0 auto;
}

/* El boton de salir usa .btn__label como fila (icono + texto) */
.appbar__logout .btn__label{
  display:inline-flex;
  align-items:center;
  gap:var(--sp-2);
}

/* En celular solo se VE el icono (el nombre de la marca necesita el ancho),
   pero el texto no puede desaparecer del arbol: el SVG es aria-hidden y con
   display:none #btnLogout se quedaba SIN nombre accesible. Se oculta a la
   vista conservandolo para lectores de pantalla. */
.appbar__logouttxt{
  position:absolute;
  width:1px; height:1px;
  margin:-1px; padding:0;
  overflow:hidden;
  clip:rect(0 0 0 0);
  clip-path:inset(50%);
  white-space:nowrap;
  border:0;
}

/* ---------------------------------------------------------------------------
   2. CONTENIDO
   ------------------------------------------------------------------------ */
.appmain{
  flex:1 1 auto;
  width:100%;
  max-width:var(--maxw-content);
  margin-inline:auto;
  display:flex;
  flex-direction:column;
  gap:var(--sp-5);
  padding:var(--sp-6) max(var(--sp-4), var(--safe-right))
          calc(var(--tabbar-h) + var(--safe-bottom) + var(--sp-8))
          max(var(--sp-4), var(--safe-left));
}

.appsec__title{
  font-size:var(--fs-lg);
  font-weight:var(--fw-bold);
  letter-spacing:var(--ls-tight);
  margin-bottom:calc(var(--sp-2) * -1);
}

.appfoot{
  text-align:center;
  line-height:var(--lh-base);
  margin-top:var(--sp-2);
}

.app__noscript{
  margin:var(--sp-6) auto;
  max-width:var(--maxw-form);
  padding:var(--sp-4);
  border-radius:var(--r-md);
  background:var(--warning-soft);
  color:var(--text);
  text-align:center;
}

/* ---------------------------------------------------------------------------
   3. SALUDO
   ------------------------------------------------------------------------ */
.hero{
  display:flex;
  align-items:center;
  gap:var(--sp-4);
  animation:hero-in var(--dur-slow) var(--ease-out) both;
}

@keyframes hero-in{
  from{ opacity:0; transform:translateY(10px); }
  to  { opacity:1; transform:translateY(0); }
}

/* Iniciales sobre gradiente de marca: identidad sin pedir foto */
.hero__avatar{
  flex:0 0 auto;
  width:58px; height:58px;
  display:flex; align-items:center; justify-content:center;
  border-radius:var(--r-full);
  background:linear-gradient(135deg, var(--primary), var(--primary-2));
  color:var(--primary-ink);
  font-size:var(--fs-lg);
  font-weight:var(--fw-bold);
  letter-spacing:var(--ls-wide);
  box-shadow:var(--sh-primary);
  animation:avatar-in var(--dur-slow) var(--ease-spring) both;
}

@keyframes avatar-in{
  from{ opacity:0; transform:scale(.6) rotate(-12deg); }
  to  { opacity:1; transform:scale(1) rotate(0); }
}

.hero__body{ min-width:0; }
.hero__eyebrow{ margin-bottom:var(--sp-1); }

.hero__name{
  font-size:var(--fs-xl);
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}

.hero__mail{
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}

.hero__status{ margin-top:var(--sp-2); }
.hero__status[hidden]{ display:none; }

/* ---------------------------------------------------------------------------
   4. BANNER DE VALIDACION
   .notice trae display:flex, asi que [hidden] necesita ganarle explicitamente.
   ------------------------------------------------------------------------ */
.vbanner{
  box-shadow:var(--sh-1);
}
.vbanner[hidden]{ display:none; }

.vbanner .notice__icon{
  background:var(--surface);
  color:var(--warning);
}

.vbanner__btn{ margin-top:var(--sp-1); }

/* Latido muy tenue del icono: llama la atencion sin gritar */
.vbanner .notice__icon::after{
  content:"";
  position:absolute;
  inset:0;
  border-radius:inherit;
  box-shadow:0 0 0 0 var(--warning);
  opacity:.45;
  animation:vbanner-pulse 2.6s var(--ease-out) infinite;
  pointer-events:none;
}
.vbanner .notice__icon{ position:relative; }

@keyframes vbanner-pulse{
  0%  { box-shadow:0 0 0 0 var(--warning); opacity:.35; }
  70% { box-shadow:0 0 0 10px var(--warning); opacity:0; }
  100%{ box-shadow:0 0 0 0 var(--warning); opacity:0; }
}

/* ---------------------------------------------------------------------------
   4.b CARTERA DE LA PRUEBA (timbres y mensajes de WhatsApp)
   Va numerada 4.b, junto al banner, porque las dos son avisos del estado de la
   cuenta y se leen antes que "Siguiente paso". Renumerar el resto del archivo
   solo por insertar aqui no aportaba nada.
   ------------------------------------------------------------------------ */
.wallet{
  display:flex;
  flex-direction:column;
  gap:var(--sp-4);
  animation:card-in var(--dur-slow) var(--ease-spring) both;
}
.wallet[hidden]{ display:none; }

.wallet__top{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--sp-3);
}

.wallet__title{
  font-size:var(--fs-lg);
  font-weight:var(--fw-semi);
  line-height:var(--lh-snug);
  min-width:0;
}

.wallet__badge{ flex:0 0 auto; }

/* Dos medidores lado a lado desde celular: son cifras cortas y partidas en dos
   filas se pierde la comparacion de un vistazo. */
.wallet__meters{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:var(--sp-3);
}

.meter{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:var(--sp-2);
  padding:var(--sp-3) var(--sp-2);
  border-radius:var(--r-md);
  background:var(--surface-2);
  border:1px solid var(--border);
  text-align:center;
  min-width:0;
}

.meter__ring{
  position:relative;
  width:76px; height:76px;
  flex:0 0 auto;
}

/* -90deg: el arco arranca arriba (12 en punto) y no a la derecha. */
.meter__ring svg{
  width:100%; height:100%;
  transform:rotate(-90deg);
  overflow:visible;
}

.meter__track,
.meter__bar{
  fill:none;
  stroke-width:6;
}

.meter__track{ stroke:var(--border-strong); }

/* pathLength="100" en el HTML deja la circunferencia normalizada a 100, asi que
   --pct se escribe tal cual como porcentaje. Se anima el dashoffset (no el
   dasharray) porque es lo que interpolan bien todos los navegadores. */
.meter__bar{
  stroke:var(--primary);
  stroke-linecap:round;
  stroke-dasharray:100;
  stroke-dashoffset:calc(100 - var(--pct, 0));
  transition:stroke-dashoffset var(--dur-xslow) var(--ease-out),
             stroke var(--dur) var(--ease-out);
}

.meter--wa .meter__bar{ stroke:var(--success); }

/* Se acaba: el aro y la cifra se ponen en rojo por si el cliente no lee el pie */
.meter.is-empty .meter__bar{ stroke:var(--danger); }
.meter.is-empty .meter__num{ color:var(--danger-ink); }
.meter.is-low   .meter__bar{ stroke:var(--warning); }
.meter.is-low   .meter__num{ color:var(--warning-ink); }

.meter__num{
  position:absolute;
  inset:0;
  display:flex;
  align-items:center;
  justify-content:center;
  font-size:var(--fs-2xl);
  font-weight:var(--fw-bold);
  font-variant-numeric:tabular-nums;
  letter-spacing:-.02em;
}

.meter__label{
  font-size:var(--fs-md);
  font-weight:var(--fw-semi);
}

.meter__sub{
  font-size:var(--fs-xs);
  color:var(--text-muted);
  line-height:var(--lh-snug);
}

.wallet__note{
  color:var(--text-muted);
  line-height:var(--lh-snug);
  margin:0;
  /* Cuando la suscripcion esta pausada esta nota lleva el recado del reseller
     TAL CUAL lo escribio, asi que sus saltos de linea tienen que sobrevivir. */
  white-space:pre-line;
}

/* ---------------------------------------------------------------------------
   5. TARJETA "SIGUIENTE PASO"
   ------------------------------------------------------------------------ */
.nextstep{
  display:flex;
  flex-direction:column;
  gap:var(--sp-3);
  animation:card-in var(--dur-slow) var(--ease-spring) both;
  animation-delay:60ms;
}

/* .nextstep es display:flex, y una regla de AUTOR le gana al display:none que
   el navegador aplica por [hidden]. Sin esto, ocultar la guia de arranque desde
   el JS no haria absolutamente nada. */
.nextstep[hidden]{ display:none !important; }

.nextstep__top{
  display:flex;
  align-items:center;
  gap:var(--sp-3);
}

.nextstep__icon{
  flex:0 0 auto;
  width:40px; height:40px;
  display:flex; align-items:center; justify-content:center;
  border-radius:var(--r-sm);
  background:var(--primary-soft);
  color:var(--primary);
}
.nextstep__icon svg{
  width:20px; height:20px;
  stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round;
}

.nextstep__title{ font-size:var(--fs-xl); }

/* --- Pasos --- */
.steps{
  list-style:none;
  margin-top:var(--sp-2);
  display:flex;
  flex-direction:column;
  gap:var(--sp-4);
}

.step{
  position:relative;
  display:flex;
  align-items:flex-start;
  gap:var(--sp-3);
  padding-left:var(--sp-1);
}

/* Linea que une los puntos */
.step:not(:last-child)::before{
  content:"";
  position:absolute;
  left:calc(var(--sp-1) + 9px);
  top:22px;
  bottom:calc(var(--sp-4) * -1 + 2px);
  width:2px;
  background:var(--border);
}

.step__dot{
  flex:0 0 auto;
  width:20px; height:20px;
  margin-top:1px;
  border-radius:var(--r-full);
  border:2px solid var(--border-strong);
  background:var(--surface);
  position:relative;
  transition:background-color var(--dur) var(--ease-out),
             border-color var(--dur) var(--ease-out);
}

.step__body{ display:flex; flex-direction:column; gap:2px; min-width:0; }
.step__title{ font-size:var(--fs-md); font-weight:var(--fw-semi); }
.step__text{ font-size:var(--fs-sm); color:var(--text-muted); }

/* Paso cumplido: punto verde con palomita dibujada */
.step.is-done .step__dot{
  background:var(--success);
  border-color:var(--success);
}
.step.is-done .step__dot::after{
  content:"";
  position:absolute;
  left:4px; top:1px;
  width:5px; height:9px;
  border:2px solid var(--primary-ink);
  border-top:0; border-left:0;
  transform:rotate(42deg);
  animation:step-check var(--dur) var(--ease-spring) both;
}
@keyframes step-check{
  from{ opacity:0; transform:rotate(42deg) scale(.4); }
  to  { opacity:1; transform:rotate(42deg) scale(1); }
}

/* Paso activo: aro de marca latiendo */
.step.is-current .step__dot{
  border-color:var(--primary);
  box-shadow:0 0 0 4px var(--primary-soft);
}
.step.is-current .step__title{ color:var(--primary); }

/* ---------------------------------------------------------------------------
   6. ACCESOS (proximamente)
   ------------------------------------------------------------------------ */
.tiles{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--sp-3);
}

/* En celular: rejilla icono | texto, con el distintivo en su propia fila.
   Como fila unica el badge se comia el ancho del texto. */
.tile{
  position:relative;
  display:grid;
  grid-template-columns:auto 1fr;
  align-items:center;
  column-gap:var(--sp-4);
  row-gap:var(--sp-3);
  padding:var(--sp-4);
  border-radius:var(--r-md);
  border:1px solid var(--border);
  background:var(--surface);
  box-shadow:var(--sh-1);
  overflow:hidden;
  /* Deshabilitado pero legible: se apaga el color, no el contraste del texto */
  cursor:not-allowed;
  transition:transform var(--dur) var(--ease-spring),
             box-shadow var(--dur) var(--ease-out),
             border-color var(--dur) var(--ease-out);
}

/* Un .tile que ES un enlace ya no esta deshabilitado: recupera el cursor y el
   :hover a los que la version <article> renuncia a proposito (levantar una
   tarjeta muerta prometia una interaccion que no existia). Los accesos que
   siguen pendientes se quedan como <article> y conservan el not-allowed. */
a.tile{ cursor:pointer; }
a.tile:active{ transform:scale(.985); }

@media (hover:hover){
  a.tile:hover{
    transform:translateY(-2px);
    box-shadow:var(--sh-2);
    border-color:var(--border-strong);
  }
}

/* Barrido de luz que cruza la tarjeta: dice "todavia no, pero viene" */
.tile::after{
  content:"";
  position:absolute;
  inset:0;
  background:linear-gradient(110deg, transparent 30%, var(--primary-soft) 50%, transparent 70%);
  opacity:.55;
  transform:translateX(-120%);
  animation:tile-sweep 5.5s var(--ease-in-out) infinite;
  pointer-events:none;
}
.tile:nth-child(2)::after{ animation-delay:1.1s; }
.tile:nth-child(3)::after{ animation-delay:2.2s; }

@keyframes tile-sweep{
  0%,   55% { transform:translateX(-120%); }
  85%, 100% { transform:translateX(120%); }
}

.tile__icon{
  grid-column:1; grid-row:1;
  flex:0 0 auto;
  width:46px; height:46px;
  display:flex; align-items:center; justify-content:center;
  border-radius:var(--r-sm);
  background:var(--surface-2);
  color:var(--text-soft);
}
.tile__icon svg{
  width:22px; height:22px;
  stroke:currentColor; stroke-width:1.9;
  stroke-linecap:round; stroke-linejoin:round;
}

.tile__body{
  grid-column:2; grid-row:1;
  display:flex; flex-direction:column; gap:2px;
  min-width:0; flex:1 1 auto;
}
.tile__title{ font-size:var(--fs-md); font-weight:var(--fw-semi); }
.tile__text{ font-size:var(--fs-sm); color:var(--text-muted); line-height:var(--lh-snug); }

/* En celular el badge va en el flujo (esquinado chocaria con el texto);
   a partir de tablet se ancla a la esquina de la tarjeta. */
.tile__badge{
  grid-column:2; grid-row:2;
  justify-self:start;
  background:var(--surface-2);
  color:var(--text-soft);
  border-color:transparent;
}

/* ---------------------------------------------------------------------------
   7. BARRA INFERIOR
   Solo celular y tablet: en escritorio estorba (hay barra superior completa).
   La pildora se mueve con --tab-i (0..3) que fija el JS.
   ------------------------------------------------------------------------ */
.tabbar{
  position:fixed;
  left:0; right:0; bottom:0;
  z-index:var(--z-header);
  display:grid;
  grid-template-columns:repeat(4, 1fr);
  align-items:stretch;
  height:calc(var(--tabbar-h, 64px) + var(--safe-bottom));
  padding-bottom:var(--safe-bottom);
  padding-inline:var(--safe-left) var(--safe-right);
  background:color-mix(in srgb, var(--surface) 82%, transparent);
  border-top:1px solid var(--border);
  backdrop-filter:saturate(180%) blur(16px);
  -webkit-backdrop-filter:saturate(180%) blur(16px);
}

@supports not (background: color-mix(in srgb, red 50%, transparent)){
  .tabbar{ background:var(--surface); }
}

/* Pildora deslizante detras del boton activo */
.tabbar__pill{
  position:absolute;
  top:6px;
  left:0;
  width:25%;
  height:calc(var(--tabbar-h, 64px) - 12px);
  transform:translateX(calc(var(--tab-i, 0) * 100%));
  transition:transform var(--dur-slow) var(--ease-spring);
  pointer-events:none;
}
.tabbar__pill::before{
  content:"";
  position:absolute;
  inset:0 var(--sp-4);
  border-radius:var(--r-full);
  background:var(--primary-soft);
}

.tabbar__btn{
  position:relative;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:3px;
  min-height:var(--tap);
  padding:var(--sp-2) var(--sp-1);
  border:0;
  background:transparent;
  color:var(--text-soft);
  font-family:inherit;
  font-size:var(--fs-xs);
  font-weight:var(--fw-medium);
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
  transition:color var(--dur) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.tabbar__btn:active{ transform:scale(.93); }
/* Tinta y no relleno: el boton activo se dibuja SOBRE la pildora
   --primary-soft, y ahi --primary solo daba 4.28:1 con texto de 12px. */
.tabbar__btn.is-active{ color:var(--primary-ink-soft); }

.tabbar__ico svg{
  width:23px; height:23px;
  stroke:currentColor; stroke-width:1.9;
  stroke-linecap:round; stroke-linejoin:round;
  transition:transform var(--dur) var(--ease-spring);
}
.tabbar__btn.is-active .tabbar__ico svg{ transform:translateY(-1px) scale(1.06); }

.tabbar__txt{ line-height:1; }

/* ---------------------------------------------------------------------------
   8. HOJA / DIALOGO DE VALIDACION
   Celular: hoja que sube desde abajo. Escritorio: dialogo centrado.
   ------------------------------------------------------------------------ */
.sheet{
  position:fixed;
  inset:0;
  z-index:var(--z-modal);
  display:flex;
  align-items:flex-end;
  justify-content:center;
}
.sheet[hidden]{ display:none; }

.sheet__scrim{
  position:absolute;
  inset:0;
  background:var(--scrim);
  backdrop-filter:blur(6px);
  -webkit-backdrop-filter:blur(6px);
  opacity:0;
  transition:opacity var(--dur) var(--ease-out);
}
.sheet.is-open .sheet__scrim{ opacity:1; }

.sheet__panel{
  position:relative;
  width:100%;
  max-width:var(--maxw-form);
  /* vh PRIMERO como respaldo: donde no existe dvh la declaracion se descarta
     entera y el panel crecia sin tope, dejando #btnOtpConfirm fuera de la
     pantalla. Quien entiende dvh se queda con la segunda. */
  max-height:92vh;
  max-height:92dvh;
  overflow-y:auto;
  -webkit-overflow-scrolling:touch;
  padding:var(--sp-5) var(--sp-5) calc(var(--sp-6) + var(--safe-bottom));
  border-radius:var(--r-xl) var(--r-xl) 0 0;
  background:var(--surface);
  box-shadow:var(--sh-3);
  transform:translateY(16px) scale(.99);
  opacity:0;
  transition:transform var(--dur-slow) var(--ease-spring),
             opacity var(--dur) var(--ease-out);
}
.sheet.is-open .sheet__panel{ transform:translateY(0) scale(1); opacity:1; }

/* Asa de la hoja: senal tactil de que es un panel movil */
.sheet__grip{
  display:block;
  width:44px; height:5px;
  margin:0 auto var(--sp-4);
  border-radius:var(--r-full);
  background:var(--border-strong);
}

.sheet__close{
  position:absolute;
  top:var(--sp-4); right:var(--sp-4);
  width:var(--tap); height:var(--tap);
  display:flex; align-items:center; justify-content:center;
  border:0;
  border-radius:var(--r-full);
  background:var(--surface-2);
  color:var(--text-muted);
  cursor:pointer;
  transition:background-color var(--dur-fast) var(--ease-out),
             color var(--dur-fast) var(--ease-out),
             transform var(--dur-fast) var(--ease-out);
}
.sheet__close:hover{ background:var(--primary-soft); color:var(--primary); }
.sheet__close:active{ transform:scale(.92); }

.sheet__body,
.sheet__done{
  display:flex;
  flex-direction:column;
  gap:var(--sp-3);
  text-align:center;
}
.sheet__done[hidden]{ display:none; }
.sheet__body[hidden]{ display:none; }

.sheet__icon{
  width:56px; height:56px;
  margin:0 auto var(--sp-1);
  display:flex; align-items:center; justify-content:center;
  border-radius:var(--r-md);
  background:var(--primary-soft);
  color:var(--primary);
}
.sheet__icon svg{
  width:26px; height:26px;
  stroke:currentColor; stroke-width:1.9;
  stroke-linecap:round; stroke-linejoin:round;
}

.sheet__title{ font-size:var(--fs-xl); }
.sheet__mail{ color:var(--text); font-weight:var(--fw-semi); word-break:break-all; }

.sheet__otp{ margin:var(--sp-3) 0 var(--sp-1); }
.sheet__cta{ margin-top:var(--sp-1); }
.sheet__resend{ margin-top:calc(var(--sp-2) * -1); }
.sheet__hint{ margin-top:var(--sp-1); }

.sheet__done .celebrate{ margin-bottom:var(--sp-2); }

/* ---------------------------------------------------------------------------
   9. SPLASH (index.html)
   ------------------------------------------------------------------------ */
.splash{
  min-height:100vh;
  min-height:100dvh;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:var(--sp-5);
  /* Cada lado con SU safe area: aplicar --safe-left a ambos ignoraba el notch
     cuando el telefono se gira y la muesca queda a la DERECHA. */
  padding-block:var(--sp-8);
  padding-inline:max(var(--sp-4), var(--safe-left)) max(var(--sp-4), var(--safe-right));
  text-align:center;
}

.splash__mark{
  position:relative;
  width:84px; height:84px;
  display:flex; align-items:center; justify-content:center;
  border-radius:var(--r-lg);
  color:var(--primary-ink);
  animation:splash-pop var(--dur-slow) var(--ease-spring) both,
            splash-float 3.2s var(--ease-in-out) 500ms infinite alternate;
}
.splash__mark svg{
  width:40px; height:40px;
  stroke:currentColor; stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round;
}
/* Mismo motivo que .brand__mark: el isotipo real trae su azul, asi que el
   cuadro degradado de atras se quito y la imagen ocupa toda la caja. */
.splash__mark img{ width:100%; height:100%; object-fit:contain; display:block; }

/* Aro que se expande alrededor del logo mientras se decide el destino */
.splash__mark::after{
  content:"";
  position:absolute;
  inset:-6px;
  border-radius:var(--r-xl);
  border:2px solid var(--primary);
  opacity:0;
  animation:splash-ring 2.2s var(--ease-out) infinite;
}

@keyframes splash-pop{
  from{ opacity:0; transform:scale(.7); }
  to  { opacity:1; transform:scale(1); }
}
@keyframes splash-float{
  from{ transform:translateY(0); }
  to  { transform:translateY(-8px); }
}
@keyframes splash-ring{
  0%  { opacity:.55; transform:scale(.92); }
  70% { opacity:0;   transform:scale(1.22); }
  100%{ opacity:0;   transform:scale(1.22); }
}

.splash__name{
  font-size:var(--fs-xl);
  font-weight:var(--fw-bold);
  letter-spacing:var(--ls-tight);
}
.splash__name span{ color:var(--primary); }

.splash__text{ color:var(--text-muted); font-size:var(--fs-sm); }

/* Barra de progreso indeterminada */
.splash__bar{
  position:relative;
  width:132px; height:4px;
  border-radius:var(--r-full);
  background:var(--surface-2);
  overflow:hidden;
}
.splash__bar::after{
  content:"";
  position:absolute;
  top:0; bottom:0; left:0;
  width:42%;
  border-radius:inherit;
  background:linear-gradient(90deg, var(--primary), var(--primary-2));
  animation:splash-load 1.15s var(--ease-in-out) infinite;
}
@keyframes splash-load{
  0%  { transform:translateX(-110%); }
  100%{ transform:translateX(280%); }
}

.splash__link{ margin-top:var(--sp-4); }

/* ---------------------------------------------------------------------------
   10. TABLET (>=768px)
   ------------------------------------------------------------------------ */
@media (min-width:768px){

  /* Desde tablet el texto vuelve al flujo visible */
  .appbar__logouttxt{
    position:static;
    width:auto; height:auto;
    margin:0;
    overflow:visible;
    clip:auto;
    clip-path:none;
    white-space:normal;
  }

  .appmain{
    gap:var(--sp-6);
    padding-top:var(--sp-8);
  }

  .hero__avatar{ width:68px; height:68px; font-size:var(--fs-xl); }
  .hero__name{ font-size:var(--fs-2xl); }

  .tiles{ grid-template-columns:repeat(3, 1fr); }

  /* Desde tablet cada acceso es una tarjeta vertical con el distintivo
     anclado en la esquina: vuelve a flex, la rejilla ya no aplica. */
  .tile{
    display:flex;
    flex-direction:column;
    align-items:flex-start;
    justify-content:flex-start;
    gap:var(--sp-3);
    padding:var(--sp-5);
    min-height:190px;
  }
  .tile__icon,
  .tile__body{ grid-column:auto; grid-row:auto; }
  .tile__body{ flex:0 1 auto; }
  .tile__badge{
    position:absolute;
    top:var(--sp-4); right:var(--sp-4);
    grid-column:auto; grid-row:auto;
  }

  /* Dialogo centrado en vez de hoja inferior */
  .sheet{ align-items:center; padding:var(--sp-6); }
  .sheet__panel{
    border-radius:var(--r-lg);
    padding:var(--sp-8);
    /* Mismo respaldo vh -> dvh que en el bloque base */
    max-height:88vh;
    max-height:88dvh;
    transform:translateY(10px) scale(.97);
  }
  .sheet__grip{ display:none; }
  .sheet__close{ top:var(--sp-5); right:var(--sp-5); }

  .splash__mark{ width:96px; height:96px; }
  .splash__mark svg{ width:46px; height:46px; }
}

/* ---------------------------------------------------------------------------
   11. ESCRITORIO (>=1200px)
   ------------------------------------------------------------------------ */
@media (min-width:1200px){

  /* La barra inferior es un patron movil: en escritorio desaparece y el
     contenido recupera el espacio reservado. */
  .tabbar{ display:none; }

  .appmain{
    padding-bottom:var(--sp-12);
    padding-top:var(--sp-10);
    gap:var(--sp-8);
  }

  /* Saludo y banner comparten fila: menos scroll en pantallas anchas */
  .hero{ gap:var(--sp-5); }
  .hero__avatar{ width:76px; height:76px; }

  .nextstep{ padding:var(--sp-10); }
  .nextstep__title{ font-size:var(--fs-2xl); }

  .tile{ padding:var(--sp-6); min-height:200px; }
  /* Sin :hover a proposito: estas tarjetas estan deshabilitadas
     (cursor:not-allowed) y levantarlas prometia una interaccion que no
     existe. El distintivo "Proximamente" es el unico indicador. */
}

/* ---------------------------------------------------------------------------
   12. MOVIMIENTO REDUCIDO (obligatorio al final)
   ------------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;
    animation-iteration-count:1!important;
    transition-duration:.01ms!important;
    scroll-behavior:auto!important;
  }
}


/* ==========================================================================
   MOBILIARIO COMPARTIDO DE PAGINA

   Estas cuatro piezas nacieron en css/facturas.css, pero NO son de facturas:
   .pagehead lo usan varias pantallas y .duo / .sheet__form / .field--select
   los necesita cualquier hoja con formulario. La cuarta pagina que las quiso
   (pagos.html) salio ROTA —el <select> sin estilo se dibuja crudo y enorme—
   porque esa hoja no la carga.

   Viven aqui, en app.css, que TODAS las paginas cargan. facturas.css sigue
   teniendo las suyas y se carga DESPUES, asi que ahi nada cambia: si algun dia
   se limpian de alla, esta es la copia buena.
   ========================================================================== */

/* Dos campos en una fila (fecha + hora, cantidad + precio, fecha + forma…). */
.duo{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:var(--sp-3);
}

.sheet__form{
  display:flex;
  flex-direction:column;
  gap:var(--sp-4);
  text-align:left;
  width:100%;
}

/* Encabezado de pantalla: titulo + subtitulo, con la accion opcional a la
   derecha. */
.pagehead{
  display:flex;
  align-items:flex-start;
  justify-content:space-between;
  gap:var(--sp-3);
}
.pagehead__body{ min-width:0; }
.pagehead__title{
  font-size:var(--fs-2xl);
  font-weight:var(--fw-bold);
  line-height:var(--lh-tight, 1.15);
  letter-spacing:-.02em;
}
.pagehead__sub{
  margin-top:2px;
  font-size:var(--fs-sm);
  color:var(--text-muted);
}
.pagehead__cta{ flex:0 0 auto; }

/* SELECT con apariencia de campo propio. Sin appearance:none el navegador
   dibuja su control nativo y se pierde la flecha, el foco y la etiqueta
   flotante: es justo lo que se veia mal. */
.field--select .field__control{
  appearance:none;
  -webkit-appearance:none;
  padding-right:calc(var(--sp-4) + 22px);
  cursor:pointer;
}
/* La flecha. Faltaba la regla BASE y solo estaba la del foco, que sin la otra
   no hace nada: el <span> se quedaba estatico y en linea, y su <svg> sin
   tamaño crecia hasta 177 px de alto. Se veia en pagos.html (el campo "¿Cómo?")
   y habria salido igual en cualquier pantalla nueva con un <select>.
   facturas.css y setup.css tienen su propia copia y cargan DESPUES, asi que
   alli no cambia nada. */
.field__chev{
  position:absolute;
  right:var(--sp-4);
  top:50%;
  transform:translateY(-50%);
  width:18px; height:18px;
  pointer-events:none;
  color:var(--text-soft);
  transition:transform var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}
.field__chev svg{
  width:100%; height:100%;
  stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round;
  fill:none;
}
.field--select .field__control:focus ~ .field__chev{
  color:var(--primary);
  transform:translateY(-50%) rotate(180deg);
}
/* La etiqueta de un select va SIEMPRE arriba: no hay estado "vacio" que
   revelar, la opcion cero ya dice que elegir. */
.field--select .field__label{
  transform:translateY(calc(-50% - 12px)) scale(.78);
  color:var(--text-muted);
}
.field--select .field__control:focus{
  outline:none;
  border-color:var(--primary);
  background:var(--surface);
  box-shadow:0 0 0 4px var(--ring);
}
.field--select .field__control:focus + .field__label{ color:var(--primary); }
.field--select .field__control[disabled]{ opacity:.6; cursor:not-allowed; }
.field--select.is-error .field__control{
  border-color:var(--danger);
  background:var(--danger-soft);
}
.field--select.is-error .field__control:focus{ box-shadow:0 0 0 4px var(--ring-danger); }
.field--select.is-error .field__label{ color:var(--danger); }

@media (min-width:768px){
  .pagehead__title{ font-size:var(--fs-3xl); }
}

/* ==========================================================================
   CHIPS (tira de filtros)

   Vivian copiados en facturas.css y en xmls.css. Al necesitarlos una TERCERA
   pantalla (pagos.html) suben aqui, que era justo lo que el comentario de
   xmls.css decia que habia que hacer. Las dos copias se borraron; eran
   identicas salvo una linea de comentario.

   La guarda de [hidden] va aqui tambien: sin ella el display:flex del autor le
   gana al atributo y una tira escondida se veria igual.
   ========================================================================== */
.chips[hidden]{ display:none !important; }

.chips{
  display:flex;
  gap:var(--sp-2);
  overflow-x:auto;
  /* El desbordamiento horizontal se queda DENTRO de la tira: la pagina nunca
     debe poder desplazarse en horizontal. */
  padding-bottom:2px;
  scrollbar-width:none;
}
.chips::-webkit-scrollbar{ display:none; }

.chip{
  flex:0 0 auto;
  display:inline-flex;
  align-items:center;
  gap:6px;
  padding:6px var(--sp-3);
  border-radius:var(--r-full);
  border:1px solid var(--border);
  background:var(--surface);
  color:var(--text-muted);
  font-size:var(--fs-sm);
  font-weight:var(--fw-medium);
  white-space:nowrap;
  cursor:pointer;
  transition:background-color var(--dur) var(--ease-out),
             color var(--dur) var(--ease-out),
             border-color var(--dur) var(--ease-out),
             transform var(--dur-fast) var(--ease-spring);
}

.chip:active{ transform:scale(.96); }

.chip.is-active{
  background:var(--primary-soft);
  border-color:transparent;
  color:var(--primary-ink-soft);
  font-weight:var(--fw-semi);
}

/* ==========================================================================
   DISTINTIVO DE AMBIENTE
   Solo existe fuera de produccion (lo inyecta initEnvBadge en js/ui.js).
   ========================================================================== */
.envbadge{
  position:fixed;
  top:6px;
  left:50%;
  transform:translateX(-50%);
  z-index:9999;
  padding:3px 11px;
  border-radius:999px;
  font-size:11px;
  font-weight:600;
  letter-spacing:.05em;
  text-transform:uppercase;
  white-space:nowrap;
  /* Colores propios y opacos: tiene que leerse igual en claro y en oscuro,
     y no puede depender de las variables del tema para cumplir su unico
     trabajo, que es avisar. */
  color:#7A3E00;
  background:#FFE1A8;
  border:1px solid #E8B860;
  box-shadow:0 1px 4px rgba(0,0,0,.16);
  /* Informativo, nunca interactivo: no debe robarse un clic jamas. */
  pointer-events:none;
  user-select:none;
}

/* ==========================================================================
   Campana de notificaciones (appbar) + panel
   ========================================================================== */
.appbar__bell{
  position:relative;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:var(--tap);
  height:var(--tap);
  border:0;
  border-radius:var(--r-full);
  background:transparent;
  color:var(--text-muted);
  cursor:pointer;
  transition:background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.appbar__bell:hover{ background:var(--surface-2); color:var(--text); }
.appbar__bell:active{ transform:scale(.94); }
.appbar__bell .ico{
  width:22px; height:22px;
  fill:none; stroke:currentColor; stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round;
}
.appbar__bell-badge{
  position:absolute;
  top:5px; right:5px;
  min-width:18px; height:18px;
  padding:0 5px;
  display:inline-flex; align-items:center; justify-content:center;
  font-size:11px; font-weight:var(--fw-bold); line-height:1;
  color:var(--danger-soft);
  background:var(--danger);
  border-radius:var(--r-full);
  box-shadow:0 0 0 2px var(--surface);   /* aro del color de la barra */
}
.appbar__bell-badge[hidden]{ display:none; }

/* Velo transparente: cierra el panel al tocar fuera, sin oscurecer la pantalla. */
.notif-scrim{ position:fixed; inset:0; z-index:calc(var(--z-modal) - 1); background:transparent; }
.notif-scrim[hidden]{ display:none; }

.notif-panel{
  position:fixed;
  top:calc(var(--header-h) + var(--safe-top) + 8px);
  right:16px;
  width:min(360px, calc(100vw - 24px));
  max-height:min(70vh, 520px);
  overflow:auto;
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--r-md);
  box-shadow:var(--sh-3);
  z-index:var(--z-modal);
  padding:8px;
  -webkit-overflow-scrolling:touch;
}
.notif-panel[hidden]{ display:none; }
.notif-panel__head{ padding:6px 10px 8px; }
.notif-panel__head h3{ margin:0; font-size:var(--fs-md); font-weight:var(--fw-semi); color:var(--text); }
.notif-empty{ padding:26px 14px; text-align:center; color:var(--text-muted); font-size:var(--fs-sm); }
.notif-item{
  padding:12px;
  border-radius:var(--r-sm);
  background:var(--surface-2);
  margin:6px 0;
}
.notif-item__title{ font-weight:var(--fw-semi); color:var(--text); margin-bottom:3px; }
.notif-item__msg{ color:var(--text-muted); font-size:var(--fs-sm); line-height:var(--lh-base); white-space:pre-wrap; word-break:break-word; }
.notif-item__msg a{ color:var(--primary); text-decoration:underline; text-underline-offset:2px; word-break:break-all; }
.notif-item__msg a:hover{ opacity:.85; }
.notif-item__time{ color:var(--text-soft); font-size:var(--fs-xs); margin-top:6px; }

/* ==========================================================================
   Botón y modal "Recordar" (recordatorios de pago por WhatsApp)
   ========================================================================== */
.hero__recordar .ico{ width:18px; height:18px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }

.rem-overlay{
  position:fixed; inset:0; z-index:var(--z-modal);
  display:flex; align-items:center; justify-content:center;
  padding:16px; background:var(--scrim);
}
.rem-overlay[hidden]{ display:none; }
.rem-modal{
  width:min(520px, 100%);
  max-height:min(86vh, 720px);
  display:flex; flex-direction:column;
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--r-lg); box-shadow:var(--sh-3); overflow:hidden;
}
.rem-head{ display:flex; align-items:flex-start; justify-content:space-between; gap:12px; padding:18px 18px 12px; border-bottom:1px solid var(--border); }
.rem-head h2{ margin:0; font-size:var(--fs-lg); font-weight:var(--fw-semi); color:var(--text); }
.rem-head p{ margin:3px 0 0; font-size:var(--fs-sm); color:var(--text-muted); }
.rem-x{ border:0; background:transparent; color:var(--text-muted); font-size:16px; cursor:pointer; width:32px; height:32px; border-radius:var(--r-full); flex:0 0 auto; }
.rem-x:hover{ background:var(--surface-2); color:var(--text); }
.rem-body{ padding:12px 18px; overflow:auto; }
.rem-tools{ display:flex; gap:16px; margin-bottom:8px; }
.rem-linkbtn{ border:0; background:transparent; color:var(--primary); font-size:var(--fs-sm); cursor:pointer; padding:2px 0; }
.rem-linkbtn:hover{ text-decoration:underline; }
.rem-list{ display:flex; flex-direction:column; gap:6px; }
.rem-item{ display:flex; align-items:center; gap:10px; padding:10px 12px; border-radius:var(--r-sm); background:var(--surface-2); cursor:pointer; }
.rem-item input{ width:18px; height:18px; flex:0 0 auto; accent-color:var(--primary); }
.rem-item__main{ flex:1 1 auto; min-width:0; color:var(--text); font-size:var(--fs-sm); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rem-item__saldo{ flex:0 0 auto; font-weight:var(--fw-semi); color:var(--text); font-variant-numeric:tabular-nums; }
.rem-item--notel{ opacity:.6; cursor:default; }
.rem-item__notel{ color:var(--danger-ink); font-style:normal; font-size:var(--fs-xs); }
.rem-note{ display:block; margin-top:14px; }
.rem-note span{ display:block; font-size:var(--fs-sm); color:var(--text-muted); margin-bottom:4px; }
.rem-note textarea{ width:100%; border:1px solid var(--border-strong); border-radius:var(--r-sm); background:var(--surface); color:var(--text); padding:10px 12px; font:inherit; resize:vertical; }
.rem-empty{ padding:32px 14px; text-align:center; color:var(--text-muted); }
.rem-foot{ display:flex; align-items:center; justify-content:space-between; gap:12px; padding:12px 18px; border-top:1px solid var(--border); flex-wrap:wrap; }
.rem-count{ font-size:var(--fs-sm); color:var(--text-muted); }
.rem-foot__btns{ display:flex; gap:8px; margin-left:auto; }

