/*
 * Estilos base del formulario. LOS MANDA LA REGENERACIÓN: el próximo zip los
 * sobrescribe, así que tus cambios van en custom.css o en el CSS de la web.
 */

/*
 * Reglas de estos estilos:
 *
 *   1. La web gana, sin `!important`. `:where()` fija la especificidad de cada regla
 *      en uno de tres niveles, y ninguno pasa de (0,2,0):
 *
 *        - CERO, `:where(.bf-form .bf-label)`: tipografía, radio, grosor y color de
 *          las etiquetas, avisos. Gana cualquier cosa, incluido un reset del tema.
 *        - UNA CLASE (0,1,0), `:where(.bf-form) .bf-choice`: estructura —display,
 *          flex, márgenes, anchos—. Gana a los resets por etiqueta, que no saben nada
 *          de este formulario (Hello Elementor pone `label { display: inline-block }`
 *          y deshace la casilla de consentimiento).
 *        - DOS CLASES (0,2,0), `.bf-form .bf-input`: relleno, borde, fondo y color de
 *          los campos, y sus estados de foco y error. Gana a los resets por atributo
 *          —`input[type=text]` es (0,1,1)—, que es como los temas pintan los campos:
 *          tanto el `border: 1px solid #666` de Hello como el borde transparente de
 *          otros temas son eso, y ninguno es algo que haya configurado un diseñador.
 *
 *      Contra el diseño de la web se pierde siempre: el estilo global de campos del
 *      kit de Elementor es (0,3,1), el CSS de un widget —`selector .bf-input`— es
 *      (0,4,0), y el custom.css del plugin se carga después de esta hoja, así que
 *      escrito con `.bf-form` delante gana los empates. Pegado el formulario como
 *      HTML, el orden de carga respecto al CSS de la web no está garantizado: ahí
 *      las reglas propias necesitan (0,3,0), o (0,2,0) cargadas después.
 *
 *   2. Lo visual se ajusta con variables. Todas tienen su valor por defecto en el
 *      propio `var()` y ninguna se declara aquí, así que se definen donde
 *      convenga —`:root`, un contenedor, el widget del shortcode— y se heredan:
 *
 *        :root { --bf-input-bg: #e6e3e2; --bf-input-border: 0; }
 *
 *      En Elementor, en el CSS personalizado del widget del shortcode:
 *
 *        selector { --bf-input-bg: #e6e3e2; --bf-input-padding: 28px 18px; }
 *
 *      Las de nivel dos funcionan en cualquier tema. Las de nivel cero (tipografía,
 *      radio) ceden ante el tema cuando este las pinta —Hello pone radio y fuente a
 *      todos los campos—, y ahí lo que funciona es una regla.
 *
 *   3. `!important` en dos sitios, y ninguno es decoración:
 *        - los avisos cerrados tienen que estar cerrados;
 *        - el texto de la casilla de consentimiento. Hay temas que pintan `label span`
 *          con su color de acento en una hoja inline con `!important`, y una casilla
 *          en azul de enlace invita a hacer clic en el sitio que no es. Solo fija
 *          `inherit`: el color sigue saliendo de `--bf-label-color`.
 *      El honeypot vive en bforms-core.css y no se toca.
 *
 * Variables:
 *
 *   --bf-gap                  hueco entre campos                1rem
 *   --bf-radius               radio de campos y avisos          4px
 *   --bf-border               color del borde                   currentColor
 *   --bf-input-border         borde entero de los campos        1px solid var(--bf-border)
 *   --bf-input-bg             fondo de los campos               transparent
 *   --bf-input-bg-focus       fondo con el foco                 var(--bf-input-bg)
 *   --bf-input-color          texto de los campos               inherit
 *   --bf-input-padding        relleno (altura) de los campos    0.5rem 0.65rem
 *   --bf-input-font           tipografía de los campos          inherit
 *   --bf-textarea-height      alto mínimo del mensaje           8rem
 *   --bf-label-color          color de etiquetas y casillas     inherit
 *   --bf-label-weight         grosor de las etiquetas           600
 *   --bf-focus                color del contorno de foco        currentColor
 *   --bf-invalid              borde de un campo con error       #b3261e
 *   --bf-accent               color de casillas y radios        auto (el del navegador)
 *   --bf-alert-error-color    texto del aviso de error          #8c1d18
 *   --bf-alert-error-bg       fondo del aviso de error          #fdeceb
 *   --bf-alert-ok-color       texto del aviso de enviado        #17542a
 *   --bf-alert-ok-bg          fondo del aviso de enviado        #e9f5ec
 *   --bf-placeholder-color    texto del placeholder (modo .bf-placeholders)   currentColor
 *   --bf-placeholder-opacity  su opacidad (modo .bf-placeholders)             0.7
 *
 * Modo placeholders: la clase `.bf-placeholders` en cualquier contenedor oculta a la vista las
 * etiquetas de los campos de texto y enseña su placeholder, que lleva el mismo texto. Las
 * etiquetas siguen en el HTML para los lectores de pantalla. Sin la clase, el placeholder no se
 * ve y el formulario queda como siempre.
 *
 * El botón de enviar no tiene variables a propósito: lo pinta la web (en Elementor,
 * el botón global del kit). Si hay que retocarlo, es una regla sobre `.bf-submit`.
 */

