/* ══════════════════════════════════════════════════════════════════════════════
   core/auth/refinado.css · capa compartida de las DOS superficies de acceso
   (login de tenant y pantalla bloqueada). Va DESPUÉS de lock-screen.css.

   Existe para que el criterio viva en UN sitio. Antes cada superficie resolvía
   su tipografía, su botón y su fondo por separado, y por eso se veían de dos
   familias distintas aunque compartieran el orbe.

   PRINCIPIO, aprendido a golpes: lo premium acá es QUITAR, no añadir. Nada de
   grano, viñetas, blur de fondo ni destellos que cruzan botones. La nitidez es
   filo (hairline .5px), contraste real de tonos y profundidad medida.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ══ TEMAS · rescatados de la cara LUZO hub ═══════════════════════════════════
   El hub trae TRES paletas completas y la cara de acceso solo se había traído la
   violeta: los botones de tema cambiaban el atributo y no pasaba nada. Acá están
   las tres, con sus mismos valores de origen salvo donde se dicen los cambios.

     · darkmode  — negro con nebulosa VIOLETA. La de siempre.
     · midnight  — noche AZUL-índigo profunda, bien distinta del oscuro.
     · cyan      — vidrio oscuro verde-azulado. Ocupa el sitio del claro del hub:
                   una sola cara clara en un producto que se usa de noche quedaba
                   fuera de familia. Es el más vítreo de los tres.

   El ORBE no cambia con el tema: es la marca. En el hub tampoco cambiaba.
   Las paradas del aurora se guardan en variables y el fondo se dibuja UNA vez
   con ellas, así que cambiar de tema no toca la maqueta: solo repinta. */
.lz-lock{
  --lz-base:#07080c;
  --lz-ink:#eceef4; --lz-ink-2:#c3c8d4; --lz-ink-3:#9aa1b1; --lz-ink-4:#7d8394;
  --lz-line:rgba(196,181,253,.22); --lz-line-suave:rgba(255,255,255,.10);
  --lz-glass-1:rgba(196,181,253,.10); --lz-glass-2:rgba(139,92,246,.045); --lz-glass-3:rgba(0,0,0,.16);
  --lz-glass-borde:rgba(167,139,250,.55);
  --lz-specular:rgba(255,255,255,.10); --lz-specular-2:rgba(255,255,255,.16);
  --lz-ring:rgba(139,92,246,.10); --lz-foco:rgba(255,255,255,.35);
  --lz-btn-fondo:rgba(255,255,255,.05); --lz-btn-activo:rgba(255,255,255,.07);
  --lz-campo:rgba(196,181,253,.07); --lz-campo-2:rgba(0,0,0,.12);
  --lz-ok:#a9e8cd; --lz-ok-fuerte:#75d7ad; --lz-err:#ef7181; --lz-err-suave:#f3a3ad;
  --lz-au-1:rgba(124,58,237,.52); --lz-au-1b:rgba(109,40,217,.38); --lz-au-1c:rgba(91,33,182,.24);
  --lz-au-1d:rgba(76,29,149,.13); --lz-au-1e:rgba(76,29,149,.05);
  --lz-au-2:rgba(139,92,246,.34); --lz-au-2b:rgba(109,40,217,.22); --lz-au-2c:rgba(76,29,149,.13);
  --lz-au-2d:rgba(59,20,120,.06);
  --lz-au-3:rgba(167,139,250,.13); --lz-au-3b:rgba(139,92,246,.06);
  /* EL ORBE TAMBIÉN ES DEL TEMA. Estaba cableado en violeta en las dos hojas
     —la del hub y la de la pantalla bloqueada—, así que sobre una escena azul o
     cyan quedaba como una canica de otro juego. Son cinco paradas del degradado
     más el halo, la chispa y la sombra: el dibujo no cambia, solo la tinta. */
  --lz-orbe-1:#f3efff; --lz-orbe-2:#c9b6ff; --lz-orbe-3:#8b5cf6;
  --lz-orbe-4:#6d28d9; --lz-orbe-5:#4c1d95;
  --lz-orbe-halo:rgba(139,92,246,.55); --lz-orbe-sombra:rgba(124,58,237,.6);
  --lz-orbe-hondo:rgba(43,15,92,.65);
  --lz-chispa:#d6c8ff; --lz-chispa-luz:rgba(167,139,250,.85);
  --lz-aura:rgba(139,92,246,.16);
  background:var(--lz-base); color:var(--lz-ink);
  /* El cambio de tema se cruza, no salta. Medio segundo es lo que tarda el ojo
     en aceptar que la escena es otra sin que parezca un parpadeo. */
  transition:background .55s ease, color .55s ease;
}
[data-theme="midnight"] .lz-lock{
  --lz-base:#03040b;
  --lz-ink:#dbe3f0; --lz-ink-2:#aab7cc; --lz-ink-3:#8b96ad; --lz-ink-4:#6f7b92;
  --lz-line:rgba(140,170,235,.22); --lz-line-suave:rgba(120,150,220,.12);
  --lz-glass-1:rgba(150,180,255,.10); --lz-glass-2:rgba(37,99,235,.06); --lz-glass-3:rgba(0,0,0,.20);
  --lz-glass-borde:rgba(96,140,240,.58);
  --lz-ring:rgba(37,99,235,.12);
  --lz-btn-fondo:rgba(120,150,255,.055); --lz-btn-activo:rgba(120,150,255,.09);
  --lz-campo:rgba(140,170,235,.07); --lz-campo-2:rgba(0,0,0,.16);
  --lz-au-1:rgba(37,99,235,.46); --lz-au-1b:rgba(30,58,138,.40); --lz-au-1c:rgba(30,58,138,.26);
  --lz-au-1d:rgba(23,42,110,.14); --lz-au-1e:rgba(23,42,110,.05);
  --lz-au-2:rgba(67,56,202,.34); --lz-au-2b:rgba(37,99,235,.20); --lz-au-2c:rgba(30,58,138,.13);
  --lz-au-2d:rgba(18,32,90,.06);
  --lz-au-3:rgba(56,110,240,.13); --lz-au-3b:rgba(37,99,235,.06);
  /* Índigo: el mismo dibujo con la tinta de la escena. */
  --lz-orbe-1:#eef2ff; --lz-orbe-2:#b9c8ff; --lz-orbe-3:#4f6ef7;
  --lz-orbe-4:#2547c8; --lz-orbe-5:#16307f;
  --lz-orbe-halo:rgba(79,110,247,.55); --lz-orbe-sombra:rgba(37,99,235,.6);
  --lz-orbe-hondo:rgba(10,26,80,.68);
  --lz-chispa:#c7d4ff; --lz-chispa-luz:rgba(120,150,255,.85);
  --lz-aura:rgba(59,110,235,.16);
}
[data-theme="cyan"] .lz-lock{
  /* CYAN · vidrio oscuro. Sustituye al claro del hub: una sola cara clara en un
     producto que se usa de noche quedaba fuera de familia.
     NO es un cyan inventado: es el acento frío que el propio CRM ya tiene en sus
     tokens —`--lk-teal`, #39c5cf en las paletas oscuras y #0891b2 en la clara—.
     Se apoya en esa rampa y por eso tira a AZUL y no a verde: el turquesa
     verdoso que llevaba antes (#2dd4bf) se fue, que era lo que lo desviaba.
     Es el más vítreo de los tres a propósito: sube el especular y la línea del
     borde, que es lo único que hace que un cristal se lea como cristal. Nada de
     más desenfoque: eso emborrona, no acristala. */
  --lz-base:#04090e;
  --lz-ink:#e0eff4; --lz-ink-2:#b0c7d0; --lz-ink-3:#87a1ad; --lz-ink-4:#6b8390;
  --lz-line:rgba(57,197,207,.26); --lz-line-suave:rgba(57,197,207,.12);
  --lz-glass-1:rgba(57,197,207,.11); --lz-glass-2:rgba(8,145,178,.06); --lz-glass-3:rgba(0,0,0,.18);
  --lz-glass-borde:rgba(57,197,207,.58);
  --lz-specular:rgba(255,255,255,.14); --lz-specular-2:rgba(255,255,255,.20);
  --lz-ring:rgba(8,145,178,.16); --lz-foco:rgba(150,230,240,.42);
  --lz-btn-fondo:rgba(57,197,207,.055); --lz-btn-activo:rgba(57,197,207,.09);
  --lz-campo:rgba(57,197,207,.07); --lz-campo-2:rgba(0,0,0,.14);
  --lz-au-1:rgba(8,145,178,.52); --lz-au-1b:rgba(14,116,144,.44); --lz-au-1c:rgba(21,94,117,.30);
  --lz-au-1d:rgba(12,74,90,.16); --lz-au-1e:rgba(12,74,90,.06);
  --lz-au-2:rgba(57,197,207,.28); --lz-au-2b:rgba(8,145,178,.22); --lz-au-2c:rgba(21,94,117,.14);
  --lz-au-2d:rgba(8,58,74,.07);
  --lz-au-3:rgba(103,232,249,.13); --lz-au-3b:rgba(8,145,178,.07);
  --lz-orbe-1:#eafcff; --lz-orbe-2:#a5e9f2; --lz-orbe-3:#39c5cf;
  --lz-orbe-4:#0891b2; --lz-orbe-5:#0b4f63;
  --lz-orbe-halo:rgba(57,197,207,.55); --lz-orbe-sombra:rgba(8,145,178,.6);
  --lz-orbe-hondo:rgba(6,42,58,.68);
  --lz-chispa:#b8f2f8; --lz-chispa-luz:rgba(103,232,249,.85);
  --lz-aura:rgba(8,145,178,.18);
}

