/**
 * TrazoForms — estilos base + sistema de design tokens.
 *
 * Los tokens NO viven en :root a propósito (ver ADR 0016). Esta hoja se carga
 * también en el panel de administración, porque el lienzo del builder
 * renderiza el formulario real (ADR 0003): con los tokens globales, cualquier
 * componente del admin que usara --tf-* heredaría en silencio la paleta del
 * formulario. Acotarlos a los dos contenedores que dibujan un formulario es lo
 * que hace cumplir la regla de que las paletas no tocan el admin.
 */

/* --- Tokens que no dependen de la paleta --- */

.trazoforms-form,
.trazoforms-builder-canvas {
	/* Espaciado — la causa #1 de queja sobre "textos pegados" en otros plugins */
	--tf-space-xs: 4px;
	--tf-space-sm: 8px;
	--tf-space-md: 16px;
	--tf-space-lg: 24px;
	--tf-space-xl: 40px;

	/* Tipografía. Los tamaños se DECLARAN, no se heredan del tema: un tema con
	   el cuerpo a 20 px hacía que el texto del consentimiento saliera enorme
	   mientras las etiquetas, que sí tenían tamaño, se veían bien.
	   El control va a 1 rem (16 px) como mínimo: por debajo de eso, iOS hace
	   zoom al enfocar un campo y descoloca la página. */
	--tf-font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
	--tf-font-size-base: 1rem;
	--tf-font-size-title: 1.375rem;
	/* Título de un salto de sección: entre el del formulario y una etiqueta. */
	--tf-font-size-section: 1.1875rem;
	--tf-font-size-label: 0.9375rem;
	--tf-font-size-input: 1rem;
	--tf-font-size-help: 0.8125rem;
	--tf-font-weight-label: 600;
	--tf-line-height: 1.5;

	/* Bordes */
	--tf-radius-sm: 6px;
	--tf-radius-md: 8px;

	/* Controles. 44px es el mínimo táctil de WCAG 2.5.8, y el de las guías de
	   Apple y de Google. */
	--tf-control-min-height: 44px;
	--tf-control-padding-y: 10px;
	--tf-control-padding-x: 12px;

	/* Aire entre el borde del formulario y su contenido. Sin esto los campos
	   quedan pegados al borde de la tarjeta. */
	--tf-form-padding: var(--tf-space-xl);

	/* Marcadores de radio/checkbox — personalizable, resuelve la queja de "bullets".
	   Van en el acento y no en la primaria: es lo que deja que una paleta tenga
	   dos colores de verdad (botón teal + marcas ámbar, por ejemplo) en lugar de
	   ser un solo matiz repetido. Si una paleta no define acento, cae en la
	   primaria y se comporta como antes. */
	--tf-marker-size: 20px;
	/* Centra el marcador con la PRIMERA línea del texto, sea cual sea su
	   tamaño: la mitad de lo que le sobra a esa línea respecto del marcador.
	   Con el texto del formulario (16px) da 2px; con la letra pequeña del
	   consentimiento (13px) da 0, que es lo correcto — un valor fijo dejaba
	   ese texto visiblemente más arriba que su casilla. Nunca negativo. */
	--tf-marker-offset: max(0px, calc((var(--tf-line-height) * 1em - var(--tf-marker-size)) / 2));
	--tf-marker-border: 2px solid var(--tf-color-border);
	--tf-marker-color-checked: var(--tf-color-accent, var(--tf-color-primary));

	/* Alias semánticos: el CSS los consume con estos nombres. No dependen de la
	   paleta —son siempre la misma derivación— así que se declaran una sola vez
	   y resuelven solos al cambiar de paleta o de modo. */
	--tf-color-label: var(--tf-color-text);
	--tf-color-help: var(--tf-color-text-muted);
	--tf-color-border-focus: var(--tf-color-primary);

	/* Iconos (ver ADR 0018): grosor del trazo, el mismo valor que en el admin
	   pero con su propia variable, porque los tokens públicos no se mezclan
	   con los del panel (ADR 0016). */
	--tf-icon-stroke: 1.5;

	/* Animación */
	--tf-anim-duration: 320ms;
	--tf-anim-easing: cubic-bezier(0.16, 1, 0.3, 1);
}

/* --- Paletas de color ---------------------------------------------------
 *
 * Cada paleta define 11 tokens en modo claro y en modo oscuro. Nueve son de
 * identidad (primary, primary-hover, primary-contrast, accent, surface,
 * surface-alt, text, text-muted, border) y dos semánticos (error y success),
 * que se resuelven contra la superficie de SU paleta: un rojo de error que
 * funciona sobre blanco no cumple sobre una crema o sobre una ciruela.
 *
 * Los valores no se eligieron a ojo: `dev/tools/contrast-check.php` lee esta
 * misma hoja y verifica los mínimos WCAG de cada paleta y cada modo.
 *
 * El modo se resuelve en tres estados, y el orden de los bloques importa:
 *
 *   1. El selector base define SIEMPRE el modo claro.
 *   2. Bajo prefers-color-scheme: dark se redefine el modo oscuro, pero
 *      excluyendo data-tf-mode="light" — así una elección explícita de "claro"
 *      gana sobre la preferencia del sistema.
 *   3. data-tf-mode="dark" lo redefine otra vez, para que la elección
 *      explícita de "oscuro" gane también cuando el sistema está en claro.
 *
 * Sin el paso 3, el ajuste solo funcionaría en una dirección. Es el motivo por
 * el que las paletas no pueden ir en un atributo style="" (ADR 0016): un
 * estilo en línea no puede contener una media query.
 *
 * Para agregar una paleta: copiar este bloque de tres, cambiar el slug y los
 * valores, y registrar el nombre visible en Palettes::catalog().
 * ---------------------------------------------------------------------- */

/* Neutro — Blancos y grises con un azul sobrio. Es la paleta de partida: un
   formulario recién creado tiene que poder caer en cualquier sitio sin
   pelearse con su marca (ver .claude/skills/diseno-visual). */
[data-tf-palette="neutro"] {
	--tf-color-primary: #3858e9;
	--tf-color-primary-hover: #2c46c4;
	--tf-color-primary-contrast: #ffffff;
	--tf-color-accent: #3858e9;
	--tf-color-surface: #ffffff;
	--tf-color-surface-alt: #f5f6f8;
	--tf-color-text: #1e2328;
	--tf-color-text-muted: #59616b;
	--tf-color-border: #858d96;
	--tf-color-error: #c02c2c;
	--tf-color-success: #1a7a47;
}

@media (prefers-color-scheme: dark) {
	[data-tf-palette="neutro"]:not([data-tf-mode="light"]) {
		--tf-color-primary: #8ea4ff;
		--tf-color-primary-hover: #a5b6ff;
		--tf-color-primary-contrast: #10131a;
		--tf-color-accent: #8ea4ff;
		--tf-color-surface: #17191d;
		--tf-color-surface-alt: #21242a;
		--tf-color-text: #e7e9ec;
		--tf-color-text-muted: #a8b0ba;
		--tf-color-border: #79828d;
		--tf-color-error: #ef6f6a;
		--tf-color-success: #4cae7f;
	}
}

[data-tf-palette="neutro"][data-tf-mode="dark"] {
	--tf-color-primary: #8ea4ff;
	--tf-color-primary-hover: #a5b6ff;
	--tf-color-primary-contrast: #10131a;
	--tf-color-accent: #8ea4ff;
	--tf-color-surface: #17191d;
	--tf-color-surface-alt: #21242a;
	--tf-color-text: #e7e9ec;
	--tf-color-text-muted: #a8b0ba;
	--tf-color-border: #79828d;
	--tf-color-error: #ef6f6a;
	--tf-color-success: #4cae7f;
}

/* Voltio — Azul eléctrico, tecnológico y nítido. Neutros fríos y superficie casi blanca. */
[data-tf-palette="voltio"] {
	--tf-color-primary: #0a66d6;
	--tf-color-primary-hover: #084fa8;
	--tf-color-primary-contrast: #f6faff;
	--tf-color-accent: #0e8fa8;
	--tf-color-surface: #f8fafd;
	--tf-color-surface-alt: #ecf1f8;
	--tf-color-text: #192333;
	--tf-color-text-muted: #58687e;
	--tf-color-border: #7f8ea2;
	--tf-color-error: #cf3833;
	--tf-color-success: #1e814c;
}

@media (prefers-color-scheme: dark) {
	[data-tf-palette="voltio"]:not([data-tf-mode="light"]) {
		--tf-color-primary: #4d9bf0;
		--tf-color-primary-hover: #6fb0f5;
		--tf-color-primary-contrast: #0a1220;
		--tf-color-accent: #2fc3de;
		--tf-color-surface: #0e1622;
		--tf-color-surface-alt: #172130;
		--tf-color-text: #dbe2eb;
		--tf-color-text-muted: #94a6bb;
		--tf-color-border: #5a6c82;
		--tf-color-error: #df514c;
		--tf-color-success: #2b935c;
	}
}

[data-tf-palette="voltio"][data-tf-mode="dark"] {
	--tf-color-primary: #4d9bf0;
	--tf-color-primary-hover: #6fb0f5;
	--tf-color-primary-contrast: #0a1220;
	--tf-color-accent: #2fc3de;
	--tf-color-surface: #0e1622;
	--tf-color-surface-alt: #172130;
	--tf-color-text: #dbe2eb;
	--tf-color-text-muted: #94a6bb;
	--tf-color-border: #5a6c82;
	--tf-color-error: #df514c;
	--tf-color-success: #2b935c;
}

/* Marea — Teal profesional con acento ámbar. Fresca y limpia, pensada para producto digital. */
[data-tf-palette="marea"] {
	--tf-color-primary: #0a7c8a;
	--tf-color-primary-hover: #06616c;
	--tf-color-primary-contrast: #f2fcfd;
	--tf-color-accent: #b9700e;
	--tf-color-surface: #f6fbfb;
	--tf-color-surface-alt: #e7f3f3;
	--tf-color-text: #192b2e;
	--tf-color-text-muted: #4f696c;
	--tf-color-border: #6b898d;
	--tf-color-error: #cf3833;
	--tf-color-success: #1e814c;
}

@media (prefers-color-scheme: dark) {
	[data-tf-palette="marea"]:not([data-tf-mode="light"]) {
		--tf-color-primary: #48b3be;
		--tf-color-primary-hover: #63c4ce;
		--tf-color-primary-contrast: #08191b;
		--tf-color-accent: #e8a24a;
		--tf-color-surface: #0d1718;
		--tf-color-surface-alt: #152526;
		--tf-color-text: #d5e4e6;
		--tf-color-text-muted: #8eb0b3;
		--tf-color-border: #557275;
		--tf-color-error: #df514c;
		--tf-color-success: #2b925b;
	}
}

