# IBAN input with check digits

> Groups the IBAN in fours on security paper, recognises the country and verifies the check digits once you finish.

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

## Where to use it

A bank account field that does the boring work for you. It strips spaces and lowercase, groups characters in fours while keeping the caret in place, reads the country code to know the expected length and fills a segmented bar group by group. At the end it runs the official mod 97 check and shows a tick or a clear error.

The guilloche pattern behind the text uses the main color at low strength, like the background of a cheque. Use it in payroll, direct debit and checkout forms, and add more countries to the length table in the script if you need them.

## Code

### HTML

```html
<div class="uvq06-ib"><label for="uvq06-ib-in" class="lb">Bank account (IBAN)</label><div class="fd"><span class="cc" aria-hidden="true">··</span><input id="uvq06-ib-in" autocomplete="off" spellcheck="false" maxlength="42" placeholder="ES00 0000 0000 0000 0000 0000" aria-describedby="uvq06-ib-st"><span class="ck" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg></span></div><div class="gr" aria-hidden="true"><i></i><i></i><i></i><i></i><i></i><i></i><i hidden></i><i hidden></i><i hidden></i></div><p class="st" id="uvq06-ib-st" aria-live="polite">Enter your IBAN</p></div>
```

### CSS

```css
.uvq06-ib {
  --c1: #047857;
  --c2: #d1fae5;
  --s: 16px;
  /* tamaño */
  --k: 1;
  /* velocidad */
  --fg: #1d1d1f;
  /* texto */
  --bg: #f5f5f7;
  /* fondo */
}

.uvq06-ib {
  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;
  width: 21em;
  --n: 6;
}

.uvq06-ib .lb {
  display: block;
  margin: 0 0 .45em;
  font-size: .82em;
  font-weight: 650;
}

.uvq06-ib .fd {
  display: flex;
  align-items: center;
  gap: .5em;
  padding: 0 .55em;
  border-radius: .9em;
  background: color-mix(in srgb,var(--fg) 3%,var(--bg));
  box-shadow: 0 0 0 1px color-mix(in srgb,var(--fg) 12%,transparent),0 14px 34px -24px rgba(0,0,0,.45);
  background-image: repeating-radial-gradient(circle at 0 130%,transparent 0 5px,color-mix(in srgb,var(--c1) 9%,transparent) 5px 6px),repeating-radial-gradient(circle at 100% -30%,transparent 0 7px,color-mix(in srgb,var(--c1) 7%,transparent) 7px 8px);
  transition: box-shadow calc(0.25s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq06-ib .fd:focus-within {
  box-shadow: 0 0 0 2px var(--c1),0 0 0 6px color-mix(in srgb,var(--c1) 18%,transparent),0 14px 34px -24px rgba(0,0,0,.45);
}

.uvq06-ib.ok .fd {
  box-shadow: 0 0 0 2px var(--c1),0 14px 34px -24px rgba(0,0,0,.45);
}

.uvq06-ib.bad .fd {
  box-shadow: 0 0 0 2px #e5484d,0 14px 34px -24px rgba(0,0,0,.45);
}

.uvq06-ib .cc {
  flex: none;
  padding: .45em .5em;
  border-radius: .4em;
  font: 800 .72em/1 ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  letter-spacing: .06em;
  color: color-mix(in srgb,var(--c1) 70%,var(--fg));
  background: color-mix(in srgb,var(--c1) 14%,transparent);
}

.uvq06-ib .cc.pop {
  animation: uvq06-ib calc(0.4s / var(--k)) cubic-bezier(.34,1.56,.64,1);
}

.uvq06-ib input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: none;
  font: inherit;
  color: var(--fg);
  width: 0;
  height: 3em;
  font-family: ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  font-size: .82em;
  letter-spacing: .02em;
  text-transform: uppercase;
}

.uvq06-ib input::placeholder {
  color: color-mix(in srgb,var(--fg) 55%,transparent);
}

.uvq06-ib .ck {
  display: grid;
  place-items: center;
  flex: none;
  width: 1.45em;
  height: 1.45em;
  border-radius: 50%;
  color: #fff;
  background: var(--c1);
  transform: scale(0) rotate(-90deg);
  transition: transform calc(0.45s / var(--k)) cubic-bezier(.34,1.56,.64,1);
}

.uvq06-ib .ck svg {
  width: .85em;
  height: .85em;
}

.uvq06-ib.ok .ck {
  transform: none;
}

.uvq06-ib .gr {
  display: grid;
  grid-template-columns: repeat(var(--n),1fr);
  gap: .25em;
  margin: .6em .15em 0;
}

.uvq06-ib .gr i {
  height: .28em;
  border-radius: 1em;
  background: color-mix(in srgb,var(--fg) 6%,transparent);
  transition: background calc(0.3s / var(--k)) cubic-bezier(.25,.1,.25,1),transform calc(0.3s / var(--k)) cubic-bezier(.34,1.56,.64,1);
}

.uvq06-ib .gr i[hidden] {
  display: none;
}

.uvq06-ib .gr i.on {
  background: var(--c1);
  transform: scaleY(1.3);
}

.uvq06-ib.bad .gr i.on {
  background: #e5484d;
}

.uvq06-ib .st {
  min-height: 1.2em;
  margin: .45em 0 0;
  font-size: .78em;
  color: color-mix(in srgb,var(--fg) 55%,transparent);
}

.uvq06-ib.ok .st {
  font-weight: 650;
  color: color-mix(in srgb,var(--c1) 70%,var(--fg));
}

.uvq06-ib.bad .st {
  font-weight: 650;
  color: #e5484d;
}

@keyframes uvq06-ib {
  from {
    transform: scale(.5);
  }
}
```

