# Aircraft seat map picker

> A cabin section with a centre aisle: choose a free seat and the boarding pass shows its number and type.

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

## Where to use it

This radio group lays out four rows of a narrow body cabin with a rounded nose, an aisle with row numbers and seat letters on top. Free seats are tinted, taken ones are crossed out and disabled, and the chosen seat lifts in solid colour. A short script updates the boarding pass strip with the seat number and whether it is window, middle or aisle.

The main color is the airline colour for free and chosen seats. List taken seats as disabled inputs, add rows by repeating the pattern, and keep the legend below so it stays clear which seats can still be booked.

## Code

### HTML

```html
<fieldset class="uvq04-seat"><legend>Choose your seat</legend><div class="bp"><span>Seat</span><b>13C</b><em>Aisle</em></div><div class="cb"><div class="gr"><i aria-hidden="true">A</i><i aria-hidden="true">B</i><i aria-hidden="true">C</i><i aria-hidden="true"></i><i aria-hidden="true">D</i><i aria-hidden="true">E</i><i aria-hidden="true">F</i><label><input type="radio" name="uvq04-seat" value="12A" aria-label="12A" disabled><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="12B" aria-label="12B" disabled><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="12C" aria-label="12C"><span class="st"></span></label><i class="rn" aria-hidden="true">12</i><label><input type="radio" name="uvq04-seat" value="12D" aria-label="12D"><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="12E" aria-label="12E"><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="12F" aria-label="12F"><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="13A" aria-label="13A"><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="13B" aria-label="13B"><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="13C" aria-label="13C" checked><span class="st"></span></label><i class="rn" aria-hidden="true">13</i><label><input type="radio" name="uvq04-seat" value="13D" aria-label="13D"><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="13E" aria-label="13E" disabled><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="13F" aria-label="13F" disabled><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="14A" aria-label="14A" disabled><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="14B" aria-label="14B"><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="14C" aria-label="14C"><span class="st"></span></label><i class="rn" aria-hidden="true">14</i><label><input type="radio" name="uvq04-seat" value="14D" aria-label="14D"><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="14E" aria-label="14E"><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="14F" aria-label="14F"><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="15A" aria-label="15A"><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="15B" aria-label="15B"><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="15C" aria-label="15C" disabled><span class="st"></span></label><i class="rn" aria-hidden="true">15</i><label><input type="radio" name="uvq04-seat" value="15D" aria-label="15D" disabled><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="15E" aria-label="15E"><span class="st"></span></label><label><input type="radio" name="uvq04-seat" value="15F" aria-label="15F"><span class="st"></span></label></div></div><p class="lg" aria-hidden="true"><i></i>Free<i class="x"></i>Taken<i class="me"></i>Your seat</p></fieldset>
```

### CSS