[data-tf-palette="marea"][data-tf-mode="dark"] {
	--tf-color-primary: #48b3be;
	--tf-color-primary-hover: #63c4ce;
	--tf-color-primary-contrast: #08191b;
	--tf-color-accent: #e8a24a;
	--tf-color-surface: #0d1718;
	--tf-color-surface-alt: #152526;
	--tf-color-text: #d5e4e6;
	--tf-color-text-muted: #8eb0b3;
	--tf-color-border: #557275;
	--tf-color-error: #df514c;
	--tf-color-success: #2b925b;
}

/* Índigo — Índigo sobrio con acento rosa. Bordes suaves y mucho aire: la más contenida del sistema. */
[data-tf-palette="indigo"] {
	--tf-color-primary: #4a44c9;
	--tf-color-primary-hover: #3a35a4;
	--tf-color-primary-contrast: #f7f6fe;
	--tf-color-accent: #c1367a;
	--tf-color-surface: #fafafe;
	--tf-color-surface-alt: #efeffa;
	--tf-color-text: #1e1b2f;
	--tf-color-text-muted: #605b7c;
	--tf-color-border: #928fa8;
	--tf-color-error: #cf3934;
	--tf-color-success: #1e814c;
}

@media (prefers-color-scheme: dark) {
	[data-tf-palette="indigo"]:not([data-tf-mode="light"]) {
		--tf-color-primary: #918bec;
		--tf-color-primary-hover: #a7a1f1;
		--tf-color-primary-contrast: #14121f;
		--tf-color-accent: #e86fa5;
		--tf-color-surface: #16151e;
		--tf-color-surface-alt: #211f2c;
		--tf-color-text: #e2e1ed;
		--tf-color-text-muted: #a3a0bd;
		--tf-color-border: #686386;
		--tf-color-error: #e0514d;
		--tf-color-success: #2b935c;
	}
}

[data-tf-palette="indigo"][data-tf-mode="dark"] {
	--tf-color-primary: #918bec;
	--tf-color-primary-hover: #a7a1f1;
	--tf-color-primary-contrast: #14121f;
	--tf-color-accent: #e86fa5;
	--tf-color-surface: #16151e;
	--tf-color-surface-alt: #211f2c;
	--tf-color-text: #e2e1ed;
	--tf-color-text-muted: #a3a0bd;
	--tf-color-border: #686386;
	--tf-color-error: #e0514d;
	--tf-color-success: #2b935c;
}

/* Ámbar — Crema de papel con ocre y acento teal. Editorial y cálida: la superficie tiñe de verdad. */
[data-tf-palette="ambar"] {
	--tf-color-primary: #9a5a08;
	--tf-color-primary-hover: #7a4505;
	--tf-color-primary-contrast: #fff8ed;
	--tf-color-accent: #0f7d80;
	--tf-color-surface: #fbf5e9;
	--tf-color-surface-alt: #f3e9d4;
	--tf-color-text: #3a2f1f;
	--tf-color-text-muted: #73634d;
	--tf-color-border: #887257;
	--tf-color-error: #cb3530;
	--tf-color-success: #1d7d4a;
}

@media (prefers-color-scheme: dark) {
	[data-tf-palette="ambar"]:not([data-tf-mode="light"]) {
		--tf-color-primary: #d9a050;
		--tf-color-primary-hover: #e6b570;
		--tf-color-primary-contrast: #1a1208;
		--tf-color-accent: #56c2c2;
		--tf-color-surface: #1c1712;
		--tf-color-surface-alt: #29211a;
		--tf-color-text: #e4dbd0;
		--tf-color-text-muted: #b1a089;
		--tf-color-border: #7a6954;
		--tf-color-error: #e0534f;
		--tf-color-success: #2b945c;
	}
}

[data-tf-palette="ambar"][data-tf-mode="dark"] {
	--tf-color-primary: #d9a050;
	--tf-color-primary-hover: #e6b570;
	--tf-color-primary-contrast: #1a1208;
	--tf-color-accent: #56c2c2;
	--tf-color-surface: #1c1712;
	--tf-color-surface-alt: #29211a;
	--tf-color-text: #e4dbd0;
	--tf-color-text-muted: #b1a089;
	--tf-color-border: #7a6954;
	--tf-color-error: #e0534f;
	--tf-color-success: #2b945c;
}

/* Brasa — Arena cálida con rojo arcilla y acento turquesa. Bordes nítidos, presencia fuerte. */
[data-tf-palette="brasa"] {
	--tf-color-primary: #a83a2a;
	--tf-color-primary-hover: #862c1f;
	--tf-color-primary-contrast: #fff7f3;
	--tf-color-accent: #157f86;
	--tf-color-surface: #fcf4f0;
	--tf-color-surface-alt: #f5e5dc;
	--tf-color-text: #392720;
	--tf-color-text-muted: #775c50;
	--tf-color-border: #8f6858;
	--tf-color-error: #cb3530;
	--tf-color-success: #1d7d4a;
}

@media (prefers-color-scheme: dark) {
	[data-tf-palette="brasa"]:not([data-tf-mode="light"]) {
		--tf-color-primary: #e08874;
		--tf-color-primary-hover: #ea9c8a;
		--tf-color-primary-contrast: #1a0f0c;
		--tf-color-accent: #46b9c0;
		--tf-color-surface: #1d1614;
		--tf-color-surface-alt: #2a1f1b;
		--tf-color-text: #e6d9d4;
		--tf-color-text-muted: #b3998e;
		--tf-color-border: #89695b;
		--tf-color-error: #e0534f;
		--tf-color-success: #2b945c;
	}
}

[data-tf-palette="brasa"][data-tf-mode="dark"] {
	--tf-color-primary: #e08874;
	--tf-color-primary-hover: #ea9c8a;
	--tf-color-primary-contrast: #1a0f0c;
	--tf-color-accent: #46b9c0;
	--tf-color-surface: #1d1614;
	--tf-color-surface-alt: #2a1f1b;
	--tf-color-text: #e6d9d4;
	--tf-color-text-muted: #b3998e;
	--tf-color-border: #89695b;
	--tf-color-error: #e0534f;
	--tf-color-success: #2b945c;
}

/* Olivo — Verde natural con acento terracota. Sobria y estable, sin recurrir al azul corporativo. */
[data-tf-palette="olivo"] {
	--tf-color-primary: #4e7420;
	--tf-color-primary-hover: #3c5a17;
	--tf-color-primary-contrast: #f9fcef;
	--tf-color-accent: #b25a1e;
	--tf-color-surface: #f8faf0;
	--tf-color-surface-alt: #ecf1dc;
	--tf-color-text: #26301c;
	--tf-color-text-muted: #596b4a;
	--tf-color-border: #6f875a;
	--tf-color-error: #cf3731;
	--tf-color-success: #1e7f4b;
}

@media (prefers-color-scheme: dark) {
	[data-tf-palette="olivo"]:not([data-tf-mode="light"]) {
		--tf-color-primary: #94bd5e;
		--tf-color-primary-hover: #a8cb79;
		--tf-color-primary-contrast: #101707;
		--tf-color-accent: #e08a4e;
		--tf-color-surface: #121a12;
		--tf-color-surface-alt: #1d271c;
		--tf-color-text: #dfe7d8;
		--tf-color-text-muted: #98ad85;
		--tf-color-border: #627451;
		--tf-color-error: #e05450;
		--tf-color-success: #2b955c;
	}
}

[data-tf-palette="olivo"][data-tf-mode="dark"] {
	--tf-color-primary: #94bd5e;
	--tf-color-primary-hover: #a8cb79;
	--tf-color-primary-contrast: #101707;
	--tf-color-accent: #e08a4e;
	--tf-color-surface: #121a12;
	--tf-color-surface-alt: #1d271c;
	--tf-color-text: #dfe7d8;
	--tf-color-text-muted: #98ad85;
	--tf-color-border: #627451;
	--tf-color-error: #e05450;
	--tf-color-success: #2b955c;
}

/* Coral — Coral vivo sobre gris absolutamente neutro. El único sistema sin tinte en los grises: el color canta solo. */
[data-tf-palette="coral"] {
	--tf-color-primary: #c93f16;
	--tf-color-primary-hover: #a7300d;
	--tf-color-primary-contrast: #fff7f3;
	--tf-color-accent: #0e8f94;
	--tf-color-surface: #fcfcfc;
	--tf-color-surface-alt: #f0f0f0;
	--tf-color-text: #292929;
	--tf-color-text-muted: #666666;
	--tf-color-border: #898989;
	--tf-color-error: #d03a35;
	--tf-color-success: #1e814d;
}

@media (prefers-color-scheme: dark) {
	[data-tf-palette="coral"]:not([data-tf-mode="light"]) {
		--tf-color-primary: #f0805a;
		--tf-color-primary-hover: #f59776;
		--tf-color-primary-contrast: #1c0c06;
		--tf-color-accent: #3fbcc2;
		--tf-color-surface: #171717;
		--tf-color-surface-alt: #232323;
		--tf-color-text: #e3e3e3;
		--tf-color-text-muted: #a7a7a7;
		--tf-color-border: #6b6b6b;
		--tf-color-error: #e0534e;
		--tf-color-success: #2b945c;
	}
}

[data-tf-palette="coral"][data-tf-mode="dark"] {
	--tf-color-primary: #f0805a;
	--tf-color-primary-hover: #f59776;
	--tf-color-primary-contrast: #1c0c06;
	--tf-color-accent: #3fbcc2;
	--tf-color-surface: #171717;
	--tf-color-surface-alt: #232323;
	--tf-color-text: #e3e3e3;
	--tf-color-text-muted: #a7a7a7;
	--tf-color-border: #6b6b6b;
	--tf-color-error: #e0534e;
	--tf-color-success: #2b945c;
}

/* Prisma — Magenta expresiva con acento dorado. Superficie rosada y modo oscuro ciruela, no negro. */
[data-tf-palette="prisma"] {
	--tf-color-primary: #ad1f6c;
	--tf-color-primary-hover: #8a1755;
	--tf-color-primary-contrast: #fff6fb;
	--tf-color-accent: #a06f05;
	--tf-color-surface: #fdf6fa;
	--tf-color-surface-alt: #f7e7f1;
	--tf-color-text: #311b29;
	--tf-color-text-muted: #7b566f;
	--tf-color-border: #a57d97;
	--tf-color-error: #cf3630;
	--tf-color-success: #1e7f4b;
}

