/* ARRA — Lenguaje de motion (decisión ago 2026: "muy dinámico" con easing de marca)
   Requiere tokens (--wp--custom--movimiento--salida, --wp--custom--movimiento--base). Activar con motion/arra-motion.js. */
:root {
  --arra-reveal-dist: 28px;
  --arra-reveal-dur: 640ms;
  --arra-stagger: 90ms;
}

/* 1 · Aparición al hacer scroll (añadir .in vía JS)
 *
 * La curva sale de una variable desde que el móvil usa una distinta a la del
 * ordenador: ver § 1b. Por defecto es la de frenada, que es la que tenía. */
.arra-reveal {
  transition: opacity var(--arra-reveal-dur) var(--arra-reveal-curva, var(--wp--custom--movimiento--salida)),
              transform var(--arra-reveal-dur) var(--arra-reveal-curva, var(--wp--custom--movimiento--salida));
  transition-delay: var(--arra-delay, 0ms);
}
/* El contenido es visible por defecto. Solo se esconde cuando el JS confirma
   que va a poder revelarlo: si el script falla o no llega, la pagina se ve
   entera en vez de quedarse en blanco esperando a un observador. */
.js-motion .arra-reveal:not(.in) {
  opacity: 0;
  transform: translateY(var(--arra-reveal-dist));
}
.arra-reveal.in { opacity: 1; transform: none; }

/* 1b · LA ENTRADA: EL BLOQUE SE ENFOCA, Y EL TITULAR LO HACE PALABRA A PALABRA
 *
 * El cliente eligió esto entre cinco maneras en
 * `preview/entrada-de-los-bloques.html`. Es el «individual» de jakub.kr, con
 * sus valores: 800 ms, curva (0.25, 0.46, 0.45, 0.94), 8 px de recorrido,
 * 8 px de desenfoque, y 80 ms entre palabras del titular.
 *
 * QUÉ CAMBIA RESPECTO A LO DE ARRIBA. El elemento deja de subir y pasa a
 * ENFOCARSE: sube 8 px en vez de 28, y el trabajo lo hace el foco. Y la
 * curva reparte el recorrido en vez de gastarlo al principio: resuelta la
 * bézier, la de frenada iba por el 69 % a los 200 ms sobre 640 y esta va por
 * el 45 %. Es el arreglo de los 53 elementos con la misma firma.
 *
 * EL TITULAR SE PARTE EN PALABRAS, y ahí hay una colisión que resolver:
 * siete de los `h2` de /corporate/ llevan dentro el barrido de m12, que es
 * `background-clip: text` sobre `color: transparent`. Una palabra con
 * opacidad propia se pinta en su propia capa, y dentro de ese recorte
 * saldría INVISIBLE. Por eso el partidor trata el `<span>` del barrido como
 * UNA palabra: se mueve entera y con su brillo intacto. Ver `motion.js`.
 *
 * TRES CAUTELAS, las tres medidas.
 *
 * · **No se le añade un estado oculto aparte al titular partido.** El
 *   fotograma final de una animación que solo declara `from` es el estilo
 *   normal del elemento; si además se declara `opacity: 0` fuera de la
 *   animación, el destino pasa a ser invisible y el bloque no aparece nunca.
 *   Pasó en el boceto y dejó dos casos como cajas vacías.
 * · El titular partido NO se anima él: si se animaran el padre y las
 *   palabras, el desvanecido se aplicaría dos veces.
 * · `filter: blur()` no fuerza maquetación, pero sí obliga a rasterizar en
 *   cada fotograma. Medido en la página de comparación: 219 fotogramas a
 *   10 ms de media con el desenfoque y 218 a 10 ms sin él, o sea que no se
 *   distingue del ruido. Falta comprobarlo en un teléfono de verdad.
 */
@keyframes arra-entra-enfocando {
  from {
    opacity: 0;
    transform: translateY(var(--arra-entra-sube, 8px));
    filter: blur(var(--arra-entra-foco, 8px));
  }
}