```css
.uvq04-seat {
  --c1: #0f8b8d;
  --c2: #f4a259;
  --s: 16px;
  /* tamaño */
  --k: 1;
  /* velocidad */
  --fg: #1d1d1f;
  /* texto */
  --bg: #f5f5f7;
  /* fondo */
}

.uvq04-seat {
  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;
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
  width: 16em;
}

.uvq04-seat legend {
  padding: 0;
  margin: 0 0 .8em;
  font-weight: 700;
}

.uvq04-seat .bp {
  display: flex;
  align-items: baseline;
  gap: .5em;
  margin-bottom: .7em;
  padding: .55em .8em;
  border-radius: .7em;
  background: color-mix(in srgb,var(--c1) 10%,transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb,var(--c1) 30%,transparent),inset .3em 0 0 var(--c1);
}

.uvq04-seat .bp span {
  font-size: .7em;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: color-mix(in srgb,var(--fg) 60%,transparent);
}

.uvq04-seat .bp b {
  display: inline-block;
  font-size: 1.3em;
  font-variant-numeric: tabular-nums;
  color: var(--c1);
}

.uvq04-seat .bp em {
  margin-left: auto;
  font-style: normal;
  font-size: .8em;
  font-weight: 600;
}

.uvq04-seat .cb {
  padding: 1.2em .8em .8em;
  border-radius: 6em 6em 1em 1em/3.5em 3.5em 1em 1em;
  background: color-mix(in srgb,var(--fg) 4%,var(--bg));
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb,var(--fg) 10%,transparent);
}

.uvq04-seat .gr {
  display: grid;
  grid-template-columns: repeat(3,1.65em) 1.4em repeat(3,1.65em);
  gap: .35em .3em;
  justify-content: center;
}

.uvq04-seat .gr > i {
  display: grid;
  place-items: center;
  font-style: normal;
  font-size: .62em;
  font-weight: 700;
  color: color-mix(in srgb,var(--fg) 45%,transparent);
}

.uvq04-seat .gr > i.rn {
  font-size: .62em;
  font-variant-numeric: tabular-nums;
}

.uvq04-seat label {
  position: relative;
  cursor: pointer;
}

.uvq04-seat input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  pointer-events: none;
}

.uvq04-seat .st {
  position: relative;
  display: block;
  height: 1.75em;
  border-radius: .45em .45em .3em .3em;
  background: color-mix(in srgb,var(--c1) 14%,var(--bg));
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb,var(--c1) 45%,transparent);
  transition: all calc(0.25s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq04-seat .st::after {
  content: "";
  position: absolute;
  left: .2em;
  right: .2em;
  bottom: .2em;
  height: .3em;
  border-radius: .2em;
  background: color-mix(in srgb,var(--c1) 30%,transparent);
}

.uvq04-seat label:hover .st {
  background: color-mix(in srgb,var(--c1) 30%,var(--bg));
}

.uvq04-seat label:active .st {
  transform: scale(.92);
}

.uvq04-seat input:checked + .st {
  background: var(--c1);
  box-shadow: 0 .3em .7em -.3em var(--c1);
  transform: translateY(-.1em);
}

.uvq04-seat input:checked + .st::after {
  background: rgba(255,255,255,.45);
}

.uvq04-seat input:disabled + .st {
  background: color-mix(in srgb,var(--fg) 9%,var(--bg));
  box-shadow: none;
}

.uvq04-seat input:disabled + .st::after {
  inset: 0;
  height: auto;
  border-radius: inherit;
  background: linear-gradient(45deg,transparent 46%,color-mix(in srgb,var(--fg) 30%,transparent) 0 54%,transparent 0),linear-gradient(-45deg,transparent 46%,color-mix(in srgb,var(--fg) 30%,transparent) 0 54%,transparent 0) 50%/55% 55% no-repeat;
  background-size: 55% 55%;
  background-position: 50%;
  background-repeat: no-repeat;
}

.uvq04-seat label:has(input:disabled) {
  cursor: not-allowed;
}

.uvq04-seat input:focus-visible + .st {
  outline: 2px solid var(--c1);
  outline-offset: 3px;
  outline-offset: 2px;
}

.uvq04-seat .lg {
  display: flex;
  align-items: center;
  gap: .4em;
  margin: .7em 0 0;
  font-size: .68em;
  color: color-mix(in srgb,var(--fg) 60%,transparent);
}

.uvq04-seat .lg i {
  width: .9em;
  height: .9em;
  border-radius: .25em;
  background: color-mix(in srgb,var(--c1) 14%,var(--bg));
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb,var(--c1) 45%,transparent);
}

.uvq04-seat .lg i + i,.uvq04-seat .lg i.x,.uvq04-seat .lg i.me {
  margin-left: .6em;
}

.uvq04-seat .lg i.x {
  background: color-mix(in srgb,var(--fg) 9%,var(--bg));
  box-shadow: none;
}

.uvq04-seat .lg i.me {
  background: var(--c1);
  box-shadow: none;
}

.uvq04-seat .bp b.in {
  animation: uvq04-seat calc(0.3s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

@keyframes uvq04-seat {
  from {
    transform: translateY(-.35em);
    opacity: 0;
  }
}

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

### JavaScript

```js
document.querySelectorAll(".uvq04-seat").forEach(el => {
  const b = el.querySelector(".bp b");
  const t = el.querySelector(".bp em");
  const K = { A: "Window", F: "Window", B: "Middle", E: "Middle", C: "Aisle", D: "Aisle" };
  const f = () => {
    const r = el.querySelector("input:checked");
    if (!r) return;
    b.textContent = r.value;
    t.textContent = K[r.value.slice(-1)];
    b.classList.remove("in");
    void b.offsetWidth;
    b.classList.add("in");
  };
  el.addEventListener("change", f);
  return () => el.removeEventListener("change", f);
});
```

### 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 = `
.uvq04-seat {
  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;
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
  width: 16em;
}

