/* Estilos del panel — extraídos de panel.html (2026-07-13). Misma razón que base.css:
 * 13.2 KB que viajaban inline en CADA vista del panel y el navegador no podía cachear. */
:root {
        --app-bg: #fafafa;
    }
    /* EL BLOQUEO Nº1 DEL TEMA OSCURO, medido el 29-ago: `--app-bg` era el ÚNICO token de color
     * de esta hoja y era el único de todo el sistema SIN gemelo oscuro (los 18 de `base.css`
     * están completos). Como `body` lo usa de fondo, subir la marca al documento SIN esto daba
     * **barra negra sobre lienzo blanco** — fotografiado en
     * docs/evidencia/tres_bugs_2026-08-29/bug1_c_control_marca_en_html.png.
     * El valor no se inventa: es el mismo `--bg` oscuro de `base.css:106-127`. */
    :root[data-theme="dark"] {
        --app-bg: #101012;
    }
    /* Buttons heredados de base.html — no duplicar aquí. */

        html,
        body {
            margin: 0;
            min-height: 100%;
        }

        body {
            font-family: "Inter", sans-serif;
            background: var(--app-bg);
            color: var(--text);
        }

/* ── EL COLOR DE ENLACE, QUE NADIE HABÍA ELEGIDO (2026-08-22, founder: «ese link azul
           todo chafa es lo contrario a la sensación que quiero dar») ─────────────────────────
           MEDIDO antes de tocar: en las 1,031 líneas de CSS del proyecto (panel.css 637 +
           base.css 394) NO existe una sola regla `a { color }`. Solo hay reglas para anclas CON
           clase (.app-nav a, .distill-tabs a, a.app-acct-user). Consecuencia: los **44 anclas
           sin `class=`** de templates/business/ —14 de ellas en Contabilidad— caían al azul de
           fábrica del navegador (#0000EE). Ese azul no era una decisión de diseño: era la
           AUSENCIA de una decisión, y por eso se veía pegado con cinta.

           El valor no se inventa: `--accent-hover` ya se documentaba a sí mismo como «hover de
           botones/LINKS accent», o sea que el sistema YA había decidido que un enlace es NEGRO
           (--accent) y que el color se reserva para el riesgo (regla T1 de la casa). Lo único
           que faltaba era escribirlo.

           Se distingue el enlace por el SUBRAYADO, no por el color — que es lo que hacen
           Stripe/Linear y lo que permite que la regla «rojo = solo riesgo» siga siendo cierta.
           `underline-offset` separa la línea de las descendentes: sin él se ve sucio a 13px.

           🪤 NO se toca `a` a secas sin más: las anclas que YA son botones/pestañas traen clase
           y sus reglas ganan por especificidad; las que se comportan como superficie (tarjetas,
           filas clicables) se marcan con [class] y quedan excluidas abajo. */
        a {
            color: var(--accent);
            text-decoration-color: var(--border);
            /* RELATIVO, no 3px: el subrayado tiene que separarse en proporción al texto que
               subraya. Con un valor fijo, a 11px queda pegado y a 20px queda flotando — y de
               paso no suma a la deuda visual, porque no es una decisión de ESPACIO sino de
               tipografía. */
            text-underline-offset: 0.18em;
        }

        a:hover {
            color: var(--accent-hover);
            text-decoration-color: currentColor;
        }

        /* Cualquier ancla que YA tiene clase trae su propio diseño (botón, pestaña, tarjeta,
           fila): no se le impone subrayado. Las 44 sin clase son las que esta regla viste. */
        a[class] {
            text-decoration: none;
        }

        /* 🩸 Y ESTE BLOQUE VA JUSTO DESPUÉS DE `a[class]`, NO ANTES — lo aprendí midiendo.
           Lo puse arriba, con la regla escrita y correcta, y en el navegador seguía SIN
           subrayado: `a[class] { text-decoration: none }` tiene la MISMA especificidad que
           `a.sf-enlace` (0,1,1) y ganaba por orden de fuente. Es el mismo bug 2 otra vez, en su
           forma general: **una regla escoba que le quita a un objeto justo la marca que lo hace
           reconocible**. `a[class]` se escribió pensando «toda ancla con clase trae su propio
           diseño»; el diseño de `.sf-enlace` ES el subrayado.
           No se sube la especificidad (eso empieza una carrera): se pone después y se dice por
           qué. Quien mueva este bloque hacia arriba verá rojo el test de la acción secundaria. */
        /* ── LA ACCIÓN SECUNDARIA (`.sf-enlace`) — UNA definición para las cuatro (bug 2, 29-ago) ──
 *
 * FOUNDER, con captura: *«"Bajar a Free" no tiene contraste»*. No era el color del texto: era
 * que **había cuatro definiciones de la misma clase y ganaba la que el autor de la página no
 * escribió**. `ajustes.css` declaraba `a.sf-enlace` (color pleno, SIN subrayado, rayita de 1px
 * del color de borde) y se carga en TODO el panel; `pricing.html` declaraba `.sf-enlace`
 * (apagado, con subrayado). El elemento es un `<a>` ⇒ `a.sf-enlace` es más específica y gana,
 * sin importar el orden de carga.
 *
 * LO QUE SE VEÍA, medido en el navegador: el texto salía `rgb(10,10,10)` — **el mismo color de
 * la prosa** — sin subrayado, y su única marca era una rayita `#e5e5e5` sobre fondo `#fafafa`:
 * **1.21 de contraste**, cuando lo legible empieza en 3.0. Lo que moría no era el color: era la
 * señal de que eso se podía pulsar.
 *
 * LOS CUATRO USOS SON EL MISMO PAPEL —una acción secundaria al lado de una primaria—, así que
 * les toca UN objeto: «Bajar a Free» junto al CTA de Planes, «Cancelar» junto a «Guardar y
 * continuar», y «Ver sus facturas →» en el pulso de Sincronización.
 * Se elige la variante APAGADA CON SUBRAYADO (la que ya escribían `pricing.html` y
 * `fiscal_profile.html`, o sea 2 de las 4): un subrayado dice «esto es un enlace» sin competir
 * con el botón primario que tiene al lado.
 *
 * Vive AQUÍ y no en `ajustes.css` porque no es de Ajustes: es del panel. Que la hoja de Ajustes
 * se cargue en todas las pantallas es justamente la trampa que produjo este bug. */