/* La misma entrada sin el foco, que es la del móvil. Se declara aparte en
   vez de poner el desenfoque a cero porque `filter: blur(0px)` NO es
   `filter: none`: deja un filtro puesto, y un filtro crea contexto de
   apilamiento y obliga al compositor a tratar la capa aparte. Cero coste
   de verdad es no declararlo. */
@keyframes arra-entra-subiendo {
  from {
    opacity: 0;
    transform: translateY(var(--arra-entra-sube, 20px));
  }
}

/* DOS ENTRADAS, Y EL CORTE ESTÁ EN 860 PX
 *
 * El cliente vio el enfoque puesto y decidió: en el ordenador sí, en el
 * teléfono no. Y tenía una segunda razón, que es la buena: **el desenfoque
 * es la parte cara**. `filter: blur()` no fuerza maquetación pero obliga a
 * rasterizar de nuevo en cada fotograma, y en el móvil eso se paga en una
 * GPU que además está moviendo el scroll. Medirlo en un portátil a 100 Hz
 * no dice nada del teléfono: quedaba pendiente comprobarlo y esta decisión
 * lo deja sin efecto donde importaba.
 *
 * 860 px es el corte del artboard, el mismo que usa el resto del tema. No
 * se inventa un punto de ruptura nuevo para esto.
 */