/* ── Base ───────────────────────────────────────────────────────────────────
   La hoja no puede dar por hecho que alguien más puso el reset: sin
   `box-sizing:border-box`, `height:100%` más relleno hace la rejilla más alta
   que la pantalla y, al centrarse, el contenido se sale por arriba. Medido: 62px
   de relleno → 31px de contenido fuera del borde en la app de iPhone. */
.lz-lock,.lz-lock *,.lz-lock *::before,.lz-lock *::after{box-sizing:border-box}

/* ── Tipografía ─────────────────────────────────────────────────────────────
   system-ui por regla del repo (prohibidas las tipografías externas). LUZO hub
   es la ÚNICA excepción y conserva Space Grotesk; estas dos caras, no.
   Sin `text-rendering:optimizeLegibility`: en textos cortos solo engorda. */
.lz-lock,.lz-lock *{
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}
.lz-lock{font-family:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif}
.lz-lock-logo{font-size:38px;letter-spacing:-.022em}

/* Escala pareja entre las dos columnas: el titular de la izquierda y el de la
   derecha miden LO MISMO (18px). Antes el derecho iba a 22 y el lado derecho
   pesaba más que el izquierdo. */
.lz-lock-copy{color:var(--lz-ink-2);font-size:13.5px;line-height:1.7;max-width:318px}
.lz-lock-copy strong{color:var(--lz-ink);font-size:18px;letter-spacing:-.01em}

/* ── Fondo ──────────────────────────────────────────────────────────────────
   Sin `filter:blur()`. El blur obligaba a rasterizar la capa entera y de ahí
   salía la sensación de foto mal comprimida. Se sustituye por degradados de
   seis paradas: suaves por construcción, sin necesitar tramado de ruido. */
.lz-lock-bg{
  filter:none;
  /* Color de verdad. La version anterior quedo lavada: al quitar el grano y el
     blur baje tambien la saturacion y el fondo se volvio gris. Tres focos en vez
     de dos, mas saturados y con un violeta calido arriba a la izquierda que le
     da temperatura a la escena. Siguen siendo degradados de muchas paradas: no
     hay banding que tramar. */
  background:
    /* AMBIENTE DEL BORDE SUPERIOR. El glow de la escena nacia solo abajo
       (24%/70%/108%) y el ~25% de arriba quedaba plano —bajo la barra de estado
       del PWA se leia como una franja. Dos lavados de baja opacidad que bajan
       DESDE el borde de arriba lo llenan sin volverlo un foco: premium por
       restar. El resto del degradado es el mismo; solo el primer foco sube de
       24% a 20% para que no deje muerto el tope. Va por tokens: sirve igual en
       violeta (prod), teal (dev) y midnight. */
    radial-gradient(135% 52% at 50% -10%,
      var(--lz-au-2c), var(--lz-au-2d) 46%, transparent 70%),
    radial-gradient(80% 30% at 50% -4%,
      var(--lz-au-3b), transparent 60%),
    radial-gradient(64% 60% at 14% 20%,
      var(--lz-au-1), var(--lz-au-1b) 20%, var(--lz-au-1c) 36%,
      var(--lz-au-1d) 54%, var(--lz-au-1e) 72%, transparent 88%),
    radial-gradient(58% 54% at 86% 70%,
      var(--lz-au-2), var(--lz-au-2b) 22%, var(--lz-au-2c) 42%,
      var(--lz-au-2d) 64%, transparent 84%),
    radial-gradient(90% 70% at 50% 108%,
      var(--lz-au-3), var(--lz-au-3b) 40%, transparent 72%);
  transition:background .55s ease;
}
.lz-lock-grid{position:relative;z-index:3}
.lz-lock-footer{color:var(--lz-ink-4)}
.lz-lock-footer{z-index:3}

