/* =============================================================================
 * FORM — la carcasa del FORMULARIO que no estaba en `gwfields.css` sino en `main.css`.
 *
 * De dónde viene: `assets/css/main.css`, bloques "FORMS" (`.ajax_form`), "TABS"
 * (`.tab_content`), el `.buttons_list` que quedó suelto en el bloque de botones borrado en
 * 0.7.0, y los `<p>` de `.form_errors`. Se movieron el 2026-07-28 (juicy-core 0.9.115).
 *
 * POR QUÉ, y por qué justo ahora. `ds/form-panel.css` (0.9.114) cruzó la carcasa que emite
 * el campo `form_panel` y dejó escrito lo que NO resolvía: el mismo renderer emite regiones
 * cuyo CSS seguía en `main.css`, que el front nuevo no importa a propósito. La que pesa es
 * **`.tab_content`**, que es lo ÚNICO que oculta los paneles inactivos: sin ella, un
 * formulario con pestañas en React pinta **todos los paneles apilados a la vez**. No es un
 * detalle estético — es la pantalla ilegible. Con 18 de las 39 pantallas pendientes siendo
 * formularios, esto va por delante del primer `.tsx`.
 *
 * ⚠ CONSUMIDORES. Esta capa la encola SOLO `juicy-core` (bootstrap.php) y la consume el
 * front nuevo (`juicy-app`, vía scripts/sync-ds.mjs). **Al Hub NO se le registra**, y es
 * deliberado, no un olvido: `juicy-core-hub` no carga `main.css` —nunca recibió estas
 * reglas de aquí— y mantiene sus PROPIAS copias en `assets/css/dashboard.css`
 * (`.tab_content` líneas 466-496, `.buttons_list` 119, `.ajax_form` 291-325), además de un
 * `.vertical_tabs` que el core no tiene. Darle esta capa le pondría una SEGUNDA definición
 * de las mismas clases. La regla que salió de la tanda de `form-panel.css` —preguntar qué
 * otros installs consumen una regla ANTES de moverla— aquí contesta "ninguno", y por eso
 * este movimiento no toca al Hub.
 *
 * CASCADA. Sale de `main.css` y entra en la capa de COMPONENTES, o sea MÁS TARDE. Se
 * comprobó que la promoción es inerte: ninguna hoja anterior (gwfields.css, main.css ni las
 * capas del DS que van delante) declara nada que case con estos selectores.
 *
 * MEDIDO — cuatro fotos, `e2e/foto-estilos.mjs`, 0 diferencias en las cuatro:
 *   A `/productos/editar?gwproduct=3499` con `--clase 'form.ajax_form=loading'` (7 paneles,
 *     2 pies de formulario, el velo de guardado ENCENDIDO)
 *   B `/productos/editar?gwproduct=3499&tab=general` (1 panel `.active`, 6 `.inactive`)
 *   C `/acceder` con credenciales malas (la caja `.form_errors`, que solo existe tras un
 *     envío fallido — se llega con `--sin-login --rellenar --enviar`)
 *   D `/almacenes/editar`, la pantalla que abre la familia
 *
 * LO QUE NO SE MOVIÓ, y por qué (para que nadie lo lea como olvido):
 *   · `.tabs_header` `.tab` `.tab.active` — se quedan en `main.css`. Son la OTRA barra de
 *     pestañas: la horizontal, y su único emisor en todo el producto es el lightbox de
 *     buscar cliente del POS (`templates/template-parts/pos/lightboxes/searchCustomer.php`).
 *     Ningún formulario las pinta: `form_panel` usa `.sidebar_tab` (ds/form-panel.css). El
 *     POS es F4 y cruza con su propia familia.
 *   · `.widget_body p` — tipografía de prosa suelta dentro de un widget, no del formulario.
 *     Cruzarla movería el Hub el día que sincronice su copia del DS (su dashboard.css NO la
 *     tiene) para vestir algo que ningún formulario de esta familia emite.
 *   · `.form_errors` a secas no tiene regla propia en ningún sitio, y eso está BIEN: es un
 *     hook de JS (`$.fn.print_errors` la busca y la crea) y quien la viste son las clases
 *     `alert-banner tone-error` del DS que la acompañan.
 * ============================================================================= */

/* -----------------------------------------------------------------------------
 * 1. EL VELO DE GUARDADO. Viene de main.css, bloque "FORMS".
 *
 * Es el estado "guardando" de cualquier `ajax_form`: `main.js` le pone `loading` al <form>
 * mientras la petición está en vuelo y lo quita al contestar. Todo el estado son DOS
 * pseudo-elementos —un velo blanco al 80% y un anillo que gira—, así que medirlo obligó a
 * ampliar la lista de propiedades de pseudo del instrumento: antes solo miraba el glifo y la
 * caja, y con `background`/`visibility`/`opacity`/`animation` fuera de la foto se podía
 * mover este bloque entero, dejarlo invisible, y el diff seguía diciendo 0.
 * -------------------------------------------------------------------------- */