.sf-enlace,
a.sf-enlace {
  font-family: "Plex Mono", ui-monospace, monospace; font-size: 11px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--muted); cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}
.sf-enlace:hover,
a.sf-enlace:hover { color: var(--text); }
/* la flechita que acompaña a «Ver sus facturas →» viaja con la clase, no con la página */
a.sf-enlace .fl { display: inline-block; transition: transform 0.18s ease; }
a.sf-enlace:hover .fl { transform: translateX(4px); }


        /* ── .sr-only: SE USABA SIN ESTAR DEFINIDA ────────────────────────────────────────────
           MEDIDO: `grep -rn "sr-only"` sobre website/ da UN solo uso
           (_contabilidad_auxiliar.html:57, el encabezado de la columna de acciones) y CERO
           definiciones en los 2 archivos CSS del proyecto. Resultado: una etiqueta pensada SOLO
           para lectores de pantalla se pintaba como texto normal, y la tabla del auxiliar
           enseñaba un «ACCIONES» que nadie quiso poner ahí.
           El patrón (clip-path + 1px) es el estándar: lo sigue leyendo el lector de pantalla,
           no ocupa una sola fila de layout. */
        .sr-only {
            /* El margen negativo de un píxel que suele acompañar a este patrón es herencia
               del viejo `clip: rect()`, que necesitaba sacar el elemento del flujo a mano. Con
               `position: absolute` + `clip-path` no hace falta: sobra. */
            position: absolute;
            width: 1px;
            height: 1px;
            padding: 0;
            overflow: hidden;
            clip-path: inset(50%);
            white-space: nowrap;
            border: 0;
        }

        .app-shell {
            min-height: 100vh;
            display: grid;
            grid-template-columns: 220px minmax(0, 1fr);
        }

        /* ═ EL CASCARÓN SIMBIOSIS (2026-08-24, mundo 6 aprobado en design/lab) ═
           La placa oscura MUERE: el sidebar es PAPEL —el mismo de la página— y la nav
           flota sin caja: mono MAYÚSCULAS, apagada, y el activo se enciende con el LED
           verde (la firma de la casa). Nada de píldoras ni fondos al pasar: color. */
        .app-sidebar {
            background: var(--bg);
            color: var(--text);
            padding: 30px 22px 22px;
            display: flex;
            flex-direction: column;
            gap: 22px;
            position: sticky;
            top: 0;
            height: 100vh;
        }

        .app-brand {
            display: block;
            padding: 0 0 4px;
            text-align: left;
            color: var(--text);
            text-decoration: none;
        }

        .app-brand strong {
            font-family: "Archivo", "Inter", sans-serif;
            font-variation-settings: 'wdth' 116;
            font-size: 20px;
            font-weight: 800;
            letter-spacing: -0.02em;
            text-transform: uppercase;
        }

        .app-brand:hover,
        .app-brand:focus,
        .app-brand:active,
        .app-brand:visited {
            color: var(--text);
            text-decoration: none;
        }

        .app-nav {
            display: flex;
            flex-direction: column;
            gap: 18px;
            width: 100%;
            flex: 1 1 auto;
            margin-top: 8px;
        }

        .app-nav a {
            display: block;
            padding: 2px 0;
            color: var(--muted);
            text-decoration: none;
            border-radius: 0;
            font-family: "Plex Mono", ui-monospace, monospace;
            font-size: 11px;
            font-weight: 500;
            letter-spacing: .14em;
            text-transform: uppercase;
            text-align: left;
            transition: color 0.16s ease;
        }

        .app-nav a:hover {
            color: var(--text);
        }

        .app-nav a.active {
            color: var(--text);
            font-weight: 500;
        }

        /* EL LED: la sección viva. Reservado al activo — un punto que respira. */
        .app-nav a.active::before {
            content: '';
            display: inline-block;
            width: 7px;
            height: 7px;
            border-radius: 50%;
            background: var(--data-in-soft);
            margin-right: 9px;
            vertical-align: 1px;
        }

        .app-main {
            /* 22px arriba = alinea con el padding-top del sidebar (la marca "Univai").
               Antes 72px: aire reservado para el botón flotante de usuario, ya removido. */
            min-width: 0;
            padding: 22px;
            position: relative;
        }

        /* Cuenta + cerrar sesión: viven en el FOOTER del sidebar (antes era un menú flotante
           "Ramses" que tapaba la esquina y cortaba la vista). Lean + siempre a la mano. */
        .app-foot {
            margin-top: auto;
            display: flex;
            flex-direction: column;
            align-items: flex-start;
            gap: 8px;
            padding: 14px 0 0;
            border-top: 1px solid var(--linea, var(--border));
        }

        .app-acct {
            display: flex;
            align-items: stretch;
            width: 100%;
        }

        .app-acct-user {
            flex: 1;
            min-width: 0;
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 4px 0;
            color: var(--text);
            font-size: 13px;
            font-weight: 700;
        }
        a.app-acct-user { text-decoration: none; cursor: pointer; }
        a.app-acct-user:hover .app-acct-name { border-bottom: 1px solid var(--text); }
        .app-acct.is-active .app-acct-name { border-bottom: 1px solid var(--text); }

        .app-acct-avatar {
            flex-shrink: 0;
            width: 28px;
            height: 28px;
            border-radius: 0;
            background: var(--text);
            color: var(--bg);
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            font-weight: 800;
        }

        .app-acct-name {
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .app-acct-out { display: flex; flex-shrink: 0; align-items: center; }

        .app-acct-logout {
            padding: 0 2px 0 10px;
            border: none;
            background: transparent;
            color: var(--muted);
            font-family: "Plex Mono", ui-monospace, monospace;
            font-size: 13px;
            font-weight: 500;
            cursor: pointer;
        }

        .app-acct-logout:hover { color: var(--text); }

        /* ═══ EL MENÚ DEL PIE (founder 29-ago) ═══════════════════════════════════════════
           `position: fixed` a propósito, no `absolute`. El sidebar es `position: sticky` con
           `height: 100vh` y el menú sale POR ENCIMA de su borde superior: un absolute dentro de
           un ancestro con overflow acaba recortado, y aquí el pie está pegado abajo. Fixed lo
           saca del flujo del contenedor y el JS lo ancla contra el rectángulo del disparador.
           Cero color cableado: todo por token, para que el oscuro lo herede solo. */
        .mc {
            position: fixed;
            z-index: 60;
            width: 232px;
            padding: var(--e1);
            background: var(--surface);
            border: 1px solid var(--border);
            border-radius: var(--r-md);
            box-shadow: 0 1px 2px rgba(10, 10, 10, 0.06), 0 12px 28px rgba(10, 10, 10, 0.12);
            display: flex;
            flex-direction: column;
            gap: var(--e1);
        }
        .mc[hidden] { display: none; }

        /* El correo es DATO, no opcion: mono, apagado, y no se puede pulsar. Va arriba porque
           es lo que contesta «con que cuenta estoy» — la pregunta que trae aqui al usuario. */
        .mc-correo {
            margin: 0;
            padding: var(--e2) var(--e3) var(--e3);
            border-bottom: 1px solid var(--border);
            font-family: "Plex Mono", ui-monospace, monospace;
            font-size: var(--t-2xs);
            line-height: 1.3;
            color: var(--muted);
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .mc-op {
            display: flex;
            align-items: center;
            /* 44px reales: es un menu y tambien se toca en pantallas estrechas. */
            min-height: 44px;
            padding: 0 var(--e3);
            border: 0;
            border-radius: var(--r-sm);
            background: none;
            width: 100%;
            font: inherit;
            font-size: var(--t-sm);
            font-weight: 600;
            color: var(--text);
            text-align: left;
            text-decoration: none;
            cursor: pointer;
        }
        .mc-op:hover { background: var(--surface-soft); }
        .mc-op:focus-visible { outline: 2px solid var(--text); outline-offset: -2px; }

        /* «Mas informacion» — cajon cerrado, el patron de la casa. El marcador propio del
           <summary> se apaga y se sustituye por un signo que dice en que estado esta. */
        .mc-mas summary { list-style: none; justify-content: space-between; }
        .mc-mas summary::-webkit-details-marker { display: none; }
        .mc-mas summary::after { content: "+"; color: var(--muted); font-weight: 700; }
        .mc-mas[open] summary::after { content: "\2013"; }
        .mc-sub { font-weight: 500; color: var(--muted-strong); padding-left: var(--e5); min-height: 40px; }
        .mc-sub:hover { color: var(--text); }

        /* Salir se separa con una linea: es el unico acto de aqui que no se deshace con otro
           clic. La distancia es la advertencia. */
        .mc-salir { margin-top: var(--e1); padding-top: var(--e1); border-top: 1px solid var(--border); }
        .mc-salir .mc-op { color: var(--muted-strong); }
        .mc-salir .mc-op:hover { color: var(--text); }

        .app-acct-ops {
            font-family: "Plex Mono", ui-monospace, monospace;
            font-size: 11px;
            font-weight: 500;
            letter-spacing: .08em;
            color: var(--muted);
            text-decoration: none;
            padding: 0;
        }

        .app-acct-ops:hover { color: var(--text); }

        .app-content {
            min-width: 0;
            max-width: 920px;
            margin: 0 auto;
        }

        /* 🪤 EL «DRIFT» ENTRE PESTAÑAS (founder 2026-08-09, tres capturas: «se siente la transición,
           como si los márgenes se movieran»). La causa es aritmética, no misteriosa: `.app-content`
           está CENTRADO, así que cualquier cambio del ancho disponible lo mueve LA MITAD. Una
           pantalla alta saca la barra de scroll (~15px) y otra baja no ⇒ 7.5px de salto al navegar.
           `stable` reserva el canal SIEMPRE, con barra o sin ella: alta y baja miden igual.

           ⚠️ HUECO DECLARADO — LA SUITE NO PUEDE VER ESTE DEFECTO. Chromium headless usa barras
           SUPERPUESTAS, que ocupan 0px; medido: `innerWidth - clientWidth = 0` con 4000px de
           contenido, y sigue en 0 con `--disable-features=OverlayScrollbar(s)` y estilizando
           `::-webkit-scrollbar`. O sea: NINGÚN test de navegador de esta casa puede detectar un
           salto causado por la barra de scroll — solo el Chrome real del founder. Por eso
           `tests_navegador_sin_salto` verifica la CAUSA (la propiedad computada) y dice en voz
           alta que no puede verificar el efecto. */
        html { scrollbar-gutter: stable; }

        /* Botón "volver" CANÓNICO (un solo patrón en TODA la app — el usuario lo reconoce de una).
           Píldora sobria con borde + flecha. Reemplaza a breadcrumb-trail/emi-back/ne-back/back-link. */
        .app-back {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            color: var(--text);
            text-decoration: none;
            font-size: var(--t-sm);
            font-weight: 700;
            margin-bottom: var(--e4);
            padding: var(--e2) var(--e3);
            border-radius: 0;
            border: 1px solid var(--border);
            background: var(--surface);
            transition: background-color .15s ease;
        }
        .app-back:hover { background: var(--surface-soft); color: var(--text); }

        /* El ícono "i"/"?" MURIÓ (founder 2026-07-24, purga de los ⓘ): las explicaciones viven en
           el title= del propio rótulo. Con él se fueron su CSS y el IIFE que posicionaba el
           tooltip. Si alguien lo intenta resucitar, el gate `check_sin_iconos_info` lo detiene. */


        /* CARD del founder (2026-07-24): identidad arriba (clic = alterna razón social ↔ RFC,
           sin navegar) · línea divisoria · "Administrar empresas" abajo (este sí navega). */
        /* LA EMPRESA (simbiosis): bloque de tipo sin caja. Razón social + RFC A LA VEZ
           (pedido del founder 2026-08-24); el clic-alterna sigue vivo (tests lo usan) y
           ahora es redundancia inofensiva. Administrar navega, como siempre. */
        .app-empresa-static {
            width: 100%;
            display: grid;
            text-align: left;
            background: transparent;
            border: 0;
            border-radius: 0;
            overflow: hidden;
            font-family: inherit;
            color: inherit;
        }
        .app-empresa-id {
            display: block;
            width: 100%;
            padding: 0;
            background: transparent;
            border: none;
            font-family: inherit;
            text-align: left;
            cursor: pointer;
        }
        .app-empresa-id:hover .app-empresa-name { color: var(--text); }
        /* ACTIVA = el LED, la misma voz que el nav (simbiosis): un solo lenguaje de «estás aquí». */
        .app-empresa-static.is-active .app-empresa-name::before {
            content: ''; display: inline-block; width: 7px; height: 7px;
            border-radius: 50%; background: var(--data-in-soft);
            margin-right: 8px; vertical-align: 1px;
        }
        .app-empresa-static.is-active .app-empresa-manage { color: var(--text); }
        .app-empresa-name, .app-empresa-rfc {
            font-size: 13px;
            font-weight: 700;
            color: var(--text);
            text-align: left;
            line-height: 1.3;
            word-break: break-word;
        }
        .app-empresa-rfc-linea {
            display: block;
            margin-top: 3px;
            font-family: "Plex Mono", ui-monospace, monospace;
            font-size: 11px;
            letter-spacing: .06em;
            color: var(--muted);
        }
        .app-empresa-manage {
            display: flex;
            align-items: center;
            gap: 4px;
            padding: 8px 0 0;
            border-top: 0;
            color: var(--muted);
            font-family: "Plex Mono", ui-monospace, monospace;
            font-size: 11px;
            font-weight: 500;
            letter-spacing: .1em;
            text-transform: uppercase;
            text-decoration: none;
        }
        .app-empresa-manage:hover { color: var(--text); }

        .app-badge {
            display: inline-block;
            min-width: 18px;
            padding: 1px 6px;
            margin-left: 6px;
            border-radius: 0;
            border: 1px solid var(--border);
            background: transparent;
            color: var(--muted);
            font-family: "Plex Mono", ui-monospace, monospace;
            font-size: 10px;
            font-weight: 500;
            text-align: center;
        }

        /* Punto de atención (e.firma / perfil fiscal): TINTA sobre papel — neutro de alto
           contraste; el rojo sigue reservado al riesgo confirmado en su propia pantalla. */
        .app-dot {
            display: inline-block;
            width: 6px;
            height: 6px;
            margin-left: 6px;
            vertical-align: middle;
            border-radius: 50%;
            background: var(--text);
        }

        .app-nav a {
            transition: color 0.16s ease;
        }

        .app-nav-hint {
            margin: 6px 0 0;
            padding: 10px 12px;
            border: 1px dashed var(--border);
            border-radius: 0;
            font-size: 11px;
            line-height: 1.4;
            color: var(--muted);
        }

        .app-nav-divider {
            height: 1px;
            background: var(--border);
            margin: auto 0 8px;
        }

        .app-demo-banner {
            margin-bottom: 18px;
            padding: 14px 18px;
            border: 1px solid var(--border);
            border-left: 4px solid var(--accent);
            border-radius: 18px;
            background: var(--surface-soft);
            color: var(--text);
            font-size: 13px;
            line-height: 1.45;
            font-weight: 500;
        }

        .app-demo-banner strong {
            color: var(--accent);
            font-weight: 700;
        }

        /* Subnavegación de sección — una sola voz para Resumen y Contabilidad.
           PEGAJOSA al hacer scroll (founder 2026-07-30): «haz que ese submenú pueda bajar junto
           con el scroll para que se pueda navegar más rápido». En las pantallas largas —el Buzón,
           las pólizas, la balanza— cambiar de pestaña obligaba a subir hasta arriba primero.

           El aire va como PADDING DENTRO del elemento pegajoso y se compensa con margen negativo:
           así el fondo opaco tapa el contenido que pasa por debajo (sin él se transparenta y se
           lee doble) y, a la vez, las tabs no se mueven ni un píxel de donde estaban al cargar.
           z-index 30 > 8 de `.multi-options`: al hacer scroll con un desplegable abierto, la barra
           pasa POR ENCIMA, que es lo que se espera de un encabezado fijo. */
        .distill-tabs-wrap {
            display: flex; justify-content: center;
            position: sticky; top: 0; z-index: 30;
            padding: 12px 0; margin: -12px 0 12px;
            background: var(--app-bg);
        }
        /* Admin (Empresas|Usuarios): más arriba — la queja era que el switch "se sentía muy abajo".
           Los -6/16 originales se conservan EXACTOS descontando el padding de arriba (-6-12 / 16-12). */
        .distill-tabs-wrap.distill-tabs-admin { margin: -18px 0 4px; }
        /* La vuelta al HUB (2026-08-01): el founder no tenía forma de salir de la sección más que
           dando un rodeo por el sidebar. Va en el componente de tabs para aparecer en las tres
           pantallas sin repetirlo.

           🪤 ESTA CLASE PINTABA SU PROPIA VUELTA ATRÁS (founder 2026-08-22: «la flecha de regreso
           no está estandarizada»). Traía font-size, color, padding y hover propios — o sea, una
           SEGUNDA apariencia para el mismo acto: texto gris chiquito en Balanza, píldora negra
           en Apertura, a un clic de distancia. Se justificaba con «discreto a propósito: es una
           salida, no una acción», que como principio no es malo — pero se aplicó a UNA de las
           siete salidas de la app, y una excepción no declarada no se lee como intención: se lee
           como descuido. Si algún día TODAS deben ser discretas, se cambia `.app-back` una vez.

           Ahora esta clase solo dice DÓNDE va; el aspecto lo pone `.app-back` (el canónico), que
           además le regala el `:focus-visible` que aquí nunca existió. Lo vigila
           `tests_una_sola_flecha_de_regreso`. */
        .distill-tabs-up { position: absolute; left: 0; top: 50%; transform: translateY(-50%);
                           white-space: nowrap; margin-bottom: 0; }
        @media (max-width: 900px) {
            /* En pantalla estrecha no cabe al lado: pasa arriba y deja de ser absoluto. */
            .distill-tabs-up { position: static; transform: none; margin-bottom: var(--e3); }
        }
        .distill-tabs {
            display: inline-flex; gap: 4px; max-width: 100%; padding: 4px;
            overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none;
            scroll-behavior: smooth; background: var(--surface-soft);
            border: 1px solid var(--border); border-radius: 0;
        }
        .distill-tabs::-webkit-scrollbar { display: none; }
        .distill-tabs a {
            padding: 8px 18px; border-radius: 0; color: var(--muted-strong);
            font-size: var(--t-sm); font-weight: 600; text-decoration: none; white-space: nowrap;
            transition: background .15s ease, color .15s ease;
        }
        .distill-tabs a:hover:not(.is-on) { color: var(--text); }
        .distill-tabs a.is-on { background: var(--accent); color: var(--surface); }

        /* Flash y franja de trabajo compartidos: planos, claros y sin bullets del navegador. */
        .app-flashes { display: grid; gap: 8px; margin: 0 0 18px; padding: 0; list-style: none; }
        .app-flash {
            padding: 12px 14px; border: 1px solid var(--border); border-radius: 12px;
            background: var(--surface); color: var(--text); font-size: 13px; line-height: 1.45;
        }
        .app-flash.error { border-color: var(--danger); color: var(--danger); }
        .workflow-strip {
            display: flex; align-items: center; justify-content: space-between; gap: 18px;
            margin-top: 18px; padding: 15px 16px; border: 1px solid var(--border);
            border-radius: 18px; background: var(--surface);
        }
        .workflow-strip-copy { min-width: 0; }
        .workflow-strip-title { margin: 0; color: var(--text); font-size: 14px; font-weight: 800; }
        .workflow-strip-note { margin: 4px 0 0; color: var(--muted); font-size: 12.5px; line-height: 1.45; }
        .workflow-strip-actions { display: flex; align-items: center; gap: 8px; flex: none; }

        /* Formulario contable compartido por la cola explícita y el auxiliar histórico. */
        /* 🩸 A9 · EL AVISO DE EJERCICIO AJENO (2026-09-03). Va AQUÍ y no en el CSS del
           drill porque la cola explícita —donde el formulario se pinta SIEMPRE abierto, sin
           ningún clic— no incluye aquel archivo: la regla habría quedado sin estilo justo en
           la superficie donde más se lee. Sin barra de color ni recuadro de alerta (T2: se
           separa con líneas, no con cajas); el rojo lo lleva SOLO la frase de la
           complementaria, que es el riesgo real — T1 no lo reparte por el bloque entero. */
        .con-reclas-ejercicio {
            margin: var(--e3) 0 0; color: var(--muted-strong);
            font-size: 12px; line-height: 1.5; max-width: 62ch;
        }
        .con-reclas-ejercicio strong { color: var(--text); }
        .con-reclas-ejercicio .con-complementaria { color: var(--danger); font-weight: 700; }
        .con-reclas-question { margin-top: 16px; }
        .con-reclas-question h2 { margin: 0; font-size: 15px; font-weight: 800; }
        .con-reclas-question p { margin: 4px 0 0; color: var(--muted); font-size: 12.5px; }
        .con-reclas-form {
            display: grid; grid-template-columns: minmax(200px, 1fr) minmax(220px, 1.3fr) auto;
            gap: 12px; align-items: end; margin-top: 13px;
        }
        /* ── EL ALCANCE DE LA DECISIÓN (2026-08-22) ──────────────────────────────────────────
           `grid-column: 1 / -1` NO es cosmética: `.con-reclas-form` es una rejilla de tres
           columnas (cuenta · motivo · botón) y un cuarto hijo se habría metido dentro de la
           primera, estrujando el selector de cuentas. Ocupa la fila entera porque la pregunta
           «¿a qué se aplica?» es de la decisión COMPLETA, no de uno de sus campos.
           Sin cajas anidadas (regla T2 de la casa: se separa con LÍNEAS, no con tarjetas). */
        /* 🪤 ESTO LLEVABA MEDIDAS A MANO (diez y dieciocho píxeles) y el gate de deuda visual
           lo cazó: «espacio: 1043 (techo 1040, +3) — este número solo puede bajar». Tenía razón
           y no es cosmético: la escala de 4 (--e1..--e8) es lo que hace que dos pantallas
           distintas se sientan del mismo producto, y cada píxel suelto la erosiona. Los dos
           valores viejos no existen en ninguna escala; eran los que «se veían bien» al
           escribirlos.

           📝 Y una nota sobre el propio gate, para quien lo toque: su censo es TEXTUAL y no
           distingue código de comentario, así que escribir aquí una medida con la sintaxis
           `propiedad: NNpx` la cuenta como violación. Por eso este comentario las nombra con
           palabras. No es grave —el número sigue siendo monótono— pero encarece documentar el
           defecto que se acaba de corregir, que es justo lo que esta casa quiere fomentar. */
        .con-reclas-alcance {
            grid-column: 1 / -1; margin: 0; padding: var(--e3) 0 0;
            border: 0; border-top: 1px solid var(--border);
            display: flex; flex-wrap: wrap; align-items: center;
            gap: var(--e2) var(--e4);
        }
        .con-reclas-alcance legend {
            padding: 0; color: var(--muted-strong); font-size: 11px; font-weight: 800;
            letter-spacing: .04em; text-transform: uppercase;
        }
        .con-reclas-alcance label {
            display: inline-flex; align-items: center; gap: var(--e2); cursor: pointer;
            font-size: 13px; color: var(--text);
        }
        /* El radio nativo se queda: es el control que el sistema operativo ya sabe dibujar,
           anunciar al lector de pantalla y operar con teclado. Lo que se estilan son sus
           HERMANOS. `accent-color` lo tiñe del negro de la casa sin reimplementarlo — que es
           justo lo que hace que un `<input type=file>` sin estilo se vea barato y un radio no. */
        .con-reclas-alcance input[type="radio"] { accent-color: var(--accent); margin: 0; }
        .con-reclas-alcance strong { font-weight: 700; }

        .con-reclas-field { display: grid; gap: 6px; min-width: 0; }
        .con-reclas-field label {
            color: var(--muted-strong); font-size: 11px; font-weight: 800;
            letter-spacing: .04em; text-transform: uppercase;
        }
        .con-reclas-field input, .con-reclas-field select {
            width: 100%; min-width: 0; box-sizing: border-box; padding: 11px 12px;
            border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
            color: var(--text); font: inherit; font-size: 13px;
        }
        /* Las cuentas SAT tienen etiquetas largas. Con el popup absoluto + nowrap, abrirlo
           ensanchaba el documento completo en 375px (aunque el campo sí cupiera). El panel
           pertenece al ancho del control y sus opciones envuelven dentro de él. */
        .con-reclas-field details.dd-facade,
        .pol-field details.dd-facade { width: 100%; min-width: 0; max-width: 100%; }
        .con-reclas-field .dd-facade .multi-options,
        .pol-field .dd-facade .multi-options {
            width: 100%; min-width: 0; max-width: 100%; box-sizing: border-box;
        }
        .con-reclas-field .dd-facade .multi-opt,
        .pol-field .dd-facade .multi-opt { white-space: normal; overflow-wrap: anywhere; }
        .con-reclas-submit { min-height: 42px; padding: 11px 20px; }

        .app-nav a:focus-visible,
        .app-empresa-static:focus-visible,
        .app-back:focus-visible,
        .distill-tabs a:focus-visible,
        .btn:focus-visible, .btn-primary:focus-visible, .btn-ghost:focus-visible,
        summary:focus-visible {
            outline: 2px solid currentColor;
            outline-offset: 2px;
        }

        @media (max-width: 640px) {
            .workflow-strip { align-items: stretch; flex-direction: column; }
            .workflow-strip-actions { flex-wrap: wrap; }
            .workflow-strip-actions .btn,
            .workflow-strip-actions .btn-primary,
            .workflow-strip-actions .btn-ghost { flex: 1 1 auto; }
        }
        @media (max-width: 760px) {
            .con-reclas-form { grid-template-columns: 1fr; }
            .con-reclas-submit { width: 100%; }
        }

/* ══ Dropdown homologado (2026-07-14) — UN componente para TODO el panel ══
   Nació en los filtros de /facturas (mecánica Excel) y se generalizó al resto
   (emisión, month-nav, configuración): el popup nativo del select no se puede
   estilizar y partía la UI en dos formatos (pedido del founder). Dos modos:
   · filtros: la verdad vive en inputs nativos adentro (checkbox/radio);
   · fachada (dd-facade): la verdad sigue en un <select> nativo OCULTO — todo el
     JS legado (options[], .value=, filtrado PF/PM) sigue funcionando intacto.
   El guardián business.E003 impide selects nativos en forms de filtros; el test
   de censo DOM (tests_navegador_selects) vigila el resto de las páginas. */
details.multi-select { position: relative; }
details.multi-select > summary {
    list-style: none; border: 1px solid var(--border); background: var(--surface); border-radius: 0;
    padding: 9px 36px 9px 12px; font-size: var(--t-sm); color: var(--text); cursor: pointer;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    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='%230a0a0a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 12px center;
}
details.multi-select > summary::-webkit-details-marker { display: none; }
details.multi-select[open] > summary { border-color: var(--text); outline: 2px solid var(--text); outline-offset: 1px; }
details.multi-select.dd-invalid > summary {
    border-color: var(--danger); outline: 2px solid var(--danger); outline-offset: 1px;
}
.dd-validation { color: var(--danger); font-size: var(--t-2xs); align-self: center; }
/* [hidden] SIEMPRE gana: display:grid (abajo) pisaba el display:none del user-agent y el
   panel "oculto" seguía visible — el atributo hidden pierde contra CUALQUIER display de autor. */
.multi-options[hidden] { display: none !important; }
.multi-options {
    position: absolute; z-index: 8; top: calc(100% + 4px); left: 0; min-width: 100%;
    max-height: 320px; overflow-y: auto;
    background: var(--surface); border: 1px solid var(--border); border-radius: 0; padding: 6px;
    border: 1px solid var(--text); display: grid; gap: 2px;
}
.multi-opt {
    display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 0;
    font-size: 13px; font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--text);
    cursor: pointer; white-space: nowrap; text-align: left;
}
.multi-opt[hidden] { display: none !important; }
.dd-option-search {
    position: sticky; top: 0; z-index: 1; width: 100%; min-width: 0;
    box-sizing: border-box; padding: 9px 10px; border: 1px solid var(--border);
    border-radius: 0; background: var(--surface); color: var(--text);
    font: inherit; font-size: var(--t-sm);
}
.dd-option-search:focus { border-color: var(--text); outline: 2px solid var(--text); outline-offset: 1px; }
.multi-opt:hover { background: var(--surface-soft); }
/* B&W: acento NEGRO — el verde es SOLO ingreso (estándar de marca), no "seleccionado". */
.multi-opt input { width: 15px; height: 15px; accent-color: var(--text); flex: none; }
.multi-opt.multi-all {
    font-weight: 600; border-bottom: 1px solid var(--border);
    border-radius: 0; margin-bottom: 2px;
}
/* Fachada: opciones = botones (la verdad vive en el select oculto de al lado). */
button.multi-opt {
    background: none; border: 0; font-family: inherit; width: 100%;
}
/* Typeahead homologado sobre <datalist> (productos/empleados/cobrables): el popup nativo del
   OS es oscuro e inestilizable — mismo motivo que los selects. El wrap ancla el panel. */
.dd-typeahead-wrap { position: relative; }
.dd-ta-panel { top: 100%; margin-top: 4px; }
.multi-opt.dd-selected { background: var(--surface-soft); font-weight: 700; }
/* display:none NO afecta la serialización del form (el select sigue viajando en el POST). */
select.dd-oculto { display: none !important; }

/* Secciones del menú de claves (founder: "división muy sutil, minimalista") */
.multi-sec {
    font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--muted); padding: 6px 8px 2px; white-space: nowrap;
}
.multi-sec.sec-divisor { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 8px; }
.cp-panel .multi-opt strong { font-weight: 700; font-variant-numeric: tabular-nums; }
.cp-panel .cp-desc { color: var(--muted-strong); margin-left: 8px; overflow: hidden; text-overflow: ellipsis; }