@media (prefers-color-scheme: dark) {
	[data-tf-palette="prisma"]:not([data-tf-mode="light"]) {
		--tf-color-primary: #e177b0;
		--tf-color-primary-hover: #e98fc0;
		--tf-color-primary-contrast: #1d0e17;
		--tf-color-accent: #f0c04d;
		--tf-color-surface: #1c1220;
		--tf-color-surface-alt: #291a2e;
		--tf-color-text: #ebdee7;
		--tf-color-text-muted: #b899ae;
		--tf-color-border: #825e78;
		--tf-color-error: #df514c;
		--tf-color-success: #2b935c;
	}
}

[data-tf-palette="prisma"][data-tf-mode="dark"] {
	--tf-color-primary: #e177b0;
	--tf-color-primary-hover: #e98fc0;
	--tf-color-primary-contrast: #1d0e17;
	--tf-color-accent: #f0c04d;
	--tf-color-surface: #1c1220;
	--tf-color-surface-alt: #291a2e;
	--tf-color-text: #ebdee7;
	--tf-color-text-muted: #b899ae;
	--tf-color-border: #825e78;
	--tf-color-error: #df514c;
	--tf-color-success: #2b935c;
}

/* Pixel — Violeta eléctrico con acento lima. Superficie lavanda: digital y jugada, pero legible. */
[data-tf-palette="pixel"] {
	--tf-color-primary: #5b48e0;
	--tf-color-primary-hover: #4738b8;
	--tf-color-primary-contrast: #faf9ff;
	--tf-color-accent: #5f8f0c;
	--tf-color-surface: #f9f8fe;
	--tf-color-surface-alt: #edeafb;
	--tf-color-text: #29243f;
	--tf-color-text-muted: #675f86;
	--tf-color-border: #8780a3;
	--tf-color-error: #cf3731;
	--tf-color-success: #1e7f4b;
}

@media (prefers-color-scheme: dark) {
	[data-tf-palette="pixel"]:not([data-tf-mode="light"]) {
		--tf-color-primary: #9a8ff2;
		--tf-color-primary-hover: #ada4f6;
		--tf-color-primary-contrast: #120f1e;
		--tf-color-accent: #9fd137;
		--tf-color-surface: #14121f;
		--tf-color-surface-alt: #1f1b30;
		--tf-color-text: #e1deec;
		--tf-color-text-muted: #a39cbd;
		--tf-color-border: #6c648f;
		--tf-color-error: #df4e4a;
		--tf-color-success: #2a915a;
	}
}

[data-tf-palette="pixel"][data-tf-mode="dark"] {
	--tf-color-primary: #9a8ff2;
	--tf-color-primary-hover: #ada4f6;
	--tf-color-primary-contrast: #120f1e;
	--tf-color-accent: #9fd137;
	--tf-color-surface: #14121f;
	--tf-color-surface-alt: #1f1b30;
	--tf-color-text: #e1deec;
	--tf-color-text-muted: #a39cbd;
	--tf-color-border: #6c648f;
	--tf-color-error: #df4e4a;
	--tf-color-success: #2a915a;
}

/* Lima — Verde lima sobre grafito frío, con acento azul. Texto grafito en vez de negro: la más relajada a la vista. */
[data-tf-palette="lima"] {
	--tf-color-primary: #4c7a14;
	--tf-color-primary-hover: #3b600f;
	--tf-color-primary-contrast: #f8fcef;
	--tf-color-accent: #1f6fb5;
	--tf-color-surface: #fafbf8;
	--tf-color-surface-alt: #edf0e8;
	--tf-color-text: #333a42;
	--tf-color-text-muted: #5f6974;
	--tf-color-border: #717e8b;
	--tf-color-error: #cf3934;
	--tf-color-success: #1e814c;
}

@media (prefers-color-scheme: dark) {
	[data-tf-palette="lima"]:not([data-tf-mode="light"]) {
		--tf-color-primary: #9acb4c;
		--tf-color-primary-hover: #acd86a;
		--tf-color-primary-contrast: #121a06;
		--tf-color-accent: #58ace8;
		--tf-color-surface: #14181a;
		--tf-color-surface-alt: #1f2528;
		--tf-color-text: #d7dce1;
		--tf-color-text-muted: #97a6b0;
		--tf-color-border: #5f6e79;
		--tf-color-error: #e0534f;
		--tf-color-success: #2b945c;
	}
}

[data-tf-palette="lima"][data-tf-mode="dark"] {
	--tf-color-primary: #9acb4c;
	--tf-color-primary-hover: #acd86a;
	--tf-color-primary-contrast: #121a06;
	--tf-color-accent: #58ace8;
	--tf-color-surface: #14181a;
	--tf-color-surface-alt: #1f2528;
	--tf-color-text: #d7dce1;
	--tf-color-text-muted: #97a6b0;
	--tf-color-border: #5f6e79;
	--tf-color-error: #e0534f;
	--tf-color-success: #2b945c;
}

/* --- Tipografías (ver ADR 0021) -----------------------------------------
   Cada una solo cambia --tf-font-family; los archivos y los @font-face están
   en assets/fonts/. La pila de respaldo de cada familia es de su misma
   categoría, para que un carácter fuera de latin/latin-ext, o un navegador
   que no pudo bajar la fuente, no cambie de serif a sans en medio del texto.

   Sin atributo manda la del sistema, definida arriba con los demás tokens.
   "theme" no define familia: hereda la del sitio (regla más abajo). */

