/*? =====================================================================
    TEMA DE MARCA — UPAEP  ·  Sistema de Diseño «Express»
    Plugin de tema; requiere la capa de roles (en style.css) cargada antes.

    Fuente de verdad: `Sistema de Diseño UPAEP Express.html` (sep 2026), un
    export empaquetado: el HTML servido solo trae el cargador y TODO el
    sistema viaja dentro del bundle (una hoja global de tokens + 33
    componentes JSX + 8 marcas en vector). Los valores de aquí salen de ese
    contenido, no del DOM inicial.
    Los valores marcados "derivado" NO vienen del sistema: se infirieron aquí.

    ---------------------------------------------------------------------
    POR QUÉ EXISTE ESTE ARCHIVO SI UPAEP YA ES LA MARCA POR DEFECTO
    ---------------------------------------------------------------------
    `style.css` ya trae un bloque `:root, [data-brand="upaep"]` que mapea los
    roles a los valores HISTÓRICOS del kit. Este archivo es otra cosa: la
    capa del **sistema Express**, que depuró el UI KIT de Figma y fijó
    decisiones que el core todavía no refleja. Es OPT-IN: una página que solo
    carga `style.css` no cambia ni un píxel.

    Lo que Express corrige respecto al core:

      · UN SOLO ROJO. El sistema declara `#E30921` como el único rojo
        institucional y retira el antiguo "Rojo UPAEP" `#E30521`. El core
        tiene `--ui-primary: #e10023`, que es un TERCER rojo y no aparece ni
        una vez en el sistema. Aquí el primario pasa a `#E30921` — el valor
        que el core ya guardaba en `--upaep-color-red`.
      · EL PRIMARIO NO ES EL ÚNICO COLOR DE ACCIÓN. Express reparte
        intención por color: rojo = destructivo/institucional, verde =
        continuar, azul = acción e información, amarillo = precaución.
      · CÁPSULA DE 30px. Controles (botón, campo, tag) en cápsula y
        contenedores en esquina de 10px. Nada intermedio.
      · EL BORDE DE CAMPO ES EL NEUTRO DE TRABAJO `#52565A`, no un gris
        claro.
      · MODO OSCURO: EL NEUTRO DEL CORE. El sistema publica una paleta oscura
        propia (negro, títulos amarillos, rojo en rosa) pero está DESCARTADA
        a propósito; sus valores quedan anotados en la capa 2.


    ---------------------------------------------------------------------
    PREFIJO DE LOS PRIMITIVOS: `--upaep-ex-*`, NO `--upaep-*`
    ---------------------------------------------------------------------
    Las demás marcas prefijan sus primitivos con su nombre (`--iesde-navy`).
    Aquí eso sería `--upaep-*`, que es EXACTAMENTE el namespace de los ~1900
    tokens de componente del core (`--upaep-btn-bg`, `--upaep-card-*`…). Un
    `--upaep-red` propio se leería como token del core y cualquier colisión
    futura sería invisible. Por eso los primitivos llevan el nombre del
    sistema: `--upaep-ex-*`. Los modificadores, igual: `.__upaep-ex-*`.

    ---------------------------------------------------------------------
    ALCANCE — se activa en CUALQUIER elemento, no solo en <html>
    ---------------------------------------------------------------------
    Todos los selectores son `[data-brand="upaep"] …`, así que la marca vale
    para el subárbol donde se ponga el atributo:

        <html data-brand="iesde">
          …
          <section data-brand="upaep"> … </section>   … isla UPAEP
          …
        </html>

    Dos consecuencias:
      · los overlays que el runtime mueve a <body> (modales, dropdowns,
        tooltips) SALEN del subárbol y vuelven a la marca del ancestro;
      · el modo oscuro se resuelve abajo con tres selectores para que
        funcione tanto si `data-theme` está en el mismo elemento como en un
        ancestro o un descendiente.

    ---------------------------------------------------------------------
    CAPAS
    ---------------------------------------------------------------------
      1. TOKENS       primitivos --upaep-ex-* + remapeo de roles --ui-*
      2. MODO OSCURO  el neutro del core, repuesto con TRES selectores

      3. TIPOGRAFÍA   los 21 estilos publicados, sobre etiquetas reales
      4. COMPONENTES  reviste los del uikit por sus propias variables
      5. PATRONES     bloques de página como clases .__upaep-ex-*
      6. RESPONSIVE   la escala móvil SÍ es del sistema; los cortes, derivados
    ===================================================================== */

/* Fira Sans y Fira Sans Condensed —las dos familias del sistema— ya las
   importa el core en la primera línea de style.css. Esta marca no carga
   ninguna fuente. */

/*? =====================================================================
    1. TOKENS
    ===================================================================== */

[data-brand="upaep"] {

    /*? --- Paleta corporativa ----------------------------------------------
        Los cuatro colores de la lámina Color del archivo: un primario y tres
        neutros. Todo lo demás se deriva de aquí. */
    --upaep-ex-corp-primary: #E30921;
    --upaep-ex-corp-secondary: #878E94;
    --upaep-ex-corp-neutral-light: #ADB2B6;
    --upaep-ex-corp-neutral-dark: #52565A;

    /*? --- Paleta ampliada -------------------------------------------------
        Dos colores de apoyo. No sustituyen al primario: lo acompañan. */
    --upaep-ex-amp-primary: #1D335B;
    --upaep-ex-amp-secondary: #FFCC00;

    /*? --- Derivados de marca ----------------------------------------------
        Estados de cada color de paleta. El sistema es explícito: no hay
        tonos fuera de esta lista. */
    --upaep-ex-red: #E30921;
    --upaep-ex-red-hover: #C2001E;
    --upaep-ex-red-soft: #F5ACB7;
    --upaep-ex-navy: #1D335B;
    --upaep-ex-navy-hover: #192A49;
    --upaep-ex-navy-soft: #AEB5C1;
    --upaep-ex-yellow: #FFCC00;
    --upaep-ex-yellow-button: #FECB15;
    --upaep-ex-yellow-hover: #EEBA00;
    --upaep-ex-yellow-soft: #FEEEB3;

    /*? --- Azul de acción --------------------------------------------------
        "Blue 500 sin envolvente": botones y enlaces. Es el color de acción
        del sistema, no un semántico de información. */
    --upaep-ex-action: #0085FF;
    --upaep-ex-action-hover: #006BCC;
    --upaep-ex-action-soft: #8DC9FF;

    /*? --- Rampa neutra (11 pasos) -----------------------------------------
        El 800 es el neutro de TRABAJO: bordes de campo, texto secundario y
        botón secundario salen de ahí. */
    --upaep-ex-gray-100: #F5F5F5;
    --upaep-ex-gray-200: #EEEEEE;
    --upaep-ex-gray-300: #E1E1E1;
    --upaep-ex-gray-350: #DBDBDB;
    --upaep-ex-gray-400: #B8BABC;
    --upaep-ex-gray-500: #AEAEAE;
    --upaep-ex-gray-600: #909496;
    --upaep-ex-gray-700: #707070;
    --upaep-ex-gray-800: var(--upaep-ex-corp-neutral-dark);
    --upaep-ex-gray-850: #434343;
    --upaep-ex-gray-900: #2E2E2E;
    --upaep-ex-gray-950: #212121;
    --upaep-ex-white: #FFFFFF;
    --upaep-ex-black: #000000;

    /*? --- Variables publicadas en la biblioteca ---------------------------
        Transcritas con su nombre y su intención de uso originales. */
    --upaep-ex-lib-red: #E30921;
    --upaep-ex-lib-red-hover: #C2001E;
    --upaep-ex-lib-blue-800-headings: #1D335B;
    --upaep-ex-lib-blue-500: #0085FF;
    --upaep-ex-lib-yellow-complementary: #FFCC00;
    --upaep-ex-lib-background: #EEEEEE;
    --upaep-ex-lib-widgets: #FFFFFF;
    --upaep-ex-lib-gray-text: #1D1D1F;

    /*? --- Estatus de pase -------------------------------------------------
        Cada estatus tiene DOS entradas: el color de texto e icono, y el de
        fondo de la etiqueta. El sistema pide no mezclarlos. */
    --upaep-ex-green-100-icons: #19CF6E;
    --upaep-ex-green-200-label: #D4EDDA;
    --upaep-ex-green-300-approved: #28A745;
    --upaep-ex-yellow-200-label: #F5E6AD;
    --upaep-ex-yellow-300-review: #C7A52E;
    --upaep-ex-red-200-label: #FFE0E3;
    --upaep-ex-red-300-rejected: #FF4D5F;

    /*? --- Estado ----------------------------------------------------------- */
    --upaep-ex-success: var(--upaep-ex-green-300-approved);
    --upaep-ex-success-hover: #1E7E34;
    --upaep-ex-success-soft: #A3D9AE;
    --upaep-ex-success-bg: var(--upaep-ex-green-200-label);
    --upaep-ex-error: var(--upaep-ex-red-300-rejected);
    --upaep-ex-error-bg: var(--upaep-ex-red-200-label);
    --upaep-ex-warning: var(--upaep-ex-yellow-300-review);
    --upaep-ex-warning-bg: var(--upaep-ex-yellow-200-label);
    /* El sistema declara el semántico de INFORMACIÓN y el azul de ACCIÓN
       como el mismo color: no hay dos azules. */
    --upaep-ex-info: var(--upaep-ex-action);

    /*? --- Textos endurecidos de los fondos tenues --------------------------
        Los pastel de etiqueta no llevan el mismo color que el relleno
        sólido: el sistema escribe encima con estos tonos. Salen de los
        componentes Alert, Tag y KpiCard del bundle. */
    --upaep-ex-on-success-bg: #1B6B2E;
    --upaep-ex-on-warning-bg: #815A00;
    --upaep-ex-on-error-bg: #A4162A;
    /* ⚠ El sistema usa DOS rojos oscuros y no nombra ninguno: el de arriba
       está en Alert, y este en KpiCard (delta negativo y crítico) y en
       FaceRating (la cara 1). No son intercambiables. */
    --upaep-ex-red-deep: #A10617;

    --upaep-ex-on-info-bg: #006BCC;
    --upaep-ex-info-bg: #D6E6FF;

    /*? --- Etiquetas -------------------------------------------------------
        Seis pasteles para categorizar SIN jerarquía. Ninguno comunica
        estado. Cinco de los seis ya viven en el core, en los tonos
        `__status` del badge; solo el 6 difiere (el core trae #C2CBFF). */
    --upaep-ex-label-1: #CCF6FF;
    --upaep-ex-label-2: #FFEEB0;
    --upaep-ex-label-3: #DEFAC3;
    --upaep-ex-label-4: #FFD2B1;
    --upaep-ex-label-5: #FFD7E6;
    --upaep-ex-label-6: #DFE3FF;

    /*? --- Escala tipográfica ----------------------------------------------
        ⚠ El core NO tiene roles de escala tipográfica: solo las familias
        (--ui-font-base / --ui-font-heading). La escala se aplica en la capa
        3 sobre etiquetas y modificadores.

        Todos los estilos publicados llevan interlineado Auto —el natural de
        la fuente—, de ahí `normal` y no un porcentaje: forzarlo rompería la
        métrica del archivo. */
    --upaep-ex-fs-h1-section: 56px;
    --upaep-ex-fs-h2-subtitle: 36px;
    --upaep-ex-fs-h3-entry: 28px;
    --upaep-ex-fs-h3-card: 26px;
    --upaep-ex-fs-h5-featured: 32px;
    --upaep-ex-fs-p1-web-large: 20px;
    --upaep-ex-fs-p2-semilarge: 18px;
    --upaep-ex-fs-p2-web-small: 16px;
    --upaep-ex-fs-p3-regular: 16px;
    --upaep-ex-fs-p4-medium: 14px;
    --upaep-ex-fs-p5-small: 12px;

    /* Móvil — la escala móvil SÍ está publicada; ver capa 6 */
    --upaep-ex-fs-h1-section-mobile: 26px;
    --upaep-ex-fs-h2-subtitle-mobile: 24px;
    --upaep-ex-fs-h3-card-mobile: 22px;

    /* Condensed */
    --upaep-ex-fs-h1-extracondensed: 56px;
    --upaep-ex-fs-h1-condensed: 50px;
    --upaep-ex-fs-h3-condensed: 32px;
    --upaep-ex-fs-h4-condensed: 26px;
    --upaep-ex-fs-p1-condensed: 16px;
    --upaep-ex-fs-p2-condensed: 14px;

    --upaep-ex-lh-auto: normal;
    --upaep-ex-lh-reading: 1.55;

    /* Estilos completos, en `font:` shorthand. Fira Sans en sistemas y
       títulos institucionales; Fira Sans Condensed en portal y web. */
    --upaep-ex-text-h1-section: var(--upaep-fw-medium) var(--upaep-ex-fs-h1-section)/var(--upaep-ex-lh-auto) var(--ui-font-base);
    --upaep-ex-text-h2-subtitle: var(--upaep-fw-semibold) var(--upaep-ex-fs-h2-subtitle)/var(--upaep-ex-lh-auto) var(--ui-font-base);
    --upaep-ex-text-h3-entry: var(--upaep-fw-semibold) var(--upaep-ex-fs-h3-entry)/var(--upaep-ex-lh-auto) var(--ui-font-base);
    --upaep-ex-text-h3-card: var(--upaep-fw-bold) var(--upaep-ex-fs-h3-card)/var(--upaep-ex-lh-auto) var(--ui-font-base);
    --upaep-ex-text-h5-featured: var(--upaep-fw-light) var(--upaep-ex-fs-h5-featured)/var(--upaep-ex-lh-auto) var(--ui-font-base);
    --upaep-ex-text-p1-web-large: var(--upaep-fw-regular) var(--upaep-ex-fs-p1-web-large)/var(--upaep-ex-lh-auto) var(--ui-font-base);
    --upaep-ex-text-p2-semilarge: var(--upaep-fw-regular) var(--upaep-ex-fs-p2-semilarge)/var(--upaep-ex-lh-auto) var(--ui-font-base);
    --upaep-ex-text-p3-regular: var(--upaep-fw-regular) var(--upaep-ex-fs-p3-regular)/var(--upaep-ex-lh-auto) var(--ui-font-base);
    --upaep-ex-text-p4-medium: var(--upaep-fw-regular) var(--upaep-ex-fs-p4-medium)/var(--upaep-ex-lh-auto) var(--ui-font-base);
    --upaep-ex-text-p5-small: var(--upaep-fw-regular) var(--upaep-ex-fs-p5-small)/var(--upaep-ex-lh-auto) var(--ui-font-base);

    --upaep-ex-text-h1-extracondensed: var(--upaep-fw-bold) var(--upaep-ex-fs-h1-extracondensed)/var(--upaep-ex-lh-auto) var(--ui-font-heading);
    --upaep-ex-text-h1-condensed: var(--upaep-fw-medium) var(--upaep-ex-fs-h1-condensed)/var(--upaep-ex-lh-auto) var(--ui-font-heading);
    --upaep-ex-text-h3-condensed: var(--upaep-fw-medium) var(--upaep-ex-fs-h3-condensed)/var(--upaep-ex-lh-auto) var(--ui-font-heading);
    --upaep-ex-text-h4-condensed: var(--upaep-fw-medium) var(--upaep-ex-fs-h4-condensed)/var(--upaep-ex-lh-auto) var(--ui-font-heading);
    --upaep-ex-text-p1-condensed: var(--upaep-fw-regular) var(--upaep-ex-fs-p1-condensed)/var(--upaep-ex-lh-reading) var(--ui-font-heading);
    --upaep-ex-text-p2-condensed: var(--upaep-fw-regular) var(--upaep-ex-fs-p2-condensed)/var(--upaep-ex-lh-reading) var(--ui-font-heading);

    /*? --- Espaciado · base 4 ---------------------------------------------- */
    --upaep-ex-space-1: 2px;
    --upaep-ex-space-2: 4px;
    --upaep-ex-space-3: 8px;
    --upaep-ex-space-4: 12px;
    --upaep-ex-space-5: 16px;
    --upaep-ex-space-6: 24px;
    --upaep-ex-space-7: 32px;
    --upaep-ex-space-8: 40px;
    --upaep-ex-space-9: 48px;
    --upaep-ex-space-10: 56px;
    --upaep-ex-space-11: 64px;

    /* Anchos de contenedor por breakpoint (los del archivo) */
    --upaep-ex-container-desktop: 1200px;
    --upaep-ex-container-tablet: 648px;
    --upaep-ex-container-mobile: 312px;

    /* Alturas de control */
    --upaep-ex-touch-min: 44px;

    /*? --- Radios ----------------------------------------------------------
        ⚠ El core NO tiene roles --ui-radius-*: se aplican componente a
        componente en la capa 4.

        El sistema es de DOS gestos: cápsula de 30px para todo lo que se
        toca y esquina de 10px para todo lo que contiene. Nada intermedio;
        los demás valores son excepciones por rol. */

    /*? --- Tintas de los neutros que se INVIERTEN en oscuro ----------------
        Cuatro variantes de botón se pintan con el extremo oscuro de la rampa
        (contorno, __dark, __black, __grey). Sobre la superficie oscura del
        sistema (#2E2E2E) ese extremo es invisible: el contorno quedaba con
        aro y texto #2E2E2E sobre #2E2E2E.

        Pasan por estos tokens en vez de por la rampa directa para que el
        bloque de oscuro pueda darles la vuelta sin duplicar las reglas. En
        claro valen EXACTAMENTE lo que dice el sistema. */
    --upaep-ex-ink: var(--upaep-ex-gray-900);
    --upaep-ex-on-ink: var(--upaep-ex-white);
    --upaep-ex-ink-hover: var(--upaep-ex-gray-850);
    --upaep-ex-btn-black-bg: var(--upaep-ex-gray-950);
    --upaep-ex-btn-black-hover: var(--upaep-ex-gray-900);
    /* Texto sobre los tonos CLAROS de deshabilitado. El sistema escribe en
       blanco sobre ellos (1.9:1 en el rojo suave) — WCAG exime a los
       controles inactivos, así que se respeta. En oscuro se invierte: blanco
       sobre #F5ACB7 en una página negra se lee como un fallo, no como un
       estado. Derivado. */
    --upaep-ex-on-soft: var(--upaep-ex-white);
    --upaep-ex-btn-grey-bg: var(--upaep-ex-gray-700);
    --upaep-ex-btn-grey-hover: var(--upaep-ex-gray-800);

    /*? --- Elevación -------------------------------------------------------
        Solo dos sombras nombradas en el archivo, más la de tarjeta. */
    --upaep-ex-shadow-1: 0 0 8px 0 rgba(0, 0, 0, .5);
    --upaep-ex-shadow-2: 0 0 6px 0 rgba(0, 0, 0, .25);
    --upaep-ex-shadow-card: 0 4px 4px 0 rgba(0, 0, 0, .25);

    /*? --- Movimiento ------------------------------------------------------
        Transiciones cortas y planas; el kit no usa rebotes ni escalados. */
    --upaep-ex-duration-fast: 120ms;
    --upaep-ex-duration-base: 180ms;
    --upaep-ex-duration-slow: 260ms;
    --upaep-ex-ease: cubic-bezier(0.2, 0, 0.2, 1);

    /*? =================================================================
        REMAPEO DE ROLES --ui-*
        Lo ÚNICO que consumen los componentes del kit.
        ================================================================= */

    /* ---- Marca ----
       ⚠ CORRECCIÓN respecto al core: el primario pasa de #e10023 a
       #E30921. Express declara un único rojo institucional y el #e10023
       del core no aparece en el sistema. 4.85:1 con blanco → AA. */
    --ui-primary: var(--upaep-ex-red);
    --ui-primary-hover: var(--upaep-ex-red-hover);
    --ui-primary-border: var(--upaep-ex-red-hover);
    --ui-on-primary: var(--upaep-ex-white);

    /* El "destacado" del sistema: amarillo de botón. Texto negro (13.6:1). */
    --ui-secondary: var(--upaep-ex-yellow-button);
    --ui-secondary-hover: var(--upaep-ex-yellow-hover);
    --ui-secondary-border: var(--upaep-ex-yellow-hover);
    --ui-on-secondary: var(--upaep-ex-black);

    /* ⚠ El terciario cambia de sentido: en el core es un gris CLARO
       (#d0d0d0) con texto negro; en Express el botón "secundario" es el
       neutro de trabajo #52565A con texto blanco (7.4:1). */
    --ui-tertiary: var(--upaep-ex-gray-800);
    --ui-tertiary-hover: var(--upaep-ex-gray-850);
    --ui-tertiary-border: var(--upaep-ex-gray-850);
    --ui-on-tertiary: var(--upaep-ex-white);

    /* ---- Estados semánticos ---- */
    --ui-success: var(--upaep-ex-success);
    --ui-success-hover: var(--upaep-ex-success-hover);
    --ui-success-border: var(--upaep-ex-success-hover);
    --ui-on-success: var(--upaep-ex-white);
    --ui-success-subtle: var(--upaep-ex-success-bg);
    --ui-on-success-subtle: var(--upaep-ex-on-success-bg);
    --ui-success-strong: var(--upaep-ex-success-hover);

    /* ⚠ #FF4D5F da 3.24:1 con blanco: por debajo de AA para texto normal.
       Es el valor del sistema —lo usa como color de TEXTO E ICONO del
       estatus "rechazado", no como relleno de botón—. El botón destructivo
       de Express es el rojo institucional (.__primary), no .__error. */
    --ui-danger: var(--upaep-ex-error);
    --ui-danger-hover: #E63347;
    --ui-danger-border: #E63347;
    --ui-on-danger: var(--upaep-ex-white);
    --ui-danger-subtle: var(--upaep-ex-error-bg);
    --ui-on-danger-subtle: var(--upaep-ex-on-error-bg);

    --ui-warning: var(--upaep-ex-warning);
    --ui-warning-hover: #AD8D1F;
    --ui-warning-border: #AD8D1F;
    --ui-on-warning: var(--upaep-ex-black);
    --ui-warning-subtle: var(--upaep-ex-warning-bg);
    --ui-on-warning-subtle: var(--upaep-ex-on-warning-bg);
    --ui-warning-strong: var(--upaep-ex-warning);

    /* ⚠ El azul de información pasa de #437EEA (core) a #0085FF: en Express
       el azul de acción y el de información son el MISMO color.
       3.62:1 con blanco → vale para texto grande y UI, no para 14px. */
    --ui-info: var(--upaep-ex-info);
    --ui-info-hover: var(--upaep-ex-action-hover);
    --ui-info-border: var(--upaep-ex-action-hover);
    --ui-on-info: var(--upaep-ex-white);
    --ui-info-subtle: var(--upaep-ex-info-bg);
    /*? U-04 · 4.18:1 sobre su propio pastel. El pastel es la SUPERFICIE del tag;
       este rol es el TEXTO que se lee encima, no 'el azul del estado'. */
    --ui-on-info-subtle: #00509B;                    /* 6.34:1 */
    --ui-info-strong: var(--upaep-ex-action-hover);

    /* ---- Superficies y texto ----
       ⚠ El core tiene surface-2 = #F5F5F5 y surface-3 = #EEEEEE. Express lo
       invierte: el FONDO DE PÁGINA es #EEEEEE ("Background" de la
       biblioteca) y #F5F5F5 es la superficie alterna (filas pares). */
    --ui-surface: var(--upaep-ex-lib-widgets);
    --ui-surface-2: var(--upaep-ex-lib-background);
    --ui-surface-2-border: var(--upaep-ex-gray-300);
    --ui-surface-3: var(--upaep-ex-gray-100);

    /* ⚠ El texto base pasa de navy (#1D335B en el core) a #1D1D1F: en
       Express el navy es el color de TÍTULO, no el del cuerpo. */
    --ui-text: var(--upaep-ex-lib-gray-text);
    --ui-text-strong: var(--upaep-ex-navy);
    /*? U-01 · Esta hoja re-declaraba el rol con `#909496` (3.06 / 2.64 / 2.81) y
       ganaba al valor corregido del core por orden de carga. El texto SECUNDARIO
       es texto: cumple 4.5 en las tres superficies o no es legible. */
    --ui-text-muted: #676B70;                        /* 5.37 / 4.92 / 4.62 */
    --ui-text-on-surface: var(--upaep-ex-gray-800);

    /* ⚠ El borde de campo del sistema es el neutro de trabajo, no un gris
       claro: el campo lleva 1px de #52565A. */
    --ui-border: var(--upaep-ex-gray-800);
    --ui-border-subtle: var(--upaep-ex-gray-300);
    --ui-divider: var(--upaep-ex-gray-350);
    --ui-surface-hover: var(--upaep-ex-gray-200);

    /* ---- Foco / sombra / tipografía ----
       El foco del sistema es el azul de acción, no el navy del core.

       ⚠ `--ui-control-ring` NO se remapea, aunque sea el mismo tipo de rol.
       El core lo define como «anillo de foco de controles de formulario» y lo
       consumen `--upaep-input-focus-boxshadow`, checkbox, radio, tag, dropzone,
       selectpicker, autocomplete, datepicker, numberpicker y selectfilters:
       tocarlo cambia el `box-shadow` que el kit da por defecto a los campos,
       que es justo lo que esta capa no debe hacer. Se notaba a ojo —el input
       enfocado salía con aro azul mientras el select, que no lee el rol,
       conservaba el gris del kit—.
       `--ui-focus-ring` sí se remapea: ningún control del kit lo lee (lo usan
       componentes de paquete —agendae, agora, axiom, courier— para su propio
       aro, y ahí el azul de acción es el color correcto). */
    --ui-focus-ring: rgba(0, 133, 255, .25);

    --ui-shadow: var(--upaep-ex-shadow-card);
    --ui-ripple: rgba(0, 0, 0, .30);
    /* Las familias del core ya son las del sistema: no se toca ninguna. */

    /* ---- Acento institucional ---- */
    --ui-accent: var(--upaep-ex-red);
    --ui-on-accent: var(--upaep-ex-white);

    /* ---- Superficie inversa / neutra oscura ----
       El gris 950 es la "barra superior y bloques de código" del sistema. */
    --ui-surface-inverse: var(--upaep-ex-gray-950);
    --ui-on-surface-inverse: var(--upaep-ex-white);
    --ui-neutral: var(--upaep-ex-gray-950);
    --ui-on-neutral: var(--upaep-ex-white);

    /* ---- Contadores y enlaces ----
       El Badge de Express es rojo por defecto (el core lo pinta navy). */
    --ui-counter: var(--upaep-ex-red);
    --ui-on-counter: var(--upaep-ex-white);
    /*? U-02 · 3.62:1. Un enlace es texto. */
    --ui-link: #0B62C4;                              /* 5.90:1 */
    --ui-link-hover: var(--upaep-ex-action-hover);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] {
    --upaep-ex-control-height: 42px;
    --upaep-ex-button-height: 46px;
    --upaep-ex-button-height-float: 55px;
    --upaep-ex-radius-control: 30px;
    --upaep-ex-radius-container: 10px;
    --upaep-ex-radius-xs: 4px;
    --upaep-ex-radius-sm: 8px;
    --upaep-ex-radius-lg: 20px;
    --upaep-ex-radius-full: 9999px;
}