/* ── Orbe · un punto menos, no dos ──────────────────────────────────────────
   Se conservan TODOS sus movimientos; solo se alargan los tiempos ~1.4x y se
   recorta la amplitud del halo, que latía entre .50 y .95 de opacidad. Sigue
   vivo, deja de pedir atención. */
.lz-lock-orb-halo{animation-duration:8s}
.lz-lock-orb-shine::before{animation-duration:9.5s}
.lz-lock-orbit{animation-duration:28s}
.lz-lock-orbit span:nth-child(2){animation-duration:4.6s}
.lz-lock-orbit span:nth-child(3){animation-duration:3.8s}
.lz-lock-orb{animation-duration:9.5s}
.lz-lock-orb::after{animation-duration:12s}
@keyframes lzLockHalo{0%,100%{opacity:.55;transform:scale(1)}50%{opacity:.85;transform:scale(1.11)}}

/* La tinta del orbe sale del tema. El dibujo —las paradas, el especular interno,
   la sombra de contacto— es el mismo de siempre; solo cambia el color. */
.lz-lock-orb{
  background:radial-gradient(circle at 36% 30%,
    var(--lz-orbe-1), var(--lz-orbe-2) 16%, var(--lz-orbe-3) 46%,
    var(--lz-orbe-4) 70%, var(--lz-orbe-5));
  box-shadow:inset 0 1px 2px rgba(255,255,255,.6),
             inset 0 -7px 16px var(--lz-orbe-hondo),
             0 9px 30px -9px var(--lz-orbe-sombra);
}
.lz-lock-orb-halo{background:radial-gradient(circle, var(--lz-orbe-halo), transparent 62%)}
.lz-lock-orbit span{background:var(--lz-chispa);box-shadow:0 0 6px 1px var(--lz-chispa-luz)}

/* ── Botón principal ────────────────────────────────────────────────────────
   Vidrio que va HACIA LO OSCURO, como el de LUZO hub: apenas una luz arriba y
   el pie cerrando en negro. Con el relleno claro se leía como pastilla gris.
   Hairline .5px — regla de la casa; 1px sobre fondo oscuro se lee grueso.
   Profundidad en tres capas: especular fino arriba, sombra de contacto corta y
   una proyectada larga y muy abierta.
   NO lleva barrido de luz al pasar el ratón: ese destello es recurso de
   plantilla, no de producto. */
.lz-lock-primary,.lz-gbtn{
  position:relative;overflow:hidden;
  width:100%;height:50px;
  display:flex;align-items:center;justify-content:center;gap:11px;
  border:.5px solid var(--lz-line);border-radius:14px;
  /* Tinte de acento en el relleno: sin el, sobre un fondo violeta el boton se
     leia como un rectangulo gris pegado encima. Sigue yendo HACIA LO OSCURO. */
  background:linear-gradient(180deg, var(--lz-glass-1), var(--lz-glass-2) 52%, var(--lz-glass-3));
  -webkit-backdrop-filter:blur(10px) saturate(1.25);backdrop-filter:blur(10px) saturate(1.25);
  box-shadow:inset 0 .5px 0 var(--lz-specular), 0 1px 2px rgba(0,0,0,.28), 0 8px 24px -16px rgba(0,0,0,.55);
  color:var(--lz-ink);font:inherit;font-weight:500;font-size:13.5px;cursor:pointer;
  transition:transform .3s cubic-bezier(.2,.7,.2,1), border-color .3s, box-shadow .3s;
}
.lz-lock-primary:hover:not(:disabled),.lz-gbtn:hover{
  transform:translateY(-1px);border-color:var(--lz-glass-borde);
  box-shadow:inset 0 .5px 0 var(--lz-specular-2), 0 2px 4px rgba(0,0,0,.3),
             0 16px 34px -18px rgba(0,0,0,.6), 0 0 0 4px var(--lz-ring);
}
.lz-lock-primary:active:not(:disabled),.lz-gbtn:active{transform:translateY(0)}
.lz-lock-primary:focus-visible,.lz-gbtn:focus-visible{outline:2px solid var(--lz-foco);outline-offset:3px}
.lz-lock-primary:disabled{opacity:.42;cursor:not-allowed;transform:none}
.lz-gbtn svg{width:18px;height:18px;flex:0 0 auto}

/* Acción secundaria: texto, sin caja. No compite con la principal. */
.lz-lock-logout{margin-top:13px;color:var(--lz-ink-3);font:inherit;font-size:11.5px}
.lz-lock-logout:hover{color:var(--lz-err)}

@media(prefers-reduced-motion:reduce){
  .lz-lock-primary,.lz-gbtn{-webkit-backdrop-filter:none;backdrop-filter:none;transition:none}
  .lz-lock-orb,.lz-lock-orb-halo,.lz-lock-orb-shine::before,.lz-lock-orbit,
  .lz-lock-orbit span,.lz-lock-orb::after{animation:none}
}


/* ══════════════════════════════════════════════════════════════════════════════
   RESPONSIVE · compartido por las dos superficies
   ══════════════════════════════════════════════════════════════════════════════ */

/* Zonas seguras. `viewport-fit=cover` ya está en login.template.html, así que el
   contenido llega hasta el borde físico: sin esto, en un iPhone el pie se mete
   bajo la barra de gestos y en horizontal el texto se va bajo el notch. */
.lz-lock{
  padding-left:env(safe-area-inset-left);
  padding-right:env(safe-area-inset-right);
  /* Las zonas seguras se leen UNA vez y se guardan en variables. Dos razones:
     se escriben en un solo sitio, y la maqueta de previsualización puede
     simularlas —`env()` no se puede falsear, una variable sí—, así que el
     mockup enseña de verdad dónde queda la marca bajo la isla del iPhone. */
  --sat:env(safe-area-inset-top);
  --sab:env(safe-area-inset-bottom);
}
.lz-lock-footer{bottom:calc(22px + var(--sab))}

