/* Portado de la maqueta ac-mezcla (paleta menta) una sola vez (78bbddd); desde entonces se edita aquí. */
/* El movimiento de la página, en un solo sitio. Cada cosa que se mueve dice algo:
   1. La portada, una vez al cargar (explicación, 2,5 s como mucho): se pone la mesa, el blíster se posa, la tapa se
      abre como una concha hacia la derecha y se retira (nunca se queda encima de la mesa), la pegatina del precio se
      pega y, en la lista de la clase, dos familias eligen merienda (5). Después, quieto. Lo que se ve sin animación es el
      estado final: el blíster abierto, sin tapa.
   2. «Se recoge sola», atada al desplazamiento: el mantel se recoge hasta la bola y queda la mesa desnuda.
   4. Ampliar la invitación: la pantalla del móvil crece hasta la ventana (View Transition con nombre).
   5. La lista se llena: dos familias eligen y su pegatina «Elegida» aterriza en el hueco, una vez.
   6. Cambiar de mundo: servilleta, móvil y tarjeta se funden juntos al nuevo (View Transition de tres piezas).
   Los estados (pulsar, encima, foco, abrir una pregunta) viven con cada pieza. Lo que se hace con el teclado no se
   anima (7). Con «reducir movimiento», nada se desplaza: queda el estado final, o un fundido de opacidad donde el
   cambio hay que verlo. Nada se repite ni dura más de 5 s. */

/* ---------- 1. La portada ---------- */
/* La tapa gira 180° sobre su canto derecho (3D flip, 820 ms con ease-in-out: se mueve por la pantalla) y, ya abierta,
   se funde en 340 ms con ease-out. En reposo tiene opacidad 0 (portada.css): sin movimiento, el blíster ya está
   abierto. --tapa-x/-y/-giro: adónde cae al abrirse, un poco a la derecha y girada, como al soltarla. */
.listachan .tapa { --tapa-x: 40px; --tapa-y: 0px; --tapa-giro: 0deg; }
@media (min-width: 1100px) {
  .listachan .tapa { --tapa-x: 24px; --tapa-y: 18px; --tapa-giro: 3deg; }
}

@media (prefers-reduced-motion: no-preference) {
  .listachan .mesa-foto { transform-origin: 50% 0; animation: poner-mesa 760ms var(--ease-out) both; }
  .listachan .blister { animation: posar 640ms var(--ease-out) 120ms both; }
  .listachan .tapa { animation: abrir-tapa 1160ms var(--ease-in-out) 700ms both; }
  .listachan .pegatina-precio--portada { animation: pegar 380ms var(--ease-out) 1440ms both; }   /* se aprieta y se queda: sin rebote */
  .listachan .movil--portada .movil-chapa { animation: asomar 260ms var(--ease-out) 1700ms both; }
}
@keyframes poner-mesa {
  from { opacity: 0; scale: 1.03; }
}
@keyframes posar {
  from { opacity: 0; translate: 0 -22px; scale: 1.03; rotate: -2.8deg; }
}
@keyframes abrir-tapa {
  0% { opacity: 1; transform: perspective(1400px) translate(0px, 0px) rotate(0deg) rotateY(0deg); }
  70.7% {
    opacity: 1; transform: perspective(1400px) translate(var(--tapa-x), var(--tapa-y)) rotate(var(--tapa-giro)) rotateY(180deg);
    animation-timing-function: var(--ease-out);
  }
  100% { opacity: 0; transform: perspective(1400px) translate(var(--tapa-x), var(--tapa-y)) rotate(var(--tapa-giro)) rotateY(180deg); }
}
@keyframes pegar {
  from { opacity: 0; scale: 1.4; rotate: -26deg; }
}
@keyframes asomar {
  from { opacity: 0; translate: 0 6px; }
}

