# Pedestrian crossing button

> The yellow box from a pedestrian crossing: pressing lights up WAIT, then a green walking figure appears.

- Category: [Buttons](https://library.aimran.es/components/buttons)
- Built with: HTML + CSS
- Live editor: https://library.aimran.es/blocks/uv-btn-crosswalk
- Library: AIMRAN Library (https://library.aimran.es), free, no sign-up, by Aimran Oukham

## Where to use it

Anyone who has waited at a crossing knows this object: a yellow metal box with screws in the corners, a black push button with a hand and a dot matrix sign. Pressing it lights WAIT in red, and after a moment the sign switches to a green walking figure that blinks before it resets. Each change is announced to screen readers. Fun for city guides and mobility apps.

The main color is the box, school bus yellow by default, and the secondary color is the WAIT light. The full cycle follows the speed setting, so you can make it feel like a slow suburban crossing or a busy downtown one.

## Code

### HTML

```html
<div class="uvq01-xwk"><div class="sg" aria-hidden="true"><span class="w1">Wait</span><span class="w2"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="13" cy="4" r="2" fill="currentColor"/><path d="M9 21l3-6 3 2v4"/><path d="M12 15l1-6-4 2-2 3"/><path d="M13 9l2.5 3 3 1"/></svg><span>Walk</span></span></div><button class="pb" type="button" aria-label="Request to cross"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 11V6a2 2 0 0 0-4 0"/><path d="M14 10V4a2 2 0 0 0-4 0v2"/><path d="M10 10.5V6a2 2 0 0 0-4 0v8"/><path d="M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.9-6-2.3l-3.6-3.6a2 2 0 0 1 2.8-2.8L7 15"/></svg></button><span class="lb" aria-hidden="true">Push</span><span class="sr" role="status"></span></div>
```

### CSS

```css
.uvq01-xwk {
  --c1: #f6c400;
  --c2: #ff4b2b;
  --s: 16px;
  /* tamaño */
  --k: 1;
  /* velocidad */
  --fg: #1d1d1f;
  /* texto */
  --bg: #f5f5f7;
  /* fondo */
}

.uvq01-xwk {
  font-family: -apple-system,BlinkMacSystemFont,"SF Pro Text","Inter",system-ui,sans-serif;
  font-size: var(--s);
  color: var(--fg);
  -webkit-tap-highlight-color: transparent;
  position: relative;
  display: inline-grid;
  justify-items: center;
  gap: .8em;
  width: 9.6em;
  padding: 1.1em .9em 1em;
  border-radius: 1.1em;
  background: linear-gradient(180deg,color-mix(in srgb,var(--c1) 82%,#fff),var(--c1) 28%,color-mix(in srgb,var(--c1) 86%,#000));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.6),inset 0 -.3em .5em rgba(0,0,0,.14),0 0 0 1px color-mix(in srgb,var(--c1) 55%,#000),0 16px 30px -16px rgba(0,0,0,.6);
}

.uvq01-xwk::before {
  content: "";
  position: absolute;
  inset: .45em;
  border-radius: .7em;
  background: radial-gradient(circle,#8a8f96 0 .16em,transparent .2em) 0 0/.4em .4em no-repeat,radial-gradient(circle,#8a8f96 0 .16em,transparent .2em) 100% 0/.4em .4em no-repeat,radial-gradient(circle,#8a8f96 0 .16em,transparent .2em) 0 100%/.4em .4em no-repeat,radial-gradient(circle,#8a8f96 0 .16em,transparent .2em) 100% 100%/.4em .4em no-repeat;
  pointer-events: none;
}

.uvq01-xwk .sg {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  height: 2.7em;
  border-radius: .45em;
  background: radial-gradient(circle,rgba(255,255,255,.05) .5px,transparent 1px) 0 0/3px 3px,#0e0e10;
  box-shadow: inset 0 0 0 .16em #2a2a2c,inset 0 .2em .5em #000;
}

.uvq01-xwk .w1,.uvq01-xwk .w2 {
  grid-area: 1/1;
  display: flex;
  align-items: center;
  gap: .35em;
  font: 800 .9em/1 ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,monospace;
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: color calc(0.2s / var(--k)) cubic-bezier(.25,.1,.25,1),opacity calc(0.2s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq01-xwk .w1 {
  color: color-mix(in srgb,var(--c2) 16%,transparent);
}

.uvq01-xwk .w2 {
  color: #3cff7a;
  opacity: 0;
  text-shadow: 0 0 .5em #3cff7a;
}

.uvq01-xwk .w2 svg {
  width: 1.3em;
  height: 1.3em;
  filter: drop-shadow(0 0 .3em #3cff7a);
}

.uvq01-xwk .pb {
  font: inherit;
  color: inherit;
  border: 0;
  margin: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  display: grid;
  place-items: center;
  width: 4.2em;
  height: 4.2em;
  border-radius: 50%;
  color: var(--c1);
  background: radial-gradient(circle at 50% 32%,#3c3c40,#121214 70%);
  box-shadow: 0 0 0 .3em #d9dbde,0 0 0 .38em #8f939a,0 0 0 .55em color-mix(in srgb,var(--c1) 78%,#000),0 .4em .6em rgba(0,0,0,.4);
  transition: transform calc(0.1s / var(--k)) cubic-bezier(.25,.1,.25,1),box-shadow calc(0.3s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq01-xwk .pb svg {
  width: 1.9em;
  height: 1.9em;
  transition: transform calc(0.3s / var(--k)) cubic-bezier(.34,1.56,.64,1);
}

.uvq01-xwk .pb:hover svg {
  transform: translateY(-.1em) rotate(-6deg);
}

.uvq01-xwk .pb:active {
  transform: scale(.93);
}

.uvq01-xwk .pb:focus-visible {
  outline: 2px solid #111;
  outline-offset: calc(.55em + 3px);
}

.uvq01-xwk .lb {
  font: 800 .66em/1 ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,monospace;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: #1a1a1a;
}

.uvq01-xwk .sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.uvq01-xwk.is-wait .w1 {
  color: var(--c2);
  text-shadow: 0 0 .5em var(--c2);
  animation: uvq01-xwk-bl calc(0.6s / var(--k)) steps(1) 2;
}

.uvq01-xwk.is-wait .pb {
  box-shadow: 0 0 0 .3em #d9dbde,0 0 0 .38em var(--c2),0 0 0 .55em color-mix(in srgb,var(--c1) 78%,#000),0 0 1.2em .2em color-mix(in srgb,var(--c2) 70%,transparent);
}

.uvq01-xwk.is-go .w1 {
  opacity: 0;
}

.uvq01-xwk.is-go .w2 {
  opacity: 1;
  animation: uvq01-xwk-bl calc(0.5s / var(--k)) steps(1) calc(2.4s / var(--k)) infinite;
}

@keyframes uvq01-xwk-bl {
  50% {
    opacity: .15;
  }
}

@media (prefers-reduced-motion:reduce) {
  .uvq01-xwk,.uvq01-xwk *,.uvq01-xwk *::before,.uvq01-xwk *::after {
    animation-duration: .01ms!important;
    animation-iteration-count: 1!important;
    transition-duration: .01ms!important;
  }
}
```

### JavaScript

```js
document.querySelectorAll(".uvq01-xwk").forEach(el => {
  const pb=el.querySelector(".pb"),w1=el.querySelector(".w1"),w2=el.querySelector(".w2"),sr=el.querySelector(".sr");let t1=0,t2=0;const k=()=>parseFloat(getComputedStyle(el).getPropertyValue("--k"))||1;
pb.addEventListener("click",()=>{if(el.classList.contains("is-wait")||el.classList.contains("is-go"))return;el.classList.add("is-wait");sr.textContent=w1.textContent;
t1=setTimeout(()=>{el.classList.remove("is-wait");el.classList.add("is-go");sr.textContent=w2.textContent.trim()},2600/k());
t2=setTimeout(()=>{el.classList.remove("is-go");sr.textContent=""},6400/k())});
return()=>{clearTimeout(t1);clearTimeout(t2)}
});
```

### React

```tsx
// @ts-nocheck: setup() es JavaScript del DOM sin tipos, el mismo de la pestaña JS.
import { useEffect, useRef, type CSSProperties } from "react";

const css = `
.uvq01-xwk {
  font-family: -apple-system,BlinkMacSystemFont,"SF Pro Text","Inter",system-ui,sans-serif;
  font-size: var(--s);
  color: var(--fg);
  -webkit-tap-highlight-color: transparent;
  position: relative;
  display: inline-grid;
  justify-items: center;
  gap: .8em;
  width: 9.6em;
  padding: 1.1em .9em 1em;
  border-radius: 1.1em;
  background: linear-gradient(180deg,color-mix(in srgb,var(--c1) 82%,#fff),var(--c1) 28%,color-mix(in srgb,var(--c1) 86%,#000));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.6),inset 0 -.3em .5em rgba(0,0,0,.14),0 0 0 1px color-mix(in srgb,var(--c1) 55%,#000),0 16px 30px -16px rgba(0,0,0,.6);
}

.uvq01-xwk::before {
  content: "";
  position: absolute;
  inset: .45em;
  border-radius: .7em;
  background: radial-gradient(circle,#8a8f96 0 .16em,transparent .2em) 0 0/.4em .4em no-repeat,radial-gradient(circle,#8a8f96 0 .16em,transparent .2em) 100% 0/.4em .4em no-repeat,radial-gradient(circle,#8a8f96 0 .16em,transparent .2em) 0 100%/.4em .4em no-repeat,radial-gradient(circle,#8a8f96 0 .16em,transparent .2em) 100% 100%/.4em .4em no-repeat;
  pointer-events: none;
}

.uvq01-xwk .sg {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  height: 2.7em;
  border-radius: .45em;
  background: radial-gradient(circle,rgba(255,255,255,.05) .5px,transparent 1px) 0 0/3px 3px,#0e0e10;
  box-shadow: inset 0 0 0 .16em #2a2a2c,inset 0 .2em .5em #000;
}

.uvq01-xwk .w1,.uvq01-xwk .w2 {
  grid-area: 1/1;
  display: flex;
  align-items: center;
  gap: .35em;
  font: 800 .9em/1 ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,monospace;
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: color calc(0.2s / var(--k)) cubic-bezier(.25,.1,.25,1),opacity calc(0.2s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq01-xwk .w1 {
  color: color-mix(in srgb,var(--c2) 16%,transparent);
}

.uvq01-xwk .w2 {
  color: #3cff7a;
  opacity: 0;
  text-shadow: 0 0 .5em #3cff7a;
}

.uvq01-xwk .w2 svg {
  width: 1.3em;
  height: 1.3em;
  filter: drop-shadow(0 0 .3em #3cff7a);
}

.uvq01-xwk .pb {
  font: inherit;
  color: inherit;
  border: 0;
  margin: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  display: grid;
  place-items: center;
  width: 4.2em;
  height: 4.2em;
  border-radius: 50%;
  color: var(--c1);
  background: radial-gradient(circle at 50% 32%,#3c3c40,#121214 70%);
  box-shadow: 0 0 0 .3em #d9dbde,0 0 0 .38em #8f939a,0 0 0 .55em color-mix(in srgb,var(--c1) 78%,#000),0 .4em .6em rgba(0,0,0,.4);
  transition: transform calc(0.1s / var(--k)) cubic-bezier(.25,.1,.25,1),box-shadow calc(0.3s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq01-xwk .pb svg {
  width: 1.9em;
  height: 1.9em;
  transition: transform calc(0.3s / var(--k)) cubic-bezier(.34,1.56,.64,1);
}

.uvq01-xwk .pb:hover svg {
  transform: translateY(-.1em) rotate(-6deg);
}

.uvq01-xwk .pb:active {
  transform: scale(.93);
}

.uvq01-xwk .pb:focus-visible {
  outline: 2px solid #111;
  outline-offset: calc(.55em + 3px);
}

.uvq01-xwk .lb {
  font: 800 .66em/1 ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,monospace;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: #1a1a1a;
}

.uvq01-xwk .sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.uvq01-xwk.is-wait .w1 {
  color: var(--c2);
  text-shadow: 0 0 .5em var(--c2);
  animation: uvq01-xwk-bl calc(0.6s / var(--k)) steps(1) 2;
}

.uvq01-xwk.is-wait .pb {
  box-shadow: 0 0 0 .3em #d9dbde,0 0 0 .38em var(--c2),0 0 0 .55em color-mix(in srgb,var(--c1) 78%,#000),0 0 1.2em .2em color-mix(in srgb,var(--c2) 70%,transparent);
}

.uvq01-xwk.is-go .w1 {
  opacity: 0;
}

.uvq01-xwk.is-go .w2 {
  opacity: 1;
  animation: uvq01-xwk-bl calc(0.5s / var(--k)) steps(1) calc(2.4s / var(--k)) infinite;
}

@keyframes uvq01-xwk-bl {
  50% {
    opacity: .15;
  }
}

@media (prefers-reduced-motion:reduce) {
  .uvq01-xwk,.uvq01-xwk *,.uvq01-xwk *::before,.uvq01-xwk *::after {
    animation-duration: .01ms!important;
    animation-iteration-count: 1!important;
    transition-duration: .01ms!important;
  }
}
`;

// Interacción en JavaScript del DOM: la misma que en la pestaña JS.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function setup(el: any) {
  const pb=el.querySelector(".pb"),w1=el.querySelector(".w1"),w2=el.querySelector(".w2"),sr=el.querySelector(".sr");let t1=0,t2=0;const k=()=>parseFloat(getComputedStyle(el).getPropertyValue("--k"))||1;
pb.addEventListener("click",()=>{if(el.classList.contains("is-wait")||el.classList.contains("is-go"))return;el.classList.add("is-wait");sr.textContent=w1.textContent;
t1=setTimeout(()=>{el.classList.remove("is-wait");el.classList.add("is-go");sr.textContent=w2.textContent.trim()},2600/k());
t2=setTimeout(()=>{el.classList.remove("is-go");sr.textContent=""},6400/k())});
return()=>{clearTimeout(t1);clearTimeout(t2)}
}

export default function BtnCrosswalk() {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const el = ref.current?.firstElementChild;
    return el ? setup(el) : undefined;
  }, []);

  return (
    <>
      <style>{css}</style>
      <div
        ref={ref} style={{
          "--c1": "#f6c400",
          "--c2": "#ff4b2b",
          "--s": "16px",
          "--k": "1",
          "--fg": "#1d1d1f",
          "--bg": "#f5f5f7",
        } as CSSProperties}
      >
        <div className="uvq01-xwk"><div className="sg" aria-hidden="true"><span className="w1">Wait</span><span className="w2"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><circle cx="13" cy="4" r="2" fill="currentColor" /><path d="M9 21l3-6 3 2v4" /><path d="M12 15l1-6-4 2-2 3" /><path d="M13 9l2.5 3 3 1" /></svg><span>Walk</span></span></div><button className="pb" type="button" aria-label="Request to cross"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M18 11V6a2 2 0 0 0-4 0" /><path d="M14 10V4a2 2 0 0 0-4 0v2" /><path d="M10 10.5V6a2 2 0 0 0-4 0v8" /><path d="M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.9-6-2.3l-3.6-3.6a2 2 0 0 1 2.8-2.8L7 15" /></svg></button><span className="lb" aria-hidden="true">Push</span><span className="sr" role="status"></span></div>
      </div>
    </>
  );
}
```

## Prompt for AI assistants

Paste this into ChatGPT, Claude, Cursor, v0 or Lovable to adapt the block to your stack (Tailwind, Vue, Svelte…):

````text
I want to add the “Pedestrian crossing button” block (Buttons) from AIMRAN Library to my project.

## What it is
The yellow box from a pedestrian crossing: pressing lights up WAIT, then a green walking figure appears.

## Chosen settings
- Main color: #f6c400
- Secondary color: #ff4b2b
- Size: 16px (from 12 to 24px)
- Speed: 1x (from 0.5 to 2x)
- Text: "Pedir paso"

## What I need
1. Add it to my project with the same look and animation as the reference code: same sizes, colours, radii, shadows, timings and easing.
2. It is built with plain HTML and CSS (the reference wraps it in a React component with its CSS). If my project uses something else (Vue, Svelte, Astro, plain HTML…), translate it without losing any behaviour. If I use Tailwind, turn the styles into classes; if not, keep the CSS in its own file.
3. Expose the settings above as props (or CSS variables) with those values as defaults.
4. Make it work well on phones: nothing that depends only on hover, touch targets of at least 44 px and no overflow on 320 px screens.
5. Make it look right in light and dark mode.
6. Keep it accessible: semantic HTML, roles and aria-* where needed, visible focus and keyboard support.
7. Respect prefers-reduced-motion: with reduced motion, no big animations but the same end result.

## Reference code
```tsx
// @ts-nocheck: setup() es JavaScript del DOM sin tipos, el mismo de la pestaña JS.
import { useEffect, useRef, type CSSProperties } from "react";

const css = `
.uvq01-xwk {
  font-family: -apple-system,BlinkMacSystemFont,"SF Pro Text","Inter",system-ui,sans-serif;
  font-size: var(--s);
  color: var(--fg);
  -webkit-tap-highlight-color: transparent;
  position: relative;
  display: inline-grid;
  justify-items: center;
  gap: .8em;
  width: 9.6em;
  padding: 1.1em .9em 1em;
  border-radius: 1.1em;
  background: linear-gradient(180deg,color-mix(in srgb,var(--c1) 82%,#fff),var(--c1) 28%,color-mix(in srgb,var(--c1) 86%,#000));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.6),inset 0 -.3em .5em rgba(0,0,0,.14),0 0 0 1px color-mix(in srgb,var(--c1) 55%,#000),0 16px 30px -16px rgba(0,0,0,.6);
}

.uvq01-xwk::before {
  content: "";
  position: absolute;
  inset: .45em;
  border-radius: .7em;
  background: radial-gradient(circle,#8a8f96 0 .16em,transparent .2em) 0 0/.4em .4em no-repeat,radial-gradient(circle,#8a8f96 0 .16em,transparent .2em) 100% 0/.4em .4em no-repeat,radial-gradient(circle,#8a8f96 0 .16em,transparent .2em) 0 100%/.4em .4em no-repeat,radial-gradient(circle,#8a8f96 0 .16em,transparent .2em) 100% 100%/.4em .4em no-repeat;
  pointer-events: none;
}

.uvq01-xwk .sg {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  height: 2.7em;
  border-radius: .45em;
  background: radial-gradient(circle,rgba(255,255,255,.05) .5px,transparent 1px) 0 0/3px 3px,#0e0e10;
  box-shadow: inset 0 0 0 .16em #2a2a2c,inset 0 .2em .5em #000;
}

.uvq01-xwk .w1,.uvq01-xwk .w2 {
  grid-area: 1/1;
  display: flex;
  align-items: center;
  gap: .35em;
  font: 800 .9em/1 ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,monospace;
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: color calc(0.2s / var(--k)) cubic-bezier(.25,.1,.25,1),opacity calc(0.2s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq01-xwk .w1 {
  color: color-mix(in srgb,var(--c2) 16%,transparent);
}

.uvq01-xwk .w2 {
  color: #3cff7a;
  opacity: 0;
  text-shadow: 0 0 .5em #3cff7a;
}

.uvq01-xwk .w2 svg {
  width: 1.3em;
  height: 1.3em;
  filter: drop-shadow(0 0 .3em #3cff7a);
}

.uvq01-xwk .pb {
  font: inherit;
  color: inherit;
  border: 0;
  margin: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  display: grid;
  place-items: center;
  width: 4.2em;
  height: 4.2em;
  border-radius: 50%;
  color: var(--c1);
  background: radial-gradient(circle at 50% 32%,#3c3c40,#121214 70%);
  box-shadow: 0 0 0 .3em #d9dbde,0 0 0 .38em #8f939a,0 0 0 .55em color-mix(in srgb,var(--c1) 78%,#000),0 .4em .6em rgba(0,0,0,.4);
  transition: transform calc(0.1s / var(--k)) cubic-bezier(.25,.1,.25,1),box-shadow calc(0.3s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq01-xwk .pb svg {
  width: 1.9em;
  height: 1.9em;
  transition: transform calc(0.3s / var(--k)) cubic-bezier(.34,1.56,.64,1);
}

.uvq01-xwk .pb:hover svg {
  transform: translateY(-.1em) rotate(-6deg);
}

.uvq01-xwk .pb:active {
  transform: scale(.93);
}

.uvq01-xwk .pb:focus-visible {
  outline: 2px solid #111;
  outline-offset: calc(.55em + 3px);
}

.uvq01-xwk .lb {
  font: 800 .66em/1 ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,monospace;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: #1a1a1a;
}

.uvq01-xwk .sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.uvq01-xwk.is-wait .w1 {
  color: var(--c2);
  text-shadow: 0 0 .5em var(--c2);
  animation: uvq01-xwk-bl calc(0.6s / var(--k)) steps(1) 2;
}

.uvq01-xwk.is-wait .pb {
  box-shadow: 0 0 0 .3em #d9dbde,0 0 0 .38em var(--c2),0 0 0 .55em color-mix(in srgb,var(--c1) 78%,#000),0 0 1.2em .2em color-mix(in srgb,var(--c2) 70%,transparent);
}

.uvq01-xwk.is-go .w1 {
  opacity: 0;
}

.uvq01-xwk.is-go .w2 {
  opacity: 1;
  animation: uvq01-xwk-bl calc(0.5s / var(--k)) steps(1) calc(2.4s / var(--k)) infinite;
}

@keyframes uvq01-xwk-bl {
  50% {
    opacity: .15;
  }
}

@media (prefers-reduced-motion:reduce) {
  .uvq01-xwk,.uvq01-xwk *,.uvq01-xwk *::before,.uvq01-xwk *::after {
    animation-duration: .01ms!important;
    animation-iteration-count: 1!important;
    transition-duration: .01ms!important;
  }
}
`;

// Interacción en JavaScript del DOM: la misma que en la pestaña JS.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function setup(el: any) {
  const pb=el.querySelector(".pb"),w1=el.querySelector(".w1"),w2=el.querySelector(".w2"),sr=el.querySelector(".sr");let t1=0,t2=0;const k=()=>parseFloat(getComputedStyle(el).getPropertyValue("--k"))||1;
pb.addEventListener("click",()=>{if(el.classList.contains("is-wait")||el.classList.contains("is-go"))return;el.classList.add("is-wait");sr.textContent=w1.textContent;
t1=setTimeout(()=>{el.classList.remove("is-wait");el.classList.add("is-go");sr.textContent=w2.textContent.trim()},2600/k());
t2=setTimeout(()=>{el.classList.remove("is-go");sr.textContent=""},6400/k())});
return()=>{clearTimeout(t1);clearTimeout(t2)}
}

export default function BtnCrosswalk() {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const el = ref.current?.firstElementChild;
    return el ? setup(el) : undefined;
  }, []);

  return (
    <>
      <style>{css}</style>
      <div
        ref={ref} style={{
          "--c1": "#f6c400",
          "--c2": "#ff4b2b",
          "--s": "16px",
          "--k": "1",
          "--fg": "#1d1d1f",
          "--bg": "#f5f5f7",
        } as CSSProperties}
      >
        <div className="uvq01-xwk"><div className="sg" aria-hidden="true"><span className="w1">Wait</span><span className="w2"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><circle cx="13" cy="4" r="2" fill="currentColor" /><path d="M9 21l3-6 3 2v4" /><path d="M12 15l1-6-4 2-2 3" /><path d="M13 9l2.5 3 3 1" /></svg><span>Walk</span></span></div><button className="pb" type="button" aria-label="Request to cross"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M18 11V6a2 2 0 0 0-4 0" /><path d="M14 10V4a2 2 0 0 0-4 0v2" /><path d="M10 10.5V6a2 2 0 0 0-4 0v8" /><path d="M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.9-6-2.3l-3.6-3.6a2 2 0 0 1 2.8-2.8L7 15" /></svg></button><span className="lb" aria-hidden="true">Push</span><span className="sr" role="status"></span></div>
      </div>
    </>
  );
}
```

Give me the complete final code, ready to paste, and tell me in one line where to put it in my project.
````