[data-tf-font="atkinson"] {
	--tf-font-family: "TrazoForms Atkinson Hyperlegible Next", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

[data-tf-font="inter"] {
	--tf-font-family: "TrazoForms Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

[data-tf-font="figtree"] {
	--tf-font-family: "TrazoForms Figtree", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

[data-tf-font="source-serif"] {
	--tf-font-family: "TrazoForms Source Serif 4", Georgia, Cambria, "Times New Roman", serif;
}

[data-tf-font="literata"] {
	--tf-font-family: "TrazoForms Literata", Georgia, Cambria, "Times New Roman", serif;
}

[data-tf-font="lora"] {
	--tf-font-family: "TrazoForms Lora", Georgia, Cambria, "Times New Roman", serif;
}

.trazoforms-form {
	font-family: var(--tf-font-family);
	font-size: var(--tf-font-size-base);
	line-height: var(--tf-line-height);
	color: var(--tf-color-text);
	background-color: var(--tf-color-surface);
	/* ~640px es el ancho donde una línea de texto sigue siendo cómoda de leer.
	   Con `width: 100%` la tarjeta se adapta a lo que haya disponible: sin eso,
	   dentro de un contenedor flex se quedaba en 640 px y en un teléfono el
	   formulario se salía de la pantalla. */
	width: 100%;
	max-width: 640px;
	padding: var(--tf-form-padding);
	box-sizing: border-box;

	/* Rejilla de 12 columnas (ver ADR 0027). Cada campo ocupa el ancho que
	   tenga configurado y los que caben juntos se acomodan solos en la misma
	   fila, sin que haya que armar "filas" a mano. Todo lo demás —encabezado,
	   descripción, errores, botones— ocupa la fila entera. */
	display: grid;
	grid-template-columns: repeat(12, minmax(0, 1fr));
	gap: var(--tf-space-lg) var(--tf-space-md);
	align-items: start;
}

.trazoforms-form > * {
	grid-column: 1 / -1;
	min-width: 0;
}

/* Cada campo empieza su propia fila: arranca en la primera columna. Angostar
   un campo deja el hueco de la derecha vacío, y ahí se queda hasta que se
   arrastre otro campo adentro. El relleno automático haría que el formulario
   se reacomodara solo al tocar un ancho, moviendo campos que nadie pidió
   mover. */
.trazoforms-width-12 { grid-column: 1 / span 12; }
.trazoforms-width-9 { grid-column: 1 / span 9; }
.trazoforms-width-8 { grid-column: 1 / span 8; }
.trazoforms-width-6 { grid-column: 1 / span 6; }
.trazoforms-width-4 { grid-column: 1 / span 4; }
.trazoforms-width-3 { grid-column: 1 / span 3; }

/* «A la par del anterior»: el campo deja de exigir la primera columna y se
   acomoda a continuación, si cabe en lo que queda de la fila. */
.trazoforms-same-row.trazoforms-width-12 { grid-column: span 12; }
.trazoforms-same-row.trazoforms-width-9 { grid-column: span 9; }
.trazoforms-same-row.trazoforms-width-8 { grid-column: span 8; }
.trazoforms-same-row.trazoforms-width-6 { grid-column: span 6; }
.trazoforms-same-row.trazoforms-width-4 { grid-column: span 4; }
.trazoforms-same-row.trazoforms-width-3 { grid-column: span 3; }

/* En un teléfono no hay ancho para compartir fila: todo vuelve a una columna.
   Es la regla de oro del diseño de formularios (una sola columna), y acá
   además es lo único legible. */
@media (max-width: 600px) {
	.trazoforms-form > * {
		grid-column: 1 / -1 !important;
	}
}

.trazoforms-form *,
.trazoforms-form *::before,
.trazoforms-form *::after {
	box-sizing: border-box;
}

.trazoforms-form[data-tf-font="theme"] {
	font-family: inherit;
}

/* Los controles no heredan la fuente por defecto en los navegadores, y los
   temas suelen fijar la de sus títulos: sin esto, el botón y el título del
   encabezado se quedarían con otra tipografía que el resto del formulario. */
.trazoforms-form :is(input, select, textarea, button),
.trazoforms-form .trazoforms-header-title {
	font-family: inherit;
}

/* --- Página de vista previa (ver Form_Preview) ---------------------------
   Es una página propia, sin el tema alrededor, así que acá va lo mínimo para
   que el formulario no quede pegado al borde. */

body.trazoforms-preview-page {
	margin: 0;
	background-color: var(--tf-color-surface-alt, #f6f7f7);
}

.trazoforms-preview-bar {
	margin: 0;
	padding: var(--tf-space-sm, 8px) var(--tf-space-md, 16px);
	background: #1d2327;
	color: #fff;
	font: 400 14px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
	text-align: center;
}

.trazoforms-preview-main {
	padding: 40px 16px;
	display: flex;
	justify-content: center;
}

/* En móvil la tarjeta respira menos: 40px de relleno a 375px de ancho se
   comen la mitad de la pantalla. Ver .claude/skills/diseno-visual. */
@media (max-width: 600px) {
	.trazoforms-form {
		--tf-form-padding: var(--tf-space-lg);
	}

	/* Ancho completo: en un teléfono es lo que queda cómodo para el pulgar. */
	.trazoforms-submit {
		width: 100%;
	}
}

/* --- Encabezado del formulario (opcional, ver ADR 0005) --- */

.trazoforms-header {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--tf-space-sm);
	/* Sin relleno propio: ya lo pone el formulario. Con imagen de fondo sí lo
	   necesita, y se lo devuelve la regla de .trazoforms-header-has-bg. */
	padding: 0;
	border-radius: var(--tf-radius-md);
	background-color: var(--tf-color-surface);
	background-size: cover;
	background-position: center;
}

/* Alineación del encabezado, configurable por formulario. Centrado es el
   valor por defecto; a la izquierda alinea el título con las etiquetas. */
.trazoforms-header-align-center {
	align-items: center;
	text-align: center;
}

.trazoforms-header-align-left {
	align-items: flex-start;
	text-align: left;
}

.trazoforms-header-align-right {
	align-items: flex-end;
	text-align: right;
}

.trazoforms-header-logo {
	max-height: 64px;
	max-width: 200px;
	object-fit: contain;
}

/* Dos clases: le ganan a las reglas habituales de un tema («.entry-content h2»),
   que antes le cambiaban tamaño, color y mayúsculas al título. */
.trazoforms-form .trazoforms-header-title,
.trazoforms-builder-canvas .trazoforms-header-title {
	margin: 0;
	padding: 0;
	font-size: var(--tf-font-size-title);
	line-height: 1.3;
	font-weight: var(--tf-font-weight-label);
	letter-spacing: normal;
	text-transform: none;
	color: var(--tf-color-text);
}

/* Con imagen de fondo: texto blanco + sombra para que se lea encima de
   cualquier imagen, sin necesitar que el usuario elija un color de texto. */
.trazoforms-header-has-bg {
	position: relative;
	padding: var(--tf-space-xl) var(--tf-space-lg);
}

.trazoforms-header-has-bg::before {
	content: "";
	position: absolute;
	inset: 0;
	background: rgba(0, 0, 0, 0.4);
	border-radius: inherit;
}

.trazoforms-header-has-bg .trazoforms-header-title {
	position: relative;
	color: #fff;
	text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}

.trazoforms-header-has-bg .trazoforms-header-logo {
	position: relative;
}

.trazoforms-field {
	display: flex;
	flex-direction: column;
	gap: var(--tf-space-sm);
}

.trazoforms-label {
	font-size: var(--tf-font-size-label);
	font-weight: var(--tf-font-weight-label);
	color: var(--tf-color-label);
}

/* --- Ubicación de la etiqueta (ajuste por campo, bloque 1) ---
   "Arriba" es el valor por defecto y la recomendación de UX (ver
   docs/FORM_DESIGN_BEST_PRACTICES.md, punto 8): la etiqueta sobre el campo se
   lee más rápido y no se rompe en móvil. Las variantes laterales existen
   porque hay formularios cortos y densos donde se piden, pero vuelven a
   apilarse por debajo de 600px para no romper el layout en pantallas chicas. */

@media (min-width: 600px) {

	.trazoforms-field.trazoforms-label-left,
	.trazoforms-field.trazoforms-label-right {
		display: grid;
		grid-template-columns: minmax(6rem, 12rem) 1fr;
		align-items: center;
		column-gap: var(--tf-space-sm);
	}

	.trazoforms-field.trazoforms-label-right {
		grid-template-columns: 1fr minmax(6rem, 12rem);
	}

	.trazoforms-field.trazoforms-label-right > .trazoforms-label {
		order: 2;
	}

	/* La ayuda, el error y el contador se alinean con el control, no con la
	   etiqueta — si no, quedan colgando en la columna equivocada. */
	.trazoforms-field.trazoforms-label-left > .trazoforms-help,
	.trazoforms-field.trazoforms-label-left > .trazoforms-error,
	.trazoforms-field.trazoforms-label-left > .trazoforms-counter {
		grid-column: 2;
	}

	.trazoforms-field.trazoforms-label-right > .trazoforms-help,
	.trazoforms-field.trazoforms-label-right > .trazoforms-error,
	.trazoforms-field.trazoforms-label-right > .trazoforms-counter {
		grid-column: 1;
	}
}

.trazoforms-required {
	color: var(--tf-color-error);
}

.trazoforms-optional {
	color: var(--tf-color-help);
	font-weight: 400;
	font-size: var(--tf-font-size-help);
}

.trazoforms-input,
.trazoforms-select {
	font-size: var(--tf-font-size-input);
	font-family: inherit;
	line-height: var(--tf-line-height);
	min-height: var(--tf-control-min-height);
	padding: var(--tf-control-padding-y) var(--tf-control-padding-x);
	border: 1px solid var(--tf-color-border);
	border-radius: var(--tf-radius-sm);
	background: var(--tf-color-surface);
	color: var(--tf-color-text);
	transition: border-color var(--tf-anim-duration) var(--tf-anim-easing),
		box-shadow var(--tf-anim-duration) var(--tf-anim-easing);
}

.trazoforms-input:focus,
.trazoforms-select:focus {
	outline: none;
	border-color: var(--tf-color-border-focus);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--tf-color-border-focus) 20%, transparent);
}

.trazoforms-help {
	font-size: var(--tf-font-size-help);
	color: var(--tf-color-help);
	margin: 0;
}

.trazoforms-counter {
	font-size: var(--tf-font-size-help);
	color: var(--tf-color-help);
	margin: 0;
	text-align: right;
}

/* --- Opciones en columnas (bloque 1, pasada 2) ---
   Vuelven a una sola columna bajo 600px: dos o tres columnas de opciones en un
   teléfono dejan objetivos táctiles demasiado angostos. */

@media (min-width: 600px) {

	/* Se repite .trazoforms-choice-group en el selector para ganarle por
	   especificidad a la regla base (display:flex), sin depender de en qué
	   orden queden los bloques dentro del archivo. */
	.trazoforms-choice-group.trazoforms-choice-columns-2,
	.trazoforms-choice-group.trazoforms-choice-columns-3 {
		display: grid;
		column-gap: var(--tf-space-md, 16px);
		row-gap: var(--tf-space-xs);
	}

	.trazoforms-choice-group.trazoforms-choice-columns-2 {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.trazoforms-choice-group.trazoforms-choice-columns-3 {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	/* El campo de "Otro" y el botón de marcar todas ocupan la fila completa:
	   no son una opción más de la lista. */
	.trazoforms-choice-other,
	.trazoforms-select-all {
		grid-column: 1 / -1;
	}
}

.trazoforms-choice-other {
	margin-top: var(--tf-space-xs, 4px);
}

.trazoforms-select-all {
	align-self: start;
	justify-self: start;
	margin-bottom: var(--tf-space-xs, 4px);
	padding: 0;
	border: 0;
	background: none;
	color: var(--tf-color-help);
	font-size: var(--tf-font-size-help);
	font-family: inherit;
	text-decoration: underline;
	cursor: pointer;
}

/* --- Selección múltiple (ADR 0030) ---
   Una caja con el mismo borde, fondo y radio que los demás controles. Arriba,
   lo elegido como etiquetas y el buscador; abajo, las opciones como casillas,
   con altura máxima y desplazamiento para listas largas. Regla de espaciado:
   las herramientas se separan de la lista más que las opciones entre sí. */

.trazoforms-multiselect {
	display: flex;
	flex-direction: column;
	gap: var(--tf-space-sm);
	padding: var(--tf-space-sm) var(--tf-control-padding-x);
	border: 1px solid var(--tf-color-border);
	border-radius: var(--tf-radius-sm);
	background: var(--tf-color-surface);
	color: var(--tf-color-text);
	transition: border-color var(--tf-anim-duration) var(--tf-anim-easing),
		box-shadow var(--tf-anim-duration) var(--tf-anim-easing);
}

.trazoforms-multiselect:focus-within {
	border-color: var(--tf-color-border-focus);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--tf-color-border-focus) 20%, transparent);
}

.trazoforms-multiselect-tools {
	display: flex;
	flex-direction: column;
	gap: var(--tf-space-sm);
	padding-bottom: var(--tf-space-sm);
	border-bottom: 1px solid color-mix(in srgb, var(--tf-color-border) 40%, transparent);
}

.trazoforms-multiselect-tools[hidden] {
	display: none;
}

.trazoforms-multiselect-chips {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--tf-space-xs);
	min-height: 28px;
}

/* «2 de 4», al final de las etiquetas. */
.trazoforms-multiselect-count {
	margin-left: auto;
	color: var(--tf-color-help);
	font-size: var(--tf-font-size-help);
}

/* Con el máximo alcanzado, las que faltan se ven atenuadas. */
.trazoforms-multiselect .trazoforms-choice.is-unavailable {
	opacity: 0.5;
	cursor: not-allowed;
}

.trazoforms-multiselect-none {
	color: var(--tf-color-help);
	font-size: var(--tf-font-size-help);
}

.trazoforms-chip {
	display: inline-flex;
	align-items: center;
	gap: var(--tf-space-xs);
	max-width: 100%;
	padding: 2px 4px 2px 10px;
	border-radius: 999px;
	background: color-mix(in srgb, var(--tf-color-primary) 14%, var(--tf-color-surface));
	color: var(--tf-color-text);
	font-size: var(--tf-font-size-help);
	line-height: 1.5;
}

