/* Nexioma · formulario de contacto común (contact.js; fundadores, 27 de octubre de 2026).
   Asset del contrato público (public-contract/ecosystem-shell.v1.json, brand.assets, revisión 2026-10-27.2): se copia byte
   a byte con su sha256. Se apoya en .form, .row, .btn y .btn--ghost de pulso.css y toma el color de la página con estas
   variables, que cada sitio (o cada página) define en su propia hoja, en el body o en un antepasado del formulario. Sin
   ellas, el formulario se ve en la casa (tinta), con los tokens de pulso.css:
     --cf-ground        fondo del formulario                       (var(--panel))
     --cf-ring          anillo del formulario y de los avisos      (var(--rule))
     --cf-shadow        sombra del formulario                      (ninguna)
     --cf-text          texto de los campos y de los avisos        (var(--text))
     --cf-text-2        etiquetas                                  (var(--text-2))
     --cf-text-3        ayudas, marcador y primera capa            (var(--text-3))
     --cf-field         fondo de los campos                        (rgba(0, 0, 0, .25))
     --cf-field-border  borde de los campos, al menos 3:1          (rgba(214, 228, 232, .42), 3,4:1 en la casa)
     --cf-accent        foco de los campos, casillas y la marca del aviso enviado (var(--research), el foco de la casa)
     --cf-error         texto y borde de los errores, al menos 4,5:1 (#ffa89e)
   Los botones son los .btn y .btn--ghost del sitio, que ya llevan su color. Los errores no dependen solo del color: cada
   uno tiene su texto. Sin animaciones. */
.cf { position: relative; background: var(--cf-ground, var(--panel)); color: var(--cf-text, var(--text)); box-shadow: 0 0 0 1px var(--cf-ring, var(--rule)), var(--cf-shadow, 0 0 #0000); }
.cf .cf__field { display: grid; gap: 6px; min-width: 0; align-content: start; }
.cf .cf__field > label { font-size: var(--t-xs); color: var(--cf-text-2, var(--text-2)); }
.cf input:not([type="checkbox"]), .cf textarea, .cf select {
  background: var(--cf-field, rgba(0, 0, 0, .25)); border-color: var(--cf-field-border, rgba(214, 228, 232, .42)); color: var(--cf-text, var(--text));
}
.cf input::placeholder, .cf textarea::placeholder { color: var(--cf-text-3, var(--text-3)); opacity: 1; }
.cf input:focus-visible, .cf textarea:focus-visible, .cf select:focus-visible { outline: 2px solid var(--cf-accent, var(--research)); outline-offset: 1px; border-color: transparent; }
/* El error, en todos los campos: con la misma especificidad que el borde normal (0,2,1) y después, para que le gane. */
.cf :is(input, textarea, select)[aria-invalid="true"] { border-color: var(--cf-error, #ffa89e); }
.cf .cf__hint { color: var(--cf-text-3, var(--text-3)); font-size: .75rem; line-height: 1.45; }
.cf .cf__error { color: var(--cf-error, #ffa89e); font-size: var(--t-xs); line-height: 1.45; }
.cf .cf__error[hidden] { display: none; }

/* Casillas: la de privacidad (obligatoria) y la de novedades (opcional), con la etiqueta al lado; la caja mide 20 px y
   toda la fila, con la etiqueta, es pulsable. */
.cf .cf__check { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 4px 12px; align-items: start; }
.cf .cf__check input { width: 20px; height: 20px; min-height: 0; margin: 1px 0 0; padding: 0; border: 0; border-radius: 0; background: none; accent-color: var(--cf-accent, var(--research)); cursor: pointer; }
.cf .cf__check input:focus-visible { outline: 2px solid var(--cf-accent, var(--research)); outline-offset: 2px; }
.cf .cf__check label { display: block; color: var(--cf-text, var(--text)); font-size: var(--t-s); line-height: 1.45; cursor: pointer; }
.cf .cf__check .cf__error { grid-column: 2; }
.cf .cf__check input[aria-invalid="true"] { outline: 2px solid var(--cf-error, #ffa89e); outline-offset: 2px; }

/* La primera capa de información sobre protección de datos, justo antes de la casilla que la acepta, con el enlace a la
   política de privacidad subrayado y en su propia línea. */
.cf .form__privacy { color: var(--cf-text-3, var(--text-3)); font-size: .75rem; line-height: 1.5; }
.cf .form__privacy a { display: block; width: fit-content; margin-top: 4px; color: inherit; text-underline-offset: 2px; }
.cf .form__privacy a:hover { color: var(--cf-text-2, var(--text-2)); }

/* La trampa anti-spam: fuera de la vista, del teclado y de los lectores de pantalla, pero en el formulario. */
.cf .cf__trap { position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }

.cf .cf__submit { justify-self: start; }
.cf .cf__submit:disabled, .cf .cf__retry:disabled { opacity: .62; cursor: progress; transform: none; }

/* El resultado, donde sigue el foco: recibido (con su marca, un SVG decorativo en el marcado: la CSP no admite imágenes
   data:) o el motivo del fallo, la dirección de correo y «Volver a
   intentarlo». */
.cf .cf__notice { display: grid; gap: 6px; padding: 14px 16px; border-radius: 14px; box-shadow: inset 0 0 0 1px var(--cf-ring, var(--rule)); color: var(--cf-text, var(--text)); font-size: var(--t-s); line-height: 1.5; }
.cf .cf__notice[hidden] { display: none; }
.cf .cf__notice:focus { outline: none; }
.cf .cf__notice:focus-visible { outline: 2px solid var(--cf-accent, var(--research)); outline-offset: 2px; }
.cf .cf__notice-title { font-weight: 500; }
.cf .cf__notice--done { grid-template-columns: 20px minmax(0, 1fr); column-gap: 12px; }
.cf .cf__mark { grid-row: span 2; width: 20px; height: 20px; margin-top: 1px; fill: none; stroke: var(--cf-accent, var(--research)); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.cf .cf__notice--error { box-shadow: inset 0 0 0 1px var(--cf-error, #ffa89e); }
.cf .cf__notice--error .cf__notice-title { color: var(--cf-text, var(--text)); }
.cf .cf__notice p:not(.cf__notice-title) { color: var(--cf-text-2, var(--text-2)); }
.cf .cf__notice code { font: inherit; color: var(--cf-text, var(--text)); user-select: all; overflow-wrap: anywhere; }
.cf .cf__retry { justify-self: start; min-height: 44px; margin-top: 6px; }
.cf .cf__retry[hidden] { display: none; } /* .btn es inline-flex: sin esto, el atributo hidden no lo ocultaría */
.cf .cf__noscript { color: var(--cf-text-2, var(--text-2)); font-size: var(--t-s); }
.cf .cf__noscript code { font: inherit; color: var(--cf-text, var(--text)); }

@media (forced-colors: active) {
  .cf :is(input, textarea, select)[aria-invalid="true"] { border-color: Mark; }
  .cf .cf__notice { border: 1px solid CanvasText; }
  .cf .cf__mark { stroke: CanvasText; }
}
