/* ============================================================================
   The Scrolling Economy — CAPA DE MOTION.  Valentina Cruz, 2026-09-24 (v2).

   Archivo aparte a proposito.  `book.css` es de Andres (sistema grafico D84);
   esta capa no toca ni una linea de aquel y se retira quitando dos lineas de
   build_web_edition.py.

   Solo `opacity` y `transform`.  Ningun elemento de esta hoja ocupa espacio en
   el flujo: la tira es `position:fixed`, asi que no puede mover una caja ni
   sumar una milesima al CLS de 0,0003.

   ---------------------------------------------------------------------------
   QUE CAMBIA EN v2, Y POR QUE

   El veredicto fue "se ve como un html plano".  La v1 tenia el argumento bien
   puesto y la presencia mal: la tira medía 13 px, se gastaba con un fundido de
   opacidad sobre filetes de 2 px —el cambio menos perceptible que existe— y
   aparecia ya montada en el primer paint, asi que el ojo la archivaba como
   adorno del pie antes de entender que era.  Se podia leer un capitulo entero
   sin verla.  Eso no se arregla animando mas: se arregla haciendo que el
   lector la vea NACER una vez y que cada gasto sea un SUCESO y no un fundido.

   M5a · EL NACIMIENTO.  La tira no existe hasta que el censo sale de pantalla.
     Entonces los diez trazos del censo se desprenden y bajan al borde.  Es la
     unica explicacion que la pieza necesita y no gasta una palabra: el lector
     ya leyo el censo veinte pixeles mas arriba.
   M5b · EL BORRADO.  El trazo no se atenua: se COME desde la izquierda, en la
     misma direccion en que el scroll se lleva el texto.  Un filete que se
     acorta se ve; un filete que baja de opacidad, no.
   M5c · LA MARCA.  Al gastarse del todo, el trazo deja una marca vertical de
     tinta que YA NO SE VA.  El trinquete deja de ser una regla del codigo y
     pasa a ser algo que se ve acumularse a lo largo del capitulo.
   M6 · EL CIERRE.  Las diez marcas —cada una con su notacion de profundidad
     perdida por el camino— se sustituyen por UNA regla continua que se traza
     en 620 ms, y solo despues las marcas se retiran.  Se ve la diferencia
     convertirse en igualdad.  Un segundo exacto, una vez por capitulo, al
     final de un documento de veinte mil pixeles.
   M7 · LA LLEGADA DE LA FIGURA.  Opacidad al inyectarse, nunca al llegar por
     scroll.  La razon esta abajo, en LOAD-02.
   ========================================================================= */

/* ---------- tokens de esta capa (no pisan ninguno de book.css) ----------- */
:root{
  --m-xs:120ms; --m-s:180ms; --m-m:320ms; --m-l:620ms;
  --m-ease-ui:cubic-bezier(.23,1,.32,1);
  --m-ease-move:cubic-bezier(.16,1,.3,1);
  --m-ease-signature:cubic-bezier(.65,0,.35,1);
}

/* ---------- M5 · la tira ------------------------------------------------- */
/* 18 px, papel opaco, CORTE DURO y sin degradado.
   La primera version llevaba un degradado de 14 px para que el texto se fuera
   por debajo con suavidad.  Hay que no tenerlo: en ESTE libro un texto que se
   desvanece ya significa algo —es lo que hace el paso de feed, M4— y una prosa
   difuminandose en el borde inferior a todas horas es esa frase dicha sin
   querer, todo el rato y sin que nadie la arme.  Con el corte duro el lector
   lee un borde de pagina, que es lo que es. */
.spend{position:fixed;left:0;right:0;bottom:0;z-index:20;pointer-events:none;
  background:var(--paper);
  padding-top:6px;padding-bottom:calc(5px + env(safe-area-inset-bottom,0px));
  opacity:0;visibility:hidden}
.spend[data-born]{opacity:1;visibility:visible}

.spend .spendrow{max-width:var(--shell);margin:0 auto;padding:0 var(--pad);
  display:flex;gap:7px;align-items:flex-start}