.uvq04-seat legend {
  padding: 0;
  margin: 0 0 .8em;
  font-weight: 700;
}

.uvq04-seat .bp {
  display: flex;
  align-items: baseline;
  gap: .5em;
  margin-bottom: .7em;
  padding: .55em .8em;
  border-radius: .7em;
  background: color-mix(in srgb,var(--c1) 10%,transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb,var(--c1) 30%,transparent),inset .3em 0 0 var(--c1);
}

.uvq04-seat .bp span {
  font-size: .7em;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: color-mix(in srgb,var(--fg) 60%,transparent);
}

.uvq04-seat .bp b {
  display: inline-block;
  font-size: 1.3em;
  font-variant-numeric: tabular-nums;
  color: var(--c1);
}

.uvq04-seat .bp em {
  margin-left: auto;
  font-style: normal;
  font-size: .8em;
  font-weight: 600;
}

.uvq04-seat .cb {
  padding: 1.2em .8em .8em;
  border-radius: 6em 6em 1em 1em/3.5em 3.5em 1em 1em;
  background: color-mix(in srgb,var(--fg) 4%,var(--bg));
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb,var(--fg) 10%,transparent);
}

.uvq04-seat .gr {
  display: grid;
  grid-template-columns: repeat(3,1.65em) 1.4em repeat(3,1.65em);
  gap: .35em .3em;
  justify-content: center;
}

.uvq04-seat .gr > i {
  display: grid;
  place-items: center;
  font-style: normal;
  font-size: .62em;
  font-weight: 700;
  color: color-mix(in srgb,var(--fg) 45%,transparent);
}

.uvq04-seat .gr > i.rn {
  font-size: .62em;
  font-variant-numeric: tabular-nums;
}

.uvq04-seat label {
  position: relative;
  cursor: pointer;
}

.uvq04-seat input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  pointer-events: none;
}

.uvq04-seat .st {
  position: relative;
  display: block;
  height: 1.75em;
  border-radius: .45em .45em .3em .3em;
  background: color-mix(in srgb,var(--c1) 14%,var(--bg));
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb,var(--c1) 45%,transparent);
  transition: all calc(0.25s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq04-seat .st::after {
  content: "";
  position: absolute;
  left: .2em;
  right: .2em;
  bottom: .2em;
  height: .3em;
  border-radius: .2em;
  background: color-mix(in srgb,var(--c1) 30%,transparent);
}

.uvq04-seat label:hover .st {
  background: color-mix(in srgb,var(--c1) 30%,var(--bg));
}

.uvq04-seat label:active .st {
  transform: scale(.92);
}

.uvq04-seat input:checked + .st {
  background: var(--c1);
  box-shadow: 0 .3em .7em -.3em var(--c1);
  transform: translateY(-.1em);
}

.uvq04-seat input:checked + .st::after {
  background: rgba(255,255,255,.45);
}

.uvq04-seat input:disabled + .st {
  background: color-mix(in srgb,var(--fg) 9%,var(--bg));
  box-shadow: none;
}

.uvq04-seat input:disabled + .st::after {
  inset: 0;
  height: auto;
  border-radius: inherit;
  background: linear-gradient(45deg,transparent 46%,color-mix(in srgb,var(--fg) 30%,transparent) 0 54%,transparent 0),linear-gradient(-45deg,transparent 46%,color-mix(in srgb,var(--fg) 30%,transparent) 0 54%,transparent 0) 50%/55% 55% no-repeat;
  background-size: 55% 55%;
  background-position: 50%;
  background-repeat: no-repeat;
}

.uvq04-seat label:has(input:disabled) {
  cursor: not-allowed;
}

.uvq04-seat input:focus-visible + .st {
  outline: 2px solid var(--c1);
  outline-offset: 3px;
  outline-offset: 2px;
}

.uvq04-seat .lg {
  display: flex;
  align-items: center;
  gap: .4em;
  margin: .7em 0 0;
  font-size: .68em;
  color: color-mix(in srgb,var(--fg) 60%,transparent);
}

.uvq04-seat .lg i {
  width: .9em;
  height: .9em;
  border-radius: .25em;
  background: color-mix(in srgb,var(--c1) 14%,var(--bg));
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb,var(--c1) 45%,transparent);
}

