/* Componente formulario (shell, #29; v2: #53): base común de los formularios
 * de la web (demo, inscripción, newsletter, descargas). Solo tokens de
 * style.css. v2: foco animado (un halo verde suave que crece dentro del anillo
 * común), error con icono y éxito con icono, que entran con un fundido breve
 * (sin desplazarse con movimiento reducido). Cada
 * formulario sigue siendo de su módulo (su <form>, script y AJAX); pone estas
 * clases en su marcado, o pinta las piezas de component.php, y su propio
 * styles.css solo lleva la caja y lo que le es propio.
 *
 * Se encola declarándolo como dependencia del componente que lo usa (filtro
 * pf_acanda_shell_component_deps: 'form-demo' => ['formulario', 'boton']) o con
 * pf_acanda_shell_enqueue('formulario'). Sale antes que la hoja del componente,
 * así que esta, a igual especificidad, gana. Clases y marcado: PLANTILLAS.md §7.1.
 *
 * Se ve igual donde se pinte (#100): el <form> lleva la letra de la web, no la
 * de lectura de la prosa en la que caiga (`.pf-bloques`: 18px e interlineado
 * amplio), y la primera capa va con doble clase para que las reglas de listas
 * de esa prosa no le cambien la sangría. */

.pf-formulario {
    position: relative;
    font-size: var(--pf-text-base);
    line-height: var(--pf-leading-normal);
}

.pf-formulario__nota {
    margin: 0 0 var(--pf-space-sm);
    font-size: var(--pf-text-sm);
    color: var(--pf-color-text-muted);
}

/* Rejilla de campos: dos columnas si caben (15rem cada una, según el ancho del
 * formulario y no el de la ventana); si no, uno debajo de otro. Nunca tres:
 * cada columna mide al menos la mitad del formulario. */
.pf-formulario__campos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, max(15rem, (100% - var(--pf-space-md)) / 2)), 1fr));
    gap: 0 var(--pf-space-md);
}

/* Campo: etiqueta, control, ayuda y error. */

.pf-formulario__campo {
    margin: 0 0 var(--pf-space-sm);
}

.pf-formulario__etiqueta {
    display: block;
    margin: 0 0 var(--pf-space-3xs);
    font-weight: var(--pf-weight-bold);
    line-height: var(--pf-leading-snug);
    color: var(--pf-color-heading);
}

/* 16px: por debajo, el móvil hace zoom al enfocarlo. 2.75rem = 44px de alto,
 * el objetivo táctil del botón. */
.pf-formulario__control {
    display: block;
    width: 100%;
    min-height: 2.75rem;
    margin: 0;
    padding: var(--pf-space-xs) var(--pf-space-sm);
    font-family: var(--pf-font-sans);
    font-size: var(--pf-text-base);
    line-height: var(--pf-leading-snug);
    color: var(--pf-color-text);
    background-color: var(--pf-color-surface);
    border: 1px solid var(--pf-color-border-control);
    border-radius: var(--pf-radius-control);
    box-shadow: 0 0 0 0 var(--pf-color-brand-soft);
    transition: border-color var(--pf-transition), box-shadow var(--pf-transition);
}

.pf-formulario__control:hover:not(:disabled, :focus) {
    border-color: var(--pf-neutro-8);
}

/* El alto del área de texto lo da su atributo rows. */
textarea.pf-formulario__control {
    line-height: var(--pf-leading-normal);
    resize: vertical;
}

.pf-formulario__control::placeholder {
    color: var(--pf-color-text-muted);
    opacity: 1;
}

/* El anillo de foco es el global (style.css: 2px a 2px de distancia); aquí
 * cambia el borde y crece un halo verde suave que llena ese hueco. */
.pf-formulario__control:focus-visible {
    border-color: var(--pf-color-focus);
    border-radius: var(--pf-radius-control);
    box-shadow: 0 0 0 2px var(--pf-color-brand-soft);
}

.pf-formulario__control[aria-invalid="true"] {
    border-color: var(--pf-color-error);
}

.pf-formulario__control[aria-invalid="true"]:focus-visible {
    box-shadow: 0 0 0 2px var(--pf-color-error-soft);
}

/* Hundido (bg-inset, distinto de surface también en oscuro) y con filete. */
.pf-formulario__control:disabled {
    cursor: not-allowed;
    color: var(--pf-color-text-muted);
    background-color: var(--pf-color-bg-inset);
    border-color: var(--pf-color-border);
}

.pf-formulario__ayuda {
    margin: var(--pf-space-3xs) 0 0;
    font-size: var(--pf-text-sm);
    line-height: var(--pf-leading-snug);
    color: var(--pf-color-text-muted);
}

/* Error de un campo: el script lo rellena y marca el control con aria-invalid.
 * Vacío, no ocupa sitio. Con texto, un icono de aviso delante (decorativo: el
 * texto ya lo dice; el color sale de currentColor). */
.pf-formulario__error {
    display: flex;
    gap: var(--pf-space-2xs);
    align-items: flex-start;
    margin: var(--pf-space-3xs) 0 0;
    font-size: var(--pf-text-sm);
    font-weight: var(--pf-weight-bold);
    line-height: var(--pf-leading-snug);
    color: var(--pf-color-error);
}

.pf-formulario__error:empty {
    display: none;
}