/* ---------- 2. Se recoge sola ---------- */
/* Reposo (sin movimiento o sin JS): la mesa desnuda con la bola. Con línea de tiempo de desplazamiento, el radio del
   vichy que queda visible va de 2400 px a 0 mientras la sección entra. Sin ella, recoger.js pone .recoge--puesta al
   cargar y la quita una vez cuando la sección se ve, a la vez que pone .recoge--viva: la transición hace lo mismo en
   1,3 s. Solo hay transición con .recoge--viva, para que poner el mantel al cargar no lo destape al revés, oculto,
   durante la intro (revisión de movimiento). El recorrido es el de la
   maqueta en px a 844 px de alto y más; en una ventana más baja se encoge en proporción (los svh son esos px / 8,44),
   para que el mantel acabe de recogerse con la bola aún a la vista (revisión 8904: con 390 px de alto acababa con ella
   ya fuera de la pantalla). */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .listachan .recoge-mesa { animation: recoger linear both; animation-timeline: --recoge; animation-range: cover min(140px, 16.59svh) cover min(760px, 90.05svh); }
    .listachan .bola { animation: hacer-bola linear both; animation-timeline: --recoge; animation-range: cover min(360px, 42.65svh) cover min(780px, 92.42svh); }
  }
}
@keyframes recoger {
  from { --radio: 2400px; }
  to { --radio: 0px; }
}
@keyframes hacer-bola {
  from { opacity: 0; scale: .55; rotate: -30deg; }
}
@media (prefers-reduced-motion: no-preference) {
  .listachan .recoge--viva .recoge-mesa { transition: --radio 1300ms var(--ease-in-out); }
  .listachan .recoge--viva .bola { transition: opacity 500ms var(--ease-out) 650ms, scale 700ms var(--ease-out) 600ms, rotate 700ms var(--ease-out) 600ms; }
  .listachan .recoge--puesta .recoge-mesa { --radio: 2400px; }
  .listachan .recoge--puesta .bola { opacity: 0; scale: .55; rotate: -30deg; }
}

/* ---------- 4. Ampliar la invitación ---------- */
:root:has(.listachan)::view-transition-group(invitacion) { animation-duration: 340ms; animation-timing-function: var(--ease-out); }
:root:has(.listachan).vt-ampliar::view-transition-old(root),
:root:has(.listachan).vt-ampliar::view-transition-new(root) { animation-duration: 220ms; }
/* Sin View Transition (reducir movimiento, o un navegador sin ella) y con el ratón o el dedo: el diálogo y su fondo se
   funden en 200 ms, al abrir y al cerrar (ampliar.js pone data-fundido). Con el teclado, al momento. */
.listachan .ampliada[data-fundido],
.listachan .ampliada[data-fundido]::backdrop {
  transition: opacity 200ms var(--ease-out), overlay 200ms allow-discrete, display 200ms allow-discrete;
}
.listachan .ampliada[data-fundido]:not([open]),
.listachan .ampliada[data-fundido]:not([open])::backdrop { opacity: 0; }
@starting-style {
  .listachan .ampliada[data-fundido][open],
  .listachan .ampliada[data-fundido][open]::backdrop { opacity: 0; }
}

/* ---------- 5. La lista se llena ---------- */
/* Explicación, una vez (lista.js), en el móvil de la portada: dos niños de la misma fila reciben su merienda. Con la
   portada a la vista al cargar, empieza a los 1400 ms de la tapa (ya ha girado) y acaba a los 2480 ms; si no, al bajar
   hasta la fila. En su hueco «+ Elegir» aterriza la pegatina «Elegida» con el gesto de la invitación de verdad
   (pegatinas/lamina.css: cae girada desde arriba, se aprieta y se queda) en 460 ms, con 500 ms entre uno y otro. Las
   tres capas de cada celda y su sitio, de la página de invitados de verdad, están en lista-celdas.css (las genera
   scripts/portada-capturas.mjs). Pegatina sobre papel = la lista final: al acabar no hay costura. Sin JS, o si ya se
   veía al cargar con «reducir movimiento», no hay capas: se ve la lista final. */
.listachan .lista-celda {
  position: absolute; display: none; pointer-events: none;
  background: var(--capa-papel) center / 100% 100% no-repeat;
}
.listachan .lista-celda::before,
.listachan .lista-celda::after { content: ""; position: absolute; background: center / 100% 100% no-repeat; }
.listachan .lista-celda::before { inset: 0; background-image: var(--capa-hueco); }
.listachan .lista-celda::after { background-image: var(--capa-pegatina); }
.listachan .lista-celda--primera { --retraso: 120ms; }
.listachan .lista-celda--segunda { --retraso: 620ms; }
.listachan .lista--antes .lista-celda,
.listachan .lista--llena .lista-celda { display: block; }
.listachan .lista--antes .lista-celda::after { opacity: 0; }
/* el hueco (y la columna de antes) se va de golpe en cuanto la pegatina empieza a caer, como en la app (.hueco.lleno) */
.listachan .lista--llena .lista-celda::before { opacity: 0; transition: opacity 0ms linear var(--retraso); }
@media (prefers-reduced-motion: no-preference) {
  .listachan .lista--llena .lista-celda::after { animation: aterrizar 460ms var(--ease-out) var(--retraso) backwards; }
}
@keyframes aterrizar {   /* en % de la pegatina (100 px en la app): sus -20 px y 2 px, a cualquier tamaño de móvil */
  0% { opacity: 0; transform: translateY(-20%) scale(1.2) rotate(-14deg); }
  60% { opacity: 1; transform: translateY(2%) scale(.97) rotate(2deg); }
}
/* Con «reducir movimiento»: la columna cambia de golpe, como en la app, y la pegatina solo se funde, sin caer (fundir
   la columna entera enseñaba dos veces a los que bajan). */