/*? =====================================================================
    2. MODO OSCURO — EL NEUTRO DEL CORE
    El oscuro de esta marca es el **modo oscuro NEUTRAL del core**
    (`[data-theme="dark"]` en `style.css`). Aquí no se elige ni un color:
    este bloque solo REPONE, con el valor exacto del core, los roles que la
    capa 1 tapa.

    ⚠ POR QUÉ HAY QUE REPONERLOS. `[data-brand="upaep"]` (capa 1) y
    `[data-theme="dark"]` (core) pesan lo mismo —(0,1,0)— y esta hoja se
    carga DESPUÉS, así que sin este bloque los valores de CLARO de la capa 1
    le ganarían al neutro. Son exactamente los **28 roles** que están en las
    dos listas; lo que la capa 1 no toca lo resuelve el neutro solo, y por
    eso no aparece aquí. `tools/verify` comprueba esa correspondencia: si el
    core añade un rol a su oscuro y la capa 1 lo pisa, hay que reponerlo.

    Los colores CROMÁTICOS de la marca **no cambian**: el rojo sigue siendo
    `#E30921`, el azul de acción `#0085FF` y los de estado los suyos. Lo que
    cambia es el papel —superficies, texto, bordes, enlaces y sombras—, que
    es justo lo que hace el neutro para todas las marcas del kit.

    ⚠ QUÉ NO SE USA, y queda anotado porque es un hallazgo del archivo: el
    sistema **sí** publica una paleta oscura propia, y está **descartada a
    propósito** (decisión de Mario). Sus valores exactos, por si algún día se
    quieren: fondo `#000000`, superficie de widgets `#2E2E2E`, títulos en
    AMARILLO `#FFDA55`, el rojo en rosa `#F66C7A`, el azul en `#68B7FF`,
    estados `#18CC6C` / `#FF7785` / `#ECC745` y fondos de etiqueta claros
    `#C5DCAE` / `#E3D7AB` / `#E0B7C6`.

    ⚠ TRES selectores. Con solo `[data-brand][data-theme]` en el mismo
    elemento, una isla de marca dentro de una página con el tema en <html>
    (o al revés) se queda en claro.
    ===================================================================== */

[data-brand="upaep"][data-theme="dark"],
[data-theme="dark"] [data-brand="upaep"],
[data-brand="upaep"] [data-theme="dark"]:not(:where([data-brand])) {

    /*? --- Papel, texto y bordes: los del neutro, literales ---------------
        Copiados uno a uno del bloque `[data-theme="dark"]` de `style.css`.
        No se eligen aquí; si el neutro del core cambia, esta lista se
        sincroniza (y el script lo detecta). */
    --ui-surface: #1b1b1e;
    --ui-surface-2: #232327;
    --ui-surface-2-border: #3a3a40;
    --ui-surface-3: #2c2c31;
    --ui-surface-inverse: #26262b;
    --ui-text: #ececf0;
    --ui-text-strong: #ffffff;
    --ui-text-muted: #9a9aa2;
    --ui-text-on-surface: #c9c9d0;
    /*? U-07 oscuro · 1.52:1: el borde de un input era invisible sobre el fondo
       oscuro. Los decorativos siguen sin tocarse. */
    --ui-border: #767681;                            /* 3.83 / 3.49 */
    --ui-border-subtle: #3a3a40;
    --ui-divider: #2f2f34;
    --ui-neutral: #3a3a40;
    --ui-surface-hover: #2c2c31;
    --ui-counter: #2c4a7a;
    --ui-link: #4da3ff;
    --ui-link-hover: #7cbcff;
    --ui-focus-ring: rgba(255, 255, 255, .22);
    --ui-shadow: 1px 2px 8px rgb(0 0 0 / 60%);
    --ui-ripple: rgba(255, 255, 255, .35);

    /* Estados tenues: relleno translúcido y texto claro. En claro esta marca
       usa los seis pasteles del sistema, que sobre papel oscuro serían
       manchas; el neutro los resuelve con transparencia. */
    --ui-success-subtle: rgba(40, 167, 69, .18);
    --ui-on-success-subtle: #7ee2a1;
    --ui-danger-subtle: rgba(220, 53, 69, .18);
    --ui-on-danger-subtle: #f2a3ac;
    --ui-warning-subtle: rgba(255, 193, 7, .16);
    --ui-on-warning-subtle: #f0cf6a;
    --ui-info-subtle: rgba(67, 126, 234, .20);
    --ui-on-info-subtle: #a9c5f7;

    /* Las tres sombras nombradas del sistema pasan a la del neutro: las de
       claro son negras al 25-50% y sobre papel oscuro no se ven. */
    --upaep-ex-shadow-1: var(--ui-shadow);
    --upaep-ex-shadow-2: var(--ui-shadow);
    --upaep-ex-shadow-card: var(--ui-shadow);

    /*? --- Las cuatro tintas que hay que voltear --------------------------
        Cuatro variantes de botón se pintan en claro con el extremo OSCURO de
        la rampa (contorno, `__dark`, `__black`, `__grey`) y sobre el papel
        del neutro (#1b1b1e) desaparecerían. Se voltean al extremo CLARO de
        la misma rampa del sistema, con su texto en el paso más oscuro. No
        entra ningún tono nuevo: son pasos de la rampa de Express. */
    --upaep-ex-ink: var(--upaep-ex-gray-300);
    --upaep-ex-ink-hover: var(--upaep-ex-white);
    --upaep-ex-on-ink: var(--upaep-ex-gray-950);
    --upaep-ex-on-soft: var(--upaep-ex-gray-950);
    --upaep-ex-btn-black-bg: var(--upaep-ex-gray-200);
    --upaep-ex-btn-black-hover: var(--upaep-ex-white);
    --upaep-ex-btn-grey-bg: var(--upaep-ex-gray-500);
    --upaep-ex-btn-grey-hover: var(--upaep-ex-gray-400);
}

/*? =====================================================================
    3. TIPOGRAFÍA
    Los 21 estilos publicados en la biblioteca, aplicados a las ETIQUETAS
    reales dentro del alcance de la marca. Los modificadores cubren los
    estilos que no tienen etiqueta propia; van en inglés, como el resto del
    uikit, y SIN prefijo de marca porque describen un rol, no algo de UPAEP.

      h1                  H1 título sección      500 · 56
      h1.__hero           H1 extracondensed      700 · 56  · Condensed
      h2                  H2 subtítulo           600 · 36
      h2.__entry          H3 entrada normal      600 · 28  · italic
      h3                  H3 título card         700 · 26
      h4                  (derivado)             600 · 20
      p                   P3 párrafo regular     400 · 16
      p.__lead            P1 párrafo web grande  400 · 20
      p.__semilarge       P2 párrafo semigrande  400 · 18
      p.__small           P4 párrafo medio       400 · 14
      p.__caption         P5 párrafo pequeño     400 · 12
      .__featured         H5 subtítulo destacado 300 · 32 · rojo
      .__condensed        cambia la familia a Fira Sans Condensed
      .__reading          sube el interlineado a 1.55 sin tocar el tamaño

    ⚠ `:where()` en los selectores de etiqueta: el core SÍ tiene reglas `p`
    y `h1..h4` sueltas. Sin `:where()` la marca pesaría (0,1,1) y pisaría los
    <p> que generan los componentes del kit.
    ===================================================================== */

[data-brand="upaep"] {
    font-family: var(--ui-font-base);
    color: var(--ui-text);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] {
    font-size: var(--upaep-ex-fs-p3-regular);
    line-height: var(--upaep-ex-lh-reading);
}

