🎄✨ Mi Contador Regresivo para las Vacaciones… con Nieve, Emojis y Mucha Magia Digital ✨🎄

(Un experimento entre código, navidad y un poquito de IA)

Hay proyectos que nacen porque “se necesitan”… y hay otros que nacen porque ya urge sentir vacaciones, porque ya estamos marcando los días con rayitas en la pared y porque ver caer nieve (aunque sea digital) nos sube el ánimo con la ilusión de un chocolate caliente imaginario.

Así nació este pequeño experimento:
🎉 un contador regresivo animado,
❄️ con nieve de verdad (bueno, de CSS),
🎄 emojis que brotan cuando pasas el dedo,
📱 y una experiencia que funciona perfecto en móvil.

Y sí: lo hice con HTML, CSS, JS… y una ayudadita estratégica de IA.
Porque si la tecnología está para jugar, se juega.

❄️ ¿Qué es este contador y por qué está tan divertido?

Es un contador regresivo que te dice cuántos días, horas, minutos y segundos faltan para las vacaciones.
Hasta ahí normal…

Pero:

✨ Tiene un fondo invernal con copos de nieve cayendo suavemente.
✨ Cuando mueves el mouse o pasas el dedo, brotan emojis navideños como si estuvieras lanzando magia.
✨ Funciona perfecto en celular, porque el contenedor se hace más pequeño y te deja jugar más con el efecto.
✨ No usa librerías externas. Todo es HTML, CSS y JS puro.
✨ Y sí, me apoyé en IA para pulir animaciones y hacerlo más interactivo.

Es un proyecto simple pero con vibes de mini-juego navideño.
Los alumnos lo aman, mis amigos lo quieren en sus páginas, y yo… bueno, yo ya ingreso diario a ver cuánta nieve cae.


🎯 HTML: la estructura del show

El HTML es casi minimalista: un contenedor visible (para mostrar el tiempo) y un contenedor invisible que sirve de escenario para la nieve y los emojis.

HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cuenta Regresiva para Vacaciones</title>
    <!-- Vinculando el archivo CSS -->
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container">
        <h1>🌴 ¡Cuenta regresiva para las vacaciones! 🎉</h1>
        <p id="days">Cargando...</p>
    </div>

    <!-- Fondo con emojis -->
    <div id="emoji-container"></div>

    <!-- Vinculando el archivo JS -->
    <script src="script.js"></script>
</body>
</html>

🎨 CSS: donde ocurre la magia visual

El CSS es la parte que da vida al proyecto:

🌫️ un degradado azul estilo “cielo frío”
🌨️ animación de los copos de nieve cayendo
🎉 animación de los emojis que explotan y se desvanecen
📱 reglas responsivas para que en móvil todo se vea tierno y compacto

SCSS
/* Importar la fuente personalizada */
@font-face {
  font-family: "Last";
  src: url("last.otf") format("opentype");
}

/* Estilos generales */
body {
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  /* Cielo invernal en degradado */
  background: linear-gradient(to bottom, #4a90e2, #87ceeb);
  overflow: hidden;
}

/* Contenedor principal */
.container {
  text-align: center;
  background: rgba(255, 255, 255, 0.95);
  padding: 40px 50px;
  border-radius: 24px;
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.25);
  z-index: 1;
  position: relative;
}

/* Título */
.container h1 {
  font-family: "Last", "Comic Sans MS", cursive, sans-serif;
  font-size: 2.6rem;
  color: #ff4500; /* Naranja vibrante */
  margin-bottom: 20px;
}

/* Días restantes */
#days {
  font-size: 2.2rem;
  font-weight: bold;
  color: #2e8b57; /* Verde bosque */
}

/* Fondo para nieve y emojis de trail */
#emoji-container {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
}

/* Copos de nieve que caen */
.snowflake {
  position: absolute;
  top: -10vh;
  animation-name: snow-fall;
  animation-timing-function: linear;
  animation-iteration-count: 1;
  opacity: 0.9;
  filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.9));
}

