/* ============================================================
   SAM — Shell de la app
   Móvil: topbar (mirar) + nav inferior (tocar, zona del pulgar).
   Desktop: rail lateral textual fijo (nada de hamburguesa) +
   contenido ancho. Fondo negro con grid neón sutil.
   ============================================================ */

/* ---- Fondo vivo ---- */
.app-bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(ellipse 95% 65% at 50% -10%, rgba(var(--c-primary-rgb), 0.16), transparent 72%),
    radial-gradient(ellipse 60% 40% at 90% 110%, rgba(var(--c-secondary-rgb), 0.08), transparent 60%),
    var(--c-black);
}
.app-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(var(--c-primary-rgb), 0.1) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--c-primary-rgb), 0.1) 1px, transparent 1px);
  background-size: 44px 44px;
  mask-image: radial-gradient(ellipse 100% 90% at 50% 0%, #000 35%, transparent 82%);
  -webkit-mask-image: radial-gradient(ellipse 100% 90% at 50% 0%, #000 35%, transparent 82%);
  animation: grid-drift 26s linear infinite;
}
@keyframes grid-drift { to { background-position: 44px 44px, 44px 44px; } }
/* Velocidad del fondo animado, configurable desde /configuracion → Temas
   (theme.bgAnim → <html data-bg-anim>). Sin atributo = normal (26s). */
:root[data-bg-anim='off'] .app-bg::after { animation: none; }
:root[data-bg-anim='slow'] .app-bg::after { animation-duration: 48s; }
:root[data-bg-anim='fast'] .app-bg::after { animation-duration: 10s; }
@media (prefers-reduced-motion: reduce) {
  /* El sistema manda MIENTRAS la persona no elija otra cosa
     (Configuración → Movimiento). */
  :root:not([data-motion='full']) {
  .app-bg::after { animation: none; }
  }
}
/* Patrón del fondo (theme.bgStyle → <html data-bg-style>). Default: la
   rejilla de arriba. Los tres beben de --c-primary-rgb/--c-secondary-rgb,
   así que siguen al tema activo igual que la rejilla. */
:root[data-bg-style='dots'] .app-bg::after {
  /* matriz de puntos; tamaño 44px = el paso de grid-drift, para que el
     bucle de la animación cierre sin salto */
  background-image: radial-gradient(rgba(var(--c-primary-rgb), 0.22) 1.6px, transparent 1.7px);
  background-size: 44px 44px;
}
:root[data-bg-style='aurora'] .app-bg::after {
  background-image:
    radial-gradient(closest-side, rgba(var(--c-primary-rgb), 0.2), transparent),
    radial-gradient(closest-side, rgba(var(--c-secondary-rgb), 0.14), transparent);
  background-size: 65vmax 65vmax, 55vmax 55vmax;
  background-position: -12vmax -12vmax, 65vw 55vh;
  background-repeat: no-repeat;
  filter: blur(34px);
  mask-image: none;
  -webkit-mask-image: none;
  animation: aurora-drift 26s ease-in-out infinite alternate;
}
@keyframes aurora-drift {
  to { background-position: 34vw 22vh, 12vw 6vh; }
}

/* ---- Layout base ---- */
#app { min-height: 100dvh; display: flex; flex-direction: column; }

.app-topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  display: flex;
  align-items: center;
  gap: var(--sp-sm);
  min-height: 58px;
  padding: 0 var(--sp-md);
  padding-top: env(safe-area-inset-top, 0px);
  background: rgba(0, 0, 0, 0.72);
  -webkit-backdrop-filter: var(--blur-glass);
  backdrop-filter: var(--blur-glass);
  border-bottom: 1px solid rgba(var(--c-primary-rgb), 0.18);
}
.app-topbar .brand {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--c-heading, #fff);
  font-weight: 800;
  letter-spacing: 2px;
  font-size: 15px;
  text-transform: uppercase;
  text-shadow: 0 0 12px var(--c-primary-text-shadow);
}
.app-topbar .brand img {
  height: 44px;
  width: auto;
  filter: drop-shadow(0 0 8px var(--c-primary-glow));
}
.app-topbar .brand span { font-size: 17px; }
/* La marca cede antes que los botones. En un telefono de 393px el logo, el
   nombre, el interruptor de tema, la campana y "Salir" no caben a su tamano de
   escritorio, y el nombre se desbordaba 46px por debajo del interruptor (se
   leia "DIEGUIT"). Primero se aprieta; si aun asi no cabe (una marca larga),
   puntos suspensivos en vez de texto pisado por otro control. */
