Fin de la partida para esta página.

La pantalla que buscas ya no está en la máquina. Rompe unos cuantos ladrillos o vuelve al menú principal.

Volver al menú
HTML + CSS404

404 Recreativa

Una recreativa con pantalla de tubo donde los ladrillos forman un 404; la pala juega sola hasta que tomas el control.

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-arcade {
        --accent: #ffd43b;
        --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-arcade *,.n4-arcade *::before,.n4-arcade *::after {
        box-sizing: border-box;
      }
      
      .n4-arcade .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-arcade .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-arcade .n4-sub {
        margin: 0;
        max-width: 34em;
        font-size: clamp(13px,2.4cqmin,18px);
        color: #a1a1a6;
        text-wrap: balance;
      }
      
      .n4-arcade .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-arcade .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-arcade .n4-cta:hover {
        transform: translateY(-2px);
        box-shadow: 0 12px 32px -10px var(--accent);
      }
      
      .n4-arcade .n4-cta:focus-visible {
        outline: 2px solid var(--accent);
        outline-offset: 3px;
      }
      
      .n4-arcade .n4-stars,.n4-arcade .n4-stars2 {
        position: absolute;
        inset: -4%;
        pointer-events: none;
      }
      
      .n4-arcade .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-arcade-tw calc(5s / var(--k)) ease-in-out infinite alternate;
      }
      
      .n4-arcade .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-arcade-tw calc(7s / var(--k)) ease-in-out infinite alternate-reverse;
      }
      
      .n4-arcade [data-depth] {
        transition: transform .9s cubic-bezier(.2,.7,.2,1);
      }
      
      @keyframes n4-arcade-tw {
        from {
          opacity: .3;
        }
      }
      
      @keyframes n4-arcade-spin {
        to {
          transform: rotate(1turn);
        }
      }
      
      @keyframes n4-arcade-fade {
        from {
          opacity: 0;
          transform: translateY(10px);
        }
      }
      
      @media (prefers-reduced-motion:reduce) {
        .n4-arcade *,.n4-arcade *::before,.n4-arcade *::after {
          animation: none!important;
          transition: none!important;
        }
      }
      
      .n4-arcade {
        background: radial-gradient(circle at 30% 30%,rgba(255,93,93,.18) 0 .5cqmin,transparent .6cqmin) 0 0/8cqmin 8cqmin,radial-gradient(circle at 70% 70%,rgba(77,171,247,.18) 0 .45cqmin,transparent .55cqmin) 0 0/6cqmin 6cqmin,radial-gradient(circle at 50% 20%,rgba(255,212,59,.14) 0 .35cqmin,transparent .45cqmin) 0 0/5cqmin 5cqmin,radial-gradient(70% 60% at 50% 30%,#151c2f,#06080f 75%);
        color: #eef3ff;
      }
      
      .n4-arcade .n4-cab {
        width: min(62cqmin,430px);
        font-size: min(2cqmin,14px);
        margin-bottom: 1.6cqmin;
        padding: 1em 1.2em 1.3em;
        border-radius: 1.4em 1.4em .8em .8em;
        background: linear-gradient(#25252c,#111115);
        box-shadow: inset 0 0 0 .2em #34343d,0 2em 3em -1.5em #000;
      }
      
      .n4-arcade .n4-marq {
        margin: 0 0 .7em;
        padding: .5em;
        border-radius: .5em;
        background: linear-gradient(#0b0b0e,#18181d);
        font: 800 1.5em/1 ui-monospace,"SF Mono",Menlo,Consolas,monospace;
        letter-spacing: .16em;
        text-transform: uppercase;
        color: var(--accent);
        text-shadow: 0 0 .4em color-mix(in srgb,var(--accent) 70%,transparent);
        box-shadow: inset 0 0 0 .1em #2e2e36;
      }
      
      .n4-arcade .n4-hud {
        display: flex;
        align-items: baseline;
        gap: .5em;
        margin-bottom: .55em;
        padding: 0 .3em;
        font: 700 .85em/1 ui-monospace,"SF Mono",Menlo,Consolas,monospace;
        text-transform: uppercase;
        letter-spacing: .12em;
        color: #8e98ad;
      }
      
      .n4-arcade .n4-hud b {
        color: #eef3ff;
        font-size: 1.15em;
      }
      
      .n4-arcade .n4-hud b:first-of-type {
        margin-right: auto;
      }
      
      .n4-arcade .n4-screen {
        position: relative;
        overflow: hidden;
        border-radius: 1.2em/1em;
        background: #060b08;
        box-shadow: 0 0 0 .45em #0a0a0c,0 0 0 calc(.45em + 1px) #2b2b33;
      }
      
      .n4-arcade .n4-screen::after {
        content: "";
        position: absolute;
        inset: 0;
        pointer-events: none;
        border-radius: inherit;
        background: repeating-linear-gradient(rgba(0,0,0,.3) 0 1px,transparent 1px 3px),radial-gradient(120% 90% at 50% 50%,transparent 58%,rgba(0,0,0,.65));
        box-shadow: inset 0 0 2em rgba(120,255,170,.08);
      }
      
      .n4-arcade .n4-cv {
        display: block;
        width: 100%;
        height: auto;
        image-rendering: pixelated;
        cursor: ew-resize;
        touch-action: none;
        filter: saturate(1.15) contrast(1.05);
      }
      
      .n4-arcade .n4-cv:focus-visible {
        outline: 2px solid var(--accent);
        outline-offset: -4px;
      }
      
      .n4-arcade .n4-title {
        font-size: clamp(20px,5cqmin,42px);
        font-weight: 800;
        letter-spacing: -.03em;
      }
      
      .n4-arcade .n4-sub {
        color: #a3aec4;
      }
      
      .n4-arcade .n4-cta {
        background: var(--accent);
        color: #14110a;
      }
    </style>
  </head>
  <body>
    <main class="n4-arcade">
      <div class="n4-copy">
        <div class="n4-cab">
          <p class="n4-marq" aria-hidden="true">Rompe el 404</p>
          <div class="n4-hud" aria-hidden="true"><span>Puntos</span><b class="n4-score" translate="no">000</b><span>Vidas</span><b translate="no">∞</b></div>
          <div class="n4-screen"><canvas class="n4-cv" width="260" height="160" tabindex="0" role="img" aria-label="Juego de ladrillos: mueve la pala con las flechas o con el puntero"></canvas></div>
        </div>
        <h1 class="n4-title">Fin de la partida para esta página.</h1>
        <p class="n4-sub">La pantalla que buscas ya no está en la máquina. Rompe unos cuantos ladrillos o vuelve al menú principal.</p>
        <a class="n4-cta" href="/">Volver al menú</a>
      </div>
    </main>
    <script>
      document.querySelectorAll(".n4-arcade").forEach((el) => {
        const cv = el.querySelector(".n4-cv");
        const ctx = cv.getContext("2d");
        const score = el.querySelector(".n4-score");
        const rm = matchMedia("(prefers-reduced-motion: reduce)").matches;
        const k = parseFloat(getComputedStyle(el).getPropertyValue("--k")) || 1;
        const W = 260, H = 160, BW = 18, BH = 8;
        const GLYPH = { "4": ["101", "101", "111", "001", "001"], "0": ["111", "101", "101", "101", "111"] };
        const COLS = ["#ff5d5d", "#ff9f43", "#ffd43b", "#51cf66", "#4dabf7"];
        let bricks = [];
        const build = () => {
          bricks = [];
          let gx = 0;
          for (const ch of "404") {
            GLYPH[ch].forEach((row, y) => row.split("").forEach((b, x) => { if (b === "1") bricks.push({ x: 21 + (gx + x) * 20, y: 16 + y * 10, c: COLS[y], on: true }); }));
            gx += 4;
          }
        };
        let px = W / 2, target = W / 2, manual = 0, pts = 0, raf = 0, last = 0, started = !rm;
        const ball = { x: W / 2, y: H - 30, vx: 1.2, vy: -1.6 };
        const reset = () => { ball.x = px; ball.y = H - 24; ball.vx = (Math.random() < 0.5 ? -1 : 1) * 1.2; ball.vy = -1.6; };
        const step = (f) => {
          const now = performance.now();
          if (now > manual) target = ball.x + Math.sin(now / 700) * 10;
          px += (target - px) * (now > manual ? 0.14 : 0.4);
          px = Math.max(20, Math.min(W - 20, px));
          ball.x += ball.vx * f;
          ball.y += ball.vy * f;
          if (ball.x < 3 || ball.x > W - 3) { ball.vx *= -1; ball.x = Math.max(3, Math.min(W - 3, ball.x)); }
          if (ball.y < 3) ball.vy = Math.abs(ball.vy);
          if (ball.vy > 0 && ball.y > H - 15 && ball.y < H - 6 && Math.abs(ball.x - px) < 23) {
            ball.vy = -Math.abs(ball.vy);
            ball.vx = (ball.x - px) / 12;
            if (Math.abs(ball.vx) < 0.5) ball.vx = ball.vx < 0 ? -0.5 : 0.5;
          }
          if (ball.y > H + 6) reset();
          for (const b of bricks) {
            if (b.on && ball.x > b.x - 2 && ball.x < b.x + BW + 2 && ball.y > b.y - 2 && ball.y < b.y + BH + 2) {
              b.on = false;
              ball.vy *= -1;
              pts += 10;
              score.textContent = String(pts).padStart(3, "0");
              break;
            }
          }
          if (bricks.every((b) => !b.on)) build();
        };
        const draw = () => {
          ctx.fillStyle = "#060b08";
          ctx.fillRect(0, 0, W, H);
          for (const b of bricks) {
            if (!b.on) continue;
            ctx.fillStyle = b.c;
            ctx.fillRect(b.x, b.y, BW, BH);
            ctx.fillStyle = "rgba(255,255,255,.28)";
            ctx.fillRect(b.x, b.y, BW, 2);
          }
          ctx.fillStyle = "#e9f5ec";
          ctx.fillRect(Math.round(px - 20), H - 12, 40, 5);
          ctx.fillRect(Math.round(ball.x - 2), Math.round(ball.y - 2), 4, 4);
        };
        const loop = (t) => {
          const f = last ? Math.min(3, (t - last) / 16.67) * k : 1;
          last = t;
          step(f);
          draw();
          raf = requestAnimationFrame(loop);
        };
        const start = () => { if (!started) { started = true; raf = requestAnimationFrame(loop); } };
        cv.addEventListener("pointermove", (e) => {
          const r = cv.getBoundingClientRect();
          target = ((e.clientX - r.left) / r.width) * W;
          manual = performance.now() + 3000;
        });
        cv.addEventListener("pointerdown", start);
        cv.addEventListener("keydown", (e) => {
          if (e.key !== "ArrowLeft" && e.key !== "ArrowRight") return;
          e.preventDefault();
          target = px + (e.key === "ArrowLeft" ? -26 : 26);
          manual = performance.now() + 3000;
          start();
        });
        build();
        draw();
        if (started) raf = requestAnimationFrame(loop);
      });
    </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

Esta página de error mete un pequeño juego de romper ladrillos en una máquina recreativa con rótulo luminoso, líneas de barrido y pantalla de tubo curvada. Los ladrillos forman un 404 de píxeles en cinco filas de colores, la bola rebota sola y la pala la sigue, así que la página tiene vida aunque nadie la toque.

Si mueves el puntero sobre la pantalla o pulsas las flechas, controlas la pala durante unos segundos. Los puntos se cuentan arriba. El juego corre en un canvas pequeño y con movimiento reducido espera a tu primer gesto.