@keyframes snow-fall {
  0% {
    transform: translateY(-10vh) translateX(0);
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  100% {
    transform: translateY(110vh) translateX(10vw);
    opacity: 0;
  }
}

/* Emojis que brotan al pasar el dedo */
.emoji-trail {
  position: absolute;
  transform: translate(-50%, -50%);
  opacity: 0;
  animation: emoji-pop 1.8s ease-out forwards;
  pointer-events: none;
}


@keyframes emoji-pop {
  0% {
    transform: translate(-50%, -50%) scale(0.2);
    opacity: 0;
  }
  40% {
    transform: translate(-50%, -70%) scale(1);
    opacity: 1;
  }
  100% {
    transform: translate(-50%, -90%) scale(0.6);
    opacity: 0;
  }
}

/* ==============================
   AJUSTES PARA MÓVIL
   ============================== */
@media (max-width: 768px) {
  .container {
    width: 80%;
    padding: 20px 25px;
    border-radius: 16px;
    transform: scale(0.85); /* La hace más pequeña */
  }

  .container h1 {
    font-size: 1.8rem;
  }

  #days {
    font-size: 1.5rem;
    font-family: Verdana, Geneva, Tahoma, sans-serif;
  }

  body {
    padding-top: 30px;
  }
}

/* Para móviles MUY pequeños */
@media (max-width: 430px) {
  .container {
    width: 75%;
    padding: 18px 20px;
    transform: scale(0.75); /* aún más chica */
  }

  .container h1 {
    font-size: 1.4rem;
  }

  #days {
    font-size: 1.2rem;
  }
}

⚙️ JavaScript: el cerebro del contador

El JS controla tres cosas:

1️⃣ El contador regresivo

Cada segundo calcula la diferencia entre ahora y una fecha objetivo (en mi caso, 19 de diciembre a las 3:00 p.m.):

JavaScript
countdownElement.textContent =
  `Faltan ${days}d ${hours}h ${minutes}m ${seconds}s para las vacaciones 🎉`;

2️⃣ La nieve animada

Cada 250 ms se crea un copo ❄️ con posición, tamaño y velocidad aleatoria:

JavaScript
setInterval(createSnowflake, 250);

3️⃣ Los emojis que aparecen cuando pasas el dedo o mouse

Aquí viene lo divertido: se detecta tu movimiento y se generan pequeños “estallidos” de emojis.

JavaScript
document.addEventListener("pointermove", handlePointerMove, { passive: true });

Y sí, funcionan perfectamente en celular, que es donde este efecto se siente más juguetón.

Cada estallido genera varios emojis aleatoriamente que flotan y se desvanecen, como si activaras un hechizo navideño cada vez que tocas la pantalla.

JavaScript
// =========================
//  COUNTDOWN A VACACIONES
// =========================

// Función para calcular el tiempo restante hasta una fecha y hora específicas
function calculateTimeUntil(targetDateTime) {
  const now = new Date();
  const target = new Date(targetDateTime);
  const timeDiff = target - now;
  return timeDiff;
}