@media (max-width:760.98px){
  /* ── EL SCROLL VERTICAL DE MÁS ────────────────────────────────────────────
     lock-screen.css deja en móvil `.lz-lock{overflow:auto;padding:70px 0}`. Con
     la rejilla de la app a `height:100%` eso da 140px garantizados de contenido
     fuera de la caja, y la pantalla —que es fija y sin barra— se podía arrastrar
     igual. No es una pantalla que deba desplazarse: el relleno lo pone la propia
     rejilla, que sabe dónde están las zonas seguras. */
  .lz-lock{padding:0;overflow:hidden}

  /* ── UNA SOLA CARA PARA EL TELÉFONO ───────────────────────────────────────
     El navegador se ve IGUAL que la app instalada: la marca en la esquina
     superior izquierda y el bloque al centro. No hay motivo para dos maquetas
     —es el mismo dedo, el mismo ancho y la misma tarea—, y tener dos era además
     tener dos sitios donde arreglar cada cosa.
     Lo que sí cambia es lo que cambia de verdad: la web no hace la ceremonia de
     apertura (se recarga a menudo y repetirla cansa) y conserva el reloj, que en
     la app ya lo pinta el sistema en la barra de estado, dos centímetros arriba.

     ── ESCALA DE MANO ──────────────────────────────────────────────────────
     El paquete no se reduce con un factor único: eso es lo que se veía tosco.
     Se aplican los tres criterios de siempre al bajar de tamaño:
       · lo GRÁFICO encoge más que lo TIPOGRÁFICO. Un orbe o un logotipo se leen
         igual un 25% más chicos; el texto tiene suelo de legibilidad y baja la
         mitad. Por eso el orbe cede 5 puntos y los titulares uno y medio.
       · el AIRE encoge más que las piezas. Al acercar la pantalla a los ojos la
         misma separación se lee más grande, así que los huecos bajan un cuarto
         mientras las piezas bajan un octavo. Eso es lo que junta la composición
         en un bloque en vez de dejar elementos flotando.
       · lo PULSABLE no encoge. Nada baja de 44px de alto, que es el mínimo
         cómodo del dedo; se afina el cuerpo de letra y el radio, no el blanco.
     El ritmo sigue siendo de base 8: 18 · 26 · 34 y no valores sueltos. */
  /* La rejilla es solo el lienzo: la marca y el contenido se colocan cada uno en
     su sitio, así que no reparte filas ni las estira. */
  .lz-lock-grid{
    display:block;position:relative;width:100%;height:100%;gap:0;min-height:0;
    padding:calc(var(--sat) + 16px) 0 calc(var(--sab) + 20px);
    /* Reposo de la marca. Un elemento absoluto se posiciona contra la caja de
       RELLENO, así que el padding de la rejilla no lo empuja: sin estas dos
       medidas la marca queda pegada al filo y el halo del orbe se recorta. */
    --marca-x:20px;
    --marca-y:calc(var(--sat) + 18px);
  }
  .lz-lock-copy{display:none}

  /* La marca, en una línea en la esquina. Apilada ocupaba dos alturas en una
     esquina donde sobra ancho y falta alto. */
  .lz-lock-brand{
    position:absolute;left:var(--marca-x);top:var(--marca-y);
    display:flex;align-items:center;gap:8px;width:auto;text-align:left;
  }
  .lz-lock-orb-wrap{width:24px;margin:0;flex:0 0 auto}
  .lz-lock-logo{font-size:17px;letter-spacing:-.015em;line-height:1}
  .lz-lock-orb-halo{opacity:.75}

  /* El bloque se centra en lo que queda BAJO la marca, no en la pantalla
     entera, y se le resta alto por abajo para que su centro caiga cerca del 48%:
     el ojo pone el centro más arriba que la regla. */
  .lz-lock-form{
    position:absolute;left:0;right:0;top:calc(var(--marca-y) + 42px);bottom:0;
    justify-content:center;width:auto;max-width:none;min-height:0;padding:0 7vw 9vh;
  }
  /* El botón conserva su altura de dedo; lo que baja es el cuerpo de letra. */
  .lz-lock-primary,.lz-gbtn{height:48px;border-radius:14px;font-size:13.5px;gap:9px}
  .lz-lock-logout{margin-top:12px;font-size:11.5px;padding:9px}
  .lz-lock-footer{font-size:10.5px}

  /* El fondo deja de derivar y deja de sobresalir. Es una capa del 140% de la
     pantalla con tres degradados grandes: mantenerla animada en bucle obliga a
     conservarla viva en memoria de vídeo toda la sesión, y el movimiento —un 3%
     en 18 s— no se ve en una pantalla de mano. Se paga batería por nada. Sin
     deriva tampoco hace falta el margen de sobra, que además era lo que hacía
     desplazable una pantalla que no debe desplazarse. */
  .lz-lock-bg{animation:none;inset:0}

  /* ── El orbe sigue vivo en el teléfono, pero a media voz ─────────────────
     Estaba apagado del todo y se veía muerto. Vuelve entero —brillo y órbita—
     con dos recortes que no se ven y sí se pagan:
       · FUERA `mix-blend-mode`. Esa máscara obliga al navegador a componer todo
         lo que hay detrás en cada vuelta, y en un teléfono eso es lo caro. Sin
         ella el brillo se dibuja igual, con opacidad.
       · FUERA los dos parpadeos de las chispas: a 24px no se distinguen y son
         dos animaciones más despiertas para siempre.
     Lo demás son giros de `transform`, que resuelve el compositor sin despertar
     a la CPU. Los tiempos se van al doble de lentos: eso no ahorra fotogramas
     —siguen siendo 60 por segundo—, ahorra AGITACIÓN, que es de lo que se queja
     el ojo. Lo que ahorra batería es lo de arriba. */
  .lz-lock-orb-shine{mix-blend-mode:normal;opacity:.30}
  .lz-lock-orb-shine::before{animation-duration:19s}
  .lz-lock-orbit{animation-duration:52s}
  .lz-lock-orbit span:nth-child(2),
  .lz-lock-orbit span:nth-child(3){animation:none;opacity:.5}
  .lz-lock-orb{animation-duration:12s}
  .lz-lock-orb-halo{animation-duration:11s}
}

/* Teléfono angosto. La marca de esquina NO encoge más: a 24/17 ya está en su
   suelo y por debajo se lee como un icono roto. Lo que cede es el margen
   lateral, que es lo que sobra. */