.trazoforms-chip-label {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.trazoforms-chip-more {
	padding-right: 10px;
	color: var(--tf-color-help);
	background: var(--tf-color-surface-alt);
}

/* 24 px: el mínimo de WCAG 2.2 (2.5.8) para un objetivo táctil. */
.trazoforms-chip-remove {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 24px;
	height: 24px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: none;
	color: inherit;
	cursor: pointer;
}

.trazoforms-multiselect .trazoforms-chip-remove .trazoforms-icon {
	width: 14px;
	height: 14px;
}

.trazoforms-chip-remove:hover:not(:disabled) {
	background: color-mix(in srgb, var(--tf-color-primary) 22%, transparent);
}

.trazoforms-chip-remove:focus-visible {
	outline: 2px solid var(--tf-color-border-focus);
	outline-offset: 1px;
}

.trazoforms-chip-remove:disabled {
	cursor: default;
}

.trazoforms-multiselect-search {
	position: relative;
	display: flex;
	align-items: center;
}

/* Doble clase a propósito: los estilos de WordPress y de muchos temas para
   input[type="search"] y los iconos del lienzo le ganan a una sola. */
.trazoforms-multiselect .trazoforms-multiselect-search .trazoforms-icon {
	position: absolute;
	left: 10px;
	width: 18px;
	height: 18px;
	color: var(--tf-color-help);
	pointer-events: none;
}

.trazoforms-multiselect .trazoforms-multiselect-search-input {
	appearance: none;
	box-sizing: border-box;
	width: 100%;
	margin: 0;
	box-shadow: none;
	min-height: 40px;
	padding: 6px 12px 6px 36px;
	border: 1px solid color-mix(in srgb, var(--tf-color-border) 60%, transparent);
	border-radius: var(--tf-radius-sm);
	background: var(--tf-color-surface-alt);
	color: var(--tf-color-text);
	font: inherit;
	font-size: var(--tf-font-size-input);
}

.trazoforms-multiselect .trazoforms-multiselect-search-input:focus {
	outline: none;
	border-color: var(--tf-color-border-focus);
}

/* Listas largas: se desplaza la lista, no el formulario entero. */
.trazoforms-multiselect-options {
	max-height: 15rem;
	overflow-y: auto;
	overscroll-behavior: contain;
}

/* Una opción descartada por el buscador. [hidden] no alcanza: las opciones
   son flex y esa regla le gana al atributo. */
.trazoforms-multiselect-options .trazoforms-choice[hidden] {
	display: none;
}

.trazoforms-multiselect-empty {
	margin: 0;
	color: var(--tf-color-help);
	font-size: var(--tf-font-size-help);
}

/* --- Casilla con prefijo (ADR 0034 y 0035) ---
   Un prefijo fijo pegado a la casilla, como una sola caja: «+506» en el
   teléfono, «https://» en el sitio web, o la lista de países del teléfono. */

.trazoforms-input-group {
	position: relative;
	display: flex;
	align-items: stretch;
}

.trazoforms-input-group .trazoforms-input {
	flex: 1;
	min-width: 0;
}

/* Pegada al prefijo: sin esquinas redondeadas de ese lado. */
.trazoforms-input-prefix + .trazoforms-input,
.trazoforms-phone-country + .trazoforms-input {
	border-top-left-radius: 0;
	border-bottom-left-radius: 0;
}

/* Pegada a lo que va a su derecha (el calendario, a. m./p. m.). */
.trazoforms-input-group .trazoforms-input:has(+ .trazoforms-input-suffix:not([hidden])),
.trazoforms-input-group .trazoforms-input:has(+ .trazoforms-time-period) {
	border-top-right-radius: 0;
	border-bottom-right-radius: 0;
}

.trazoforms-input-suffix {
	display: flex;
	flex: none;
	align-items: center;
	justify-content: center;
	min-width: var(--tf-control-min-height);
	padding: 0 var(--tf-space-sm);
	border: 1px solid var(--tf-color-border);
	border-left: 0;
	border-radius: 0 var(--tf-radius-sm) var(--tf-radius-sm) 0;
	background: var(--tf-color-surface-alt);
	color: var(--tf-color-text);
	cursor: pointer;
}

.trazoforms-input-suffix[hidden] {
	display: none;
}

/* Triple clase: la regla general de íconos del formulario, más abajo en la
   hoja, los deja en 1em. */
.trazoforms-input-group .trazoforms-input-suffix .trazoforms-icon {
	width: 20px;
	height: 20px;
}

.trazoforms-input-suffix:hover:not(:disabled) {
	background: color-mix(in srgb, var(--tf-color-primary) 12%, var(--tf-color-surface-alt));
}

.trazoforms-input-suffix:focus-visible {
	outline: 2px solid var(--tf-color-border-focus);
	outline-offset: 2px;
}

.trazoforms-input-suffix:disabled {
	cursor: default;
}

/* El control nativo de fecha solo existe para abrir el calendario del
   sistema: invisible y fuera del recorrido del teclado. */
.trazoforms-date-native {
	position: absolute;
	right: 0;
	bottom: 0;
	width: 1px;
	height: 1px;
	padding: 0;
	border: 0;
	opacity: 0;
	pointer-events: none;
}

.trazoforms-time .trazoforms-time-period {
	flex: none;
	width: auto;
	border-left: 0;
	border-top-left-radius: 0;
	border-bottom-left-radius: 0;
}

/* Con el reloj a su derecha, a. m./p. m. queda pegado a él. */
.trazoforms-time .trazoforms-time-period:has(+ .trazoforms-input-suffix:not([hidden])) {
	border-top-right-radius: 0;
	border-bottom-right-radius: 0;
}

/* El campo con un selector abierto va por encima de los que siguen: cada
   campo es su propia capa por la animación de entrada. */
.trazoforms-field.trazoforms-field-popup-open {
	position: relative;
	z-index: 20;
}

/* --- Selector de hora estilo ruleta (ADR 0036) ---
   Tres filas visibles por rueda: la anterior, la elegida (en la franja del
   centro) y la siguiente. --tf-wheel-row es el alto de una fila: la rueda
   mide tres, y el relleno de una fila arriba y abajo deja que la primera y
   la última también lleguen al centro. */
.trazoforms-time-picker {
	--tf-wheel-row: 36px;
	position: absolute;
	top: calc(100% + var(--tf-space-xs));
	right: 0;
	z-index: 10;
	display: flex;
	align-items: center;
	gap: var(--tf-space-xs);
	padding: var(--tf-space-xs) var(--tf-space-sm);
	border: 1px solid var(--tf-color-border);
	border-radius: var(--tf-radius-sm);
	background: var(--tf-color-surface);
	color: var(--tf-color-text);
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);
}

.trazoforms-time-picker[hidden] {
	display: none;
}

/* La franja del centro, detrás de las ruedas. */
.trazoforms-time-picker::before {
	content: "";
	position: absolute;
	top: 50%;
	right: var(--tf-space-xs);
	left: var(--tf-space-xs);
	height: var(--tf-wheel-row);
	border-radius: var(--tf-radius-sm);
	background: var(--tf-color-surface-alt);
	transform: translateY(-50%);
	pointer-events: none;
}

.trazoforms-wheel {
	position: relative;
	height: calc(var(--tf-wheel-row) * 3);
	min-width: 3rem;
	padding: var(--tf-wheel-row) 0;
	overflow-y: auto;
	overscroll-behavior: contain;
	scroll-snap-type: y mandatory;
	scrollbar-width: none;
	border-radius: var(--tf-radius-sm);
	/* Las filas de los bordes se desvanecen, como en una ruleta. */
	mask-image: linear-gradient(to bottom, transparent, #000 30%, #000 70%, transparent);
}

.trazoforms-wheel::-webkit-scrollbar {
	display: none;
}

.trazoforms-wheel:focus-visible {
	outline: 2px solid var(--tf-color-border-focus);
	outline-offset: 1px;
}

.trazoforms-wheel-item {
	display: flex;
	align-items: center;
	justify-content: center;
	height: var(--tf-wheel-row);
	padding: 0 var(--tf-space-sm);
	scroll-snap-align: center;
	color: var(--tf-color-help);
	font-size: var(--tf-font-size-input);
	cursor: pointer;
}

.trazoforms-wheel-item.is-selected {
	color: var(--tf-color-text);
	font-weight: 600;
}

.trazoforms-wheel-colon {
	position: relative;
	font-weight: 600;
}

.trazoforms-input-prefix {
	display: flex;
	flex: none;
	align-items: center;
	padding: 0 var(--tf-control-padding-x);
	border: 1px solid var(--tf-color-border);
	border-right: 0;
	border-radius: var(--tf-radius-sm) 0 0 var(--tf-radius-sm);
	background: var(--tf-color-surface-alt);
	color: var(--tf-color-text);
	font-size: var(--tf-font-size-input);
}

/* La lista de países del teléfono hace de prefijo, sin comerse el espacio
   del número. */
.trazoforms-input-group .trazoforms-phone-country {
	flex: none;
	width: auto;
	max-width: 45%;
	border-right: 0;
	border-top-right-radius: 0;
	border-bottom-right-radius: 0;
}

/* --- Campos compuestos: nombre y dirección (bloque 3) ---
   Cada subcampo lleva su propia etiqueta visible. Se apilan en una columna en
   móvil y se reparten en dos a partir de 600px; las señas exactas ocupan el
   ancho completo porque es texto largo. */

/* Dirección (ADR 0032): país y provincia traen su lista y un espacio para
   escribir («Otro», o un país sin lista), y el script oculta lo que no
   corresponde. [hidden] solo no alcanza: los controles tienen su display. */
.trazoforms-subfields-address [hidden] {
	display: none;
}

.trazoforms-address-other {
	margin-top: var(--tf-space-xs);
}

/* Sin lista delante (país sin provincias, u «Otro» como país), el espacio
   para escribir es el único control: va alineado con los de al lado. */
.trazoforms-subfields-address [hidden] + .trazoforms-address-other {
	margin-top: 0;
}

.trazoforms-subfields {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--tf-space-sm, 12px);
}

@media (min-width: 600px) {

	.trazoforms-subfields {
		grid-template-columns: 1fr 1fr;
	}

	.trazoforms-subfields-address .trazoforms-subfield-senas {
		grid-column: 1 / -1;
	}
}

.trazoforms-subfield {
	display: flex;
	flex-direction: column;
	gap: var(--tf-space-xs, 4px);
	min-width: 0;
}

.trazoforms-sublabel {
	font-size: var(--tf-font-size-help);
	color: var(--tf-color-help);
}

.trazoforms-subfield textarea {
	resize: vertical;
}

/* Confirmación tras un envío correcto (bloque 6). Reemplaza al formulario, no
   se superpone: reofrecerlo invitaría a enviar dos veces lo mismo. */
.trazoforms-confirmation {
	padding: var(--tf-space-lg, 24px) 0;
	text-align: center;
	color: var(--tf-color-label);
}

.trazoforms-form .trazoforms-icon,
.trazoforms-builder-canvas .trazoforms-icon {
	width: 1em;
	height: 1em;
	flex-shrink: 0;
	stroke-width: var(--tf-icon-stroke);
}

/* El check de la confirmación usa el color de éxito de la paleta, que ya
   está verificado a 4.5:1 contra la superficie (dev/tools/contrast-check.php);
   un gráfico solo necesita 3:1. */
.trazoforms-confirmation-icon {
	display: block;
	margin: 0 auto var(--tf-space-sm, 12px);
	font-size: 2.5rem;
	line-height: 0;
	color: var(--tf-color-success);
}

.trazoforms-confirmation p {
	margin: 0 0 var(--tf-space-sm, 12px);
}

.trazoforms-confirmation p:last-child {
	margin-bottom: 0;
}