/* El tramo es la raya del censo y nada mas: sin caja, sin fondo, sin numero.
   La altura de 7 px es la que necesita la marca de M5c; el filete sigue siendo
   un `border-top` de 2 px, exactamente como `.census .ticks a` dibuja el suyo,
   para que sea el mismo objeto y no uno nuevo que se le parece. */
.spend .seg{flex:1 1 0;min-width:0;height:7px;position:relative}

/* el filete: se come desde la izquierda (origen a la derecha, scaleX -> 0) */
.spend .segrule{position:absolute;left:0;right:0;top:0;height:0;
  border-top:2px solid var(--ink);
  transform-origin:right center;transform:scaleX(1)}

/* la marca: 2 x 7 px de tinta en el extremo donde acabo el borrado.  Arranca
   en la linea del filete y baja los 7 px enteros de la fila: a 5 px se veia en
   una captura ampliada y no se veia leyendo, que era exactamente el defecto de
   la v1.  Es uniforme para los diez: la profundidad la lleva el filete, y
   gastarse es justamente lo que borra esa diferencia.  Por eso la marca no
   hereda ni notacion ni acento. */
.spend .segtick{position:absolute;right:0;top:0;width:2px;height:7px;
  background:var(--ink);opacity:0;
  transform:scaleY(0);transform-origin:top center}
.spend .seg[data-spent] .segtick{opacity:1;transform:scaleY(1);
  transition:transform var(--m-s) var(--m-ease-move),opacity var(--m-s) linear}

/* La profundidad de fuente se marca con la REGLA, nunca con color (D84).
   Misma notacion que `.census .ticks`, copiada tramo a tramo desde el censo. */
.spend .seg[data-depth="abstract"] .segrule{border-top-color:var(--ink2)}
.spend .seg[data-depth="record"] .segrule,
.spend .seg[data-depth="preprint"] .segrule{border-top-style:dashed;border-top-color:var(--ink2)}
.spend .seg[data-none] .segrule{border-top-style:dotted;border-top-color:var(--ink2)}
.spend .seg[data-none="revisar"] .segrule{border-top-color:var(--accent)}

/* ---------- M5a · el nacimiento ------------------------------------------ */
/* El vuelo es transform puro sobre un elemento `fixed`: no toca el flujo, no
   lee geometria dentro del frame (las dos cajas se miden antes) y no puede
   sumar CLS.  El retardo por tramo lo pone el JS. */
.spend[data-flying] .seg{transition:transform var(--m-l) var(--m-ease-move)}
.spend[data-born]{transition:opacity var(--m-m) linear}

/* ---------- M6 · el cierre ----------------------------------------------- */
/* La regla continua cae EXACTAMENTE sobre la linea de los filetes (top:6px,
   el mismo padding-top de la tira), no sobre la del borde inferior: si
   apareciera en otra altura seria una llegada, y lo que tiene que leerse es
   una sustitucion. */
.spend .spendclose{position:absolute;left:0;right:0;top:6px;
  max-width:calc(var(--shell) - var(--pad) * 2);margin:0 auto;
  height:0;border-top:2px solid var(--ink);
  transform:scaleX(0);transform-origin:left center;opacity:0}

/*  0 ms   la ultima marca se estampa (M5c, 180 ms)
    220    empieza a trazarse la regla continua
    840    la regla esta entera; las marcas se retiran
   1000    fin.  Un segundo, una vez, al final del capitulo. */
.spend[data-closed] .spendclose{transform:scaleX(1);opacity:1;
  transition:transform var(--m-l) var(--m-ease-signature) 220ms,
             opacity   var(--m-xs) linear 220ms}
.spend[data-closed] .seg[data-spent] .segtick{transform:scaleY(0);opacity:0;
  transition:transform 160ms var(--m-ease-move) 840ms,
             opacity   160ms linear 840ms}

/* ---------- donde la tira no va ------------------------------------------ */
/* En vistazo el capitulo YA es lo que un scroll deja: el instrumento sobra, y
   ademas la columna mide dos viewports y se gastaria de un tiron. */
body[data-glance] .spend{display:none}
@media print{.spend{display:none}}