@media (prefers-reduced-motion: no-preference) {

  /* ------------------------------------------------------------------
     ORDENADOR · el enfoque, palabra a palabra en el titular
     ------------------------------------------------------------------ */
  /* SOLO CON RATÓN, ADEMÁS DEL ANCHO. Una tableta apaisada pasa de 860 px
     y entraba aquí, y el cliente vio en ella el enfoque como «el texto que
     sube y a la vez se difumina» (22/09/2026): es la misma rasterización
     cara que se quitó del teléfono, en una GPU que también es de teléfono.
     `hover: hover` y `pointer: fine` dejan fuera a lo que se toca con el
     dedo, sea del ancho que sea; abajo, la rama del móvil recoge a esas
     pantallas con la consulta simétrica. */
  @media (min-width: 860px) and (hover: hover) and (pointer: fine) {
    /* El bloque entero, cuando el observador lo ve. El titular partido
       queda fuera: de él se encargan sus palabras. */
    .js-motion .arra-reveal.in:not(.arra-partido) {
      animation: arra-entra-enfocando var(--arra-entra-dur, 800ms)
                 cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
      animation-delay: var(--arra-delay, 0ms);
    }

    /* El titular partido no se esconde ni se mueve: lo hacen sus palabras. */
    .js-motion .arra-partido { opacity: 1; transform: none; }
    .js-motion .arra-partido:not(.in) .arra-palabra { opacity: 0; }
    .js-motion .arra-partido.in .arra-palabra {
      animation: arra-entra-enfocando var(--arra-entra-dur, 800ms)
                 cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
      /* Cada palabra arranca 80 ms después de la anterior, y todas después
         del retraso que a su titular le tocaba en la cascada. */
      animation-delay: calc(var(--arra-delay, 0ms) + var(--arra-palabra, 0) * 80ms);
    }
    /* LA PALABRA DEL BARRIDO LLEVA LAS DOS ANIMACIONES. `animation` es una
       sola propiedad: la regla de arriba, al ponerle la entrada a la
       palabra, le quitaba el `arra-shine` de m12 y el destello desaparecía
       en cuanto el titular entraba. Medido el 22/09/2026 en /corporate/ y en
       las interiores a 1440: los titulares ya vistos tenían
       `animation-name: arra-entra-enfocando` y ninguno brillaba; por debajo
       de 860, donde el titular no se parte, el barrido seguía. Así que aquí
       van las dos, la entrada una vez y el barrido sin fin, cada una con su
       retraso. */
    .js-motion .arra-partido.in .arra-palabra.arra-brillo {
      animation: arra-entra-enfocando var(--arra-entra-dur, 800ms)
                 cubic-bezier(0.25, 0.46, 0.45, 0.94) both,
                 arra-shine 2.4s linear infinite;
      animation-delay: calc(var(--arra-delay, 0ms) + var(--arra-palabra, 0) * 80ms), 0ms;
    }

    /* La palabra es un `inline-block` para poder moverla. El partidor
       conserva los espacios como nodos de texto entre ellas, así que la
       frase mide lo mismo y se parte por donde se partía.

       SALVO EL BARRIDO, QUE SE QUEDA EN LÍNEA. Un `inline-block` es una
       caja atómica y no se parte entre dos líneas; el barrido de m12 no
       envuelve una palabra sino un trozo de frase —«Sin capas
       innecesarias»—, así que volverlo inline-block lo obligaba a caber
       entero en un renglón. Medido a 375, cuando esta regla aún era
       general: el titular de «Por qué ARRA» pasaba de dos líneas a tres y
       la sección crecía 37 px. En línea pierde solo el recorrido, porque
       `transform` no se aplica a un elemento en línea, y conserva el
       desenfoque y la opacidad, que son los que hacen el gesto.

       Las dos reglas viven DENTRO de esta consulta a propósito: si se
       quedaran fuera, al estrechar la ventana las palabras seguirían
       siendo cajas atómicas y el titular se partiría distinto. */
    .arra-palabra { display: inline-block; }
    .arra-brillo.arra-palabra { display: inline; }
  }

  /* ------------------------------------------------------------------
     MÓVIL · UN SOLO GESTO, EL DE SIEMPRE: 28 px EN 640 ms
     ------------------------------------------------------------------
     Decisión del cliente el 19/09/2026, después de verlo en el teléfono.

     AQUÍ ESTUVO EL CASO 1 DE LA COMPARACIÓN —tres familias según el papel:
     el héroe largo, las cabeceras a 34 px y 900 ms con la curva que
     reparte, y el resto a 20 y 640 con la de frenada—. El cliente lo
     describió exacto: «los bloques aparecen y luego es como que se mueven
     hacia arriba». Y no era una avería: medido fotograma a fotograma sobre
     la página real, los 76 elementos con revelado recibían su animación y
     recorrían su opacidad y su transform enteros. **Era el efecto haciendo
     lo que se le había puesto.** Un recorrido de 20 o 34 px gasta la mitad
     de su camino cuando el bloque YA se ve, así que se lee como un
     deslizamiento; en el ordenador el mismo gesto son 8 px y lo que manda
     es el desenfoque, que se lee como enfocarse. Repartir el recorrido por
     papeles no arregla eso: lo multiplica, porque pone tres deslizamientos
     distintos en la misma pantalla.

     Se vuelve a lo que había antes de todo esto: un gesto, 28 px, 640 ms y
     la curva de frenada, igual para todos.

     PERO SIGUE SIENDO UNA ANIMACIÓN Y NO UNA TRANSICIÓN, que es lo único
     que NO se revierte. La § 1 de arriba hace esto mismo con `transition`,
     y varios bloques declaran la suya para el hover en `paginas.css`, que
     se encola después: `transition` es una sola propiedad y la última regla
     que la escriba borra lo que hubiera. Medido en su día: las filas de
     capacidades se quedaban con 0,22 s de `background` y ni una pizca de la
     entrada, o sea que aparecían de golpe. Con una animación no hay pelea,
     porque `animation` y `transition` son canales distintos. Así que el
     gesto es el original y el canal es el que sobrevive.

     El titular partido no necesita nada: aquí sus palabras no llevan ni
     estado oculto ni animación, así que entra como un bloque más. */
  @media (max-width: 859px), (hover: none), (pointer: coarse) {
    /* VA POR ANIMACIÓN Y NO POR TRANSICIÓN, y no es una preferencia.
     *
     * Una transición se declara en una propiedad, `transition`, y esa
     * propiedad solo puede tener un valor: la última regla que la escriba
     * gana y **borra** lo que hubiera. Varios bloques declaran la suya para
     * el hover -`.arra-capacidades-fila` tiene `transition: background`- y
     * viven en `paginas.css`, que se encola DESPUÉS de esta hoja. Medido:
     * esas filas se quedaban con 0,22 s de `background` y ni una pizca de
     * la entrada, o sea que aparecían de golpe.
     *
     * Con una animación no hay tal pelea: `animation` y `transition` son
     * canales distintos y conviven. Además la animación gana a cualquier
     * declaración normal, que es justo lo que hace falta aquí. Por eso el
     * ordenador tampoco lo sufría: allí la entrada ya era una animación.
     */
    /* Los 28 px y los 640 ms son los mismos números de la § 1, que es de
       donde vienen: `--arra-reveal-dist` y `--arra-reveal-dur`. Se
       escriben aquí como `--arra-entra-*` porque los lee el fotograma, no
       la transición. El héroe conserva su variante propia —54 px y
       900 ms—, que es anterior a todo esto y la pone `destilar.py`. */
    .js-motion .arra-reveal.in {
      --arra-entra-sube: 28px;
      animation: arra-entra-subiendo var(--arra-entra-dur, 640ms)
                 var(--wp--custom--movimiento--salida) both;
      animation-delay: var(--arra-delay, 0ms);
    }
  }
}