@media (max-width:400px){
  .lz-lock-form{padding:0 5.5vw 9vh}
}

/* Pantalla baja —teléfono acostado, o la ventana del Mac aplastada—. Con la
   marca fuera del flujo, centrar el bloque en lo que queda bajo ella lo dejaba
   sin sitio. Acá el bloque recupera la altura completa y se apoya en la marca:
   vale más que se toquen a que se corte. */
@media (max-width:760.98px) and (max-height:560px){
  .lz-lock-form{top:0;padding-bottom:0}
}

/* Puntero grueso: en táctil todo lo pulsable sube a 44px, que es el mínimo
   cómodo de Apple. No se aplica por ancho sino por tipo de puntero — un
   escritorio angosto no necesita botones de dedo. */
@media (pointer:coarse){
  .lz-lock-primary,.lz-gbtn{height:48px}
  .lz-lock-logout{padding:10px 14px}
}

/* ══ INSTALADA COMO APP (PWA) ══════════════════════════════════════════════════
   Sí: una PWA puede mostrar cosas distintas de la web, y conviene. Se detecta
   con `display-mode`, no con el agente de usuario.
   Qué cambia de verdad cuando corre como app:
     · No hay barra de direcciones, así que la pantalla es de veras pantalla
       completa y el contenido puede respirar más arriba.
     · El sistema pinta la barra de estado por encima: hay que reservarla con
       env(safe-area-inset-top) o el reloj del teléfono se come el contenido.
     · No hay «tirar para recargar» ni botón atrás del navegador: la salida tiene
       que estar SIEMPRE en pantalla — por eso «Cerrar sesión» no se esconde.
     · El color de la barra de estado lo fija <meta name="theme-color">, que ya
       está en login.template.html.
     · PassKey funciona igual en la app instalada (iOS 16+ y macOS), con Face ID
       o Touch ID; no hace falta camino distinto. */
/* ══ INSTALADA COMO APP ════════════════════════════════════════════════════════
   La detección va por JS y estampa `.app` sobre `.lz-lock`, en vez de repetir
   cada regla dentro de un @media: así el modo app tiene UNA fuente de verdad y
   la previsualización puede encenderlo sin instalar nada.
     var app = matchMedia('(display-mode: standalone)').matches
            || window.navigator.standalone === true;   // iOS antiguo
     lock.classList.toggle('app', app);

   ⚠ MAC Y IPHONE NO SON LA MISMA APP. Meterlas en el mismo modo es el error
   fácil: en macOS «Añadir al Dock» abre una VENTANA de escritorio, con puntero
   fino, redimensionable y sin zonas seguras; en iPhone es pantalla completa,
   con la barra de estado encima y la barra de gestos abajo. Por eso el reparto
   de teléfono está detrás de su propia consulta y no se aplica en Mac. */

/* ── App en escritorio (macOS) ──────────────────────────────────────────────
   La composición de dos columnas se queda: hay sitio y el puntero es fino. Lo
   que cambia es que ya no es una página web dentro de un navegador, así que el
   pie de enlaces —gesto de sitio— pierde sentido y se reduce a la firma. */
/* El pie se mantiene en TODAS las vistas, con el mismo formato: es la firma y
   el acceso a lo legal, y en una app instalada es además lo único que dice dónde
   está el usuario. En el teléfono se acerca al borde seguro y baja de cuerpo. */
.lz-lock.app .lz-lock-footer{opacity:.85}
/* La zona segura de arriba la reserva la REJILLA, no el contenedor. Puestas en
   los dos, se sumaban: la marca acababa al doble de distancia del filo. */

/* ── App en teléfono ────────────────────────────────────────────────────────
   Acá sí cambia el reparto, y es lo que la hace sentir app: la marca sube
   arriba y la ACCIÓN baja a la zona del pulgar. Un bloque centrado con pie de
   enlaces, dentro de un icono del escritorio, se siente «un sitio metido en una
   app». */
/* La maqueta de mano es la MISMA en la web y en la app: vive completa en el
   bloque responsive de arriba. Acá abajo solo queda lo que de verdad distingue a
   la app instalada —las zonas seguras, el reloj que sobra y la ceremonia—. */

/* ── ENTRADA DE LA APP ──────────────────────────────────────────────────────
   Al tocar el icono no hay barra de direcciones ni pestaña que dé la sensación
   de «ha cargado algo»: la app aparece de golpe y se siente barata. Una
   secuencia corta de arranque es lo que la convierte en apertura.

   NO se inventa: es la misma que ya tiene la cara LUZO hub —`ignite` para el
   orbe y `rise` para el logotipo—, traída aquí con sus mismas curvas.

   EN MÓVIL ENTRA **SOLO LUZOcrm**: el orbe enciende y el logotipo sube, y nada
   más. Escalonar además la identidad, el botón y el pie convierte una apertura
   de dos tiempos en una cascada de seis, que en una pantalla de mano se lee
   lenta y recargada. La marca abre; el contenido ya está.

   Solo en modo app: una web se recarga a menudo y repetir la ceremonia en cada
   visita cansa. La app se abre desde cero, y ahí sí corresponde. */
/* Las animaciones de apertura se respetan solo si el sistema no pide menos
   movimiento; el guardia va DENTRO de cada consulta, no envolviéndolas, para
   no anidar @media. */

/* Estas dos SOLO valen en escritorio. Estaban al nivel superior y, aunque el
   bloque de móvil viene después y ganaba por orden, cualquier reordenación del
   archivo las dejaba pisando la recomposición del teléfono. Encerradas en su
   consulta no pueden alcanzarla nunca. */
@media (min-width:761px){
  .lz-lock.app.abriendo .lz-lock-orb-wrap{animation:lzEncender 1.25s cubic-bezier(.2,.8,.2,1) both}
  .lz-lock.app.abriendo .lz-lock-logo    {animation:lzSubir .8s cubic-bezier(.2,.7,.2,1) .36s both}
}

