Ascensor de servicio

Este ascensor no llega a la planta 404.

El edificio tiene cinco plantas y la página que buscas no está en ninguna. Elige otra o baja al vestíbulo.

Bajar al vestíbulo
HTML + CSS404

404 Ascensor

Una esfera de latón art déco marca la planta del ascensor; al pulsar el 404 la aguja choca contra el tope y tiembla.

Ajustes

1x

Código

<!doctype html>
<html lang="es">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="robots" content="noindex" />
    <title>404 · Página no encontrada</title>
    <style>
      body { margin: 0; background: #000; }
      .n4-elevator {
        --accent: #f2b84b;
        --k: 1;
        position: fixed;
        inset: 0;
        z-index: 0;
        overflow: hidden;
        container-type: size;
        display: grid;
        place-items: center;
        background: #000;
        color: #f5f5f7;
        font-family: -apple-system,BlinkMacSystemFont,"SF Pro Display","Inter","Segoe UI",system-ui,sans-serif;
        -webkit-font-smoothing: antialiased;
        text-align: center;
        line-height: 1.4;
      }
      
      .n4-elevator *,.n4-elevator *::before,.n4-elevator *::after {
        box-sizing: border-box;
      }
      
      .n4-elevator .n4-copy {
        position: relative;
        z-index: 5;
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 1.6cqmin;
        width: 100%;
        max-width: 680px;
        padding: 0 6cqw;
      }
      
      .n4-elevator .n4-title {
        margin: 0;
        font-size: clamp(17px,4.2cqmin,36px);
        font-weight: 600;
        letter-spacing: -.02em;
        line-height: 1.15;
        text-wrap: balance;
      }
      
      .n4-elevator .n4-sub {
        margin: 0;
        max-width: 34em;
        font-size: clamp(13px,2.4cqmin,18px);
        color: #a1a1a6;
        text-wrap: balance;
      }
      
      .n4-elevator .n4-tag {
        font: 600 clamp(10px,1.9cqmin,13px)/1 ui-monospace,"SF Mono",Menlo,Consolas,monospace;
        letter-spacing: .16em;
        text-transform: uppercase;
        color: var(--accent);
      }
      
      .n4-elevator .n4-cta {
        margin-top: 1.8cqmin;
        display: inline-flex;
        align-items: center;
        gap: .5em;
        padding: .85em 1.5em;
        border-radius: 999px;
        background: #f5f5f7;
        color: #000;
        font-size: clamp(13px,2.2cqmin,16px);
        font-weight: 600;
        text-decoration: none;
        transition: transform .3s cubic-bezier(.25,.1,.25,1),box-shadow .3s cubic-bezier(.25,.1,.25,1);
      }
      
      .n4-elevator .n4-cta:hover {
        transform: translateY(-2px);
        box-shadow: 0 12px 32px -10px var(--accent);
      }
      
      .n4-elevator .n4-cta:focus-visible {
        outline: 2px solid var(--accent);
        outline-offset: 3px;
      }
      
      .n4-elevator .n4-stars,.n4-elevator .n4-stars2 {
        position: absolute;
        inset: -4%;
        pointer-events: none;
      }
      
      .n4-elevator .n4-stars {
        background-image: radial-gradient(1px 1px at 8% 12%,#fff 60%,transparent),radial-gradient(1px 1px at 22% 68%,#fff 60%,transparent),radial-gradient(1.5px 1.5px at 35% 24%,#fff 60%,transparent),radial-gradient(1px 1px at 48% 82%,#fff 60%,transparent),radial-gradient(1px 1px at 57% 9%,#fff 60%,transparent),radial-gradient(1.5px 1.5px at 66% 44%,#fff 60%,transparent),radial-gradient(1px 1px at 74% 72%,#fff 60%,transparent),radial-gradient(1px 1px at 86% 18%,#fff 60%,transparent),radial-gradient(1.5px 1.5px at 93% 58%,#fff 60%,transparent),radial-gradient(1px 1px at 14% 42%,#fff 60%,transparent),radial-gradient(1px 1px at 40% 55%,#fff 60%,transparent),radial-gradient(1px 1px at 81% 90%,#fff 60%,transparent),radial-gradient(1px 1px at 4% 88%,#fff 60%,transparent),radial-gradient(1px 1px at 62% 30%,#fff 60%,transparent);
        opacity: .75;
        animation: n4-elevator-tw calc(5s / var(--k)) ease-in-out infinite alternate;
      }
      
      .n4-elevator .n4-stars2 {
        background-image: radial-gradient(2px 2px at 18% 30%,rgba(255,255,255,.9) 50%,transparent),radial-gradient(1.5px 1.5px at 72% 20%,rgba(255,255,255,.8) 50%,transparent),radial-gradient(2px 2px at 30% 85%,rgba(255,255,255,.7) 50%,transparent),radial-gradient(1.5px 1.5px at 88% 70%,rgba(255,255,255,.8) 50%,transparent),radial-gradient(2px 2px at 52% 60%,rgba(255,255,255,.6) 50%,transparent),radial-gradient(1.5px 1.5px at 6% 55%,rgba(255,255,255,.8) 50%,transparent);
        opacity: .55;
        animation: n4-elevator-tw calc(7s / var(--k)) ease-in-out infinite alternate-reverse;
      }
      
      .n4-elevator [data-depth] {
        transition: transform .9s cubic-bezier(.2,.7,.2,1);
      }
      
      @keyframes n4-elevator-tw {
        from {
          opacity: .3;
        }
      }
      
      @keyframes n4-elevator-spin {
        to {
          transform: rotate(1turn);
        }
      }
      
      @keyframes n4-elevator-fade {
        from {
          opacity: 0;
          transform: translateY(10px);
        }
      }
      
      @media (prefers-reduced-motion:reduce) {
        .n4-elevator *,.n4-elevator *::before,.n4-elevator *::after {
          animation: none!important;
          transition: none!important;
        }
      }
      
      .n4-elevator {
        background: repeating-conic-gradient(from -90deg at 50% 112%,rgba(242,184,75,.07) 0 2deg,transparent 2deg 9deg),radial-gradient(80% 60% at 50% 30%,#241d12,#0b0906 75%);
        color: #f6ecd4;
        font-family: "Futura","Century Gothic","Avenir Next","Gill Sans",system-ui,sans-serif;
      }
      
      .n4-elevator .n4-lift {
        display: flex;
        flex-direction: column;
        align-items: center;
        font-size: min(2cqmin,14px);
        margin-bottom: .5cqmin;
      }
      
      .n4-elevator .n4-dial {
        width: 22em;
        height: auto;
        overflow: visible;
        filter: drop-shadow(0 1.2em 1.4em rgba(0,0,0,.6));
      }
      
      .n4-elevator .n4-ray {
        stroke: rgba(242,184,75,.16);
        stroke-width: 1;
      }
      
      .n4-elevator .n4-tk {
        stroke: #f1cf73;
        stroke-width: 2.4;
        stroke-linecap: round;
      }
      
      .n4-elevator .n4-fl {
        font: 500 15px "Futura","Century Gothic","Avenir Next","Gill Sans",system-ui,sans-serif;
        fill: #f6ecd4;
        text-anchor: middle;
      }
      
      .n4-elevator .n4-l404 {
        font: 700 11px ui-monospace,"SF Mono",Menlo,Consolas,monospace;
        fill: #5a4a33;
        text-anchor: middle;
        transition: fill .3s;
      }
      
      .n4-elevator .n4-needle {
        transform-box: view-box;
        transform-origin: 120px 130px;
        transform: rotate(var(--a,-60deg));
        transition: transform calc(var(--d,1s) / var(--k)) cubic-bezier(.34,1.45,.5,1);
      }
      
      .n4-elevator .n4-lost .n4-needle {
        animation: n4-elevator-wob calc(.14s / var(--k)) linear infinite alternate;
      }
      
      .n4-elevator .n4-lost .n4-l404 {
        fill: #ff5b4a;
        filter: drop-shadow(0 0 4px #ff5b4a);
      }
      
      .n4-elevator .n4-btns {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        gap: .8em;
        margin-top: 1.2em;
        padding: .9em 1.2em;
        border-radius: 1em;
        background: linear-gradient(135deg,#2c261c,#14110b);
        box-shadow: inset 0 0 0 1px rgba(242,184,75,.35),0 1em 1.6em -1em #000;
      }
      
      .n4-elevator .n4-fb {
        width: 3.3em;
        height: 3.3em;
        min-width: 30px;
        min-height: 30px;
        border: 0;
        border-radius: 50%;
        cursor: pointer;
        font: 600 1.15em/1 "Futura","Century Gothic","Avenir Next","Gill Sans",system-ui,sans-serif;
        color: #1a140a;
        background: radial-gradient(circle at 40% 35%,#fff3c4,#d9a93f 55%,#8a5e14);
        box-shadow: 0 .2em 0 #5a3d0c,inset 0 0 0 .18em rgba(255,255,255,.25);
        transition: transform .12s,box-shadow .2s,filter .2s;
      }
      
      .n4-elevator .n4-fb.n4-x {
        width: auto;
        padding: 0 1em;
        border-radius: 999px;
        font-family: ui-monospace,"SF Mono",Menlo,Consolas,monospace;
        font-size: 1em;
      }
      
      .n4-elevator .n4-fb:hover {
        filter: brightness(1.1);
      }
      
      .n4-elevator .n4-fb:active {
        transform: translateY(.15em);
        box-shadow: 0 .05em 0 #5a3d0c;
      }
      
      .n4-elevator .n4-fb[aria-pressed="true"] {
        box-shadow: 0 .2em 0 #5a3d0c,0 0 0 .2em #14110b,0 0 0 .38em var(--accent),0 0 1.4em var(--accent);
      }
      
      .n4-elevator .n4-fb:focus-visible {
        outline: 2px solid #fff;
        outline-offset: 5px;
      }
      
      .n4-elevator .n4-msg {
        min-height: 1.3em;
        margin: .8em 0 0;
        font: 700 .95em/1.3 ui-monospace,"SF Mono",Menlo,Consolas,monospace;
        letter-spacing: .14em;
        text-transform: uppercase;
        color: #ff6b5b;
      }
      
      .n4-elevator .n4-tag {
        font-family: "Futura","Century Gothic","Avenir Next","Gill Sans",system-ui,sans-serif;
        letter-spacing: .3em;
      }
      
      .n4-elevator .n4-title {
        font-size: clamp(20px,4.8cqmin,40px);
        font-weight: 500;
        letter-spacing: 0;
      }
      
      .n4-elevator .n4-sub {
        color: #c8b998;
      }
      
      .n4-elevator .n4-cta {
        background: var(--accent);
        color: #1a140a;
      }
      
      @keyframes n4-elevator-wob {
        from {
          rotate: -1.2deg;
        }
        to {
          rotate: 1.8deg;
        }
      }
    </style>
  </head>
  <body>
    <main class="n4-elevator">
      <div class="n4-copy">
        <div class="n4-lift">
          <svg class="n4-dial" viewBox="0 0 240 140" aria-hidden="true">
            <defs><linearGradient id="uvq17-brass" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#f7dc8c"/><stop offset=".45" stop-color="#b8862b"/><stop offset=".7" stop-color="#f1cf73"/><stop offset="1" stop-color="#8a5e14"/></linearGradient></defs>
            <path d="M8 132A112 112 0 0 1 232 132Z" fill="url(#uvq17-brass)"/>
            <path d="M20 130A100 100 0 0 1 220 130Z" fill="#15110b"/>
            <path class="n4-ray" d="M98.3 126.2L47.1 117.2"/><path class="n4-ray" d="M99.3 122.5L50.5 104.7"/><path class="n4-ray" d="M100.9 119.0L55.9 93.0"/><path class="n4-ray" d="M103.1 115.9L63.3 82.4"/><path class="n4-ray" d="M105.9 113.1L72.4 73.3"/><path class="n4-ray" d="M109.0 110.9L83.0 65.9"/><path class="n4-ray" d="M112.5 109.3L94.7 60.5"/><path class="n4-ray" d="M116.2 108.3L107.2 57.1"/><path class="n4-ray" d="M120.0 108.0L120.0 56.0"/><path class="n4-ray" d="M123.8 108.3L132.8 57.1"/><path class="n4-ray" d="M127.5 109.3L145.3 60.5"/><path class="n4-ray" d="M131.0 110.9L157.0 65.9"/><path class="n4-ray" d="M134.1 113.1L167.6 73.3"/><path class="n4-ray" d="M136.9 115.9L176.7 82.4"/><path class="n4-ray" d="M139.1 119.0L184.1 93.0"/><path class="n4-ray" d="M140.7 122.5L189.5 104.7"/><path class="n4-ray" d="M141.7 126.2L192.9 117.2"/><path class="n4-tk" d="M42.1 85.0L35.1 81.0"/><text class="n4-fl" x="52.5" y="96.0">0</text><path class="n4-tk" d="M67.1 57.2L62.4 50.7"/><text class="n4-fl" x="74.2" y="71.9">1</text><path class="n4-tk" d="M101.3 42.0L99.6 34.1"/><text class="n4-fl" x="103.8" y="58.7">2</text><path class="n4-tk" d="M138.7 42.0L140.4 34.1"/><text class="n4-fl" x="136.2" y="58.7">3</text><path class="n4-tk" d="M172.9 57.2L177.6 50.7"/><text class="n4-fl" x="165.8" y="71.9">4</text><path class="n4-tk" d="M197.9 85.0L204.9 81.0"/><text class="n4-fl" x="187.5" y="96.0">5</text>
            <text class="n4-l404" x="207" y="122">404</text>
            <g class="n4-needle"><path d="M117 130L120 40l3 90z" fill="url(#uvq17-brass)"/></g>
            <circle cx="120" cy="130" r="10" fill="url(#uvq17-brass)"/>
          </svg>
          <div class="n4-btns" role="group" aria-label="Botonera del ascensor">
            <button class="n4-fb" type="button" data-f="0" aria-pressed="false">0</button><button class="n4-fb" type="button" data-f="1" aria-pressed="false">1</button><button class="n4-fb" type="button" data-f="2" aria-pressed="false">2</button><button class="n4-fb" type="button" data-f="3" aria-pressed="false">3</button><button class="n4-fb" type="button" data-f="4" aria-pressed="false">4</button><button class="n4-fb" type="button" data-f="5" aria-pressed="false">5</button>
            <button class="n4-fb n4-x" type="button" data-f="404" aria-pressed="false">404</button>
          </div>
          <p class="n4-msg" aria-live="polite"></p>
        </div>
        <span class="n4-tag">Ascensor de servicio</span>
        <h1 class="n4-title">Este ascensor no llega a la planta 404.</h1>
        <p class="n4-sub">El edificio tiene cinco plantas y la página que buscas no está en ninguna. Elige otra o baja al vestíbulo.</p>
        <a class="n4-cta" href="/">Bajar al vestíbulo</a>
      </div>
    </main>
    <script>
      document.querySelectorAll(".n4-elevator").forEach((el) => {
        const btns = el.querySelectorAll(".n4-fb");
        const lift = el.querySelector(".n4-lift");
        const msg = el.querySelector(".n4-msg");
        const rm = matchMedia("(prefers-reduced-motion: reduce)").matches;
        const k = parseFloat(getComputedStyle(el).getPropertyValue("--k")) || 1;
        const pos = (f) => (f === 404 ? 7 : f);
        let cur = 0, timer = 0;
        const go = (b) => {
          const f = Number(b.dataset.f);
          const steps = Math.abs(pos(f) - pos(cur));
          clearTimeout(timer);
          btns.forEach((x) => x.setAttribute("aria-pressed", String(x === b)));
          lift.classList.remove("n4-lost");
          msg.textContent = "";
          lift.style.setProperty("--d", 0.4 + steps * 0.25 + "s");
          lift.style.setProperty("--a", (f === 404 ? 86 : -60 + 24 * f) + "deg");
          cur = f;
          timer = setTimeout(() => {
            if (f !== 404) b.setAttribute("aria-pressed", "false");
            else {
              lift.classList.add("n4-lost");
              msg.textContent = "Esta planta no existe";
            }
          }, rm ? 0 : (400 + steps * 250) / k + 120);
        };
        btns.forEach((b) => b.addEventListener("click", () => go(b)));
        const auto = setTimeout(() => go(btns[btns.length - 1]), rm ? 0 : 900 / k);
      });
    </script>
  </body>
</html>

Prompt para IA

Pégalo en ChatGPT, Claude o Cursor y adaptará el bloque a tu proyecto con estos ajustes, aunque no uses React.

Versión Markdown con todo el código, para asistentes de IA

Más en 404

Ver todos: 404

Dónde usarlo

Los hoteles y edificios de oficinas antiguos todavía conservan esas esferas semicirculares de latón sobre las puertas del ascensor, y esta página de error construye una en SVG sobre un fondo lacado en negro con rayos dorados muy suaves. La aguja salta a cada planta con un rebote de muelle, y la planta 404 la lleva más allá del último número, contra el tope.

Los botones de planta son botones reales, con estado pulsado, foco de teclado y un aro iluminado mientras la cabina se mueve. Un aviso breve dice que la planta no existe. Ajusta el dorado y enlaza el botón con tu vestíbulo.