@media (prefers-reduced-motion: reduce) {
  .listachan .lista--llena .lista-celda::after { animation: aparecer 240ms var(--ease-out) var(--retraso) backwards; }
}
@keyframes aparecer {
  from { opacity: 0; }
}

/* ---------- 6. Cambiar de mundo ---------- */
/* mundos.js envuelve el cambio en una View Transition con .vt-mundo cuando las fotos nuevas ya están cargadas. Solo se
   capturan las tres piezas del sitio (la raíz no): el resto de la página sigue viva, y el velo de la transición deja
   pasar los toques, así que se puede elegir otra figura a mitad (la nueva salta la vieja). El móvil se captura entero
   para que la servilleta no le pase por encima. La tarjeta, a su tamaño: si cambia de ancho, la letra no se estira. */
:root:has(.listachan).vt-mundo { view-transition-name: none; }
:root:has(.listachan).vt-mundo::view-transition { pointer-events: none; }
:root:has(.listachan).vt-mundo .mundo-panel .servilleta { view-transition-name: mundo-servilleta; }
:root:has(.listachan).vt-mundo .mundo-panel .movil { view-transition-name: mundo-movil; }
:root:has(.listachan).vt-mundo .mundo-panel .tarjeta { view-transition-name: mundo-tarjeta; }
:root:has(.listachan).vt-mundo::view-transition-group(*) { animation-duration: 220ms; animation-timing-function: var(--ease-out); }
:root:has(.listachan).vt-mundo::view-transition-old(mundo-tarjeta),
:root:has(.listachan).vt-mundo::view-transition-new(mundo-tarjeta) { inline-size: auto; block-size: auto; }
:root:has(.listachan).vt-mundo::view-transition-old(*) { animation: mundo-sale 220ms var(--ease-out) both; }
:root:has(.listachan).vt-mundo::view-transition-new(*) { animation: mundo-entra 220ms var(--ease-out) both; }
@keyframes mundo-sale { to { opacity: 0; filter: blur(2px); } }
@keyframes mundo-entra { from { opacity: 0; filter: blur(2px); } }
@media (prefers-reduced-motion: reduce) {
  :root:has(.listachan).vt-mundo::view-transition-group(*) { animation: none; }   /* solo se funde: ni tamaño ni sitio */
  :root:has(.listachan).vt-mundo::view-transition-old(*) { animation: mundo-sale-suave 160ms ease both; }
  :root:has(.listachan).vt-mundo::view-transition-new(*) { animation: mundo-entra-suave 160ms ease both; }
}
@keyframes mundo-sale-suave { to { opacity: 0; } }
@keyframes mundo-entra-suave { from { opacity: 0; } }

/* ---------- 7. Con el teclado, al momento ---------- */
/* Elegir figura o plato con las flechas, abrir una pregunta con Intro: el cambio se ve en el acto, sin transición. */
.listachan .modelos:has(:focus-visible) :is(.modelo, .modelo-marca),
.listachan .platos:has(:focus-visible) .plato,
.listachan .pregunta:has(> summary:focus-visible),
.listachan .pregunta summary:focus-visible .pregunta-icono { transition: none; }
.listachan .pregunta:has(> summary:focus-visible)::details-content { transition: none; }

/* ---------- Reducir movimiento ---------- */
@media (prefers-reduced-motion: reduce) {
  .listachan .boton, .listachan button.movil, .listachan .modelo, .listachan .plato, .listachan .boton-icono {
    transition-property: background-color, color, box-shadow, opacity;
  }
  .listachan .boton:hover,
  .listachan button.movil:hover,
  .listachan .modelo:hover,
  .listachan .plato:hover,
  .listachan .modelo[aria-selected="true"],
  .listachan .plato[aria-selected="true"] { transform: none; }
  .listachan .boton:hover .boton-icono { transform: none; }
  .listachan .pregunta-icono { transition-property: background-color, color; }
  .listachan .movil-chapa { transition-property: background-color, color; }   /* la chapa cambia de color, no crece */
  .listachan .cerrar { transition-property: background-color; }               /* cerrar no se hunde al pulsarlo */
  .listachan .modelo-marca { scale: 1; transition-property: opacity; }   /* la marca del mundo elegido solo se funde */
}