/* ── APP EN IPHONE · secuencia de apertura ────────────────────────────────
   Cuatro tiempos, como una app de verdad:

     1. 0 → 0,45 s   el FONDO se dibuja. La pantalla no aparece hecha: nace.
     2. 0,25 → 1,2 s LUZOcrm entra en el CENTRO exacto, horizontal y vertical,
                     grande. El orbe enciende y el logotipo sube.
     3. 1,2 → 2,0 s  la marca VIAJA a la esquina superior izquierda y encoge,
                     dejando la pantalla libre.
     4. 1,9 → 2,5 s  entra el contenido en el sitio que la marca liberó: en el
                     acceso, el logo del tenant y su cuadro de diálogo; en la
                     bloqueada, el halo con el nombre y lo demás, centrado.

   El viaje se anima con `left`/`top`, no con un desplazamiento en `vh`: así el
   centro es el centro REAL del contenedor y funciona igual en un iPhone que
   dentro del marco de una previsualización, sin números mágicos. */
@media (max-width:760.98px){
  /* 1 · el fondo se dibuja */
  .lz-lock.app.abriendo .lz-lock-bg{animation:lzFondoEntra .95s ease both}

  /* 2 · la marca nace GRANDE y APILADA en el centro exacto: el mismo logotipo
     que en Mac —orbe arriba, LUZOcrm debajo—, un punto por debajo de su tamaño
     de escritorio porque acá la pantalla es de mano.

     Es un estado ESTÁTICO, no un fotograma: el texto está dibujado de verdad a
     34px, no escalado, y por eso se ve nítido los dos segundos que se sostiene. */
  .lz-lock.app.marca-centro .lz-lock-brand{
    left:0;right:0;top:0;bottom:0;width:auto;
    flex-direction:column;justify-content:center;gap:12px;
    animation:lzMarcaNace .85s cubic-bezier(.22,1,.36,1) .12s both;
  }
  .lz-lock.app.marca-centro .lz-lock-orb-wrap{width:48px}
  .lz-lock.app.marca-centro .lz-lock-logo{font-size:34px;letter-spacing:-.022em}

  /* 3 · EL VIAJE A LA ESQUINA NO SE ESCRIBE ACÁ, y es deliberado. Lo mide el
     componente y lo resuelve con UNA transformación por pieza (ver `viajar` en
     componente.js): el orbe llega primero y el texto se coloca a su lado 150 ms
     después. Escrito en fotogramas había que animar `left`, `top`, `width`,
     `font-size` y `letter-spacing` —cinco propiedades que recalculan la maqueta
     entera en cada uno de los ~195 fotogramas del viaje—, y eso era exactamente
     lo que se sentía tosco y con tirones. */

  /* 4 · el contenido entra en el sitio liberado. Cada pieza con su registro y
     desde la derecha, que es el gesto nativo cuando una vista sucede a otra; los
     ~100 ms entre una y otra alcanzan para que se lea la secuencia sin que se
     note la espera. Empieza a 2,72 s, cuando la marca ya va llegando. */
  .lz-lock.app.abriendo .lz-lock-form > *{animation-fill-mode:both;animation-timing-function:cubic-bezier(.22,1,.36,1)}
  .lz-lock.app.abriendo .lz-lock-form > *:nth-child(1){animation-name:lzAcerca;animation-duration:.7s;animation-delay:2.72s}
  .lz-lock.app.abriendo .lz-lock-form > *:nth-child(2){animation-name:lzEntraDerecha;animation-duration:.62s;animation-delay:2.82s}
  .lz-lock.app.abriendo .lz-lock-form > *:nth-child(3){animation-name:lzEntraDerecha;animation-duration:.6s;animation-delay:2.91s}
  .lz-lock.app.abriendo .lz-lock-form > *:nth-child(4){animation-name:lzSeAsienta;animation-duration:.68s;animation-delay:3s}
  .lz-lock.app.abriendo .lz-lock-form > *:nth-child(5){animation-name:lzEnciende;animation-duration:.6s;animation-delay:3.12s}
  /* La barra y el pie cierran la ceremonia, en ese orden y con el mismo formato
     que en Mac: la firma no aparece antes que el contenido. */
  .lz-lock.app.abriendo .lz-topbar{animation:lzEntraDerecha .62s cubic-bezier(.22,1,.36,1) 3.1s both}
  .lz-lock.app.abriendo .lz-lock-footer{animation:lzEnciende .7s ease 3.2s both}
}

/* ── APP EN macOS · misma idea, otro reparto ──────────────────────────────
   No es la del teléfono con otro ancho: aquí hay dos columnas y la apertura
   las presenta en orden.

     1. 0 → 0,9 s    el fondo se dibuja.
     2. 0,2 → 1,1 s  LUZOcrm entra en el CENTRO de la ventana, algo mayor.
     3. 1,1 → 1,9 s  la marca se DESPLAZA A LA IZQUIERDA, a su columna.
     4. 1,45 s       aparece la bajada, debajo de la marca ya asentada.
     5. 1,75 s       EMERGE la columna derecha, que es la que pide algo.

   El viaje no lleva un número inventado: la marca arranca desplazada media
   columna derecha más medio hueco —que es exactamente la distancia entre el
   centro de la ventana y el centro de su columna—, y esas dos medidas son las
   mismas variables con las que se dibuja la rejilla. Si cambia el reparto,
   el viaje se ajusta solo. */
@media (min-width:761px){
  .lz-lock.app .lz-lock-grid{
    --hueco:90px; --col-derecha:340px;
    grid-template-columns:1fr var(--col-derecha);
    gap:var(--hueco);
  }
  .lz-lock.app.abriendo .lz-lock-bg{animation:lzFondoEntra .9s ease both}
  .lz-lock.app.abriendo .lz-lock-brand{animation:lzMarcaAIzquierda 1.9s cubic-bezier(.22,.72,.2,1) both}
  .lz-lock.app.abriendo .lz-lock-copy{animation:lzSubir .75s cubic-bezier(.2,.7,.2,1) 1.45s both}
  /* La columna derecha ya no entra como un bloque: cada pieza tiene SU gesto.
     El mismo efecto repetido cuatro veces es lo que se sentía monótono —se lee
     como un panel que se desliza, no como una interfaz que se compone—. Cada
     pieza entra según lo que es: lo que identifica aparece, lo que se lee sube,
     lo que se pulsa se asienta. */
  .lz-lock.app.abriendo .lz-lock-form{animation:none}
  .lz-lock.app.abriendo .lz-lock-form > *{animation-fill-mode:both;animation-timing-function:cubic-bezier(.22,1,.36,1)}
  /* 1 · identidad (logo del tenant o avatar): aparece con un acercamiento corto */
  .lz-lock.app.abriendo .lz-lock-form > *:nth-child(1){animation-name:lzAcerca;animation-duration:.72s;animation-delay:1.72s}
  /* 2 · el título sube */
  .lz-lock.app.abriendo .lz-lock-form > *:nth-child(2){animation-name:lzSubir;animation-duration:.62s;animation-delay:1.86s}
  /* 3 · la bajada sube detrás, más corta */
  .lz-lock.app.abriendo .lz-lock-form > *:nth-child(3){animation-name:lzSubir;animation-duration:.58s;animation-delay:1.96s}
  /* 4 · la acción se asienta: llega desde arriba y frena */
  .lz-lock.app.abriendo .lz-lock-form > *:nth-child(4){animation-name:lzSeAsienta;animation-duration:.7s;animation-delay:2.08s}
  /* 5 · la nota solo se enciende */
  .lz-lock.app.abriendo .lz-lock-form > *:nth-child(5){animation-name:lzEnciende;animation-duration:.6s;animation-delay:2.26s}
  .lz-lock.app.abriendo .lz-topbar{animation:lzEnciende .7s ease 2.4s both}
  .lz-lock.app.abriendo .lz-lock-footer{animation:lzEnciende .7s ease 2.55s both}
}