/* El mensaje viene del editor visual (ADR 0046): una imagen más ancha que
   el formulario se ajusta a él, y una más chica no se estira. */
.trazoforms-confirmation-message img {
	max-width: 100%;
	height: auto;
}

.trazoforms-confirmation-message .aligncenter {
	display: block;
	margin-left: auto;
	margin-right: auto;
}

.trazoforms-confirmation-message .alignleft {
	float: left;
	margin: 0 var(--tf-space-sm, 12px) var(--tf-space-sm, 12px) 0;
}

.trazoforms-confirmation-message .alignright {
	float: right;
	margin: 0 0 var(--tf-space-sm, 12px) var(--tf-space-sm, 12px);
}

.trazoforms-confirmation-message::after {
	content: "";
	display: table;
	clear: both;
}

.trazoforms-confirmation-message .wp-caption {
	max-width: 100%;
}

.trazoforms-confirmation-message .wp-caption-text {
	font-size: var(--tf-font-size-help);
	color: var(--tf-color-help);
}

/* Se acerca al tope: se avisa con color, pero el texto por sí solo ya dice
   cuántos caracteres quedan — el color nunca es el único portador del dato
   (WCAG 1.4.1). */
.trazoforms-counter-low {
	color: var(--tf-color-error);
}

.trazoforms-error {
	font-size: var(--tf-font-size-help);
	color: var(--tf-color-error);
	margin: 0;
	min-height: 1em;
}

/* Reset del <fieldset> nativo del navegador — usamos nuestro propio spacing.
   Regla de espaciado: el título se separa de su contenido más de lo que se
   separan los elementos entre sí (ver la guía diseno-visual). La misma
   distancia que la etiqueta de un campo de texto a su caja. */
.trazoforms-fieldset {
	border: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: var(--tf-space-sm);
}

/* El navegador dibuja el <legend> fuera del contenido del fieldset, así que
   el gap de arriba no lo separa de la primera opción: el margen sí. */
.trazoforms-fieldset > legend {
	padding: 0;
	margin-bottom: calc(var(--tf-space-sm) + var(--tf-space-xs));
}

.trazoforms-form-error {
	color: var(--tf-color-error);
	background: color-mix(in srgb, var(--tf-color-error) 10%, transparent);
	border-radius: var(--tf-radius-sm);
	padding: var(--tf-space-sm) var(--tf-space-md);
	margin: 0;
}

.trazoforms-form-error-title {
	display: flex;
	align-items: flex-start;
	gap: var(--tf-space-sm);
	margin: 0;
}

/* Centrado óptico con la primera línea del texto, no con todo el párrafo. */
.trazoforms-form-error-title .trazoforms-icon {
	font-size: 1.25em;
	margin-top: 0.05em;
}

/* Rojo solo en el control con el problema (aria-invalid), no en todo el
   campo: en un correo con confirmación, la segunda casilla sin tocar no
   tiene por qué verse mal (ADR 0033). */
.trazoforms-field-has-error .trazoforms-input[aria-invalid="true"],
.trazoforms-field-has-error .trazoforms-select[aria-invalid="true"] {
	border-color: var(--tf-color-error);
}

/* Confirmación visual de que un campo quedó bien lleno: se pone en cuanto
   lo está, mientras se escribe (initLiveValidation, ADR 0033). */
.trazoforms-field-is-valid .trazoforms-input,
.trazoforms-field-is-valid .trazoforms-select {
	border-color: var(--tf-color-success);
}

/* Oculto visualmente pero disponible para lectores de pantalla (no display:none) */
/* Campo trampa antispam (ver ADR 0022). Fuera de la pantalla y no con
   display:none, que algunos bots detectan para saltearlo. Al ser absoluto no
   ocupa lugar ni suma un espacio en el flex del formulario. */
.trazoforms-trap {
	position: absolute !important;
	left: -10000px;
	top: auto;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	white-space: nowrap;
}

.trazoforms-section-break {
	padding-top: var(--tf-space-md);
}

/* Estilos del separador (Field_Section_Break::dividers). */
/* Grosor y color: los fija el campo con --tf-section-line-width y
   --tf-section-line-color (Field_Section_Break::line_style); sin ellos, el
   de la paleta. */
.trazoforms-section-break-line {
	border-top: var(--tf-section-line-width, 1px) solid var(--tf-section-line-color, var(--tf-color-border));
}

/* Línea, estrella, línea, centradas sobre el título. */
.trazoforms-section-ornament {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--tf-space-sm);
	margin-bottom: var(--tf-space-md);
	color: var(--tf-section-line-color, var(--tf-color-accent));
}

.trazoforms-section-ornament-line {
	width: calc(var(--tf-space-xl) * 2);
	height: var(--tf-section-line-width, 1px);
	border-radius: var(--tf-section-line-width, 1px);
	background: currentColor;
}

/* Dos clases, como la regla general de los iconos del formulario
   (.trazoforms-form .trazoforms-icon), para poder fijar su medida. */
.trazoforms-section-ornament .trazoforms-icon {
	width: var(--tf-space-md);
	height: var(--tf-space-md);
	flex: none;
}

/* «Solo espacio»: el relleno de arriba más la separación entre campos ya
   suman los 40 px de una sección; no hace falta nada más. */

/* Espacio extra arriba y abajo (Field_Section_Break::spaces), en pasos de
   la escala. Se suma a la separación de siempre entre campos. */
.trazoforms-section-space-above-sm { margin-top: var(--tf-space-sm); }
.trazoforms-section-space-above-md { margin-top: var(--tf-space-md); }
.trazoforms-section-space-above-lg { margin-top: var(--tf-space-lg); }
.trazoforms-section-space-above-xl { margin-top: var(--tf-space-xl); }
.trazoforms-section-space-below-sm { margin-bottom: var(--tf-space-sm); }
.trazoforms-section-space-below-md { margin-bottom: var(--tf-space-md); }
.trazoforms-section-space-below-lg { margin-bottom: var(--tf-space-lg); }
.trazoforms-section-space-below-xl { margin-bottom: var(--tf-space-xl); }

.trazoforms-form .trazoforms-section-title,
.trazoforms-builder-canvas .trazoforms-section-title {
	margin: 0 0 var(--tf-space-xs);
	padding: 0;
	font-family: inherit;
	font-size: var(--tf-font-size-section);
	font-weight: 600;
	line-height: 1.3;
	letter-spacing: normal;
	text-transform: none;
	color: var(--tf-color-text);
}

.trazoforms-form .trazoforms-section-description,
.trazoforms-builder-canvas .trazoforms-section-description {
	margin: 0;
	font-size: var(--tf-font-size-base);
	line-height: 1.5;
	color: var(--tf-color-help);
}

/* --- Bloque HTML: base propia, no la del tema ---
   Títulos, párrafos, listas, enlaces e imágenes con medidas del formulario.
   Sin esto tomaban las del tema, y el mismo bloque se veía bien en un sitio y
   descuadrado en otro. Dos clases en cada selector: le ganan a las reglas
   habituales de un tema («.entry-content h2»). */
.trazoforms-form .trazoforms-html-block,
.trazoforms-builder-canvas .trazoforms-html-block {
	font-size: var(--tf-font-size-base);
	line-height: 1.5;
	color: var(--tf-color-text);
	overflow-wrap: anywhere;
}

/* Sin margen antes del primero ni después del último: el espacio alrededor
   lo pone el formulario (o la caja de aviso). Tres clases, para ganarle a la
   regla de margen de cada párrafo, lista o cita. */
:is(.trazoforms-form, .trazoforms-builder-canvas) :is(.trazoforms-html-block, .trazoforms-html-box-content) > :first-child {
	margin-top: 0;
}

:is(.trazoforms-form, .trazoforms-builder-canvas) :is(.trazoforms-html-block, .trazoforms-html-box-content) > :last-child {
	margin-bottom: 0;
}

.trazoforms-form .trazoforms-html-block :is(p, ul, ol, blockquote, figure, table, pre),
.trazoforms-builder-canvas .trazoforms-html-block :is(p, ul, ol, blockquote, figure, table, pre) {
	margin: 0 0 var(--tf-space-md);
}

/* El tamaño va en cada elemento de texto y no solo en el bloque: el tema se
   lo pone directo a cada párrafo («.entry-content p»), y eso le gana a lo
   heredado. */
.trazoforms-form .trazoforms-html-block :is(p, li, blockquote, figcaption),
.trazoforms-builder-canvas .trazoforms-html-block :is(p, li, blockquote, figcaption) {
	font-size: var(--tf-font-size-base);
	line-height: 1.5;
	letter-spacing: normal;
}

.trazoforms-form .trazoforms-html-block :is(h2, h3, h4, h5, h6),
.trazoforms-builder-canvas .trazoforms-html-block :is(h2, h3, h4, h5, h6) {
	margin: var(--tf-space-lg) 0 var(--tf-space-sm);
	padding: 0;
	font-family: inherit;
	font-size: var(--tf-font-size-base);
	font-weight: 600;
	line-height: 1.3;
	color: var(--tf-color-text);
	letter-spacing: normal;
	text-transform: none;
}

/* El h2 es el título más grande que tiene sentido dentro de un formulario:
   el h1 es la página y el título del formulario va aparte. */
.trazoforms-form .trazoforms-html-block h2,
.trazoforms-builder-canvas .trazoforms-html-block h2 {
	font-size: var(--tf-font-size-title);
}

.trazoforms-form .trazoforms-html-block :is(ul, ol),
.trazoforms-builder-canvas .trazoforms-html-block :is(ul, ol) {
	padding-left: var(--tf-space-lg);
	list-style-position: outside;
}

.trazoforms-form .trazoforms-html-block ul,
.trazoforms-builder-canvas .trazoforms-html-block ul {
	list-style-type: disc;
}

.trazoforms-form .trazoforms-html-block ol,
.trazoforms-builder-canvas .trazoforms-html-block ol {
	list-style-type: decimal;
}

.trazoforms-form .trazoforms-html-block li,
.trazoforms-builder-canvas .trazoforms-html-block li {
	margin: 0 0 var(--tf-space-xs);
}

/* Enlaces: el color principal (4.5:1 verificado en contrast-check.php) y
   siempre subrayados, para que no dependan solo del color. */
.trazoforms-form .trazoforms-html-block a,
.trazoforms-builder-canvas .trazoforms-html-block a {
	color: var(--tf-color-primary);
	font-size: inherit;
	text-decoration: underline;
	text-underline-offset: 2px;
}

.trazoforms-form .trazoforms-html-block a:hover,
.trazoforms-builder-canvas .trazoforms-html-block a:hover {
	color: var(--tf-color-primary-hover);
}