/* ═══ RESPONSIVE AL FINAL, A PROPÓSITO ═══
   Este bloque vivía ARRIBA y `.app-empresa-static { display: grid }` —definida 60 líneas más
   abajo, misma especificidad— le ganaba por ORDEN DE CASCADA: la tarjeta de empresa seguía
   apilada en la cabecera del teléfono. Se vio en la captura, no en el código.
   Un override responsive va DESPUÉS de lo que anula, o no anula nada. */
        /* 📱 EL TELÉFONO (medido 2026-08-09, 390×844 con contexto TÁCTIL de verdad).
           El móvil nunca se había medido. El censo: **436px de navegación antes del primer dato**
           en TODAS las pantallas — sobre 844px de alto, más de la mitad del primer vistazo era
           cromo. La regla vieja (`grid-template-columns: 1fr` + `height: auto`) no era responsive:
           era la misma columna, tumbada encima del contenido.

           LA FORMA NATIVA: cabecera fina arriba (marca · empresa · cuenta) y los enlaces del nav
           anclados ABAJO como la tab bar de iOS. Y encaja sin inventar nada porque la regla de la
           casa —**sidebar ≤5**— es exactamente el tope de una tab bar nativa: los 5 caben.

           SIN DUPLICAR MARCADO: es el MISMO `<nav>`, recolocado por CSS. Un segundo nav para móvil
           serían dos fuentes de verdad sobre cuál está activo, y el JS de `afterSettle` que pinta
           `.active` tendría que conocer las dos. */
        @media (max-width: 960px) {
            /* 🪤 LA CABECERA CRECÍA EN LAS PANTALLAS CORTAS (medido: 61px en facturas, 193 en
               resumen, 233 en empresas — MISMO CSS). `.app-shell` es un grid con `min-height:100vh`:
               en una columna, sus dos filas (cabecera y contenido) se REPARTEN el sobrante, así que
               cuanto menos contenido hay, más se estira la cabecera. `auto 1fr` la fija a su alto
               natural y le da el resto al contenido. */
            .app-shell { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
            /* 🪤 En rejilla, min-width:auto del ítem = su min-content — y con el nombre en
               nowrap eso es EL TEXTO ENTERO (296px): la columna crecía a 620 y el navegador
               alejaba la página (medido con bisección). El cero permite encoger → elipsis. */
            .app-sidebar, .app-sidebar > * { min-width: 0; }

            /* CABECERA: una fila, no una columna. Pegada arriba para no perderla al bajar. */
            .app-sidebar {
                position: sticky;
                top: 0;
                z-index: 30;
                height: auto;
                flex-direction: row;
                align-items: center;
                gap: var(--e2);
                padding: var(--e2) var(--e3);
                border-bottom: 1px solid var(--border);
            }
            .app-brand { flex-shrink: 0; padding: 0; border-bottom: none; }
            .app-brand strong { font-size: 17px; }

            .app-empresa-static { flex: 1 1 auto; min-width: 0; display: flex; align-items: stretch; }
            .app-empresa-id { flex: 1; min-width: 0; padding: var(--e1) var(--e2); border-bottom: none; }
            .app-empresa-manage {
                flex-shrink: 0; white-space: nowrap; padding: var(--e1) var(--e2);
                border-top: none; border-left: 1px solid var(--border);
            }
            /* En la cabecera del teléfono el RFC extra la ENGORDA (censo: tope 72px) —
               ahí basta la razón social; el RFC vive en Empresas. */
            .app-empresa-rfc-linea { display: none; }
            /* En 390px la razón social larga se parte en 5 líneas y la cabecera crece a
               160px (medido). Una línea con elipsis: el nombre completo vive en Empresas. */
            .app-empresa-name { white-space: nowrap; overflow: hidden;
                                text-overflow: ellipsis; word-break: normal; display: block; }

            /* La cuenta cabe en la cabecera: en un teléfono basta el avatar. */
            .app-foot {
                flex-shrink: 0; flex-direction: row; align-items: center;
                margin: 0; padding: 0; border-top: none;
            }
            .app-acct { width: auto; }
            .app-acct-name,
            .app-acct-ops { display: none; }
            .app-acct-user { padding: var(--e2); }

            /* TAB BAR: los ≤5 del nav, abajo, con blanco de toque de 44px (guía de Apple).
               `env(safe-area-inset-bottom)` deja libre la barra de gestos del iPhone; en un
               aparato sin muesca vale 0 y no estorba. */
            .app-nav {
                position: fixed;
                left: 0; right: 0; bottom: 0;
                z-index: 40;
                flex: none;
                flex-direction: row;
                gap: 0;
                background: var(--bg);
                border-top: 1px solid var(--text);
                padding: var(--e1) var(--e1) calc(var(--e1) + env(safe-area-inset-bottom, 0px));
            }
            .app-nav a {
                flex: 1 1 0;
                min-width: 0;
                min-height: 44px;
                display: flex;
                align-items: center;
                justify-content: center;
                text-align: center;
                padding: var(--e2) 2px;
                font-size: var(--t-2xs);
                border-radius: var(--r-sm);
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }
            /* El separador de secciones no significa nada en una fila de 5; y el aviso de setup es
               un párrafo que rompería la tab bar. ⚠️ Se ocultan A PROPÓSITO: el aviso de "conecta
               tu empresa" sigue viéndose en el cuerpo de la pantalla de setup, que es su sitio. */
            .app-nav-divider,
            .app-nav-hint { display: none; }

            /* Que la tab bar no tape el final del contenido: 44 + holgura. */
            .app-main { padding-top: var(--e4); padding-bottom: 84px; }
        }

/* ══ LA CAPA EDITORIAL DEL REWORK (F2, 2026-08-23) — dirección: design/referencias/DIRECCION.md.
   Vive en panel.css porque TODAS las pantallas del panel la heredan; las clases son uz-* porque
   ese es el sistema canónico de la casa. Tipos: Archivo (display, eje de anchura expandido) y
   Plex Mono (importes/códigos — la columna de dinero SIEMPRE alinea). Las fuentes ya viven en
   main/static/main/fonts/ desde F1: mismo archivo, cero duplicación. */
@font-face {
    font-family: "Archivo";
    font-style: normal;
    font-weight: 100 900;
    font-stretch: 62% 125%;
    font-display: swap;
    src: url("../../main/fonts/archivo-latin.de2f1fe81758.woff2") format("woff2");
}
@font-face {
    font-family: "Plex Mono";
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("../../main/fonts/plexmono-latin.b1c8a895f5fd.woff2") format("woff2");
}
.uz-display { font-family: "Archivo", "Inter", sans-serif; font-weight: 800;
              letter-spacing: -0.035em; font-variation-settings: 'wdth' 116; }
.uz-mono { font-family: "Plex Mono", monospace; font-weight: 500;
           font-variant-numeric: tabular-nums; }
.uz-eti { font-size: var(--t-2xs); font-weight: 600; letter-spacing: 0.14em;
          text-transform: uppercase; color: var(--muted); }
/* El punto del estado sano — el LED verde de la referencia favorita del founder. */
.uz-punto::before { content: ''; display: inline-block; width: 7px; height: 7px;
                    border-radius: var(--r-full); background: var(--data-in-soft);
                    margin-right: var(--e2); vertical-align: 2px; }
/* La firma del sistema: el número fantasma. Un contenedor position:relative + overflow:hidden
   lo recorta; SIEMPRE sangra por ABAJO (por arriba se lee decapitado — lección de la tarjeta). */
.uz-fantasma { position: absolute; right: -4vw; bottom: -0.35em; font-size: 16vw; line-height: 0.8;
               color: var(--text); opacity: 0.045; white-space: nowrap; pointer-events: none;
               user-select: none; }

/* ══ EL VOCABULARIO DEL FORMATO (05-sep) — sin el riel (06-sep) ══════════════════════════════
   Facturas (ea02bea3) habla con estas clases: ceja en mono con los mandos a la derecha, el ESTADO
   como héroe («● AL DÍA», como Sincronización), h1 de 20 px, bloques con hairline en vez de
   tarjetas. El RIEL de sección que las acompañaba se revirtió por orden del founder (06-sep:
   «el apartado izquierdo como subsección le roba espacio al contenido»); el vocabulario se queda
   porque una pantalla lo usa y el rework completo que sigue lo va a redefinir. */
.uz-ceja { display: flex; justify-content: space-between; align-items: center; gap: var(--e4);
           flex-wrap: wrap; min-height: 44px; }
.uz-ceja-acc { display: flex; align-items: center; gap: var(--e3); flex-wrap: wrap; margin-left: auto; }
.uz-estado { display: inline-flex; align-items: center; gap: var(--e3); margin: var(--e3) 0 0;
             font-family: "Plex Mono", ui-monospace, monospace; font-size: var(--t-md);
             font-weight: 800; letter-spacing: 0.02em; text-transform: uppercase; color: var(--text); }
.uz-estado::before { content: ''; flex: none; width: 9px; height: 9px; box-sizing: border-box;
                     border-radius: var(--r-full); background: var(--data-in-soft); }
.uz-estado.is-pend::before { background: transparent; border: 2px solid var(--text); }
.uz-estado.is-mal { color: var(--danger); }
.uz-estado.is-mal::before { background: var(--danger); }
.uz-estado.is-vacio { color: var(--muted); }
.uz-estado.is-vacio::before { background: transparent; border: 2px solid var(--muted); }
.uz-h1 { margin: var(--e3) 0 0; font-size: var(--t-lg); font-weight: 800; letter-spacing: -0.02em;
         line-height: 1.2; }
.uz-sub1 { margin: var(--e2) 0 0; font-size: var(--t-md); color: var(--muted); line-height: 1.5; }
.uz-sub1 b, .uz-sub1 strong { color: var(--text); font-weight: 800; }
.uz-sub1 a, .uz-nota a { color: var(--text); font-weight: 700; text-decoration: underline;
                         text-underline-offset: 2px; }
.uz-acciones { display: flex; align-items: center; gap: var(--e4); flex-wrap: wrap; margin-top: var(--e4); }
.uz-bloque { margin-top: var(--e5); padding-top: var(--e5); border-top: 1px solid var(--border); }
.uz-bloque-cab { display: flex; justify-content: space-between; align-items: baseline; gap: var(--e4);
                 flex-wrap: wrap; margin-bottom: var(--e4); }
.uz-bloque-cab > .uz-eti:first-child { color: var(--text); }
.uz-nota { margin: var(--e3) 0 0; font-size: var(--t-xs); color: var(--muted); line-height: 1.5;
           max-width: 78ch; }
.uz-nota strong { color: var(--muted-strong); }
@media print { .uz-ceja-acc { display: none !important; } }