/* Con movimiento reducido no hay ceremonia: el componente ni siquiera pone las
   clases `abriendo` / `marca-centro`, así que la pantalla nace ya compuesta. Esto
   es el cinturón por si alguien las pone a mano. */
@media (prefers-reduced-motion:reduce){
  .lz-lock.app .lz-lock-orb-wrap,.lz-lock.app .lz-lock-logo,.lz-lock.app .lz-lock-copy,
  .lz-lock.app .lz-lock-brand,.lz-lock.app .lz-lock-form,.lz-lock.app .lz-lock-bg,
  .lz-lock.app .lz-lock-form > *,.lz-lock.app .lz-topbar,
  .lz-lock.app .lz-lock-footer,.lz-modo.activo{animation:none}
}

@keyframes lzEncender{
  0%  {opacity:0;transform:scale(.62)}
  55% {opacity:1;transform:scale(1.07);filter:brightness(1.28)}
  100%{opacity:1;transform:scale(1);filter:brightness(1)}
}
@keyframes lzSubir{ from{opacity:0;transform:translateY(12px)} to{opacity:1;transform:none} }

/* 1 · el fondo se dibuja */
@keyframes lzFondoEntra{ from{opacity:0;transform:scale(1.06)} to{opacity:1;transform:none} }

/* 2 · la marca aparece en el centro. Solo opacidad y escala: las dos las resuelve
   el compositor sin volver a calcular la maqueta. Nace un pelo grande —102%— y
   se asienta, que es como aparecen las cosas con peso.
   El sostenido de dos segundos NO es un fotograma: es el estado estático
   `.marca-centro`, y por eso el logotipo se ve dibujado a su tamaño real. Una
   marca que se va enseguida no llega a leerse como apertura. */
@keyframes lzMarcaNace{
  from{opacity:0;transform:scale(1.02)}
  to  {opacity:1;transform:none}
}

/* El contenido entra DESDE LA DERECHA, no desde abajo. Es el gesto de las apps
   nativas cuando una vista sucede a otra: la marca ya ocupó su sitio y lo que
   viene detrás llega desde el borde, no emerge del suelo. Recorrido corto —26px—
   porque un desplazamiento largo se lee como transición de página, no como
   entrada de contenido. La curva es de salida rápida y frenado largo, que es lo
   que da la sensación de peso físico. */
@keyframes lzEntraDerecha{
  from{opacity:0;transform:translateX(26px)}
  to  {opacity:1;transform:none}
}

/* macOS · la marca nace en el centro de la ventana y se desplaza a su columna.
   El desplazamiento sale de la propia rejilla: media columna derecha + medio
   hueco es la distancia exacta entre el centro de la ventana y el de la columna
   izquierda. Cambia el reparto y el viaje se ajusta solo. */
@keyframes lzMarcaAIzquierda{
  0%  {transform:translateX(calc((var(--col-derecha) + var(--hueco)) / 2)) scale(1.16);opacity:0}
  14% {transform:translateX(calc((var(--col-derecha) + var(--hueco)) / 2)) scale(1.16);opacity:1}
  52% {transform:translateX(calc((var(--col-derecha) + var(--hueco)) / 2)) scale(1.16);opacity:1}
  100%{transform:translateX(0) scale(1);opacity:1}
}

/* ══ BARRA SUPERIOR · reloj y temas ═══════════════════════════════════════════
   Vienen de la cara LUZO hub, con su mismo marcado y sus mismas medidas: barra
   fija arriba a la derecha, reloj con cifras de ancho fijo y el selector de tres
   temas. No se reinventan aquí; se comparten, que es de lo que trata esta capa.
   El pie ya existía en la pantalla de bloqueo y se mantiene tal cual. */
.lz-topbar{
  position:absolute;top:20px;right:24px;z-index:5;
  display:flex;align-items:center;gap:16px;
}
.lz-reloj{
  font-size:12.5px;color:var(--lz-ink-4);letter-spacing:.02em;
  font-variant-numeric:tabular-nums;   /* sin esto el reloj baila cada minuto */
}
.lz-modos{
  display:flex;gap:2px;padding:3px;
  border:.5px solid var(--lz-line-suave);border-radius:11px;
  background:var(--lz-btn-fondo);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
}
.lz-modo{
  width:30px;height:30px;display:grid;place-items:center;
  border:0;background:transparent;border-radius:8px;color:var(--lz-ink-4);cursor:pointer;
  transition:color .2s, background .2s;
}
.lz-modo:hover{color:var(--lz-ink-2)}
.lz-modo.activo{color:var(--lz-ink);background:var(--lz-btn-activo)}
.lz-modo:focus-visible{outline:2px solid var(--lz-foco);outline-offset:2px}
.lz-modo svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}

/* En la app del teléfono el reloj SOBRA: el sistema ya pinta el suyo en la barra
   de estado, justo encima. Dos relojes a dos centímetros es un descuido, no una
   funcionalidad. El selector de temas se queda. */