/* ---------- M4 · el paso de feed ----------------------------------------- */
/* Los selectores de ocultacion los inyecta motion.js, porque la lista sale del
   HTML y no de esta hoja.  Aqui va solo lo que es decision de motion: la
   salida es SECA y el regreso tiene easing —un scroll no se lleva las cosas
   con delicadeza; devolverlas es la cortesia— y la PRIMERA vez el regreso dura
   400 ms en vez de 120 para que al lector le de tiempo a ver que ha pasado.
   De la segunda en adelante, 120: ya lo sabe. */
body[data-feedpass-first] .prose > .sec > p,
body[data-feedpass-first] .prose > .sec > .rail,
body[data-feedpass-first] .prose .figbox,
body[data-feedpass-first] .quiz{transition-duration:400ms}

/* ---------- M7 · la llegada de la figura --------------------------------- */
/* Solo opacidad, solo al inyectarse, y solo en figuras que NO estan en el
   primer viewport (lo decide el JS): una figura que empieza en opacidad 0 y
   es el elemento LCP retrasaria el LCP por definicion.

   170 ms Y NO 260, RECALIBRADO CON LAS FIGURAS DE LA FILA F YA PUESTAS.
   Los 260 se eligieron cuando esto caia sobre una caja que no dibujaba nada.
   Con dibujo de verdad —de 840 a 1.720 px de alto— medi la curva fotograma a
   fotograma sobre una figura real:

     0.5 a los 36 ms · 0.9 a los 94 · 0.95 a los 118 · 0.99 a los 166

   O sea que los ultimos 94 ms, el 36 % de la animacion, mueven la opacidad de
   0,99 a 1,00: el lector no ve nada y el compositor mantiene la capa animada
   igual, por 85 figuras, y justo en la fase donde Diego midio los fotogramas
   de 485 ms de la inyeccion.  170 ms es donde esta curva termina de ser
   visible.  No es un cambio de aspecto —es identico de mirar— es quitar
   trabajo que no se ve.  La cola del 36 % es de la curva, no de la duracion:
   acortarla la hace pequeña en absoluto, que es lo que importa. */
/* M7 RETIRADA — la sustituye M8.  Se ataba a `data-mode`, que `book.js` pone
   900 px antes de que la figura entre en pantalla, asi que el fundido pasaba
   entero fuera de la vista.  La regla se queda comentada y no en la papelera
   porque el razonamiento de por que no servia es lo util:
   .fig[data-m-in] .figbox{animation:m-figin 170ms var(--m-ease-ui) both} */
@keyframes m-figin{from{opacity:0}to{opacity:1}}

/* ---------- M8 · EL REVEAL DE LECTURA ------------------------------------
   "The picture arrives. The words wait."  (D80, y el mensaje clave del brief.)

   PARA EL REGISTRO: yo escribi que un reveal al entrar en pantalla cobra por lo
   que el libro regala, y lo defendi.  Carlos, que es el autor, lo veto: quiere
   que el texto aparezca al bajar.  Se hace, y mi objecion queda en la spec por
   si dentro de un mes resulta que tenia razon.

   LO QUE NO ES: un fade-up de manual.  Todo bloque de la columna pertenece a la
   capa de VISTAZO o a la de LECTURA —es la tesis entera del libro, el umbral de
   20 px, la figura de dos capas— y esa distincion nunca se habia visto moverse.
   Aqui se ve: el vistazo llega en el tiempo, la lectura llega 130 ms despues.
   Un titular, un pie de figura, una cita y la figura misma entran a la vez; el
   parrafo que los explica entra detras.  Treinta y ocho pantallas de eso y el
   lector ha visto el argumento del libro ejecutarse bloque a bloque sin que
   nadie se lo diga.

   Y ARREGLA LO QUE M7 NO PODIA.  `book.js` inyecta las figuras con
   `rootMargin:'900px 0px'`: el fundido de M7 terminaba 900 px ANTES de que la
   figura entrara en pantalla.  Ochenta y cinco llegadas, todas fuera de la
   vista.  Por eso la pagina no parecia moverse por mucho motion que llevara.
   M8 se ata a la entrada real en la ventana de lectura y M7 se retira.

   EL ESTADO EN REPOSO ES VISIBLE.  Nada de esta seccion esconde nada por si
   solo: la clase `m-rv` la pone el JS en <html> y solo si va a animar.  Si el
   JS no corre, no se carga, falla o el lector tiene reduced motion, el CSS de
   abajo no casa con nada y la pagina se ve entera.  Un reveal que deja texto
   invisible cuando algo falla no es un reveal, es un fallo. */
