/* ── Componente Questor (constructor de formularios) ────────────────────────
   Dos bloques que se usan juntos o por separado:
     .upaep__questor        el constructor (edición + vista previa)
     .upaep__questor-form   el formulario contestable (QuestorForm)

   El componente NO pinta fondo ni relleno propios: se apoya en la superficie de
   la página. `.upaep__questor.__surface` le devuelve el lienzo gris.

   Ambos aceptan los mismos modificadores de presentación:
     .__cards-flat      tarjetas planas, con borde fino          (por defecto)
     .__cards-outline   solo contorno, sin fondo propio
     .__cards-raised    tarjetas con sombra, aspecto elevado "3D"
     .__inputs-rounded  controles con esquinas muy redondeadas
     .__inputs-square   controles con esquinas rectas

   Variables configurables (fallback a tokens globales):
   --upaep-questor-accent          color de acento (marcador, foco, chips)
   --upaep-questor-bg              fondo del lienzo (transparente por defecto)
   --upaep-questor-pad             relleno del lienzo (0 por defecto)
   --upaep-questor-subtle          relleno tenue de estados y cabeceras
   --upaep-questor-sticky-bg       superficie de la barra al quedar fija
   --upaep-questor-card-bg         fondo de tarjetas y preguntas
   --upaep-questor-card-border     color del borde de la tarjeta
   --upaep-questor-card-shadow     sombra de la tarjeta (variante raised)
   --upaep-questor-radius          radio de las tarjetas
   --upaep-questor-control-radius  radio de los controles de formulario
   --upaep-questor-gap             separación entre tarjetas
   --upaep-questor-padding         relleno interno de una tarjeta
   --upaep-questor-marker          ancho de la barra lateral de la activa
   --upaep-questor-toolbar-pad     relleno vertical de la barra
   --upaep-questor-tool-size       lado del botón de la barra en modo icono
   --upaep-questor-tool-icon       tamaño del glifo de ese botón
   --upaep-questor-tool-gap        separación entre botones de la barra
   --upaep-questor-sticky-shadow   sombra de la barra fija (hacia abajo)
   --upaep-questor-sticky-shadow-up sombra de la barra fija abajo (hacia arriba)
   --upaep-questor-sticky-top      hueco al pegarse arriba (lo pone el JS)
   --upaep-questor-sticky-bottom   hueco al pegarse abajo (lo pone el JS)
   --upaep-questor-duration        duración de las transiciones (el JS espera
                                   QUESTOR_FOLD_DELAY, que debe ser >= ésta)
--------------------------------------------------------------------------- */
.upaep__questor,
.upaep__questor-form {
    --upaep-questor-accent: var(--ui-primary, var(--upaep-color-primary));
    --upaep-questor-on-accent: var(--ui-on-primary, var(--upaep-color-white, #fff));

    /*? El componente NO pinta fondo ni ocupa relleno propio: se apoya en la
       superficie de la página. Con .__surface recupera el lienzo gris. */
    --upaep-questor-bg: transparent;
    --upaep-questor-pad: 0px;
    /*? Relleno tenue para estados y cabeceras (hover, encabezado de una
       cuadrícula). Es un color de verdad, no el fondo del componente: si se
       apoyara en --upaep-questor-bg se quedaría transparente. */
    --upaep-questor-subtle: var(--ui-surface-2, var(--upaep-color-tenue-gray));
    /*? Solo se usa cuando la barra queda fija: ahí necesita algo opaco que tape
       el contenido que pasa por debajo. */
    --upaep-questor-sticky-bg: var(--ui-surface, var(--upaep-color-white, #fff));

    --upaep-questor-card-bg: var(--ui-surface, var(--upaep-color-white, #fff));
    --upaep-questor-color: var(--ui-text-on-surface, var(--upaep-color-dark-grey));
    --upaep-questor-muted: var(--ui-text-muted, var(--upaep-color-grey));
    --upaep-questor-border: var(--ui-border, var(--upaep-color-border-grey));
    --upaep-questor-divider: var(--ui-border-subtle, var(--ui-border));
    --upaep-questor-danger: var(--ui-danger, var(--upaep-color-error));
    --upaep-questor-success: var(--ui-success, var(--upaep-color-success));

    /*? Presentación de la tarjeta: la cambian los modificadores __cards-* */
    --upaep-questor-card-border: var(--ui-border-subtle, var(--upaep-color-border-grey));
    --upaep-questor-card-shadow: none;
    --upaep-questor-card-hover-shadow: none;
    /*? Caída recta y difusa para la barra fija; no vale la sombra de tarjeta.
       Una por sentido: cae siempre hacia el lado donde está el contenido. */
    --upaep-questor-sticky-shadow: 0 6px 16px -10px rgb(0 0 0 / .45);
    --upaep-questor-sticky-shadow-up: 0 -6px 16px -10px rgb(0 0 0 / .45);
    /*? Hueco que deja la barra al pegarse, para no quedar debajo de la cabecera
       o del pie que ya tenga la página. El JS sobreescribe la del borde que use
       (opción stickyOffset); sin ella la barra se pega al borde. */
    --upaep-questor-sticky-top: 0px;
    --upaep-questor-sticky-bottom: 0px;

    --upaep-questor-radius: 12px;
    --upaep-questor-control-radius: 10px;
    --upaep-questor-gap: 1rem;
    --upaep-questor-padding: 1.25rem;
    --upaep-questor-marker: 5px;
    --upaep-questor-fz: var(--upaep-fz15);
    --upaep-questor-icon: 20px;
    /*? Hueco que reserva el campo para su icono, y ancho de la caja del icono:
       una sola medida para que no puedan desalinearse. */
    --upaep-questor-icon-slot: 2.75rem;
    --upaep-questor-icon-btn: 34px;
    /*? Botón de la barra en modo icono: caja cuadrada y glifo, en una sola
       medida para que TODOS salgan iguales (el principal incluido) sin depender
       de qué regla gane. */
    --upaep-questor-tool-size: 34px;
    --upaep-questor-tool-icon: 1.25rem;
    /*? Separación ENTRE botones de la barra. Va corta a propósito: la caja de
       cada botón ya deja aire alrededor del glifo, y con más separación dejan de
       leerse como un grupo. */
    --upaep-questor-tool-gap: .125rem;
    /*? Relleno vertical propio de la barra, independiente del del lienzo */
    --upaep-questor-toolbar-pad: .75rem;
    --upaep-questor-max-width: 800px;

    /*? ── Escalera de apilado ────────────────────────────────────────────────
       Se deriva de los tokens del kit, no de números sueltos, porque el
       componente convive con los paneles flotantes de otros componentes:
       selectpicker, autocomplete, datepicker y dropdown están TODOS en
       --upaep-zindex-* ≈ 1015. El orden que hace falta es:

         contenido  <  barra fija  <  aviso de deshacer  <  paneles (≈1015)

       Si la barra fija estuviera por encima de 1015 (p. ej. con
       --upaep-zindex-sticky, que vale 1020) taparía el calendario de un
       datepicker abierto en una tarjeta. Por eso va en la banda de 100. */
    --upaep-questor-z-sticky: var(--upaep-zindex-menubar, 100);
    --upaep-questor-z-undo: var(--upaep-zindex-tag, 1000);

    --upaep-questor-duration: .22s;
    --upaep-questor-easing: cubic-bezier(.2, .7, .3, 1);

    font-family: var(--ui-font-base, var(--upaep-ff-fira-sans));
    font-size: var(--upaep-questor-fz);
    color: var(--upaep-questor-color);

    /*? Barras de scroll finas en todo el componente. Las dos propiedades se
       heredan, así que declararlas en la raíz cubre cuadrículas, listas de
       casillas, barra de herramientas y los paneles de los componentes
       envueltos, sin repetirlas en cada caja. */
    scrollbar-width: thin;
    scrollbar-color: var(--upaep-questor-border) transparent;
}

/* ── Presentación de las tarjetas ─────────────────────────────────────────── */
.upaep__questor.__cards-outline,
.upaep__questor-form.__cards-outline {
    --upaep-questor-card-bg: transparent;
    --upaep-questor-card-border: var(--ui-border, var(--upaep-color-border-grey));
}

/*? Elevada: dos capas de sombra (contacto + difusa). --ui-shadow ya cambia de
   intensidad en modo oscuro, así que la variante se adapta sola. */
.upaep__questor.__cards-raised,
.upaep__questor-form.__cards-raised {
    --upaep-questor-card-border: transparent;
    --upaep-questor-card-shadow: var(--ui-shadow), 0 14px 30px -18px rgb(0 0 0 / .55);
    --upaep-questor-card-hover-shadow: var(--ui-shadow), 0 22px 40px -20px rgb(0 0 0 / .6);
}

/*? En oscuro una tarjeta sin borde se pierde contra el lienzo: la sombra sola
   no basta, así que la variante elevada recupera un contorno tenue. */
[data-theme="dark"] .upaep__questor.__cards-raised,
[data-theme="dark"] .upaep__questor-form.__cards-raised {
    --upaep-questor-card-border: var(--ui-border-subtle);
}

/* ── Radio de los controles ───────────────────────────────────────────────── */
.upaep__questor.__inputs-rounded,
.upaep__questor-form.__inputs-rounded {
    --upaep-questor-control-radius: 999px;
}

.upaep__questor.__inputs-square,
.upaep__questor-form.__inputs-square {
    --upaep-questor-control-radius: 0px;
}

/*? Se aplica a los controles del kit que viven dentro del componente. Los
   campos con la variante .__underline quedan fuera: no tienen caja. */
.upaep__questor .upaep__input:not(.__underline),
.upaep__questor .upaep__select,
.upaep__questor-form .upaep__input:not(.__underline),
.upaep__questor-form .upaep__select {
    --upaep-input-border-radius: var(--upaep-questor-control-radius);
    --upaep-select-border-radius: var(--upaep-questor-control-radius);
}

/*? Con las esquinas muy redondeadas hace falta más aire horizontal */
.upaep__questor.__inputs-rounded .upaep__input:not(.__underline),
.upaep__questor-form.__inputs-rounded .upaep__input:not(.__underline) {
    --upaep-input-padding: .35rem 1rem;
}

/* ── Estados de los controles: el core reaplica tipografía en hover ───────── */
/*? .upaep__input:hover vuelve a fijar font-size, font-weight, color y fondo con
   las variables --upaep-input-hover-*. Si no se igualan a las de reposo, el
   texto cambia de tamaño al pasar el ratón y el campo "salta". Se enlazan a sí
   mismas para que cada regla más específica las arrastre. */
.upaep__questor .upaep__input,
.upaep__questor-form .upaep__input {
    --upaep-input-hover-fz: var(--upaep-input-fz);
    --upaep-input-hover-fw: var(--upaep-input-fw);
    --upaep-input-hover-color: var(--upaep-input-color);
    --upaep-input-hover-bg: var(--upaep-input-bg);
    --upaep-input-hover-border-size: var(--upaep-input-border-size);
    --upaep-input-focus-border-size: var(--upaep-input-border-size);
    --upaep-input-focus-bg: var(--upaep-input-bg);
}

/* ── Dos familias de campo, y solo dos ────────────────────────────────────── */
/*? Para no mezclar estilos a medias, cada campo cae en un grupo:

     · escritura del contenido (título, descripción, opciones) → SOLO borde
       inferior, con la variante .__underline del core;
     · controles de configuración (ajustes, selects, cuadrículas) → borde
       completo, fino y con el halo de foco del kit.

   Aquí va el segundo grupo: 1px de borde (el core trae 2px, que junto al select
   de al lado se veía tosco) y el halo estándar --ui-control-ring en vez de
   engrosar el borde. */
.upaep__questor-card .upaep__input:not(.__underline),
.upaep__questor-card .upaep__select {
    --upaep-input-border-size: 1px;
    --upaep-input-hover-border-size: 1px;
    --upaep-input-focus-border-size: 1px;
    --upaep-select-border-size: 1px;
    --upaep-select-focus-border-size: 1px;
    --upaep-input-focus-border-color: var(--upaep-questor-accent);
    --upaep-select-focus-border-color: var(--upaep-questor-accent);
    --upaep-input-focus-boxshadow: 0 0 0 3px var(--ui-control-ring);
    --upaep-select-focus-boxshadow: 0 0 0 3px var(--ui-control-ring);
}

/*? El editor plegable recorta lo que se sale, así que el halo del primer y del
   último control se vería cortado contra el borde del área. Con este aire
   interior cabe entero sin tocar la geometría del plegado. */
.upaep__questor-card-head {
    padding-top: 4px;
}

.upaep__questor-card-foot {
    padding-bottom: 4px;
}

/* ── Hueco para el icono del campo ────────────────────────────────────────── */
/*? El wrapper del core ya reserva el relleno izquierdo con
   `:has(.upaep__input-icon.__left)`, pero su especificidad (0-4-0) empata con la
   de `.__inputs-rounded .upaep__input:not(.__underline)` de aquí arriba, y al
   cargar esta hoja después ganaba la nuestra: el icono se montaba encima del
   placeholder. Se repone con un selector más específico. Y el lado derecho no lo
   contempla el core, así que se añade. */
.upaep__questor .upaep__input-wrapper:has(.upaep__input-icon.__left),
.upaep__questor-form .upaep__input-wrapper:has(.upaep__input-icon.__left) {

    & .upaep__input {
        --upaep-input-padding: .35rem 1rem .35rem var(--upaep-questor-icon-slot);
    }

    & .upaep__select {
        --upaep-select-padding: .5rem .75rem .5rem var(--upaep-questor-icon-slot);
    }
}

.upaep__questor .upaep__input-wrapper:has(.upaep__input-icon.__right),
.upaep__questor-form .upaep__input-wrapper:has(.upaep__input-icon.__right) {

    & .upaep__input {
        --upaep-input-padding: .35rem var(--upaep-questor-icon-slot) .35rem 1rem;
    }

    /*? El select ya usa su lado derecho para la flecha: el icono se corre para
       no taparla. */
    & .upaep__select {
        --upaep-select-padding: .5rem 3.75rem .5rem .75rem;
    }

    & .upaep__input-icon.__right {
        --upaep-input-icon-iset: auto 5px auto auto;
    }
}

/*? Nuestros iconos son decorativos: los clics deben llegar al campo de debajo.
   Se limita a `.__left`/`.__right`, los que genera wrapIcon: el Datepicker usa
   `.upaep__input-icon.__datepicker` como BOTÓN para abrir el calendario, y con
   un `pointer-events: none` general se quedaba sin poder pulsarse.

   Se fija además su geometría: el core deja `--upaep-input-icon-iset` sin valor
   por defecto (solo lo declara dentro de .upaep__input-wrapper), y un SVG inline
   sin medidas no tiene ancho propio — o se estira o se colapsa. */
.upaep__questor .upaep__input-icon:is(.__left, .__right),
.upaep__questor-form .upaep__input-icon:is(.__left, .__right) {
    --upaep-input-icon-width: var(--upaep-questor-icon-slot);
    --upaep-input-icon-height: 100%;
    --upaep-input-icon-margin: 0;
    pointer-events: none;

    & svg {
        flex: 0 0 auto;
        width: 1.15rem;
        height: 1.15rem;
    }
}

.upaep__questor .upaep__input-icon.__left,
.upaep__questor-form .upaep__input-icon.__left {
    --upaep-input-icon-iset: 0 auto 0 0;
}

.upaep__questor .upaep__input-icon.__right,
.upaep__questor-form .upaep__input-icon.__right {
    --upaep-input-icon-iset: 0 0 0 auto;
}

/* ── Switch sólido ────────────────────────────────────────────────────────── */
/*? El .__switch del core deja el mismo color de fondo apagado y encendido
   (--upaep-checkbox-checked-bg = --ui-border), así que solo se movía el
   pulsador y no se distinguía el estado.

   Aquí va sólido en los dos estados: el riel se rellena —gris apagado, de
   acento encendido— y el pulsador se queda siempre del color de la superficie.
   Así lo que se lee es el color del riel, no un contorno fino. */
.upaep__questor,
.upaep__questor-form {
    --upaep-questor-switch-width: 30px;
    --upaep-questor-switch-height: 16px;
}

.upaep__questor .upaep__checkbox.__switch,
.upaep__questor-form .upaep__checkbox.__switch {
    --upaep-checkbox-width: var(--upaep-questor-switch-width);
    --upaep-checkbox-height: var(--upaep-questor-switch-height);
    --upaep-checkbox-border-size: 2px;
    /*? El borde va del color del riel: la caja se ve maciza y deja al pulsador
       un margen interior sin tener que tocar su geometría. */
    --upaep-checkbox-border-color: var(--upaep-questor-border);
    --upaep-checkbox-bg: var(--upaep-questor-border);
    --upaep-checkbox-hover-bg: var(--upaep-questor-border);
    --upaep-checkbox-focus-bg: var(--upaep-questor-border);
    --upaep-checkbox-active-bg: var(--upaep-questor-border);
    --upaep-checkbox-checked-bg: var(--upaep-questor-border);
    --upaep-checkbox-checked-color: var(--upaep-questor-card-bg);
    --upaep-checkbox-margin: 0;
    flex: 0 0 auto;
    transition:
        background var(--upaep-questor-duration) var(--upaep-questor-easing),
        border-color var(--upaep-questor-duration) var(--upaep-questor-easing);

    /*? El desplazamiento del pulsador es del core (::before con
       `transition: all .25s` y `transform: translateX(100%)` al marcarse). Aquí
       solo se corrige la forma y se acota la transición:

       - width:50% sobre 16px de alto sale ovalado; con el ancho derivado del
         alto queda redondo, y translateX(100%) sigue moviéndolo justo su propio
         ancho, así que recorre el riel de extremo a extremo.
       - el `.25s` del core está fijo y se salta prefers-reduced-motion; con la
         duración del componente pasa a 0s cuando el sistema lo pide.
       - `background` sigue en la lista porque el pulsador cambia de color entre
         --ui-surface y --ui-on-primary: en UPAEP los dos son blancos, pero en
         una marca donde difieran el color daría un salto sin ella. */
    &::before {
        width: auto;
        aspect-ratio: 1;
        transition:
            transform var(--upaep-questor-duration) var(--upaep-questor-easing),
            background var(--upaep-questor-duration) var(--upaep-questor-easing);
    }

    &:hover:not(:disabled) {
        --upaep-checkbox-border-color: var(--upaep-questor-muted);
        --upaep-checkbox-bg: var(--upaep-questor-muted);
        --upaep-checkbox-hover-bg: var(--upaep-questor-muted);
    }
}

/*? Encendido: el riel completo toma el acento */
.upaep__questor .upaep__checkbox.__switch:checked,
.upaep__questor-form .upaep__checkbox.__switch:checked {
    --upaep-checkbox-border-color: var(--upaep-questor-accent);
    --upaep-checkbox-bg: var(--upaep-questor-accent);
    --upaep-checkbox-hover-bg: var(--upaep-questor-accent);
    --upaep-checkbox-focus-bg: var(--upaep-questor-accent);
    --upaep-checkbox-active-bg: var(--upaep-questor-accent);
    --upaep-checkbox-checked-bg: var(--upaep-questor-accent);
    --upaep-checkbox-checked-color: var(--upaep-questor-on-accent);
}

.upaep__questor .upaep__checkbox.__switch:checked:hover:not(:disabled),
.upaep__questor-form .upaep__checkbox.__switch:checked:hover:not(:disabled) {
    --upaep-checkbox-border-color: var(--ui-primary-hover, var(--upaep-questor-accent));
    --upaep-checkbox-bg: var(--ui-primary-hover, var(--upaep-questor-accent));
    --upaep-checkbox-hover-bg: var(--ui-primary-hover, var(--upaep-questor-accent));
}

/* ── El constructor ───────────────────────────────────────────────────────── */
.upaep__questor {
    position: relative;
    /* ancla del aviso de deshacer */
    display: flex;
    flex-direction: column;
    gap: var(--upaep-questor-gap);
    background: var(--upaep-questor-bg);
    border-radius: var(--upaep-questor-radius);
    padding: var(--upaep-questor-pad);
}

/* ── Barra de herramientas ────────────────────────────────────────────────── */
/*? La barra ocupa todo el ancho (su fondo tapa lo que pasa por debajo cuando
   está fija) pero su CONTENIDO se ceñe al mismo ancho que las tarjetas: si no,
   los botones arrancan pegados al borde y las tarjetas van centradas, y la
   barra parece de otra página. */
.upaep__questor-toolbar {
    padding-bottom: var(--upaep-questor-toolbar-pad);
    border-bottom: 1px solid var(--upaep-questor-divider);
}

/*? UNA SOLA FILA, siempre. Con `wrap` las tres piezas (pestañas + herramientas +
   acciones) miden más que el ancho de las tarjetas y la barra se partía en tres
   filas: pegada abajo se comía un tercio de la pantalla y dejaba de leerse como
   una barra. Si aun así no cabe, lo que se desplaza son las herramientas, no la
   barra entera. */
.upaep__questor-toolbar-inner {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: .75rem;
    width: 100%;
    max-width: var(--upaep-questor-max-width);
    margin-inline: auto;
}

/*? Las piezas de los extremos no se encogen ni se parten */
.upaep__questor-toolbar-inner>.upaep__questor-tabs,
.upaep__questor-toolbar-inner>.upaep__questor-actions {
    flex: 0 0 auto;
    flex-wrap: nowrap;
}

/*? Abajo: se reordena con `order` en vez de mover el nodo, para no romper el
   orden del DOM ni el recorrido con el tabulador. */
.upaep__questor.__toolbar-bottom .upaep__questor-toolbar {
    order: 99;
    padding-bottom: 0;
    padding-top: var(--upaep-questor-toolbar-pad);
    border-bottom: 0;
    border-top: 1px solid var(--upaep-questor-divider);
}

/*? Fija (por defecto): se pega arriba al hacer scroll. Los márgenes negativos la
   sacan del relleno del contenedor para que nada asome por los lados al pasar.
   `--upaep-questor-sticky-top` la baja lo que ocupe la cabecera de la página
   (el JS lo publica desde la opción stickyOffset). */
/*? Fija: sin fondo mientras está en su sitio (el componente no pinta nada), y
   solo al despegarse toma una superficie opaca — sin ella no se leería sobre el
   contenido que le pasa por debajo. */
/*? Se pega al borde al desplazar. Lo COMÚN a los dos bordes va aquí; el offset
   se aplica solo al borde que toca, más abajo.

   Se usa `inset-block-start` / `inset-block-end` y NO el atajo `inset`: en un
   elemento sticky, poner los dos desplazamientos verticales a la vez lo deja
   atrapado entre ambos (y por las reglas de sobrerrestricción manda el de
   arriba), así que con `inset` nunca se conseguiría el pegado inferior. */
.upaep__questor.__toolbar-sticky .upaep__questor-toolbar {
    position: sticky;
    z-index: var(--upaep-questor-z-sticky);
    /*? Los márgenes negativos la llevan hasta los bordes del componente, para
       que al pasar el contenido por debajo no asome por los lados. Con el
       relleno en 0 (por defecto) no hay nada de lo que escapar. */
    margin-inline: calc(var(--upaep-questor-pad) * -1);
    background: transparent;
    transition:
        background var(--upaep-questor-duration) var(--upaep-questor-easing),
        box-shadow var(--upaep-questor-duration) var(--upaep-questor-easing),
        border-color var(--upaep-questor-duration) var(--upaep-questor-easing);
}

/*? El relleno vertical es SUYO, no el del componente: desde que el lienzo dejó
   de tener relleno propio (--upaep-questor-pad: 0), la barra se quedaba pegada
   al borde por el lado por el que se fija. Al borde fijado se le suma el
   relleno del contenedor, que el margen negativo se acaba de llevar. */
.upaep__questor.__toolbar-sticky:not(.__toolbar-bottom) .upaep__questor-toolbar {
    inset-block-start: var(--upaep-questor-sticky-top);
    margin-block-start: calc(var(--upaep-questor-pad) * -1);
    padding-block: calc(var(--upaep-questor-pad) + var(--upaep-questor-toolbar-pad)) var(--upaep-questor-toolbar-pad);
    padding-inline: var(--upaep-questor-pad);
    border-radius: var(--upaep-questor-radius) var(--upaep-questor-radius) 0 0;
}

/*? Pegada ABAJO. Funciona porque `__toolbar-bottom` ya la manda al final del
   flujo con `order`: un sticky con inset-block-end solo se pega dentro de su
   sitio en el flujo, así que si estuviera al principio flotaría desde el
   arranque. */
.upaep__questor.__toolbar-sticky.__toolbar-bottom .upaep__questor-toolbar {
    inset-block-end: var(--upaep-questor-sticky-bottom);
    margin-block-end: calc(var(--upaep-questor-pad) * -1);
    padding-block: var(--upaep-questor-toolbar-pad) calc(var(--upaep-questor-pad) + var(--upaep-questor-toolbar-pad));
    padding-inline: var(--upaep-questor-pad);
    border-radius: 0 0 var(--upaep-questor-radius) var(--upaep-questor-radius);
}

/*? La sombra solo cuando de verdad está despegada de su sitio: si fuera
   permanente se vería como una franja sombreada sin motivo. Lo marca el JS con
   un centinela (IntersectionObserver).

   No se usa --ui-shadow: es una sombra de tarjeta, con desplazamiento lateral y
   mucha opacidad, y en una franja de lado a lado se veía como un borde sucio.
   Aquí va una caída recta y muy difusa, que es lo que hace legible el corte
   entre la barra y lo que pasa por debajo. Además se cuadran las esquinas:
   redondeadas y pegadas al borde de la ventana quedaban raras. */
.upaep__questor.__toolbar-sticky.is-stuck .upaep__questor-toolbar {
    background: var(--upaep-questor-sticky-bg);
    border-radius: 0;
    /*? Al despegarse necesita su propio aire: en su sitio lo daba el
       contenedor. */
    padding-inline: .5rem;
}

/*? La sombra cae hacia el lado del contenido, así que se invierte según el
   borde por el que esté pegada. */
.upaep__questor.__toolbar-sticky.is-stuck:not(.__toolbar-bottom) .upaep__questor-toolbar {
    box-shadow: var(--upaep-questor-sticky-shadow);
    border-block-end-color: var(--upaep-questor-divider);
}

.upaep__questor.__toolbar-sticky.is-stuck.__toolbar-bottom .upaep__questor-toolbar {
    box-shadow: var(--upaep-questor-sticky-shadow-up);
    border-block-start-color: var(--upaep-questor-divider);
}

/*? Nodos de alto cero a cada lado de la barra: sirven de referencia para saber
   si ya se despegó. No ocupan nada ni se leen. Hace falta uno por borde, porque
   el que vigila está siempre al OTRO lado de la barra. */
.upaep__questor-sentinel {
    display: block;
    height: 0;
    margin: 0;
    pointer-events: none;
}

/*? Último también a la vista: la barra de abajo usa `order: 99`, así que el
   centinela inferior tiene que ir por detrás de ella. */
.upaep__questor-sentinel.__bottom {
    order: 100;
}

/* ── Fondo que viaja ──────────────────────────────────────────────────────── */
/*? En vez de un fondo por botón hay un solo nodo que se desplaza al destino. El
   JS solo publica las medidas en variables; el movimiento es CSS. */
.upaep__questor-slider {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 0; /*? apilado LOCAL: detrás de las pestañas, no es un overlay */
    width: var(--upaep-questor-slider-w, 0);
    height: var(--upaep-questor-slider-h, 0);
    translate: var(--upaep-questor-slider-x, 0) var(--upaep-questor-slider-y, 0);
    border-radius: 999px;
    opacity: 0;
    pointer-events: none;
    transition:
        translate var(--upaep-questor-duration) var(--upaep-questor-easing),
        width var(--upaep-questor-duration) var(--upaep-questor-easing),
        height var(--upaep-questor-duration) var(--upaep-questor-easing),
        opacity var(--upaep-questor-duration) var(--upaep-questor-easing);
}

.is-sliding>.upaep__questor-slider {
    opacity: 1;
}

.upaep__questor-tabs {
    position: relative;
    display: flex;
    align-items: center;
    gap: .25rem;
    background: var(--upaep-questor-card-bg);
    border: 1px solid var(--upaep-questor-border);
    border-radius: 999px;
    padding: .25rem;
}

/*? En las pestañas el fondo viajero ES la pastilla de acento: se mueve de
   "Editar" a "Vista previa" al cambiar de modo. */
.upaep__questor-tabs>.upaep__questor-slider {
    background: var(--upaep-questor-accent);
}

.upaep__questor-tab {
    position: relative;
    z-index: 1; /*? apilado LOCAL: por delante del fondo deslizante */
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    padding: .4rem .9rem;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--upaep-questor-muted);
    font: inherit;
    line-height: 1;
    cursor: pointer;
    transition: color var(--upaep-questor-duration) var(--upaep-questor-easing);

    /*? Un SVG inline no tiene ancho intrínseco: sin medidas se estira o se
       encoge a cero dentro de un flex. Siempre flex + width + height. */
    & svg {
        flex: 0 0 auto;
        width: 1.05em;
        height: 1.05em;
    }

    &:hover {
        color: var(--upaep-questor-color);
    }
}

.upaep__questor-tab.is-active {
    color: var(--upaep-questor-on-accent);
}

/*? Respaldo si el JS aún no ha medido (primer pintado, o sin JS): la pestaña
   activa lleva su propio fondo hasta que el deslizador aparece. */
.upaep__questor-tabs:not(.is-sliding) .upaep__questor-tab.is-active {
    background: var(--upaep-questor-accent);
}

/* ── Herramientas: añadir pregunta / bloques, importar y exportar ─────────── */
/*? Sin fondo viajero: cada botón se realza al pasar por encima. Un realce que
   se desplaza queda bonito pero en una barra ancha, o con la vista a medio
   scroll, no siempre se ve de dónde viene ni sobre qué botón está. */
/*? `flex: 0 1 auto` y NO `1 1 auto`: si las herramientas se quedaban con todo el
   espacio libre, el slot de acciones (que va con margin-inline-start: auto)
   caía a una segunda fila él solo. */
.upaep__questor-tools {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: var(--upaep-questor-tool-gap);
    /*? Se queda con el espacio que sobra y, si no alcanza, se desplaza en
       horizontal. Es la única pieza que puede encogerse. */
    flex: 1 1 auto;
    min-width: 0;
    overflow-x: auto;
    transition: opacity var(--upaep-questor-duration) var(--upaep-questor-easing);
}

/*? En vista previa las herramientas no aplican: se apagan sin mover el layout */
.upaep__questor-tools.is-hidden {
    opacity: 0;
    pointer-events: none;
}

.upaep__questor-sep {
    width: 1px;
    height: 22px;
    margin-inline: .375rem;
    background: var(--upaep-questor-divider);
}

/*? Botón de texto con icono: minimalista, sin la caja de .upaep__btn (que
   además fija un ancho de 130px en su variante pequeña). Icono y texto
   comparten color: un "+" de acento sobre texto gris se ve descosido. */
.upaep__questor-tool,
.upaep__questor-action {
    position: relative;
    z-index: 1; /*? apilado LOCAL: por delante del fondo deslizante */
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .4rem .7rem;
    border: 1px solid transparent;
    border-radius: 8px;
    background: transparent;
    color: var(--upaep-questor-muted);
    font: inherit;
    font-size: var(--upaep-fz14);
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    transition:
        background var(--upaep-questor-duration) var(--upaep-questor-easing),
        border-color var(--upaep-questor-duration) var(--upaep-questor-easing),
        color var(--upaep-questor-duration) var(--upaep-questor-easing),
        transform var(--upaep-questor-duration) var(--upaep-questor-easing);

    & svg {
        flex: 0 0 auto;
        width: 1.15em;
        height: 1.15em;
        color: inherit;
    }

    &:hover:not(:disabled) {
        color: var(--upaep-questor-color);
    }

    &:active:not(:disabled) {
        transform: scale(.96);
    }

    &:disabled {
        opacity: .4;
        cursor: not-allowed;
    }
}

/*? Los botones de la barra se realzan con fondo propio: es lo que deja claro
   sobre cuál está el puntero. */
.upaep__questor-tool:hover:not(:disabled) {
    background: var(--upaep-questor-card-bg);
    border-color: var(--upaep-questor-divider);
    color: var(--upaep-questor-color);
}

/*? Los de dentro de la tarjeta llevan contorno para que se lean como botones
   sin depender de un fondo de color. */
.upaep__questor-action {
    border-color: var(--upaep-questor-divider);

    &:hover:not(:disabled) {
        border-color: var(--upaep-questor-accent);
        color: var(--upaep-questor-accent);
        background: transparent;
    }
}

/*? Solo la acción principal lleva texto; el resto van como iconos con tooltip.
   Con las ocho etiquetas la fila medía ~1115px y no cabía en el ancho de las
   tarjetas. Es además lo que hace que se lea como una barra de herramientas y no
   como una fila de botones. El nombre accesible no se pierde: todos llevan
   `aria-label` y `title`, y el aria-label gana sobre el texto oculto.
   Con `.upaep__questor.__tools-labels` se recuperan las etiquetas. */
.upaep__questor:not(.__tools-labels) .upaep__questor-tool:not([data-primary]) {
    /*? Caja CUADRADA y fija, no relleno simétrico: con `padding` el botón medía
       lo que midiera su glifo y quedaban desparejos y aireados. */
    width: var(--upaep-questor-tool-size);
    height: var(--upaep-questor-tool-size);
    flex: 0 0 auto;
    justify-content: center;
    padding: 0;
    gap: 0;

    &>span {
        display: none;
    }

    & svg {
        width: var(--upaep-questor-tool-icon);
        height: var(--upaep-questor-tool-icon);
    }
}

/*? El botón principal (añadir pregunta) va resaltado y SIEMPRE al extremo
   derecho del grupo: es la acción que más se repite, y separada del resto se
   distingue de las de insertar. Se coloca con `order` + margen automático, no
   moviéndolo en el HTML: así el orden del DOM y el del tabulador no cambian. */
.upaep__questor-tool[data-primary] {
    order: 1;
    margin-inline-start: auto;
    background: var(--upaep-questor-accent);
    color: var(--upaep-questor-on-accent);

    &:hover:not(:disabled) {
        background: var(--ui-primary-hover, var(--upaep-questor-accent));
        color: var(--upaep-questor-on-accent);
    }
}

/*? Sobre la superficie invertida del aviso de deshacer. El realce se deriva del
   propio color de texto: no hay rol translúcido en el kit y así funciona con
   cualquier marca sin escribir un literal. */
.upaep__questor-action.__on-dark {
    color: var(--ui-on-surface-inverse, var(--upaep-color-white, #fff));

    &:hover:not(:disabled) {
        background: color-mix(in srgb, currentColor 18%, transparent);
        color: var(--ui-on-surface-inverse, var(--upaep-color-white, #fff));
    }
}

.upaep__questor-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .5rem;
    margin-inline-start: auto;
}

/* ── Lienzo de edición y panel de vista previa ────────────────────────────── */
.upaep__questor-canvas,
.upaep__questor-preview {
    flex-direction: column;
    gap: var(--upaep-questor-gap);
    width: 100%;
    max-width: var(--upaep-questor-max-width);
    margin-inline: auto;
}

/*? El panel de vista previa recibe además la clase .upaep__questor-form (es un
   QuestorForm): estas reglas van con más peso para que gane el estado. */
.upaep__questor>.upaep__questor-canvas,
.upaep__questor>.upaep__questor-preview {
    display: none;
}

.upaep__questor>.upaep__questor-canvas.is-show,
.upaep__questor>.upaep__questor-preview.is-show {
    display: flex;
}

/*? La vista previa entra con un fundido corto: deja claro que es otra capa */
.upaep__questor>.upaep__questor-preview.is-show {
    animation: upaepQuestorFadeIn var(--upaep-questor-duration) var(--upaep-questor-easing) both;
}

@keyframes upaepQuestorFadeIn {
    from {
        opacity: 0;
        translate: 0 8px;
    }

    to {
        opacity: 1;
        translate: 0 0;
    }
}

/* ── Cabecera del formulario (título + descripción) ───────────────────────── */
.upaep__questor-header {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    position: relative;
    background: var(--upaep-questor-card-bg);
    border: 1px solid var(--upaep-questor-card-border);
    border-radius: var(--upaep-questor-radius);
    box-shadow: var(--upaep-questor-card-shadow);
    padding: var(--upaep-questor-padding);
    padding-block-start: calc(var(--upaep-questor-padding) + var(--upaep-questor-marker));
}

/*? Franja de acento superior, como pseudoelemento: un border-top haría que la
   caja midiera distinto que las tarjetas. Se redondea a sí misma en vez de
   recortarse con overflow, que aquí también atraparía paneles flotantes. */
.upaep__questor-header::before,
.upaep__questor-form-header::before {
    content: '';
    position: absolute;
    inset: 0 0 auto 0;
    height: var(--upaep-questor-marker);
    border-start-start-radius: var(--upaep-questor-radius);
    border-start-end-radius: var(--upaep-questor-radius);
    background: var(--upaep-questor-accent);
}

/*? Campos que se ven como texto hasta que se enfocan. Se apoyan en la variante
   .__underline del core y solo afinan sus variables. */
.upaep__questor-form-name,
.upaep__questor-form-help,
.upaep__questor-question,
.upaep__questor-card-help,
.upaep__questor-option-input,
.upaep__questor-other {
    /*? El grosor NO cambia nunca: solo el color. Antes el foco lo indicaba una
       box-shadow a 2px por debajo del borde, y quedaba una línea despegada que
       parecía un salto; y variar el grosor movería el texto 1px. */
    --upaep-input-border-bottom-size: 2px;
    --upaep-input-border-bottom-color: transparent;
    --upaep-input-focus-boxshadow: none;
    --upaep-input-padding: .3rem 0;
    --upaep-input-margin: 0;
    --upaep-input-bg: transparent;
    --upaep-input-hover-bg: transparent;
    --upaep-input-focus-bg: transparent;
    resize: none;
    transition: border-color var(--upaep-questor-duration) var(--upaep-questor-easing);

    &:hover:not(:focus) {
        --upaep-input-border-bottom-color: var(--upaep-questor-divider);
    }

    &:focus {
        --upaep-input-border-bottom-color: var(--upaep-questor-accent);
    }
}

.upaep__questor-form-name {
    --upaep-input-fz: var(--upaep-fz28);
    --upaep-input-fw: var(--upaep-fw-bold);
}

.upaep__questor-form-help {
    --upaep-input-fz: var(--upaep-fz14);
    --upaep-input-color: var(--upaep-questor-muted);
}

/*? Descripciones: arrancan en una línea y crecen con el contenido (lo mide el
   JS con growAll()). Sin scroll interno ni agarradera de redimensionado. */
.upaep__questor-form-help,
.upaep__questor-card-help {
    --upaep-input-height: auto;
    display: block;
    overflow: hidden;
    min-height: calc(1.5em + .6rem);
    line-height: 1.5;
}

/* ── Lista de elementos ───────────────────────────────────────────────────── */
.upaep__questor-list {
    display: flex;
    flex-direction: column;
    gap: var(--upaep-questor-gap);
}

.upaep__questor-empty {
    margin: 0;
    padding: calc(var(--upaep-questor-padding) * 1.5);
    background: var(--upaep-questor-card-bg);
    border: 1px dashed var(--upaep-questor-border);
    border-radius: var(--upaep-questor-radius);
    color: var(--upaep-questor-muted);
    text-align: center;
}

/* ── Tarjeta de elemento ──────────────────────────────────────────────────── */
/*? Sin `overflow: hidden`: recortaba los paneles flotantes de los componentes
   envueltos (el calendario del datepicker salía DENTRO de la tarjeta). El
   marcador lateral se redondea por sí mismo en vez de recortarse. */
.upaep__questor-card {
    position: relative;
    background: var(--upaep-questor-card-bg);
    border: 1px solid var(--upaep-questor-card-border);
    border-radius: var(--upaep-questor-radius);
    box-shadow: var(--upaep-questor-card-shadow);
    padding: var(--upaep-questor-padding);
    padding-inline-start: calc(var(--upaep-questor-padding) + var(--upaep-questor-marker));
    transition:
        box-shadow var(--upaep-questor-duration) var(--upaep-questor-easing),
        border-color var(--upaep-questor-duration) var(--upaep-questor-easing);
}

/*? El marcador lateral es un pseudoelemento, no un border-left transparente:
   así la tarjeta inactiva no muestra una franja clara contra el lienzo. */
.upaep__questor-card::before {
    content: '';
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width: var(--upaep-questor-marker);
    border-start-start-radius: var(--upaep-questor-radius);
    border-end-start-radius: var(--upaep-questor-radius);
    background: var(--upaep-questor-accent);
    opacity: 0;
    transition: opacity var(--upaep-questor-duration) var(--upaep-questor-easing);
}

.upaep__questor-card.is-active::before {
    opacity: 1;
}

.upaep__questor-card:hover {
    box-shadow: var(--upaep-questor-card-hover-shadow, var(--upaep-questor-card-shadow));
}

.upaep__questor-card.is-active {
    border-color: var(--upaep-questor-border);
}

/*? Mientras se arrastra: la tarjeta se despega y el resto se aparta */
.upaep__questor-card.is-dragging {
    opacity: .45;
    scale: .99;
}

.upaep__questor-list.is-sorting .upaep__questor-card {
    transition: box-shadow var(--upaep-questor-duration) var(--upaep-questor-easing);
    cursor: grabbing;
}

/*? Asa de arrastre: centrada arriba, aparece al acercarse a la tarjeta */
.upaep__questor-grip {
    position: absolute;
    top: .25rem;
    left: 50%;
    translate: -50% 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 18px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--upaep-questor-border);
    cursor: grab;
    opacity: 0;
    transition:
        opacity var(--upaep-questor-duration) var(--upaep-questor-easing),
        color var(--upaep-questor-duration) var(--upaep-questor-easing);

    & svg {
        flex: 0 0 auto;
        width: 18px;
        height: 18px;
        rotate: 90deg;
    }

    &:hover {
        color: var(--upaep-questor-accent);
    }

    &:active {
        cursor: grabbing;
    }
}

.upaep__questor-card:hover .upaep__questor-grip,
.upaep__questor-card.is-active .upaep__questor-grip,
.upaep__questor-grip:focus-visible {
    opacity: 1;
}

/* ── Plegado animado ──────────────────────────────────────────────────────── */
/*? Truco de rejilla 1fr → 0fr: es lo único que anima una altura "auto" sin
   medirla con JS. El hijo directo recorta el desbordamiento mientras encoge. */
.upaep__questor-fold {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows var(--upaep-questor-duration) var(--upaep-questor-easing);
}

.upaep__questor-fold>* {
    overflow: hidden;
    min-height: 0;
}

/*? Tarjeta ya abierta: se levanta el recorte. Mientras crece hace falta para que
   el contenido no se desborde, pero una vez quieta tiene que dejar salir los
   paneles flotantes de los componentes de dentro (el desplegable de un
   selectpicker, el calendario de un datepicker), que si no se ven cortados por
   el borde de la tarjeta. Lo marca el JS al terminar la animación. */
.upaep__questor-fold.is-expanded>* {
    overflow: visible;
}

.upaep__questor-fold.__editor>* {
    display: flex;
    flex-direction: column;
    gap: .85rem;
}

/*? Expandida: se esconde el resumen. Plegada: se esconde el editor. */
.upaep__questor-card.is-active .upaep__questor-fold.__summary,
.upaep__questor.__collapse .upaep__questor-card:not(.is-active) .upaep__questor-fold.__editor {
    grid-template-rows: 0fr;
}

/*? El contenido se desvanece mientras encoge, para que no se vea "cortado" */
.upaep__questor-fold>* {
    transition: opacity var(--upaep-questor-duration) var(--upaep-questor-easing);
}

.upaep__questor-card.is-active .upaep__questor-fold.__summary>*,
.upaep__questor.__collapse .upaep__questor-card:not(.is-active) .upaep__questor-fold.__editor>* {
    opacity: 0;
}

/* ── Resumen (tarjeta plegada) ────────────────────────────────────────────── */
.upaep__questor-summary {
    display: flex;
    align-items: center;
    gap: .625rem;
    cursor: pointer;
}

.upaep__questor-summary-icon {
    display: inline-flex;
    color: var(--upaep-questor-muted);

    & svg {
        flex: 0 0 auto;
        width: var(--upaep-questor-icon);
        height: var(--upaep-questor-icon);
    }
}

.upaep__questor-summary-title {
    flex: 1 1 auto;
    min-width: 0;
    font-weight: var(--upaep-fw-medium, 500);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.upaep__questor-chip {
    flex: 0 0 auto;
    padding: .2rem .625rem;
    border: 1px solid var(--upaep-questor-divider);
    border-radius: 999px;
    color: var(--upaep-questor-muted);
    font-size: var(--upaep-fz12);
    white-space: nowrap;
}

/* ── Encabezado editable del elemento ─────────────────────────────────────── */
.upaep__questor-card-head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(190px, 270px);
    align-items: center;
    gap: 1rem;
}

.upaep__questor-question {
    --upaep-input-fz: var(--upaep-fz16);
    --upaep-input-fw: var(--upaep-fw-medium, 500);
}

.upaep__questor-card-help {
    --upaep-input-fz: var(--upaep-fz14);
    --upaep-input-color: var(--upaep-questor-muted);
}

/*? Selector de tipo: icono en su propia caja, con aire, para que no se lea
   como una mancha pegada al select. */
.upaep__questor-type {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: .5rem;
}

.upaep__questor-type-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: 1px solid var(--upaep-questor-divider);
    border-radius: 8px;
    color: var(--upaep-questor-accent);

    & svg {
        flex: 0 0 auto;
        width: var(--upaep-questor-icon);
        height: var(--upaep-questor-icon);
    }
}

.upaep__questor-type .upaep__select {
    --upaep-select-margin: 0;
    --upaep-select-fz: var(--upaep-fz14);
}

/*? Con typePicker: 'selectpicker' el componente envuelve al <select> y mete su
   propio contenedor en la rejilla: tiene que estirarse igual que el nativo. */
.upaep__questor-type .upaep__selectpicker {
    width: 100%;
    min-width: 0;

    & .upaep__btn {
        --upaep-btn-width: 100%;
        --upaep-btn-margin: 0;
        --upaep-btn-fz: var(--upaep-fz14);
    }
}

/*? Cuerpo de la tarjeta: opciones + ajustes. Vacío no debe dejar hueco en el
   flex del editor. */
.upaep__questor-card-body {
    display: flex;
    flex-direction: column;
    gap: .75rem;

    &:empty {
        display: none;
    }
}

/* ── Editor de opciones ───────────────────────────────────────────────────── */
.upaep__questor-options {
    display: flex;
    flex-direction: column;
    gap: .375rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.upaep__questor-option {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: .625rem;
}

/*? La marca imita el control que verá quien responde (círculo, cuadro o número) */
.upaep__questor-option-mark {
    width: 18px;
    height: 18px;
    border: 2px solid var(--upaep-questor-border);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--upaep-questor-muted);
    font-size: var(--upaep-fz12);
}

.upaep__questor-option-mark.__circle {
    border-radius: 50%;
}

.upaep__questor-option-mark.__square {
    border-radius: 4px;
}

.upaep__questor-option-mark.__number {
    border: 0;
}

/*? Con etiqueta y valor por separado (escala con textos propios) la fila crece
   a cuatro columnas y el valor va más estrecho. */
.upaep__questor-option.__with-value {
    grid-template-columns: auto minmax(0, 1fr) minmax(70px, .45fr) auto;
}

.upaep__questor-option-input,
.upaep__questor-option-value {
    --upaep-input-fz: var(--upaep-fz14);
}

.upaep__questor-option-value {
    --upaep-input-color: var(--upaep-questor-muted);
    font-variant-numeric: tabular-nums;
}

.upaep__questor-option-fixed {
    color: var(--upaep-questor-muted);
    font-size: var(--upaep-fz14);
}

/*? Sin margen negativo: el editor plegable recorta su contenido, así que
   cualquier cosa que se salga del área se ve cortada por el borde. */
.upaep__questor-option-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .375rem;
    margin-top: .5rem;
}

/* ── Una lista editable (opciones, o filas y columnas de una cuadrícula) ───── */
.upaep__questor-list-editor {
    display: flex;
    flex-direction: column;
    gap: .375rem;
}

.upaep__questor-list-title {
    --upaep-label-fz: var(--upaep-fz12);
    --upaep-label-margin: 0;
    --upaep-label-padding: 0;
    color: var(--upaep-questor-muted);
    text-transform: uppercase;
    letter-spacing: .04em;
}

/* ── Ajustes propios de cada tipo (settings) ──────────────────────────────── */
.upaep__questor-settings {
    display: flex;
    flex-wrap: wrap;
    gap: .875rem;
    padding-top: .875rem;
    border-top: 1px dashed var(--upaep-questor-divider);
}

.upaep__questor-settings:first-child {
    padding-top: 0;
    border-top: 0;
}

.upaep__questor-setting {
    display: flex;
    flex-direction: column;
    gap: .2rem;
    min-width: 150px;
    flex: 1 1 150px;

    & .upaep__label {
        --upaep-label-fz: var(--upaep-fz12);
        --upaep-label-margin: 0;
        --upaep-label-padding: 0;
        color: var(--upaep-questor-muted);
    }

    & .upaep__input,
    & .upaep__select {
        --upaep-input-margin: 0;
        --upaep-select-margin: 0;
        --upaep-input-fz: var(--upaep-fz14);
        --upaep-select-fz: var(--upaep-fz14);
    }
}

/*? El interruptor va con su etiqueta al lado, no encima */
.upaep__questor-setting.__switch {
    flex-direction: row-reverse;
    align-items: center;
    justify-content: flex-end;
    gap: .625rem;
    flex: 0 0 auto;

    & .upaep__label {
        --upaep-label-fz: var(--upaep-fz14);
        color: var(--upaep-questor-color);
        cursor: pointer;
    }
}

/*? Los ajustes que necesitan toda la fila (listas, textos largos, archivos) */
.upaep__questor-setting.__wide {
    flex: 1 1 100%;
}

.upaep__questor-hint {
    color: var(--upaep-questor-muted);
    font-size: var(--upaep-fz12);
    line-height: 1.4;
}

/* ── Ajuste tipo lista de casillas ────────────────────────────────────────── */
.upaep__questor-checks {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: .25rem .75rem;
    padding: .5rem .625rem;
    border: 1px solid var(--upaep-questor-divider);
    border-radius: var(--upaep-questor-control-radius);
    max-height: 190px;
    overflow-y: auto;
}

.upaep__questor-check {
    align-items: center;
    gap: .5rem;

    & .upaep__label {
        --upaep-label-fz: var(--upaep-fz14);
        cursor: pointer;
    }

    & .upaep__checkbox {
        --upaep-checkbox-margin: 0;
    }
}

/* ── Ajuste tipo archivo ──────────────────────────────────────────────────── */
.upaep__questor-file-field {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
}

.upaep__questor-file-state {
    color: var(--upaep-questor-muted);
    font-size: var(--upaep-fz12);
}

/* ── Pie de la tarjeta ────────────────────────────────────────────────────── */
.upaep__questor-card-foot {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: .25rem;
    padding-top: .875rem;
    border-top: 1px solid var(--upaep-questor-divider);
}

.upaep__questor-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--upaep-questor-icon-btn);
    height: var(--upaep-questor-icon-btn);
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--upaep-questor-muted);
    cursor: pointer;
    transition:
        background var(--upaep-questor-duration) var(--upaep-questor-easing),
        color var(--upaep-questor-duration) var(--upaep-questor-easing),
        transform var(--upaep-questor-duration) var(--upaep-questor-easing);

    & svg {
        flex: 0 0 auto;
        width: 18px;
        height: 18px;
    }

    &:hover:not(:disabled) {
        background: var(--ui-surface-hover, var(--upaep-questor-subtle));
        color: var(--upaep-questor-color);
    }

    &:active:not(:disabled) {
        transform: scale(.9);
    }

    &:disabled {
        opacity: .4;
        cursor: not-allowed;
    }
}

.upaep__questor-icon-btn.__sm {
    --upaep-questor-icon-btn: 28px;

    & svg {
        width: 15px;
        height: 15px;
    }
}

.upaep__questor-icon-btn.__danger:hover:not(:disabled) {
    background: var(--ui-danger-subtle, transparent);
    color: var(--upaep-questor-danger);
}

.upaep__questor-required-toggle {
    align-items: center;
    gap: .5rem;
    margin-inline-start: .5rem;
    padding-inline-start: .875rem;
    border-inline-start: 1px solid var(--upaep-questor-divider);

    & .upaep__label {
        --upaep-label-fz: var(--upaep-fz14);
        white-space: nowrap;
    }
}

/* ── Aviso de deshacer ────────────────────────────────────────────────────── */
/*? Fuera del flujo: si ocupara sitio dejaría un hueco permanente al pie del
   componente cuando está oculto. Se ancla al contenedor, no al viewport. */
.upaep__questor-undo {
    position: absolute;
    left: 50%;
    /*? Con la barra abajo el JS sube el aviso justo lo que mide la barra */
    bottom: calc(1rem + var(--upaep-questor-undo-offset, 0px));
    z-index: var(--upaep-questor-z-undo);
    display: flex;
    align-items: center;
    gap: 1rem;
    max-width: calc(100% - 2rem);
    padding: .5rem .5rem .5rem 1rem;
    border-radius: 999px;
    background: var(--ui-surface-inverse, var(--upaep-color-dark-grey));
    color: var(--ui-on-surface-inverse, var(--upaep-color-white, #fff));
    box-shadow: var(--ui-shadow);
    font-size: var(--upaep-fz14);
    opacity: 0;
    visibility: hidden;
    transform: translateX(-50%) translateY(1rem);
    transition:
        opacity var(--upaep-questor-duration) var(--upaep-questor-easing),
        transform var(--upaep-questor-duration) var(--upaep-questor-easing),
        visibility 0s var(--upaep-questor-duration);
}

.upaep__questor-undo.is-show {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
    transition-delay: 0s;
}

/*? El input de importar no se ve nunca: lo dispara el botón de la barra */
.upaep__questor-file {
    display: none;
}

.upaep__questor-undo-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── Formulario contestable (QuestorForm) ─────────────────────────────────── */
.upaep__questor-form {
    display: flex;
    flex-direction: column;
    gap: var(--upaep-questor-gap);
    width: 100%;
}

.upaep__questor-form-header {
    position: relative;
    background: var(--upaep-questor-card-bg);
    border: 1px solid var(--upaep-questor-card-border);
    border-radius: var(--upaep-questor-radius);
    box-shadow: var(--upaep-questor-card-shadow);
    padding: calc(var(--upaep-questor-padding) * 1.2);
    padding-block-start: calc(var(--upaep-questor-padding) * 1.2 + var(--upaep-questor-marker));
}

.upaep__questor-form-title {
    margin: 0;
    font-family: var(--ui-font-heading, var(--upaep-ff-fira-sans));
    font-size: var(--upaep-fz28);
    font-weight: var(--upaep-fw-bold);
    line-height: 1.2;
    color: var(--upaep-questor-color);
}

.upaep__questor-form-description {
    margin: .625rem 0 0;
    color: var(--upaep-questor-muted);
    font-size: var(--upaep-fz14);
    line-height: 1.55;
}

.upaep__questor-legend {
    margin: .875rem 0 0;
    color: var(--upaep-questor-muted);
    font-size: var(--upaep-fz12);
}

.upaep__questor-fields {
    display: flex;
    flex-direction: column;
    gap: var(--upaep-questor-gap);
}

/*? Sin `overflow: hidden` (ver la nota de .upaep__questor-card): recortaba el
   calendario del datepicker y cualquier panel flotante de un componente. */
.upaep__questor-item {
    position: relative;
    background: var(--upaep-questor-card-bg);
    border: 1px solid var(--upaep-questor-card-border);
    border-radius: var(--upaep-questor-radius);
    box-shadow: var(--upaep-questor-card-shadow);
    padding: var(--upaep-questor-padding);
    padding-inline-start: calc(var(--upaep-questor-padding) + var(--upaep-questor-marker));
    transition:
        box-shadow var(--upaep-questor-duration) var(--upaep-questor-easing),
        border-color var(--upaep-questor-duration) var(--upaep-questor-easing);
}

/*? Mismo marcador lateral que en el constructor: se enciende al escribir y
   cambia de color con el resultado de la validación. */
.upaep__questor-item::before {
    content: '';
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width: var(--upaep-questor-marker);
    border-start-start-radius: var(--upaep-questor-radius);
    border-end-start-radius: var(--upaep-questor-radius);
    background: var(--upaep-questor-accent);
    opacity: 0;
    transition:
        opacity var(--upaep-questor-duration) var(--upaep-questor-easing),
        background var(--upaep-questor-duration) var(--upaep-questor-easing);
}

.upaep__questor-item:focus-within::before {
    opacity: 1;
}

.upaep__questor-item:hover {
    box-shadow: var(--upaep-questor-card-hover-shadow, var(--upaep-questor-card-shadow));
}

.upaep__questor-item-label {
    display: flex;
    align-items: baseline;
    gap: .3rem;
    font-size: var(--upaep-fz16);
    font-weight: var(--upaep-fw-medium, 500);
    line-height: 1.4;
}

.upaep__questor-number {
    color: var(--upaep-questor-muted);
    font-variant-numeric: tabular-nums;
}

.upaep__questor-required {
    color: var(--upaep-questor-danger);
    font-weight: var(--upaep-fw-bold);
}

.upaep__questor-item-help {
    margin: .3rem 0 0;
    color: var(--upaep-questor-muted);
    font-size: var(--upaep-fz14);
    line-height: 1.5;
}

/*? Los controles de respuesta ocupan el ancho disponible, venga el tipo de
   donde venga (nativo, plugin o custom): así todas las preguntas se ven
   alineadas y se adaptan al contenedor. */
.upaep__questor-field {
    margin-top: .875rem;
    width: 100%;

    & .upaep__input,
    & .upaep__select {
        --upaep-input-margin: 0;
        --upaep-select-margin: 0;
        --upaep-input-width: 100%;
        --upaep-select-width: 100%;
    }

    /*? Los componentes envueltos traen su propio contenedor: que también se
       estire en vez de quedarse al ancho de su contenido. */
    &>.upaep__selectpicker,
    &>.upaep__autocomplete,
    &>.upaep__tokenfield,
    &>.upaep__dropzone,
    &>.upaep__datepicker,
    &>.upaep__numberpicker,
    &>.upaep__scriptor {
        width: 100%;
        max-width: 100%;
    }
}

/*? La firma se dibuja sobre un canvas. El componente le fija width=618 y
   height=250 como atributos (su resolución de dibujo); aquí solo se ajusta el
   tamaño VISUAL para que quepa en la tarjeta sin deformarse. */
.upaep__questor-field .upaep__signature {
    width: 100%;
    max-width: 100%;
}

.upaep__questor-signature {
    width: 100%;
    max-width: 100%;
    height: auto;
    aspect-ratio: 618 / 250;
    border: 1px dashed var(--upaep-questor-border);
    border-radius: var(--upaep-questor-control-radius);
    background: var(--upaep-questor-card-bg);
    touch-action: none;
    cursor: crosshair;
    display: block;
}

/*? Un bloque de contenido no tiene etiqueta ni control: el campo va sin sangría */
.upaep__questor-item.__content .upaep__questor-field {
    margin-top: 0;
}

/* ── Listas de opciones al responder ──────────────────────────────────────── */
.upaep__questor-choices {
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.upaep__questor-choice {
    align-items: center;
    gap: .5rem;

    & .upaep__label {
        --upaep-label-fz: var(--upaep-questor-fz);
        cursor: pointer;
    }
}

.upaep__questor-choice-other {
    gap: .5rem;
}

/*? Estilo interruptor: la etiqueta va después del control y las filas respiran
   más, para que cada una se lea como un ajuste y no como una casilla de lista. */
.upaep__questor-choices.__switch {
    gap: .625rem;
}

.upaep__questor-choice.__switch {
    gap: .625rem;

    & .upaep__label {
        order: 1;
    }

    & .upaep__checkbox.__switch {
        order: 0;
    }

    & .upaep__questor-other {
        order: 2;
    }
}

/* ── Cuadrícula (filas × columnas) ────────────────────────────────────────── */
/*? Va en <table> por semántica: los <th scope> dan a cada control su contexto
   de fila y columna. El scroll horizontal es del contenedor, nunca de la página. */
.upaep__questor-grid {
    width: 100%;
    overflow-x: auto;
    border: 1px solid var(--upaep-questor-divider);
    border-radius: var(--upaep-questor-control-radius);
}

.upaep__questor-grid-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--upaep-fz14);

    & th,
    & td {
        padding: .55rem .75rem;
        text-align: center;
        border-bottom: 1px solid var(--upaep-questor-divider);
    }

    & tbody tr:last-child :is(th, td) {
        border-bottom: 0;
    }

    /*? La primera columna son las filas: alineada a la izquierda y pegajosa,
       para no perder de vista a qué fila corresponde cada control al desplazar. */
    & th[scope="row"] {
        position: sticky;
        inset-inline-start: 0;
        z-index: 1; /*? apilado LOCAL dentro de la tabla, para que la columna de filas no se pierda al desplazar */
        text-align: start;
        font-weight: var(--upaep-fw-medium, 500);
        background: var(--upaep-questor-card-bg);
        min-width: 8rem;
    }

    & thead :is(th, td) {
        background: var(--upaep-questor-subtle);
        color: var(--upaep-questor-muted);
        font-weight: var(--upaep-fw-medium, 500);
        vertical-align: bottom;
    }

    & thead th[scope="col"] {
        min-width: 5.5rem;
    }

    & tbody tr:hover :is(th, td) {
        background: var(--ui-surface-hover, var(--upaep-questor-subtle));
    }

    & :is(.upaep__radio, .upaep__checkbox) {
        --upaep-radio-margin: 0;
        --upaep-checkbox-margin: 0;
    }
}

.upaep__questor-grid-corner {
    background: var(--upaep-questor-subtle);
}

/* ── Modo error de la cuadrícula ──────────────────────────────────────────── */
/*? Marcar la caja entera no dice nada cuando hay diez filas: el JS marca las
   filas que faltan y aquí se pintan. */
.upaep__questor-grid.is-invalid {
    border-color: var(--upaep-questor-danger);
}

/*? Solo se marca la ETIQUETA de la fila que falta, no la fila entera: teñir
   también las celdas de opciones daba la impresión de que el error estaba en las
   columnas, y con varias filas pendientes la tabla quedaba toda roja. */
.upaep__questor-grid-table tbody tr.is-invalid th[scope="row"] {
    color: var(--upaep-questor-danger);
    font-weight: var(--upaep-fw-bold);
}

/*? Marca fina en el borde de arranque de la fila, que es lo que la señala sin
   pintarla. El th ya es sticky, así que sirve de ancla. */
.upaep__questor-grid-table tbody tr.is-invalid th[scope="row"]::before {
    content: '';
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width: 3px;
    background: var(--upaep-questor-danger);
}

.upaep__questor-other {
    --upaep-input-border-bottom-color: var(--upaep-questor-divider);
    --upaep-input-width: auto;
    flex: 1 1 160px;
    min-width: 0;
}

/*? Una fila deshabilitada: el "Otro" sin marcar, o una casilla que ya no se
   puede marcar por haber llegado al tope. Se atenúa pero se sigue leyendo. */
.upaep__questor-choice.is-disabled {
    & .upaep__label {
        opacity: .55;
    }
}

.upaep__questor-choice-other.is-disabled .upaep__questor-other {
    --upaep-input-border-bottom-color: transparent;
    opacity: .55;
    cursor: not-allowed;
}

/* ── Escala lineal ────────────────────────────────────────────────────────── */
.upaep__questor-linear {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 1rem;
}

.upaep__questor-linear-label {
    color: var(--upaep-questor-muted);
    font-size: var(--upaep-fz14);
}

.upaep__questor-linear-scale {
    display: flex;
    align-items: center;
    gap: 1.125rem;

    /*? La escala llega a 11 puntos (0-10) y sus etiquetas pueden ser largas:
       en una pantalla estrecha no cabe en una fila y, sin envolver, empujaba
       el ANCHO DEL DOCUMENTO en vez de repartirse. Envuelve antes que
       desbordar la pagina; el scroll horizontal nunca es del documento. */
    flex-wrap: wrap;
    justify-content: center;
    min-width: 0;
}

.upaep__questor-linear-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .3rem;
    cursor: pointer;

    & .upaep__radio {
        --upaep-radio-margin: 0;
    }
}

.upaep__questor-linear-number {
    font-size: var(--upaep-fz14);
    color: var(--upaep-questor-muted);
}

/* ── Rango de fecha / hora ────────────────────────────────────────────────── */
.upaep__questor-range {
    display: flex;
    align-items: end;
    flex-wrap: wrap;
    gap: .75rem;
}

.upaep__questor-range-part {
    display: flex;
    flex-direction: column;
    gap: .2rem;
    flex: 1 1 160px;
    min-width: 0;

    & .upaep__label {
        --upaep-label-fz: var(--upaep-fz12);
        --upaep-label-margin: 0;
        --upaep-label-padding: 0;
        color: var(--upaep-questor-muted);
    }
}

.upaep__questor-range-sep {
    padding-bottom: .55rem;
    color: var(--upaep-questor-muted);
}

/* ── Bloques de contenido ─────────────────────────────────────────────────── */
.upaep__questor-block-title {
    margin: 0 0 .5rem;
    font-family: var(--ui-font-heading, var(--upaep-ff-fira-sans));
    font-weight: var(--upaep-fw-bold);
    line-height: 1.25;
    color: var(--upaep-questor-color);
}

.upaep__questor-block-text {
    margin: 0 0 .625rem;
    color: var(--upaep-questor-muted);
    font-size: var(--upaep-fz15);
    line-height: 1.6;

    &:last-child {
        margin-bottom: 0;
    }
}

.upaep__questor-block-text.is-empty {
    font-style: italic;
    opacity: .7;
}

.upaep__questor-media {
    display: flex;
    flex-direction: column;
    gap: .5rem;
    margin: 0;
    align-items: start;
}

.upaep__questor-media[data-align="center"] {
    align-items: center;
    text-align: center;
    margin-inline: auto;
}

.upaep__questor-media[data-align="end"] {
    align-items: end;
    text-align: end;
    margin-inline-start: auto;
}

.upaep__questor-media-image,
.upaep__questor-media-video {
    max-width: 100%;
    height: auto;
    border-radius: 8px;
    display: block;
}

/*? El iframe no tiene proporción propia: se le da con aspect-ratio */
.upaep__questor-media-frame {
    width: 100%;
    min-width: min(100%, 320px);
    aspect-ratio: 16 / 9;
    border: 0;
    border-radius: 8px;
    display: block;
}

.upaep__questor-media-caption {
    color: var(--upaep-questor-muted);
    font-size: var(--upaep-fz12);
}

/* ── Validación: se apoya en .upaep__feedback del kit ─────────────────────── */
/*? El core ya muestra el hermano .upaep__feedback.__invalid cuando algo lleva
   .is-invalid, así que no hace falta el modo contenedor .__validated. */
.upaep__questor-form .upaep__feedback {
    --upaep-feedback-fz: var(--upaep-fz14);
    --upaep-feedback-margin: .5rem 0 0;
}

.upaep__questor-item:has(.is-invalid)::before {
    background: var(--upaep-questor-danger);
    opacity: 1;
}

/*? El kit marca en rojo el input y el select con `is-invalid`, y la casilla
   también — pero para el RADIO solo trae el modificador `.__error`, y añadir un
   modificador del core a una clase del core es justo lo que no se debe hacer.
   Así que el estado se pinta desde el campo, que es de este componente. */
.upaep__questor-field.is-invalid {

    /*? Mismo juego de variables que usa el `.__error` del core, para que el
       estado se vea idéntico al del resto del kit. */
    & .upaep__radio {
        --upaep-radio-border-color: var(--upaep-questor-danger);
        --upaep-radio-hover-border-color: var(--ui-danger-hover, var(--upaep-questor-danger));
        --upaep-radio-focus-border-color: var(--upaep-questor-danger);
        --upaep-radio-active-border-color: var(--upaep-questor-danger);
        --upaep-radio-checked-color: var(--upaep-questor-danger);
    }

    /*? Las etiquetas de las opciones acompañan, sin gritar: el mensaje de error
       ya va debajo en rojo. */
    & .upaep__questor-choice .upaep__label,
    & .upaep__questor-linear-number {
        color: var(--upaep-questor-danger);
    }
}

/*? Los pasos de una escala en error: el número marca, no el círculo entero */
.upaep__questor-field.is-invalid .upaep__questor-linear-label {
    color: var(--upaep-questor-danger);
}

.upaep__questor-item:has(.is-valid)::before {
    background: var(--upaep-questor-success);
    opacity: 1;
}

/*? Zona de envío: una barra propia, separada de las preguntas, para que el
   botón principal no parezca parte de la última tarjeta. */
.upaep__questor-form-footer {
    display: flex;
    align-items: center;
    gap: .75rem;
    flex-wrap: wrap;
    padding: var(--upaep-questor-padding);
    background: var(--upaep-questor-card-bg);
    border: 1px solid var(--upaep-questor-card-border);
    border-radius: var(--upaep-questor-radius);
    box-shadow: var(--upaep-questor-card-shadow);

    & .upaep__btn {
        --upaep-btn-width: auto;
        --upaep-btn-margin: 0;
        --upaep-btn-border-radius: var(--upaep-questor-control-radius);
        min-width: 140px;
        justify-content: center;
    }

    /*? El secundario queda al otro extremo: no compiten por la mirada */
    & .upaep__btn.__light {
        margin-inline-start: auto;
        min-width: 0;
    }
}

@media (max-width: 560px) {
    .upaep__questor-form-footer {

        & .upaep__btn,
        & .upaep__btn.__light {
            flex: 1 1 100%;
            margin-inline-start: 0;
        }
    }
}

/* ── Estados ──────────────────────────────────────────────────────────────── */
.upaep__questor.is-disabled,
.upaep__questor-form.is-disabled {
    opacity: .6;
    pointer-events: none;
}

/* ── Variantes del contenedor ─────────────────────────────────────────────── */
/*? Lo contrario del comportamiento por defecto: dibuja un lienzo propio, con
   fondo y relleno, para cuando el constructor va suelto en una página en blanco
   y conviene que se lea como una zona de trabajo. */
.upaep__questor.__surface {
    --upaep-questor-bg: var(--ui-surface-2, var(--upaep-color-tenue-gray));
    --upaep-questor-pad: var(--upaep-questor-gap);
    --upaep-questor-sticky-bg: var(--ui-surface-2, var(--upaep-color-tenue-gray));
}

/*? Ancho completo: útil dentro de un panel estrecho */
.upaep__questor.__wide {
    --upaep-questor-max-width: none;
}

/* ── Responsive ───────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
    .upaep__questor {
        --upaep-questor-padding: 1rem;
        --upaep-questor-gap: .75rem;
    }

    /*? El gap vive en el envoltorio interno, no en la barra. En estrecho se
       permite envolver, pero solo como salida cuando de verdad no cabe. */
    .upaep__questor-toolbar-inner {
        gap: .5rem;
        flex-wrap: wrap;
    }

    /*? Aquí NO se desplaza: en una pantalla estrecha un carrusel horizontal
       esconde botones sin avisar y es incómodo de recorrer con el pulgar. Se
       envuelve, que a cambio solo cuesta alto — y siendo iconos, poco.

       Tampoco se le fuerza una fila entera (antes llevaba `order` y
       `width: 100%`): con pocas herramientas sobraba sitio y aun así se partía
       en dos renglones. Ahora comparte fila y solo baja cuando no cabe. */
    .upaep__questor-tools {
        flex-wrap: wrap;
        overflow-x: visible;
    }

    /*? En pantalla estrecha la barra se queda solo con los iconos. El nombre
       accesible lo mantienen el aria-label y el title de cada botón. */
    .upaep__questor-tool>span,
    .upaep__questor-tab>span {
        display: none;
    }

    /*? MISMA geometría que el modo icono de escritorio, con las mismas
       variables: las dos reglas tienen especificidad distinta (0-1-0 aquí,
       0-4-0 la de arriba), así que si midieran cosas distintas el botón
       principal saldría de un tamaño y el resto de otro. */
    .upaep__questor-tool,
    .upaep__questor-tab {
        width: var(--upaep-questor-tool-size);
        height: var(--upaep-questor-tool-size);
        flex: 0 0 auto;
        justify-content: center;
        padding: 0;
        gap: 0;
    }

    .upaep__questor-tool svg,
    .upaep__questor-tab svg {
        width: var(--upaep-questor-tool-icon);
        height: var(--upaep-questor-tool-icon);
    }

    .upaep__questor-actions {
        margin-inline-start: 0;
    }

    .upaep__questor-card-head {
        grid-template-columns: minmax(0, 1fr);
        gap: .75rem;
    }

    /*? Se quitó el `space-between`: repartía los cuatro iconos por todo el ancho
       de la tarjeta y quedaban sueltos, sin leerse como un grupo. Siguen juntos
       al final, y si el interruptor de "obligatoria" no cabe, envuelve. */
    .upaep__questor-card-foot {
        justify-content: flex-end;
    }

    .upaep__questor-required-toggle {
        margin-inline-start: 0;
        padding-inline-start: 0;
        border-inline-start: 0;
    }

    .upaep__questor-linear-scale {
        gap: .625rem;
    }
}

/*? Como el resto del kit: se anula la duración propia del componente en vez de
   pisar las transiciones de todo lo que haya dentro. El JS consulta la misma
   preferencia para saltarse las animaciones FLIP. */
@media (prefers-reduced-motion: reduce) {

    .upaep__questor,
    .upaep__questor-form {
        --upaep-questor-duration: 0s;
    }
}
