Buscando emisora…

Frecuencia 100,4 MHz

En esta frecuencia no emite nadie.

La página que buscas se ha quedado sin señal. Gira el dial o vuelve al inicio, que ahí siempre hay programa.

Volver al inicio
HTML + CSS404

404 Radio antigua

Una radio de madera con escala FM, ojo mágico y estática: arrastra el dial y en el 100,4 solo suena el ruido del 404.

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-radio {
        --accent: #ffb347;
        --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-radio *,.n4-radio *::before,.n4-radio *::after {
        box-sizing: border-box;
      }
      
      .n4-radio .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-radio .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-radio .n4-sub {
        margin: 0;
        max-width: 34em;
        font-size: clamp(13px,2.4cqmin,18px);
        color: #a1a1a6;
        text-wrap: balance;
      }
      
      .n4-radio .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-radio .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-radio .n4-cta:hover {
        transform: translateY(-2px);
        box-shadow: 0 12px 32px -10px var(--accent);
      }
      
      .n4-radio .n4-cta:focus-visible {
        outline: 2px solid var(--accent);
        outline-offset: 3px;
      }
      
      .n4-radio .n4-stars,.n4-radio .n4-stars2 {
        position: absolute;
        inset: -4%;
        pointer-events: none;
      }
      
      .n4-radio .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-radio-tw calc(5s / var(--k)) ease-in-out infinite alternate;
      }
      
      .n4-radio .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-radio-tw calc(7s / var(--k)) ease-in-out infinite alternate-reverse;
      }
      
      .n4-radio [data-depth] {
        transition: transform .9s cubic-bezier(.2,.7,.2,1);
      }
      
      @keyframes n4-radio-tw {
        from {
          opacity: .3;
        }
      }
      
      @keyframes n4-radio-spin {
        to {
          transform: rotate(1turn);
        }
      }
      
      @keyframes n4-radio-fade {
        from {
          opacity: 0;
          transform: translateY(10px);
        }
      }
      
      @media (prefers-reduced-motion:reduce) {
        .n4-radio *,.n4-radio *::before,.n4-radio *::after {
          animation: none!important;
          transition: none!important;
        }
      }
      
      .n4-radio {
        background: radial-gradient(70% 60% at 50% 30%,#3d2b1d,#140d08 75%);
        color: #f7ead2;
      }
      
      .n4-radio .n4-set {
        --v: 0;
        --sig: 0;
        --noise: 1;
        width: min(64cqmin,450px);
        font-size: min(2cqmin,14px);
        margin-bottom: 1.6cqmin;
        padding: 1.5em 1.6em 1.1em;
        border-radius: 5em 5em 1.2em 1.2em/3.4em 3.4em 1.2em 1.2em;
        background: repeating-linear-gradient(93deg,rgba(0,0,0,.07) 0 .25em,transparent .25em .9em,rgba(255,220,180,.04) .9em 1.2em,transparent 1.2em 2em),linear-gradient(160deg,#8f4f25,#5a2d12 60%,#3b1d0a);
        box-shadow: inset 0 .25em .3em rgba(255,255,255,.2),inset 0 -.5em .8em rgba(0,0,0,.45),0 2em 3em -1.4em #000;
      }
      
      .n4-radio .n4-top {
        display: flex;
        gap: 1.2em;
        height: 8.5em;
      }
      
      .n4-radio .n4-grille {
        position: relative;
        flex: 1;
        overflow: hidden;
        border-radius: 2.6em 2.6em .6em .6em;
        background: repeating-linear-gradient(90deg,transparent 0 1.6em,#4a240d 1.6em 2em),repeating-linear-gradient(45deg,rgba(0,0,0,.2) 0 1px,transparent 1px 3px),repeating-linear-gradient(-45deg,rgba(0,0,0,.2) 0 1px,transparent 1px 3px),#cdb68a;
        box-shadow: inset 0 0 0 .3em #3b1d0a,inset 0 0 1.4em rgba(0,0,0,.5);
      }
      
      .n4-radio .n4-on .n4-grille {
        animation: n4-radio-thump calc(.45s / var(--k)) ease-in-out infinite alternate;
      }
      
      .n4-radio .n4-static {
        position: absolute;
        inset: -10px;
        opacity: var(--noise);
        background: repeating-radial-gradient(circle at 27% 38%,rgba(255,255,255,.55) 0 1px,transparent 1px 3px),repeating-radial-gradient(circle at 71% 63%,rgba(0,0,0,.45) 0 1px,transparent 1px 4px);
        animation: n4-radio-noise calc(.18s / var(--k)) steps(3) infinite;
      }
      
      .n4-radio .n4-side {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: space-between;
        width: 5.4em;
      }
      
      .n4-radio .n4-eye {
        width: 3.6em;
        height: 3.6em;
        border-radius: 50%;
        background: radial-gradient(circle,#0b1a10 0 22%,transparent 23%),conic-gradient(from calc(180deg - var(--uvq17-w)),#0b1a10 0 calc(var(--uvq17-w) * 2),#6dff8a 0);
        --uvq17-w: calc((1 - var(--sig)) * 70deg + 4deg);
        box-shadow: 0 0 0 .35em #2a160a,0 0 0 .5em #b78a4a,0 0 1.2em rgba(109,255,138,calc(var(--sig) * .7));
        transition: --uvq17-w .2s;
      }
      
      .n4-radio .n4-knob {
        width: 2.6em;
        height: 2.6em;
        border-radius: 50%;
        background: repeating-conic-gradient(#e9d8b4 0 8deg,#b99b66 8deg 16deg);
        box-shadow: inset 0 0 0 .5em #f3e6c8,0 .2em .3em rgba(0,0,0,.5);
        rotate: calc(var(--v) * 3.6deg);
      }
      
      .n4-radio .n4-k2 {
        rotate: calc(var(--v) * -1.2deg);
      }
      
      .n4-radio .n4-scale {
        position: relative;
        height: 3.2em;
        margin-top: 1.1em;
        border-radius: .5em;
        cursor: ew-resize;
        touch-action: none;
        background: linear-gradient(#f6e7bf,#e2c98d);
        box-shadow: inset 0 0 0 .2em #3b1d0a,inset 0 0 1.6em rgba(255,170,60,.55);
      }
      
      .n4-radio .n4-scale:focus-visible {
        outline: 2px solid var(--accent);
        outline-offset: 3px;
      }
      
      .n4-radio .n4-track {
        position: absolute;
        inset: 0 6%;
        background: repeating-linear-gradient(90deg,#3b1d0a 0 1px,transparent 1px 2%) 0 100%/100% 28% no-repeat;
      }
      
      .n4-radio .n4-nums b {
        position: absolute;
        top: .35em;
        left: calc(var(--p) * 1%);
        translate: -50% 0;
        font: 700 .95em/1 ui-monospace,"SF Mono",Menlo,Consolas,monospace;
        color: #3b1d0a;
      }
      
      .n4-radio .n4-needle {
        position: absolute;
        top: .25em;
        bottom: .25em;
        left: calc(var(--v) * 1%);
        width: .2em;
        margin-left: -.1em;
        border-radius: .1em;
        background: #d7261e;
        box-shadow: 0 0 .4em rgba(215,38,30,.6);
      }
      
      .n4-radio .n4-station {
        min-height: 1.3em;
        margin: .7em 0 0;
        font: 600 1em/1.3 ui-monospace,"SF Mono",Menlo,Consolas,monospace;
        letter-spacing: .04em;
        color: #f6e7bf;
      }
      
      .n4-radio .n4-tag {
        color: var(--accent);
      }
      
      .n4-radio .n4-title {
        font-size: clamp(20px,5cqmin,42px);
        font-weight: 700;
        letter-spacing: -.025em;
      }
      
      .n4-radio .n4-sub {
        color: #cdb79b;
      }
      
      .n4-radio .n4-cta {
        background: var(--accent);
        color: #2a1406;
      }
      
      @property --uvq17-w {
        syntax: "<angle>";
        inherits: true;
        initial-value: 74deg;
      }
      
      @keyframes n4-radio-noise {
        33% {
          background-position: 3px 1px,-2px 3px;
        }
        66% {
          background-position: -1px -3px,2px -1px;
        }
      }
      
      @keyframes n4-radio-thump {
        to {
          transform: scale(1.012);
        }
      }
    </style>
  </head>
  <body>
    <main class="n4-radio">
      <div class="n4-copy">
        <div class="n4-set">
          <div class="n4-top" aria-hidden="true">
            <div class="n4-grille"><i class="n4-static"></i></div>
            <div class="n4-side"><i class="n4-eye"></i><i class="n4-knob"></i><i class="n4-knob n4-k2"></i></div>
          </div>
          <div class="n4-scale" role="slider" tabindex="0" aria-label="Dial de sintonía" aria-valuemin="880" aria-valuemax="1080" aria-valuenow="880" aria-valuetext="88,0 MHz">
            <div class="n4-track"><span class="n4-nums" aria-hidden="true" translate="no"><b style="--p:0">88</b><b style="--p:20">92</b><b style="--p:40">96</b><b style="--p:60">100</b><b style="--p:80">104</b><b style="--p:100">108</b></span><i class="n4-needle" aria-hidden="true"></i></div>
          </div>
          <p class="n4-station" aria-live="polite">Buscando emisora…</p>
        </div>
        <span class="n4-tag">Frecuencia 100,4 MHz</span>
        <h1 class="n4-title">En esta frecuencia no emite nadie.</h1>
        <p class="n4-sub">La página que buscas se ha quedado sin señal. Gira el dial o vuelve al inicio, que ahí siempre hay programa.</p>
        <a class="n4-cta" href="/">Volver al inicio</a>
      </div>
    </main>
    <script>
      document.querySelectorAll(".n4-radio").forEach((el) => {
        const set = el.querySelector(".n4-set");
        const scale = el.querySelector(".n4-scale");
        const track = el.querySelector(".n4-track");
        const label = el.querySelector(".n4-station");
        const rm = matchMedia("(prefers-reduced-motion: reduce)").matches;
        const k = parseFloat(getComputedStyle(el).getPropertyValue("--k")) || 1;
        const ST = [[914, "Onda Jazz"], [965, "Noticias 24 horas"], [1004, "404 FM: emisión no encontrada"], [1052, "Boleros de madrugada"]];
        const SEARCH = "Buscando emisora…";
        let v = 880, shown = SEARCH, raf = 0;
        const render = () => {
          let best = 0, name = SEARCH, lost = false;
          for (const [f, n] of ST) {
            const s = Math.max(0, 1 - Math.abs(v - f) / 10);
            if (s > best) { best = s; if (s > 0.55) { name = n; lost = f === 1004; } }
          }
          set.style.setProperty("--v", ((v - 880) / 2).toFixed(2));
          set.style.setProperty("--sig", best.toFixed(2));
          set.style.setProperty("--noise", (lost ? 0.75 : 1 - best * 0.9).toFixed(2));
          set.classList.toggle("n4-on", best > 0.55 && !lost);
          scale.setAttribute("aria-valuenow", String(v));
          scale.setAttribute("aria-valuetext", (v / 10).toFixed(1).replace(".", ",") + " MHz");
          if (name !== shown) { shown = name; label.textContent = name; }
        };
        const tune = (n) => { cancelAnimationFrame(raf); v = Math.max(880, Math.min(1080, Math.round(n))); render(); };
        const fromX = (e) => { const r = track.getBoundingClientRect(); tune(880 + ((e.clientX - r.left) / r.width) * 200); };
        let down = false;
        scale.addEventListener("pointerdown", (e) => { down = true; scale.setPointerCapture(e.pointerId); fromX(e); });
        scale.addEventListener("pointermove", (e) => { if (down) fromX(e); });
        scale.addEventListener("pointerup", () => { down = false; });
        scale.addEventListener("pointercancel", () => { down = false; });
        scale.addEventListener("keydown", (e) => {
          const d = { ArrowRight: 1, ArrowUp: 1, ArrowLeft: -1, ArrowDown: -1, PageUp: 10, PageDown: -10 }[e.key];
          if (d) { e.preventDefault(); tune(v + d); }
          else if (e.key === "Home") { e.preventDefault(); tune(880); }
          else if (e.key === "End") { e.preventDefault(); tune(1080); }
        });
        const t0 = performance.now();
        const sweep = (t) => {
          const p = Math.min(1, (t - t0) / (2400 / k));
          v = Math.round(880 + 124 * (1 - Math.pow(1 - p, 3)));
          render();
          if (p < 1) raf = requestAnimationFrame(sweep);
        };
        if (rm) { v = 1004; render(); } else raf = requestAnimationFrame(sweep);
      });
    </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 es una radio de sobremesa de nogal con rejilla de tela, ojo mágico verde para sintonizar y una escala FM iluminada. Al cargar, la aguja roja recorre la banda; arrastra la escala o usa las flechas para sintonizar, y el ojo se abre al acercarte a una emisora mientras la estática se apaga.

Casi todas las emisoras suenan y la rejilla late un poco, pero 404 FM, en el 100,4, tiene señal perfecta y nada en antena. La escala es un control deslizante accesible que anuncia la frecuencia. Ajusta el ámbar y la velocidad.