.pf-formulario__error::before,
.pf-formulario__estado--error:not(:empty)::before,
.pf-formulario__exito::before {
    content: "";
    flex: none;
    width: 1.125rem;
    height: 1.125rem;
    background-color: currentColor;
    -webkit-mask: var(--pf-formulario-icono) center / contain no-repeat;
    mask: var(--pf-formulario-icono) center / contain no-repeat;
}

/* Iconos de Lucide (ISC): circle-alert y circle-check, como máscara. */
.pf-formulario__error,
.pf-formulario__estado--error {
    --pf-formulario-icono: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 8v4M12 16h.01'/%3E%3C/svg%3E");
}

.pf-formulario__exito {
    --pf-formulario-icono: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='m9 12 2 2 4-4'/%3E%3C/svg%3E");
}

/* Casilla (consentimiento): sin marcar, con su texto al lado. Va en un campo
 * con el modificador --casilla: casilla, <label> y error. */

.pf-formulario__campo--casilla {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0 var(--pf-space-xs);
    align-items: start;
    margin-top: var(--pf-space-xs);
}

/* Centrada en la primera línea de su texto (text-sm × leading-normal). */
.pf-formulario__casilla {
    width: 1.25rem;
    height: 1.25rem;
    margin: calc((var(--pf-text-sm) * var(--pf-leading-normal) - 1.25rem) / 2) 0 0;
    accent-color: var(--pf-color-accent);
}

.pf-formulario__campo--casilla label {
    font-size: var(--pf-text-sm);
    line-height: var(--pf-leading-normal);
}

.pf-formulario__campo--casilla .pf-formulario__error {
    grid-column: 1 / -1;
}

/* Primera capa de protección de datos: responsable, finalidad, legitimación,
 * destinatarios, conservación, derechos y enlace a la política. Texto
 * secundario: 14px e interlineado de párrafo (#48). Doble clase (0,2,0): gana a
 * las listas de la prosa de una plantilla (`.pf-bloques ul`, 0,1,1), que le
 * daban 24px de sangría en lugar de 16 (#100). */

.pf-formulario .pf-formulario__capa {
    margin: 0 0 var(--pf-space-md);
    padding: 0 0 0 var(--pf-space-sm);
    list-style: none;
    font-size: var(--pf-text-sm);
    line-height: var(--pf-leading-normal);
    color: var(--pf-color-text-muted);
    border-left: 2px solid var(--pf-color-border);
}

.pf-formulario .pf-formulario__capa li + li {
    margin-top: var(--pf-space-3xs);
}

.pf-formulario .pf-formulario__capa strong {
    font-weight: var(--pf-weight-bold);
    color: var(--pf-color-text-soft);
}

/* Campo trampa: fuera de la vista y del orden de tabulación (tabindex="-1",
 * aria-hidden en su contenedor), nunca type="hidden". */
.pf-formulario__trampa {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* Envío: el botón a todo el ancho en móvil. */

.pf-formulario__envio .pf-boton {
    width: 100%;
}

/* Enviando: el botón de enviar muestra el anillo de «cargando» (boton, #53). */
.pf-formulario[aria-busy="true"] .pf-boton {
    cursor: progress;
}

/* Estado del envío (role="status"): «Enviando…», o el error general con el
 * modificador --error. Vacío, no ocupa sitio. */
.pf-formulario__estado {
    margin: 0;
    font-size: var(--pf-text-sm);
    color: var(--pf-color-text-soft);
}

.pf-formulario__estado:not(:empty) {
    margin-top: var(--pf-space-sm);
}

.pf-formulario__estado--error {
    font-weight: var(--pf-weight-bold);
    color: var(--pf-color-error);
}

.pf-formulario__estado--error:not(:empty) {
    display: flex;
    gap: var(--pf-space-2xs);
    align-items: flex-start;
}

/* Éxito: sustituye al formulario en la misma página y recibe el foco. Caja
 * verde suave con el icono de hecho (en success, ≥ 3:1 sobre su fondo). */
.pf-formulario__exito {
    display: flex;
    gap: var(--pf-space-xs);
    align-items: flex-start;
    margin: 0;
    padding: var(--pf-space-sm) var(--pf-space-md);
    font-size: var(--pf-text-md);
    line-height: var(--pf-leading-normal);
    color: var(--pf-color-heading);
    background-color: var(--pf-color-success-soft);
    border-left: 3px solid var(--pf-color-success);
    border-radius: 0 var(--pf-radius-md) var(--pf-radius-md) 0;
}

.pf-formulario__exito[hidden] {
    display: none;
}

.pf-formulario__exito::before {
    width: 1.5rem;
    height: 1.5rem;
    margin-top: 0.05em;
    color: var(--pf-color-success);
}

@media (min-width: 768px) {
    .pf-formulario__envio .pf-boton {
        width: auto;
    }
}

/* Entradas con movimiento: el error y el éxito aparecen con un fundido y bajan
 * 2px; el halo de foco crece (transición de box-shadow, arriba). Con
 * movimiento reducido, sin desplazamiento. */
@media (prefers-reduced-motion: no-preference) {
    .pf-formulario__error:not(:empty),
    .pf-formulario__estado--error:not(:empty),
    .pf-formulario__exito:not([hidden]) {
        animation: pf-formulario-aparece 0.24s ease-out;
    }
}

@keyframes pf-formulario-aparece {
    from {
        opacity: 0;
        transform: translateY(-2px);
    }
}