.uvq04-seat .lg i + i,.uvq04-seat .lg i.x,.uvq04-seat .lg i.me {
  margin-left: .6em;
}

.uvq04-seat .lg i.x {
  background: color-mix(in srgb,var(--fg) 9%,var(--bg));
  box-shadow: none;
}

.uvq04-seat .lg i.me {
  background: var(--c1);
  box-shadow: none;
}

.uvq04-seat .bp b.in {
  animation: uvq04-seat calc(0.3s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

@keyframes uvq04-seat {
  from {
    transform: translateY(-.35em);
    opacity: 0;
  }
}

@media (prefers-reduced-motion:reduce) {
  .uvq04-seat,.uvq04-seat *,.uvq04-seat *::before,.uvq04-seat *::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 b = el.querySelector(".bp b");
  const t = el.querySelector(".bp em");
  const K = { A: "Window", F: "Window", B: "Middle", E: "Middle", C: "Aisle", D: "Aisle" };
  const f = () => {
    const r = el.querySelector("input:checked");
    if (!r) return;
    b.textContent = r.value;
    t.textContent = K[r.value.slice(-1)];
    b.classList.remove("in");
    void b.offsetWidth;
    b.classList.add("in");
  };
  el.addEventListener("change", f);
  return () => el.removeEventListener("change", f);
}

export default function RdSeatMap() {
  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": "#0f8b8d",
          "--c2": "#f4a259",
          "--s": "16px",
          "--k": "1",
          "--fg": "#1d1d1f",
          "--bg": "#f5f5f7",
        } as CSSProperties}
      >
        <fieldset className="uvq04-seat"><legend>Choose your seat</legend><div className="bp"><span>Seat</span><b>13C</b><em>Aisle</em></div><div className="cb"><div className="gr"><i aria-hidden="true">A</i><i aria-hidden="true">B</i><i aria-hidden="true">C</i><i aria-hidden="true"></i><i aria-hidden="true">D</i><i aria-hidden="true">E</i><i aria-hidden="true">F</i><label><input type="radio" name="uvq04-seat" value="12A" aria-label="12A" disabled={true} /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="12B" aria-label="12B" disabled={true} /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="12C" aria-label="12C" /><span className="st"></span></label><i className="rn" aria-hidden="true">12</i><label><input type="radio" name="uvq04-seat" value="12D" aria-label="12D" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="12E" aria-label="12E" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="12F" aria-label="12F" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="13A" aria-label="13A" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="13B" aria-label="13B" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="13C" aria-label="13C" checked={true} /><span className="st"></span></label><i className="rn" aria-hidden="true">13</i><label><input type="radio" name="uvq04-seat" value="13D" aria-label="13D" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="13E" aria-label="13E" disabled={true} /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="13F" aria-label="13F" disabled={true} /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="14A" aria-label="14A" disabled={true} /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="14B" aria-label="14B" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="14C" aria-label="14C" /><span className="st"></span></label><i className="rn" aria-hidden="true">14</i><label><input type="radio" name="uvq04-seat" value="14D" aria-label="14D" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="14E" aria-label="14E" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="14F" aria-label="14F" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="15A" aria-label="15A" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="15B" aria-label="15B" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="15C" aria-label="15C" disabled={true} /><span className="st"></span></label><i className="rn" aria-hidden="true">15</i><label><input type="radio" name="uvq04-seat" value="15D" aria-label="15D" disabled={true} /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="15E" aria-label="15E" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="15F" aria-label="15F" /><span className="st"></span></label></div></div><p className="lg" aria-hidden="true"><i></i>Free<i className="x"></i>Taken<i className="me"></i>Your seat</p></fieldset>
      </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 “Aircraft seat map picker” block (Radio buttons) from AIMRAN Library to my project.

## What it is
A cabin section with a centre aisle: choose a free seat and the boarding pass shows its number and type.

## Chosen settings
- Main color: #0f8b8d
- Secondary color: #f4a259
- Size: 16px (from 12 to 24px)
- Speed: 1x (from 0.5 to 2x)
- Text: "Elige tu asiento"

## 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 = `
.uvq04-seat {
  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;
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
  width: 16em;
}

.uvq04-seat legend {
  padding: 0;
  margin: 0 0 .8em;
  font-weight: 700;
}

.uvq04-seat .bp {
  display: flex;
  align-items: baseline;
  gap: .5em;
  margin-bottom: .7em;
  padding: .55em .8em;
  border-radius: .7em;
  background: color-mix(in srgb,var(--c1) 10%,transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb,var(--c1) 30%,transparent),inset .3em 0 0 var(--c1);
}

.uvq04-seat .bp span {
  font-size: .7em;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: color-mix(in srgb,var(--fg) 60%,transparent);
}

.uvq04-seat .bp b {
  display: inline-block;
  font-size: 1.3em;
  font-variant-numeric: tabular-nums;
  color: var(--c1);
}

.uvq04-seat .bp em {
  margin-left: auto;
  font-style: normal;
  font-size: .8em;
  font-weight: 600;
}

.uvq04-seat .cb {
  padding: 1.2em .8em .8em;
  border-radius: 6em 6em 1em 1em/3.5em 3.5em 1em 1em;
  background: color-mix(in srgb,var(--fg) 4%,var(--bg));
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb,var(--fg) 10%,transparent);
}