html.m-rv .m-rv-i{opacity:0}
html.m-rv .m-rv-i.m-rv-go{
  animation:m-rise 400ms var(--m-ease-move) var(--m-rv-d,0ms) both}
@keyframes m-rise{from{opacity:0;transform:translate3d(0,10px,0)}
                  to  {opacity:1;transform:none}}

/* ---------- reduced motion ----------------------------------------------- */
/* No es un apagado.  La tira sigue, sigue gastandose, sigue marcando y sigue
   cerrando: el argumento entero se queda.  Lo que se va es el MOVIMIENTO —el
   vuelo del nacimiento, el barrido continuo del borrado (en JS pasa a ser 0 o
   1 por seccion), el trazo del cierre y la llegada de la figura.  El paso de
   feed no se instala siquiera.  Lo que el lector pierde es una demostracion;
   ningun enunciado, porque todos estan en texto en el censo. */
@media (prefers-reduced-motion:reduce){
  .spend[data-flying] .seg{transition:none}
  .spend .seg[data-spent] .segtick,
  .spend[data-closed] .spendclose,
  .spend[data-closed] .seg[data-spent] .segtick{transition:none}
  .fig[data-m-in] .figbox{animation:none}
  /* Doble cinturon: el JS ya no pone `m-rv` con reduced motion, pero si el
     lector cambia la preferencia con la pagina abierta, esto lo descubre todo
     en el acto.  Nunca puede quedar un bloque en opacidad 0. */
  html.m-rv .m-rv-i{opacity:1}
  html.m-rv .m-rv-i.m-rv-go{animation:none}
}

/* ============================================================================
   LOAD-01 · NO VA EN ESTA CAPA.  Y la razon cambio al volver a medir.

   PRIMERA MEDICION (build anterior al parche de CLS de Diego).  Escribi el
   override que sustituye el arco giratorio por la regla de la figura
   respirando, lo medi, y salia carisimo:

     con el override    movimiento total 0,2634   CLS 0,0044
     sin el             movimiento total 0,0239   CLS 0,0100

   SEGUNDA MEDICION (build del 2026-09-24 18:04, con el parche YA aplicado):

     con el override    movimiento total 0,0239   CLS 0,0100
     sin el             movimiento total 0,0239   CLS 0,0100

   Identicos.  Lo que medi la primera vez no era el override: era el override
   COINCIDIENDO con una caja que crecia dos veces.  Reservada la altura, no hay
   nada con lo que coincidir.

   AUN ASI NO ENTRA AQUI, por la razon que siempre fue la mas fuerte: la regla
   que sustituye vive en `book.css`.  Una capa de motion que neutraliza una
   regla ajena con un `content:none` es una trampa para el proximo que lea el
   archivo.  Sigue aprobada, ya no tiene coste medible, y le toca a Andres
   hacerla en su archivo — con el numero de las dos vueltas, no con una.

   ---------------------------------------------------------------------------
   LOAD-02 · POR QUE LAS FIGURAS NO LLEGAN CON UN REVEAL DE SCROLL.

   Es la peticion mas facil de conceder y es la unica que hay que negar.  Un
   fade-up al entrar en pantalla COBRA por lo que este libro regala: su tesis
   entera es "the glance is free... the read costs effort", y una figura que
   hay que ganarse llegando dice lo contrario en cada una de las 85.  El mapa
   de scroll de esta edicion tiene un cero permanente en la columna
   "scroll-revealed" y ese cero es una decision, no una omision.

   Lo que si es un suceso real es el momento en que la figura se INYECTA, que
   hoy es un pop.  Eso es M7, y cuesta 260 ms de opacidad.
   ========================================================================= */