/* 2 · Titulares línea a línea: <h2 data-arra-lines><span class="arra-line"><span>…</span></span>…</h2> */
.arra-line { display: block; overflow: hidden; }
.arra-line > span { display: block; }
.js-motion .arra-line > span {
  transform: translateY(110%);
  transition: transform 720ms var(--wp--custom--movimiento--salida);
  transition-delay: var(--arra-delay, 0ms);
}
.in .arra-line > span, .arra-line.in > span { transform: none; }

/* 3 · Ken burns: contenedor .arra-kenburns con <img> o capa dentro */
@keyframes arra-kenburns {
  from { transform: scale(1.02) translate(0, 0); }
  to   { transform: scale(1.14) translate(-2.5%, -1.5%); }
}
.arra-kenburns { overflow: hidden; }
.arra-kenburns > img, .arra-kenburns > .arra-kenburns-layer {
  width: 100%; height: 100%; object-fit: cover;
  animation: arra-kenburns 16s var(--wp--custom--movimiento--entrada-salida) infinite alternate;
  will-change: transform;
}

/* 4 · Marquee de partners: .arra-marquee > .arra-marquee-track (contenido duplicado 2x) */
@keyframes arra-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.arra-marquee { overflow: hidden; }
.arra-marquee-track {
  display: inline-flex; align-items: center; gap: 64px; padding-right: 64px;
  white-space: nowrap;
  animation: arra-marquee 26s linear infinite;
  will-change: transform;
}
.arra-marquee:hover .arra-marquee-track { animation-play-state: paused; }

/* 4b · Columnas verticales de cards (patron evolve.es): 1a sube, 2a baja, 3a sube mas lenta.
   Estructura: .arra-vmarquee > .arra-vmarquee-col (contenido duplicado 2x) */
