/* ==========================================================================
   Papelito · la impresión
   La ranura está medida sobre el render, no estimada:
   y = 57.7% del alto, x = 21.3%..76.4% del ancho.
   ========================================================================== */

.printer {
  --ranura-y: 57.7%;
  --ranura-x: 21.3%;
  --ranura-w: 55.1%;
  position: relative;
  display: flex;
  justify-content: center;
  /* El ancho es explícito y Papelito lo llena — NO al revés.
     Con `width: max-content` el ancho de la impresora dependía del de Papelito;
     al animar el ancho de Papelito, Chrome recalculaba el contenedor, el
     contenedor volvía a afectar al hijo, y la transición se reiniciaba en cada
     recálculo: quedaba en currentTime 0 para siempre y el ancho se congelaba.
     Los porcentajes de la ranura resuelven contra esta caja. */
  width: 100%;
}

/* --- La ventana de la ranura ---------------------------------------------
   El papel vive DELANTE de la impresora (así se ve en el mockup, apoyado sobre
   la mitad inferior) y se recorta contra esta ventana, cuyo borde superior es
   exactamente la línea de la ranura. Sin el overflow, el ticket aparecería
   flotando en vez de salir de adentro. */
.printer__slot {
  position: absolute;
  left: var(--ranura-x);
  top: var(--ranura-y);
  width: var(--ranura-w);
  overflow: hidden;
  z-index: 2;
  pointer-events: none;
}

/* El papel tiene el ancho de maqueta del ticket de la columna y se DIBUJA más
   chico con un scale, en vez de maquetarse angosto. Así los saltos de línea, la
   tipografía y los espaciados son los mismos que va a tener en la columna, y al
   crecer durante el vuelo no se recompone nada.
   `transform-origin: top left` hace que el borde izquierdo del papel coincida
   con el de la boca, y la escala la publica el JS para que el ancho dibujado dé
   exactamente el de la ranura. */
.printer__paper {
  width: var(--ticket-w);
  transform-origin: top left;
  transform: scale(var(--ticket-escala, 1)) translateY(-101%);
  filter: drop-shadow(0 6px 10px rgba(139, 30, 65, 0.16));
}

/* La salida: primero un tirón corto, después el avance parejo del rodillo.
   Una sola curva suave se siente motorizada de más.
   El `scale` va PRIMERO para que el translate en porcentaje también se escale:
   así -101% equivale al alto ya dibujado y el papel queda justo fuera de vista. */
.printer__paper--out {
  animation: papel-sale 1500ms cubic-bezier(0.32, 0.08, 0.24, 1) forwards;
}

@keyframes papel-sale {
  0%   { transform: scale(var(--ticket-escala, 1)) translateY(-101%) rotateX(14deg); }
  14%  { transform: scale(var(--ticket-escala, 1)) translateY(-88%)  rotateX(11deg); }
  100% { transform: scale(var(--ticket-escala, 1)) translateY(0)     rotateX(0deg);  }
}

/* --- El temblorcito del rodillo mientras imprime -------------------------- */
.printer--imprimiendo .papelito {
  animation: papelito-imprime 150ms linear 10;
}

@keyframes papelito-imprime {
  0%, 100% { transform: translate(0, 0); }
  25%      { transform: translate(-1px, 0.5px); }
  75%      { transform: translate(1px, -0.5px); }
}

/* La vista 3/4 tiene la ranura en otro lado. Medido igual que la frontal:
   y = 58.1% del alto, x = 21.4%..72.2% del ancho. */
.printer--side {
  --ranura-y: 58.1%;
  --ranura-x: 21.4%;
  --ranura-w: 50.8%;
}

/* --- Despegue -------------------------------------------------------------
   Se va la impresora entera con el papel adentro, no sólo el personaje.
   Se agacha antes de saltar: sin ese anticipo, el despegue se lee como un corte
   y no como una decisión de Papelito. */
.printer--despega {
  animation: printer-despega 900ms cubic-bezier(0.5, -0.28, 0.74, 0.05) forwards;
}

@keyframes printer-despega {
  0%   { transform: translateY(0)      scale(1);    }
  18%  { transform: translateY(26px)   scale(0.96); }
  100% { transform: translateY(-125vh) scale(1.04); }
}

/* --- Confeti -------------------------------------------------------------
   Detrás de todo: en el mockup dice "confeti de fondo". */
.confeti {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}

/* --- Mensaje de éxito ----------------------------------------------------
   Ocupa el lugar que deja el input al colapsar: la composición no salta. */
/* El padding va en el último hijo, no en el hijo directo del colapsable —
   si no, el bloque no puede llegar a altura cero. Ver intro.css. */
.exito { text-align: center; }
.exito__sub { padding-bottom: var(--s7); }

.exito__titulo {
  font-size: clamp(24px, 3.2vw, 38px);
  font-weight: var(--w-title);
  letter-spacing: var(--title-tracking);
  color: var(--plum);
}
.exito__titulo em { font-style: normal; color: var(--pink); }

.exito__sub {
  margin-top: var(--s2);
  font-size: 15px;
  color: var(--ink-mute);
}

.exito--entra .exito__titulo { animation: exito-pop 620ms var(--ease-pop) both; }
.exito--entra .exito__sub    { animation: exito-pop 620ms var(--ease-pop) 140ms both; }

@keyframes exito-pop {
  from { opacity: 0; transform: translateY(10px) scale(0.94); }
  to   { opacity: 1; transform: none; }
}

/* El .intro tiene que crear contexto de apilado para que el canvas quede
   detrás del contenido pero delante del degradé. */
.intro__stage { position: relative; z-index: 1; }