.ajax_form:before{
	content:'';
	position: absolute;
	top:0;
	left:0;
	width:100%;
	height:100%;
	background:rgba(255,255,255,0.8);
	z-index:2;
	visibility: hidden;
	opacity: 0;
}
.ajax_form:after{
	content:'';
	position: absolute;
	top:calc(50% - 25px);
	left:calc(50% - 25px);
	width:40px;
	height:40px;
	border-width: 5px;
	border-style: solid;
	border-color: var(--neutral-500) var(--neutral-500) var(--neutral-500) transparent;
	border-radius: 50%;
	z-index:3;
	animation: loadingRotate 1s infinite ease;
	-webkit-animation: loadingRotate 1s infinite ease;
	-moz-animation: loadingRotate 1s infinite ease;
	-o-animation: loadingRotate 1s infinite ease;
	visibility: hidden;
	opacity: 0;
}
.ajax_form.loading:before,
.ajax_form.loading:after{
	opacity: 1;
	visibility: visible;
}

/* Los keyframes viajan con quien los usa. Y hay un segundo consumidor que los necesitaba
   aquí: `ds/pos.css:290` también anima `loadingRotate`, y como los keyframes vivían en
   `main.css` —que el front nuevo NO importa— esa animación estaba rota en el front nuevo
   desde el día que cruzó. Con esto se arregla de paso. */
@keyframes loadingRotate {
	from{
		transform: rotate(0deg)
	}
	to{
		transform: rotate(359deg)
	}
}
@-webkit-keyframes loadingRotate {
	from{
		transform: rotate(0deg)
	}
	to{
		transform: rotate(359deg)
	}
}
@-moz-keyframes loadingRotate {
	from{
		transform: rotate(0deg)
	}
	to{
		transform: rotate(359deg)
	}
}
@-o-keyframes loadingRotate {
	from{
		transform: rotate(0deg)
	}
	to{
		transform: rotate(359deg)
	}
}

/* -----------------------------------------------------------------------------
 * 2. LOS PANELES DE PESTAÑA. Viene de main.css, bloque "TABS".
 *
 * `.tab_content` es lo que oculta los paneles que no son el activo. El mecanismo tiene DOS
 * mitades y conviene saberlo antes de portarlo: la de CSS (esto) decide qué se ve al cargar
 * —`:first-child` visible, `.active`/`.inactive` cuando la URL trae `?tab=`— y a partir del
 * primer clic manda el JS, que hace `.hide()`/`.fadeIn()` con estilo EN LÍNEA y ya no toca
 * estas clases. Un port que solo mire las clases se queda a medias.
 * -------------------------------------------------------------------------- */
.tab_content {
	display: none;
	width: 100%;
	padding: 25px;
}
.widget_body .tab_content {
	padding: 0;
}
.tab_content:first-child,
.tab_content.active{
	display: inline-block;
}
.tab_content.inactive{
	display: none;
}

/* -----------------------------------------------------------------------------
 * 3. EL PIE DEL FORMULARIO.
 *
 * `.buttons_list` lo emiten los dos renderers de gw-fields (`gwform::afterForm()` y el pie
 * del `form_panel`) y también, a mano, una decena de lightboxes del core y del POS. Es
 * LAYOUT, no botones: el bloque de botones de `main.css` se borró entero en 0.7.0 y esto es
 * lo que quedó vivo de él.
 *
 * `.form_footer`, que es su envoltura, NO tiene regla en `main.css` — se buscó y no está.
 * Solo la viste `ds/bubble.css` cuando cuelga de un popover. Queda dicho porque estaba
 * anotado al revés en la doc 29.
 * -------------------------------------------------------------------------- */
.buttons_list{
	gap: 10px;
}

/* -----------------------------------------------------------------------------
 * 4. LOS ERRORES DE VALIDACIÓN QUE DEVUELVE EL SERVIDOR.
 *
 * `$.fn.print_errors` (main.js) crea la caja si no está y le mete un `<p>` por error. Aquí
 * solo se le quita a esos `<p>` el margen del navegador; el aspecto lo pone el
 * `alert-banner tone-error` del DS. Hoy el único sitio del producto donde esto se pinta de
 * verdad es el login fallido (los 12 `print_errors` del backend viven en `gw_Users.php`),
 * y ahí es donde se midió.
 *
 * NO MEDIDO, declarado: `.form_errors p + p`. El login devuelve UN error, así que nunca hay
 * un segundo `<p>` que fotografiar. La regla viaja sin comprobar.
 * -------------------------------------------------------------------------- */
.form_errors p{
	margin: 0;
}
.form_errors p + p{
	margin-top: 6px;
}