.app-topbar .brand { min-width: 0; flex: 0 1 auto; }
.app-topbar .brand span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 480px) {
  .app-topbar { gap: 6px; padding-left: 12px; padding-right: 12px; }
  .app-topbar .brand { gap: 6px; letter-spacing: 1px; }
  .app-topbar .brand img { height: 38px; }
  .app-topbar .brand span { font-size: 15px; }
}
.topbar-spacer { flex: 1; }
.topbar-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: var(--touch-min);
  min-height: var(--touch-min);
  border: 0;
  background: none;
  color: var(--c-text-variant);
  font-family: var(--font);
  font-size: 13px;
  font-weight: 700;
  border-radius: var(--r-full);
  cursor: pointer;
}
.topbar-btn:hover { color: var(--c-heading, #fff); background: var(--c-primary-glow-soft); }
/* Icono de apagado (SVG inline: no depende de que el sistema tenga el glifo
   U+23FB, que en Android/iOS no existe y dejaba el boton sin icono). */
.ico-power { width: 16px; height: 16px; flex: 0 0 auto; }
.topbar-btn .ico-power { width: 15px; height: 15px; }
.rail-logout .nav-ico { display: inline-flex; align-items: center; justify-content: center; }

/* ---- Vista (punto de montaje de módulos) ---- */
.app-view {
  flex: 1;
  width: 100%;
  max-width: var(--mobile-max);
  margin: 0 auto;
  /* Abajo: la zona de los botones flotantes + 16px (0.26.0: antes 96px a mano). */
  padding: var(--sp-md) var(--sp-sm) calc(var(--sui-float-zone, 70px) + 16px + env(safe-area-inset-bottom, 0px));
  animation: view-in var(--t-slow) var(--ease-out) both;
}
/* 0.26.1: lo que el navegador desplaza por su cuenta (foco con el teclado, un
   ancla, scrollIntoView) se detiene ENCIMA de los botones flotantes, no debajo.
   El relleno de la vista cubre el final de la pagina; esto, el resto. */
@media (max-width: 899.98px) {
  html { scroll-padding-bottom: calc(var(--sui-float-zone, 70px) + 16px); }
}
@keyframes view-in { from { opacity: 0; transform: translateY(10px); } }

/* ---- Telefono: dos botones flotantes en la zona del pulgar ----
   Sustituyen a la barra inferior, que ocupaba ~70px de cada pantalla y en
   Inicio se escondia (el launcher traia su propio dock). Abajo a la izquierda
   la CASA (accesos directos -> modulos -> cerrar); abajo a la derecha las
   SECCIONES de la vista, con el nombre de la actual escrito (Biblia cap.1:
   un icono solo no dice donde estas). Todo en --z-fabnav, por encima de la
   mascota (que se atenua con el fondo al abrir). */
.fab-nav { --fab: 56px; --fab-gap: 14px; }
.fab-backdrop {
  position: fixed; inset: 0; z-index: var(--z-fabnav);
  background: rgba(0, 0, 0, 0.45);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  animation: fab-fade var(--t-fast) var(--ease-out) both;
}
.fab-home, .fab-secciones {
  position: fixed;
  bottom: calc(var(--fab-gap) + env(safe-area-inset-bottom, 0px));
  z-index: calc(var(--z-fabnav) + 2);
  min-height: var(--fab);
  border: 1px solid var(--c-border-glass-strong, var(--c-border-glass));
  background: var(--c-glass-strong);
  -webkit-backdrop-filter: var(--blur-glass); backdrop-filter: var(--blur-glass);
  box-shadow: var(--glow-primary), 0 8px 26px rgba(0, 0, 0, 0.55);
  color: var(--c-heading, #fff);
  font-family: var(--font);
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease-out), box-shadow var(--t-base) var(--ease-out), background var(--t-base);
}
.fab-home {
  left: var(--fab-gap);
  width: var(--fab);
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 24px; line-height: 1;
}
.fab-secciones {
  right: var(--fab-gap);
  max-width: min(58vw, 260px);
  padding: 0 18px 0 14px;
  border-radius: var(--r-full);
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 700; letter-spacing: 0.4px;
}
.fab-secciones[hidden] { display: none; }
.fab-sec-ico { font-size: 16px; line-height: 1; opacity: 0.85; }
.fab-home:active, .fab-secciones:active { transform: scale(0.94); }
.fab-nav[data-estado='1'] .fab-home,
.fab-nav[data-estado='2'] .fab-home,
.fab-nav[data-estado='3'] .fab-secciones {
  color: var(--c-on-primary-container, #001a24);
  background: linear-gradient(100deg, var(--c-primary-container), var(--c-secondary-container));
  box-shadow: 0 0 18px var(--c-primary-glow);
}

/* Menus que suben desde el boton (accesos y secciones) */
.fab-atajos, .fab-secciones-lista {
  position: fixed;
  bottom: calc(var(--fab-gap) + var(--fab) + 12px + env(safe-area-inset-bottom, 0px));
  z-index: calc(var(--z-fabnav) + 1);
  display: flex; flex-direction: column; gap: 8px;
  max-height: calc(100dvh - 180px); overflow-y: auto; overscroll-behavior: contain;
  padding: 2px;
  scrollbar-width: none;
}
.fab-atajos::-webkit-scrollbar, .fab-secciones-lista::-webkit-scrollbar { display: none; }
/* Inicio, el primero, PEGADO a la casa: lo que mas se usa va donde esta el
   pulgar, y el resto sube en cascada. */
.fab-atajos { left: var(--fab-gap); align-items: flex-start; flex-direction: column-reverse; }
.fab-secciones-lista { right: var(--fab-gap); align-items: flex-end; }
.fab-atajos[hidden], .fab-secciones-lista[hidden], .fab-modulos[hidden], .fab-backdrop[hidden] { display: none; }
.fab-item {
  display: inline-flex; align-items: center; gap: 10px;
  min-height: var(--touch-min); max-width: min(78vw, 320px);
  padding: 0 18px 0 14px;
  border-radius: var(--r-full);
  border: 1px solid var(--c-border-glass);
  background: var(--c-glass-strong);
  -webkit-backdrop-filter: var(--blur-glass); backdrop-filter: var(--blur-glass);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
  color: var(--c-text); text-decoration: none;
  font-family: var(--font); font-size: 14px; font-weight: 650;
  cursor: pointer;
  animation: fab-sube 0.22s var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * 32ms);
}
.fab-item .nav-ico { font-size: 19px; line-height: 1; }
.fab-item.is-active {
  color: var(--c-on-primary-container, #001a24);
  background: linear-gradient(100deg, var(--c-primary-container), var(--c-secondary-container));
  border-color: transparent;
}

/* Catalogo de modulos (segundo toque de la casa): hoja desde abajo */
.fab-modulos {
  position: fixed; left: 0; right: 0; bottom: 0;
  z-index: calc(var(--z-fabnav) + 1);
  max-height: 78dvh; overflow-y: auto; overscroll-behavior: contain;
  padding: 16px var(--sp-sm) calc(var(--fab) + var(--fab-gap) + 20px + env(safe-area-inset-bottom, 0px));
  border-radius: 24px 24px 0 0;
  border-top: 1px solid var(--c-border-glass);
  /* Opaca: con el vidrio se leia la lista de detras entre los iconos. */
  background: var(--c-surface, #0d121f);
  box-shadow: 0 -12px 40px rgba(0, 0, 0, 0.5);
  animation: fab-hoja 0.28s var(--ease-out) both;
}
.fab-modulos-titulo {
  margin: 0 0 12px; text-align: center;
  font-size: 11px; font-weight: 700; letter-spacing: 1.6px; text-transform: uppercase;
  color: var(--c-text-muted);
}
.fab-modulos-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(76px, 1fr)); gap: 10px 6px; }
.fab-mod {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  min-height: 84px; padding: 8px 2px; border-radius: 16px;
  text-decoration: none; color: var(--c-text);
}
.fab-mod-ico {
  display: grid; place-items: center; width: 50px; height: 50px; border-radius: 16px;
  font-size: 22px; background: var(--c-surface-container, rgba(255, 255, 255, 0.06));
  border: 1px solid var(--c-border-glass);
}
.fab-mod-label {
  font-size: 11px; font-weight: 650; line-height: 1.2; text-align: center;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
}
.fab-mod.is-active .fab-mod-ico { box-shadow: 0 0 0 2px var(--c-primary-container), 0 0 16px var(--c-primary-glow); }
@keyframes fab-fade { from { opacity: 0; } }
@keyframes fab-sube { from { opacity: 0; transform: translateY(12px) scale(0.96); } }
@keyframes fab-hoja { from { transform: translateY(40px); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion='full']) .fab-item,
  :root:not([data-motion='full']) .fab-modulos,
  :root:not([data-motion='full']) .fab-backdrop { animation: none; }
}

/* ---- Desktop (≥900px): rail lateral textual + contenido ancho ---- */
@media (min-width: 900px) {
  #app.has-nav { flex-direction: row; }
  .app-rail {
    position: sticky;
    top: 0;
    align-self: flex-start;
    height: 100dvh;
    width: 232px;
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: var(--sp-md) var(--sp-xs);
    border-right: 1px solid rgba(var(--c-primary-rgb), 0.18);
    background: rgba(0, 0, 0, 0.5);
    -webkit-backdrop-filter: var(--blur-glass);
    backdrop-filter: var(--blur-glass);
  }
  .app-rail .brand {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 12px 18px;
    text-decoration: none;
    color: var(--c-heading, #fff);
    font-weight: 800;
    letter-spacing: 2px;
    text-transform: uppercase;
    font-size: 14px;
    text-shadow: 0 0 12px var(--c-primary-text-shadow);
  }
  .app-rail .brand img {
    height: 42px;
    width: auto;
    filter: drop-shadow(0 0 8px var(--c-primary-glow));
  }
  .app-rail .brand span { font-size: 15px; }
  .app-rail a.rail-link {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 44px;
    padding: 0 14px;
    border-radius: var(--r-md);
    text-decoration: none;
    color: var(--c-text-variant);
    font-size: 13.5px;
    font-weight: 600;
    letter-spacing: 0.4px;
    transition: color var(--t-fast), background var(--t-base) var(--ease-out);
  }
  .app-rail a.rail-link .nav-ico { font-size: 17px; width: 22px; text-align: center; }
  .app-rail a.rail-link.is-active {
    color: var(--c-heading, #fff);
    background: rgba(var(--c-primary-rgb), 0.14);
    text-shadow: 0 0 10px var(--c-primary-text-shadow);
  }
  .app-rail a.rail-link:not(.is-active):hover { color: var(--c-heading, #fff); background: var(--c-primary-glow-soft); }

  /* Contenedor de accesos directos configurables (drag & drop desde /home).
     Sin position propia: el rail-indicator mide offsetTop contra .app-rail. */
  .rail-links { display: flex; flex-direction: column; gap: 4px; min-height: 44px; }
  .rail-links a.rail-link--shortcut { cursor: grab; }
  .rail-links a.rail-link--shortcut:active { cursor: grabbing; }
  .rail-links a.rail-link.is-dragging { opacity: 0.35; }

  /* Rail como zona de soltado: marco punteado neón mientras se arrastra encima */
  .app-rail.is-drop-hover {
    outline: 2px dashed var(--c-primary-bright, #38bdf8);
    outline-offset: -6px;
    background: rgba(var(--c-primary-rgb), 0.06);
  }

  /* Sin accesos aún: pista de uso */
  .rail-hint {
    margin: 4px 6px;
    padding: 10px 12px;
    border: 1px dashed rgba(var(--c-primary-rgb), 0.35);
    border-radius: var(--r-md);
    color: var(--c-muted, rgba(255, 255, 255, 0.55));
    font-size: 12px;
    line-height: 1.5;
  }

  /* Indicador de módulo activo: marco neón que VIAJA entre enlaces.
     Lo posiciona shell.js (top/left/width/height); el desplazamiento lo
     anima la transition y el "latido" neón el keyframe rail-neon. */
  .rail-indicator {
    position: absolute;
    pointer-events: none;
    border: 1px solid var(--c-primary-bright);
    border-radius: var(--r-md);
    opacity: 0;
    transition:
      top 0.35s var(--ease-out, cubic-bezier(0.22, 1, 0.36, 1)),
      left 0.35s var(--ease-out, cubic-bezier(0.22, 1, 0.36, 1)),
      width 0.35s var(--ease-out, cubic-bezier(0.22, 1, 0.36, 1)),
      height 0.35s var(--ease-out, cubic-bezier(0.22, 1, 0.36, 1)),
      opacity 0.2s ease;
    animation: rail-neon 2.4s ease-in-out infinite;
  }
  @keyframes rail-neon {
    0%, 100% {
      border-color: rgba(var(--c-primary-rgb), 0.55);
      box-shadow:
        0 0 6px rgba(var(--c-primary-rgb), 0.25),
        inset 0 0 4px rgba(var(--c-primary-rgb), 0.12);
    }
    50% {
      border-color: rgba(var(--c-primary-rgb), 1);
      box-shadow:
        0 0 16px rgba(var(--c-primary-rgb), 0.55),
        inset 0 0 9px rgba(var(--c-primary-rgb), 0.3);
    }
  }
  @media (prefers-reduced-motion: reduce) {
  /* El sistema manda MIENTRAS la persona no elija otra cosa
     (Configuración → Movimiento). */
  :root:not([data-motion='full']) {
    .rail-indicator {
      transition: opacity 0.2s ease;
      animation: none;
      box-shadow: 0 0 10px rgba(var(--c-primary-rgb), 0.4);
    }
  }
}
  .rail-foot { margin-top: auto; display: flex; flex-direction: column; gap: 4px; }

  .app-main { flex: 1; min-width: 0; }
  .app-view {
    max-width: 1080px;
    padding: var(--sp-lg) var(--sp-xl) var(--sp-section);
  }
  /* En desktop los botones flotantes se ocultan: manda el rail */
  #app.has-nav .fab-nav { display: none; }
  #app.has-nav .app-topbar { display: none; }
}
@media (max-width: 899.98px) {
  .app-rail { display: none; }
}

/* ---- Transición universal de módulos ----
   Salida: la vista entera se desvanece en bloque (core.js añade
   .view-leave y espera). Entrada: las secciones del módulo (nietos del
   contenedor: cabecera, filtros, listas…) hacen fade-in escalonado de
   arriba hacia abajo. */
/* La salida es una ANIMACIÓN (no transition): .app-view ya lleva una
   animación base con fill, y una animación adherida se queda dueña de la
   opacity — una transition sobre la misma propiedad no llega a correr.
   Al añadir la clase, esta animación sustituye a la base y corre limpia. */
.app-view.view-leave { animation: view-leave-out 320ms var(--ease-in) both; }
@keyframes view-leave-out {
  from { opacity: 1; }
  to { opacity: 0; }
}

.app-view.view-enter > * > * {
  animation: view-section-in 0.6s var(--ease-out) both;
  animation-delay: 0.62s; /* secciones más allá de la 8ª entran al final */
}
.app-view.view-enter > * > *:nth-child(1) { animation-delay: 0.05s; }
.app-view.view-enter > * > *:nth-child(2) { animation-delay: 0.13s; }
.app-view.view-enter > * > *:nth-child(3) { animation-delay: 0.21s; }
.app-view.view-enter > * > *:nth-child(4) { animation-delay: 0.29s; }
.app-view.view-enter > * > *:nth-child(5) { animation-delay: 0.37s; }
.app-view.view-enter > * > *:nth-child(6) { animation-delay: 0.45s; }
.app-view.view-enter > * > *:nth-child(7) { animation-delay: 0.53s; }
.app-view.view-enter > * > *:nth-child(8) { animation-delay: 0.61s; }
@keyframes view-section-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  /* El sistema manda MIENTRAS la persona no elija otra cosa
     (Configuración → Movimiento). */
  :root:not([data-motion='full']) {
  .app-view.view-leave { animation: none; }
  .app-view.view-enter > * > * { animation: none; }
  .app-view { animation: none; }
  }
}

/* ---- Cambiar tema: mismo cuerpo que un rail-link, en botón ---- */
.rail-theme {
  border: 0;
  background: none;
  cursor: pointer;
  font-family: var(--font);
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 0 14px;
  border-radius: var(--r-md);
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: 0.4px;
  text-align: left;
  color: var(--c-text-variant);
  transition: color var(--t-fast), background var(--t-base) var(--ease-out);
}
.rail-theme .nav-ico { font-size: 17px; width: 22px; text-align: center; }
.rail-theme:hover,
.rail-theme:focus-visible {
  color: var(--c-heading, #fff);
  background: var(--c-primary-glow-soft);
}
/* ---- Toggle sol/luna (base Uiverse.io by JkHuger, adaptado a tokens) ----
   checked = oscuro. Sin .theme__fill del original: el wipe de pantalla con
   mix-blend-mode pelearía con el theming real por data-theme. El resto de la
   coreografía (slide del knob, sol→luna con rayos plegándose) queda intacta. */
.theme {
  --transDur: 0.3s;
  --theme-primary: var(--c-primary, #38bdf8);
  --theme-primaryT: color-mix(in srgb, var(--c-primary, #38bdf8) 55%, transparent);
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
/* La escala em vive en el wrap, NO en .theme: así el texto del label
   ("Modo claro/oscuro") conserva la fuente del rail. Track 42×21px. */
.theme__toggle-wrap { font-size: 7px; }
.theme__text { user-select: none; }
/* En el rail, el label ocupa toda la fila: cualquier punto del item conmuta. */
.rail-theme .theme { width: 100%; min-height: 44px; }
.theme__icon { transition: 0.3s; }
.theme__icon, .theme__toggle { z-index: 1; }
.theme__icon, .theme__icon-part { position: absolute; }
/* Centro del knob: padding .25em + radio 1.25em = 1.5em; icono de 1.5em →
   offset .75em. El .5em del asset original lo dejaba descentrado. */
.theme__icon { display: block; top: 0.75em; left: 0.75em; width: 1.5em; height: 1.5em; pointer-events: none; }
.theme__icon-part {
  border-radius: 50%;
  box-shadow: 0.4em -0.4em 0 0.5em hsl(0, 0%, 100%) inset;
  top: calc(50% - 0.5em);
  left: calc(50% - 0.5em);
  width: 1em;
  height: 1em;
  transition: box-shadow var(--transDur) ease-in-out,
    opacity var(--transDur) ease-in-out,
    transform var(--transDur) ease-in-out;
  transform: scale(0.5);
}
.theme__icon-part ~ .theme__icon-part {
  background-color: hsl(0, 0%, 100%);
  border-radius: 0.05em;
  top: 50%;
  left: calc(50% - 0.05em);
  transform: rotate(0deg) translateY(0.5em);
  transform-origin: 50% 0;
  width: 0.1em;
  height: 0.2em;
}
.theme__icon-part:nth-child(3) { transform: rotate(45deg) translateY(0.45em); }
.theme__icon-part:nth-child(4) { transform: rotate(90deg) translateY(0.45em); }
.theme__icon-part:nth-child(5) { transform: rotate(135deg) translateY(0.45em); }
.theme__icon-part:nth-child(6) { transform: rotate(180deg) translateY(0.45em); }
.theme__icon-part:nth-child(7) { transform: rotate(225deg) translateY(0.45em); }
.theme__icon-part:nth-child(8) { transform: rotate(270deg) translateY(0.5em); }
.theme__icon-part:nth-child(9) { transform: rotate(315deg) translateY(0.5em); }
.theme__toggle, .theme__toggle-wrap { position: relative; }
.theme__toggle, .theme__toggle::before { display: block; }
.theme__toggle {
  /* Lado sol (claro activo): también en el acento del tema — feedback del
     owner 2026-08-11: el amarillo fijo desentonaba con temas no-cálidos. */
  background-color: color-mix(in srgb, var(--c-primary-bright, #38bdf8) 28%, #ffffff);
  border-radius: 25% / 50%;
  box-shadow: 0 0 0 0.125em var(--theme-primaryT);
  padding: 0.25em;
  width: 6em;
  height: 3em;
  margin: 0;
  /* CRÍTICO: los input no heredan font-size; sin esto los em del track se
     calculan a 16px (96×48px gigante) y desalineados con el icono (7px). */
  font-size: inherit;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: background-color var(--transDur) ease-in-out,
    box-shadow 0.15s ease-in-out,
    transform var(--transDur) ease-in-out;
}
.theme__toggle::before {
  background-color: var(--c-primary-bright, hsl(48, 90%, 55%));
  border-radius: 50%;
  content: "";
  width: 2.5em;
  height: 2.5em;
  transition: 0.3s;
}
.theme__toggle:focus {
  box-shadow: 0 0 0 0.125em var(--theme-primary);
  outline: transparent;
}
/* Lado luna (oscuro activo): track y knob en el ACENTO del tema — con un tema
   Rubí el toggle es rubí, no el azul de fábrica. El lado sol queda amarillo a
   propósito: el sol es semántica de "claro", no marca. */
.theme__toggle:checked { background-color: color-mix(in srgb, var(--c-primary-bright, #38bdf8) 18%, #06090f); }
.theme__toggle:checked::before,
.theme__toggle:checked ~ .theme__icon { transform: translateX(3em); }
.theme__toggle:checked::before { background-color: var(--c-primary-bright, hsl(198, 90%, 55%)); }
/* Luna centrada: el asset original la desplazaba (.2em/-.2em) porque su icono
   ya venía descentrado; con el icono bien anclado, la luna (1em) se centra en
   la caja de 1.5em con .25em exactos por lado. */
.theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(1) {
  box-shadow: 0.2em -0.2em 0 0.2em hsl(0, 0%, 100%) inset;
  transform: scale(1);
  top: 0.25em;
  left: 0.25em;
}
.theme__toggle:checked ~ .theme__icon .theme__icon-part ~ .theme__icon-part { opacity: 0; }
.theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(2) { transform: rotate(45deg) translateY(0.8em); }
.theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(3) { transform: rotate(90deg) translateY(0.8em); }
.theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(4) { transform: rotate(135deg) translateY(0.8em); }
.theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(5) { transform: rotate(180deg) translateY(0.8em); }
.theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(6) { transform: rotate(225deg) translateY(0.8em); }
.theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(7) { transform: rotate(270deg) translateY(0.8em); }
.theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(8) { transform: rotate(315deg) translateY(0.8em); }
.theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(9) { transform: rotate(360deg) translateY(0.8em); }
.theme__toggle-wrap { margin: 0; }
@supports selector(:focus-visible) {
  .theme__toggle:focus { box-shadow: 0 0 0 0.125em var(--theme-primaryT); }
  .theme__toggle:focus-visible { box-shadow: 0 0 0 0.125em var(--theme-primary); }
}
@media (prefers-reduced-motion: reduce) {
  /* El sistema manda MIENTRAS la persona no elija otra cosa
     (Configuración → Movimiento). */
  :root:not([data-motion='full']) {
  .theme__toggle, .theme__toggle::before, .theme__icon, .theme__icon-part { transition: none !important; }
  }
}
/* ---- Cerrar sesión: latido rojo constante + hover ---- */
.rail-logout {
  border: 0;
  background: none;
  cursor: pointer;
  font-family: var(--font);
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 0 14px;
  border-radius: var(--r-md);
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: 0.4px;
  text-align: left;
  color: var(--c-text-variant);
  animation: logout-ember 3s ease-in-out infinite;
  transition:
    background var(--t-base) var(--ease-out),
    text-shadow var(--t-fast),
    transform var(--t-fast) var(--ease-out);
}
@keyframes logout-ember {
  0%, 100% { color: var(--c-text-variant); text-shadow: none; }
  50% { color: #ff8a80; text-shadow: 0 0 10px rgba(255, 82, 82, 0.45); }
}
.rail-logout:hover,
.rail-logout:focus-visible {
  animation: none;
  color: #ff8a80;
  background: rgba(255, 82, 82, 0.12);
  text-shadow: 0 0 12px rgba(255, 82, 82, 0.55);
  transform: translateX(2px);
}
.rail-logout:active { transform: translateX(2px) scale(0.98); }
@media (prefers-reduced-motion: reduce) {
  /* El sistema manda MIENTRAS la persona no elija otra cosa
     (Configuración → Movimiento). */
  :root:not([data-motion='full']) {
  .rail-logout { animation: none; transition: none; }
  .rail-logout:hover, .rail-logout:focus-visible { transform: none; }
  }
}

/* ---- Usuario + campana (pie del rail / topbar) ---- */
.rail-user-row { display: flex; align-items: center; gap: 8px; }
.rail-user-row .rail-link { flex: 1; min-width: 0; }

.rail-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  overflow: hidden;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  background: var(--c-surface-high);
  border: 1px solid var(--c-border-glass);
  color: var(--c-primary);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.5px;
}
.rail-avatar img { width: 100%; height: 100%; object-fit: cover; }

/* Campana (base Uiverse.io by vinodjangid07, adaptada a tokens) */
.bell-btn {
  width: 44px;
  height: 44px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--c-surface-high);
  border-radius: 50%;
  cursor: pointer;
  transition-duration: 0.3s;
  box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.13);
  border: 1px solid var(--c-outline-variant);
  flex: 0 0 auto;
}
.bell-btn .bell { width: 16px; }
.bell-btn .bell path { fill: var(--c-text); }
.bell-btn:hover { background: var(--c-surface-highest); border-color: var(--c-border-glass); }
.bell-btn:hover .bell { animation: bellRing 0.9s both; }
.bell-btn:active { transform: scale(0.85); }

@keyframes bellRing {
  0%, 100% { transform-origin: top; }
  15% { transform: rotateZ(10deg); }
  30% { transform: rotateZ(-10deg); }
  45% { transform: rotateZ(5deg); }
  60% { transform: rotateZ(-5deg); }
  75% { transform: rotateZ(2deg); }
}

/* Badge de pendientes: oculto cuando el atributo hidden está presente */
.bell-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--r-full);
  display: grid;
  place-items: center;
  background: var(--c-error-container);
  color: var(--c-on-error-container);
  border: 2px solid var(--c-black);
  font-size: 10px;
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.bell-badge[hidden] { display: none; }

/* ---- Vista pública (login): centrada, columna 420 ---- */
.auth-screen {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--sp-md);
}
.auth-card { width: min(100%, var(--mobile-max)); padding: var(--sp-xl); }
.auth-logo { display: flex; flex-direction: column; align-items: center; gap: var(--sp-xs); margin-bottom: var(--sp-lg); text-align: center; }
.auth-logo img { height: 162px; width: auto; filter: drop-shadow(0 0 14px var(--c-primary-glow)); }

/* ============================================================
   Modo claro: superficies del chrome que no salen de tokens
   ============================================================ */
:root[data-theme='light'] .app-topbar {
  background: rgba(255, 255, 255, 0.82);
  border-bottom-color: var(--c-border-glass);
}
:root[data-theme='light'] .fab-home,
:root[data-theme='light'] .fab-secciones,
:root[data-theme='light'] .fab-item {
  box-shadow: var(--glow-primary), 0 8px 24px rgba(15, 23, 42, 0.16);
}
:root[data-theme='light'] .fab-item.is-active,
:root[data-theme='light'] .fab-nav[data-estado='1'] .fab-home,
:root[data-theme='light'] .fab-nav[data-estado='2'] .fab-home,
:root[data-theme='light'] .fab-nav[data-estado='3'] .fab-secciones { color: #ffffff; }
:root[data-theme='light'] .fab-backdrop { background: rgba(15, 23, 42, 0.25); }
:root[data-theme='light'] .app-rail {
  background: rgba(255, 255, 255, 0.66);
  border-right-color: var(--c-border-glass);
}
:root[data-theme='light'] .app-rail a.rail-link.is-active { background: var(--c-primary-glow-soft); }
:root[data-theme='light'] .rail-hint { color: var(--c-text-muted); }

/* Icono de módulo (Lucide via CSS mask). El SVG es la FORMA; el color es
   currentColor del contexto — el rail lo pinta como su texto y el tema activo
   lo re-tiñe gratis. 1em: hereda el tamaño del glifo que sustituye, así la
   misma forma sirve en la tile grande y en el rail pequeño. */
.ico-svg {
  display: inline-block;
  width: 1em; height: 1em;
  vertical-align: -0.12em;
  background: currentColor;
  -webkit-mask: var(--ico) center / contain no-repeat;
  mask: var(--ico) center / contain no-repeat;
}
/* Un icono multicolor (pack "color") no se enmascara: se pinta como imagen con
   el mismo hueco que la mascara, para que el resto del CSS no note la
   diferencia. */
.ico-img {
  display: inline-block;
  width: 1em; height: 1em;
  vertical-align: -0.12em;
  object-fit: contain;
  user-select: none;
}
/* El pack de la mascota es un DIBUJO con contorno grueso, no un trazo: a 1em se
   ve mas chico que el glifo de al lado porque su tinta esta repartida en vez de
   concentrada en una linea. Sube a 1.25em para igualar el tamano OPTICO, que es
   el que se percibe. Cabe: el hueco del rail mide 22px y la fuente 17. */
:root[data-icon-pack="maneirito"] .nav-ico .ico-img,
:root[data-icon-pack="maneirito"] .fab-mod-ico .ico-img { width: 1.25em; height: 1.25em; }

/* ---- Una vista que se presenta como APP (motor 0.31, `presentation:"app"`) ----
   Solo en el telefono. La cabecera del panel se queda en «‹ Inicio» y la
   campana: el titulo NO se repite aqui porque la cabecera de la vista ya lo
   lleva, con las flechas de sus secciones. Fuera la mascota y los botones
   flotantes: salir es la flecha de arriba, cambiar de seccion es deslizar o
   las flechas de la cabecera, y abajo queda sitio para el dock de la vista. */
.topbar-app-back { display: none; }
html[data-device='phone'][data-presentacion='app'] .app-topbar .brand,
html[data-device='phone'][data-presentacion='app'] .app-topbar .theme,
html[data-device='phone'][data-presentacion='app'] .app-topbar [data-action='logout'] { display: none; }
html[data-device='phone'][data-presentacion='app'] .topbar-app-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--touch-min);
  padding: 0 14px 0 8px;
  border-radius: var(--r-full);
  color: var(--c-heading, #fff);
  font-family: var(--font);
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
}
html[data-device='phone'][data-presentacion='app'] .topbar-app-back span:first-child {
  font-size: 26px;
  line-height: 1;
  color: var(--c-primary);
  text-shadow: 0 0 10px rgba(var(--c-primary-rgb), 0.55);
}
html[data-device='phone'][data-presentacion='app'] .topbar-app-back:active { background: var(--c-primary-glow-soft); }
html[data-device='phone'][data-presentacion='app'] .fab-nav,
html[data-device='phone'][data-presentacion='app'] .bob-fab,
html[data-device='phone'][data-presentacion='app'] .bob-bubble { display: none; }
html[data-device='phone'][data-presentacion='app'] { --sui-float-zone: 12px; }
html[data-device='phone'][data-presentacion='app'] .app-view { overscroll-behavior-y: contain; }