### JavaScript

```js
document.querySelectorAll(".uvq06-ib").forEach(el => {
  const i=el.querySelector("input"),cc=el.querySelector(".cc"),gs=[...el.querySelectorAll(".gr i")],st=el.querySelector(".st");const LEN={ES:24,DE:22,FR:27,IT:27,PT:25,NL:18,BE:16,GB:22,IE:22,AT:20,CH:21,LU:20};
const mod=s=>{let m=0;for(const ch of s.slice(4)+s.slice(0,4)){const v=/[A-Z]/.test(ch)?String(ch.charCodeAt(0)-55):ch;for(const d of v)m=(m*10+Number(d))%97}return m===1};
const u=()=>{const p=i.selectionStart||0,before=i.value.slice(0,p).replace(/[^0-9A-Za-z]/g,"").length;const s=i.value.toUpperCase().replace(/[^0-9A-Z]/g,"").slice(0,34);i.value=s.replace(/(.{4})(?=.)/g,"$1 ");
if(document.activeElement===i){const np=before+Math.floor(Math.max(0,before-1)/4)+(before&&before%4===0&&before<s.length?1:0);i.setSelectionRange(np,np)}
const cn=s.slice(0,2),n=LEN[cn],code=/^[A-Z]{2}$/.test(cn)?cn:"··";if(cc.textContent!==code){cc.textContent=code;cc.classList.remove("pop");void cc.offsetWidth;cc.classList.add("pop")}
const need=n||24,g=Math.ceil(need/4);el.style.setProperty("--n",String(g));gs.forEach((x,k)=>{x.hidden=k>=g;x.classList.toggle("on",(k+1)*4<=s.length||k===g-1&&s.length>=need)});
el.classList.remove("ok","bad");const left=need-s.length;
if(!s)st.textContent="Enter your IBAN";else if(/^[A-Z]{2}/.test(s)&&!n){st.textContent="Country not recognised";el.classList.add("bad")}else if(left===1)st.textContent="1 character left";else if(left>0)st.textContent="Missing "+left+" characters";else if(left<0){st.textContent="Too many characters";el.classList.add("bad")}else if(mod(s)){st.textContent="Valid IBAN";el.classList.add("ok")}else{st.textContent="The check digits don't match";el.classList.add("bad")}};
i.addEventListener("input",u);i.value="ES9121000418450200051332";u()
});
```