@media (max-width:760.98px){
  .lz-lock.app .lz-reloj{display:none}
  .lz-lock.app .lz-lock-footer{font-size:10.5px;bottom:calc(var(--sab) + 14px)}
  .lz-lock.app .lz-lock-footer .lz-sep{margin:0 5px}
  .lz-topbar{top:calc(var(--sat) + 12px);right:16px}

  /* ── UN SOLO BOTÓN DE TEMA ────────────────────────────────────────────────
     Tres blancos de 30px pegados en una barra de 390px es un segmentado que se
     falla con el pulgar. En compacto se muestra SOLO el tema vigente y el botón
     avanza al siguiente; el marcado no cambia —los tres siguen ahí para el
     escritorio y para el lector de pantalla—, solo se ocultan dos.
     El blanco visible mide 34px, pero la zona sensible se estira a 46 con un
     pseudo-elemento: se cumple el mínimo del dedo sin engordar el dibujo. */
  .lz-modos{padding:0;border-radius:12px}
  .lz-modo{display:none}
  .lz-modo.activo{
    display:grid;position:relative;width:34px;height:34px;border-radius:12px;
    background:transparent;
    animation:lzTemaCambia .24s cubic-bezier(.22,1,.36,1);
  }
  .lz-modo.activo::after{content:'';position:absolute;inset:-6px}
  .lz-modo.activo svg{width:15.5px;height:15.5px}
}
/* El icono no se cambia de golpe: entra girando un pelo y creciendo desde 92%.
   24 ms más y se lee como juguete; sin nada, se lee como un fallo de pintado. */
@keyframes lzTemaCambia{
  from{opacity:.35;transform:scale(.92) rotate(-14deg)}
  to  {opacity:1;transform:none}
}


/* ── Registros de entrada ───────────────────────────────────────────────────
   Cuatro gestos distintos, no cuatro repeticiones del mismo. Ninguno desplaza
   más de 14px: la variedad está en la CUALIDAD del movimiento, no en su tamaño. */
@keyframes lzAcerca{ from{opacity:0;transform:scale(.94)}      to{opacity:1;transform:none} }
@keyframes lzSeAsienta{ from{opacity:0;transform:translateY(-10px) scale(.985)} to{opacity:1;transform:none} }
@keyframes lzEnciende{ from{opacity:0} to{opacity:1} }

/* ══ iOS PWA · SAFE-AREA DEL ORBE (SB-01) ═══════════════════════════════════════
   Con apple-mobile-web-app-status-bar-style=black-translucent la barra de estado
   es transparente y deja ver el LIENZO (html), que lleva el fondo del shell
   (--lk-bg-body, p.ej. #0b0b0d) — distinto del fondo del orbe (--lz-base) → una
   franja de otro color en la zona de la hora/batería. Se iguala el lienzo al
   orbe SOLO mientras el orbe está abierto (login/desbloqueo). :has = iOS 15.4+. */
html:has(.lz-lock.open){background:#07080c}
html[data-theme="midnight"]:has(.lz-lock.open){background:#03040b}
html[data-theme="cyan"]:has(.lz-lock.open){background:#04090e}

/* ══ ENTORNO DEV · tema TEAL completo + etiqueta «dev» sobre el orbe (DEV-01) ══
   Se activa con `.lz-lock.is-dev` (lo pone el JS de login/desbloqueo por subdominio
   dev.*, la misma detección del favicon/ícono dev). Aplica los MISMOS tokens del
   tema cyan sobre el .lz-lock: como el orbe, el fondo, el halo, el aura y los
   acentos se pintan por tokens (--lz-*), TODO el login/desbloqueo vira al teal
   SIN tocar data-theme ni persistir lz_theme (no corrompe el tema de la app, que
   no conoce cyan). Va al final: gana por orden a los bloques de tema. En
   producción no se aplica nada. */
.lz-lock.is-dev{
  --lz-base:#04090e;
  --lz-ink:#e0eff4; --lz-ink-2:#b0c7d0; --lz-ink-3:#87a1ad; --lz-ink-4:#6b8390;
  --lz-line:rgba(57,197,207,.26); --lz-line-suave:rgba(57,197,207,.12);
  --lz-glass-1:rgba(57,197,207,.11); --lz-glass-2:rgba(8,145,178,.06); --lz-glass-3:rgba(0,0,0,.18);
  --lz-glass-borde:rgba(57,197,207,.58);
  --lz-specular:rgba(255,255,255,.14); --lz-specular-2:rgba(255,255,255,.20);
  --lz-ring:rgba(8,145,178,.16); --lz-foco:rgba(150,230,240,.42);
  --lz-btn-fondo:rgba(57,197,207,.055); --lz-btn-activo:rgba(57,197,207,.09);
  --lz-campo:rgba(57,197,207,.07); --lz-campo-2:rgba(0,0,0,.14);
  --lz-au-1:rgba(8,145,178,.52); --lz-au-1b:rgba(14,116,144,.44); --lz-au-1c:rgba(21,94,117,.30);
  --lz-au-1d:rgba(12,74,90,.16); --lz-au-1e:rgba(12,74,90,.06);
  --lz-au-2:rgba(57,197,207,.28); --lz-au-2b:rgba(8,145,178,.22); --lz-au-2c:rgba(21,94,117,.14);
  --lz-au-2d:rgba(8,58,74,.07);
  --lz-au-3:rgba(103,232,249,.13); --lz-au-3b:rgba(8,145,178,.07);
  --lz-orbe-1:#eafcff; --lz-orbe-2:#a5e9f2; --lz-orbe-3:#39c5cf; --lz-orbe-4:#0891b2; --lz-orbe-5:#0b4f63;
  --lz-orbe-halo:rgba(57,197,207,.55); --lz-orbe-sombra:rgba(8,145,178,.6); --lz-orbe-hondo:rgba(6,42,58,.68);
  --lz-chispa:#b8f2f8; --lz-chispa-luz:rgba(103,232,249,.85);
  --lz-aura:rgba(8,145,178,.18);
}
/* El lienzo (safe-area SB-01) también teal cuando el orbe dev está abierto. */
html:has(.lz-lock.is-dev.open){background:#04090e}
/* Etiqueta «dev» montada en el borde inferior-derecho del orbe. */
.lz-lock-devtag{display:none}
.lz-lock.is-dev .lz-lock-devtag{position:absolute;z-index:4;right:-8px;bottom:-2px;display:inline-flex;align-items:center;gap:5px;
  font:700 9px/1 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;letter-spacing:.12em;text-transform:uppercase;color:#04121a;
  background:#a5e9f2;border:.5px solid rgba(255,255,255,.35);border-radius:99px;padding:4px 7px 3px;box-shadow:0 3px 10px rgba(0,0,0,.45)}
.lz-lock.is-dev .lz-lock-devtag i{width:4px;height:4px;border-radius:50%;background:#0891b2}