:where(.bf-form) *,
:where(.bf-form) *::before,
:where(.bf-form) *::after {
    box-sizing: border-box;
}

/*
 * Los avisos viven FUERA del `<form>`, así que no pueden colgar de `.bf-form`. Van por
 * el atributo `data-bforms-alert`, que es además el que busca el script: si alguien se
 * lo lleva de la plantilla, el CSS y el JavaScript dejan de funcionar juntos, en vez de
 * quedar un aviso sin estilo o un estilo sin aviso.
 */
:where(.bf-alert[data-bforms-alert]) {
    margin: 0 0 1rem;
    border: 1px solid currentColor;
    border-left-width: 4px;
    border-radius: var(--bf-radius, 4px);
    padding: 0.75rem 1rem;
}

:where(.bf-alert[data-bforms-alert]) > :where(p) {
    margin: 0;
}

:where(.bf-alert-error[data-bforms-alert]) {
    color: var(--bf-alert-error-color, #8c1d18);
    background: var(--bf-alert-error-bg, #fdeceb);
}

:where(.bf-alert-ok[data-bforms-alert]) {
    color: var(--bf-alert-ok-color, #17542a);
    background: var(--bf-alert-ok-bg, #e9f5ec);
}

/*
 * `!important` 1 de 2: un aviso cerrado tiene que estar cerrado aunque el tema le ponga
 * `display` a los `div` o a los `p`. El atributo `hidden` ya lo hace por su cuenta si
 * esta hoja no carga.
 */
:where(.bf-alert[data-bforms-alert])[hidden],
:where(.bf-alert[data-bforms-alert]) > [hidden] {
    display: none !important;
}

/* ---- Estructura: una clase, (0,1,0) ---------------------------------------------- */

:where(.bf-form) .bf-field {
    margin: 0 0 var(--bf-gap, 1rem);
    border: 0;
    padding: 0;
    min-width: 0; /* un `fieldset` no encoge sin esto y desborda en móvil */
}

/*
 * `font-size: inherit` es por la `legend` de un grupo de radios: Bootstrap y normalize
 * la ponen a 1.5rem.
 */
:where(.bf-form) .bf-label {
    display: block;
    margin-bottom: 0.35rem;
    padding: 0;
    font-size: inherit;
    line-height: 1.3;
}

:where(.bf-form) .bf-input {
    display: block;
    width: 100%;
    max-width: 100%;
    height: auto;
    margin: 0;
}

:where(.bf-form) .bf-choice {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin-bottom: 0.35rem;
    line-height: 1.4;
}

/*
 * La casilla va sin `.bf-input` y así se queda: un tema o un widget que estilice
 * `input` a secas (relleno, fondo, ancho) la deforma, y eso se arregla en la web con
 * una regla sobre `.bf-choice input`, no subiendo más la especificidad aquí.
 */
:where(.bf-form) .bf-choice :where(input) {
    flex: 0 0 auto;
    width: auto;
    height: auto;
    margin: 0.2rem 0 0;
    padding: 0;
    accent-color: var(--bf-accent, auto);
}

:where(.bf-form) .bf-actions {
    margin: 0;
}

@media (min-width: 40em) {
    :where(.bf-form) .bf-row {
        display: flex;
        gap: var(--bf-gap, 1rem);
    }

    :where(.bf-form .bf-row) > .bf-field {
        flex: 1 1 0;
    }
}

/* ---- Campos: dos clases, (0,2,0) --------------------------------------------------- */

.bf-form .bf-input {
    padding: var(--bf-input-padding, 0.5rem 0.65rem);
    color: var(--bf-input-color, inherit);
    background: var(--bf-input-bg, transparent);
    border: var(--bf-input-border, 1px solid var(--bf-border, currentColor));
}

/*
 * Los estados van al MISMO nivel que la regla de arriba y después de ella, que a igual
 * especificidad gana la última. A nivel cero perderían contra el fondo y el borde del
 * propio plugin, y el foco y el error dejarían de verse sin que nada lo dijera.
 */
.bf-form .bf-input:where(:focus) {
    background: var(--bf-input-bg-focus, var(--bf-input-bg, transparent));
}

/* El script marca así los campos que el endpoint rechaza (`?error=validation`). */
.bf-form .bf-input:where([aria-invalid="true"]) {
    border-color: var(--bf-invalid, #b3261e);
}

/* ---- Aspecto: especificidad cero ----------------------------------------------------- */

:where(.bf-form .bf-label) {
    font-weight: var(--bf-label-weight, 600);
    color: var(--bf-label-color, inherit);
}

:where(.bf-form .bf-required) {
    opacity: 0.6;
}

:where(.bf-form .bf-input) {
    font: var(--bf-input-font, inherit);
    border-radius: var(--bf-radius, 4px);
    box-shadow: none;
}

:where(.bf-form .bf-input:focus-visible) {
    outline: 2px solid var(--bf-focus, currentColor);
    outline-offset: 1px;
}

/* Los grupos de casillas y radios también los marca el script, y no llevan `.bf-input`. */
:where(.bf-form [aria-invalid="true"]) {
    border-color: var(--bf-invalid, #b3261e);
}

:where(.bf-form .bf-textarea) {
    min-height: var(--bf-textarea-height, 8rem);
    resize: vertical;
}

:where(.bf-form .bf-choice) {
    font-weight: 400;
    color: var(--bf-label-color, inherit);
}

/*
 * `!important` 2 de 2: el texto de la casilla hereda de la casilla, pase lo que pase. Lo
 * explica la cabecera. El enlace de dentro no entra: es un `<a>`, no un `span`, y su color
 * lo decide la web.
 */
.bf-form .bf-choice :where(span) {
    color: inherit !important;
}

/*
 * El enlace de dentro de una etiqueta: la «política de privacidad» de la casilla de
 * consentimiento. Subrayado siempre, que es lo que lo mantiene reconocible como enlace
 * aunque el tema lo pinte del mismo color que el texto.
 */
:where(.bf-form .bf-label-link) {
    text-decoration: underline;
    text-underline-offset: 0.15em;
}

:where(.bf-form .bf-submit) {
    cursor: pointer;
}

/* ---- Modo placeholders ---------------------------------------------------------------- */

/*
 * Los campos de texto llevan siempre `placeholder`, con el mismo texto que su etiqueta, y por
 * defecto no se ve: así una web que no lo usa queda como estaba. Una clase —la del tema, del kit
 * o de un widget— que pinte los placeholders gana a esta.
 */
:where(.bf-form) .bf-input::placeholder {
    color: transparent;
}

/*
 * `.bf-placeholders` en cualquier contenedor —en Elementor, Avanzado → Clases CSS del widget del
 * shortcode— cambia la etiqueta por el placeholder. La etiqueta NO se quita: se oculta a la
 * vista y sigue en el HTML, que es lo que da nombre al campo para un lector de pantalla y lo que
 * lo explica cuando el placeholder ya ha desaparecido al escribir o al autorrellenar.
 *
 * Solo en los campos con placeholder (`.bf-has-placeholder`): una fecha, un desplegable, un
 * grupo de opciones o la casilla de privacidad conservan su etiqueta, porque es el único nombre
 * que tienen a la vista. El asterisco de obligatorio va dentro de la etiqueta y se oculta con
 * ella.
 */
:where(.bf-placeholders .bf-form) .bf-has-placeholder > .bf-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/*
 * Si el placeholder es lo único que se ve, necesita contraste con el fondo del campo (4,5:1):
 * compruébalo con los colores de cada web y ajústalo con las dos variables.
 */
:where(.bf-placeholders .bf-form) .bf-input::placeholder {
    color: var(--bf-placeholder-color, currentColor);
    opacity: var(--bf-placeholder-opacity, 0.7);
}