@keyframes arra-vmarquee-up { from { transform: translateY(0); } to { transform: translateY(-50%); } }
@keyframes arra-vmarquee-down { from { transform: translateY(-50%); } to { transform: translateY(0); } }
.arra-vmarquee { display: grid; grid-auto-flow: column; gap: 16px; overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 12%, #000 88%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 12%, #000 88%, transparent); }
.arra-vmarquee-col { display: flex; flex-direction: column; gap: 16px; will-change: transform;
  animation: arra-vmarquee-up 22s linear infinite; }
.arra-vmarquee-col:nth-child(2) { animation-name: arra-vmarquee-down; animation-duration: 26s; }
.arra-vmarquee-col:nth-child(3) { animation-duration: 34s; }
.arra-vmarquee:hover .arra-vmarquee-col { animation-play-state: paused; }

/* 5 · Flecha de los botones: <svg class="arra-cta-flecha"> dentro de a/button
 *
 * El dibujo nace apuntando a la derecha. Al apuntar el boton —o al tabular
 * hasta el— gira 45 grados y se queda en diagonal. Un solo gesto: sin avance,
 * sin escala y sin rebote.
 *
 * LA ALTURA. En un boton flexible `align-items: center` centra la flecha en
 * la caja de linea y, con esta tipografia, ese centro coincide con el de las
 * mayusculas: medido en las paginas, entre 0 y 0,045 em. No hay que tocarla.
 *
 * Donde si hay que tocarla es en los rotulos en linea -el «Ver servicio» de
 * las tarjetas-: ahi la flecha es un inline-block apoyado en la linea base,
 * o sea 0,275 em por ENCIMA de ese mismo centro. Se baja con `vertical-align`
 * y en em, para que acompanie a la letra cuando encoge.
 *
 * Antes esto animaba el glifo `↗` de una fuente del sistema, y ademas lo
 * giraba en el sentido contrario: la flecha apuntaba hacia ARRIBA. */
.arra-cta-flecha {
  display: inline-block; flex: none;
  inline-size: 1.25em; block-size: 1.25em;
  transition: transform var(--wp--custom--movimiento--base) var(--wp--custom--movimiento--salida);
}
.arra-cta-flecha--en-linea { vertical-align: -0.275em; }

a:hover .arra-cta-flecha, button:hover .arra-cta-flecha,
a:focus-visible .arra-cta-flecha, button:focus-visible .arra-cta-flecha {
  transform: rotate(-45deg);
}

/* Y TAMBIEN AL PASAR POR LA TARJETA ENTERA, no solo por el enlace.
   El cliente (22/09/2026): en las cinco fichas blancas del mazo la flecha
   gira al pasar por cualquier parte de la ficha -son un `<a>` entero- y en
   la granate solo al pasar por «Agenda una reunion». La tarjeta granate no
   puede ser un enlace: lleva dos anillos y un parrafo, y envolver todo eso
   en un `<a>` haria un objetivo de pulsacion enorme con texto que no es
   enlace. Asi que gira desde el contenedor, que es `.arra-anillos` en las
   tarjetas de llamada a la accion de media pagina. */
.arra-anillos:hover .arra-cta-flecha {
  transform: rotate(-45deg);
}

/* 6 · m12 · Barrido sobre la palabra destacada del titular
   <span class="arra-brillo">palabra clave</span>

   Un brillo mate recorre la palabra cada 6 s. Es el m12 del catálogo, con un
   cambio: allí el barrido es DORADO porque la palabra de ejemplo lo es, y en
   los titulares de Corporate la palabra destacada va en granate. Un barrido
   dorado sobre una palabra granate no la ilumina, la repinta de otro color.
   Así que el degradado se hace con la propia familia: `burdeos-700` de base
   —que es el color que ya tenía la palabra— y `burdeos-500` como reflejo.
   El gesto es el mismo; lo que cambia es de qué color es la luz.

   DOS CUIDADOS, y los dos son de los que dejan texto invisible:

   · `background-clip: text` con `color: transparent` significa que si el
     fondo no pinta, la palabra desaparece. Por eso el color se declara
     ANTES y el recorte va detrás, dentro de un `@supports`: donde no se
     soporte, queda el granate liso de siempre.
   · Con `prefers-reduced-motion` se para la animación, pero NO se quita el
     recorte: se deja el degradado quieto en su posición de reposo, que es
     granate liso. Quitar el recorte sin más dejaría la palabra transparente
     durante un fotograma en algunos motores. */
/* LA CLASE VA REPETIDA, `.arra-brillo.arra-brillo`, y no es un descuido.

   La palabra destacada ya trae su propia clase del destilador con
   `color: var(--corp)`. Esa clase y esta pesan lo mismo —una clase cada
   una—, así que decide el orden de los archivos… y `paginas.css` se encola
   DESPUÉS de este. O sea que el color plano ganaba y el barrido no se veía.

   Repetir la clase sube el peso a dos sin tocar el marcado ni recurrir a
   `!important`, que es lo que habría que deshacer el día que esto cambie. */
.arra-brillo.arra-brillo {
  color: var(--wp--preset--color--burdeos-700);
}

/* EL DEGRADADO NO PINTA EL COLOR BASE: LO PINTA EL `background-color`.

   Así estaba en el catálogo y así estaba mal. Con `background-size: 220%` y
   posiciones del 110 % al −110 %, la imagen se sale de la caja por los dos
   lados: en `background-position`, los porcentajes se miden sobre la
   DIFERENCIA entre la caja y la imagen, así que con una imagen más ancha que
   la caja el 100 % ya es el tope y todo lo que pase de ahí deja hueco. Y
   donde hay hueco, `background-repeat` hace lo suyo y **repite el
   degradado**: por eso se veía una pasada entera, empezaba otra y se
   quedaba clavada a media palabra.

   La solución no es ajustar los números, es quitarle al degradado el trabajo
   de pintar el fondo. El color base va en `background-color` —que con
   `background-clip: text` también se recorta a la letra, así que la palabra
   NUNCA se queda sin pintar— y el degradado pasa a ser transparente salvo la
   banda de luz, en `no-repeat`. Ahora el recorrido es limpio: del 100 % al
   0 % la banda cruza una vez, y al saltar del final al principio está fuera
   de la caja por los dos lados, o sea que el salto no se ve. */
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
  .arra-brillo.arra-brillo {
    /* EL DESTELLO ES LUZ, NO SOMBRA. Esto estuvo mal dos veces.
     *
     * El barrido del dorado funciona porque salta de `dorado-700` a
     * `dorado-300`: de 0,25 de luminancia a 0,68, un factor de 2,4. Es un
     * reflejo, o sea algo MÁS CLARO pasando por encima.
     *
     * En el granate se intentó lo mismo con los colores que hay, y no los
     * hay: el más claro de la familia es `burdeos-500`, que contra el
     * `burdeos-700` de la palabra da 1,51. Al ver que no se notaba, el
     * segundo intento fue meter `burdeos-900` en los hombros para agrandar
     * el salto DENTRO de la banda. Subía a 1,99 sobre el papel y en pantalla
     * se veía todavía menos: lo que se percibe es lo claro contra el fondo,
     * y ahí lo único que se había hecho era rodear de sombra un reflejo que
     * seguía siendo flojo.
     *
     * El reflejo tiene que ser CLARO, y la paleta no tiene un granate claro,
     * así que hay que fabricarlo. El tercer intento lo mezcló con
     * `dorado-300` y tampoco valía: eso no aclara el granate, lo CALIENTA.
     * Medido, salía un tostado de tono **17°** cuando el granate está en
     * 339°: no era un granate claro, era otro color, y en pantalla se leía
     * como un dorado.
     *
     * El cuarto intento lo mezcló con `neutro-100`, que sí conserva el tono
     * —341°— pero a costa de la saturación: del 47 % de la palabra bajaba
     * al 16 %, y un granate sin color es un gris rosado. Por eso «se ponía
     * blanco».
     *
     * UN GRANATE CLARO NO ES EL GRANATE CON BLANCO: es el MISMO TONO con
     * más luz Y la saturación en su sitio, y eso no se consigue mezclando,
     * porque toda mezcla con un neutro desatura. Se consigue diciéndolo:
     * `hsl(from …)` toma el tono del color de la paleta y le pone la luz y
     * la saturación que hacen falta. Es lo que sería un `burdeos-300` si la
     * paleta lo tuviera —no lo tiene: sus granates son 950, 900, 700 y
     * 500—, derivado del que sí está en vez de inventar un hex.
     *
     * La reserva, para el navegador que aún no entienda esa sintaxis, es la
     * mezcla con el neutro: apagada, pero del mismo tono y sin romper nada. */
    --arra-brillo-luz: color-mix(in srgb,
        var(--wp--preset--color--burdeos-500) 55%,
        var(--wp--preset--color--neutro-100));
    background-color: var(--wp--preset--color--burdeos-700);
    background-image: linear-gradient(100deg,
      transparent 34%,
      var(--arra-brillo-luz) 50%,
      transparent 66%);
    background-repeat: no-repeat;
    background-size: 220% 100%;
    /* 125 %, NO 100 %, Y LA CUENTA IMPORTA.
     *
     * En `background-position` el porcentaje se mide sobre la DIFERENCIA
     * entre la caja y la imagen, así que con una imagen del 220 % el 100 %
     * NO deja la imagen fuera: la deja con su borde derecho pegado al de
     * la caja, o sea que se extiende de −120 % a 100 %. Y la banda, que va
     * del 34 % al 66 % de la imagen, cae entonces del −45 % al 25 % de la
     * palabra: EN REPOSO ESTABA PUESTA SOBRE LAS PRIMERAS LETRAS. Como la
     * espera ocupa el primer tercio del ciclo, se veía una mancha clara
     * parada en el arranque de la palabra casi un segundo de cada dos y
     * medio, y parecía que el barrido se enganchaba antes de volver a
     * empezar.
     *
     * Con 125 % la banda cae del −75 % al −5 %: entera fuera por la
     * izquierda. Y el final va a −25 %, que la deja del 105 % al 175 %,
     * entera fuera por la derecha. Se puede salir de la caja porque el
     * color base lo pinta `background-color` y el degradado va
     * `no-repeat`; con `repeat` esto volvería a duplicar la pasada. */
    background-position: 125% 0;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    /* `linear` a propósito: una curva de entrada y salida hace que la banda
       se arrastre en los extremos, que es justo donde está fuera de la caja,
       y se coma la mitad del tiempo visible. */
    animation: arra-shine 2.4s linear infinite;
  }
  /* Sobre fondo oscuro la palabra va en dorado, y allí el destello sí es el
     dorado claro del catálogo. */
  /* El dorado ya era así de origen y por eso funcionaba: un solo reflejo
     claro, sin hombros oscuros que lo apaguen. */
  .arra-brillo--dorado.arra-brillo--dorado {
    background-color: var(--wp--preset--color--dorado-700);
    background-image: linear-gradient(100deg,
      transparent 34%,
      var(--wp--preset--color--dorado-300) 50%,
      transparent 66%);
  }
  /* Y EN CORE, EL MISMO GESTO EN VERDE (22/09/2026).
   *
   * La palabra destacada de Core va en `verde-400` —es el `--core` del
   * sistema—, así que el reflejo tiene que ser un verde claro DEL MISMO
   * TONO. Ni el dorado, que no la ilumina sino que la repinta de otro
   * color, ni el granate claro, que es de la otra línea.
   *
   * Es el mismo método que el granate, y por la misma razón: la paleta no
   * tiene un verde claro —sus verdes son 900, 700, 500 y 400— y una mezcla
   * con un neutro conserva el tono pero se lleva la saturación por
   * delante. Se deriva del que sí está. La reserva vuelve a ser la mezcla,
   * apagada pero del mismo tono. */
  .arra-brillo--verde.arra-brillo--verde {
    --arra-brillo-luz: color-mix(in srgb,
        var(--wp--preset--color--verde-400) 40%,
        var(--wp--preset--color--blanco));
    background-color: var(--wp--preset--color--verde-400);
    background-image: linear-gradient(100deg,
      transparent 34%,
      var(--arra-brillo-luz) 50%,
      transparent 66%);
  }
  /* EL DORADO CLARO, PARA LO QUE YA ESTÁ EN `dorado-500` (24/09/2026).
   *
   * Las tres cifras del panel verde de /core/asesoria-fiscal-contable/ van
   * en `--gold`, que es `dorado-500`, sobre `verde-700`. El cliente pidió
   * ponerles el barrido del titular y con `--dorado` se habría ROTO EL
   * CONTRASTE: ese variante repinta la palabra de `dorado-700`, y medido
   * sobre ese verde eso son 1,99:1 —por debajo incluso del 3:1 que pide AA
   * para texto grande—, mientras que `dorado-500` da 3,11:1 y pasa.
   *
   * Así que la base se queda en `dorado-500` y lo que hace falta es un oro
   * MÁS CLARO que `dorado-300` para el reflejo. La paleta no lo tiene —sus
   * dorados son 700, 500 y 300—, así que se deriva del que sí está, igual
   * que el granate claro y el verde claro: mismo tono, misma saturación,
   * más luz. Medido: el salto dentro de la banda queda en 1,96:1, del orden
   * del 2,41 del dorado del catálogo, que es el que sí se nota. */
  .arra-brillo--dorado-claro.arra-brillo--dorado-claro {
    --arra-brillo-luz: color-mix(in srgb,
        var(--wp--preset--color--dorado-300) 45%,
        var(--wp--preset--color--blanco));
    background-color: var(--wp--preset--color--dorado-500);
    background-image: linear-gradient(100deg,
      transparent 34%,
      var(--arra-brillo-luz) 50%,
      transparent 66%);
  }
}