### 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 = `
.uvq06-ib {
  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;
  width: 21em;
  --n: 6;
}

.uvq06-ib .lb {
  display: block;
  margin: 0 0 .45em;
  font-size: .82em;
  font-weight: 650;
}

.uvq06-ib .fd {
  display: flex;
  align-items: center;
  gap: .5em;
  padding: 0 .55em;
  border-radius: .9em;
  background: color-mix(in srgb,var(--fg) 3%,var(--bg));
  box-shadow: 0 0 0 1px color-mix(in srgb,var(--fg) 12%,transparent),0 14px 34px -24px rgba(0,0,0,.45);
  background-image: repeating-radial-gradient(circle at 0 130%,transparent 0 5px,color-mix(in srgb,var(--c1) 9%,transparent) 5px 6px),repeating-radial-gradient(circle at 100% -30%,transparent 0 7px,color-mix(in srgb,var(--c1) 7%,transparent) 7px 8px);
  transition: box-shadow calc(0.25s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq06-ib .fd:focus-within {
  box-shadow: 0 0 0 2px var(--c1),0 0 0 6px color-mix(in srgb,var(--c1) 18%,transparent),0 14px 34px -24px rgba(0,0,0,.45);
}

.uvq06-ib.ok .fd {
  box-shadow: 0 0 0 2px var(--c1),0 14px 34px -24px rgba(0,0,0,.45);
}

.uvq06-ib.bad .fd {
  box-shadow: 0 0 0 2px #e5484d,0 14px 34px -24px rgba(0,0,0,.45);
}

.uvq06-ib .cc {
  flex: none;
  padding: .45em .5em;
  border-radius: .4em;
  font: 800 .72em/1 ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  letter-spacing: .06em;
  color: color-mix(in srgb,var(--c1) 70%,var(--fg));
  background: color-mix(in srgb,var(--c1) 14%,transparent);
}

.uvq06-ib .cc.pop {
  animation: uvq06-ib calc(0.4s / var(--k)) cubic-bezier(.34,1.56,.64,1);
}

.uvq06-ib input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: none;
  font: inherit;
  color: var(--fg);
  width: 0;
  height: 3em;
  font-family: ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  font-size: .82em;
  letter-spacing: .02em;
  text-transform: uppercase;
}

.uvq06-ib input::placeholder {
  color: color-mix(in srgb,var(--fg) 55%,transparent);
}

.uvq06-ib .ck {
  display: grid;
  place-items: center;
  flex: none;
  width: 1.45em;
  height: 1.45em;
  border-radius: 50%;
  color: #fff;
  background: var(--c1);
  transform: scale(0) rotate(-90deg);
  transition: transform calc(0.45s / var(--k)) cubic-bezier(.34,1.56,.64,1);
}

.uvq06-ib .ck svg {
  width: .85em;
  height: .85em;
}

.uvq06-ib.ok .ck {
  transform: none;
}

.uvq06-ib .gr {
  display: grid;
  grid-template-columns: repeat(var(--n),1fr);
  gap: .25em;
  margin: .6em .15em 0;
}

.uvq06-ib .gr i {
  height: .28em;
  border-radius: 1em;
  background: color-mix(in srgb,var(--fg) 6%,transparent);
  transition: background calc(0.3s / var(--k)) cubic-bezier(.25,.1,.25,1),transform calc(0.3s / var(--k)) cubic-bezier(.34,1.56,.64,1);
}

.uvq06-ib .gr i[hidden] {
  display: none;
}

.uvq06-ib .gr i.on {
  background: var(--c1);
  transform: scaleY(1.3);
}

.uvq06-ib.bad .gr i.on {
  background: #e5484d;
}

.uvq06-ib .st {
  min-height: 1.2em;
  margin: .45em 0 0;
  font-size: .78em;
  color: color-mix(in srgb,var(--fg) 55%,transparent);
}

.uvq06-ib.ok .st {
  font-weight: 650;
  color: color-mix(in srgb,var(--c1) 70%,var(--fg));
}

.uvq06-ib.bad .st {
  font-weight: 650;
  color: #e5484d;
}

@keyframes uvq06-ib {
  from {
    transform: scale(.5);
  }
}
`;

// 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 i=el.querySelector("input"),cc=el.querySelector(".cc"),gs=[...el.querySelectorAll(".gr i")],st=el.querySelector(".st");const LEN={ES:24,DE:22,FR:27,IT:27,PT:25,NL:18,BE:16,GB:22,IE:22,AT:20,CH:21,LU:20};
const mod=s=>{let m=0;for(const ch of s.slice(4)+s.slice(0,4)){const v=/[A-Z]/.test(ch)?String(ch.charCodeAt(0)-55):ch;for(const d of v)m=(m*10+Number(d))%97}return m===1};
const u=()=>{const p=i.selectionStart||0,before=i.value.slice(0,p).replace(/[^0-9A-Za-z]/g,"").length;const s=i.value.toUpperCase().replace(/[^0-9A-Z]/g,"").slice(0,34);i.value=s.replace(/(.{4})(?=.)/g,"$1 ");
if(document.activeElement===i){const np=before+Math.floor(Math.max(0,before-1)/4)+(before&&before%4===0&&before<s.length?1:0);i.setSelectionRange(np,np)}
const cn=s.slice(0,2),n=LEN[cn],code=/^[A-Z]{2}$/.test(cn)?cn:"··";if(cc.textContent!==code){cc.textContent=code;cc.classList.remove("pop");void cc.offsetWidth;cc.classList.add("pop")}
const need=n||24,g=Math.ceil(need/4);el.style.setProperty("--n",String(g));gs.forEach((x,k)=>{x.hidden=k>=g;x.classList.toggle("on",(k+1)*4<=s.length||k===g-1&&s.length>=need)});
el.classList.remove("ok","bad");const left=need-s.length;
if(!s)st.textContent="Enter your IBAN";else if(/^[A-Z]{2}/.test(s)&&!n){st.textContent="Country not recognised";el.classList.add("bad")}else if(left===1)st.textContent="1 character left";else if(left>0)st.textContent="Missing "+left+" characters";else if(left<0){st.textContent="Too many characters";el.classList.add("bad")}else if(mod(s)){st.textContent="Valid IBAN";el.classList.add("ok")}else{st.textContent="The check digits don't match";el.classList.add("bad")}};
i.addEventListener("input",u);i.value="ES9121000418450200051332";u()
}

export default function InIban() {
  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": "#047857",
          "--c2": "#d1fae5",
          "--s": "16px",
          "--k": "1",
          "--fg": "#1d1d1f",
          "--bg": "#f5f5f7",
        } as CSSProperties}
      >
        <div className="uvq06-ib"><label htmlFor="uvq06-ib-in" className="lb">Bank account (IBAN)</label><div className="fd"><span className="cc" aria-hidden="true">··</span><input id="uvq06-ib-in" autoComplete="off" spellCheck="false" maxLength={42} placeholder="ES00 0000 0000 0000 0000 0000" aria-describedby="uvq06-ib-st" /><span className="ck" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5" /></svg></span></div><div className="gr" aria-hidden="true"><i></i><i></i><i></i><i></i><i></i><i></i><i hidden={true}></i><i hidden={true}></i><i hidden={true}></i></div><p className="st" id="uvq06-ib-st" aria-live="polite">Enter your IBAN</p></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 “IBAN input with check digits” block (Inputs) from AIMRAN Library to my project.

## What it is
Groups the IBAN in fours on security paper, recognises the country and verifies the check digits once you finish.

## Chosen settings
- Main color: #047857
- Secondary color: #d1fae5
- Size: 16px (from 12 to 24px)
- Speed: 1x (from 0.5 to 2x)
- Text: "Cuenta bancaria (IBAN)"

## 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 = `
.uvq06-ib {
  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;
  width: 21em;
  --n: 6;
}

.uvq06-ib .lb {
  display: block;
  margin: 0 0 .45em;
  font-size: .82em;
  font-weight: 650;
}

.uvq06-ib .fd {
  display: flex;
  align-items: center;
  gap: .5em;
  padding: 0 .55em;
  border-radius: .9em;
  background: color-mix(in srgb,var(--fg) 3%,var(--bg));
  box-shadow: 0 0 0 1px color-mix(in srgb,var(--fg) 12%,transparent),0 14px 34px -24px rgba(0,0,0,.45);
  background-image: repeating-radial-gradient(circle at 0 130%,transparent 0 5px,color-mix(in srgb,var(--c1) 9%,transparent) 5px 6px),repeating-radial-gradient(circle at 100% -30%,transparent 0 7px,color-mix(in srgb,var(--c1) 7%,transparent) 7px 8px);
  transition: box-shadow calc(0.25s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq06-ib .fd:focus-within {
  box-shadow: 0 0 0 2px var(--c1),0 0 0 6px color-mix(in srgb,var(--c1) 18%,transparent),0 14px 34px -24px rgba(0,0,0,.45);
}

.uvq06-ib.ok .fd {
  box-shadow: 0 0 0 2px var(--c1),0 14px 34px -24px rgba(0,0,0,.45);
}

.uvq06-ib.bad .fd {
  box-shadow: 0 0 0 2px #e5484d,0 14px 34px -24px rgba(0,0,0,.45);
}

.uvq06-ib .cc {
  flex: none;
  padding: .45em .5em;
  border-radius: .4em;
  font: 800 .72em/1 ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  letter-spacing: .06em;
  color: color-mix(in srgb,var(--c1) 70%,var(--fg));
  background: color-mix(in srgb,var(--c1) 14%,transparent);
}

.uvq06-ib .cc.pop {
  animation: uvq06-ib calc(0.4s / var(--k)) cubic-bezier(.34,1.56,.64,1);
}

.uvq06-ib input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: none;
  font: inherit;
  color: var(--fg);
  width: 0;
  height: 3em;
  font-family: ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  font-size: .82em;
  letter-spacing: .02em;
  text-transform: uppercase;
}

.uvq06-ib input::placeholder {
  color: color-mix(in srgb,var(--fg) 55%,transparent);
}

.uvq06-ib .ck {
  display: grid;
  place-items: center;
  flex: none;
  width: 1.45em;
  height: 1.45em;
  border-radius: 50%;
  color: #fff;
  background: var(--c1);
  transform: scale(0) rotate(-90deg);
  transition: transform calc(0.45s / var(--k)) cubic-bezier(.34,1.56,.64,1);
}

.uvq06-ib .ck svg {
  width: .85em;
  height: .85em;
}

.uvq06-ib.ok .ck {
  transform: none;
}

.uvq06-ib .gr {
  display: grid;
  grid-template-columns: repeat(var(--n),1fr);
  gap: .25em;
  margin: .6em .15em 0;
}

.uvq06-ib .gr i {
  height: .28em;
  border-radius: 1em;
  background: color-mix(in srgb,var(--fg) 6%,transparent);
  transition: background calc(0.3s / var(--k)) cubic-bezier(.25,.1,.25,1),transform calc(0.3s / var(--k)) cubic-bezier(.34,1.56,.64,1);
}

.uvq06-ib .gr i[hidden] {
  display: none;
}

.uvq06-ib .gr i.on {
  background: var(--c1);
  transform: scaleY(1.3);
}

.uvq06-ib.bad .gr i.on {
  background: #e5484d;
}

.uvq06-ib .st {
  min-height: 1.2em;
  margin: .45em 0 0;
  font-size: .78em;
  color: color-mix(in srgb,var(--fg) 55%,transparent);
}

.uvq06-ib.ok .st {
  font-weight: 650;
  color: color-mix(in srgb,var(--c1) 70%,var(--fg));
}

.uvq06-ib.bad .st {
  font-weight: 650;
  color: #e5484d;
}

@keyframes uvq06-ib {
  from {
    transform: scale(.5);
  }
}
`;

// 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 i=el.querySelector("input"),cc=el.querySelector(".cc"),gs=[...el.querySelectorAll(".gr i")],st=el.querySelector(".st");const LEN={ES:24,DE:22,FR:27,IT:27,PT:25,NL:18,BE:16,GB:22,IE:22,AT:20,CH:21,LU:20};
const mod=s=>{let m=0;for(const ch of s.slice(4)+s.slice(0,4)){const v=/[A-Z]/.test(ch)?String(ch.charCodeAt(0)-55):ch;for(const d of v)m=(m*10+Number(d))%97}return m===1};
const u=()=>{const p=i.selectionStart||0,before=i.value.slice(0,p).replace(/[^0-9A-Za-z]/g,"").length;const s=i.value.toUpperCase().replace(/[^0-9A-Z]/g,"").slice(0,34);i.value=s.replace(/(.{4})(?=.)/g,"$1 ");
if(document.activeElement===i){const np=before+Math.floor(Math.max(0,before-1)/4)+(before&&before%4===0&&before<s.length?1:0);i.setSelectionRange(np,np)}
const cn=s.slice(0,2),n=LEN[cn],code=/^[A-Z]{2}$/.test(cn)?cn:"··";if(cc.textContent!==code){cc.textContent=code;cc.classList.remove("pop");void cc.offsetWidth;cc.classList.add("pop")}
const need=n||24,g=Math.ceil(need/4);el.style.setProperty("--n",String(g));gs.forEach((x,k)=>{x.hidden=k>=g;x.classList.toggle("on",(k+1)*4<=s.length||k===g-1&&s.length>=need)});
el.classList.remove("ok","bad");const left=need-s.length;
if(!s)st.textContent="Enter your IBAN";else if(/^[A-Z]{2}/.test(s)&&!n){st.textContent="Country not recognised";el.classList.add("bad")}else if(left===1)st.textContent="1 character left";else if(left>0)st.textContent="Missing "+left+" characters";else if(left<0){st.textContent="Too many characters";el.classList.add("bad")}else if(mod(s)){st.textContent="Valid IBAN";el.classList.add("ok")}else{st.textContent="The check digits don't match";el.classList.add("bad")}};
i.addEventListener("input",u);i.value="ES9121000418450200051332";u()
}

export default function InIban() {
  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": "#047857",
          "--c2": "#d1fae5",
          "--s": "16px",
          "--k": "1",
          "--fg": "#1d1d1f",
          "--bg": "#f5f5f7",
        } as CSSProperties}
      >
        <div className="uvq06-ib"><label htmlFor="uvq06-ib-in" className="lb">Bank account (IBAN)</label><div className="fd"><span className="cc" aria-hidden="true">··</span><input id="uvq06-ib-in" autoComplete="off" spellCheck="false" maxLength={42} placeholder="ES00 0000 0000 0000 0000 0000" aria-describedby="uvq06-ib-st" /><span className="ck" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5" /></svg></span></div><div className="gr" aria-hidden="true"><i></i><i></i><i></i><i></i><i></i><i></i><i hidden={true}></i><i hidden={true}></i><i hidden={true}></i></div><p className="st" id="uvq06-ib-st" aria-live="polite">Enter your IBAN</p></div>
      </div>
    </>
  );
}
```

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