// Actualizar el contador en pantalla
function updateCountdown() {
  // Fecha objetivo: 19 de diciembre a las 3:00 p.m.
  const targetDateTime = new Date("2025-12-19T15:00:00");

  const countdownElement = document.getElementById("days");
  const timeLeft = calculateTimeUntil(targetDateTime);

  if (timeLeft > 0) {
    const days = Math.floor(timeLeft / (1000 * 60 * 60 * 24));
    const hours = Math.floor(
      (timeLeft % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
    );
    const minutes = Math.floor(
      (timeLeft % (1000 * 60 * 60)) / (1000 * 60)
    );
    const seconds = Math.floor((timeLeft % (1000 * 60)) / 1000);

    countdownElement.textContent =
      `Faltan ${days}d ${hours}h ${minutes}m ${seconds}s para las vacaciones 🎉`;
  } else {
    countdownElement.textContent =
      "¡Las vacaciones ya comenzaron! 🌴☀️🏖️";
  }
}

// =========================
//  NIEVE (SOLO COPOS ❄️)
// =========================

function createSnowflake() {
  const emojiContainer = document.getElementById("emoji-container");
  if (!emojiContainer) return;

  const snowflake = document.createElement("div");
  snowflake.textContent = "❄️";
  snowflake.classList.add("snowflake");

  // Posición aleatoria horizontal
  snowflake.style.left = Math.random() * 100 + "vw";

  // Duración de la caída (un poco aleatoria)
  const duration = Math.random() * 5 + 5; // 5s a 10s
  snowflake.style.animationDuration = duration + "s";

  // Tamaño aleatorio
  const size = Math.random() * 1.3 + 1; // 1rem - 2.3rem aprox
  snowflake.style.fontSize = size + "rem";

  emojiContainer.appendChild(snowflake);

  setTimeout(() => {
    snowflake.remove();
  }, duration * 1000 + 500);
}

function startSnow() {
  // Nieva suavecito
  setInterval(createSnowflake, 250);
}

// =========================
//  EMOJIS AL PASAR EL DEDO
// =========================

const trailEmojis = [
  "🎄", "🎅", "🤶", "🦌", "☃️", "⛄", "🎁",
  "🌟", "🕯️", "🧤", "🧣", "🍪", "☕", "🍫", "🎀"
];

let lastEmojiTime = 0;

// Crea un solo emoji en la posición indicada
function createTrailEmoji(x, y) {
  const emojiContainer = document.getElementById("emoji-container");
  if (!emojiContainer) return;

  const emoji = document.createElement("div");
  emoji.textContent =
    trailEmojis[Math.floor(Math.random() * trailEmojis.length)];
  emoji.classList.add("emoji-trail");

  // Posición absoluta según el dedo / mouse
  emoji.style.left = x + "px";
  emoji.style.top = y + "px";

  // Tamaño aleatorio para que se vea más vivo
  const size = Math.random() * 0.8 + 1.2; // 1.2rem - 2rem
  emoji.style.fontSize = size + "rem";

  emojiContainer.appendChild(emoji);

  // Se quedan más tiempo en pantalla
  setTimeout(() => {
    emoji.remove();
  }, 3500);
}

// CREA VARIOS EMOJIS CERCA DEL PUNTO
function spawnEmojiBurst(x, y) {
  const count = 4 + Math.floor(Math.random() * 3); // entre 4 y 6 emojis

  for (let i = 0; i < count; i++) {
    const offsetX = (Math.random() - 0.5) * 60; // -30px a +30px
    const offsetY = (Math.random() - 0.5) * 60;

    createTrailEmoji(x + offsetX, y + offsetY);
  }
}

// Maneja el movimiento del mouse / dedo con throttle
function handlePointerMove(e) {
  const now = Date.now();
  // Más frecuente para que salgan más emojis
  if (now - lastEmojiTime < 30) return;
  lastEmojiTime = now;

  let x, y;

  if (e.touches && e.touches.length > 0) {
    x = e.touches[0].clientX;
    y = e.touches[0].clientY;
  } else {
    x = e.clientX;
    y = e.clientY;
  }

  if (x == null || y == null) return;

  spawnEmojiBurst(x, y);
}

// =========================
//  INICIO
// =========================

document.addEventListener("DOMContentLoaded", () => {
  // Inicia el contador
  updateCountdown();
  setInterval(updateCountdown, 1000);

  // Inicia la nieve
  startSnow();

  // Para mouse / pointer
  document.addEventListener("pointermove", handlePointerMove, {
    passive: true,
  });

  // Fallback por si algún navegador usa solo touchmove
  document.addEventListener("touchmove", handlePointerMove, {
    passive: true,
  });
});

🤖 ¿Y la IA en todo esto?

Yo escribí la mayor parte del código y la estructura, pero le pedí a la IA que:

✔ me sugiriera animaciones más suaves
✔ ajustara tiempos y movimientos para hacerlo más mágico
✔ me ayudara con la parte responsiva
✔ aportara ideas para el efecto de estallido de emojis

Fue un muy buen experimento:
yo puse la idea, la lógica y el diseño…
la IA aportó finesse ✨.

🎁 PROMPT: así puedes pedirle a otra IA que te genere algo similar

Quiero que me generes una mini aplicación web navideña con HTML, CSS y JavaScript.  
Debe tener un contador regresivo a una fecha específica, un fondo con nieve animada
(copos ❄️), y un efecto donde al mover el mouse o el dedo aparezcan emojis navideños
en pequeños estallidos con animación.
La app debe ser responsiva, con un contenedor central más pequeño en móvil, estilo
navideño agradable y animaciones suaves.
No uses librerías externas.
Explica el código paso a paso.