/* La espera con la banda fuera ocupa el primer tercio; el resto es la
   pasada. A 2,4 s eso son unos 0,8 s de reposo y 1,6 de recorrido. */
/* El granate claro de verdad: el tono de `burdeos-500`, la saturación al 48 %
   —o sea más color que el original, no menos— y la luz al 56 %.
   Empezó en 68 y el cliente lo vio «muy clarito»: a esa luz el reflejo se
   despega demasiado de la palabra y parece rosa, no granate iluminado. A 56
   sigue siendo lo más claro de la familia con diferencia y se lee como la
   misma tinta con luz encima. */
@supports (color: hsl(from red h s l)) {
  .arra-brillo.arra-brillo {
    --arra-brillo-luz: hsl(from var(--wp--preset--color--burdeos-500) h 48% 56%);
  }
  /* El verde claro de verdad: el tono de `verde-400` —100°—, la saturación
     algo por encima de la suya y la luz arriba. VA DESPUÉS del granate a
     propósito: los dos selectores pesan lo mismo, así que aquí manda el
     orden, y si esta regla subiera, la palabra verde se iluminaría de
     granate. */
  .arra-brillo--verde.arra-brillo--verde {
    --arra-brillo-luz: hsl(from var(--wp--preset--color--verde-400) h 30% 86%);
  }
  /* El oro claro de verdad: el tono de `dorado-300` —41°—, su saturación y
     la luz al 92 %. Medido contra `dorado-500`, que es la base de esta
     variante: 1,96:1 de salto dentro de la banda. También va DESPUÉS, por
     lo mismo que el verde. */
  .arra-brillo--dorado-claro.arra-brillo--dorado-claro {
    --arra-brillo-luz: hsl(from var(--wp--preset--color--dorado-300) h s 92%);
  }
}

@keyframes arra-shine {
  0%, 32% { background-position: 125% 0; }
  100%    { background-position: -25% 0; }
}

/* Accesibilidad */
@media (prefers-reduced-motion: reduce) {
  .arra-reveal { opacity: 1; transform: none; transition: none; }
  .arra-line > span { transform: none; transition: none; }
  .arra-kenburns > img, .arra-kenburns > .arra-kenburns-layer, .arra-marquee-track, .arra-vmarquee-col { animation: none; }
  .arra-cta-flecha { transition: none; }
  .arra-brillo.arra-brillo { animation: none; }
}