.uvq04-seat .gr {
  display: grid;
  grid-template-columns: repeat(3,1.65em) 1.4em repeat(3,1.65em);
  gap: .35em .3em;
  justify-content: center;
}

.uvq04-seat .gr > i {
  display: grid;
  place-items: center;
  font-style: normal;
  font-size: .62em;
  font-weight: 700;
  color: color-mix(in srgb,var(--fg) 45%,transparent);
}

.uvq04-seat .gr > i.rn {
  font-size: .62em;
  font-variant-numeric: tabular-nums;
}

.uvq04-seat label {
  position: relative;
  cursor: pointer;
}

.uvq04-seat input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  pointer-events: none;
}

.uvq04-seat .st {
  position: relative;
  display: block;
  height: 1.75em;
  border-radius: .45em .45em .3em .3em;
  background: color-mix(in srgb,var(--c1) 14%,var(--bg));
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb,var(--c1) 45%,transparent);
  transition: all calc(0.25s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq04-seat .st::after {
  content: "";
  position: absolute;
  left: .2em;
  right: .2em;
  bottom: .2em;
  height: .3em;
  border-radius: .2em;
  background: color-mix(in srgb,var(--c1) 30%,transparent);
}

.uvq04-seat label:hover .st {
  background: color-mix(in srgb,var(--c1) 30%,var(--bg));
}

.uvq04-seat label:active .st {
  transform: scale(.92);
}

.uvq04-seat input:checked + .st {
  background: var(--c1);
  box-shadow: 0 .3em .7em -.3em var(--c1);
  transform: translateY(-.1em);
}

.uvq04-seat input:checked + .st::after {
  background: rgba(255,255,255,.45);
}

.uvq04-seat input:disabled + .st {
  background: color-mix(in srgb,var(--fg) 9%,var(--bg));
  box-shadow: none;
}

.uvq04-seat input:disabled + .st::after {
  inset: 0;
  height: auto;
  border-radius: inherit;
  background: linear-gradient(45deg,transparent 46%,color-mix(in srgb,var(--fg) 30%,transparent) 0 54%,transparent 0),linear-gradient(-45deg,transparent 46%,color-mix(in srgb,var(--fg) 30%,transparent) 0 54%,transparent 0) 50%/55% 55% no-repeat;
  background-size: 55% 55%;
  background-position: 50%;
  background-repeat: no-repeat;
}

.uvq04-seat label:has(input:disabled) {
  cursor: not-allowed;
}

.uvq04-seat input:focus-visible + .st {
  outline: 2px solid var(--c1);
  outline-offset: 3px;
  outline-offset: 2px;
}

.uvq04-seat .lg {
  display: flex;
  align-items: center;
  gap: .4em;
  margin: .7em 0 0;
  font-size: .68em;
  color: color-mix(in srgb,var(--fg) 60%,transparent);
}

.uvq04-seat .lg i {
  width: .9em;
  height: .9em;
  border-radius: .25em;
  background: color-mix(in srgb,var(--c1) 14%,var(--bg));
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb,var(--c1) 45%,transparent);
}

