* {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
      -webkit-tap-highlight-color: transparent
    }

    html,
    body {
      height: 100%;
      /* Fondo por TOKEN para que el toggle de tema funcione sin estilos inline
         (gApplyTheme ya no pinta body.style.background). */
      background: var(--color-bg, #0A0F1E);
      font-family: "Inter", system-ui, sans-serif;
      overflow: hidden;
      -webkit-font-smoothing: antialiased;
      /* iOS infla el texto solo al recomponer la vista (volver del bloqueo,
         rotar, cambiar de app). Fijarlo a 100% desactiva ese autoajuste y las
         fuentes ya no "crecen solas" al reabrir la app. */
      -webkit-text-size-adjust: 100%;
      text-size-adjust: 100%
    }

    /* ── LOGIN OVERLAY ──────────────────────────────────────────────── */
    #login-overlay {
      position: fixed;
      inset: 0;
      z-index: 9999;
      background: var(--color-bg, #0A0F1E);
      /* Centro con margin:auto en .lcard + overflow para que, al abrir el
         teclado y reducirse el alto, se pueda desplazar sin tapar campos. */
      display: flex;
      overflow-y: auto;
      -webkit-overflow-scrolling: touch;
      padding: calc(24px + env(safe-area-inset-top)) 20px calc(24px + env(safe-area-inset-bottom));
      transition: opacity .35s;
    }

    #login-overlay.hiding {
      opacity: 0;
      pointer-events: none;
    }
    /* Face ID SIEMPRE por delante: mientras el gate biométrico está pendiente,
       ocultamos el formulario para que iOS no pueda autorrellenarlo antes de pasar
       la cara. Se revela al superar el gate (o al agotar el tope de seguridad). */
    body.bio-gate #login-overlay { display: none !important; }

    .lcard {
      width: 100%;
      max-width: 340px;
      /* Arriba (no centrado) para que el teclado/autorrelleno no tape el formulario */
      margin: 5vh auto 24px;
    }

    .lbrand {
      display: flex;
      flex-direction: column;
      align-items: center;
      margin-bottom: 22px;
    }

    .lbrand-logo {
      position: relative;
      width: 74px;
      height: 74px;
      display: flex;
      align-items: center;
      justify-content: center;
      margin-bottom: 12px;
      animation: nibo-enter 1s cubic-bezier(.2, .8, .2, 1) both;
    }
    /* Aura suave detrás del símbolo (efecto elegante de portada). ESTÁTICA a
       propósito: animar opacity/scale de un elemento con blur repinta cada
       fotograma y daba tirones (lag) en la portada del móvil. */
    .lbrand-logo::after {
      content: "";
      position: absolute;
      inset: -14px;
      border-radius: 50%;
      background: radial-gradient(circle, rgba(108, 140, 255, .42), rgba(32, 214, 166, .16) 45%, transparent 72%);
      filter: blur(8px);
      z-index: 0;
      opacity: .8;
    }

    .lbrand-logo svg {
      position: relative;
      z-index: 1;
      width: 70px;
      height: 70px;
      transform-origin: center;
      animation: brand-o-spin 7s ease-in-out infinite 1s;
    }
    /* El punto verde (la base de la "O") late suavemente */
    .lbrand-logo svg circle:last-of-type {
      transform-box: fill-box;
      transform-origin: center;
      animation: nibo-dot 2.4s ease-in-out infinite;
    }
    @keyframes nibo-enter { from { opacity: 0; transform: scale(.5) rotate(-45deg); } to { opacity: 1; transform: none; } }
    @keyframes nibo-dot { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.28); } }

    /* Símbolo (la "O") en la cabecera de Configuración, gira de vez en cuando */

    @media (prefers-reduced-motion: reduce) {
      .lbrand-logo, .lbrand-logo::after, .lbrand-logo svg, .lbrand-logo svg circle:last-of-type { animation: none !important; }
    }

    .lbrand-name {
      font-family: "Sora", system-ui, sans-serif;
      font-size: 30px;
      font-weight: 800;
      letter-spacing: .05em;
      color: var(--color-text);
    }

    .lbrand-sub {
      font-size: 13px;
      color: var(--color-text-muted);
      margin-top: 4px;
      font-weight: 500;
    }

    .lfield {
      margin-bottom: 14px;
    }

    .lfield label {
      display: block;
      font-size: 11px;
      font-weight: 700;
      color: var(--color-text-muted);
      text-transform: uppercase;
      letter-spacing: .06em;
      margin-bottom: 6px;
    }

    .lfield input {
      width: 100%;
      background: var(--color-surface);
      border: 1px solid var(--color-border);
      border-radius: 11px;
      padding: 13px 14px;
      color: var(--color-text);
      /* 16px como MÍNIMO en inputs: por debajo, Safari iOS hace zoom de página al
         enfocar y el usuario tiene que pellizcar para volver. */
      font-size: 16px;
      outline: none;
      /* Fuente del SISTEMA (no la webfont): en iOS, la webfont hacía que los
         puntos de la contraseña (•) salieran como cuadros "tofu". El sistema los
         dibuja siempre bien. */
      font-family: -apple-system, system-ui, "Segoe UI", Roboto, sans-serif;
      transition: border-color .15s;
    }

    .lfield input:focus {
      border-color: var(--color-focus);
    }

    .lfield input::placeholder {
      color: var(--color-text-muted);
      opacity: .55;
    }

    .lpass-wrap {
      position: relative;
    }

    .lpass-wrap input {
      padding-right: 44px;
    }

    .lpass-toggle {
      position: absolute;
      right: 14px;
      top: 50%;
      transform: translateY(-50%);
      background: none;
      border: none;
      cursor: pointer;
      padding: 4px;
      color: var(--color-text-muted);
    }

    .lpass-toggle svg {
      width: 18px;
      height: 18px;
      stroke: currentColor;
      fill: none;
      stroke-width: 1.75;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .lbtn {
      width: 100%;
      padding: 14px;
      margin-top: 6px;
      background: var(--color-primary);
      border: none;
      border-radius: 11px;
      color: var(--color-on-primary);
      font-size: 15px;
      font-weight: 700;
      font-family: inherit;
      cursor: pointer;
      transition: background .15s, opacity .15s;
    }

    .lbtn:hover {
      background: var(--color-primary-hover);
    }

    .lbtn:disabled {
      opacity: .5;
      cursor: not-allowed;
    }

    .lbtn-inner {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
    }

    .lsp {
      width: 16px;
      height: 16px;
      border: 2px solid rgba(255, 255, 255, .3);
      border-top-color: #fff;
      border-radius: 50%;
      animation: spin .8s linear infinite;
      display: none;
    }

    .lbtn.loading .lsp {
      display: block;
    }

    .lbtn.loading .lbtn-text {
      display: none;
    }

    .lerr {
      margin-top: 12px;
      padding: 10px 14px;
      background: var(--color-danger-bg);
      border: 1px solid var(--color-danger);
      border-radius: 10px;
      color: var(--color-danger);
      font-size: 13px;
      display: none;
    }

    .lerr.show {
      display: block;
    }

    /* ── FRAMES ─────────────────────────────────────────────────────── */
    .fw {
      position: fixed;
      /* A pantalla COMPLETA (también bajo el reloj/notch): el iframe no puede
         leer env(), así que el shell mide los insets y se los pasa al panel por
         postMessage ({type:'safeArea'}); el panel reserva el hueco con --sat. */
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: var(--color-bg, #0A0F1E);
      transform: translateX(-110%);
      pointer-events: none;
    }

    .fw.act {
      transform: translateX(0);
      pointer-events: auto;
      animation: frameIn 0.15s ease;
    }

    @keyframes frameIn {
      from { opacity: 0; }
      to   { opacity: 1; }
    }

    .fw iframe {
      width: 100%;
      height: 100%;
      border: none;
      background: #0A0F1E;
    }

    /* El marco llega hasta abajo: la cápsula de navegación FLOTA sobre el
       contenido (sin franja de shell alrededor). El panel reserva margen
       inferior propio para que nada quede tapado por la cápsula. */
    body.authed .fw.act {
      bottom: 0;
    }

    /* ── NAV: invisible hasta body.authed ───────────────────────────── */
    #nav {
      position: fixed;
      /* Cápsula FLOTANTE de cristal (modelo WhatsApp): translúcida con desenfoque
         fuerte, el contenido de la app se ve DETRÁS difuminado. Flota sobre el
         borde con márgenes laterales, dejando ver la app alrededor. NO hay velo
         sólido debajo (eso oscurecía la zona y parecía una banda negra). */
      bottom: max(8px, calc(env(safe-area-inset-bottom, 0px) - 20px));
      left: 10px;
      right: 10px;
      height: 58px;
      background: rgba(18, 23, 40, 0.72);
      -webkit-backdrop-filter: blur(24px) saturate(180%);
      backdrop-filter: blur(24px) saturate(180%);
      border: 1px solid rgba(255, 255, 255, 0.10);
      border-radius: 30px;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
      align-items: center;
      padding: 0 6px;
      z-index: 200;
      display: none;
    }

    body.authed #nav {
      display: flex;
      animation: navIn .28s ease both;
    }

    /* Con un modal del panel abierto, ocultamos el nav flotante para que no tape
       el botón Guardar. Al cerrarse, el nav vuelve (con su animación de entrada).
       SOLO en móvil: la cápsula flota sobre el contenido y sí taparía botones;
       el rail lateral de escritorio nunca los tapa, así que allí se mantiene
       (regla en la media query de escritorio). */
    @media (max-width: 1023px) {
      body.nav-hidden #nav {
        display: none !important;
      }
    }

    /* En la barra INFERIOR (móvil) la búsqueda ya vive en la cabecera del panel
       (lupa): el botón "Buscar" del rail solo estrecharía los 6 accesos. Se
       muestra únicamente en el rail lateral de escritorio (≥1024px). */
    @media (max-width: 1023px) {
      #nb-buscar {
        display: none !important;
      }
    }

    /* Modo TÉCNICO: la barra muestra SOLO "Actuaciones" (las sub-pestañas
       Incidencias/Presupuestos/Preventivos van dentro de la vista, vía actToggle).
       La Configuración la abre el avatar de la cabecera del panel, no la barra. */
    body.tech #nav button:not(#nb-actuaciones) {
      display: none !important;
    }

    /* ── CTA de acceso de técnicos en la portada ─────────────────────── */
    .tec-cta-ico {
      width: 36px;
      height: 36px;
      flex-shrink: 0;
      border-radius: 10px;
      background: var(--manto-gradient);
      display: flex;
      align-items: center;
      justify-content: center;
      color: #fff;
    }
    .tec-cta-ico svg { width: 18px; height: 18px; }
    /* Cabecera del formulario de técnico (mismo lenguaje que la CTA) */
    .tec-head {
      display: flex;
      align-items: center;
      gap: 12px;
      margin-bottom: 16px;
    }
    .tec-head .tec-cta-ico { width: 40px; height: 40px; }
    .tec-head-t { font-size: 16px; font-weight: 800; color: var(--color-text); }
    .tec-head-s { font-size: 12.5px; color: var(--color-text-muted); margin-top: 2px; }

    /* Con Configuración abierta, la barra flota POR ENCIMA del overlay (que cubre
       toda la pantalla) y se vuelve OPACA (sin cristal): así no quedan huecos ni
       se transparenta el borde del menú a través de ella. Sigue clicable (es la
       vía para salir de Configuración tocando otra pestaña). */
    body.cfg-open #nav {
      z-index: 350;
      background: #141a2c;
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
    }
    /* Con Configuración abierta, el marco de la app se OCULTA (el overlay opaco
       lo cubre entero de todos modos). En el iPhone del usuario el overlay se
       abría (telemetría: cfgMsg ok) pero NO se veía — todo apunta a un fallo de
       composición de iOS con el iframe pintándose sobre el overlay pese al
       z-index. Ocultarlo elimina esa posibilidad de raíz (y ahorra GPU). */
    body.cfg-open .fw {
      visibility: hidden;
    }
    html.light body.cfg-open #nav,
    body.light.cfg-open #nav {
      background: #fff;
    }


    @keyframes navIn {
      from { opacity: 0; transform: translateY(10px); }
      to   { opacity: 1; transform: none; }
    }
    @media (prefers-reduced-motion: reduce) {
      body.authed #nav { animation: none; }
    }

    .nb {
      flex: 1;
      min-width: 0;
      height: 48px;
      margin: 0 1px;
      background: transparent;
      border: none;
      border-radius: 16px;
      color: var(--color-text-muted);
      font-family: inherit;
      font-size: 10px;
      font-weight: 700;
      cursor: pointer;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 4px;
      padding: 6px 2px;
      transition: color .18s, background .18s;
      text-transform: none;
      letter-spacing: 0;
      line-height: 1;
      text-align: center;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      max-width: 100%;
    }

    .nb svg {
      width: 22px;
      height: 22px;
      stroke: currentColor;
      fill: none;
      stroke-width: 1.75;
      stroke-linecap: round;
      stroke-linejoin: round;
      flex-shrink: 0;
    }

    .nb.act {
      color: var(--color-primary);
      background: rgba(255, 255, 255, 0.10);
    }

    /* El login ya se pinta con tokens --color-* (claro/oscuro automático), así
       que no necesita overrides de modo claro propios. */

    /* ── FRAMES / CARGA: modo claro ────────────────────────────────── */
    html.light,
    html.light body,
    html.light .fw,
    html.light .fw iframe,
    body.light .fw,
    body.light .fw iframe,
    body.light .ild {
      background: #f5f7fa;
    }

    html.light #nav,
    body.light #nav {
      background: rgba(255, 255, 255, 0.78);
      border: 1px solid rgba(0, 0, 0, 0.06);
      box-shadow: 0 10px 30px rgba(20, 30, 60, 0.16);
    }
    html.light .nb.act,
    body.light .nb.act {
      background: rgba(59, 111, 255, 0.12);
    }

    /* Cabecera (logo), selector de organización y pie (cuenta) del rail: SOLO
       existen en la barra lateral de escritorio. En móvil (cápsula flotante) no
       se pintan. (El JS puede poner display inline en #nav-org; con inline vacío
       manda esta regla en móvil y la de escritorio en pantalla ancha.) */
    .nav-brand, .nav-org, .nav-grouplbl, .nav-foot { display: none; }
    /* .nav-main (envoltorio de la navegación del rail) no debe existir como caja en
       móvil: display:contents la disuelve y sus hijos siguen siendo la cápsula. La
       pestaña Configuración del rail y la capa .nav-cfg son SOLO de escritorio. */
    .nav-main { display: contents; }
    .nav-cfg-btn, .nav-cfg { display: none; }

    /* ═══ ESCRITORIO (>=1024px): la cápsula pasa a BARRA LATERAL ═══════════════
       Panel expandido: logo NIBO arriba, pestañas con icono + etiqueta, y pie
       con Configuración + Salir. El contenido (.fw) se desplaza a la derecha
       para dejarle sitio. En <1024px NADA de esto aplica: la barra sigue siendo
       la cápsula flotante de abajo, intacta. */
    @media (min-width: 1024px) {
      :root { --nav-w: 295px; }

      #nav {
        /* De cápsula flotante a columna anclada al borde izquierdo. */
        top: 0;
        bottom: 0;
        left: 0;
        right: auto;
        width: var(--nav-w);
        height: auto;
        flex-direction: column;
        align-items: stretch;
        gap: 2px;
        padding: 16px 14px;
        border: none;
        border-right: 1px solid var(--color-border);
        border-radius: 0;
        /* Superficie sólida (ya no cristal flotante): es un panel de navegación. */
        background: var(--color-surface);
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
        box-shadow: none;
        overflow-y: auto;
        /* El cross-slide de Configuración (Opción 2) mueve las capas en X; que no
           provoque scroll horizontal. */
        overflow-x: hidden;
      }
      body.authed #nav { animation: navSideIn .3s ease both; }

      /* En escritorio .nav-main SÍ es una caja: columna flexible que llena el rail
         (el pie sigue anclado abajo con margin-top:auto). Es la capa que se desliza
         fuera al abrir Configuración. */
      #nav .nav-main {
        display: flex;
        flex-direction: column;
        flex: 1 1 auto;
        min-height: 0;
        transition: transform .32s cubic-bezier(.4, 0, .2, 1), opacity .24s ease;
      }
      #nav.cfg-mode .nav-main { transform: translateX(-24%); opacity: 0; pointer-events: none; }

      /* El marco de la app arranca a la derecha del rail (no por debajo). */
      .fw { left: var(--nav-w); transition: left .3s ease; }
      /* Mientras NO hay sesión pintada (arranque/restauración) el rail aún es
         invisible: el marco ocupa TODO el ancho para que el splash NIBO quede
         centrado en la ventana (antes quedaba corrido, centrado en el hueco de
         un rail que no se ve). Al aparecer el rail vuelve a su sitio con la
         misma duración que la entrada del propio rail (navSideIn, .3s). */
      body:not(.authed) .fw { left: 0; }

      .nav-brand {
        display: flex;
        align-items: center;
        gap: 11px;
        padding: 4px 8px 16px;
      }
      .nav-o { width: 30px; height: 30px; flex: 0 0 auto; }
      .nav-o svg { width: 100%; height: 100%; display: block; }
      .nav-word {
        font-family: "Sora", system-ui, sans-serif;
        font-weight: 800;
        font-size: 19px;
        letter-spacing: -.01em;
        color: var(--color-text);
      }

      /* Selector de organización del rail (superadmin/Admin). Su display real lo
         gobierna el JS (inline) + esta media query; base lo oculta en móvil. */
      .nav-org { display: block; margin: 2px 4px 10px; }
      .nav-orgsel {
        width: 100%;
        height: 40px;
        padding: 0 34px 0 12px;
        font-family: inherit;
        font-size: 13px;
        font-weight: 600;
        color: var(--color-text);
        background: var(--color-surface-2);
        border: 1px solid var(--color-border);
        border-radius: 12px;
        cursor: pointer;
        -webkit-appearance: none;
        appearance: none;
        /* Chevron dibujado (SVG data-uri) a la derecha; sin depender del nativo. */
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%239AA6BF' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: right 11px center;
        transition: border-color .16s;
      }
      .nav-orgsel:hover { border-color: var(--color-primary); }
      .nav-orgsel:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 1px; }

      /* Cada pestaña: fila con icono + etiqueta a la izquierda (ya no columna). */
      #nav .nb {
        flex: 0 0 auto;
        height: auto;
        margin: 0 0 1px;
        flex-direction: row;
        justify-content: flex-start;
        gap: 11px;
        padding: 8px 10px;
        font-size: 13.5px;
        border-radius: 12px;
        white-space: nowrap;
      }
      /* Icono de cada pestaña en CHIP branded, igual que las secciones de Config
         (.ncfg-ico): cuadro tintado con borde y glifo en el azul de marca. Solo el
         icono principal (> svg); el chevron del botón de Config va aparte. */
      #nav .nb > svg {
        width: 30px; height: 30px;
        flex: 0 0 auto;
        padding: 7px;
        border-radius: 9px;
        background: rgba(59, 111, 255, 0.09);
        border: 1px solid rgba(59, 111, 255, 0.28);
        color: var(--color-primary);
      }

      /* Activo: franja de marca a la izquierda + fondo tenue (no el pill móvil). */
      #nav .nb.act {
        color: var(--color-text);
        background: rgba(59, 111, 255, 0.14);
        position: relative;
      }
      #nav .nb.act::before {
        content: "";
        position: absolute;
        left: 0; top: 8px; bottom: 8px;
        width: 3px;
        border-radius: 3px;
        background: var(--manto-gradient);
      }
      html.light #nav .nb.act,
      body.light #nav .nb.act { background: rgba(59, 111, 255, 0.1); }
      /* El chip se mantiene igual en activo (como en Config): solo cambia el fondo
         de la fila y la franja, no el icono. */
      #nav .nb.act > svg { color: var(--color-primary); }

      /* Feedback al pasar el ratón por una pestaña inactiva. */
      #nav .nb:not(.act):hover { color: var(--color-text); background: rgba(255, 255, 255, 0.045); }
      html.light #nav .nb:not(.act):hover { background: rgba(20, 30, 60, 0.045); }

      /* Etiqueta de grupo ("Operación"): eyebrow sobre las pestañas. */
      .nav-grouplbl {
        display: block;
        font-size: 10px;
        font-weight: 700;
        letter-spacing: .13em;
        text-transform: uppercase;
        color: var(--color-text-muted);
        opacity: .8;
        padding: 6px 12px 7px;
      }

      /* Pie: columna con el bloque de cuenta (nombre → abre Config) ARRIBA y el
         botón de salir a lo ancho DEBAJO. Pegado abajo, separado por una línea. */
      .nav-foot {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
        margin-top: auto;
        padding-top: 10px;
        border-top: 1px solid var(--color-border);
      }
      .nav-account {
        min-width: 0;
        display: flex;
        align-items: center;
        gap: 11px;
        padding: 9px 8px;
        background: transparent;
        border: none;
        border-radius: 12px;
        cursor: pointer;
        font-family: inherit;
        text-align: left;
        transition: background .16s;
      }
      .nav-account:hover { background: rgba(255, 255, 255, 0.05); }
      html.light .nav-account:hover { background: rgba(20, 30, 60, 0.05); }
      .na-av {
        width: 36px;
        height: 36px;
        flex: 0 0 auto;
        border-radius: 50%;
        background: var(--manto-gradient);
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: center;
        font-weight: 800;
        font-size: 13px;
        box-shadow: 0 4px 12px -3px rgba(59, 111, 255, 0.5);
      }
      .na-txt { min-width: 0; display: flex; flex-direction: column; gap: 1px; line-height: 1.22; }
      .na-name {
        font-size: 12.5px;
        font-weight: 700;
        color: var(--color-text);
        /* Nombre COMPLETO: se parte en tantas filas como haga falta (por palabras),
           NUNCA con puntos suspensivos. El pie está pegado abajo y crece hacia
           arriba, así que un nombre largo simplemente ocupa una fila más. */
        white-space: normal;
        overflow-wrap: break-word;
      }
      /* Rol · versión: se parte si no cabe (el botón de salir estrecha la fila),
         en vez de recortar la versión con puntos suspensivos. */
      .na-role { font-size: 10.5px; color: var(--color-text-muted); margin-top: 1px; overflow-wrap: anywhere; }

      /* Botón de SALIR: a lo ancho, DEBAJO de la cuenta. Píldora branded con los
         colores de la app (azul→verde). En reposo va como "ghost" tintado; al
         pasar el ratón se rellena con el degradado de marca, texto blanco y un
         halo suave + micro-elevación. */
      .nav-exit {
        position: relative;
        overflow: hidden;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 8px;
        width: 100%;
        padding: 10px 12px;
        border: 1px solid rgba(59, 111, 255, 0.28);
        border-radius: 12px;
        background: rgba(59, 111, 255, 0.09);
        color: var(--color-primary);
        font-family: inherit;
        font-size: 12.5px;
        font-weight: 700;
        letter-spacing: .01em;
        cursor: pointer;
        transition: color .18s, border-color .18s, background .18s, transform .12s, box-shadow .18s;
      }
      /* Capa del degradado de marca: aparece al hover por opacidad (sin repintar
         el fondo, para que la transición sea suave). */
      .nav-exit::before {
        content: "";
        position: absolute;
        inset: 0;
        background: var(--manto-gradient);
        opacity: 0;
        transition: opacity .18s;
        z-index: 0;
      }
      .nav-exit svg,
      .nav-exit .nav-exit-lbl { position: relative; z-index: 1; }
      .nav-exit svg { width: 17px; height: 17px; stroke: currentColor; fill: none; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; flex: 0 0 auto; }
      .nav-exit:hover {
        color: #fff;
        border-color: transparent;
        transform: translateY(-1px);
        box-shadow: 0 8px 20px -8px rgba(59, 111, 255, 0.6);
      }
      .nav-exit:hover::before { opacity: 1; }
      .nav-exit:active { transform: translateY(0) scale(0.98); }
      .nav-exit:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }

      /* ── Pestaña CONFIGURACIÓN del rail + capa de secciones (Opción 2) ────────── */
      /* La pestaña usa el estilo .nb (icono + etiqueta), se muestra en escritorio y
         se separa un poco del pie con un margen. La flecha gira al abrir. */
      #nav .nav-cfg-btn { display: flex; margin-top: 2px; }
      #nav .nav-cfg-btn .nav-cfg-chev { margin-left: auto; display: inline-flex; color: var(--color-text-muted); transition: transform .3s cubic-bezier(.22, 1, .36, 1); }
      #nav .nav-cfg-btn .nav-cfg-chev svg { width: 15px; height: 15px; }
      #nav.cfg-mode .nav-cfg-btn .nav-cfg-chev { transform: rotate(90deg); }

      /* Capa de secciones: cubre el rail, entra desde la derecha al activar cfg-mode. */
      .nav-cfg {
        display: flex;
        flex-direction: column;
        position: absolute;
        inset: 0;
        padding: 16px 14px;
        background: var(--color-surface);
        transform: translateX(22%);
        opacity: 0;
        pointer-events: none;
        transition: transform .32s cubic-bezier(.4, 0, .2, 1), opacity .24s ease;
        z-index: 2;
      }
      #nav.cfg-mode .nav-cfg { transform: translateX(0); opacity: 1; pointer-events: auto; }

      /* Cabecera de la capa: flecha de volver + título. */
      .ncfg-hd {
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 4px 4px 12px;
        flex-shrink: 0;
      }
      .ncfg-title { font-family: "Sora", system-ui, sans-serif; font-weight: 800; font-size: 16px; letter-spacing: -.01em; color: var(--color-text); }
      .ncfg-back {
        width: 32px; height: 32px; flex: 0 0 auto;
        display: grid; place-items: center;
        background: var(--color-surface-2);
        border: 1px solid var(--color-border);
        border-radius: 10px;
        color: var(--color-text-muted);
        cursor: pointer;
        transition: color .15s, border-color .15s, background .15s, transform .12s;
      }
      .ncfg-back svg { width: 17px; height: 17px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
      .ncfg-back:hover { color: var(--color-text); border-color: var(--color-primary); }
      .ncfg-back:active { transform: scale(.94); }
      .ncfg-back:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 1px; }

      .nav-cfg-list { display: flex; flex-direction: column; gap: 2px; overflow-y: auto; padding-right: 2px; }

      /* Ítem de sección: mismo lenguaje que .nb, con chip de icono branded. */
      .ncfg-item {
        display: flex;
        align-items: center;
        gap: 11px;
        padding: 8px 10px;
        border: none;
        background: none;
        border-radius: 12px;
        color: var(--color-text-muted);
        font-family: inherit;
        font-size: 13.5px;
        font-weight: 600;
        text-align: left;
        cursor: pointer;
        position: relative;
        transition: color .15s, background .15s;
      }
      .ncfg-item:hover { color: var(--color-text); background: rgba(255, 255, 255, 0.045); }
      html.light .ncfg-item:hover { background: rgba(20, 30, 60, 0.045); }
      .ncfg-item.on { color: var(--color-text); background: rgba(59, 111, 255, 0.14); }
      html.light .ncfg-item.on { background: rgba(59, 111, 255, 0.1); }
      .ncfg-item.on::before {
        content: "";
        position: absolute;
        left: 0; top: 8px; bottom: 8px;
        width: 3px;
        border-radius: 3px;
        background: var(--manto-gradient);
      }
      .ncfg-ico {
        width: 30px; height: 30px; flex: 0 0 auto;
        display: grid; place-items: center;
        border-radius: 9px;
        background: rgba(59, 111, 255, 0.09);
        border: 1px solid rgba(59, 111, 255, 0.28);
        color: var(--color-primary);
      }
      .ncfg-ico svg { width: 16px; height: 16px; display: block; }
      .ncfg-lbl { flex: 1; min-width: 0; }

      /* Con Configuración abierta, el rail deja de ir opaco/flotante: se queda
         como panel sólido normal a la izquierda (el override móvil lo volvía una
         cápsula opaca centrada). El overlay de config se abre a su derecha. */
      body.cfg-open #nav {
        z-index: 200;
        background: var(--color-surface);
      }
      html.light body.cfg-open #nav,
      body.light.cfg-open #nav { background: var(--color-surface); }
      /* El overlay de Configuración respeta el rail (arranca a su derecha) para
         que la barra lateral siga visible y utilizable mientras Config está abierta. */
      #cfg-ov { left: var(--nav-w) !important; }

      /* Modo TÉCNICO: la barra lateral se oculta entera (su única pestaña,
         Actuaciones, no justifica un rail; la vista técnica ya es una sola). */
      body.tech #nav { display: none; }
      body.tech .fw { left: 0; }

      /* nav-hidden (modales del panel) ocultaba la cápsula para no tapar el botón
         Guardar; un rail LATERAL nunca tapa botones inferiores, así que en
         escritorio se mantiene visible. */
      body.authed.nav-hidden #nav { display: flex; }
    }

    @keyframes navSideIn {
      from { opacity: 0; transform: translateX(-12px); }
      to   { opacity: 1; transform: none; }
    }
    @media (prefers-reduced-motion: reduce) {
      body.authed #nav { animation: none; }
    }

    @keyframes spin {
      to {
        transform: rotate(360deg)
      }
    }

    /* ── CONFIG GLOBAL ────────────────────────────────────────── */
    /* Configuración: menú lateral (sin recargar todo al cambiar de sección) */
    /* Configuración: todo por tokens de marca (css/manto-colors.css); el tema
       claro/oscuro lo resuelven las variables, sin overrides por color. */
    #cfg-ov {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      /* Cubre TODA la pantalla (fondo opaco = --color-bg) para que no se vea el
         contenido de la app por detrás. La barra flotante va POR ENCIMA de este
         overlay (z-index mayor) y opaca mientras Configuración está abierta, así
         sigue visible y sin huecos ni cortes. El contenido lleva padding inferior
         (.cfg-content) para no quedar oculto tras la barra. */
      bottom: 0;
      z-index: 300;
      font-family: "Inter", system-ui, sans-serif;
      color: var(--color-text);
      font-size: 14px;
      -webkit-font-smoothing: antialiased;
      background: var(--color-bg);
      display: none;
      flex-direction: column;
      padding-top: env(safe-area-inset-top);
    }

    .cfg-topbar {
      display: flex;
      align-items: center;
      gap: 10px;
      flex-shrink: 0;
      padding: 10px 12px 12px;
    }
    /* Selector de organización bajo la cabecera (como en el resto de pestañas) */
    .cfg-orgbar { flex-shrink: 0; display: flex; gap: 8px; padding: 0 12px 12px; }
    .cfg-orgsel { flex: 1; min-width: 0; background: var(--color-surface); border: 1px solid var(--color-border);
      border-radius: 12px; padding: 12px 14px; color: var(--color-text); font-family: inherit; font-size: 15px; font-weight: 600; }
    .cfg-hdr { flex: 1; display: flex; flex-direction: column; justify-content: center; min-width: 0; }
    .cfg-sub { font-size: 12px; color: var(--color-text-muted); margin-top: 2px;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .cfg-logout { flex-shrink: 0; width: 38px; height: 38px; border-radius: 10px;
      background: var(--color-surface); border: 1px solid var(--color-border); color: var(--color-text-muted);
      display: flex; align-items: center; justify-content: center; cursor: pointer; }
    .cfg-logout:active { color: var(--color-primary); }
    .cfg-logout svg { width: 20px; height: 20px; display: block; }

    .cfg-menu {
      background: none; border: none; color: var(--color-text); font-size: 22px;
      cursor: pointer; padding: 4px 6px; line-height: 1; flex-shrink: 0;
    }
    /* Contenedor con barra lateral izquierda ocultable (drawer) */
    .cfg-main {
      flex: 1;
      position: relative;
      min-height: 0;
      overflow: hidden;
    }

    /* Rueda de carga BRANDEADA (NIBO) breve al cambiar de organización: cubre el
       intercambio de datos y se desvanece (transición suave, sin corte brusco).
       El spinner usa .manto-spinner (css/manto-loader.css), el mismo del resto. */
    .cfg-switch-ov { position: absolute; inset: 0; z-index: 50; display: flex; flex-direction: column; align-items: center; justify-content: center;
      background: var(--color-bg); opacity: 0; transition: opacity .2s ease; pointer-events: none; }
    .cfg-switch-ov.on { opacity: 1; }
    .cfg-content {
      height: 100%;
      overflow-y: auto;
      /* Padding inferior = sitio para la barra flotante (que va por encima del
         overlay), para que el contenido no quede oculto tras ella. */
      padding: 14px 16px calc(88px + env(safe-area-inset-bottom));
    }

    .cfg-nav {
      position: absolute;
      top: 0; left: 0; bottom: 0;
      width: 220px; max-width: 78%;
      background: var(--color-surface);
      border-right: 1px solid var(--color-border);
      overflow-y: auto;
      padding: 12px 10px;
      transform: translateX(-102%);
      transition: transform .22s ease;
      z-index: 3;
      box-shadow: 2px 0 24px rgba(0,0,0,.35);
    }
    .cfg-main.nav-open .cfg-nav { transform: translateX(0); }

    .cfg-backdrop {
      position: absolute; inset: 0; background: rgba(0,0,0,.45);
      opacity: 0; pointer-events: none; transition: opacity .2s; z-index: 2;
    }
    .cfg-main.nav-open .cfg-backdrop { opacity: 1; pointer-events: auto; }

    /* MODO RAIL (Opción 2, solo escritorio): las secciones y el logo/logout viven
       en el rail, así que el overlay se queda como panel de CONTENIDO puro. Se
       oculta la topbar (☰ + wordmark + salir) y el cajón de secciones; se conserva
       el selector de organización (útil dentro de Config) y el contenido, que
       ocupa todo el ancho. */
    #cfg-ov.cfg-railnav .cfg-topbar,
    #cfg-ov.cfg-railnav .cfg-nav,
    #cfg-ov.cfg-railnav .cfg-backdrop { display: none; }
    #cfg-ov.cfg-railnav .cfg-orgbar { padding-top: 16px; }
    #cfg-ov.cfg-railnav .cfg-content { padding-top: 20px; }

    /* Secciones de Config (cajón móvil): MISMA estética que el rail de escritorio
       (.ncfg-item) — chip de icono branded + selección con franja de degradado y
       fondo tenue, en vez del antiguo relleno azul sólido. */
    .cfg-navbtn {
      display: flex;
      align-items: center;
      gap: 11px;
      width: 100%;
      padding: 10px 12px;
      border-radius: 12px;
      background: none;
      border: none;
      color: var(--color-text-muted);
      font-family: inherit;
      font-size: 14px;
      font-weight: 600;
      text-align: left;
      cursor: pointer;
      margin-bottom: 2px;
      position: relative;
      transition: color .15s, background .15s;
    }
    .cfg-navbtn:hover { color: var(--color-text); background: rgba(255, 255, 255, 0.045); }
    html.light .cfg-navbtn:hover { background: rgba(20, 30, 60, 0.045); }
    .cfg-navbtn.on { color: var(--color-text); background: rgba(59, 111, 255, 0.14); }
    html.light .cfg-navbtn.on { background: rgba(59, 111, 255, 0.1); }
    .cfg-navbtn.on::before {
      content: "";
      position: absolute;
      left: 0; top: 8px; bottom: 8px;
      width: 3px;
      border-radius: 3px;
      background: var(--manto-gradient);
    }
    /* Chip de icono branded (idéntico a .ncfg-ico del rail). */
    .cfg-navbtn .cfg-nav-ico {
      width: 30px; height: 30px; flex-shrink: 0;
      display: grid; place-items: center;
      border-radius: 9px;
      background: rgba(59, 111, 255, 0.09);
      border: 1px solid rgba(59, 111, 255, 0.28);
      color: var(--color-primary);
    }
    .cfg-navbtn .cfg-nav-ico svg { width: 16px; height: 16px; display: block; }

    /* Tarjetas de actividad de cuentas (más visual) */
    /* Navegador de mes de la actividad de cuentas */
    .act-monthnav { display: flex; align-items: center; justify-content: space-between; gap: 10px;
      background: var(--color-surface); border: 1px solid var(--color-border); border-radius: 12px;
      padding: 6px 8px; margin-bottom: 12px; }
    .act-monthnav span { font-size: 14px; font-weight: 700; color: var(--color-text); }
    .act-monthnav button { width: 44px; height: 44px; border-radius: 10px; border: 1px solid var(--color-border);
      background: var(--color-surface-2); color: var(--color-primary); font-size: 18px; cursor: pointer; font-family: inherit;
      display: inline-flex; align-items: center; justify-content: center; }
    .act-monthnav button:disabled { opacity: .35; cursor: default; }
    /* Selector interno de "Cuentas" (Con acceso · Actividad · Solicitudes):
       pastillas sobre una barra de superficie, la activa se eleva. */
    .cfg-seg { display: flex; gap: 4px; background: var(--color-surface-2); border: 1px solid var(--color-border);
      border-radius: 12px; padding: 4px; margin-bottom: 16px; }
    .cfg-seg button { flex: 1; min-width: 0; padding: 9px 6px; border: none; border-radius: 9px; background: transparent;
      color: var(--color-text-muted); font-size: 12.5px; font-weight: 700; font-family: inherit; cursor: pointer;
      display: inline-flex; align-items: center; justify-content: center; gap: 6px;
      transition: background .15s, color .15s; }
    .cfg-seg button.on { background: var(--color-surface); color: var(--color-text); box-shadow: 0 1px 4px rgba(0, 0, 0, .14); }
    .cfg-seg button .sv { width: 14px; height: 14px; flex-shrink: 0; display: inline-flex; }
    .cfg-seg-b { min-width: 17px; height: 17px; padding: 0 4px; border-radius: 9px; background: var(--color-danger);
      color: #fff; font-size: 10.5px; font-weight: 800; display: inline-flex; align-items: center; justify-content: center; }
    /* Panel de actividad (Opción 3): tabla + gráfico detallado a un clic. */
    .spt-head, .spt-row {
      display: grid; grid-template-columns: 32px 1fr 44px 44px 52px 18px; align-items: center; gap: 8px; }
    .spt-head { padding: 0 6px 8px; font-size: 10px; text-transform: uppercase; letter-spacing: .04em;
      color: var(--color-text-muted); font-weight: 700; }
    .spt-head .spt-n { text-align: right; }
    .spt-tbl { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: 14px; overflow: hidden; }
    .spt-row { padding: 11px 8px; border-top: 1px solid var(--color-border); cursor: pointer; transition: background .12s; }
    .spt-tbl > .spt-row:first-child { border-top: 0; }
    .spt-row:hover { background: var(--color-surface-2); }
    .spt-row.on { background: color-mix(in srgb, var(--color-primary) 9%, transparent); }
    .spt-mono { width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; color: #fff;
      font-family: Sora, Inter, sans-serif; font-weight: 800; font-size: 11px; background: var(--manto-gradient); }
    .spt-mail { min-width: 0; font-size: 13px; font-weight: 700; font-family: Sora, Inter, sans-serif; color: var(--color-text);
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .spt-n { text-align: right; font-family: Sora, Inter, sans-serif; font-weight: 800; font-size: 13px; color: var(--color-text);
      font-variant-numeric: tabular-nums; }
    .spt-inc { color: var(--color-warning, #FF8A5B); }
    .spt-prev { color: var(--color-info, #3B6FFF); }
    .spt-h { color: var(--color-text-muted); }
    .spt-chev { text-align: center; color: var(--color-text-muted); font-size: 13px; }
    /* Gráfico detallado a todo el ancho: curva suave con halo + rejilla. */
    .spt-detail { border-top: 1px solid var(--color-border); padding: 14px 0 6px;
      background: var(--color-surface-2); }
    .spt-detail-hd { font-size: 10px; text-transform: uppercase; letter-spacing: .06em; font-weight: 700;
      color: var(--color-text-muted); margin: 0 0 6px; padding: 0 12px; }
    .spt-detail-svg { display: block; width: 100%; height: auto; }
    .spt-detail-empty { font-size: 12.5px; color: var(--color-text-muted); padding: 10px 12px 14px; }
    /* Mini-carrusel del detalle: dos gráficas deslizables con el dedo. */
    .spt-swipe { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
    .spt-swipe::-webkit-scrollbar { display: none; }
    .spt-slide { flex: 0 0 100%; min-width: 100%; scroll-snap-align: start; }
    /* Leyenda en SUBCUADRO centrado (como la de Estadísticas del panel): caja
       con borde, punto de color, etiqueta y total del mes en negrita. */
    .spt-leg { display: flex; gap: 4px 16px; width: max-content; max-width: calc(100% - 24px);
      margin: 4px auto 2px; padding: 8px 12px; background: var(--color-surface-2, rgba(255,255,255,.05));
      border: 1px solid var(--color-border); border-radius: 9px; font-size: 11px; color: var(--color-text-muted); flex-wrap: wrap; justify-content: center; }
    .spt-leg span { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
    .spt-leg i { display: inline-block; width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
    .spt-leg b { margin-left: 3px; font-weight: 700; color: var(--color-text); }
    /* Navegación del carrusel como en Análisis interactivo: flechas redondas
       superpuestas en los EXTREMOS del marco + contador «n / N» debajo. */
    .spt-wrap { position: relative; }
    .spt-side { position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
      display: flex; align-items: center; justify-content: center; width: 34px; height: 34px;
      border-radius: 50%; border: 1px solid var(--color-border); background: var(--color-surface);
      color: var(--color-text-muted); font-size: 21px; line-height: 1; padding: 0 0 3px;
      cursor: pointer; font-family: inherit; box-shadow: 0 2px 10px rgba(0, 0, 0, .14); }
    .spt-side:hover { border-color: var(--color-primary); color: var(--color-text); }
    .spt-side:active { transform: translateY(-50%) scale(.92); }
    .spt-side-l { left: 2px; }
    .spt-side-r { right: 2px; }
    .spt-dots { display: flex; gap: 6px; justify-content: center; padding: 8px 0 2px; }
    .spt-dots span { width: 6px; height: 6px; border-radius: 50%; background: var(--color-border); transition: background .2s; }
    .spt-dots span.on { background: var(--color-primary); }
    /* Aviso de horas NO cargadas (fallo/timeout de RTDB): distingue el cero real
       del dato que no llegó, con reintento a mano. */
    .act-warn { display: flex; align-items: center; gap: 10px; background: var(--color-warning-bg);
      border: 1px solid var(--color-warning); border-radius: 10px; padding: 9px 12px; margin-bottom: 10px; }
    .act-warn span { flex: 1; font-size: 11.5px; color: var(--color-warning); font-weight: 600; line-height: 1.4; }
    .act-warn button { flex-shrink: 0; background: var(--color-surface); border: 1px solid var(--color-border);
      border-radius: 8px; color: var(--color-text); font-family: inherit; font-size: 11.5px; font-weight: 700;
      padding: 7px 12px; min-height: 36px; cursor: pointer; }
    /* Aparición sobria: un ligero fundido del conjunto (siempre acaba visible;
       sin animar el trazo, que un re-pintado podía dejar a medias). */
    .spt-detail { animation: sptFade .32s ease; }
    @keyframes sptFade { from { opacity: 0; } to { opacity: 1; } }
    @media (prefers-reduced-motion: reduce) { .spt-detail { animation: none; } }
    @media (max-width: 480px) {
      .spt-head, .spt-row { grid-template-columns: 30px 1fr 38px 40px 46px 16px; gap: 6px; }
    }

    /* Filas tipo iOS del helper _row(): esquinas redondeadas arriba/abajo */
    #cfg-ov .cfg-content > div[style*="background:var(--color-surface)"]:first-of-type {
      border-radius: 12px 12px 0 0;
    }
    #cfg-ov .cfg-content > div[style*="background:var(--color-surface)"]:last-of-type {
      border-radius: 0 0 12px 12px;
      border-bottom: none !important;
    }

    #cfg-ov ::-webkit-scrollbar {
      width: 3px
    }

    #cfg-ov ::-webkit-scrollbar-thumb {
      background: var(--color-border);
      border-radius: 99px
    }

    /* Gestión de accesos integrada en Configuración */
    .acc-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: 14px; padding: 13px 14px; margin-bottom: 9px; }
    .acc-mail { font-size: 15px; font-weight: 800; font-family: Sora, Inter, sans-serif; color: var(--color-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .acc-sub { font-size: 12px; color: var(--color-text-muted); margin-top: 2px; }
    .acc-btns { display: flex; gap: 8px; margin-top: 10px; }
    .acc-btns button { flex: 1; padding: 9px; border-radius: 10px; font-size: 12.5px; font-weight: 700; cursor: pointer; font-family: inherit; border: 1px solid transparent; }
    .acc-ok { background: var(--color-success-bg); border-color: var(--color-success) !important; color: var(--color-success); }
    .acc-no { background: var(--color-danger-bg); border-color: var(--color-danger) !important; color: var(--color-danger); }
    /* Autosuficiente (base de botón propia): fuera de .acc-btns —p. ej. «Editar
       ficha» en Organización— salía como botón nativo del navegador. Dentro de
       .acc-btns, su regla (más específica) sigue mandando en padding/flex. */
    .acc-ed { padding: 9px 16px; border-radius: 10px; font-size: 12.5px; font-weight: 700; cursor: pointer; font-family: inherit;
      background: var(--color-surface-2); color: var(--color-text); border: 1px solid transparent; border-color: var(--color-border) !important; }
    .acc-ed:active { transform: scale(.97); }
    .acc-del { flex: 0 0 auto !important; width: 42px; background: var(--color-danger-bg); color: var(--color-danger); border-color: rgba(255,107,107,.25) !important; }
    .acc-form:empty { display: none; }
    .acc-form { margin-top: 11px; padding-top: 11px; border-top: 1px solid var(--color-border); }

    /* ── Cuentas con acceso: contador-filtro (total + celda por rol) ──────── */
    /* Misma estructura que el contador de Presupuestos del panel: total grande
       (degradado de marca) que resetea + celdas por rol que FILTRAN. */
    .cta-cnt { display: flex; gap: 8px; align-items: stretch; background: var(--color-surface);
      border: 1px solid var(--color-border); border-radius: 16px; padding: 10px; margin-bottom: 6px; }
    .cta-cnt-total { flex-shrink: 0; width: 96px; display: flex; flex-direction: column; align-items: center;
      justify-content: center; gap: 5px; border: 0; cursor: pointer; border-radius: 12px; padding: 10px 6px;
      color: #fff; font-family: inherit; background: var(--manto-gradient); box-shadow: 0 4px 12px rgba(59,111,255,.25);
      transition: transform .06s, filter .12s; }
    .cta-cnt-total:active { transform: scale(.97); }
    .cta-cnt-total:not(.on) { filter: saturate(.7) brightness(.92); }
    .cta-cnt-total-n { font-family: Sora, Inter, sans-serif; font-size: 30px; font-weight: 800; line-height: 1; }
    .cta-cnt-total-l { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; opacity: .95; text-align: center; line-height: 1.1; }
    .cta-cnt-groups { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; justify-content: center; }
    .cta-cnt-row { display: flex; flex-direction: column; gap: 4px; }
    .cta-cnt-rowlbl { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--color-text-muted); font-weight: 700; text-align: center; }
    .cta-cnt-cells { display: flex; gap: 6px; }
    .cta-cnt-cells > * { flex: 1 1 0; min-width: 0; }
    .cta-cnt-cell { height: 60px; background: var(--color-surface-2); border: 1px solid var(--color-border); border-radius: 12px;
      padding: 8px 3px 7px; text-align: center; cursor: pointer; display: flex; flex-direction: column; align-items: center;
      justify-content: flex-start; gap: 4px; transition: border-color .12s, background .12s, transform .06s; }
    .cta-cnt-cell:active { transform: scale(.95); }
    .cta-cnt-cell.on { background: rgba(59,111,255,.14); border-color: var(--color-primary); }
    html.light .cta-cnt-cell.on { background: rgba(59,111,255,.1); }
    .cta-cnt-zero { opacity: .5; }
    .cta-cnt-zero.on { opacity: 1; }
    .cta-hint { text-align: center; color: var(--color-text-muted); font-size: 13px; padding: 18px 12px; }
    .cta-cnt-n { font-family: Sora, Inter, sans-serif; font-size: 18px; font-weight: 800; line-height: 1; height: 18px;
      display: flex; align-items: center; font-variant-numeric: tabular-nums; }
    .cta-cnt-l { font-size: 10px; color: var(--color-text-muted); font-weight: 600; line-height: 1.15;
      display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

    /* Listado: FICHAS por cuenta (aro y monograma de color por rol), una por
       línea (apiladas, no en columnas). */
    .cta-cards { display: flex; flex-direction: column; gap: 9px; }
    .cta-card { position: relative; overflow: hidden; background: var(--color-surface); border: 1px solid var(--color-border);
      border-radius: 13px; padding: 11px 13px; }
    .cta-card::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--rc); opacity: .9; }
    .cta-card-top { display: flex; align-items: center; gap: 10px; }
    .cta-ring { flex-shrink: 0; display: inline-flex; }
    .cta-mono { width: 36px; height: 36px; border-radius: 50%; background: var(--manto-gradient); display: grid; place-items: center;
      font-family: Sora, Inter, sans-serif; font-weight: 800; font-size: 12.5px; color: #fff; letter-spacing: .02em;
      box-shadow: 0 2px 7px rgba(32, 111, 170, .28); }
    .cta-mail { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 700; font-family: Sora, Inter, sans-serif; color: var(--color-text);
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .cta-pill { margin-left: auto; flex-shrink: 0; display: inline-flex; }
    /* Pie compacto (sin borde superior): alcance a la izquierda, iconos a la derecha. */
    .cta-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 9px; }
    .cta-scope { font-size: 11.5px; color: var(--color-text-muted); min-width: 0; line-height: 1.35;
      overflow: hidden; text-overflow: ellipsis; }
    .cta-when { opacity: .8; }
    .cta-acts { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
    .cta-ico { width: 30px; height: 30px; border-radius: 8px; border: 1px solid var(--color-border); background: var(--color-surface-2);
      color: var(--color-text-muted); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
    .cta-ico svg { width: 15px; height: 15px; }
    .cta-ico-del { color: var(--color-danger); background: color-mix(in srgb, var(--color-danger) 8%, transparent);
      border-color: color-mix(in srgb, var(--color-danger) 25%, transparent); }
    .cta-conv { padding: 6px 10px; border-radius: 8px; font-size: 12px; font-weight: 700; cursor: pointer; font-family: inherit;
      background: var(--color-primary); color: #fff; border: 1px solid var(--color-primary); }

    /* Invitar a un cliente: envío por email con branding. */
    .inv-mail-l { display: block; font-size: 11px; font-weight: 700; color: var(--color-text-muted);
      text-transform: uppercase; letter-spacing: .03em; margin-bottom: 7px; }
    .inv-mail-row { display: flex; gap: 8px; }
    .inv-mail-in { flex: 1; min-width: 0; box-sizing: border-box; background: var(--color-surface-2);
      border: 1px solid var(--color-border); border-radius: 10px; padding: 11px 12px; color: var(--color-text);
      font-size: 14px; font-family: inherit; outline: none; }
    .inv-mail-in:focus { border-color: var(--color-primary); }
    .inv-mail-in::placeholder { color: var(--color-text-muted); }
    .inv-mail-send { flex-shrink: 0; padding: 11px 18px; border-radius: 10px; font-size: 13px; font-weight: 700;
      background: var(--color-primary); color: #fff; border: none; cursor: pointer; font-family: inherit; }
    .inv-mail-send:disabled { opacity: .6; cursor: default; }
    .inv-mail-msg { margin-top: 9px; font-size: 12.5px; font-weight: 600; line-height: 1.45; }
    .inv-mail-msg.ok { color: var(--color-success, #22A06B); }
    .inv-mail-msg.err { color: var(--color-danger); }
    /* Separador "o" entre enviar por email y copiar enlace. */
    .inv-or { display: flex; align-items: center; gap: 10px; margin: 14px 0; color: var(--color-text-muted); font-size: 11.5px; }
    .inv-or::before, .inv-or::after { content: ""; flex: 1; height: 1px; background: var(--color-border); }
    .acc-frow { margin-bottom: 9px; }
    .acc-frow label { display: block; font-size: 11px; font-weight: 700; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: .03em; margin-bottom: 5px; }
    .acc-frow select, .acc-frow input, .acc-frow textarea { width: 100%; box-sizing: border-box; background: var(--color-surface-2); border: 1px solid var(--color-border); border-radius: 10px; padding: 10px 12px; color: var(--color-text); font-size: 14px; font-family: inherit; outline: none; }
    .acc-frow input:focus, .acc-frow textarea:focus, .acc-frow select:focus { border-color: var(--color-primary); }
    .acc-frow textarea { resize: vertical; min-height: 62px; line-height: 1.5; }
    .acc-frow input::placeholder, .acc-frow textarea::placeholder { color: var(--color-text-muted); }
    .acc-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 4px; }
    .acc-chip { border: 1.5px solid var(--color-border); background: transparent; color: var(--color-text-muted); font-size: 12.5px; font-weight: 600; padding: 7px 12px; border-radius: 999px; cursor: pointer; }
    .acc-chip.on { border-color: var(--color-primary); background: var(--color-primary); color: #fff; }
    .acc-err { color: var(--color-danger); font-size: 12px; margin: 4px 0 8px; }
    .org-doms { display: flex; flex-wrap: wrap; gap: 6px; }
    .org-domchip { display: inline-block; background: rgba(108, 140, 255, .12); border: 1px solid rgba(108, 140, 255, .32); color: var(--color-text); font-size: 12.5px; font-weight: 600; padding: 5px 11px; border-radius: 999px; }
    .acc-apply { width: 100%; margin-top: 6px; padding: 11px; border-radius: 11px; font-size: 13px; font-weight: 700; background: var(--color-primary); color: #fff; border: none; cursor: pointer; font-family: inherit; }
    /* ── Diálogos de marca del shell (confirm/alert/prompt) ── */
    .sdlg-wrap { position: fixed; inset: 0; z-index: 400; display: none; align-items: center; justify-content: center;
      background: rgba(5,8,16,.66); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
    .sdlg { width: 100%; max-width: 330px; margin: 0 22px; background: var(--color-surface); border: 1px solid var(--color-border);
      border-radius: 22px; padding: 24px 20px 18px; box-shadow: 0 24px 70px rgba(0,0,0,.55); text-align: center;
      animation: sdlg-in .22s cubic-bezier(.2,.9,.25,1.1) both; }
    @keyframes sdlg-in { from { opacity: 0; transform: scale(.9) translateY(8px); } to { opacity: 1; transform: none; } }
    .sdlg-ico { width: 54px; height: 54px; border-radius: 50%; margin: 0 auto 15px; display: flex; align-items: center; justify-content: center;
      color: #fff; background: var(--manto-gradient); box-shadow: 0 6px 18px rgba(59,111,255,.3); }
    .sdlg-wrap.danger .sdlg-ico { background: linear-gradient(135deg, #FF6B6B, #d64545); box-shadow: 0 6px 18px rgba(255,107,107,.32); }
    .sdlg-ico svg { width: 26px; height: 26px; }
    .sdlg-t { font-family: "Sora", system-ui, sans-serif; font-size: 17px; font-weight: 800; color: var(--color-text); margin-bottom: 6px; letter-spacing: -.01em; }
    .sdlg-m { font-size: 13.5px; color: var(--color-text-muted); line-height: 1.5; margin-bottom: 20px; }
    .sdlg-input { width: 100%; background: var(--color-surface-2); border: 1px solid var(--color-border); border-radius: 12px;
      padding: 12px 14px; color: var(--color-text); font-size: 15px; font-family: inherit; outline: none; margin: 4px 0 20px; box-sizing: border-box; }
    .sdlg-input:focus { border-color: var(--color-primary); }
    .sdlg-btns { display: flex; gap: 10px; }
    .sdlg-btn { flex: 1; padding: 13px; border-radius: 13px; font-family: inherit; font-size: 14px; font-weight: 700; cursor: pointer; border: 1px solid transparent; transition: transform .06s; }
    .sdlg-btn:active { transform: scale(.96); }
    .sdlg-cancel { background: var(--color-surface-2); border-color: var(--color-border); color: var(--color-text); }
    .sdlg-ok { background: var(--color-primary); color: #fff; box-shadow: 0 4px 12px rgba(59,111,255,.25); }
    .sdlg-ok.danger { background: var(--color-danger); box-shadow: 0 4px 12px rgba(255,107,107,.25); }
    /* Tercer botón (p.ej. "No mostrar más"): a ancho completo bajo la fila,
       atenuado y sin relleno, para que no compita con Activar / Ahora no. */
    .sdlg-extra { width: 100%; margin-top: 10px; background: transparent; border-color: transparent;
      color: var(--color-text-muted); font-weight: 600; font-size: 13px; }
    .sdlg-extra:hover { color: var(--color-text); }

    /* Accesibilidad: anillo de foco visible por teclado, coherente con la marca. */
    a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible,
    textarea:focus-visible, [tabindex]:focus-visible {
      outline: 2px solid var(--color-focus, #6C8CFF);
      outline-offset: 2px;
      border-radius: 6px;
    }

    /* ── BLOQUEO BIOMÉTRICO (Face ID / huella) ──────────────────────── */
    #bio-lock {
      position: fixed; inset: 0; z-index: 10000;
      background: var(--color-bg, #0A0F1E);
      display: none; align-items: center; justify-content: center;
      padding: calc(24px + env(safe-area-inset-top)) 20px calc(24px + env(safe-area-inset-bottom));
    }
    .bio-card { width: 100%; max-width: 320px; text-align: center; display: flex; flex-direction: column; align-items: center; }
    .bio-ico { width: 66px; height: 66px; border-radius: 20px; display: flex; align-items: center; justify-content: center;
      background: rgba(108,140,255,.14); border: 1px solid rgba(108,140,255,.35); color: var(--color-primary); margin-bottom: 18px; }
    .bio-ico svg { width: 32px; height: 32px; }
    .bio-t { font-family: "Sora", system-ui, sans-serif; font-size: 20px; font-weight: 800; color: var(--color-text); margin-bottom: 6px; }
    .bio-s { font-size: 13.5px; color: var(--color-text-muted); margin-bottom: 22px; line-height: 1.5; }
    .bio-actions { width: 100%; }
    .bio-btn { width: 100%; padding: 14px; background: var(--color-primary); border: none; border-radius: 12px;
      color: var(--color-on-primary); font-size: 15px; font-weight: 700; font-family: inherit; cursor: pointer; }
    .bio-btn:active { transform: scale(.98); }
    .bio-alt { width: 100%; margin-top: 12px; padding: 12px; background: none; border: none; color: var(--color-text-muted);
      font-size: 13.5px; font-weight: 600; font-family: inherit; cursor: pointer; }
    .bio-err { margin-top: 14px; font-size: 13px; color: var(--color-danger); min-height: 18px; }

/* Sesión de TÉCNICO: la barra de pestañas del shell es de GESTIÓN — se oculta
   entera (su pantalla de tareas vive dentro del panel y tiene lo suyo). Sin
   esto, la barra parpadeaba un instante al entrar el técnico. */
body.tec-sesion #nav { display: none !important; }

/* Arranque con sesión de TÉCNICO persistida (body.tec-boot, lo pone auth.js
   antes del primer pintado): la portada queda oculta y se ve el splash NIBO
   hasta que la sesión resuelve — al re-entrar flasheaba la portada un instante
   antes de la pantalla de carga. Failsafe de 8 s en auth.js. */
html.tec-boot #login-overlay { display: none !important; }

/* Config → Notificaciones · tarjeta "En este dispositivo" (activar/probar push).
   Estilos PROPIOS del shell: antes se usaba la clase .btn del PANEL, que aquí no
   existe, y los botones salían como píldoras blancas del navegador. Todo con
   tokens del tema (claro/oscuro) y tap-targets de 48px para cualquier móvil. */
.cfg-push-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: 14px; padding: 14px; }
.cfg-push-state { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--color-text); margin-bottom: 12px; }
.cfg-push-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--color-text-muted); flex-shrink: 0; }
.cfg-push-dot.on { background: var(--color-success); box-shadow: 0 0 0 4px var(--color-success-bg); }
.cfg-push-dot.off { background: var(--color-danger, #FF6B6B); }
.cfg-push-btn { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 48px; padding: 12px 16px; border: none; border-radius: 12px; font-family: inherit; font-size: 15px; font-weight: 700; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: filter .12s, background .12s; }
.cfg-push-btn.primary { background: var(--manto-gradient, var(--manto-gradient)); color: #fff; box-shadow: 0 6px 18px rgba(59, 111, 255, .25); }
.cfg-push-btn.primary:active { filter: brightness(.9); }
.cfg-push-btn.ghost { background: var(--color-surface-2); color: var(--color-text); border: 1px solid var(--color-border); margin-top: 10px; }
.cfg-push-btn.ghost:active { filter: brightness(.94); }
.cfg-push-btn:disabled { opacity: .55; cursor: default; }
.cfg-push-btn .svg-ico { width: 17px; height: 17px; display: inline-flex; flex-shrink: 0; }
.cfg-push-hint { font-size: 12px; color: var(--color-text-muted); line-height: 1.5; margin-top: 10px; }
.cfg-push-btn .svg-ico svg { width: 100%; height: 100%; }


/* ── Ficha del técnico · documentos del DNI en bloques (tiles) ─────────────
   Dos ranuras (cara/dorso) como tarjetas: miniatura firmada que abre el visor
   del shell; vacía = tile de adjuntar (foto o PDF); PDF `raw` legado sin
   miniatura = tile "Ver documento". El input real va oculto (label for=). */
.tdoc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 12px; }
/* En escritorio los tiles ocupaban demasiado: se acota el ancho del bloque a la
   mitad (alineado a la izquierda) para que las tarjetas sean más compactas. */
@media (min-width: 720px) { .tdoc-grid { max-width: 50%; } }
.tdoc-cell { min-width: 0; }
.tdoc-tile { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; width: 100%; aspect-ratio: 3 / 2; border-radius: 12px; overflow: hidden; border: 1px solid var(--color-border); background: var(--color-surface-2); color: var(--color-text-muted); font-family: inherit; font-size: 12px; font-weight: 700; padding: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.tdoc-tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.tdoc-tag { position: absolute; left: 8px; bottom: 8px; z-index: 1; background: rgba(4, 7, 14, .62); color: #fff; font-size: 10.5px; font-weight: 700; letter-spacing: .02em; padding: 3px 9px; border-radius: 999px; pointer-events: none; }
.tdoc-add { border-style: dashed; background: transparent; }
.tdoc-add:hover { color: var(--color-text); border-color: var(--color-primary); }
.tdoc-add svg { opacity: .8; }
.tdoc-empty { cursor: default; }
.tdoc-ok { cursor: default; border-color: var(--color-success, #20D6A6); }
.tdoc-okico { width: 26px; height: 26px; border-radius: 50%; background: var(--color-success-bg, rgba(32, 214, 166, .16)); color: var(--color-success, #20D6A6); display: flex; align-items: center; justify-content: center; font-size: 14px; }
.tdoc-oktxt { font-size: 11px; font-weight: 600; color: var(--color-text-muted); text-align: center; line-height: 1.45; padding: 0 8px; }
.tdoc-pdf { gap: 4px; }
.tdoc-pdfico { font-size: 13px; font-weight: 800; letter-spacing: .08em; color: var(--color-text); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: 8px; padding: 5px 10px; }
.tdoc-vertxt { font-size: 11px; color: var(--color-primary); }
.tdoc-input { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; clip: rect(0 0 0 0); }
.tdoc-replace { display: block; margin-top: 6px; text-align: center; font-size: 11.5px; font-weight: 700; color: var(--color-primary); cursor: pointer; }
.tdoc-status { font-size: 11.5px; color: var(--color-text-muted); min-height: 15px; margin-top: 3px; text-align: center; }

/* ── Visor de imágenes del shell (documentos del DNI) ──────────────────────
   Mismo lenguaje que el visor del panel: carrusel scroll-snap (dedo), flechas
   en escritorio (pointer: fine), contador y cierre por × o fondo. */
.imgv { position: fixed; inset: 0; z-index: 400; background: rgba(4, 7, 14, .95); display: flex; flex-direction: column; }
.imgv-track { flex: 1; display: flex; overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.imgv-track::-webkit-scrollbar { display: none; }
.imgv-slide { min-width: 100%; height: 100%; scroll-snap-align: center; display: flex; align-items: center; justify-content: center; padding: 18px; box-sizing: border-box; }
.imgv-slide img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 8px; }
/* Documento (PDF) dentro del visor de la app: iframe a pantalla casi completa,
   con margen para el botón de cerrar. */
.imgv-doc { flex: 1; width: 100%; border: 0; background: #fff; }
.imgv-x { position: absolute; top: calc(12px + env(safe-area-inset-top)); right: 14px; z-index: 2; width: 40px; height: 40px; border-radius: 999px; border: none; background: rgba(255, 255, 255, .16); color: #fff; font-size: 26px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.imgv-count { position: absolute; top: calc(20px + env(safe-area-inset-top)); left: 0; right: 0; text-align: center; color: rgba(255, 255, 255, .85); font-size: 13px; font-weight: 600; z-index: 1; pointer-events: none; font-variant-numeric: tabular-nums; }
.imgv-nav { display: none; }
@media (pointer: fine) {
  .imgv-nav { position: absolute; top: 50%; transform: translateY(-50%); z-index: 2; display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: 999px; border: none; background: rgba(255, 255, 255, .16); color: #fff; font-size: 30px; line-height: 1; cursor: pointer; padding-bottom: 4px; }
  .imgv-nav:hover { background: rgba(255, 255, 255, .28); }
  .imgv-nav-l { left: 16px; }
  .imgv-nav-r { right: 16px; }
}