.trazoforms-form .trazoforms-html-block a:focus-visible {
	outline: 2px solid var(--tf-color-border-focus);
	outline-offset: 2px;
	border-radius: 2px;
}

/* Imágenes y videos nunca más anchos que el formulario. */
.trazoforms-form .trazoforms-html-block :is(img, video),
.trazoforms-builder-canvas .trazoforms-html-block :is(img, video) {
	max-width: 100%;
	height: auto;
	border-radius: var(--tf-radius-sm);
}

.trazoforms-form .trazoforms-html-block blockquote,
.trazoforms-builder-canvas .trazoforms-html-block blockquote {
	margin-left: 0;
	margin-right: 0;
	padding: 0 0 0 var(--tf-space-md);
	border-left: var(--tf-space-xs) solid var(--tf-color-border);
	color: var(--tf-color-text-muted);
	font-style: normal;
}

.trazoforms-form .trazoforms-html-block hr,
.trazoforms-builder-canvas .trazoforms-html-block hr {
	margin: var(--tf-space-lg) 0;
	border: 0;
	border-top: 1px solid var(--tf-color-border);
}

.trazoforms-form .trazoforms-html-block table,
.trazoforms-builder-canvas .trazoforms-html-block table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--tf-font-size-label);
}

.trazoforms-form .trazoforms-html-block :is(th, td),
.trazoforms-builder-canvas .trazoforms-html-block :is(th, td) {
	padding: var(--tf-space-sm);
	border: 1px solid var(--tf-color-border);
	text-align: left;
}

/* Respuestas dentro del Bloque HTML (Field_Html::fill_answers). En el
   lienzo del builder, cada etiqueta es un distintivo con el nombre del
   campo, para ver dónde irá la respuesta. */
.trazoforms-builder-canvas .trazoforms-answer-preview {
	display: inline-block;
	padding: 0 var(--tf-space-xs);
	border: 1px dashed var(--tf-color-border);
	border-radius: var(--tf-radius-sm);
	background: var(--tf-color-surface-alt);
	color: var(--tf-color-text-muted);
	font-size: 0.9em;
	line-height: 1.4;
}

/* El resumen de lo respondido ({all_fields}): etiqueta y respuesta en dos
   columnas; en el teléfono, una debajo de la otra. */
.trazoforms-form .trazoforms-answers {
	display: grid;
	gap: var(--tf-space-sm);
	margin: 0 0 var(--tf-space-md);
}

.trazoforms-form .trazoforms-answers-row {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
	gap: var(--tf-space-md);
}

.trazoforms-form .trazoforms-answers-row[hidden] {
	display: none;
}

.trazoforms-form .trazoforms-answers dt {
	margin: 0;
	font-size: var(--tf-font-size-label);
	font-weight: 600;
	color: var(--tf-color-text-muted);
}

.trazoforms-form .trazoforms-answers dd {
	margin: 0;
	font-size: var(--tf-font-size-base);
	color: var(--tf-color-text);
	overflow-wrap: anywhere;
}

@media (max-width: 480px) {
	.trazoforms-form .trazoforms-answers-row {
		grid-template-columns: 1fr;
		gap: 0;
	}
}

/* Videos y mapas insertados (Field_Html::content_html): de todo el ancho y
   con su proporción, también en el teléfono. El recuadro lleva la del video
   (aspect-ratio en línea); un mapa, 4:3. */
.trazoforms-form .trazoforms-embed,
.trazoforms-builder-canvas .trazoforms-embed {
	position: relative;
	width: 100%;
	aspect-ratio: 16 / 9;
	margin: 0 0 var(--tf-space-md);
	overflow: hidden;
	border-radius: var(--tf-radius-sm);
	background: var(--tf-color-surface-alt);
}

.trazoforms-form .trazoforms-embed-map,
.trazoforms-builder-canvas .trazoforms-embed-map {
	aspect-ratio: 4 / 3;
}

.trazoforms-form .trazoforms-embed iframe,
.trazoforms-builder-canvas .trazoforms-embed iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: 0;
}

/* Cajas de aviso del Bloque HTML (Field_Html::boxes): un fondo apenas
   teñido, una barra del color del aviso y su icono. El texto sigue siendo el
   del formulario, que sobre un tinte del 8 % mantiene su contraste. */
.trazoforms-form .trazoforms-html-box,
.trazoforms-builder-canvas .trazoforms-html-box {
	--tf-box-color: var(--tf-color-accent);
	display: flex;
	align-items: flex-start;
	gap: var(--tf-space-sm);
	padding: var(--tf-space-md);
	border-left: var(--tf-space-xs) solid var(--tf-box-color);
	border-radius: var(--tf-radius-sm);
	background: var(--tf-color-surface-alt);
	background: color-mix(in srgb, var(--tf-box-color) 8%, var(--tf-color-surface));
}

.trazoforms-form .trazoforms-html-box-important,
.trazoforms-builder-canvas .trazoforms-html-box-important {
	--tf-box-color: var(--tf-color-error);
}

.trazoforms-html-box > .trazoforms-icon {
	/* Del alto de una línea de texto, alineado con la primera. */
	width: calc(var(--tf-space-md) + var(--tf-space-xs));
	height: calc(var(--tf-space-md) + var(--tf-space-xs));
	margin-top: 2px;
	color: var(--tf-box-color);
}

.trazoforms-html-box-content {
	flex: 1;
	min-width: 0;
}


/* --- Grupo de opciones (radio/checkbox) con marcador personalizable --- */

.trazoforms-choice-group {
	display: flex;
	flex-direction: column;
	gap: var(--tf-space-xs);
}

.trazoforms-choice {
	display: inline-flex;
	/* Arriba y no al centro: con un texto de dos líneas, el marcador centrado
	   queda flotando en la mitad de la frase. */
	align-items: flex-start;
	gap: var(--tf-space-sm);
	cursor: pointer;
	font-size: var(--tf-font-size-input);
	/* Sin altura mínima de control ni relleno: con el texto arriba, los 44px
	   dejaban un hueco debajo de cada opción. Cada opción mide una línea de
	   texto (24px, el mínimo de WCAG 2.2, 2.5.8) y el gap del grupo las
	   separa: unos 28px de una a la siguiente. */
	padding: 0;
}

/* El consentimiento es la letra pequeña del formulario, no una opción más.
   El marcador se recalcula solo con este tamaño de letra (ver --tf-marker-offset). */
.trazoforms-consent {
	font-size: var(--tf-font-size-help);
	color: var(--tf-color-help);
}

.trazoforms-choice input {
	position: absolute;
	opacity: 0;
	width: 1px;
	height: 1px;
}

.trazoforms-choice-marker {
	width: var(--tf-marker-size);
	height: var(--tf-marker-size);
	margin-top: var(--tf-marker-offset);
	border: var(--tf-marker-border);
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	transition: border-color var(--tf-anim-duration) var(--tf-anim-easing),
		background-color var(--tf-anim-duration) var(--tf-anim-easing);
}

/* data-marker en el contenedor decide la forma — todo editable por tokens */
.trazoforms-choice-group[data-marker="circle"] .trazoforms-choice-marker { border-radius: 50%; }
.trazoforms-choice-group[data-marker="square"] .trazoforms-choice-marker { border-radius: 4px; }
.trazoforms-choice-group[data-marker="check"] .trazoforms-choice-marker { border-radius: 4px; }

.trazoforms-choice input:checked + .trazoforms-choice-marker {
	border-color: var(--tf-marker-color-checked);
	background-color: var(--tf-marker-color-checked);
}

/* "check": al marcarse no se rellena; se dibuja una marca de verificación
   con dos bordes de un rectángulo girado, en el mismo color del marcador. */
.trazoforms-choice-group[data-marker="check"] .trazoforms-choice input:checked + .trazoforms-choice-marker {
	background-color: transparent;
}

.trazoforms-choice-group[data-marker="check"] .trazoforms-choice input:checked + .trazoforms-choice-marker::after {
	content: "";
	width: 30%;
	height: 55%;
	border: solid var(--tf-marker-color-checked);
	border-width: 0 2px 2px 0;
	transform: translateY(-10%) rotate(45deg);
}

.trazoforms-choice input:focus-visible + .trazoforms-choice-marker {
	outline: 2px solid var(--tf-color-border-focus);
	outline-offset: 2px;
}

/* Control de archivo propio (lo arma trazoforms-public.js). El campo nativo
   queda fuera de la vista pero sigue enfocable: es el que el teclado y el
   lector de pantalla usan, y el que valida el navegador. */
.trazoforms-file-native {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: 0;
	border: 0;
	min-height: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
}

.trazoforms-file-control {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: var(--tf-space-sm);
	min-height: var(--tf-control-min-height);
}

.trazoforms-file-button {
	display: inline-flex;
	align-items: center;
	min-height: var(--tf-control-min-height);
	padding: var(--tf-control-padding-y) var(--tf-space-md);
	border: 1px solid var(--tf-color-border);
	border-radius: var(--tf-radius-sm);
	background: var(--tf-color-surface-alt);
	color: var(--tf-color-text);
	font-size: var(--tf-font-size-input);
	font-weight: var(--tf-font-weight-label);
	cursor: pointer;
	transition: border-color var(--tf-anim-duration) var(--tf-anim-easing),
		background-color var(--tf-anim-duration) var(--tf-anim-easing);
}

.trazoforms-file-button:hover {
	border-color: var(--tf-color-primary);
}

/* El foco vive en el campo nativo, que no se ve: se dibuja sobre el botón. */
.trazoforms-file-native:focus-visible + .trazoforms-file-control .trazoforms-file-button {
	outline: 2px solid var(--tf-color-border-focus);
	outline-offset: 2px;
}

.trazoforms-file-name {
	font-size: var(--tf-font-size-input);
	overflow-wrap: anywhere;
}

.trazoforms-file-name-empty {
	color: var(--tf-color-help);
}

/* El botón nativo de "elegir archivo" (cuando no hay JavaScript) se ve del
   sistema y no del formulario; en modo oscuro queda blanco sobre un campo
   oscuro. */
.trazoforms-input[type="file"]::file-selector-button {
	font: inherit;
	margin-right: var(--tf-space-sm);
	padding: 6px var(--tf-space-md);
	border: 1px solid var(--tf-color-border);
	border-radius: var(--tf-radius-sm);
	background: var(--tf-color-surface-alt);
	color: var(--tf-color-text);
	cursor: pointer;
}

.trazoforms-input[type="file"]::file-selector-button:hover {
	border-color: var(--tf-color-primary);
}

