aeworks.tech/lab/cursor-linterna
← AE Lab

La web a oscuras con linterna

21 oct 2026· nivel mediolinternaradial-gradientlanding

Una página de lanzamiento totalmente a oscuras donde el ratón (o el dedo) es una linterna con polvo en el aire y borde cálido. Al encontrar las 3 pistas escondidas, la luz se abre en círculo y aparece todo, con el botón «Avísame».

// CÓMO ESTÁ HECHO

  1. El contenido está siempre pintado; encima va un cuadrado enorme con un radial-gradient que deja un agujero transparente en el centro: esa es la oscuridad.
  2. En cada requestAnimationFrame la linterna se acerca al puntero con inercia (1 - e^-9·dt) y la oscuridad solo se mueve con transform: translate3d, sin repintar el layout.
  3. Cada pista mide su distancia a la luz: su opacidad sube al acercarse y, si la alumbras un instante, cuenta como hallada.
  4. Con 3 pistas, la capa oscura se escala hasta cubrir la diagonal y se desvanece mientras una onda cálida se expande: el revelado en círculo.
  5. Un canvas pinta motas de polvo solo dentro del haz, y un modo demostración pasea la linterna por las pistas hasta que alguien toca.

// EL CÓDIGO

<!-- 1 · Lo que hay en la habitación (siempre está ahí, la oscuridad lo tapa) -->
<main class="escena" aria-label="Lanzamiento del perfume Lumbre">
  <header class="titulo">
    <small>Casa Ámbar presenta</small>
    <h1>LUMBRE</h1>
    <p>Un perfume que solo se descubre a oscuras.</p>
  </header>

  <div class="frasco" aria-hidden="true">
    <svg viewBox="0 0 200 320">
      <defs>
        <linearGradient id="cristal" x1="0" x2="1">
          <stop offset="0" stop-color="#3b2410"/><stop offset=".45" stop-color="#d98a32"/>
          <stop offset=".6" stop-color="#ffc677"/><stop offset="1" stop-color="#5a3412"/>
        </linearGradient>
        <linearGradient id="tapon" x1="0" x2="1">
          <stop offset="0" stop-color="#2a2016"/><stop offset=".5" stop-color="#8a6a44"/><stop offset="1" stop-color="#1c150e"/>
        </linearGradient>
        <radialGradient id="brillo" cx=".5" cy=".55" r=".5">
          <stop offset="0" stop-color="#ffb45c" stop-opacity=".55"/><stop offset="1" stop-color="#ffb45c" stop-opacity="0"/>
        </radialGradient>
      </defs>
      <ellipse cx="100" cy="200" rx="120" ry="130" fill="url(#brillo)"/>
      <rect x="70" y="18" width="60" height="54" rx="8" fill="url(#tapon)"/>
      <rect x="84" y="72" width="32" height="22" fill="#6b4a26"/>
      <path d="M40 120 Q40 94 70 94 H130 Q160 94 160 120 V282 Q160 304 136 304 H64 Q40 304 40 282 Z" fill="url(#cristal)" stroke="#ffe2b0" stroke-opacity=".35"/>
      <path d="M52 128 Q52 108 70 106 V290 Q52 288 52 276 Z" fill="#fff" opacity=".22"/>
      <rect x="58" y="176" width="84" height="64" rx="4" fill="#120c06" opacity=".82"/>
      <text x="100" y="206" fill="#ffe2b0" font-family="ui-monospace, monospace" font-size="15" font-weight="800" text-anchor="middle" letter-spacing="2">LUMBRE</text>
      <text x="100" y="226" fill="#ffb45c" font-family="ui-monospace, monospace" font-size="9" text-anchor="middle" letter-spacing="1">Nº21 · 50 ML</text>
    </svg>
  </div>

  <button class="pista" data-n="1" type="button">
    <span class="tinta"><em>1 · El olor</em><strong>Higo negro, cedro y una chispa de pimienta.</strong></span>
  </button>
  <button class="pista" data-n="2" type="button">
    <span class="tinta"><em>2 · La fecha</em><strong>Se enciende el 21·10·2026 a las 21:00.</strong></span>
  </button>
  <button class="pista" data-n="3" type="button">
    <span class="tinta"><em>3 · El secreto</em><strong><span class="codigo">LUMBRE15</span>−15 % para quien llegue primero.</strong></span>
  </button>
</main>

<!-- 2 · La linterna: oscuridad con agujero, borde cálido, onda del revelado y polvo -->
<div class="oscuridad" aria-hidden="true"></div>
<div class="halo" aria-hidden="true"></div>
<div class="onda" aria-hidden="true"></div>
<canvas id="polvo" aria-hidden="true"></canvas>

<!-- 3 · Interfaz siempre visible -->
<div class="barra">
  <span class="marca"><b>Casa Ámbar</b> · próximamente</span>
  <span class="contador" aria-hidden="true">Pistas <i class="punto"></i><i class="punto"></i><i class="punto"></i></span>
</div>
<div class="mando">
  <p class="pistaTexto" aria-live="polite">Mueve el ratón: es una linterna. Hay 3 pistas escondidas.</p>
  <div class="botones">
    <button class="btn principal" id="avisame" type="button" hidden>Avísame</button>
    <button class="btn" id="encender" type="button">Encender la luz</button>
    <button class="btn" id="apagar" type="button" hidden>Apagar otra vez</button>
  </div>
</div>