.uvq04-seat .lg i + i,.uvq04-seat .lg i.x,.uvq04-seat .lg i.me {
  margin-left: .6em;
}

.uvq04-seat .lg i.x {
  background: color-mix(in srgb,var(--fg) 9%,var(--bg));
  box-shadow: none;
}

.uvq04-seat .lg i.me {
  background: var(--c1);
  box-shadow: none;
}

.uvq04-seat .bp b.in {
  animation: uvq04-seat calc(0.3s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

@keyframes uvq04-seat {
  from {
    transform: translateY(-.35em);
    opacity: 0;
  }
}

@media (prefers-reduced-motion:reduce) {
  .uvq04-seat,.uvq04-seat *,.uvq04-seat *::before,.uvq04-seat *::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 b = el.querySelector(".bp b");
  const t = el.querySelector(".bp em");
  const K = { A: "Window", F: "Window", B: "Middle", E: "Middle", C: "Aisle", D: "Aisle" };
  const f = () => {
    const r = el.querySelector("input:checked");
    if (!r) return;
    b.textContent = r.value;
    t.textContent = K[r.value.slice(-1)];
    b.classList.remove("in");
    void b.offsetWidth;
    b.classList.add("in");
  };
  el.addEventListener("change", f);
  return () => el.removeEventListener("change", f);
}

export default function RdSeatMap() {
  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": "#0f8b8d",
          "--c2": "#f4a259",
          "--s": "16px",
          "--k": "1",
          "--fg": "#1d1d1f",
          "--bg": "#f5f5f7",
        } as CSSProperties}
      >
        <fieldset className="uvq04-seat"><legend>Choose your seat</legend><div className="bp"><span>Seat</span><b>13C</b><em>Aisle</em></div><div className="cb"><div className="gr"><i aria-hidden="true">A</i><i aria-hidden="true">B</i><i aria-hidden="true">C</i><i aria-hidden="true"></i><i aria-hidden="true">D</i><i aria-hidden="true">E</i><i aria-hidden="true">F</i><label><input type="radio" name="uvq04-seat" value="12A" aria-label="12A" disabled={true} /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="12B" aria-label="12B" disabled={true} /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="12C" aria-label="12C" /><span className="st"></span></label><i className="rn" aria-hidden="true">12</i><label><input type="radio" name="uvq04-seat" value="12D" aria-label="12D" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="12E" aria-label="12E" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="12F" aria-label="12F" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="13A" aria-label="13A" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="13B" aria-label="13B" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="13C" aria-label="13C" checked={true} /><span className="st"></span></label><i className="rn" aria-hidden="true">13</i><label><input type="radio" name="uvq04-seat" value="13D" aria-label="13D" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="13E" aria-label="13E" disabled={true} /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="13F" aria-label="13F" disabled={true} /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="14A" aria-label="14A" disabled={true} /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="14B" aria-label="14B" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="14C" aria-label="14C" /><span className="st"></span></label><i className="rn" aria-hidden="true">14</i><label><input type="radio" name="uvq04-seat" value="14D" aria-label="14D" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="14E" aria-label="14E" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="14F" aria-label="14F" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="15A" aria-label="15A" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="15B" aria-label="15B" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="15C" aria-label="15C" disabled={true} /><span className="st"></span></label><i className="rn" aria-hidden="true">15</i><label><input type="radio" name="uvq04-seat" value="15D" aria-label="15D" disabled={true} /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="15E" aria-label="15E" /><span className="st"></span></label><label><input type="radio" name="uvq04-seat" value="15F" aria-label="15F" /><span className="st"></span></label></div></div><p className="lg" aria-hidden="true"><i></i>Free<i className="x"></i>Taken<i className="me"></i>Your seat</p></fieldset>
      </div>
    </>
  );
}
```

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