/* Sugerencia de tipeo del correo («¿Quisiste decir…?», ADR 0033). La
   dirección sugerida es un botón: un clic la acepta. */
.trazoforms-email-suggestion {
	margin: var(--tf-space-xs) 0 0;
	font-size: var(--tf-font-size-help);
	color: var(--tf-color-help);
}

.trazoforms-email-suggestion[hidden] {
	display: none;
}

.trazoforms-email-suggestion-button {
	padding: 0;
	border: 0;
	background: none;
	/* El color del texto y no el principal: como texto, el principal no
	   llega a 4,5:1 en todas las paletas (solo se le exige 3:1, de botón). */
	color: var(--tf-color-text);
	font: inherit;
	font-weight: 600;
	text-decoration: underline;
	cursor: pointer;
}

.trazoforms-email-suggestion-button:focus-visible {
	outline: 2px solid var(--tf-color-border-focus);
	outline-offset: 2px;
}

.trazoforms-field-hint,
.trazoforms-file-kept {
	font-size: var(--tf-font-size-help);
	color: var(--tf-color-help);
	margin: var(--tf-space-xs) 0 0;
}

.trazoforms-file-kept strong {
	color: var(--tf-color-text);
	overflow-wrap: anywhere;
}

/* Color y esquinas: los fija el formulario con --tf-submit-* (ADR 0045,
   Form_Renderer::submit_actions_attrs); sin ellos, los de la paleta. El texto
   sobre un color propio lo elige el servidor, el que mejor se lee. */
.trazoforms-submit {
	align-self: flex-start;
	background: var(--tf-submit-bg, var(--tf-color-primary));
	color: var(--tf-submit-text, var(--tf-color-primary-contrast));
	border: none;
	border-radius: var(--tf-submit-radius, var(--tf-radius-sm));
	min-height: var(--tf-control-min-height);
	padding: 12px var(--tf-space-lg);
	font-size: var(--tf-font-size-input);
	line-height: var(--tf-line-height);
	font-weight: var(--tf-font-weight-label);
	cursor: pointer;
	transition: background-color var(--tf-anim-duration) var(--tf-anim-easing);
}

.trazoforms-submit:hover {
	background: var(--tf-submit-bg-hover, var(--tf-color-primary-hover));
}

/* Tamaños (Form_Renderer::submit_sizes). Mediano es el de siempre; todos
   conservan los 44 px de alto mínimo para tocarlo cómodo. */
.trazoforms-submit-small {
	padding: var(--tf-space-sm) var(--tf-space-md);
	font-size: var(--tf-font-size-label);
}

.trazoforms-submit-large {
	min-height: calc(var(--tf-control-min-height) + var(--tf-space-sm));
	padding: var(--tf-space-md) var(--tf-space-xl);
	font-size: var(--tf-font-size-section);
}

.trazoforms-submit:active {
	transform: translateY(0);
}

/* --- Animaciones de aparición por campo --- */

.trazoforms-anim-fade-up,
.trazoforms-anim-fade,
.trazoforms-anim-slide {
	opacity: 0;
	animation: tf-fade-up var(--tf-anim-duration) var(--tf-anim-easing) forwards;
	animation-delay: calc(var(--tf-field-index, 0) * 60ms);
}

.trazoforms-anim-fade {
	animation-name: tf-fade;
}

.trazoforms-anim-slide {
	animation-name: tf-slide-in;
}

@keyframes tf-fade-up {
	from { opacity: 0; transform: translateY(10px); }
	to { opacity: 1; transform: translateY(0); }
}

@keyframes tf-fade {
	from { opacity: 0; }
	to { opacity: 1; }
}

@keyframes tf-slide-in {
	from { opacity: 0; transform: translateX(-16px); }
	to { opacity: 1; transform: translateX(0); }
}

/* --- Confirmación de envío exitoso --- */

.trazoforms-success {
	display: flex;
	align-items: center;
	gap: var(--tf-space-sm);
	padding: var(--tf-space-md);
	border-radius: var(--tf-radius-md);
	background: color-mix(in srgb, var(--tf-color-success) 12%, transparent);
	color: var(--tf-color-success);
	animation: tf-fade-up var(--tf-anim-duration) var(--tf-anim-easing) forwards;
}

/* Respeto a accesibilidad: quien prefiere menos movimiento, no anima nada */
@media (prefers-reduced-motion: reduce) {
	.trazoforms-anim-fade-up,
	.trazoforms-anim-fade,
	.trazoforms-anim-slide,
	.trazoforms-success,
	.trazoforms-submit {
		animation: none !important;
		transition: none !important;
		opacity: 1 !important;
		transform: none !important;
	}
}

/* --- Ajustes generales del formulario (bloque 10) --- */

.trazoforms-form-description {
	color: var(--tf-color-help);
}

.trazoforms-form-description p {
	margin: 0 0 var(--tf-space-sm, 12px);
}

.trazoforms-required-text {
	color: var(--tf-color-help);
	font-weight: 400;
	font-size: var(--tf-font-size-help);
}

/* Resumen de errores al inicio: da el panorama cuando el formulario es largo
   y el primer error quedó fuera de la pantalla. */
.trazoforms-error-summary {
	margin: var(--tf-space-sm, 12px) 0 0;
	padding-left: var(--tf-space-lg, 24px);
}

.trazoforms-error-summary a {
	color: inherit;
}

/* Formulario cerrado (horario, cupo o sesión requerida). */
.trazoforms-unavailable {
	padding: var(--tf-space-lg, 24px) 0;
	text-align: center;
	color: var(--tf-color-label);
}

.trazoforms-unavailable p {
	margin: 0 0 var(--tf-space-sm, 12px);
}

.trazoforms-unavailable p:last-child {
	margin-bottom: 0;
}

/* --- Formularios de varias páginas (bloque 7) --- */

/* Avance de un formulario de varias páginas (Form_Renderer::render_progress):
   un círculo por paso y una línea que los une. La línea de cada paso va
   antes de su círculo y toma su estado: se pinta hasta el paso actual.

   Los círculos miden 40 px mientras quepan; con muchos pasos en una
   pantalla angosta se achican parejo hasta 24 px (el ancho de la lista,
   100cqw, repartido entre --tf-steps). Si ni así caben, la lista se
   desplaza de lado dentro de sí misma, sin romper la página. */
.trazoforms-steps {
	container-type: inline-size;
	display: flex;
	align-items: center;
	margin: 0;
	padding: 0;
	overflow-x: auto;
	list-style: none;
}

.trazoforms-step {
	--tf-step-size: clamp(var(--tf-space-lg), calc((100cqw - (var(--tf-steps, 1) - 1) * var(--tf-space-xs)) / var(--tf-steps, 1)), var(--tf-space-xl));
	display: flex;
	flex: 1;
	align-items: center;
	margin: 0;
}

.trazoforms-step:first-child {
	flex: none;
}

.trazoforms-step:not(:first-child)::before {
	content: "";
	flex: 1;
	min-width: var(--tf-space-xs);
	height: var(--tf-space-xs);
	background: var(--tf-color-border);
	transition: background-color var(--tf-anim-duration) var(--tf-anim-easing);
}

.trazoforms-step-circle {
	display: flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: var(--tf-step-size);
	height: var(--tf-step-size);
	border: 2px solid var(--tf-color-border);
	border-radius: 50%;
	background: var(--tf-color-surface);
	color: var(--tf-color-text-muted);
	font-size: clamp(var(--tf-font-size-help), calc(var(--tf-step-size) * 0.4), var(--tf-font-size-label));
	font-weight: 700;
	line-height: 1;
	transition: background-color var(--tf-anim-duration) var(--tf-anim-easing), border-color var(--tf-anim-duration) var(--tf-anim-easing);
}

.trazoforms-step-circle .trazoforms-icon {
	/* La mitad del círculo y trazo grueso: el ✓ se lee igual de firme que un número. */
	width: calc(var(--tf-step-size) / 2);
	height: calc(var(--tf-step-size) / 2);
	stroke-width: 3;
}

.trazoforms-step-current .trazoforms-step-circle {
	border-color: var(--tf-color-primary);
	background: var(--tf-color-primary);
	color: var(--tf-color-primary-contrast);
}

.trazoforms-step-current:not(:first-child)::before {
	background: var(--tf-color-primary);
}

.trazoforms-step-done .trazoforms-step-circle {
	border-color: var(--tf-color-success);
	background: var(--tf-color-success);
	color: var(--tf-color-surface);
}

.trazoforms-step-done:not(:first-child)::before {
	background: var(--tf-color-success);
}

/* Fila de botones: "Anterior" a la izquierda y el avance a la derecha, que es
   el orden en que se leen y el que esperan las manos en móvil. */
.trazoforms-actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--tf-space-sm, 12px);
}

/* En una sola página el botón queda a la izquierda, donde vuelve el ojo al
   terminar de leer. Con varios pasos comparte fila con "Anterior" y ahí sí se
   va a la derecha, que es el orden esperado de un asistente. */
.trazoforms-actions .trazoforms-submit:not(:only-child) {
	margin-left: auto;
}

/* Alineación elegida (Form_Renderer::submit_aligns). Centro y derecha
   llevan toda la fila; ahí el botón ya no se separa de «Anterior». */
.trazoforms-actions-center {
	justify-content: center;
}

.trazoforms-actions-right {
	justify-content: flex-end;
}

.trazoforms-actions:is(.trazoforms-actions-center, .trazoforms-actions-right) .trazoforms-submit:not(:only-child) {
	margin-left: 0;
}

/* Ancho elegido (Form_Renderer::submit_layout): una parte de la fila, en
   columnas de 12 como los campos; sin elegir, según el texto. En el teléfono,
   siempre de todo el ancho. */
.trazoforms-actions .trazoforms-submit {
	width: var(--tf-submit-width, auto);
}

@media (max-width: 600px) {
	.trazoforms-actions .trazoforms-submit {
		width: 100%;
	}
}

.trazoforms-nav-previous,
.trazoforms-nav-save {
	background: none;
	border: 1px solid var(--tf-color-border);
	color: var(--tf-color-label);
	font-family: inherit;
	font-size: var(--tf-font-size-input);
	padding: var(--tf-space-sm) var(--tf-space-md);
	border-radius: var(--tf-radius-sm);
	cursor: pointer;
}

.trazoforms-nav-save {
	border-style: dashed;
	font-size: var(--tf-font-size-help);
	color: var(--tf-color-help);
}

@media (prefers-reduced-motion: reduce) {

	.trazoforms-step::before,
	.trazoforms-step-circle {
		transition: none;
	}
}