:where([data-brand="upaep"]) h1 {
    color: var(--ui-text-strong);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h1 {
    font: var(--upaep-ex-text-h1-section);
    margin: 0 0 .5rem;
}

:where([data-brand="upaep"]) h1.__hero {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h1.__hero {
    font: var(--upaep-ex-text-h1-extracondensed);
}

:where([data-brand="upaep"]) h2 {
    color: var(--ui-text-strong);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h2 {
    font: var(--upaep-ex-text-h2-subtitle);
    margin: 0 0 .5rem;
}

/* La "entrada normal" del sistema es la única cursiva de la escala. */
:where([data-brand="upaep"]) h2.__entry {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h2.__entry {
    font: var(--upaep-ex-text-h3-entry);
    font-style: italic;
}

:where([data-brand="upaep"]) h3 {
    color: var(--ui-text-strong);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h3 {
    font: var(--upaep-ex-text-h3-card);
    margin: 2rem 0 1rem;
}

/* El sistema no publica un cuarto nivel: este es derivado. */
:where([data-brand="upaep"]) h4 {
    color: var(--ui-text-strong);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h4 {
    font: var(--upaep-fw-semibold) 20px/1.3 var(--ui-font-base);
    margin: 1.5rem 0 .75rem;
}

:where([data-brand="upaep"]) p {
    color: var(--ui-text);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) p {
    font: var(--upaep-ex-text-p3-regular);
    line-height: var(--upaep-ex-lh-reading);
    margin: 0 0 1rem;
}

:where([data-brand="upaep"]) p.__lead {
    color: var(--ui-text-on-surface);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) p.__lead {
    font: var(--upaep-ex-text-p1-web-large);
    line-height: var(--upaep-ex-lh-reading);
}

:where([data-brand="upaep"]) p.__semilarge {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) p.__semilarge {
    font: var(--upaep-ex-text-p2-semilarge);
    line-height: var(--upaep-ex-lh-reading);
}

:where([data-brand="upaep"]) p.__small {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) p.__small {
    font: var(--upaep-ex-text-p4-medium);
    line-height: var(--upaep-ex-lh-reading);
}

:where([data-brand="upaep"]) p.__caption {
    color: var(--ui-text-muted);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) p.__caption {
    font: var(--upaep-ex-text-p5-small);
    line-height: var(--upaep-ex-lh-reading);
}

/* Destacado: el único estilo de la escala que trae color propio. */
[data-brand="upaep"] .__featured {
    color: var(--ui-accent);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__featured {
    font: var(--upaep-ex-text-h5-featured);
}

/* Familia condensada. El sistema la reparte por SUPERFICIE (portal y web),
   no por nivel, así que va como modificador y no dentro de cada etiqueta. */
[data-brand="upaep"] .__condensed {
    font-family: var(--ui-font-heading);
}

:where([data-brand="upaep"]) h1.__condensed {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h1.__condensed {
    font: var(--upaep-ex-text-h1-condensed);
}

:where([data-brand="upaep"]) h2.__condensed {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h2.__condensed {
    font: var(--upaep-ex-text-h3-condensed);
}

:where([data-brand="upaep"]) h3.__condensed {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h3.__condensed {
    font: var(--upaep-ex-text-h4-condensed);
}

:where([data-brand="upaep"]) p.__condensed {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) p.__condensed {
    font: var(--upaep-ex-text-p1-condensed);
}

:where([data-brand="upaep"]) p.__condensed.__small {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) p.__condensed.__small {
    font: var(--upaep-ex-text-p2-condensed);
}

/* Bloques de texto largo: sube el interlineado sin cambiar el token. */
[data-brand="upaep"] .__reading {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__reading {
    line-height: var(--upaep-ex-lh-reading);
}

/* Puente con las clases tipográficas propias del uikit, para que un bloque
   escrito con ellas también hable Express. */
[data-brand="upaep"] .upaep__title {
    --upaep-title-color: var(--ui-text-strong);
    color: var(--ui-text-strong);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__title {
    font: var(--upaep-ex-text-h1-section);
}

[data-brand="upaep"] .upaep__subtitle {
    --upaep-subtitle-color: var(--ui-text-strong);
    color: var(--ui-text-strong);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__subtitle {
    font: var(--upaep-ex-text-h2-subtitle);
}

[data-brand="upaep"] .upaep__subtitle-2 {
    color: var(--ui-text-strong);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__subtitle-2 {
    font: var(--upaep-ex-text-h3-card);
}

[data-brand="upaep"] .upaep__text {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__text {
    font: var(--upaep-ex-text-p3-regular);
    line-height: var(--upaep-ex-lh-reading);
}

[data-brand="upaep"] .upaep__subtext {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__subtext {
    font: var(--upaep-ex-text-p4-medium);
    line-height: var(--upaep-ex-lh-reading);
}

[data-brand="upaep"] .upaep__caption {
    color: var(--ui-text-muted);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__caption {
    font: var(--upaep-ex-text-p5-small);
    line-height: var(--upaep-ex-lh-reading);
}

/* El sistema no publica un "overline", pero el catálogo lo usa como rótulo
   de grupo: 11-12px en mayúsculas con tracking. Derivado del uso real. */
[data-brand="upaep"] .upaep__overline {
    text-transform: uppercase;
    color: var(--ui-text-muted);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__overline {
    font: var(--upaep-fw-semibold) 11px/1.4 var(--ui-font-base);
    letter-spacing: .08em;
}

/*? =====================================================================
    4. COMPONENTES
    Reviste componentes EXISTENTES del uikit a través de sus propias
    variables. No define componentes nuevos; cuando el sistema pide una
    variante que el uikit no tiene, se añade como MODIFICADOR .__upaep-ex-*.
    ===================================================================== */

/*? ------ Botón ------
    Cápsula de 30px, alto 46, Fira Sans Bold 16, padding 10px 24px, ancho
    mínimo 140. Cuatro alturas (30/38/46/55) y ocho familias de color, cada
    una con su propio deshabilitado —el sistema NO usa opacidad para
    apagarlas, usa un tono claro de la familia—.

    Reparto de intención del sistema (esto es doctrina, no estética):
      rojo      eliminar/cancelar en sistemas; en el portal, institucional
      verde     marcha, arranque, éxito, continuar
      azul      acción, información neutral, enlaces
      amarillo  precaución, corregir una anomalía

    ⚠ La FORMA (cápsula, alto, ancho mínimo) va SOLO en las variantes
    públicas, nunca en `.upaep__btn` a secas: el runtime construye con esa
    misma clase base los botones internos de Selectpicker, Numberpicker,
    Dropzone, Payment y las vistas (`upaep__btn __selectpicker is-close`,
    `upaep__btn __dropzone`, `upaep__btn __back`…), y vestirla los deforma.

    ⚠ Y hay variantes de COLOR que también son internas: el runtime genera
    los botones de Signature como `upaep__btn __signature __rounded
    __success __save`. Por eso `__success` y `__blue` entran en la lista
    pero el `:not(:is(…))` excluye cualquier botón que lleve además una
    clase de componente. */
[data-brand="upaep"] .upaep__btn:is(.__primary, .__secondary, .__tertiary, .__success, .__error, .__warning, .__blue, .__blue-sky, .__sky, .__black, .__grey, .__dark, .__light, .__upaep-ex-outline, .__upaep-ex-text):not(:is(.__signature, .__selectpicker, .__dropzone, .__back, .__views, .__view-back, .__payment, .__datepicker, .__timepicker, .__autocomplete, .__checkbox, .__radio, .__tab, .__slice, .__contacto, .__flotante, .__menu, .__menu-circle, .__more, .__delete, .__trinity, .__appointments, .__add-schedule, .__delete-schedule, .__copy-schedules, .__clear-schedules, .__dropdown-buttons, .__modalidad)) {
    /* El sistema apaga con un tono claro de la familia, no bajando alfa. */
    --upaep-btn-opacity-disabled: 1;
    white-space: nowrap;
    transition: background var(--upaep-ex-duration-base) var(--upaep-ex-ease),
        color var(--upaep-ex-duration-base) var(--upaep-ex-ease),
        box-shadow var(--upaep-ex-duration-base) var(--upaep-ex-ease),
        transform var(--upaep-ex-duration-fast) var(--upaep-ex-ease);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__btn:is(.__primary, .__secondary, .__tertiary, .__success, .__error, .__warning, .__blue, .__blue-sky, .__sky, .__black, .__grey, .__dark, .__light, .__upaep-ex-outline, .__upaep-ex-text):not(:is(.__signature, .__selectpicker, .__dropzone, .__back, .__views, .__view-back, .__payment, .__datepicker, .__timepicker, .__autocomplete, .__checkbox, .__radio, .__tab, .__slice, .__contacto, .__flotante, .__menu, .__menu-circle, .__more, .__delete, .__trinity, .__appointments, .__add-schedule, .__delete-schedule, .__copy-schedules, .__clear-schedules, .__dropdown-buttons, .__modalidad)) {
    --upaep-btn-border-radius: var(--upaep-ex-radius-control);
    --upaep-btn-hover-border-radius: var(--upaep-ex-radius-control);
    --upaep-btn-height: var(--upaep-ex-button-height);
    --upaep-btn-padding: 10px 24px;
    --upaep-btn-margin: 0;
    --upaep-btn-border-size: 0;
    --upaep-btn-hover-border-size: 0;
    --upaep-btn-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-btn-fw: var(--upaep-fw-bold);
    --upaep-btn-hover-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-btn-hover-fw: var(--upaep-fw-bold);
    --upaep-btn-cont-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-btn-cont-fw: var(--upaep-fw-bold);
    min-width: 140px;
    gap: 10px;
    line-height: 1;
}

/* ⚠ Un SVG inline dentro de `.upaep__btn` se estira: el botón es flex y el
   svg no trae `flex-shrink: 0`. */
[data-brand="upaep"] .upaep__btn svg {
    flex: 0 0 auto;
}

/* Pulsado: un hundimiento de 1px. Ningún cambio de color, para no inventar
   un cuarto tono por familia. */
[data-brand="upaep"] .upaep__btn:is(.__primary, .__secondary, .__tertiary, .__success, .__blue, .__blue-sky, .__sky, .__light, .__upaep-ex-outline):active:not(:disabled) {
    transform: translateY(1px);
}

/*? Alturas. Ojo: xs y sm quedan por debajo del área táctil mínima de 44px
    (--upaep-ex-touch-min), así que en móvil piden una zona táctil mayor.

    ⚠ El core fija `--upaep-btn-width` en `.__sm` (130px) y `.__lg` (282px);
    el sistema trabaja con ancho MÍNIMO, no fijo, así que se libera el
    width y el número pasa a min-width. */
[data-brand="upaep"] .upaep__btn.__upaep-ex-xs {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__btn.__upaep-ex-xs {
    --upaep-btn-height: 30px;
    --upaep-btn-padding: 6px 16px;
    --upaep-btn-fz: var(--upaep-ex-fs-p5-small);
    --upaep-btn-hover-fz: var(--upaep-ex-fs-p5-small);
    --upaep-btn-cont-fz: var(--upaep-ex-fs-p5-small);
    min-width: 0;
}

[data-brand="upaep"] .upaep__btn.__sm {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__btn.__sm {
    --upaep-btn-width: auto;
    --upaep-btn-height: 38px;
    --upaep-btn-padding: 9px 22px;
    --upaep-btn-fz: 13px;
    --upaep-btn-hover-fz: 13px;
    --upaep-btn-cont-fz: 13px;
    min-width: 0;
}

[data-brand="upaep"] .upaep__btn.__lg {
    /* El botón grande lleva un aro interior blanco de 1px en el archivo. */
    box-shadow: inset 0 0 0 1px var(--upaep-ex-white);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__btn.__lg {
    --upaep-btn-width: auto;
    --upaep-btn-height: var(--upaep-ex-button-height-float);
    --upaep-btn-padding: 10px 24px;
    --upaep-btn-fz: var(--upaep-ex-fs-p1-web-large);
    --upaep-btn-hover-fz: var(--upaep-ex-fs-p1-web-large);
    --upaep-btn-cont-fz: var(--upaep-ex-fs-p1-web-large);
    min-width: 241px;
}

/* Rectangular: el sistema admite esquina de 4px cuando el botón vive dentro
   de una rejilla densa (barras de herramientas, matrices). */
[data-brand="upaep"] .upaep__btn.__upaep-ex-rect {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__btn.__upaep-ex-rect {
    --upaep-btn-border-radius: var(--upaep-ex-radius-xs);
    --upaep-btn-hover-border-radius: var(--upaep-ex-radius-xs);
}

/*? Deshabilitados por familia — muestreados uno a uno del frame
    web_buttons. Los que el core ya resuelve por rol no se repiten. */
[data-brand="upaep"] .upaep__btn.__primary {
    --upaep-btn-disabled-bg: var(--upaep-ex-red-soft);
    --upaep-btn-disabled-border-color: var(--upaep-ex-red-soft);
    --upaep-btn-disabled-color: var(--upaep-ex-on-soft);
    --upaep-btn-disabled-cont-color: var(--upaep-ex-on-soft);
}

[data-brand="upaep"] .upaep__btn.__secondary {
    --upaep-btn-disabled-bg: var(--upaep-ex-yellow-soft);
    --upaep-btn-disabled-border-color: var(--upaep-ex-yellow-soft);
    --upaep-btn-disabled-color: var(--upaep-ex-gray-600);
    --upaep-btn-disabled-cont-color: var(--upaep-ex-gray-600);
}

[data-brand="upaep"] .upaep__btn.__tertiary {
    --upaep-btn-disabled-bg: var(--upaep-ex-gray-200);
    --upaep-btn-disabled-border-color: var(--upaep-ex-gray-200);
    --upaep-btn-disabled-color: var(--upaep-ex-gray-400);
    --upaep-btn-disabled-cont-color: var(--upaep-ex-gray-400);
}

[data-brand="upaep"] .upaep__btn.__success {
    --upaep-btn-disabled-bg: var(--upaep-ex-success-soft);
    --upaep-btn-disabled-border-color: var(--upaep-ex-success-soft);
    --upaep-btn-disabled-color: var(--upaep-ex-on-soft);
    --upaep-btn-disabled-cont-color: var(--upaep-ex-on-soft);
}

/* Institucional. ⚠ El core cablea el hover a --upaep-color-blue-primary-hover
   (#234885); el sistema lo quiere en #192A49. */
[data-brand="upaep"] .upaep__btn.__blue {
    --upaep-btn-bg: var(--upaep-ex-navy);
    --upaep-btn-border-color: var(--upaep-ex-navy);
    --upaep-btn-hover-bg: var(--upaep-ex-navy-hover);
    --upaep-btn-hover-border-color: var(--upaep-ex-navy-hover);
    --upaep-btn-disabled-bg: var(--upaep-ex-navy-soft);
    --upaep-btn-disabled-border-color: var(--upaep-ex-navy-soft);
    --upaep-btn-disabled-color: var(--upaep-ex-on-soft);
    --upaep-btn-disabled-cont-color: var(--upaep-ex-on-soft);
}

/* Acción. ⚠ Mismo caso: el core cablea el hover a
   --upaep-color-blue-sky-hover (#3564BC), ajeno a la paleta de Express. */
[data-brand="upaep"] .upaep__btn:is(.__blue-sky, .__sky) {
    --upaep-btn-hover-bg: var(--upaep-ex-action-hover);
    --upaep-btn-hover-border-color: var(--upaep-ex-action-hover);
    --upaep-btn-disabled-bg: var(--upaep-ex-action-soft);
    --upaep-btn-disabled-border-color: var(--upaep-ex-action-soft);
    --upaep-btn-disabled-color: var(--upaep-ex-on-soft);
    --upaep-btn-disabled-cont-color: var(--upaep-ex-on-soft);
}

/* Claro. El relleno blanco se pierde sobre superficie clara: lleva aro de
   1px. ⚠ El core lo pinta #f8f9fa, que no está en la rampa de Express. */
[data-brand="upaep"] .upaep__btn.__light {
    --upaep-btn-bg: var(--upaep-ex-white);
    --upaep-btn-border-color: var(--upaep-ex-white);
    --upaep-btn-color: var(--upaep-ex-black);
    --upaep-btn-cont-color: var(--upaep-ex-black);
    --upaep-btn-hover-bg: var(--upaep-ex-gray-200);
    --upaep-btn-hover-border-color: var(--upaep-ex-gray-200);
    --upaep-btn-hover-color: var(--upaep-ex-black);
    --upaep-btn-disabled-bg: var(--upaep-ex-gray-400);
    --upaep-btn-disabled-border-color: var(--upaep-ex-gray-400);
    --upaep-btn-disabled-color: var(--upaep-ex-gray-200);
    --upaep-btn-disabled-cont-color: var(--upaep-ex-gray-200);
    box-shadow: inset 0 0 0 1px var(--upaep-ex-gray-300);
}

/* Los tres neutros oscuros del core traen hexes de Bootstrap (#212529,
   #3e3e3e, --colordark3). Se reencauzan a la rampa de Express; el reparto
   —cuál va a cuál— es derivado, porque el sistema solo nombra UN neutro de
   botón (el #52565A de .__tertiary). */
[data-brand="upaep"] .upaep__btn.__dark {
    --upaep-btn-bg: var(--upaep-ex-ink);
    --upaep-btn-border-color: var(--upaep-ex-ink);
    --upaep-btn-color: var(--upaep-ex-on-ink);
    --upaep-btn-cont-color: var(--upaep-ex-on-ink);
    --upaep-btn-hover-bg: var(--upaep-ex-ink-hover);
    --upaep-btn-hover-border-color: var(--upaep-ex-ink-hover);
    --upaep-btn-hover-color: var(--upaep-ex-on-ink);
    --upaep-btn-disabled-bg: var(--upaep-ex-gray-400);
    --upaep-btn-disabled-border-color: var(--upaep-ex-gray-400);
}

[data-brand="upaep"] .upaep__btn.__black {
    --upaep-btn-bg: var(--upaep-ex-btn-black-bg);
    --upaep-btn-border-color: var(--upaep-ex-btn-black-bg);
    --upaep-btn-color: var(--upaep-ex-on-ink);
    --upaep-btn-cont-color: var(--upaep-ex-on-ink);
    --upaep-btn-hover-bg: var(--upaep-ex-btn-black-hover);
    --upaep-btn-hover-border-color: var(--upaep-ex-btn-black-hover);
    --upaep-btn-hover-color: var(--upaep-ex-on-ink);
}

[data-brand="upaep"] .upaep__btn.__grey {
    --upaep-btn-bg: var(--upaep-ex-btn-grey-bg);
    --upaep-btn-border-color: var(--upaep-ex-btn-grey-bg);
    --upaep-btn-hover-bg: var(--upaep-ex-btn-grey-hover);
    --upaep-btn-hover-border-color: var(--upaep-ex-btn-grey-hover);
    --upaep-btn-disabled-bg: var(--upaep-ex-gray-400);
    --upaep-btn-disabled-border-color: var(--upaep-ex-gray-400);
}

/* Semánticos que el sistema no usa como botón: existen en el kit y ahora
   apuntan a los tonos de Express. El deshabilitado es derivado. */
[data-brand="upaep"] .upaep__btn.__error {
    --upaep-btn-disabled-bg: #FFB3BB;
    --upaep-btn-disabled-border-color: #FFB3BB;
    --upaep-btn-disabled-color: var(--upaep-ex-white);
    --upaep-btn-disabled-cont-color: var(--upaep-ex-white);
}

[data-brand="upaep"] .upaep__btn.__warning {
    --upaep-btn-disabled-bg: var(--upaep-ex-yellow-200-label);
    --upaep-btn-disabled-border-color: var(--upaep-ex-yellow-200-label);
    --upaep-btn-disabled-color: var(--upaep-ex-gray-600);
    --upaep-btn-disabled-cont-color: var(--upaep-ex-gray-600);
}

/*? Contorno — el uikit no tiene botón de contorno, así que va como
    MODIFICADOR de `.upaep__btn`. Sin relleno, marco de 1.5px; al pasar el
    cursor se rellena entero. El marco es `box-shadow: inset` y no `border`
    porque el componente redeclara el borde completo en :hover con su
    propia variable de grosor: con border, el marco cambiaría de grueso. */
[data-brand="upaep"] .upaep__btn.__upaep-ex-outline {
    --upaep-btn-bg: transparent;
    --upaep-btn-border-color: transparent;
    --upaep-btn-color: var(--upaep-ex-ink);
    --upaep-btn-cont-color: var(--upaep-ex-ink);
    --upaep-btn-hover-bg: var(--upaep-ex-ink);
    --upaep-btn-hover-border-color: var(--upaep-ex-ink);
    --upaep-btn-hover-color: var(--upaep-ex-on-ink);
    --upaep-btn-hover-cont-color: var(--upaep-ex-on-ink);
    --upaep-btn-disabled-bg: transparent;
    --upaep-btn-disabled-border-color: transparent;
    --upaep-btn-disabled-color: var(--upaep-ex-gray-400);
    --upaep-btn-disabled-cont-color: var(--upaep-ex-gray-400);
    box-shadow: inset 0 0 0 1.5px var(--upaep-ex-ink);
}

[data-brand="upaep"] .upaep__btn.__upaep-ex-outline:disabled {
    box-shadow: inset 0 0 0 1.5px var(--upaep-ex-gray-400);
}

/*? Botón de texto azul, sin envolvente. Su hermano oscuro es `.__underline`
    del propio uikit, que ya pinta el subrayado con --ui-accent (rojo). */
[data-brand="upaep"] .upaep__btn.__upaep-ex-text {
    --upaep-btn-bg: transparent;
    --upaep-btn-border-color: transparent;
    --upaep-btn-color: var(--ui-link);
    --upaep-btn-cont-color: var(--ui-link);
    --upaep-btn-hover-bg: transparent;
    --upaep-btn-hover-border-color: transparent;
    --upaep-btn-hover-color: var(--ui-link);
    --upaep-btn-hover-cont-color: var(--ui-link);
    --upaep-btn-disabled-bg: transparent;
    --upaep-btn-disabled-border-color: transparent;
    --upaep-btn-disabled-color: var(--upaep-ex-gray-400);
    --upaep-btn-disabled-cont-color: var(--upaep-ex-gray-400);
}

[data-brand="upaep"] .upaep__btn.__upaep-ex-text:hover:not(:disabled) {
    text-decoration: underline;
    text-underline-offset: 6px;
}

/* Texto oscuro: negro sin relleno, subrayado rojo al pasar el cursor. Es el
   `.__underline` del kit; solo se ajustan métrica y color de texto. */
[data-brand="upaep"] .upaep__btn.__underline {
    --upaep-btn-color: var(--upaep-ex-black);
    --upaep-btn-cont-color: var(--upaep-ex-black);
    --upaep-btn-hover-color: var(--upaep-ex-black);
    --upaep-btn-disabled-color: var(--upaep-ex-gray-400);
    --upaep-btn-disabled-cont-color: var(--upaep-ex-gray-400);
    --upaep-btn-color-underline: var(--ui-accent);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__btn.__underline {
    --upaep-btn-margin: 0;
    --upaep-btn-padding: 10px 0;
    --upaep-btn-fw: var(--upaep-fw-bold);
    --upaep-btn-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-btn-cont-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-btn-cont-fw: var(--upaep-fw-bold);
    gap: 10px;
}

/*? ------ Navbar ------
    La barra del sistema es blanca, pegada arriba, con la sombra secundaria
    y enlaces en cápsula que solo se tiñen de gris al pasar el cursor.

    Tres cosas del componente que condicionan el revestido:
      · el FONDO y la ALTURA viven en .upaep__navbar-content, no en el <nav>
        → el radio y el overflow van ahí;
      · la altura no puede ser `height` fijo: el -collapse es hijo del
        -content y en móvil se abre con max-height → altura auto + min-height;
      · --upaep-navbar-item-padding se aplica al <li> Y al <a> (mismo
        selector) → se deja en 0 y el respiro va solo en el enlace. */
[data-brand="upaep"] .upaep__navbar {
    --upaep-navbar-bg: var(--ui-surface);
    --upaep-navbar-boxshadow: var(--upaep-ex-shadow-2);
    --upaep-navbar-brand-color: var(--ui-text-strong);
    --upaep-navbar-item-color: var(--ui-text-on-surface);
    --upaep-navbar-item-bg: transparent;
    --upaep-navbar-item-hover-color: var(--ui-text-strong);
    --upaep-navbar-item-hover-bg: transparent;
    --upaep-navbar-item-active-color: var(--ui-text-strong);
    --upaep-navbar-item-active-bg: transparent;
    --upaep-navbar-btn-mark-color: var(--ui-text-on-surface);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__navbar {
    --upaep-navbar-height: auto;
    --upaep-navbar-padding: 0 24px;
    --upaep-navbar-items-padding: 0;
    --upaep-navbar-item-padding: 0;
    --upaep-navbar-item-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-navbar-item-fw: var(--upaep-fw-regular);
    --upaep-navbar-item-hover-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-navbar-item-hover-fw: var(--upaep-fw-regular);
    --upaep-navbar-item-active-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-navbar-item-active-fw: var(--upaep-fw-semibold);
}

[data-brand="upaep"] .upaep__navbar .upaep__navbar-content {
    overflow: hidden;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__navbar .upaep__navbar-content {
    min-height: 68px;
}

[data-brand="upaep"] .upaep__navbar .upaep__navbar-brand {
    display: flex;
    align-items: center;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__navbar .upaep__navbar-brand {
    gap: 12px;
}

[data-brand="upaep"] .upaep__navbar .upaep__navbar-brand :is(img, svg) {
    display: block;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__navbar .upaep__navbar-brand :is(img, svg) {
    height: 36px;
    width: auto;
}

[data-brand="upaep"] .upaep__navbar .upaep__navbar-items {
    flex-wrap: wrap;
    align-items: center;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__navbar .upaep__navbar-items {
    gap: 4px;
}

/* El realce es la cápsula gris del sistema, no un fondo de color. */
[data-brand="upaep"] .upaep__navbar .upaep__navbar-link {
    white-space: nowrap;
    transition: background var(--upaep-ex-duration-base) var(--upaep-ex-ease);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__navbar .upaep__navbar-link {
    padding: 8px 12px;
    border-radius: var(--upaep-ex-radius-control);
}

[data-brand="upaep"] .upaep__navbar .upaep__navbar-link:hover,
[data-brand="upaep"] .upaep__navbar .upaep__navbar-link.is-active {
    background: var(--ui-surface-3);
    text-decoration: none;
}

/* Barra oscura: la variante de sistemas internos (gris 950). */
[data-brand="upaep"] .upaep__navbar.__upaep-ex-dark {
    --upaep-navbar-bg: var(--ui-neutral);
    --upaep-navbar-brand-color: var(--upaep-ex-white);
    --upaep-navbar-item-color: var(--upaep-ex-gray-300);
    --upaep-navbar-item-hover-color: var(--upaep-ex-white);
    --upaep-navbar-item-active-color: var(--upaep-ex-white);
    --upaep-navbar-btn-mark-color: var(--upaep-ex-white);
}

[data-brand="upaep"] .upaep__navbar.__upaep-ex-dark .upaep__navbar-link:hover,
[data-brand="upaep"] .upaep__navbar.__upaep-ex-dark .upaep__navbar-link.is-active {
    /* Velo blanco al 12%: se calcula sobre el token, no se escribe a mano. */
    background: color-mix(in srgb, var(--upaep-ex-white) 12%, transparent);
}

/*? ------ Tabs ------
    Métrica del sistema: 16px en todas, padding 12px 20px; la activa se
    distingue por texto pleno + negrita + riel rojo de 3px. No crece.

    ★ CÓMO SE DIBUJA EL RIEL. El sistema pinta **una línea gris continua en
    el CONTENEDOR** y, encima de ella, un tramo rojo de 3px bajo la pestaña
    activa. Es la forma que da el original y hay que respetarla:

      · `--upaep-tab-tabs-border-bottom-*` → la línea gris de 1px, continua;
      · cada `.upaep__tab-item` lleva `border-bottom: 3px solid transparent`
        y la activa lo pone en rojo.

    Dar el riel gris a CADA pestaña (que es lo primero que sale) deja huecos
    entre ellas: los tramos no se tocan porque las pestañas están separadas.

    ⚠ `--upaep-tab-tabs-margin` viene en `0 1rem`: hay que ponerlo a 0 o la
    línea gris no llega a los extremos del contenedor.

    ⚠ El componente cambia padding, tamaño y peso en :hover y en
    .is-active:hover con variables PROPIAS (--…-hover-fz/-fw/-padding, cuyos
    defaults son .5rem / 16px / bold). Si solo se define el estado normal, al
    pasar el ratón la pestaña salta de tamaño. Por eso se declaran los cuatro
    estados: en Express el hover NO cambia la métrica, solo el color. */
[data-brand="upaep"] .upaep__tab {



    --upaep-tab-tabitem-color: var(--ui-text-on-surface);
    --upaep-tab-tabitem-hover-color: var(--ui-text);
    --upaep-tab-tabitem-active-color: var(--ui-text);
    --upaep-tab-tabitem-active-hover-color: var(--ui-text);

    --upaep-tab-tabitem-bg: transparent;
    --upaep-tab-tabitem-hover-bg: transparent;
    --upaep-tab-tabitem-active-bg: transparent;
    --upaep-tab-tabitem-active-hover-bg: transparent;


    --upaep-tab-tabitem-hover-boxshadow: none;
    --upaep-tab-boxshadow: none;
    --upaep-tab-tabscontent-bg: transparent;
    --upaep-tab-tabscontent-boxshadow: none;

    /* La línea continua del contenedor: 1px gris, de extremo a extremo. */
    --upaep-tab-tabs-border-bottom-color: var(--ui-border-subtle);
    /* Las pestañas se alinean a la izquierda, como en el original, no
       repartidas con `space-around`. */
    --upaep-tab-tabsitem-justify: flex-start;
    /* El elemento "underline" que el uikit anima aparte se apaga: aquí el
       riel activo es el borde inferior de la propia pestaña. */
    --upaep-tab-tabitem-underline-height: 0;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__tab {
    --upaep-tab-tabitem-padding: 12px 20px;
    --upaep-tab-tabitem-hover-padding: 12px 20px;
    --upaep-tab-tabitem-active-padding: 12px 20px;
    --upaep-tab-tabitem-active-hover-padding: 12px 20px;
    --upaep-tab-tabitem-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-tab-tabitem-hover-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-tab-tabitem-active-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-tab-tabitem-active-hover-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-tab-tabitem-fw: var(--upaep-fw-regular);
    --upaep-tab-tabitem-hover-fw: var(--upaep-fw-regular);
    --upaep-tab-tabitem-active-fw: var(--upaep-fw-bold);
    --upaep-tab-tabitem-active-hover-fw: var(--upaep-fw-bold);
    --upaep-tab-tabitem-border-radius: 0;
    --upaep-tab-tabitem-hover-border-radius: 0;
    --upaep-tab-tabitem-active-border-radius: 0;
    --upaep-tab-tabitem-active-hover-border-radius: 0;
    --upaep-tab-padding: 0;
    --upaep-tab-margin: 0;
    --upaep-tab-tabscontent-padding: 16px 0 0;
    --upaep-tab-tabs-border-bottom-size: 1px;
    --upaep-tab-tabs-margin: 0;
}

/* ⚠ `white-space` y `word-break`: el componente trae `text-wrap: balance` y
   `word-break: break-word`, así que un rótulo de dos palabras se parte y las
   pestañas quedan de distinta altura. */
[data-brand="upaep"] .upaep__tab .upaep__tab-item {
    white-space: nowrap;
    text-wrap: nowrap;
    word-break: normal;
    /* Transparente por defecto: deja ver la línea gris del contenedor. */
    border-bottom: 3px solid transparent;
    transition: color var(--upaep-ex-duration-base) var(--upaep-ex-ease),
        border-color var(--upaep-ex-duration-base) var(--upaep-ex-ease);
}

[data-brand="upaep"] .upaep__tab .upaep__tab-item.is-active {
    border-bottom-color: var(--ui-accent);
}

/*? Variante de cápsulas: la barra vive sobre gris 100 y la activa es una
    pastilla blanca con la sombra secundaria.

    ⚠ Tres cosas del componente hay que desactivar aquí:
      · la línea gris del contenedor (esta variante no la lleva);
      · `overflow: hidden` de `.upaep__tabs`, que recortaría la sombra de la
        pastilla activa;
      · `width: 100%` de `.upaep__tabs-item`, que hacía que la cápsula gris
        ocupara todo el ancho disponible y las pastillas se salieran de ella
        por los extremos. Con `fit-content` la cápsula abraza sus pestañas. */
[data-brand="upaep"] .upaep__tab.__upaep-ex-pill {

    --upaep-tab-tabitem-active-bg: var(--ui-surface);
    --upaep-tab-tabitem-active-hover-bg: var(--ui-surface);


    /* La cápsula abraza sus pestañas, así que el contenedor tiene que
       alinearla: con el `space-around` por defecto queda centrada. */
    --upaep-tab-tabs-justify: flex-start;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__tab.__upaep-ex-pill {
    --upaep-tab-tabitem-padding: 8px 20px;
    --upaep-tab-tabitem-hover-padding: 8px 20px;
    --upaep-tab-tabitem-active-padding: 8px 20px;
    --upaep-tab-tabitem-active-hover-padding: 8px 20px;
    --upaep-tab-tabitem-border-radius: var(--upaep-ex-radius-control);
    --upaep-tab-tabitem-hover-border-radius: var(--upaep-ex-radius-control);
    --upaep-tab-tabitem-active-border-radius: var(--upaep-ex-radius-control);
    --upaep-tab-tabitem-active-hover-border-radius: var(--upaep-ex-radius-control);
    --upaep-tab-tabs-border-bottom-size: 0;
}

[data-brand="upaep"] .upaep__tab.__upaep-ex-pill .upaep__tabs {
    overflow: visible;
}

[data-brand="upaep"] .upaep__tab.__upaep-ex-pill .upaep__tabs-item {
    flex-wrap: wrap;
    background: var(--ui-surface-3);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__tab.__upaep-ex-pill .upaep__tabs-item {
    width: fit-content;
    max-width: 100%;
    gap: 8px;
    padding: 4px;
    border-radius: var(--upaep-ex-radius-control);
}

[data-brand="upaep"] .upaep__tab.__upaep-ex-pill .upaep__tab-item {
    border-bottom: none;
}

[data-brand="upaep"] .upaep__tab.__upaep-ex-pill .upaep__tab-item.is-active {
    box-shadow: var(--upaep-ex-shadow-2);
}

/*? ------ Acordeón (details/summary, sin JS) ------
    Caja de 10px con aro de 1px, cabecera de 16px 24px en Condensed 20 y la
    marca en rojo. El contenido va también en Condensed: en el sistema el
    acordeón es una pieza de PORTAL, no de sistemas. */
[data-brand="upaep"] .upaep__details-accordion {
    --upaep-details-accordion-bg: var(--ui-surface);
    --upaep-details-accordion-border-color: var(--ui-border-subtle);
    --upaep-details-accordion-summary-color: var(--ui-text);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__details-accordion {
    --upaep-details-accordion-border-size: 1px;
    --upaep-details-accordion-border-radius: var(--upaep-ex-radius-container);
    --upaep-details-accordion-padding: 16px 24px;
    --upaep-details-accordion-summary-fz: var(--upaep-ex-fs-p1-web-large);
    --upaep-details-accordion-summary-fw: var(--upaep-fw-medium);
}

/* El componente baja la opacidad del resumen a .75; el sistema lo quiere
   pleno, y el título abierto pasa a rojo. */
[data-brand="upaep"] .upaep__details-accordion .upaep__details-summary {
    opacity: 1;
    font-family: var(--ui-font-heading);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__details-accordion .upaep__details-summary {
    gap: 16px;
}

[data-brand="upaep"] .upaep__details-accordion[open] .upaep__details-summary {
    --upaep-details-accordion-summary-color: var(--ui-accent);
}

/* ⚠ La marca del uikit es un `background-image` en `::after` que se cambia
   por otra imagen al abrir. Express no cambia de icono: GIRA el mismo
   chevron 180°, y eso una imagen de fondo no lo puede hacer. Se apaga la
   marca del componente y el icono va inline en el <summary>. */
[data-brand="upaep"] .upaep__details-accordion .upaep__details-summary::after {
    content: none;
}

[data-brand="upaep"] .upaep__details-accordion .__upaep-ex-acc-icon {
    flex: 0 0 auto;
    color: var(--ui-accent);
    transform: rotate(180deg);
    transition: transform var(--upaep-ex-duration-base) var(--upaep-ex-ease);
}

[data-brand="upaep"] .upaep__details-accordion[open] .__upaep-ex-acc-icon {
    transform: rotate(0deg);
}

[data-brand="upaep"] .upaep__details-accordion>div {
    color: var(--ui-text-on-surface);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__details-accordion>div {
    font: var(--upaep-ex-text-p1-condensed);
}

/*? ------ Cards ------
    Esquina de 10px, relleno de 24, sombra de tarjeta y título en Condensed
    26. Sin borde: el sistema separa la tarjeta del fondo con la sombra.

    ⚠ Contrato del componente: `--upaep-card-img-*` dimensiona la <img>
    INTERIOR; el contenedor se controla con `--upaep-card-img-content-*` y
    `--upaep-card-icon_content-*` (sí, con guion bajo). */
[data-brand="upaep"] .upaep__card {
    --upaep-card-bg: var(--ui-surface);
    --upaep-card-border-color: transparent;
    /* ⚠ El sistema BAJÓ la sombra de las cards de `--sombra-tarjeta` a
       `--sombra-2` (revisión de sep 2026), y se la dio también a las tres
       variantes del portal, que antes iban planas. La de tarjeta se queda
       para la TABLA y para el mobiliario de las páginas de documentación. */
    --upaep-card-boxshadow: var(--upaep-ex-shadow-2);
    /* sin esto la card no puede encogerse y desborda su celda del grid */
    --upaep-card-title-color: var(--ui-text-strong);
    --upaep-card-subtitle-color: var(--ui-text-muted);
    --upaep-card-text-color: var(--ui-text-on-surface);
    --upaep-card-header-bg: transparent;
    --upaep-card-header-color: var(--ui-text-strong);
    --upaep-card-header-border-bottom-color: var(--ui-border-subtle);
    --upaep-card-footer-bg: transparent;
    --upaep-card-footer-border-top-color: var(--ui-border-subtle);
    /* ⚠ En el sistema no hay pie: las acciones viven DENTRO de la caja de
       24px de la card, con 16px de aire por arriba. El kit las saca a un
       hermano, así que el pie tiene que traer el relleno lateral e inferior
       de la card o el botón queda pegado al borde —que era el caso—. */

    /* El sistema recorta la imagen solo por arriba. */
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card {
    --upaep-card-border-radius: var(--upaep-ex-radius-container);
    --upaep-card-border-size: 0;
    --upaep-card-content-padding: 24px;
    --upaep-card-margin: 0;
    --upaep-card-minwidth: 0;
    min-width: 0;
    --upaep-card-title-fz: var(--upaep-ex-fs-h3-card);
    --upaep-card-title-fw: var(--upaep-fw-medium);
    --upaep-card-subtitle-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-card-text-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-card-footer-padding: 16px 24px 24px;
    --upaep-card-img-content-border-radius: var(--upaep-ex-radius-container) var(--upaep-ex-radius-container) 0 0;
}

/* El hueco entre acciones es de 12px y el pie del kit no declara ninguno:
   con dos botones se pegaban uno a otro. */
[data-brand="upaep"] .upaep__card .upaep__card-footer {
    display: flex;
    flex-wrap: wrap;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card .upaep__card-footer {
    gap: 12px;
}

/* Las tarjetas del portal son enlaces (`<a class="upaep__card …">`) y sin
   esto heredan el azul de `--ui-link`: el sistema las pinta con su propio
   color de texto. */
[data-brand="upaep"] .upaep__card:is(.__upaep-ex-list, .__upaep-ex-tile) {
    color: var(--ui-text);
}

/* El título y el texto de la card son Condensed: en el sistema la card es
   pieza de portal. El componente no expone familia, así que va directo. */

[data-brand="upaep"] .upaep__card :is(.upaep__card-title, .upaep__card-text) {
    font-family: var(--ui-font-heading);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card :is(.upaep__card-title, .upaep__card-text) {
    line-height: 1.2;
}

/* Los títulos y textos de la card son <p>: hay que neutralizar el margen
   que les pone la capa tipográfica. */
[data-brand="upaep"] .upaep__card p {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card p {
    margin: 0;
}

/* Antetítulo de la card (el "kicker" del sistema): 12px en mayúsculas,
   rojo sobre fondo claro. El uikit no lo tiene; va como modificador. */
[data-brand="upaep"] .upaep__card .__upaep-ex-kicker {
    text-transform: uppercase;
    color: var(--ui-accent);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card .__upaep-ex-kicker {
    font: var(--upaep-fw-bold) var(--upaep-ex-fs-p5-small)/1.3 var(--ui-font-base);
    letter-spacing: .04em;
}

/* Cards de fondo pleno. En las oscuras el antetítulo pasa a amarillo, como
   pide el componente Card del sistema. */
[data-brand="upaep"] .upaep__card.__upaep-ex-navy {
    --upaep-card-bg: var(--upaep-ex-navy);
    --upaep-card-title-color: var(--upaep-ex-white);
    --upaep-card-subtitle-color: var(--upaep-ex-gray-300);
    --upaep-card-text-color: var(--upaep-ex-gray-300);
    /* El tono fija el color de primer plano de TODA la tarjeta, no solo de
       sus textos con token: lo que no tenga variable propia —la flecha de la
       variante lista, que es texto— hereda de aquí. */
    color: var(--upaep-ex-white);
}

[data-brand="upaep"] .upaep__card.__upaep-ex-red {
    --upaep-card-bg: var(--upaep-ex-red);
    --upaep-card-title-color: var(--upaep-ex-white);
    --upaep-card-subtitle-color: rgba(255, 255, 255, .9);
    --upaep-card-text-color: rgba(255, 255, 255, .9);
    color: var(--upaep-ex-white);
}


[data-brand="upaep"] .upaep__card:is(.__upaep-ex-navy, .__upaep-ex-red) .__upaep-ex-kicker {
    color: var(--upaep-ex-yellow);
}

[data-brand="upaep"] .upaep__card.__upaep-ex-gray {
    --upaep-card-bg: var(--ui-surface-3);
    --upaep-card-boxshadow: var(--upaep-ex-shadow-2);
    --upaep-card-text-color: var(--upaep-ex-gray-700);
}

/*? ------ Campos de formulario ------
    Cápsula de 42px con relleno 10px 22px y borde de 1px del NEUTRO DE
    TRABAJO (#52565A) — no un gris claro. El multilínea rompe la cápsula y
    usa la esquina de 10px.

    ★ TRES REGLAS DE ESTA CAPA, y las tres importan:

    1. EL GROSOR DEL BORDE NO CAMBIA NUNCA: 1px en los seis estados (reposo,
       hover, foco, error, acierto, deshabilitado). Subir
       `--upaep-input-focus-border-size` a 2px —lo que parece natural— mueve
       el campo 1px por lado al recibir el foco, y hacerlo en `is-error` deja
       ese campo permanentemente 1px más alto que sus vecinos de la fila.

    2. EL `box-shadow` DEL CORE NO SE TOCA. Ni `--upaep-input-boxshadow` ni
       `--upaep-input-focus-boxshadow` ni sus equivalentes de select,
       checkbox y radio: el aro de foco por defecto del kit se queda como
       está. Lo único que hace esta capa es no descuadrar la geometría.

    3. LOS ICONOS DE VALIDACIÓN SE QUEDAN, Y SIEMPRE. El core pinta un icono
       de aviso / de acierto como `background-image` y lo repite en su regla
       de `:hover`/`:focus`. Apagarlo solo en la regla base —que es lo que
       hacía antes esta hoja— dejaba el icono apareciendo ÚNICAMENTE al pasar
       el ratón o al enfocar, que es lo peor de los dos mundos. Aquí no se
       apaga: se le hace sitio subiendo el relleno derecho a 42px, con lo que
       la cápsula conserva su alto de 42.

    ⚠ `.upaep__input` es una PRIMITIVA compartida: el runtime la genera
    dentro de Selectpicker (`upaep__input __selectpicker`), Autocomplete,
    Tokenfield, Datepicker y Numberpicker. Vestir la clase a secas les cambia
    relleno, radio y borde de foco y descuadra el control. Por eso la
    geometría solo se aplica cuando el input está dentro de sus contenedores
    de CAMPO —los que se escriben a mano en un formulario—.

    NOTA: un <textarea> se marca con `.upaep__input`, no con
    `.upaep__textarea`: esa segunda clase solo existe anidada en
    `.upaep__input-group` / `.__float-label` y no consume ninguna variable
    `--upaep-input-*`. */
[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>.upaep__input {
    --upaep-input-border-color: var(--ui-border);
    --upaep-input-border-bottom-color: var(--ui-border);
    --upaep-input-color: var(--ui-text);
    --upaep-input-bg: var(--ui-surface);
    --upaep-input-placeholder-color: var(--ui-text-muted);

    /* Hover: el sistema no cambia nada. Mismo grosor y mismo color. */
    --upaep-input-hover-bg: var(--ui-surface);
    --upaep-input-hover-border-color: var(--ui-border);
    --upaep-input-hover-border-bottom-color: var(--ui-border);
    --upaep-input-hover-color: var(--ui-text);

    /* Foco: el borde sigue en 1px. El aro es el del core, sin tocar. */
    --upaep-input-focus-bg: var(--ui-surface);
    --upaep-input-focus-color: var(--ui-text);
    --upaep-input-focus-border-color: var(--ui-border);

    --upaep-input-disabled-bg: var(--ui-surface-3);
    --upaep-input-disabled-opacity: 1;
    --upaep-input-readonly-bg: var(--ui-surface-3);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>.upaep__input {
    --upaep-input-border-size: 1px;
    --upaep-input-border-bottom-size: 1px;
    --upaep-input-border-radius: var(--upaep-ex-radius-control);
    --upaep-input-padding: 10px 22px;
    --upaep-input-height: var(--upaep-ex-control-height);
    --upaep-input-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-input-fw: var(--upaep-fw-regular);
    --upaep-input-placeholder-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-input-hover-border-size: 1px;
    --upaep-input-hover-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-input-hover-fw: var(--upaep-fw-regular);
    --upaep-input-focus-border-size: 1px;
}

/* El multilínea es el único campo que NO va en cápsula. */
[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>textarea.upaep__input {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>textarea.upaep__input {
    --upaep-input-border-radius: var(--upaep-ex-radius-container);
    --upaep-input-height: auto;
}

/* ⚠ El componente vuelve a declarar `border-bottom` DESPUÉS del `border`
   completo en :hover y :focus, y lee las variables BASE
   (`--upaep-input-border-bottom-*`), no unas de hover o de foco. Sin
   igualarlo estado por estado, los otros tres lados cambian y el inferior se
   queda con el color de reposo — el «borde de abajo de otro color». */
[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>.upaep__input:hover:not(:disabled):not([readonly]),
[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>.upaep__input:focus:not(:disabled):not([readonly]) {
    border-bottom-width: 1px;
    border-bottom-color: var(--ui-border);
}

/* Deshabilitado: el sistema lo comunica con fondo gris y texto tenue, no
   bajando la opacidad de todo el control. */
[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>.upaep__input:disabled {
    --upaep-input-border-color: var(--upaep-ex-gray-400);
    border-bottom-color: var(--upaep-ex-gray-400);
    color: var(--ui-text-muted);
}

/*? =====================================================================
    ESTADOS DE VALIDACIÓN — los MISMOS en los cinco controles
    Input, textarea, select, checkbox, radio y switch. Tres cosas se
    corrigen del core y ninguna toca su `box-shadow`:

      · el grosor del borde se queda en 1px, para que el control no crezca
        al pasar a error;
      · el core pone `--upaep-…-hover-border-color: var(--ui-danger-hover)`,
        que en esta marca es OTRO rojo (#E63347 frente a #FF4D5F): al pasar
        el ratón los lados cambiaban de tono y el inferior se quedaba en el
        original. Se igualan al color de estado;
      · el relleno derecho sube a 42px para que el icono de validación
        —que el core pinta siempre y aquí se conserva— tenga sitio sin
        romper la cápsula.

    ⚠ Dos huecos del core que esta capa rellena:
      · `.upaep__checkbox` solo reconoce `is-invalid` / `is-valid`, no
        `is-error` / `is-success` como el input y el select;
      · `.upaep__radio` NO tiene estado de validación en el core. Se le da
        aquí, con las mismas cuatro variables que el checkbox.
    ===================================================================== */

[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>.upaep__input:is(.is-error, .is-invalid) {
    --upaep-input-border-color: var(--ui-danger);
    --upaep-input-border-bottom-color: var(--ui-danger);
    --upaep-input-hover-border-color: var(--ui-danger);
    --upaep-input-hover-border-bottom-color: var(--ui-danger);
    --upaep-input-focus-border-color: var(--ui-danger);
    border-bottom-color: var(--ui-danger);

    /* Sitio para el icono, sin perder el alto de la cápsula. El core lo
       resuelve con `.35rem 1.8rem .35rem 1rem`, que rompe la métrica. */
    &:not([type="color"]):not([type="range"]):not(textarea):not(.__icon) {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *) & {
        --upaep-input-padding: 10px 42px 10px 22px;
    }

    &~.upaep__label,
    &~span .upaep__label {
        --upaep-label-color: var(--ui-danger);
    }
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>.upaep__input:is(.is-error, .is-invalid) {
    --upaep-input-border-size: 1px;
    --upaep-input-border-bottom-size: 1px;
    --upaep-input-hover-border-size: 1px;
    --upaep-input-focus-border-size: 1px;
}

[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>.upaep__input:is(.is-success, .is-valid) {
    --upaep-input-border-color: var(--ui-success);
    --upaep-input-border-bottom-color: var(--ui-success);
    --upaep-input-hover-border-color: var(--ui-success);
    --upaep-input-hover-border-bottom-color: var(--ui-success);
    --upaep-input-focus-border-color: var(--ui-success);
    border-bottom-color: var(--ui-success);

    &:not([type="color"]):not([type="range"]):not(textarea):not(.__icon) {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *) & {
        --upaep-input-padding: 10px 42px 10px 22px;
    }
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>.upaep__input:is(.is-success, .is-valid) {
    --upaep-input-border-size: 1px;
    --upaep-input-border-bottom-size: 1px;
    --upaep-input-hover-border-size: 1px;
    --upaep-input-focus-border-size: 1px;
}

/* Y los dos estados reafirman el borde inferior, por el mismo motivo que
   arriba: el core lo redeclara después del borde completo. */
[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>.upaep__input:is(.is-error, .is-invalid):is(:hover, :focus):not(:disabled):not([readonly]) {
    border-bottom-width: 1px;
    border-bottom-color: var(--ui-danger);
}

[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>.upaep__input:is(.is-success, .is-valid):is(:hover, :focus):not(:disabled):not([readonly]) {
    border-bottom-width: 1px;
    border-bottom-color: var(--ui-success);
}

/* El textarea no lleva icono (el core lo excluye), así que conserva su
   relleno parejo. */
[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>textarea.upaep__input:is(.is-error, .is-invalid, .is-success, .is-valid) {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] :is(.upaep__input-container, .upaep__input-wrapper)>textarea.upaep__input:is(.is-error, .is-invalid, .is-success, .is-valid) {
    --upaep-input-padding: 10px 22px;
}

/*? Select: el core ya trae su icono de validación y su aro. Solo se iguala
    el hover y se fija el grosor. */
[data-brand="upaep"] .upaep__select:is(.is-error, .is-invalid) {
    --upaep-select-border-color: var(--ui-danger);
    --upaep-select-focus-border-color: var(--ui-danger);
    /* ⚠ El select validado lleva DOS fondos: su chevron a 0.75rem del borde y
       el icono de validación a 2.25rem. Con el relleno de 22px de la cápsula
       el icono se monta encima del chevron, así que hay que abrirle sitio. */
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__select:is(.is-error, .is-invalid) {
    --upaep-select-border-size: 1px;
    --upaep-select-focus-border-size: 1px;
    --upaep-select-padding: 10px 52px 10px 22px;
}

[data-brand="upaep"] .upaep__select:is(.is-error, .is-invalid):hover {
    border-color: var(--ui-danger);
}

[data-brand="upaep"] .upaep__select:is(.is-success, .is-valid) {
    --upaep-select-border-color: var(--ui-success);
    --upaep-select-focus-border-color: var(--ui-success);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__select:is(.is-success, .is-valid) {
    --upaep-select-border-size: 1px;
    --upaep-select-focus-border-size: 1px;
    --upaep-select-padding: 10px 52px 10px 22px;
}

[data-brand="upaep"] .upaep__select:is(.is-success, .is-valid):hover {
    border-color: var(--ui-success);
}

/*? Checkbox y radio. El core solo cubre el checkbox y solo con
    `is-invalid`/`is-valid`; aquí se aceptan los cuatro nombres y se añade el
    radio, que no lo tenía. El grosor se queda en 1px en los tres estados,
    como en el resto de la capa. */
[data-brand="upaep"] :is(.upaep__checkbox, .upaep__radio):is(.is-error, .is-invalid) {
    --upaep-checkbox-border-color: var(--ui-danger);
    --upaep-checkbox-hover-border-color: var(--ui-danger);
    --upaep-checkbox-focus-border-color: var(--ui-danger);
    --upaep-checkbox-active-border-color: var(--ui-danger);
    --upaep-checkbox-checked-bg: var(--ui-danger);
    --upaep-checkbox-checked-color: var(--ui-on-danger);
    --upaep-checkbox-focus-bg: var(--ui-danger);
    --upaep-checkbox-active-bg: var(--ui-danger);

    --upaep-radio-border-color: var(--ui-danger);
    --upaep-radio-hover-border-color: var(--ui-danger);
    --upaep-radio-focus-border-color: var(--ui-danger);
    --upaep-radio-active-border-color: var(--ui-danger);
    --upaep-radio-checked-color: var(--ui-danger);

    &~.upaep__label,
    &~span .upaep__label {
        --upaep-label-color: var(--ui-danger);
    }
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] :is(.upaep__checkbox, .upaep__radio):is(.is-error, .is-invalid) {
    --upaep-checkbox-border-size: 1px;
    --upaep-checkbox-hover-border-size: 1px;
    --upaep-checkbox-focus-border-size: 1px;
    --upaep-checkbox-active-border-size: 1px;
    --upaep-radio-border-size: 1px;
    --upaep-radio-hover-border-size: 1px;
    --upaep-radio-focus-border-size: 2px;
    --upaep-radio-active-border-size: 2px;
}

[data-brand="upaep"] :is(.upaep__checkbox, .upaep__radio):is(.is-success, .is-valid) {
    --upaep-checkbox-border-color: var(--ui-success);
    --upaep-checkbox-hover-border-color: var(--ui-success);
    --upaep-checkbox-focus-border-color: var(--ui-success);
    --upaep-checkbox-checked-bg: var(--ui-success);
    --upaep-checkbox-checked-color: var(--ui-on-success);
    --upaep-checkbox-focus-bg: var(--ui-success);
    --upaep-checkbox-active-bg: var(--ui-success);

    --upaep-radio-border-color: var(--ui-success);
    --upaep-radio-hover-border-color: var(--ui-success);
    --upaep-radio-focus-border-color: var(--ui-success);
    --upaep-radio-checked-color: var(--ui-success);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] :is(.upaep__checkbox, .upaep__radio):is(.is-success, .is-valid) {
    --upaep-checkbox-border-size: 1px;
    --upaep-checkbox-hover-border-size: 1px;
    --upaep-checkbox-focus-border-size: 1px;
}

/* El switch en error: el carril mantiene su relleno (nunca va blanco) y lo
   que cambia es el color de apagado. */
[data-brand="upaep"] .upaep__checkbox.__switch:is(.is-error, .is-invalid):not(:checked),
[data-brand="upaep"] .upaep__checkbox.__switch:is(.is-error, .is-invalid):not(:checked):hover,
[data-brand="upaep"] .upaep__checkbox.__switch:is(.is-error, .is-invalid):not(:checked):focus {
    background: var(--ui-danger-subtle);
}

[data-brand="upaep"] .upaep__checkbox.__switch:is(.is-error, .is-invalid) {
    --upaep-checkbox-checked-bg: var(--ui-danger);
}

[data-brand="upaep"] .upaep__select {
    --upaep-select-border-color: var(--ui-border);
    --upaep-select-color: var(--ui-text);
    --upaep-select-bg: var(--ui-surface);
    --upaep-select-focus-bg: var(--ui-surface);
    --upaep-select-focus-color: var(--ui-text);
    /* Mismo criterio que el input: el grosor NO cambia (1px siempre), para
       que el select no salte al enfocarse, y el `box-shadow` del core se
       queda como está. */
    --upaep-select-focus-border-color: var(--ui-border);
    --upaep-select-bg-disabled: var(--ui-surface-3);
    --upaep-select-disabled-opacity: 1;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__select {
    --upaep-select-border-size: 1px;
    --upaep-select-border-radius: var(--upaep-ex-radius-control);
    --upaep-select-padding: 10px 22px;
    --upaep-select-height: var(--upaep-ex-control-height);
    --upaep-select-margin: 0;
    --upaep-select-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-select-fw: var(--upaep-fw-regular);
    --upaep-select-focus-border-size: 1px;
}

/* Mensaje bajo el campo: 12px regular, no el bold del core. */
[data-brand="upaep"] .upaep__feedback {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__feedback {
    --upaep-feedback-fz: var(--upaep-ex-fs-p5-small);
    --upaep-feedback-fw: var(--upaep-fw-regular);
    --upaep-feedback-margin: 6px 0 0 22px;
}

[data-brand="upaep"] .upaep__feedback:is(.__invalid, .__error) {
    --upaep-feedback-color: var(--ui-danger);
}

/*? El COLOR de la etiqueta sí va en la clase base, y a propósito: el core lo
    cablea a `var(--upaep-color-dark-grey)` (#52565A), un primitivo que no
    sigue al tema. Sobre la superficie oscura del sistema (#2E2E2E) eso deja
    la etiqueta prácticamente invisible — y afecta a TODA etiqueta que no
    preceda a un campo (las de casilla, radio y switch van detrás del
    control, así que la regla de abajo no las alcanza).

    Vestir el color de la primitiva es seguro; lo que no se puede tocar en la
    base es la GEOMETRÍA (el `display: block` rompe las filas que el runtime
    construye en Payment y Selectpicker). */
[data-brand="upaep"] .upaep__label {
    --upaep-label-color: var(--ui-text-on-surface);
}

/* Etiqueta de campo: 14px del neutro de trabajo, bloque con respiro.
   ⚠ `.upaep__label` es otra primitiva compartida —el runtime la genera en
   Payment (`upaep__label upaep__methods-item`, `upaep__balances-item`) y en
   las opciones del Selectpicker—, y ahí forzar `display: block` rompe la
   fila. Por eso solo se viste la etiqueta que PRECEDE a un campo. */
[data-brand="upaep"] .upaep__label:has(+ :is(.upaep__input-container, .upaep__input-wrapper, .upaep__input, .upaep__select, .upaep__textarea)) {
    --upaep-label-color: var(--ui-text-on-surface);
    display: block;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__label:has(+ :is(.upaep__input-container, .upaep__input-wrapper, .upaep__input, .upaep__select, .upaep__textarea)) {
    --upaep-label-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-label-fw: var(--upaep-fw-regular);
    margin-bottom: 8px;
}

/*? ------ Checkbox, radio y switch ------
    Caja de 20px con esquina de 4px, círculo de 20px y carril de 44×24. El
    sistema los marca en ROJO institucional (el core los deja en gris
    neutro), salvo el switch: su carril encendido es VERDE, porque en Express
    el interruptor comunica "en marcha", no "seleccionado".

    Dos trampas del componente que hay que desactivar:
      · en :hover y :focus vuelve a declarar el `border` COMPLETO con su
        propio grosor (2px por defecto): si solo se cambia el color, la caja
        engorda al pasar el ratón → hay que fijar los tres grosores;
      · `--upaep-checkbox-focus-bg` es BLANCO por defecto y la regla
        `:focus:checked` lo repinta: al enfocar, una casilla marcada se
        vaciaba. El fondo de foco tiene que ser el mismo rojo. */
[data-brand="upaep"] .upaep__checkbox {
    --upaep-checkbox-border-color: var(--ui-border);
    --upaep-checkbox-bg: var(--ui-surface);

    --upaep-checkbox-hover-bg: var(--ui-surface);
    --upaep-checkbox-hover-border-color: var(--ui-text);

    --upaep-checkbox-checked-bg: var(--ui-accent);
    --upaep-checkbox-checked-color: var(--upaep-ex-white);

    --upaep-checkbox-active-bg: var(--ui-accent);
    --upaep-checkbox-active-border-color: var(--ui-accent);

    --upaep-checkbox-focus-bg: var(--ui-accent);
    --upaep-checkbox-focus-border-color: var(--ui-accent);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__checkbox {
    --upaep-checkbox-border-size: 1px;
    --upaep-checkbox-border-radius: var(--upaep-ex-radius-xs);
    --upaep-checkbox-hover-border-size: 1px;
    --upaep-checkbox-active-border-size: 1px;
    --upaep-checkbox-focus-border-size: 1px;
}

[data-brand="upaep"] .upaep__radio {
    --upaep-radio-border-color: var(--ui-border);
    --upaep-radio-bg: var(--ui-surface);

    --upaep-radio-hover-bg: var(--ui-surface);
    --upaep-radio-hover-border-color: var(--ui-text);

    --upaep-radio-checked-color: var(--ui-accent);

    --upaep-radio-active-bg: var(--ui-surface);
    --upaep-radio-active-border-color: var(--ui-accent);

    --upaep-radio-focus-bg: var(--ui-surface);
    --upaep-radio-focus-border-color: var(--ui-accent);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__radio {
    --upaep-radio-border-size: 1px;
    --upaep-radio-hover-border-size: 1px;
    --upaep-radio-active-border-size: 2px;
    --upaep-radio-focus-border-size: 2px;
}

/* Sin marcar, la casilla enfocada no debe rellenarse de rojo.
   El switch se excluye: su carril nunca es blanco (ver abajo). */
[data-brand="upaep"] .upaep__checkbox:not(.__switch):focus:not(:checked) {
    background: var(--ui-surface);
    border-color: var(--ui-accent);
}

/*? Switch — el carril SIEMPRE va relleno; lo que se mueve es la perilla
    blanca. Apagado: gris 400. Encendido: VERDE de éxito.

    ⚠ La regla genérica de arriba pone `--upaep-checkbox-bg: var(--ui-surface)`
    (blanco) y tiene la MISMA especificidad que `.upaep__checkbox.__switch` del
    core, pero se carga después → le ganaba. Resultado: carril blanco con
    perilla blanca, o sea invisible cuando estaba apagado. Por eso hay que
    volver a declarar los cuatro fondos, no solo el de marcado. */
[data-brand="upaep"] .upaep__checkbox.__switch {
    --upaep-checkbox-checked-color: var(--upaep-ex-white);
    --upaep-checkbox-bg: var(--upaep-ex-gray-400);
    --upaep-checkbox-hover-bg: var(--upaep-ex-gray-400);
    --upaep-checkbox-focus-bg: var(--upaep-ex-gray-400);
    --upaep-checkbox-active-bg: var(--upaep-ex-gray-400);
    --upaep-checkbox-checked-bg: var(--ui-success);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__checkbox.__switch {
    --upaep-checkbox-border-radius: var(--upaep-ex-radius-full);
    --upaep-checkbox-border-size: 0;
}

[data-brand="upaep"] .upaep__checkbox.__switch:checked,
[data-brand="upaep"] .upaep__checkbox.__switch:checked:hover,
[data-brand="upaep"] .upaep__checkbox.__switch:checked:focus {
    background: var(--ui-success);
}

[data-brand="upaep"] .upaep__checkbox.__switch:not(:checked),
[data-brand="upaep"] .upaep__checkbox.__switch:not(:checked):hover,
[data-brand="upaep"] .upaep__checkbox.__switch:not(:checked):focus {
    background: var(--upaep-ex-gray-400);
}

/* ⚠ Un grupo de casillas en `display: flex` sin `align-items` estira los
   hijos y la etiqueta queda más alta que el control. */
[data-brand="upaep"] .__upaep-ex-check-row {
    display: flex;
    align-items: center;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-check-row {
    gap: 12px;
    --upaep-checkbox-margin: 0;
    --upaep-radio-margin: 0;
}

/* La etiqueta de una casilla es TEXTO, no rótulo de campo: va al color de
   texto pleno y a 16px, como en el componente Checkbox del sistema. */
[data-brand="upaep"] .__upaep-ex-check-row .upaep__label {
    --upaep-label-color: var(--ui-text);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-check-row .upaep__label {
    --upaep-label-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-label-fw: var(--upaep-fw-regular);
    margin: 0;
}

/*? ------ Tag ------
    El chip removible del sistema: cápsula de 4px 12px, 12px semibold sobre
    fondo tenue. El uikit lo trae con marco de 2px y alto mínimo de 2.5rem;
    Express lo quiere sin marco y compacto. */
[data-brand="upaep"] .upaep__tag {
    --upaep-tag-border-color: transparent;
    --upaep-tag-bg: var(--ui-surface-3);
    --upaep-tag-text-color: var(--ui-text-on-surface);
    --upaep-tag-close-color: currentColor;
    /* El aro de hover se queda tal como lo trae el kit: el sistema no define
       ninguno para el tag, así que no hay nada que portar —y el aro sale de
       `--ui-control-ring`, que esta hoja no toca. */

}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__tag {
    --upaep-tag-minwidth: 0;
    --upaep-tag-minheight: 28px;
    --upaep-tag-border-size: 0;
    --upaep-tag-border-radius: var(--upaep-ex-radius-control);
    --upaep-tag-padding: 4px 12px;
    --upaep-tag-margin: 0;
    --upaep-tag-text-fz: var(--upaep-ex-fs-p5-small);
    --upaep-tag-text-fw: var(--upaep-fw-semibold);
    --upaep-tag-text-margin: 0;
    --upaep-tag-close-fz: var(--upaep-ex-fs-p5-small);
    --upaep-tag-close-margin: 0 0 0 8px;
    gap: 0;
}

/* Los seis tonos de etiqueta del sistema, como modificadores del tag.
   Ninguno comunica estado: solo categorizan. */
[data-brand="upaep"] .upaep__tag.__upaep-ex-1 {
    --upaep-tag-bg: var(--upaep-ex-label-1);
    --upaep-tag-text-color: var(--upaep-ex-gray-900);
}

[data-brand="upaep"] .upaep__tag.__upaep-ex-2 {
    --upaep-tag-bg: var(--upaep-ex-label-2);
    --upaep-tag-text-color: var(--upaep-ex-gray-900);
}

[data-brand="upaep"] .upaep__tag.__upaep-ex-3 {
    --upaep-tag-bg: var(--upaep-ex-label-3);
    --upaep-tag-text-color: var(--upaep-ex-gray-900);
}

[data-brand="upaep"] .upaep__tag.__upaep-ex-4 {
    --upaep-tag-bg: var(--upaep-ex-label-4);
    --upaep-tag-text-color: var(--upaep-ex-gray-900);
}

[data-brand="upaep"] .upaep__tag.__upaep-ex-5 {
    --upaep-tag-bg: var(--upaep-ex-label-5);
    --upaep-tag-text-color: var(--upaep-ex-gray-900);
}

[data-brand="upaep"] .upaep__tag.__upaep-ex-6 {
    --upaep-tag-bg: var(--upaep-ex-label-6);
    --upaep-tag-text-color: var(--upaep-ex-gray-900);
}

/* Tonos de estatus de pase: fondo de etiqueta + texto endurecido. */
[data-brand="upaep"] .upaep__tag.__upaep-ex-approved {
    --upaep-tag-bg: var(--ui-success-subtle);
    --upaep-tag-text-color: var(--ui-on-success-subtle);
}

[data-brand="upaep"] .upaep__tag.__upaep-ex-review {
    --upaep-tag-bg: var(--ui-warning-subtle);
    --upaep-tag-text-color: var(--ui-on-warning-subtle);
}

[data-brand="upaep"] .upaep__tag.__upaep-ex-rejected {
    --upaep-tag-bg: var(--ui-danger-subtle);
    --upaep-tag-text-color: var(--ui-on-danger-subtle);
}

[data-brand="upaep"] .upaep__tag-group {
    --upaep-taggroup-border-color: var(--ui-border-subtle);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__tag-group {
    gap: 8px;
}

/*? ------ Badge ------
    Contador: cápsula de 20px, rojo, 12px bold. Se ancla a iconos, tabs y
    filtros. El core lo pinta navy y con esquina de 5px. */
[data-brand="upaep"] .upaep__badge {
    --upaep-badge-bg: var(--ui-counter);
    --upaep-badge-color: var(--ui-on-counter);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__badge {
    --upaep-badge-border-radius: var(--upaep-ex-radius-full);
    --upaep-badge-padding: 0 6px;
    --upaep-badge-height: 20px;
    --upaep-badge-fz: var(--upaep-ex-fs-p5-small);
    --upaep-badge-fw: var(--upaep-fw-bold);
    min-width: 20px;
}

/*? La pastilla de estatus del sistema. Sus diez tonos `__status` ya son casi
    exactamente los seis colores de etiqueta de Express: `__blue` = etiqueta
    1, `__yellow` = 2, `__green` = 3, `__orange` = 4, `__pink` = 5 — todos
    idénticos al hex del sistema. Solo `__purple` difiere (el core trae
    #C2CBFF y el sistema #DFE3FF), así que se remapea el primitivo. */
[data-brand="upaep"] .upaep__badge.__status {
    --bg-status-purple: var(--upaep-ex-label-6);
    --bg-status-blue: var(--upaep-ex-label-1);
    --bg-status-yellow: var(--upaep-ex-label-2);
    --bg-status-green: var(--upaep-ex-label-3);
    --bg-status-orange: var(--upaep-ex-label-4);
    --bg-status-pink: var(--upaep-ex-label-5);
    --bg-status-grey: var(--upaep-ex-gray-100);
    --color-status-green: var(--upaep-ex-gray-900);
    --color-status-yellow: var(--upaep-ex-gray-900);
    --color-status-blue: var(--upaep-ex-gray-900);
    --color-status-orange: var(--upaep-ex-gray-900);
    --color-status-pink: var(--upaep-ex-gray-900);
    --color-status-purple: var(--upaep-ex-gray-900);
    --color-status-grey: var(--upaep-ex-gray-900);

    /* El core sube el relleno a .75rem 1rem cuando no hay tamaño secundario;
       la pastilla del sistema es más compacta. */
    &:not(:is(.__secondary, .__tertiary)) {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *) & {
        --upaep-badge-padding: 4px 12px;
    }
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__badge.__status {
    --upaep-badge-border-radius: var(--upaep-ex-radius-control);
    --upaep-badge-fz: var(--upaep-ex-fs-p5-small);
    --upaep-badge-fw: var(--upaep-fw-semibold);
    --upaep-badge-height: auto;
    min-width: 0;
}

/*? ------ Alert ------
    Aviso en línea: esquina de 10px, fondo tenue, barra izquierda de 4px del
    color del tipo y texto endurecido. El uikit lo pinta con relleno pleno
    por defecto y con `__light` en tenue; Express solo tiene la tenue, así
    que la barra se añade a las dos y el modificador `__light` sigue
    funcionando igual. */
[data-brand="upaep"] .upaep__alert {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__alert {
    --upaep-alert-border-radius: var(--upaep-ex-radius-container);
    --upaep-alert-border-size: 0;
    --upaep-alert-padding: 12px 16px;
    --upaep-alert-margin: 0;
    --upaep-alert-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-alert-fw: var(--upaep-fw-regular);
    line-height: 1.5;
}

/* La franja izquierda, tipo por tipo. Con `currentColor` salía del color de
   TEXTO endurecido de cada variante —un tono más apagado—; el sistema la
   quiere del color de estado pleno. */
[data-brand="upaep"] .upaep__alert.__success {
    border-left: 4px solid var(--ui-success);
}

[data-brand="upaep"] .upaep__alert.__error {
    border-left: 4px solid var(--ui-danger);
}

[data-brand="upaep"] .upaep__alert.__warning {
    border-left: 4px solid var(--ui-warning);
}

[data-brand="upaep"] .upaep__alert:is(.__info, .__blue) {
    border-left: 4px solid var(--ui-info);
}

[data-brand="upaep"] .upaep__alert.__primary {
    border-left: 4px solid var(--ui-primary);
}

/*? ------ Notification (toast) ------
    Confirmación efímera: superficie blanca, sombra principal, barra
    izquierda del color del tipo y título de 16 bold. */
[data-brand="upaep"] .upaep__notification {
    --upaep-notification-bg: var(--ui-surface);
    --upaep-notification-boxshadow: var(--upaep-ex-shadow-1);
    --upaep-notification-content-text-color: var(--ui-text-on-surface);
    --upaep-notification-header-title-color: var(--ui-text);
    --upaep-notification-header-bg: transparent;
    --upaep-notification-close-color: var(--ui-text-muted);
    /* ⚠ NO tocar `--upaep-notification-content-icon-ring`: pese al nombre no
       es un radio, es el ANCHO Y ALTO del anillo del icono
       (`width: var(...)`). Puesto a `9999px` genera un pseudo-elemento de
       9999px y dispara 3900px de scroll horizontal en la página. El core ya
       le da 1.75rem en cada variante de tipo, que es justo el círculo de
       28px que pide Express. */
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__notification {
    --upaep-notification-border-size: 0;
    --upaep-notification-border-radius: var(--upaep-ex-radius-container);
    --upaep-notification-maxwidth: 360px;
    --upaep-notification-padding: 0;
    --upaep-notification-content-padding: 14px 16px;
    --upaep-notification-content-text-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-notification-header-title-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-notification-header-title-fw: var(--upaep-fw-bold);
    --upaep-notification-header-border-bottom-size: 0;
}

/*? La franja izquierda y el icono, tipo por tipo.

    ⚠ NO se puede leer `--upaep-notification-content-icon-color` para la
    franja: las variantes del core pintan la notificación con RELLENO PLENO
    del color de estado y ponen el icono en BLANCO. Esta hoja aplana el fondo
    a la superficie (así lo quiere Express: blanco + barra de 4px), con lo que
    ese blanco heredado dejaba la franja invisible — la franja verde del toast
    de éxito no se veía. Cada tipo declara su color explícitamente. */
[data-brand="upaep"] .upaep__notification.__success {
    --upaep-notification-content-icon-color: var(--ui-success);
    border-left: 4px solid var(--ui-success);
}

[data-brand="upaep"] .upaep__notification.__error {
    --upaep-notification-content-icon-color: var(--ui-danger);
    border-left: 4px solid var(--ui-danger);
}

[data-brand="upaep"] .upaep__notification.__warning {
    --upaep-notification-content-icon-color: var(--ui-warning);
    border-left: 4px solid var(--ui-warning);
}

[data-brand="upaep"] .upaep__notification:is(.__info, .__question, .__blue) {
    --upaep-notification-content-icon-color: var(--ui-info);
    border-left: 4px solid var(--ui-info);
}

/*? ------ Table ------
    Encabezado azul institucional con texto blanco de 14 bold, filas
    alternas sobre gris 100, hairline gris 300 y números a la derecha. La
    envolvente lleva la esquina de 10px y la sombra de tarjeta. */
[data-brand="upaep"] .upaep__table {
    --upaep-table-bg: var(--ui-surface);
    /* ⚠ `--upaep-table-padding` es el relleno de la ETIQUETA <table>, no de las
       celdas. El de las celdas sale de `--upaep-table-caption-padding` —sí,
       con ese nombre— porque el core lo aplica en
       `&>:not(caption)>*>*`. Poner 12px 16px en el primero solo mete un
       margen interior a la tabla entera. */
    --upaep-table-thead-bg: var(--upaep-ex-navy);
    --upaep-table-thead-color: var(--upaep-ex-white);
    --upaep-table-tbody-color: var(--ui-text-on-surface);
    --upaep-table-tbody-border-bottom-color: var(--ui-border-subtle);
    --upaep-table-striped-bg: var(--ui-surface-3);
    --upaep-table-striped-color: var(--ui-text-on-surface);
    --upaep-table-hover-bg: var(--ui-surface-hover);
    --upaep-table-hover-color: var(--ui-text);
    --upaep-table-striped-hover-bg: var(--ui-surface-hover);
    --upaep-table-active-bg: var(--ui-info-subtle);
    --upaep-table-active-color: var(--ui-on-info-subtle);
    --upaep-table-border-color: var(--ui-border-subtle);
    /* El original alinea el texto a la izquierda; los números, a la derecha
       con un `text-align` por columna. */
    --upaep-table-tbody-align: left;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__table {
    --upaep-table-margin: 0;
    --upaep-table-padding: 0;
    --upaep-table-caption-padding: 12px 16px;
    --upaep-table-thead-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-table-thead-fw: var(--upaep-fw-bold);
    --upaep-table-thead-border-bottom-size: 0;
    --upaep-table-tbody-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-table-tbody-border-bottom-size: 1px;
}

/* ⚠ El core cablea `text-align: center` en TODAS las celdas
   (`&>:not(caption)>*>*`), sin variable que lo gobierne: hay que pisarlo.
   Un `style="text-align:right"` en la columna de importes sigue ganando,
   porque es inline. */
[data-brand="upaep"] .upaep__table>:not(caption)>*>* {
    text-align: left;
}

/* La cabecera lleva un punto más de aire que las celdas, como el original. */
[data-brand="upaep"] .upaep__table thead th {
    white-space: nowrap;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__table thead th {
    padding: 14px 16px;
}

[data-brand="upaep"] .upaep__table-content {
    --upaep-table-content-bg: var(--ui-surface);
    --upaep-table-content-boxshadow: var(--upaep-ex-shadow-card);
    --upaep-table-content-thumb-color: var(--ui-border-subtle);
    --upaep-table-content-track-color: var(--ui-surface-3);
    overflow: hidden;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__table-content {
    --upaep-table-content-border-radius: var(--upaep-ex-radius-container);
    --upaep-table-content-border-size: 0;
    --upaep-table-content-margin: 0;
    --upaep-table-content-padding: 0;
}

/*? ------ Modal ------
    Caja de 554px con esquina de 10px, cabecera de 76 sin borde y el cierre
    en un círculo NEGRO de 28. Título navy 24 semibold, cuerpo 20 regular
    gris 800, acciones centradas.

    El sistema es explícito con la acción principal del modal: es AZUL, no
    roja. El rojo se reserva para lo destructivo. */
[data-brand="upaep"] .upaep__modal {
    --upaep-modal-content-bg: var(--ui-surface);
    --upaep-modal-backdrop-bg: rgba(0, 0, 0, .5);
    --upaep-modal-header-bg: transparent;
    --upaep-modal-title-color: var(--upaep-ex-navy);
    --upaep-modal-body-bg: var(--ui-surface);
    --upaep-modal-body-color: var(--ui-text-on-surface);
    --upaep-modal-footer-bg: transparent;
    --upaep-modal-close-color: var(--upaep-ex-white);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__modal {
    --upaep-modal-content-border-radius: var(--upaep-ex-radius-container);
    --upaep-modal-content-border-size: 0;
    --upaep-modal-header-border-bottom-size: 0;
    --upaep-modal-header-padding: 18px 18px 0;
    --upaep-modal-title-fz: var(--upaep-ex-fs-h3-condensed);
    --upaep-modal-title-fw: var(--upaep-fw-semibold);
    --upaep-modal-title-lineheight: 1.15;
    --upaep-modal-body-padding: 24px 40px 32px;
    --upaep-modal-footer-border-top-size: 0;
    --upaep-modal-footer-padding: 0 40px 32px;
    --upaep-modal-close-fz: var(--upaep-ex-fs-p5-small);
}

/* El cierre del sistema es un círculo negro con la cruz blanca; el del kit
   es un glifo suelto. El componente no expone fondo para el cierre. */
[data-brand="upaep"] .upaep__modal .upaep__modal-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--upaep-ex-black);
    transition: background var(--upaep-ex-duration-base) var(--upaep-ex-ease);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__modal .upaep__modal-close {
    width: 28px;
    height: 28px;
    border-radius: var(--upaep-ex-radius-full);
}

[data-brand="upaep"] .upaep__modal .upaep__modal-close:hover {
    background: var(--upaep-ex-gray-850);
}

[data-brand="upaep"] .upaep__modal .upaep__modal-title {
    font-family: var(--ui-font-base);
}

/*? ------ Offcanvas ------
    Panel lateral para tareas largas que no caben en un modal. Cabecera sin
    relleno de color, título de 20 bold y hairline gris 100. */
[data-brand="upaep"] .upaep__offcanvas {
    --upaep-offcanvas-bg: var(--ui-surface);
    --upaep-offcanvas-boxshadow: var(--upaep-ex-shadow-1);
    --upaep-offcanvas-header-bg: transparent;
    --upaep-offcanvas-header-border-bottom-color: var(--ui-surface-3);
    --upaep-offcanvas-title-color: var(--ui-text);
    --upaep-offcanvas-content-bg: var(--ui-surface);
    --upaep-offcanvas-content-color: var(--ui-text);
    --upaep-offcanvas-footer-bg: transparent;
    --upaep-offcanvas-footer-border-top-color: var(--ui-border-subtle);
    --upaep-offcanvas-close-color: var(--ui-link);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__offcanvas {
    --upaep-offcanvas-header-padding: 24px 32px 12px;
    --upaep-offcanvas-header-border-bottom-size: 1px;
    --upaep-offcanvas-title-fz: var(--upaep-ex-fs-p1-web-large);
    --upaep-offcanvas-title-fw: var(--upaep-fw-bold);
    --upaep-offcanvas-content-padding: 24px 32px;
    --upaep-offcanvas-content-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-offcanvas-footer-padding: 16px 32px 24px;
}

/*? ------ Breadcrumb ------
    Ruta de migas de 14px: niveles intermedios en azul de enlace, el último
    en texto pleno semibold, y el divisor una barra gris.
    ⚠ El divisor por defecto del componente es un glifo de FontAwesome
    (`"\f105"`): si la fuente no está, no se ve nada. Aquí se cambia por un
    carácter Unicode y se declara la familia. */
[data-brand="upaep"] .upaep__breadcrumb {
    --upaep-breadcrumb-bg: transparent;
    --upaep-breadcrumb-item-color: var(--ui-link);
    --upaep-breadcrumb-item-active-color: var(--ui-text);
    --upaep-breadcrumb-divider: "/";
    --upaep-breadcrumb-divider-ff: var(--ui-font-base);
    --upaep-breadcrumb-divider-color: var(--upaep-ex-gray-400);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__breadcrumb {
    --upaep-breadcrumb-border-size: 0;
    --upaep-breadcrumb-padding: 0;
    --upaep-breadcrumb-margin: 0;
    --upaep-breadcrumb-item-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-breadcrumb-item-fw: var(--upaep-fw-regular);
    --upaep-breadcrumb-item-active-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-breadcrumb-item-active-fw: var(--upaep-fw-semibold);
    --upaep-breadcrumb-divider-fz: var(--upaep-ex-fs-p4-medium);
}

/*? ------ Tracker ------
    El progreso por pasos del sistema (su *ProgressSteps*) se reviste sobre
    **`.upaep__tracker`**. `.upaep__progresstracker` queda **deprecado** y a
    propósito sin vestir: si aparece en una página vieja se verá con los
    valores del core, no con los de la marca.

    Regla del sistema, y es lo que distingue este revestido del core: el paso
    **en curso es ROJO** y los **completados VERDES**. El core los pinta
    todos del primario. Marca de 28px, riel de 2px, pendiente en blanco con
    aro gris. */
[data-brand="upaep"] .upaep__tracker {
    --upaep-tracker-bg: transparent;

    --upaep-tracker-item-mark-bg: var(--ui-surface);
    --upaep-tracker-item-mark-border-color: var(--upaep-ex-gray-400);
    --upaep-tracker-item-icon-color: var(--ui-text-muted);
    --upaep-tracker-item-dot-bg: var(--upaep-ex-gray-400);

    --upaep-tracker-item-line-bg: var(--ui-border-subtle);

    --upaep-tracker-item-title-color: var(--ui-text-muted);
    --upaep-tracker-item-text-color: var(--ui-text-muted);
    --upaep-tracker-item-opacity: 1;

    /* En curso: rojo. */
    --upaep-tracker-item-progress-mark-bg: var(--ui-accent);
    --upaep-tracker-item-progress-mark-border-color: var(--ui-accent);
    --upaep-tracker-item-progress-mark-color: var(--ui-on-accent);
    --upaep-tracker-item-progress-icon-color: var(--ui-on-accent);
    --upaep-tracker-item-progress-dot-bg: var(--ui-accent);
    --upaep-tracker-item-progress-title-color: var(--ui-text);
    --upaep-tracker-item-progress-text-color: var(--ui-text-on-surface);
    /* El tramo POSTERIOR al paso en curso todavía no está hecho. */
    --upaep-tracker-item-progress-line-bg: var(--ui-border-subtle);

    /* Completados: verde. */
    --upaep-tracker-item-complete-mark-bg: var(--ui-success);
    --upaep-tracker-item-complete-mark-border-color: var(--ui-success);
    --upaep-tracker-item-complete-mark-color: var(--ui-on-success);
    --upaep-tracker-item-complete-icon-color: var(--ui-on-success);
    --upaep-tracker-item-complete-dot-bg: var(--ui-success);
    --upaep-tracker-item-complete-line-bg: var(--ui-success);
    --upaep-tracker-item-complete-title-color: var(--ui-text);
    --upaep-tracker-item-complete-text-color: var(--ui-text-on-surface);

    /* Error y rechazo: los dos rojos que el sistema sí distingue —el de
       revisión (amarillo) y el de rechazo (rojo de estatus)—. */
    --upaep-tracker-item-error-mark-bg: var(--ui-warning);
    --upaep-tracker-item-error-mark-border-color: var(--ui-warning);
    --upaep-tracker-item-error-mark-color: var(--ui-on-warning);
    --upaep-tracker-item-error-icon-color: var(--ui-on-warning);
    --upaep-tracker-item-error-dot-bg: var(--ui-warning);
    --upaep-tracker-item-error-line-bg: var(--ui-warning);
    --upaep-tracker-item-error-title-color: var(--ui-text);

    --upaep-tracker-item-rejected-mark-bg: var(--ui-danger);
    --upaep-tracker-item-rejected-mark-border-color: var(--ui-danger);
    --upaep-tracker-item-rejected-mark-color: var(--ui-on-danger);
    --upaep-tracker-item-rejected-icon-color: var(--ui-on-danger);
    --upaep-tracker-item-rejected-dot-bg: var(--ui-danger);
    --upaep-tracker-item-rejected-line-bg: var(--ui-danger);
    --upaep-tracker-item-rejected-title-color: var(--ui-text);

    --upaep-tracker-progress-color: var(--ui-accent);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__tracker {
    --upaep-tracker-padding: 0;
    --upaep-tracker-margin: 0;
    --upaep-tracker-item-mark-size: 28px;
    --upaep-tracker-item-mark-border-size: 2px;
    --upaep-tracker-item-line-width: 2px;
    --upaep-tracker-item-title-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-tracker-item-title-fw: var(--upaep-fw-regular);
    --upaep-tracker-item-text-fz: var(--upaep-ex-fs-p5-small);
    --upaep-tracker-item-progress-title-fw: var(--upaep-fw-semibold);
    --upaep-tracker-item-complete-title-fw: var(--upaep-fw-regular);
    --upaep-tracker-progress-fz: var(--upaep-ex-fs-p5-small);
}

/*? ------ Steps ------ */
[data-brand="upaep"] .upaep__steps {
    --upaep-steps-items-bg: var(--ui-surface-3);
    --upaep-steps-item-bg: transparent;
    --upaep-steps-item-color: var(--ui-text-muted);
    --upaep-steps-item-opacity: 1;
    --upaep-steps-item-active-bg: var(--ui-surface);
    --upaep-steps-item-active-color: var(--ui-text);
    --upaep-steps-item-active-opacity: 1;
    --upaep-steps-item-complete-bg: transparent;
    --upaep-steps-item-complete-color: var(--ui-success);
    --upaep-steps-item-complete-opacity: 1;
    --upaep-steps-info-color: var(--ui-text-muted);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__steps {
    --upaep-steps-margin: 0;
    --upaep-steps-padding: 0;
    --upaep-steps-items-border-radius: var(--upaep-ex-radius-container);
    --upaep-steps-item-border-radius: var(--upaep-ex-radius-control);
    --upaep-steps-item-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-steps-item-fw: var(--upaep-fw-regular);
    --upaep-steps-item-active-fw: var(--upaep-fw-bold);
    --upaep-steps-info-fz: var(--upaep-ex-fs-p5-small);
}

/*? ------ Tooltip ------
    Caja gris 900 con esquina de 8px y texto de 12. El sistema es explícito:
    el tooltip NUNCA guarda información imprescindible. */
[data-brand="upaep"] .upaep__tooltip {
    --upaep-tooltip-bg: var(--upaep-ex-gray-900);
    --upaep-tooltip-color: var(--upaep-ex-white);
    --upaep-tooltip-arrow-bg: var(--upaep-ex-gray-900);
    --upaep-tooltip-body-bg: var(--upaep-ex-gray-900);
    --upaep-tooltip-body-color: var(--upaep-ex-white);
    --upaep-tooltip-header-bg: var(--upaep-ex-gray-950);
    --upaep-tooltip-header-color: var(--upaep-ex-white);
    box-shadow: var(--upaep-ex-shadow-2);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__tooltip {
    --upaep-tooltip-border-size: 0;
    --upaep-tooltip-border-radius: var(--upaep-ex-radius-sm);
    --upaep-tooltip-padding: 8px 12px;
    --upaep-tooltip-fz: var(--upaep-ex-fs-p5-small);
    --upaep-tooltip-fw: var(--upaep-fw-regular);
    --upaep-tooltip-maxwidth: 260px;
    --upaep-tooltip-body-fz: var(--upaep-ex-fs-p5-small);
    --upaep-tooltip-header-fz: var(--upaep-ex-fs-p5-small);
    --upaep-tooltip-header-fw: var(--upaep-fw-bold);
}

/*? =====================================================================
    5. PATRONES DE MARCA
    Piezas que el sistema documenta y el uikit no tiene como componente.
    NO son componentes: son clases decorativas .__upaep-ex-*, sin runtime, y
    no se registran en ai/components.json.
    ===================================================================== */

/*? Tarjeta de indicador (KpiCard). Icono en pastilla de 40, delta arriba a
    la derecha y la cifra en 28 regular.
    El delta usa colores de ETIQUETA, no de estado: comunica variación, no
    veredicto. Se combina con la card del kit:
    `upaep__card __upaep-ex-kpi`. */
[data-brand="upaep"] .upaep__card.__upaep-ex-kpi {
    align-items: stretch;
    text-align: left;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-kpi {
    --upaep-card-content-padding: 24px;
}

/* ⚠ `.upaep__card-content` del kit es `display: flex` en FILA y centrado:
   sin esto, el icono, el delta, el rótulo y la cifra quedan uno al lado del
   otro. El KPI los quiere apilados y alineados a la izquierda. */
[data-brand="upaep"] .upaep__card.__upaep-ex-kpi .upaep__card-content {
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
}

[data-brand="upaep"] .__upaep-ex-kpi-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-kpi-top {
    gap: 12px;
    margin-bottom: 24px;
}

/* La pastilla del icono: el sistema le da SEIS acentos, cada uno con su
   pastel de etiqueta y su tono de glifo. El azul es el de por defecto; los
   otros tres que el catálogo usa van como modificadores.
   ⚠ Quedan dos sin portar —naranja (`--etiqueta-4` + `#8A4B12`) y violeta
   (`--etiqueta-6` + `#3B3F8F`)— porque el catálogo no los ejercita y no se
   declara un primitivo que nadie use: si hacen falta, son esos dos valores. */
[data-brand="upaep"] .__upaep-ex-kpi-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    background: var(--upaep-ex-label-1);
    color: var(--upaep-ex-navy);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-kpi-icon {
    width: 40px;
    height: 40px;
    border-radius: var(--upaep-ex-radius-control);
}

[data-brand="upaep"] .__upaep-ex-kpi-icon.__green {
    background: var(--upaep-ex-label-3);
    color: var(--upaep-ex-success-hover);
}

[data-brand="upaep"] .__upaep-ex-kpi-icon.__yellow {
    background: var(--upaep-ex-label-2);
    color: var(--upaep-ex-on-warning-bg);
}

[data-brand="upaep"] .__upaep-ex-kpi-icon.__pink {
    background: var(--upaep-ex-label-5);
    color: var(--upaep-ex-red);
}


[data-brand="upaep"] .__upaep-ex-kpi-delta {
    background: var(--upaep-ex-label-3);
    color: var(--upaep-ex-success-hover);
    white-space: nowrap;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-kpi-delta {
    padding: 4px 10px;
    border-radius: var(--upaep-ex-radius-control);
    font: var(--upaep-fw-semibold) var(--upaep-ex-fs-p5-small)/1.3 var(--ui-font-base);
}

[data-brand="upaep"] .__upaep-ex-kpi-delta.__warning {
    background: var(--upaep-ex-label-2);
    color: var(--upaep-ex-on-warning-bg);
}

/* El delta negativo y el crítico comparten pastilla y color: el rojo oscuro
   del KpiCard, que NO es el del Alert. */
[data-brand="upaep"] .__upaep-ex-kpi-delta.__critical {
    background: var(--upaep-ex-label-5);
    color: var(--upaep-ex-red-deep);
}


[data-brand="upaep"] .__upaep-ex-kpi-label {
    display: block;
    text-transform: uppercase;
    color: var(--upaep-ex-gray-700);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-kpi-label {
    font: var(--upaep-fw-semibold) var(--upaep-ex-fs-p5-small)/1.3 var(--ui-font-base);
    letter-spacing: .04em;
    margin-bottom: 4px;
}

[data-brand="upaep"] .__upaep-ex-kpi-value {
    display: block;
    color: var(--ui-text);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-kpi-value {
    font: var(--upaep-fw-regular) var(--upaep-ex-fs-h3-entry)/1.1 var(--ui-font-base);
}

/*? Avatar con iniciales. Círculo neutro por defecto; los institucionales
    distinguen personas en una lista sin usar colores de estado. */
[data-brand="upaep"] .__upaep-ex-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    overflow: hidden;
    background: var(--upaep-ex-gray-800);
    color: var(--upaep-ex-white);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-avatar {
    width: 36px;
    height: 36px;
    border-radius: var(--upaep-ex-radius-full);
    font: var(--upaep-fw-semibold) 14px/1 var(--ui-font-base);
}

[data-brand="upaep"] .__upaep-ex-avatar.__red {
    background: var(--upaep-ex-red);
}

[data-brand="upaep"] .__upaep-ex-avatar.__navy {
    background: var(--upaep-ex-navy);
}

[data-brand="upaep"] .__upaep-ex-avatar.__action {
    background: var(--upaep-ex-action);
}

[data-brand="upaep"] .__upaep-ex-avatar.__lg {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-avatar.__lg {
    width: 52px;
    height: 52px;
    font-size: 20px;
}

/*? Punto de prioridad. El punto ACOMPAÑA al texto, no lo sustituye: en el
    sistema el color clasifica pero nunca comunica solo. */
[data-brand="upaep"] .__upaep-ex-priority {
    display: inline-flex;
    align-items: center;
    color: var(--ui-text-on-surface);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-priority {
    gap: 8px;
    font: var(--upaep-fw-medium) var(--upaep-ex-fs-p5-small)/1.4 var(--ui-font-base);
}

[data-brand="upaep"] .__upaep-ex-priority::before {
    content: "";
    flex: 0 0 auto;
    background: var(--upaep-ex-gray-600);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-priority::before {
    width: 8px;
    height: 8px;
    border-radius: var(--upaep-ex-radius-full);
}

[data-brand="upaep"] .__upaep-ex-priority.__high::before {
    background: var(--upaep-ex-red);
}

[data-brand="upaep"] .__upaep-ex-priority.__medium::before {
    background: var(--upaep-ex-yellow-button);
}

[data-brand="upaep"] .__upaep-ex-priority.__low::before {
    background: var(--upaep-ex-success);
}


/*? Campo con ICONO. El kit tiene una estructura canónica para esto y es la
    que hay que usar —no un envoltorio propio con el icono en absoluto—:

        .upaep__input-container > .upaep__input-wrapper
            > .upaep__input-icon.__left|.__right
            > .upaep__input.__icon

    El `.__icon` del input no es decorativo: excluye al campo del relleno
    extra que añaden los iconos de estado de validación.

    ⚠ El core solo abre sitio para el icono IZQUIERDO
    (`:has(.upaep__input-icon.__left)`, con relleno de 1rem/3rem); para el
    derecho no hay regla. Las dos las pone esta capa, en las métricas de la
    marca —cápsula de 22px de relleno, 48px por el lado del icono—. */
[data-brand="upaep"] .upaep__input-wrapper:has(.upaep__input-icon.__left)>.upaep__input {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__input-wrapper:has(.upaep__input-icon.__left)>.upaep__input {
    --upaep-input-padding: 10px 22px 10px 48px;
}

[data-brand="upaep"] .upaep__input-wrapper:has(.upaep__input-icon.__right)>.upaep__input {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__input-wrapper:has(.upaep__input-icon.__right)>.upaep__input {
    --upaep-input-padding: 10px 48px 10px 22px;
}

/* El icono del sistema mide 18px, no los 40 de la caja del kit. */
[data-brand="upaep"] .upaep__input-icon {
    --upaep-input-icon-img-width: 18px;
    --upaep-input-icon-img-height: 18px;
}

/*? Caja de búsqueda (SearchBox). Es el caso anterior con la lupa a la
    derecha, y en el sistema esa lupa **envía**: es un `<button type="submit">`
    con la clase de la caja de icono, no un adorno. De ahí el cursor y el
    gris 600 —el icono del kit viene en el acento rojo—. */
[data-brand="upaep"] .__upaep-ex-search .upaep__input-icon {
    --upaep-input-icon-color: var(--upaep-ex-gray-600);
    --upaep-input-icon-hover-color: var(--upaep-ex-gray-800);
    --upaep-input-icon-cursor: pointer;
}


/*? Indicadores de carrusel (CarouselDots). El punto activo se alarga a 28px
    y pasa a rojo; los demás son círculos de 10px en gris 400. */
[data-brand="upaep"] .__upaep-ex-dots {
    display: flex;
    align-items: center;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-dots {
    gap: 8px;
}

[data-brand="upaep"] .__upaep-ex-dots button {
    border: 0;
    cursor: pointer;
    background: var(--upaep-ex-gray-400);
    transition: width var(--upaep-ex-duration-base) var(--upaep-ex-ease),
        background var(--upaep-ex-duration-base) var(--upaep-ex-ease);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-dots button {
    width: 10px;
    height: 10px;
    padding: 0;
    border-radius: var(--upaep-ex-radius-full);
}

[data-brand="upaep"] .__upaep-ex-dots button[aria-selected="true"] {
    background: var(--ui-accent);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-dots button[aria-selected="true"] {
    width: 28px;
}

/*? Escala de satisfacción (FaceRating). Cinco pasos; cada cara lleva SU
    etiqueta escrita, porque la cara sola no es un dato legible. En los tonos
    claros el glifo va oscuro para conservar el contraste. */
[data-brand="upaep"] .__upaep-ex-faces {
    display: flex;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-faces {
    gap: 8px;
}

[data-brand="upaep"] .__upaep-ex-faces button {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    border: 0;
    background: none;
    cursor: pointer;
    color: var(--upaep-ex-gray-700);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-faces button {
    gap: 8px;
    padding: 8px 0;
    font: var(--upaep-fw-medium) var(--upaep-ex-fs-p5-small)/1.3 var(--ui-font-base);
}

[data-brand="upaep"] .__upaep-ex-faces button>span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--ui-surface-3);
    color: var(--ui-text-muted);
    transition: background var(--upaep-ex-duration-fast) var(--upaep-ex-ease),
        box-shadow var(--upaep-ex-duration-fast) var(--upaep-ex-ease);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-faces button>span {
    width: 56px;
    height: 56px;
    border-radius: var(--upaep-ex-radius-full);
}

[data-brand="upaep"] .__upaep-ex-faces button[aria-checked="true"] {
    color: var(--ui-text-strong);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-faces button[aria-checked="true"] {
    font-weight: var(--upaep-fw-bold);
}

/* Los cinco tonos de la rampa de caras. Los dos claros (regular y bien)
   llevan glifo navy; los tres oscuros, blanco. */
[data-brand="upaep"] .__upaep-ex-faces button[aria-checked="true"][data-face="1"]>span {
    background: var(--upaep-ex-red-deep);
    color: var(--upaep-ex-white);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--upaep-ex-red-deep) 20%, transparent);
}


[data-brand="upaep"] .__upaep-ex-faces button[aria-checked="true"][data-face="2"]>span {
    background: var(--upaep-ex-red-hover);
    color: var(--upaep-ex-white);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--upaep-ex-red-hover) 20%, transparent);
}

[data-brand="upaep"] .__upaep-ex-faces button[aria-checked="true"][data-face="3"]>span {
    background: var(--upaep-ex-yellow-button);
    color: var(--upaep-ex-navy);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--upaep-ex-yellow-button) 20%, transparent);
}

[data-brand="upaep"] .__upaep-ex-faces button[aria-checked="true"][data-face="4"]>span {
    background: var(--upaep-ex-success);
    color: var(--upaep-ex-navy);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--upaep-ex-success) 20%, transparent);
}

[data-brand="upaep"] .__upaep-ex-faces button[aria-checked="true"][data-face="5"]>span {
    background: var(--upaep-ex-success-hover);
    color: var(--upaep-ex-white);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--upaep-ex-success-hover) 20%, transparent);
}

/*? WeekCalendar y HourSelect: RETIRADOS del catálogo.
    La revisión de sep 2026 los saca de la documentación: el conteo baja de 30
    piezas a 28, la descripción del bloque ya no menciona el calendario y la
    lista de archivos dice «28 componentes».

    ⚠ Sus dos `.jsx` SIGUEN dentro del export (el bundle no borra archivos), así
    que encontrarlos ahí no significa que el sistema los sostenga. Su revestido
    y sus patrones se quitaron de esta hoja: para un calendario se usa
    **Chronicle** (`calendar-chronicle/`), y para elegir una hora, el
    `.upaep__select` normal. */

/*? ------ Herald ------
    El *FeedbackModal* del sistema —el modal de desenlace, que cierra un
    flujo con UNA sola idea centrada— **es Herald**, no un modificador del
    modal. Herald es la fábrica de diálogos del kit: monta el DOM al vuelo,
    devuelve una Promise y se destruye al cerrar.

    Ya hereda la marca casi entera: su superficie es
    `<dialog class="upaep__modal upaep__herald __centered">`, así que le
    aplica el revestido del modal de arriba, y sus variantes de icono leen
    `--ui-success` / `--ui-danger` / `--ui-warning` directamente. Aquí solo
    se ajusta lo que el sistema pide distinto: esquina de 20px, aro de 5px
    alrededor de un icono de 96 y las métricas de título y cuerpo.

    ⚠ Herald es un paquete: hay que enlazar `herald/herald.css` +
    `herald/herald.js` (y los de `bottomSheet/` si se usa `surface: 'bottomSheet'`).
    No vive en el monolito. */
[data-brand="upaep"] .upaep__herald {
    --upaep-herald-icon-size: 96px;
    --upaep-herald-icon-border-size: 5px;
    --upaep-herald-title-color: var(--ui-text);
    --upaep-herald-text-color: var(--ui-text-on-surface);
    --upaep-herald-input-border-color: var(--ui-border);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__herald {
    --upaep-modal-content-border-radius: var(--upaep-ex-radius-lg);
    --upaep-herald-maxwidth: 460px;
    --upaep-herald-body-padding: 48px 40px 8px;
    --upaep-herald-actions-padding: 24px 40px 40px;
    --upaep-herald-gap: 12px;
    --upaep-herald-title-fz: var(--upaep-ex-fs-h3-entry);
    --upaep-herald-title-fw: var(--upaep-fw-bold);
    --upaep-herald-text-fz: var(--upaep-ex-fs-p4-medium);
    --upaep-herald-input-border-radius: var(--upaep-ex-radius-control);
    --upaep-herald-input-fz: var(--upaep-ex-fs-p3-regular);
    --upaep-herald-input-padding: 10px 22px;
}

/*? Diálogo con MASCOTA (`__upaep-ex-mascot`) — de la revisión de sep 2026.
    El aviso de **dato faltante** es el único componente del sistema donde
    Brumildo *sustituye* al icono de estado en vez de acompañarlo: 120px, sin
    anillo, en el hueco del icono (arriba del título, no en el cuerpo).

    Se monta con `iconHtml` + `customClass: '__upaep-ex-mascot'`: el `iconHtml`
    lo pone en el hueco correcto y `__custom` ya apaga el glifo. Aquí sólo hay
    que agrandar la caja y **apagar el anillo**, que Herald pinta con el
    `::after` del icono y seguiría dibujando una circunferencia alrededor del
    pájaro.

    ⚠ El `:is(svg, img)` de Herald vale 55% de la caja; la mascota va al 100%,
    así que la imagen ocupa los 120px completos. */
[data-brand="upaep"] .upaep__herald.__upaep-ex-mascot .upaep__herald-icon {
    --upaep-herald-icon-size: 120px;
}

[data-brand="upaep"] .upaep__herald.__upaep-ex-mascot .upaep__herald-icon::after {
    content: none;
}

[data-brand="upaep"] .upaep__herald.__upaep-ex-mascot .upaep__herald-icon :is(svg, img) {
    object-fit: contain;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__herald.__upaep-ex-mascot .upaep__herald-icon :is(svg, img) {
    width: 100%;
    height: 100%;
}

/*? Card de ACCIÓN — variante nueva de la revisión de sep 2026.
    Icono, título, una línea de explicación y una sola salida, todo centrado.
    Para rejillas de accesos donde ninguna tarjeta manda sobre otra.

    ⚠ El sistema es explícito: **el botón es el enlace**, así que esta
    variante NO toma `href`. Si la card entera fuera el enlace habría dos
    destinos para el mismo gesto.

    El icono va en una caja de 64px de alto mínimo para que los títulos
    queden alineados entre tarjetas aunque los iconos midan distinto. */
[data-brand="upaep"] .upaep__card.__upaep-ex-action {
    --upaep-card-title-align: center;
    --upaep-card-text-align: center;
    align-items: center;
    text-align: center;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-action {
    --upaep-card-content-padding: 36px 28px 32px;
    --upaep-card-title-fz: var(--upaep-ex-fs-p1-web-large);
    --upaep-card-title-fw: var(--upaep-fw-bold);
    --upaep-card-text-fz: 15px;
}

/* El título de esta variante va en Fira Sans, no en Condensed como el resto
   de las cards. */
[data-brand="upaep"] .upaep__card.__upaep-ex-action .upaep__card-title {
    font-family: var(--ui-font-base);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-action .upaep__card-title {
    line-height: 1.2;
}

[data-brand="upaep"] .upaep__card.__upaep-ex-action .upaep__card-content {
    flex-direction: column;
    align-items: center;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-action .upaep__card-content {
    gap: 16px;
}

/* La caja del icono: alto mínimo para alinear los títulos entre tarjetas. */
[data-brand="upaep"] .__upaep-ex-action-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--ui-text-on-surface);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-action-icon {
    min-height: 64px;
}

[data-brand="upaep"] .__upaep-ex-action-icon svg {
    display: block;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .__upaep-ex-action-icon svg {
    width: 77px;
    height: 77px;
}

/* La salida va abajo, empujada, para que todas las tarjetas de la rejilla
   tengan el botón a la misma altura. Si hay más de una acción se apilan
   —columna, no fila—, como en el sistema. */
[data-brand="upaep"] .upaep__card.__upaep-ex-action .upaep__card-footer {
    /* Mismo caso que la card base: el relleno lateral e inferior de la
       tarjeta (28 y 32) tiene que estar aquí, o el botón toca el borde. */

    border-top: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-action .upaep__card-footer {
    --upaep-card-footer-padding: 8px 28px 32px;
    margin-top: auto;
    gap: 10px;
}

/*? Variantes de card del PORTAL. Tres formas que el sistema documenta y que
    el kit no tiene: lista (miniatura de 96px + flecha), acreditación
    (logotipo de 74×52 + texto menudo) y mosaico (imagen 240×148 + rótulo
    centrado). Son modificadores de `.upaep__card`. */
[data-brand="upaep"] .upaep__card.__upaep-ex-list {
    --upaep-card-boxshadow: var(--upaep-ex-shadow-2);
    flex-direction: row;
    align-items: stretch;
    overflow: hidden;
    text-decoration: none;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-list {
    --upaep-card-content-padding: 13px 0;
    gap: 13px;
    min-height: 86px;
}

[data-brand="upaep"] .upaep__card.__upaep-ex-list .upaep__card-img {
    flex: none;
    align-self: stretch;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-list .upaep__card-img {
    --upaep-card-img-content-width: 96px;
    --upaep-card-img-content-border-radius: 0;
}

[data-brand="upaep"] .upaep__card.__upaep-ex-list .upaep__card-content {
    flex: 1;
    align-items: flex-start;
    flex-direction: column;
    justify-content: center;
    text-align: left;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-list .upaep__card-content {
    min-width: 0;
}

[data-brand="upaep"] .upaep__card.__upaep-ex-list .upaep__card-title {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-list .upaep__card-title {
    --upaep-card-title-fz: 17px;
    --upaep-card-title-fw: var(--upaep-fw-bold);
    line-height: 1.05;
}

[data-brand="upaep"] .upaep__card.__upaep-ex-list .upaep__card-text {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-list .upaep__card-text {
    --upaep-card-text-fz: var(--upaep-ex-fs-p5-small);
    margin-top: 5px;
}

/* La flecha del final: el kit no tiene un slot para ella. */
[data-brand="upaep"] .upaep__card.__upaep-ex-list .upaep__card-footer {
    align-self: center;
    border-top: 0;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-list .upaep__card-footer {
    --upaep-card-footer-padding: 0 14px 0 0;
    font-size: 21px;
    font-weight: var(--upaep-fw-bold);
    width: auto;
}

[data-brand="upaep"] .upaep__card.__upaep-ex-accreditation {
    --upaep-card-bg: var(--ui-surface-3);
    --upaep-card-boxshadow: var(--upaep-ex-shadow-2);
    --upaep-card-text-color: var(--upaep-ex-gray-700);
    flex-direction: row;
    align-items: center;
    text-decoration: none;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-accreditation {
    --upaep-card-content-padding: 11px 13px;
    gap: 13px;
}

[data-brand="upaep"] .upaep__card.__upaep-ex-accreditation .upaep__card-img {
    /* El logotipo de acreditación es un vector de proporción libre: sin
       `contain` y con la <img> a 100%, el core la estira a 74×52 y la recorta. */
    --upaep-card-img-objectfit: contain;
    flex: none;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-accreditation .upaep__card-img {
    --upaep-card-img-content-width: 74px;
    --upaep-card-img-content-height: 52px;
    --upaep-card-img-content-border-radius: 0;
    --upaep-card-img-width: auto;
    --upaep-card-img-height: auto;
    margin-left: 13px;
}

[data-brand="upaep"] .upaep__card.__upaep-ex-accreditation .upaep__card-img img {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-accreditation .upaep__card-img img {
    max-width: 100%;
    max-height: 100%;
}

[data-brand="upaep"] .upaep__card.__upaep-ex-accreditation .upaep__card-text {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-accreditation .upaep__card-text {
    --upaep-card-text-fz: 11.5px;
    line-height: 1.4;
}

[data-brand="upaep"] .upaep__card.__upaep-ex-tile {
    --upaep-card-boxshadow: var(--upaep-ex-shadow-2);
    overflow: hidden;
    text-decoration: none;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-tile {
    --upaep-card-content-padding: 11px 9px 13px;
}

[data-brand="upaep"] .upaep__card.__upaep-ex-tile .upaep__card-img {
    /* La proporción la manda el aspect-ratio, así que hay que soltar el alto
       que el core le fija: con los dos puestos, uno de los dos miente. */
    aspect-ratio: 240 / 148;
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-tile .upaep__card-img {
    --upaep-card-img-content-border-radius: 0;
    --upaep-card-img-content-height: auto;
}

[data-brand="upaep"] .upaep__card.__upaep-ex-tile .upaep__card-title {
    --upaep-card-title-align: center;
    font-family: var(--ui-font-base);
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-tile .upaep__card-title {
    --upaep-card-title-fz: 13px;
    --upaep-card-title-fw: var(--upaep-fw-semibold);
    line-height: 1.25;
}

[data-brand="upaep"] .upaep__card.__upaep-ex-tile .upaep__card-content {
}

/*? geometria del sistema institucional — solo en el lienzo (U-32) */
:is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card.__upaep-ex-tile .upaep__card-content {
    min-height: 64px;
}

/*? =====================================================================
    6. RESPONSIVE
    A diferencia de las demás marcas, aquí la ESCALA MÓVIL NO ES DERIVADA:
    el sistema publica cuatro estilos de texto para móvil (26 bold, 24
    regular y dos de 22 cursiva). Lo derivado son los CORTES, que salen de
    los anchos de contenedor del archivo (1200 / 648 / 312).
    ===================================================================== */

/* Tablet — contenedor de 648px */
@media (width < 1024px) {

    :where([data-brand="upaep"]) h1 {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h1 {
        font-size: 42px;
    }

    :where([data-brand="upaep"]) h1.__hero {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h1.__hero {
        font-size: 44px;
    }

    :where([data-brand="upaep"]) h2 {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h2 {
        font-size: 30px;
    }
}

/* Móvil — contenedor de 312px. Aquí entra la escala publicada. */
@media (width < 700px) {

    :where([data-brand="upaep"]) h1 {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h1 {
        font-size: var(--upaep-ex-fs-h1-section-mobile);
        font-weight: var(--upaep-fw-bold);
    }

    :where([data-brand="upaep"]) h1.__hero {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h1.__hero {
        font-size: 34px;
    }

    :where([data-brand="upaep"]) h2 {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h2 {
        font-size: var(--upaep-ex-fs-h2-subtitle-mobile);
        font-weight: var(--upaep-fw-regular);
    }

    :where([data-brand="upaep"]) h2.__entry {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h2.__entry {
        font-size: var(--upaep-ex-fs-h3-card-mobile);
        font-weight: var(--upaep-fw-regular);
    }

    :where([data-brand="upaep"]) h3 {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) h3 {
        font-size: var(--upaep-ex-fs-h3-card-mobile);
    }

    :where([data-brand="upaep"]) p.__lead {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *):where([data-brand="upaep"]) p.__lead {
        font-size: var(--upaep-ex-fs-p2-semilarge);
    }

    [data-brand="upaep"] .upaep__card {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__card {
        --upaep-card-content-padding: 16px;
    }

    /* El modal a ancho de móvil no puede gastar 40px por lado. */
    [data-brand="upaep"] .upaep__modal {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__modal {
        --upaep-modal-body-padding: 20px 24px 24px;
        --upaep-modal-footer-padding: 0 24px 24px;
    }

    [data-brand="upaep"] .upaep__offcanvas {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__offcanvas {
        --upaep-offcanvas-header-padding: 20px 20px 12px;
        --upaep-offcanvas-content-padding: 20px;
        --upaep-offcanvas-footer-padding: 12px 20px 20px;
    }

    /* xs y sm quedan por debajo del área táctil mínima de 44px: en móvil el
       botón compacto sube al alto de control. */
    [data-brand="upaep"] .upaep__btn:is(.__upaep-ex-xs, .__sm) {
    }

    /*? geometria del sistema institucional — solo en el lienzo (U-32) */
    :is([data-brand-canvas], [data-brand-canvas] *)[data-brand="upaep"] .upaep__btn:is(.__upaep-ex-xs, .__sm) {
        --upaep-btn-height: var(--upaep-ex-control-height);
    }
}

/*? El sistema pide respetar prefers-reduced-motion; su hoja global ya pone
    las tres duraciones a 0. Aquí se replica y se apaga el hundimiento del
    botón, que es la única transformación que añade esta hoja. */
@media (prefers-reduced-motion: reduce) {

    [data-brand="upaep"] {
        --upaep-ex-duration-fast: 0ms;
        --upaep-ex-duration-base: 0ms;
        --upaep-ex-duration-slow: 0ms;
    }

    [data-brand="upaep"] .upaep__btn:active:not(:disabled) {
        transform: none;
    }
}
