/*!
 * DPGA · Los doce principios del motion graphics
 * (c) 2026 L.D.G. Luis E. Maldonado Gil - CodeLibri
 * aula.codelibri.com.mx - Todos los derechos reservados.
 * ref CL-DPGA-MG12-2026-8F80
 */
/* ═══════════════════════════════════════════════════════════════════════════
   LOS DOCE PRINCIPIOS DEL MOTION GRAPHICS
   Aula CodeLibri

   La clasificación es de Issara Willenskomer, «Creating Usability with Motion:
   The UX in Motion Manifesto» (2017). Los textos de definición vienen del
   material de partida, respetados casi palabra por palabra, y con una decisión
   tomada: donde el manifiesto pone «Dimensionality» aquí va «Anticipation»,
   porque lo que ese principio explica se reparte ya entre Overlay, Parallax y
   Dolly & Zoom. La numeración es propia y sigue las tres familias.

   Qué cambia respecto al original: allí cada principio se ilustraba con un GIF
   —51 archivos, 52 MB, más de tres veces lo que pesa el Aula entera—. Aquí no
   hay un solo GIF. Los doce principios SON animaciones, así que están
   construidos en CSS y se pueden manipular: la lámina está hecha de la cosa
   que explica. Doce laboratorios, uno por principio, más el mapa, el repaso y
   el cuestionario.

   La paleta se midió en el PowerPoint, no se aproximó: crema #F3F3EB,
   violeta #5632DA, azul #3C4BAF, magenta #A72BC9, lavanda #C3BBFA. Las cintas
   que serpentean por las esquinas también son del original, redibujadas en SVG.

   Motor: lienzo fijo 1600×900 centrado a mano (punto 1 del estándar).
   ═══════════════════════════════════════════════════════════════════════════ */

/* La tipografía se sirve desde aquí: una petición a Google Fonts desde una
   lámina de clase cuenta quién la abre y cuándo (punto 7 del estándar). */
@font-face{font-family:Poppins;font-weight:400;font-style:normal;font-display:block;src:url(../media/poppins-400-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Poppins;font-weight:400;font-style:normal;font-display:block;src:url(../media/poppins-400-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:Poppins;font-weight:500;font-style:normal;font-display:block;src:url(../media/poppins-500-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Poppins;font-weight:500;font-style:normal;font-display:block;src:url(../media/poppins-500-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:Poppins;font-weight:600;font-style:normal;font-display:block;src:url(../media/poppins-600-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Poppins;font-weight:600;font-style:normal;font-display:block;src:url(../media/poppins-600-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:Poppins;font-weight:700;font-style:normal;font-display:block;src:url(../media/poppins-700-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Poppins;font-weight:700;font-style:normal;font-display:block;src:url(../media/poppins-700-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}

:root{
  /* medidos en el original */
  --crema:#F3F3EB;   --violeta:#5632DA;  --azul:#3C4BAF;
  --magenta:#A72BC9; --lavanda:#C3BBFA;  --azul-vivo:#0B6EFB;
  --tinta:#171433;

  /* Los que lee tools/mejoras/ayuda.css. Sin un nombre que reconozca cae a su
     reserva —panel oscuro con el color heredado— y en modo claro sale texto
     negro sobre panel negro. Ya pasó una vez, en la del C.V. */
  --surface:#FFFFFF; --surface-2:#FAFAF6;
  --txt:#171433;     --txt-2:#4A4468;    --txt-3:#7E7899;
  --line:#DFDED4;    --line-soft:#ECEBE3;
  --bg:var(--crema); --accent:var(--violeta); --onaccent:#fff;

  --sans:'Poppins','Segoe UI Variable Display','Segoe UI',system-ui,-apple-system,Arial,sans-serif;
  --mono:'Cascadia Mono',Consolas,'Courier New',monospace;

  /* Tres sombras en capas. Una sola sombra plana delata el CSS de plantilla:
     lo que da profundidad es el contacto corto más la difusión larga. */
  --sombra-1:0 1px 2px rgba(23,20,51,.06), 0 4px 10px rgba(23,20,51,.05);
  --sombra-2:0 2px 4px rgba(23,20,51,.06), 0 10px 24px rgba(23,20,51,.09), 0 24px 60px rgba(86,50,218,.10);
  --sombra-3:0 4px 8px rgba(23,20,51,.08), 0 18px 40px rgba(23,20,51,.13), 0 40px 90px rgba(86,50,218,.16);

  /* una familia, un color: se usa en el mapa, en los separadores y en el chip */
  --f-objeto:var(--violeta); --f-jerarquia:var(--azul); --f-continuidad:var(--magenta);
}
:root[data-theme="dark"]{
  --crema:#131024;   --lavanda:#3A2E7A;
  --surface:#1C1838; --surface-2:#221D45;
  --txt:#F2F0FF;     --txt-2:#B9B2E0;    --txt-3:#8A82B8;
  --line:#2E2857;    --line-soft:#241F47;
  --bg:var(--crema); --accent:#9B7BFF;   --violeta:#9B7BFF;
  --azul:#6E86FF;    --magenta:#D46BF0;  --azul-vivo:#5AA0FF;
  --sombra-1:0 1px 2px rgba(0,0,0,.3), 0 4px 10px rgba(0,0,0,.25);
  --sombra-2:0 2px 4px rgba(0,0,0,.3), 0 10px 24px rgba(0,0,0,.35), 0 24px 60px rgba(120,90,255,.18);
  --sombra-3:0 4px 8px rgba(0,0,0,.35), 0 18px 40px rgba(0,0,0,.4), 0 40px 90px rgba(120,90,255,.24);
}

*{box-sizing:border-box;margin:0}
html,body{height:100%;overflow:hidden;background:var(--bg)}
body{font-family:var(--sans);color:var(--txt);-webkit-font-smoothing:antialiased}
button{font:inherit;color:inherit;cursor:pointer}
:focus-visible{outline:3px solid var(--accent);outline-offset:2px;border-radius:6px}

/* ══════════ el lienzo ══════════
   Centrado a mano y NUNCA con place-items del padre: cuando el lienzo es mayor
   que el hueco, la especificación degrada ese centrado a alineación al inicio
   y la lámina se dibuja desplazada, con el pie cortado. Los 26 px de más en el
   margen superior son el sitio que ocupa la barra de mandos. */
#escenario{position:fixed;inset:0;overflow:hidden}
#lienzo{
  width:1600px;height:900px;overflow:hidden;
  transform-origin:center center;
  position:absolute;left:50%;top:50%;margin:-476px 0 0 -800px;
  background:var(--bg);
}
.slide{
  position:absolute;inset:0;display:flex;background:var(--bg);
  opacity:0;visibility:hidden;transition:opacity .3s ease,visibility .3s;
}
.slide.on{opacity:1;visibility:visible}
/* El contenido se centra en vertical. Con «safe» delante, si el navegador no
   entendiera la palabra la declaracion entera se cae y vuelve al comportamiento
   de arriba: nunca deja contenido desbordado e inalcanzable, que es lo que hace
   un centrado normal cuando el hijo es mas alto que el hueco. */
.wrap{flex:1;min-width:0;position:relative;z-index:2;padding:80px 100px 86px;
      display:flex;flex-direction:column;justify-content:safe center}
/* Y sus hijos no encogen. Al pasar .wrap a columna flexible, la rejilla del
   repaso se comprimio a un tercio de su alto: un hijo flexible cede altura
   antes que desbordar, y los azulejos de 88 px se quedaron en 20. */
.wrap > *{flex:none}

/* ── las cintas del original, redibujadas y animadas ──
   stroke-dasharray al largo del trazo y dashoffset animado: la cinta se traza
   sola al entrar en la lámina, no al cargar la presentación. */
.cintas{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden;
        opacity:.42;filter:blur(1.5px)}
.cintas svg{position:absolute;width:520px;height:520px}
.cintas path{stroke-dasharray:var(--largo,1400);stroke-dashoffset:var(--largo,1400)}
.slide.on .cintas path{animation:trazar 1.5s cubic-bezier(.33,.9,.35,1) forwards}
.slide.on .cintas .abajo path{animation-delay:.22s}
@keyframes trazar{ to{stroke-dashoffset:0} }
.cintas .arriba{right:-90px;top:-150px;color:var(--azul)}
/* Mas metida en la esquina: en la portada el trazo cruzaba por detras del
   parrafo y, aunque el texto va por encima, se leia peor. */
.cintas .abajo{left:-205px;bottom:-255px;color:var(--magenta)}
:root[data-theme="dark"] .cintas{opacity:.3}

/* ── rótulo, como en el original ── */
.chip{
  position:absolute;left:0;top:42px;z-index:4;
  background:var(--violeta);color:#fff;
  padding:11px 26px 11px 100px;border-radius:0 8px 8px 0;
  font-size:19px;font-weight:500;box-shadow:var(--sombra-1);
}
.chip.jerarquia{background:var(--azul)}
.chip.continuidad{background:var(--magenta)}

/* ── tipografía ── */
.eyebrow{
  font-family:var(--mono);font-size:16px;letter-spacing:.22em;
  text-transform:uppercase;color:var(--magenta);
}
h1{font-size:104px;font-weight:700;letter-spacing:-.035em;line-height:.98}
h2{font-size:72px;font-weight:700;letter-spacing:-.03em;line-height:1;color:var(--violeta)}
h3{font-size:29px;font-weight:600;letter-spacing:-.01em}
h4{font-size:21px;font-weight:600;letter-spacing:-.005em}
p{font-size:23px;line-height:1.6;color:var(--txt-2);max-width:40ch}
b,strong{font-weight:600;color:var(--txt)}
.chico{font-size:18.5px;line-height:1.55}
.mini{font-size:16px;line-height:1.5;color:var(--txt-3)}

.dos{display:grid;grid-template-columns:1fr 1fr;gap:60px;height:100%;align-items:center}
.dos.ancha-der{grid-template-columns:.78fr 1.22fr}
.ancha .dos.ancha-der{grid-template-columns:.56fr 1.44fr;gap:44px}
.ancha .wrap{padding:44px 72px}
.texto{display:flex;flex-direction:column;gap:20px}

.pista{
  display:inline-flex;align-items:center;gap:8px;
  font-family:var(--mono);font-size:14px;letter-spacing:.1em;text-transform:uppercase;
  color:#fff;background:var(--magenta);padding:5px 13px;border-radius:20px;
  box-shadow:var(--sombra-1);align-self:flex-start;
}

/* ── la tarjeta del taller: profundidad de verdad, no un borde ── */
.taller{
  position:relative;border-radius:22px;background:var(--surface);
  box-shadow:var(--sombra-3);overflow:hidden;border:1px solid var(--line-soft);
}
.taller-cab{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:17px 24px;border-bottom:1px solid var(--line-soft);background:var(--surface-2);
}
.taller-cab h3{font-size:21px}
.taller-cab .val{font-family:var(--mono);font-size:17px;color:var(--violeta);font-variant-numeric:tabular-nums}
.lienzo-demo{position:relative;overflow:hidden}

input[type=range]{width:100%;accent-color:var(--violeta)}
.mando{display:flex;flex-direction:column;gap:7px;padding:15px 24px 20px}
.mando label{font-family:var(--mono);font-size:13.5px;letter-spacing:.12em;
             text-transform:uppercase;color:var(--txt-3)}
.mando.linea{display:grid;grid-template-columns:auto 1fr auto;gap:18px;align-items:center;padding:13px 20px 15px}
.mando.linea label{white-space:nowrap}
.mando.dosc{display:grid;grid-template-columns:1fr 1fr;gap:14px 26px;align-items:end}
.casilla{display:flex;align-items:center;gap:11px;font-size:17px;cursor:pointer}
.casilla input{accent-color:var(--violeta);width:19px;height:19px}
.pie-mando{display:flex;align-items:center;gap:18px;flex-wrap:wrap;padding:0 24px 20px}

.boton{
  border:0;border-radius:12px;padding:11px 21px;font-size:16px;font-weight:500;
  background:var(--violeta);color:#fff;box-shadow:var(--sombra-1);transition:.16s;
}
.boton:hover{transform:translateY(-1px);box-shadow:var(--sombra-2)}
.boton.hueco{background:var(--surface);color:var(--txt-2);border:1px solid var(--line)}
.boton.hueco:hover{border-color:var(--violeta);color:var(--violeta)}
.boton[aria-pressed="true"]{background:var(--magenta)}
.grupo{display:flex;gap:9px;flex-wrap:wrap}

/* ══════════ 01 · EASING ══════════
   Una fila por curva, con su play. La gráfica es de posición contra tiempo y
   lleva los tiradores punteados: es el mismo dibujo del editor de gráficos de
   After Effects, que es donde van a practicar. */
.siete{display:flex;flex-direction:column}
.curva{
  display:grid;grid-template-columns:38px 186px 1fr 136px;gap:16px;align-items:center;
  padding:2px 20px;border-bottom:1px solid var(--line-soft);
}
.curva:last-child{border-bottom:0}
.curva.activa{background:color-mix(in srgb,var(--violeta) 6%,transparent)}
.play{
  width:38px;height:38px;border-radius:50%;display:grid;place-items:center;
  border:1px solid var(--line);background:var(--surface-2);color:var(--violeta);
  font-size:13px;line-height:1;transition:.16s;box-shadow:var(--sombra-1);
}
.play:hover{border-color:var(--violeta);transform:scale(1.06)}
.play[aria-pressed="true"]{background:var(--violeta);color:#fff;border-color:var(--violeta)}
.curva .nom{font-size:17px;font-weight:600;line-height:1.15;display:block}
.curva .bez{font-family:var(--mono);font-size:11px;color:var(--txt-3);display:block;margin-top:3px}
.riel-c{position:relative;height:44px;display:flex;align-items:center}
.riel-c::before{content:"";position:absolute;left:0;right:0;height:2px;
  background:repeating-linear-gradient(90deg,var(--line) 0 6px,transparent 6px 12px)}
.bolita{
  position:relative;width:34px;height:34px;border-radius:50%;flex:none;
  background:linear-gradient(150deg,#8f6bff,var(--violeta));
  box-shadow:0 2px 5px rgba(23,20,51,.22), 0 10px 22px rgba(86,50,218,.3);
}
/* El 70 % del ciclo es el viaje y el resto un descanso: en bucle, sin esa
   pausa las siete se leen como un parpadeo continuo. */
.curva.corre .bolita{
  animation:viaja var(--ciclo,1285ms) var(--fn,linear) both;
  animation-iteration-count:var(--veces,1);
}
@keyframes viaja{
  0%{transform:translateX(0)}
  70%{transform:translateX(var(--rec,200px))}
  100%{transform:translateX(var(--rec,200px))}
}
.graf{width:136px;height:80px}
.graf .marco{stroke:var(--line);stroke-width:1;fill:var(--surface-2)}
.graf .malla{stroke:var(--line);stroke-width:.6}
.graf .base{stroke:var(--txt-3);stroke-width:.9;opacity:.55}
.graf .tir{stroke:var(--txt-3);stroke-width:1.2;stroke-dasharray:3 3}
.graf .cur{stroke:var(--magenta);stroke-width:2.6;fill:none;stroke-linecap:round}
.graf .pto{fill:var(--violeta)}
.graf .man{fill:none;stroke:var(--txt-3);stroke-width:1.2}
.graf .et{font-family:var(--mono);font-size:8px;fill:var(--txt-3)}
.interruptor{display:flex;align-items:center;gap:10px;font-size:17px;cursor:pointer}
.interruptor input{accent-color:var(--violeta);width:19px;height:19px}

/* ══════════ 02 · ANTICIPATION ══════════
   Dos carriles idénticos salvo por una cosa: el de abajo retrocede antes de
   salir. El retroceso va en una variable, así que el deslizador lo mueve sin
   volver a escribir la animación. */
.carriles{display:flex;flex-direction:column;gap:16px;padding:30px 26px 14px}
/* El rotulo va encima y no al lado: asi el carril ocupa el ancho entero de la
   tarjeta y el viaje se hace largo, que es lo que hay que comparar. */
.carril{display:block}
.carril .et{display:block;font-family:var(--mono);font-size:14px;color:var(--txt-3);letter-spacing:.06em}
.pista-a{position:relative;height:165px;display:flex;align-items:center}
.pista-a::before{content:"";position:absolute;left:0;right:0;height:2px;
  background:repeating-linear-gradient(90deg,var(--line) 0 6px,transparent 6px 12px)}
.cubo{
  width:70px;height:70px;border-radius:17px;flex:none;box-shadow:var(--sombra-2);
  display:grid;place-items:center;color:#fff;font-family:var(--mono);font-size:13px;
}
.cubo.plano{background:linear-gradient(150deg,#5b7bff,var(--azul))}
.cubo.ant{background:linear-gradient(150deg,#d16bea,var(--magenta))}
.corre-a .cubo.plano{animation:directo var(--dur-a,900ms) cubic-bezier(.33,.9,.35,1) both}
.corre-a .cubo.ant{animation:anticipa var(--dur-a,900ms) cubic-bezier(.33,.9,.35,1) both}
@keyframes directo{
  0%{transform:translateX(0) scaleX(1)}
  100%{transform:translateX(var(--rec-a,400px)) scaleX(1)}
}
/* El 22 % inicial es la carga: retrocede y se comprime. Es lo que hace que el
   ojo prevea la salida antes de que ocurra. */
@keyframes anticipa{
  0%  {transform:translateX(0) scale(1,1)}
  22% {transform:translateX(calc(-1 * var(--ant,26px))) scale(.86,1.12)}
  34% {transform:translateX(calc(-1 * var(--ant,26px) * .6)) scale(1.1,.9)}
  100%{transform:translateX(var(--rec-a,400px)) scale(1,1)}
}

/* ══════════ 03 · MASKING ══════════
   La máscara no borra el objeto: decide qué parte se ve. clip-path con una
   forma que se abre es exactamente eso, y se puede recorrer a mano. */
.mask-caja{position:relative;height:410px;margin:22px 26px 6px;border-radius:16px;overflow:hidden;background:var(--surface-2)}
.mask-obj{
  position:absolute;inset:0;display:grid;place-items:center;text-align:center;
  background:linear-gradient(135deg,#7d5bff,#a72bc9 52%,#3c4baf);
  color:#fff;padding:24px;
}
.mask-obj .gr{font-size:52px;font-weight:700;letter-spacing:-.02em;line-height:1.14}
.mask-obj .pq{font-family:var(--mono);font-size:14px;letter-spacing:.18em;margin-top:10px;opacity:.82}
.mask-borde{position:absolute;inset:0;border-radius:16px;border:2px dashed var(--line);pointer-events:none}
/* Sin transición de CSS: el recorrido lo lleva el guion, igual para las cuatro
   formas. La persiana no usa clip-path sino máscara, y las dos cosas no se
   pueden interpolar con la misma regla. */

/* ══════════ 04 · OVERLAY ══════════ */
.capas{height:458px;display:grid;place-items:center;perspective:1300px;perspective-origin:50% 45%}
.pila{position:relative;width:300px;height:346px;transform-style:preserve-3d;
      transform:rotateX(var(--rx,14deg)) rotateY(var(--ry,-26deg));
      transition:transform .5s cubic-bezier(.22,1,.36,1)}
.capa{
  position:absolute;inset:0;border-radius:16px;border:1px solid rgba(255,255,255,.5);
  box-shadow:var(--sombra-2);display:grid;place-items:center;
  font-family:var(--mono);font-size:14px;letter-spacing:.14em;color:#fff;
  transition:transform .5s cubic-bezier(.22,1,.36,1);
}
.c1{background:linear-gradient(150deg,#7d5bff,#5632da);transform:translateZ(var(--z1,0px))}
.c2{background:linear-gradient(150deg,#c264e4,#a72bc9);transform:translateZ(var(--z2,0px))}
.c3{background:linear-gradient(150deg,#4f74ff,#3c4baf);transform:translateZ(var(--z3,0px))}

/* ══════════ 05 · CLONING ══════════ */
.clon-caja{position:relative;height:410px;margin:20px 26px 4px;border-radius:16px;
           background:var(--surface-2);overflow:hidden}
.clon{
  position:absolute;width:30px;height:30px;border-radius:9px;
  background:linear-gradient(150deg,#8f6bff,var(--violeta));
  box-shadow:0 2px 6px rgba(86,50,218,.35);
  transform:translate(-50%,-50%) scale(0);opacity:0;
}
.clon-caja.corre .clon{animation:brota .52s cubic-bezier(.34,1.56,.64,1) forwards;animation-delay:var(--esp,0ms)}
@keyframes brota{ to{transform:translate(-50%,-50%) scale(1);opacity:1} }
.clon.madre{background:linear-gradient(150deg,#d16bea,var(--magenta));width:40px;height:40px;
            transform:translate(-50%,-50%) scale(1);opacity:1;animation:none!important;z-index:2}

/* ══════════ 06 · DOLLY / ZOOM ══════════
   Con perspective:P, un plano a translateZ(z) se dibuja a escala P/(P−z). El
   sujeto en z=0 → escala P/P = 1, CONSTANTE. El fondo en z=−Δ → P/(P+Δ), que
   sí cambia. Así que el efecto entero es mover P: nada más se toca. */
.camara{
  position:relative;aspect-ratio:16/9;border-radius:16px;overflow:hidden;
  background:linear-gradient(#141033,#0b0820);
  perspective:600px;perspective-origin:50% 50%;box-shadow:var(--sombra-2);
}
.escena{position:absolute;inset:0;transform-style:preserve-3d}
/* La rejilla NO está en el espacio 3D. Cuando el suelo era un plano rotado, su
   borde lejano subía hacia el punto de fuga y acababa cruzando por delante del
   sujeto: las líneas se le montaban encima. Dibujada en SVG y confinada a la
   banda inferior, sugiere la profundidad sin poder cruzarse con nada. */
.rejilla{position:absolute;left:0;right:0;bottom:0;height:52%;z-index:0;pointer-events:none;opacity:.5}
.rejilla line{stroke:#9B7BFF;stroke-width:1.2;vector-effect:non-scaling-stroke}
.sujeto{
  position:absolute;left:50%;top:44%;translate:-50% -50%;
  width:128px;height:196px;border-radius:14px;
  background:linear-gradient(155deg,#fff,#d9d2ff);
  box-shadow:0 18px 40px rgba(0,0,0,.55);display:grid;place-items:center;color:#2a2350;
  font-family:var(--mono);font-size:13px;letter-spacing:.16em;transform:translateZ(0);
}
.poste{position:absolute;top:50%;translate:0 -50%;width:26px;border-radius:5px}
.q1{left:16%;height:230px;background:linear-gradient(180deg,#8f6bff,#4a35a8);transform:translateZ(-300px)}
.q2{right:17%;height:270px;background:linear-gradient(180deg,#c264e4,#7a1f96);transform:translateZ(-620px)}
.q3{left:36%;height:320px;background:linear-gradient(180deg,#5b7bff,#2c3a86);transform:translateZ(-1150px);opacity:.75}
.lectura-cam{
  position:absolute;left:0;right:0;bottom:0;display:flex;justify-content:space-between;
  padding:11px 18px;font-family:var(--mono);font-size:14px;color:rgba(255,255,255,.72);
  background:linear-gradient(to top,rgba(8,6,24,.8),transparent);
}

/* ══════════ 07 · OFFSET & DELAY ══════════ */
/* Cinco filas de 68 y cuatro huecos de 10 son 380, dentro de los 396 que deja
   la caja. Antes las filas medían 86 y la lista se salía por arriba, encima de
   la cabecera de la tarjeta. */
.lista-off{display:flex;flex-direction:column;gap:10px;padding:16px 26px 12px;height:430px;justify-content:center}
.fila-off{
  display:grid;grid-template-columns:44px 1fr auto;gap:16px;align-items:center;
  padding:8px 18px;border-radius:13px;background:var(--surface-2);
  border:1px solid var(--line-soft);
  opacity:0;transform:translateX(46px);
}
.lista-off.corre .fila-off{
  animation:entra var(--dur-o,540ms) cubic-bezier(.22,1,.36,1) both;
  animation-delay:calc(var(--i) * var(--esp-o,90ms));
}
@keyframes entra{ to{opacity:1;transform:translateX(0)} }
.fila-off .ico{
  width:44px;height:44px;border-radius:12px;display:grid;place-items:center;color:#fff;
  background:linear-gradient(150deg,#8f6bff,var(--violeta));font-size:19px;
}
.fila-off .tt{font-size:19.5px;font-weight:500}
.fila-off .ss{font-family:var(--mono);font-size:12.5px;color:var(--txt-3)}

/* ══════════ 08 · PARENTING ══════════ */
.pad-caja{position:relative;height:414px;margin:18px 26px 2px;border-radius:16px;background:var(--surface-2);overflow:hidden}
.padre{
  position:absolute;left:50%;top:50%;width:150px;height:150px;margin:-75px 0 0 -75px;
  border-radius:24px;background:linear-gradient(150deg,#d16bea,var(--magenta));
  box-shadow:var(--sombra-2);display:grid;place-items:center;color:#fff;
  font-family:var(--mono);font-size:12px;letter-spacing:.14em;
  transform:rotate(var(--rot,0deg)) scale(var(--esc,1));
  transition:transform .35s cubic-bezier(.22,1,.36,1);
}
.hijo{
  position:absolute;width:70px;height:70px;border-radius:17px;
  background:linear-gradient(150deg,#8f6bff,var(--violeta));box-shadow:var(--sombra-1);
  display:grid;place-items:center;color:#fff;font-family:var(--mono);font-size:11px;
  transition:transform .35s cubic-bezier(.22,1,.36,1);
}
/* Vinculados: los hijos viven DENTRO del padre y heredan su transformación.
   Sueltos: se quedan donde están, que es justo lo que hay que ver. */
.pad-caja.sueltos .padre{transform:rotate(var(--rot,0deg)) scale(var(--esc,1))}
.pad-caja.sueltos .hijo{transform:none!important}
.linea-pad{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:0}
.linea-pad line{stroke:var(--line);stroke-width:2;stroke-dasharray:5 5}

/* ══════════ 09 · OBSCURATION ══════════ */
.obs-caja{position:relative;height:414px;margin:18px 26px 2px;border-radius:16px;overflow:hidden;background:var(--surface-2)}
.obs-fondo{position:absolute;inset:0;padding:20px;display:flex;flex-direction:column;gap:11px;
           filter:blur(var(--desenf,0px));transition:filter .4s ease}
.obs-fondo .barra{height:19px;border-radius:10px;background:var(--line)}
.obs-fondo .barra.corta{width:56%}
.obs-fondo .bloque{flex:1;border-radius:12px;background:linear-gradient(135deg,#c9c4e8,#9d95d6);min-height:70px}
.obs-velo{position:absolute;inset:0;background:#12102a;opacity:var(--velo,0);transition:opacity .4s ease}
.obs-dialogo{
  position:absolute;left:50%;top:50%;width:356px;translate:-50% -50%;
  background:var(--surface);border-radius:18px;padding:26px 28px;box-shadow:var(--sombra-3);
  opacity:0;transform:scale(.9) translateY(14px);transition:.42s cubic-bezier(.22,1,.36,1);
  pointer-events:none;
}
.obs-caja.abierto .obs-dialogo{opacity:1;transform:none;pointer-events:auto}
.obs-dialogo h4{margin-bottom:7px}
.obs-dialogo .boton{white-space:nowrap}

/* ══════════ 10 · PARALLAX ══════════ */
.par-caja{
  position:relative;height:412px;margin:18px 26px 2px;border-radius:16px;overflow:hidden;
  background:linear-gradient(#1b1540,#0d0a24);cursor:ew-resize;touch-action:none;
}
.par-capa{position:absolute;inset:0;will-change:transform}
.par-capa .pieza{position:absolute;bottom:0;border-radius:12px 12px 0 0}
.par-luna{position:absolute;right:14%;top:14%;width:84px;height:84px;border-radius:50%;
          background:radial-gradient(circle at 34% 32%,#fff,#cfc6ff)}
.par-eti{
  position:absolute;left:0;bottom:0;padding:9px 16px;font-family:var(--mono);font-size:13px;
  color:rgba(255,255,255,.7);background:linear-gradient(to top,rgba(8,6,24,.85),transparent);
  width:100%;display:flex;justify-content:space-between;
}

/* ══════════ 11 · TRANSFORMATION ══════════ */
.tra-caja{position:relative;height:418px;margin:20px 26px 2px;border-radius:16px;background:var(--surface-2);display:grid;place-items:center}
.tra-obj{
  --t:0;
  width:calc(206px + var(--t) * 184px);
  height:calc(62px + var(--t) * 288px);
  border-radius:calc(31px - var(--t) * 11px);
  background:linear-gradient(150deg,#7d5bff,#5632da);
  box-shadow:var(--sombra-2);position:relative;overflow:hidden;color:#fff;
}
.tra-eti{
  position:absolute;inset:0;display:grid;place-items:center;
  font-size:17px;font-weight:500;letter-spacing:.02em;
  opacity:calc(1 - var(--t) * 2.6);
}
.tra-cuerpo{
  position:absolute;inset:0;padding:22px;display:flex;flex-direction:column;gap:11px;
  opacity:calc((var(--t) - .55) * 2.3);
}
.tra-cuerpo .l{height:12px;border-radius:7px;background:rgba(255,255,255,.42)}
.tra-cuerpo .l.c{width:62%}
.tra-cuerpo .tit{font-size:26px;font-weight:600;margin-bottom:6px}

/* ══════════ 12 · VALUE CHANGE ══════════ */
.val-caja{padding:24px 26px 6px;display:flex;flex-direction:column;gap:26px;height:430px;justify-content:center}
.contador{
  font-size:126px;font-weight:700;letter-spacing:-.04em;line-height:1.16;
  font-variant-numeric:tabular-nums;text-align:center;
  background:linear-gradient(115deg,var(--violeta),var(--magenta) 70%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
.aguja{position:relative;height:20px;border-radius:9px;background:var(--line-soft);overflow:hidden}
.aguja i{position:absolute;inset:0 auto 0 0;border-radius:9px;
         background:linear-gradient(90deg,var(--violeta),var(--magenta));width:0%}
.val-fila{display:flex;justify-content:space-between;font-family:var(--mono);font-size:13.5px;color:var(--txt-3)}

/* ══════════ pestañas: lo construido y lo real ══════════
   El laboratorio enseña el principio aislado y manipulable; el vídeo enseña el
   mismo principio dentro de un producto de verdad. Las dos cosas ocupan el
   mismo hueco, así que la tarjeta no cambia de alto al pasar de una a otra. */
.pestanas{display:flex;border-bottom:1px solid var(--line-soft);background:var(--surface-2)}
.pes{
  flex:1;border:0;background:none;padding:10px 14px;font-size:15.5px;color:var(--txt-3);
  border-bottom:2px solid transparent;transition:.16s;
}
.pes:hover{color:var(--violeta)}
.pes[aria-pressed="true"]{
  color:var(--violeta);font-weight:600;border-bottom-color:var(--violeta);background:var(--surface);
}
.cuerpo{position:relative}
.panel-real{
  position:absolute;inset:0;z-index:3;background:var(--surface);
  display:none;grid-template-columns:1fr 1fr;gap:16px;padding:20px 22px 14px;
  grid-template-rows:1fr auto;
}
.panel-real.on{display:grid}
.panel-real figure{margin:0;display:flex;flex-direction:column;gap:8px;min-height:0}
.panel-real video{
  width:100%;flex:1;min-height:0;object-fit:contain;border-radius:12px;
  background:var(--surface-2);box-shadow:var(--sombra-1);
}
.panel-real figcaption{
  font-family:var(--mono);font-size:12px;color:var(--txt-3);
  letter-spacing:.08em;text-align:center;
}
.panel-real .fuente{
  grid-column:1/-1;font-size:13px;color:var(--txt-3);text-align:center;align-self:end;
}

/* ══════════ mapa de los doce ══════════ */
.mapa{display:grid;grid-template-columns:repeat(4,1fr);gap:13px}
.mp{
  text-align:left;border:1px solid var(--line);background:var(--surface);
  border-radius:16px;padding:15px 16px 14px;transition:.18s;box-shadow:var(--sombra-1);
  display:flex;flex-direction:column;gap:7px;min-height:112px;
}
.mp:hover{transform:translateY(-3px);box-shadow:var(--sombra-2);border-color:var(--c)}
.mp[aria-pressed="true"]{background:var(--c);border-color:var(--c);color:#fff}
.mp[aria-pressed="true"] .mp-n,.mp[aria-pressed="true"] .mp-f{color:rgba(255,255,255,.78)}
.mp-n{font-family:var(--mono);font-size:12px;color:var(--txt-3);letter-spacing:.14em}
.mp-t{font-size:19px;font-weight:600;line-height:1.15;letter-spacing:-.01em}
.mp-f{font-size:12.5px;color:var(--c);font-weight:500;margin-top:auto}
.mapa-det{
  margin-top:18px;border-radius:18px;background:var(--surface);border:1px solid var(--line-soft);
  box-shadow:var(--sombra-2);padding:22px 26px;min-height:150px;
  display:grid;grid-template-columns:auto 1fr;gap:24px;align-items:start;
}
.mapa-det .num{font-size:60px;font-weight:700;letter-spacing:-.04em;line-height:.9;color:var(--c,var(--violeta))}
.mapa-det p{max-width:none;font-size:19.5px;line-height:1.55}
.mapa-det h4{margin-bottom:6px;font-size:24px}

/* ══════════ separadores de familia ══════════ */
.sep{display:flex;flex-direction:column;justify-content:center;gap:26px;height:100%}
.sep .grande{font-size:118px;font-weight:700;letter-spacing:-.045em;line-height:.95;color:var(--c)}
.sep-lista{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;max-width:1100px;margin-top:8px}
.sep-lista div{
  border-left:4px solid var(--c);padding:9px 0 9px 16px;font-size:20px;font-weight:500;
}
.sep-lista span{display:block;font-family:var(--mono);font-size:12px;color:var(--txt-3);letter-spacing:.14em;margin-bottom:3px}

/* ══════════ repaso: los doce de un vistazo ══════════ */
.vistazo{display:grid;grid-template-columns:repeat(6,1fr);gap:14px}
.vt{
  border:1px solid var(--line);background:var(--surface);border-radius:16px;padding:0 0 12px;
  overflow:hidden;box-shadow:var(--sombra-1);transition:.18s;text-align:center;
}
.vt:hover{transform:translateY(-3px);box-shadow:var(--sombra-2);border-color:var(--c)}
/* «display:block» no es decoracion: los tres son <span>, y un span en linea
   ignora la altura. Sin esto el azulejo de 88 px se queda en la altura del
   texto. Ya paso una vez, con las caras de las tarjetas del C.V. */
.vt-lienzo{display:block;height:88px;position:relative;background:var(--surface-2);overflow:hidden;border-bottom:1px solid var(--line-soft)}
.vt-t{display:block;font-size:14.5px;font-weight:600;padding:9px 8px 0;line-height:1.2}
.vt-n{display:block;font-family:var(--mono);font-size:10.5px;color:var(--txt-3);letter-spacing:.1em}
.vt-pieza{position:absolute;border-radius:7px;background:var(--c)}
/* Cada azulejo mueve su pieza a su manera; el nombre del principio se lee en
   el movimiento antes que en la etiqueta. */
.vt.anda .vt-pieza{animation:var(--anim) 1.5s infinite}
@keyframes v-easing{0%,100%{left:14%}50%{left:66%}}
@keyframes v-antic {0%,100%{left:14%}14%{left:6%}50%{left:66%}}
@keyframes v-mask  {0%,100%{clip-path:inset(0 100% 0 0)}55%,95%{clip-path:inset(0 0 0 0)}}
@keyframes v-over  {0%,100%{transform:translate(0,0)}50%{transform:translate(9px,-9px)}}
@keyframes v-clon  {0%,100%{transform:scale(.4);opacity:.4}50%{transform:scale(1);opacity:1}}
@keyframes v-dolly {0%,100%{transform:scale(.7)}50%{transform:scale(1.25)}}
@keyframes v-offset{0%,100%{transform:translateY(0)}50%{transform:translateY(-11px)}}
@keyframes v-parent{0%,100%{transform:rotate(0)}50%{transform:rotate(38deg)}}
@keyframes v-obscu {0%,100%{filter:blur(0);opacity:1}50%{filter:blur(3px);opacity:.45}}
@keyframes v-parax {0%,100%{transform:translateX(0)}50%{transform:translateX(-15px)}}
@keyframes v-trans {0%,100%{border-radius:20px;height:16px}50%{border-radius:6px;height:40px}}
@keyframes v-value {0%,100%{width:16%}50%{width:74%}}

/* ══════════ cuestionario ══════════ */
.quiz{display:grid;grid-template-columns:1.05fr 1fr;gap:34px;align-items:start}
.quiz-esc{
  position:relative;height:322px;border-radius:18px;background:var(--surface-2);
  border:1px solid var(--line-soft);overflow:hidden;box-shadow:var(--sombra-2);
}
.q-op{
  display:block;width:100%;text-align:left;border:1px solid var(--line);background:var(--surface);
  border-radius:14px;padding:14px 18px;font-size:18.5px;transition:.16s;margin-bottom:11px;
  box-shadow:var(--sombra-1);
}
.q-op:hover{border-color:var(--violeta);transform:translateX(3px)}
/* El acierto y el fallo tienen que verse de lejos y en los dos temas: con un
   12 % de tinte sobre la superficie oscura no se distinguian. */
.q-op.bien{border-color:#1E9E63;border-width:2px;background:color-mix(in srgb,#1E9E63 24%,var(--surface));font-weight:600}
.q-op.mal{border-color:#D14343;border-width:2px;background:color-mix(in srgb,#D14343 20%,var(--surface))}
.q-op.bien::after{content:" ✓";color:#1E9E63;font-weight:700}
.q-op.mal::after{content:" ✕";color:#D14343;font-weight:700}
.q-op[disabled]{cursor:default;transform:none}
.q-razon{
  border-left:4px solid var(--violeta);padding:12px 0 12px 16px;font-size:17.5px;
  line-height:1.55;color:var(--txt-2);min-height:60px;
}
.q-cab{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:14px}
.q-cont{font-family:var(--mono);font-size:14px;color:var(--txt-3)}

/* ── las escenas del cuestionario ──
   También construidas en CSS. Preguntar por un principio enseñando un GIF
   sería contradecir la presentación entera. */
.qe-lista,.qe-dolly,.qe-mask,.qe-antic,.qe-obscu{position:absolute;inset:0}
.qe-lista{display:flex;flex-direction:column;justify-content:center;gap:15px;padding:0 56px}
.qe-lista i{
  display:block;height:40px;border-radius:12px;
  background:linear-gradient(90deg,var(--violeta),#8f6bff);
  animation:qe-entra 2.4s cubic-bezier(.22,1,.36,1) infinite both;
  animation-delay:calc(var(--i) * .13s);
}
@keyframes qe-entra{
  0%{opacity:0;transform:translateX(64px)}
  20%,84%{opacity:1;transform:translateX(0)}
  100%{opacity:0;transform:translateX(64px)}
}
.qe-dolly{background:linear-gradient(#141033,#0b0820);display:grid;place-items:center}
.qe-dolly .fondo{
  position:absolute;left:20%;top:50%;width:56px;height:150px;margin-top:-75px;
  border-radius:8px;background:#5a3fb8;animation:qe-fondoI 3s ease-in-out infinite;
}
.qe-dolly .fondo.b{left:auto;right:20%;background:#7a2f96;animation-name:qe-fondoD}
.qe-dolly .suj{
  position:relative;display:block;width:78px;height:124px;border-radius:12px;
  background:linear-gradient(155deg,#fff,#d9d2ff);box-shadow:0 14px 30px rgba(0,0,0,.5);
}
@keyframes qe-fondoI{0%,100%{transform:translateX(0) scale(.6)}50%{transform:translateX(-48px) scale(1.55)}}
@keyframes qe-fondoD{0%,100%{transform:translateX(0) scale(.6)}50%{transform:translateX(48px) scale(1.55)}}
.qe-mask{display:grid;place-items:center;background:var(--surface-2)}
.qe-mask i{
  display:block;width:74%;height:64px;border-radius:14px;
  background:linear-gradient(90deg,var(--violeta),var(--magenta));
  animation:qe-mask 2.6s ease-in-out infinite;
}
@keyframes qe-mask{
  0%,8%{clip-path:inset(0 100% 0 0)}
  52%,92%{clip-path:inset(0 0 0 0)}
  100%{clip-path:inset(0 100% 0 0)}
}
.qe-antic{background:var(--surface-2)}
.qe-antic i{
  position:absolute;left:46px;top:50%;margin-top:-30px;width:60px;height:60px;border-radius:16px;
  background:linear-gradient(150deg,#d16bea,var(--magenta));box-shadow:var(--sombra-2);
  animation:qe-antic 2.6s cubic-bezier(.33,.9,.35,1) infinite;
}
@keyframes qe-antic{
  0%  {left:46px;transform:scale(1,1)}
  14% {left:16px;transform:scale(.86,1.14)}
  22% {left:30px;transform:scale(1.08,.92)}
  62%,90%{left:calc(100% - 106px);transform:scale(1,1)}
  100%{left:46px;transform:scale(1,1)}
}
.qe-obscu{padding:28px;display:flex;flex-direction:column;gap:15px;justify-content:center;background:var(--surface-2)}
.qe-obscu .bg{display:block;height:46px;border-radius:12px;background:#c1bbe4;animation:qe-obscu 3s ease-in-out infinite}
.qe-obscu .bg.b{width:64%}
.qe-obscu .tarj{
  position:absolute;left:50%;top:50%;width:62%;height:46%;translate:-50% -50%;
  border-radius:16px;background:var(--surface);box-shadow:var(--sombra-3);
  animation:qe-tarj 3s ease-in-out infinite;
}
@keyframes qe-obscu{0%,22%{filter:blur(0);opacity:1}52%,88%{filter:blur(5px);opacity:.4}100%{filter:blur(0);opacity:1}}
@keyframes qe-tarj{0%,22%{opacity:0;transform:scale(.9)}52%,88%{opacity:1;transform:scale(1)}100%{opacity:0;transform:scale(.9)}}

/* ══════════ tabla del puente a After Effects ══════════ */
.puente{width:100%;border-collapse:collapse;font-size:19px}
.puente th{
  text-align:left;font-family:var(--mono);font-size:12.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--txt-3);padding:0 16px 11px;font-weight:500;
}
.puente td{padding:12px 16px;border-top:1px solid var(--line-soft);vertical-align:top}
.puente tr td:first-child{font-weight:500;color:var(--violeta);width:27%}
.puente code{font-family:var(--mono);font-size:15.5px;background:var(--surface-2);
             padding:2px 7px;border-radius:6px;border:1px solid var(--line-soft)}

/* ══════════ listas de cierre ══════════ */
.tarjetas{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:6px}
.tj{background:var(--surface);border:1px solid var(--line-soft);border-radius:18px;
    padding:22px 24px;box-shadow:var(--sombra-2);display:flex;flex-direction:column;gap:9px}
.tj .n{font-family:var(--mono);font-size:12.5px;letter-spacing:.16em;color:var(--magenta)}
.tj p{font-size:17.5px;line-height:1.5;max-width:none}
.dosl{display:grid;grid-template-columns:1fr 1fr;gap:46px;align-items:start}
.lista-p{display:flex;flex-direction:column;gap:13px;padding:0;margin:0}
/* La vineta va en un ::before absoluto y NO en una rejilla: con display:grid
   cada <b> del texto se convertia en su propia celda y la frase salia partida
   en trozos sueltos. */
.lista-p li{list-style:none;position:relative;padding-left:25px;font-size:19.5px;line-height:1.45;color:var(--txt-2)}
.lista-p li::before{content:"";position:absolute;left:0;top:10px;width:9px;height:9px;border-radius:3px;background:var(--violeta)}
.creditos{display:flex;flex-direction:column;gap:15px;font-size:18.5px;line-height:1.55;color:var(--txt-2)}
.creditos b{display:block;color:var(--txt)}
/* Los enlaces salen del mazo hacia el Aula: en pestaña nueva, porque la
   presentación se ve dentro de un marco y perderla a media clase es peor. */
a.enlace{color:var(--violeta);text-decoration:underline;text-underline-offset:3px;
         text-decoration-thickness:1px;transition:.14s}
a.enlace:hover{color:var(--magenta);text-decoration-thickness:2px}
/* Referencias en APA: sangría francesa. */
.apa{display:flex;flex-direction:column;gap:16px}
.apa p{font-size:17.5px;line-height:1.55;max-width:none;text-indent:-2.1em;padding-left:2.1em}
.apa i{font-style:italic}
/* La dirección va a la vista pero sin enlazar: una referencia se cita, no se
   pulsa. Los enlaces del mazo son otra cosa y siguen siendo enlaces. */
.apa .url{font-size:16.5px;color:var(--txt-3);overflow-wrap:anywhere}
.portada{display:flex;flex-direction:column;justify-content:center;gap:24px;height:100%}
.portada .doce{
  font-size:190px;font-weight:700;line-height:.82;letter-spacing:-.05em;
  background:linear-gradient(115deg,var(--violeta),var(--magenta) 62%,var(--azul));
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
.portada .cred{font-size:20.5px;color:var(--txt-3);margin-top:10px;max-width:74ch;line-height:1.6}
.gracias{display:flex;flex-direction:column;justify-content:center;align-items:center;gap:18px;height:100%;text-align:center}
.gracias h1{font-size:132px}

/* ══════════ cromo ══════════ */
.railbar{position:fixed;left:0;right:0;bottom:0;height:3px;z-index:21;background:var(--line-soft)}
.railbar i{display:block;height:100%;width:0;background:linear-gradient(90deg,var(--violeta),var(--magenta));transition:width .3s ease}
/* La clase «chrome» la busca ayuda.js para meter su botón en esta fila. Sin
   ella queda flotando por su cuenta, fuera de línea con los demás. */
.chrome.hud{
  position:fixed;left:0;right:0;bottom:0;z-index:20;height:52px;
  display:flex;align-items:center;gap:11px;padding:0 18px;
  background:linear-gradient(0deg,color-mix(in srgb,var(--bg) 94%,transparent),transparent);
}
.hud-btn{
  width:34px;height:34px;border-radius:11px;display:grid;place-items:center;
  border:1px solid var(--line);background:var(--surface);color:var(--txt-2);
  font-size:15px;transition:.16s;box-shadow:var(--sombra-1);
}
.hud-btn:hover{border-color:var(--violeta);color:var(--violeta);transform:translateY(-1px)}
.hud-btn[disabled]{opacity:.36;cursor:default;transform:none}
.counter{font-family:var(--mono);font-size:12px;color:var(--txt-3);min-width:58px;text-align:center}
.hud-title{flex:1;font-size:12px;color:var(--txt-3);letter-spacing:.1em;text-transform:uppercase;text-align:center;
           overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ── índice ── */
.index{
  position:fixed;inset:0;z-index:40;background:color-mix(in srgb,var(--bg) 96%,transparent);
  padding:54px 66px;overflow:auto;display:none;
}
.index.on{display:block}
.index h2{font-size:40px;color:var(--txt);margin-bottom:8px}
/* Con borde y fondo propios: un botón de cerrar que solo es un aspa gris se
   pierde, y hubo que rehacerlo en tres presentaciones por eso. */
.idx-close{
  position:fixed;right:26px;top:24px;width:46px;height:46px;border-radius:14px;
  border:1px solid var(--line);background:var(--surface);color:var(--txt);
  font-size:24px;line-height:1;display:grid;place-items:center;box-shadow:var(--sombra-2);transition:.16s;
}
.idx-close:hover{background:var(--violeta);color:#fff;border-color:var(--violeta);transform:rotate(90deg)}
.idx-keys{display:flex;gap:20px;flex-wrap:wrap;font-size:14px;color:var(--txt-3);margin-bottom:26px}
.idx-keys kbd{
  font-family:var(--mono);font-size:12px;border:1px solid var(--line);border-radius:6px;
  padding:2px 7px;margin-right:5px;background:var(--surface);
}
.idx-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:28px 34px}
.idx-group h3{font-size:13px;font-family:var(--mono);letter-spacing:.18em;text-transform:uppercase;
              color:var(--magenta);margin-bottom:11px}
.idx-item{
  display:grid;grid-template-columns:34px 1fr;gap:10px;width:100%;text-align:left;
  border:0;background:none;padding:7px 9px;border-radius:10px;font-size:17px;color:var(--txt-2);
  transition:.14s;
}
.idx-item:hover{background:var(--surface);color:var(--violeta)}
.idx-item.aqui{background:var(--violeta);color:#fff}
.idx-item .nn{font-family:var(--mono);font-size:12.5px;color:var(--txt-3)}
.idx-item.aqui .nn{color:rgba(255,255,255,.75)}

.tiny{display:none;position:fixed;inset:auto 0 62px 0;text-align:center;font-size:14px;color:var(--txt-3);padding:0 20px}
@media (max-width:640px) and (orientation:portrait){.tiny{display:block}}

/* Quien pida menos movimiento no lo tendrá: el contenido se lee igual, y los
   deslizadores siguen moviendo las cosas —eso es control, no animación—. */
@media (prefers-reduced-motion:reduce){
  .slide,.capa,.pila,.boton,.mp,.vt,.obs-dialogo{transition:none}
  .cintas path,.bolita,.cubo,.clon,.fila-off,.vt-pieza{animation:none!important}
  .qe-lista i,.qe-dolly .fondo,.qe-mask i,.qe-antic i,.qe-obscu .bg,.qe-obscu .tarj{animation:none!important}
  .cintas path{stroke-dashoffset:0}
  .fila-off,.qe-lista i,.qe-obscu .tarj{opacity:1;transform:none}
  .clon{transform:translate(-50%,-50%) scale(1);opacity:1}
}

/* Se reparte en papel, así que cada laboratorio tiene que dejar algo impreso:
   un interactivo que en papel deja un hueco en blanco está sin terminar. */
@media print{
  html,body{height:auto;overflow:visible;background:#fff}
  #escenario{position:static}
  #lienzo{position:static;margin:0;transform:none!important;width:100%;height:auto}
  .slide{position:static;display:block;opacity:1!important;visibility:visible!important;
         page-break-after:always;height:auto;min-height:0}
  .wrap{padding:22px 0}
  .dos,.dos.ancha-der,.ancha .dos.ancha-der{grid-template-columns:1fr 1fr;height:auto;gap:26px}
  .chrome.hud,.railbar,.tiny,.cintas,.index,.chip{display:none!important}
  /* En papel se imprime lo construido: un vídeo detenido no explica nada. */
  .pestanas,.panel-real{display:none!important}
  .taller{box-shadow:none;border:1px solid #ccc}
  .mando,.pie-mando{display:none}
  .fila-off,.clon{opacity:1!important;transform:translate(-50%,-50%) scale(1)!important}
  .fila-off{transform:none!important}
  .mapa-det{min-height:0}
  h1{font-size:52px}h2{font-size:38px}p{font-size:14.5px}
  .curva{page-break-inside:avoid}
}

/* ══════════ vertical ══════════
   Se abandona el lienzo y la lámina se recompone en una columna. Lo que sigue
   es lo que el módulo compartido no puede saber de esta presentación. */
@media (max-aspect-ratio:1/1){
  /* La dirección, que es la que faltaba. */
  .slide.on{flex-direction:column}
  /* Las cintas son adorno de esquina: en una columna estrecha solo estorban. */
  .cintas{display:none}
  .chip{
    align-self:flex-start;margin:0 0 18px -18px;padding:9px 20px;
    font-size:15px;border-radius:0 8px 8px 0;
  }
  .wrap{padding:0;display:block}

  /* Los titulares con techo propio: el módulo pone el suyo a h1, h2 y h3, pero
     estos tres son <div> y no los alcanza. */
  .portada .doce{font-size:min(88px,26vw);line-height:.9}
  .sep .grande{font-size:min(50px,15vw)}
  #lienzo .gracias h1{font-size:min(46px,13vw)}
  .portada .cred,.mapa-det p{font-size:16px}
  .eyebrow{font-size:13px;letter-spacing:.16em}
  .taller-cab{padding:13px 16px}
  .taller-cab h3{font-size:17px}
  .taller-cab .val{font-size:14px}
  .mando,.pie-mando{padding-left:16px;padding-right:16px}
  .mando.linea{padding:12px 16px 14px}

  /* Las demostraciones caben en menos alto; las que dependen del ancho para
     que se vea el viaje se quedan con todo el que hay. */
  .mask-caja,.clon-caja,.pad-caja,.obs-caja,.par-caja,.tra-caja{height:220px;margin:14px}
  .capas{height:240px;perspective:800px}
  .pila{width:180px;height:210px}
  .lista-off,.val-caja{height:auto}
  .pista-a{height:96px}
  .cubo{width:52px;height:52px}
  .quiz-esc{height:200px}
  .contador{font-size:56px}
  .padre{width:110px;height:110px;margin:-55px 0 0 -55px}
  .hijo{width:52px;height:52px}
  .obs-dialogo{width:min(300px,84%)}
  /* Sin esto la escena del parallax se traga el desplazamiento de la página. */
  .par-caja{touch-action:pan-y}

  /* La fila de la curva ya la colapsa el inyector; lo que hay que devolverle
     es el alto, porque el riel se queda sin sitio al apilarse. */
  .curva{padding:10px 16px;gap:6px}
  .riel-c{height:52px}
  .vt-lienzo{height:72px}
  /* El inyector colapsa toda rejilla a una columna con !important. Para estas
     dos, dos columnas se leen mucho mejor que doce tarjetas en fila india:
     el mapa entero pasa de 1 380 px de recorrido a 700. */
  #lienzo .slide .mapa,
  #lienzo .slide .vistazo{grid-template-columns:1fr 1fr!important;gap:10px}
  /* El panel de ejemplos deja de estar superpuesto: en columna no hay un alto
     que respetar, y superpuesto taparía el laboratorio recompuesto. */
  .panel-real{position:static;grid-template-columns:1fr;grid-template-rows:none;padding:16px}
  /* Y al dejar de estar superpuesto hay que apagar lo de debajo, o el
     laboratorio y los ejemplos salen uno detras de otro en la misma columna. */
  .cuerpo.real > :not(.panel-real){display:none}
  .panel-real video{height:200px;flex:none}
  .mapa-det{gap:14px;padding:16px 18px}
  .mapa-det .num{font-size:38px}

  /* El índice cuelga fuera de la lámina, así que las reglas que genera el
     inyector para «.slide .idx-grid» no lo alcanzan. */
  .index{padding:22px 16px 70px}
  .index h2{font-size:26px}
  .idx-grid{grid-template-columns:1fr;gap:20px}
  .idx-close{right:14px;top:14px}
}



/* CL-MEJORAS-INICIO */

/* ════════════════════════════════════════════════════════════
   REVELADO PROGRESIVO  ·  módulo compartido
   La barra espaciadora descubre los elementos de la diapositiva
   uno por uno. Las flechas siguen saltando de lámina completa.

   Los elementos se ocultan ANTES del primer pintado y solo se
   les añade la transición después, para que nunca se vea el
   parpadeo de aparecer y desaparecer.
   ════════════════════════════════════════════════════════════ */
.clf{opacity:0!important;transform:translateY(calc(.6 * var(--u, 10px)))}
.clf-t{transition:opacity .3s ease, transform .3s cubic-bezier(.22,.9,.3,1)}
@media (prefers-reduced-motion:reduce){.clf-t{transition:none}}

/* Durante el montaje se suprime TODA transición del documento. Sin esto,
   los elementos que ya traen una transición propia —los botones de los
   selectores, por ejemplo— se ven desvanecerse al cargar la página. */
body.clf-montando *{transition:none!important;animation-duration:0s!important}

/* indicador discreto de cuántos elementos quedan */
#clf-hint{
  position:fixed;left:50%;bottom:calc(52px + 10px);transform:translateX(-50%);
  z-index:60;display:flex;gap:5px;align-items:center;pointer-events:none;
  opacity:0;transition:opacity .25s ease
}
#clf-hint.on{opacity:.8}
#clf-hint i{
  width:6px;height:6px;border-radius:50%;display:block;
  background:currentColor;opacity:.26;transition:opacity .2s ease,transform .2s ease
}
#clf-hint i.done{opacity:1;transform:scale(1.25)}

/* ════════════════════════════════════════════════════════════
   AYUDA DE USO  ·  módulo compartido
   Vive en el cromo, nunca en la diapositiva: un botón en el HUD
   que abre el panel, y un aviso breve la primera vez que se abre
   la presentación en ese navegador.

   Los colores se toman de los tokens de cada presentación. Cada
   cadena de reserva prueba primero los nombres en inglés de las
   presentaciones antiguas y después los que usa el esqueleto del
   estándar, en español: sin eso, un mazo nuevo caía al #12161f de
   reserva con el color heredado, y en modo claro salía texto negro
   sobre panel negro.
   ════════════════════════════════════════════════════════════ */
#clf-ayuda-btn.clf-suelto{
  position:fixed;right:14px;bottom:58px;z-index:900;
  width:30px;height:30px;border-radius:50%;font-size:14px;line-height:1;
  background:var(--surface,var(--fondo-2,var(--bg-2,var(--bg2,transparent))));
  color:inherit;opacity:.55;
  border:1px solid var(--line,var(--linea,var(--line-soft,rgba(127,127,127,.4))))
}
#clf-ayuda-btn.clf-suelto:hover{opacity:1}

#clf-ayuda{
  position:fixed;inset:0;z-index:1000;display:grid;place-items:center;padding:24px;
  background:rgba(7,10,16,.55);opacity:0;transition:opacity .18s ease
}
/* Imprescindible: el atributo hidden no puede con un display de autor, y
   sin esta regla la capa se queda encima de la lámina, invisible, robando
   cada clic de los módulos interactivos. */
#clf-ayuda[hidden]{display:none}
#clf-ayuda.on{opacity:1}
@media (prefers-reduced-motion:reduce){#clf-ayuda{transition:none}}

#clf-ayuda .clf-panel{
  position:relative;width:min(520px,100%);max-height:88vh;overflow:auto;
  padding:26px 28px 24px;border-radius:10px;
  background:var(--surface,var(--fondo-2,var(--bg-2,var(--bg2,var(--bg,var(--fondo,#12161f))))));
  color:var(--txt,var(--texto,inherit));
  border:1px solid var(--line,var(--linea,var(--line-soft,var(--linea-suave,rgba(127,127,127,.35)))));
  box-shadow:0 12px 40px rgba(0,0,0,.28);
  font-family:var(--sans,system-ui,"Segoe UI",Arial,sans-serif);
  font-size:14px;line-height:1.5;text-align:left
}
#clf-ayuda h2{
  font-size:17px;line-height:1.25;margin:0 0 4px;font-weight:700;
  color:var(--txt,var(--texto,inherit));letter-spacing:0
}
#clf-ayuda .clf-sub{
  font-size:11px;letter-spacing:.16em;text-transform:uppercase;font-weight:700;
  color:var(--accent,var(--acento,var(--gold,currentColor)));margin:0 0 14px
}
#clf-ayuda dl{display:grid;grid-template-columns:auto 1fr;gap:10px 16px;margin:0;align-items:baseline}
#clf-ayuda dt{white-space:nowrap;display:flex;gap:4px}
#clf-ayuda dd{margin:0;color:var(--txt-2,var(--texto-2,var(--dim,inherit)))}
#clf-ayuda .clf-pie{
  margin:16px 0 0;padding-top:14px;font-size:12.5px;
  border-top:1px solid var(--line-soft,var(--linea-suave,var(--line,var(--linea,rgba(127,127,127,.25)))));
  color:var(--txt-3,var(--texto-3,var(--dim,inherit)))
}
#clf-ayuda .clf-cerrar{
  position:absolute;top:10px;right:12px;font-size:20px;line-height:1;
  padding:4px 6px;opacity:.5;background:none;border:0;color:inherit;cursor:pointer
}
#clf-ayuda .clf-cerrar:hover{opacity:1}

#clf-ayuda kbd,#clf-onboard kbd{
  font-family:var(--mono,ui-monospace,Consolas,monospace);font-size:11.5px;
  padding:2px 6px;border-radius:4px;white-space:nowrap;
  border:1px solid var(--line,var(--linea,var(--line-soft,rgba(127,127,127,.45))));
  background:var(--surface-2,var(--fondo-3,var(--bg-2,var(--bg2,transparent))));
  color:var(--txt,var(--texto,inherit))
}

/* aviso de la primera visita */
#clf-onboard{
  position:fixed;left:50%;bottom:84px;transform:translateX(-50%) translateY(8px);
  z-index:900;width:min(430px,calc(100vw - 32px));
  padding:14px 16px;border-radius:9px;
  background:var(--surface,var(--fondo-2,var(--bg-2,var(--bg2,var(--bg,var(--fondo,#12161f))))));
  color:var(--txt,var(--texto,inherit));
  border:1px solid var(--line,var(--linea,var(--line-soft,var(--linea-suave,rgba(127,127,127,.35)))));
  box-shadow:0 8px 28px rgba(0,0,0,.22);
  font-family:var(--sans,system-ui,"Segoe UI",Arial,sans-serif);
  font-size:13px;line-height:1.45;
  opacity:0;transition:opacity .3s ease,transform .3s ease
}
#clf-onboard.on{opacity:1;transform:translateX(-50%) translateY(0)}
@media (prefers-reduced-motion:reduce){#clf-onboard{transition:none}}
#clf-onboard p{margin:0 0 4px}
#clf-onboard p:last-of-type{margin:0}
#clf-onboard .clf-acciones{display:flex;gap:14px;align-items:center;margin-top:12px}
#clf-onboard button{
  font:inherit;cursor:pointer;border:0;background:none;color:inherit;padding:0
}
#clf-onboard .clf-ok{
  padding:5px 12px;border-radius:5px;font-weight:600;font-size:12.5px;
  background:var(--accent,var(--acento,var(--gold,currentColor)));
  color:var(--onaccent,var(--bg,var(--fondo,#fff)))
}
#clf-onboard .clf-todo{font-size:12.5px;opacity:.7;text-decoration:underline}
#clf-onboard .clf-todo:hover{opacity:1}

/* fuera del sitio autorizado no se pinta nada del cromo añadido */
.cl-lock #clf-ayuda-btn,.cl-lock #clf-ayuda,.cl-lock #clf-onboard,.cl-lock #clf-hint{display:none!important}
@media print{#clf-ayuda-btn,#clf-ayuda,#clf-onboard{display:none!important}}

/* ════════════════════════════════════════════════════════════
   VERTICAL · módulo compartido

   Los motores de lienzo fijo escalan un rectángulo de 1280×720 o
   1600×900 al hueco disponible. En un teléfono de pie ese hueco es
   el ancho, y la escala se desploma: medido en IEL con una ventana
   de 375×812, el lienzo quedaba en 375×211 y el cuerpo del texto en
   4.2 px. Ilegible, y encogerlo mejor no existe.

   Así que en vertical se abandona el lienzo. Las láminas dejan de
   estar superpuestas, pasan al flujo normal, se recomponen en una
   columna y la página se desplaza. La tipografía recupera su tamaño
   de diseño —14.5 px de cuerpo, que en un teléfono está bien— porque
   ya no la encoge ninguna transformación.

   El colapso de las rejillas no está aquí: lo genera el inyector
   leyendo la hoja de cada presentación, porque cada una nombra sus
   columnas a su manera.
   ════════════════════════════════════════════════════════════ */
@media (max-aspect-ratio:1/1){

  html,body{overflow-x:hidden;overflow-y:auto;height:auto}

  /* El escenario deja de ser una ventana fija y el lienzo, un lienzo. */
  /* Los cuatro primeros nombres son los de las presentaciones que ya
     existian; #escenario y #lienzo son los que usa el esqueleto del
     estandar, y sin ellos un mazo nuevo escrito segun el documento se
     queda con el lienzo escalado: la tipografia cambia de tamano pero la
     transformacion sigue puesta, asi que en el telefono se ve igual de
     pequena y parece que el modulo funciona cuando no ha entrado. */
  .stage,#viewport,#escenario{position:static;display:block;width:100%}
  .deck,#stage,#lienzo{
    position:static;left:auto;top:auto;margin:0;
    width:100%;max-width:100%;height:auto;min-height:100dvh;
    /* «!important» porque la funcion de ajuste sigue escribiendo la
       transformacion en el atributo de estilo en cada redimension. */
    transform:none!important;
    border:0;box-shadow:none;border-radius:0;
  }

  /* Las láminas dejan de estar una encima de otra. */
  .slide{
    position:static;inset:auto;
    opacity:1;visibility:visible;transform:none;
    display:none;width:100%;max-width:100%;
    padding:22px 18px 88px;
    overflow-wrap:anywhere;
  }
  .slide.on,.slide.is-active{display:flex}

  /* Sin esto, un hijo flex no baja de su contenido y desborda. */
  .slide *{min-width:0}
  .slide > *{max-width:100%}
  .slide [class*="badge"],.slide .tag{flex-wrap:wrap;max-width:100%}
  .body{justify-content:flex-start}

  /* Algunas rejillas se declaran en el atributo de estilo, donde la
     extraccion de selectores del inyector no las ve. Se alcanzan por
     atributo: «!important» gana a un estilo en linea normal. */
  .slide [style*="grid-template-columns"]{grid-template-columns:1fr!important}

  /* Un titular de 60 px es de proyector, no de telefono: en una columna de
     320 px no cabe ni la primera palabra y se parte a lo bruto —el
     navegador no guiona en espanol, se probo—. Se le pone un techo
     relativo al marco, que es lo que hace DPGA al crecer su unidad. */
  .slide h1{font-size:min(34px,10vw)}
  .slide h2{font-size:min(26px,7.5vw)}
  .slide h3{font-size:min(20px,6vw)}

  /* Y el cuerpo tambien, por la razon contraria. Como aqui se abandona el
     lienzo, las medidas de diseno se usan tal cual, asi que el tamano del
     lienzo decidia a que tamano se lee en un telefono: medido, las de 1280
     quedaban en 13 px —pequeno— y las de 1600 en 22 —grande y con lineas de
     26 caracteres—. Con esta horquilla las tres familias caen en 17-18 px y
     30-36 caracteres, y el lienzo deja de tener consecuencia. */
  .slide p,.slide li,.slide td,.slide th{font-size:clamp(15px,4.8vw,18px)}

  /* Una tabla de ocho o diez columnas no se recompone en una: se
     comprime hasta partir las palabras letra a letra. Se le deja su
     ancho natural y su propio desplazamiento lateral. */
  .slide table{
    display:block;max-width:100%;
    overflow-x:auto;overflow-y:hidden;overflow-wrap:normal;
  }
  .slide table td,.slide table th{white-space:nowrap;overflow-wrap:normal}

  /* El aviso de «esto es de pantalla horizontal» deja de ser cierto
     en cuanto la lámina se recompone. */
  .tiny{display:none!important}
}

/* El cromo absoluto de la lamina, al flujo. */
@media (max-aspect-ratio:1/1){
.slide > #lienzo,
.slide > .slide,
.slide > /* ── las cintas del original,
.slide > redibujadas y animadas ── stroke-dasharray al largo del trazo y dashoffset animado: la cinta se traza sola al entrar en la lámina,
.slide > no al cargar la presentación. */ .cintas,
.slide > .cintas svg,
.slide > /* ── rótulo,
.slide > como en el original ── */ .chip,
.slide > .riel-c::before,
.slide > .pista-a::before,
.slide > .mask-obj,
.slide > .mask-borde,
.slide > .capa,
.slide > .clon,
.slide > .escena,
.slide > /* La rejilla NO está en el espacio 3D. Cuando el suelo era un plano rotado,
.slide > su borde lejano subía hacia el punto de fuga y acababa cruzando por delante del sujeto: las líneas se le montaban encima. Dibujada en SVG y confinada a la banda inferior,
.slide > sugiere la profundidad sin poder cruzarse con nada. */ .rejilla,
.slide > .sujeto,
.slide > .poste,
.slide > .lectura-cam,
.slide > .padre,
.slide > .hijo,
.slide > .linea-pad,
.slide > .obs-fondo,
.slide > .obs-velo,
.slide > .obs-dialogo,
.slide > .par-capa,
.slide > .par-capa .pieza,
.slide > .par-luna,
.slide > .par-eti,
.slide > .tra-eti,
.slide > .tra-cuerpo,
.slide > .aguja i,
.slide > .vt-pieza,
.slide > /* ── las escenas del cuestionario ── También construidas en CSS. Preguntar por un principio enseñando un GIF sería contradecir la presentación entera. */ .qe-lista,
.slide > .qe-dolly,
.slide > .qe-mask,
.slide > .qe-antic,
.slide > .qe-obscu,
.slide > .qe-dolly .fondo,
.slide > .qe-antic i,
.slide > .qe-obscu .tarj,
.slide > .lista-p li::before{position:static}
}

/* Lo que no se puede partir, con desplazamiento propio. */
@media (max-aspect-ratio:1/1){
.slide .mando.linea label,
.slide .obs-dialogo .boton,
.slide .hud-title{max-width:100%;overflow-x:auto}
}

/* Rejillas de esta presentacion, a una columna. */
@media (max-aspect-ratio:1/1){
.slide .dos,
.slide .dos.ancha-der,
.slide .ancha .dos.ancha-der,
.slide .mando.linea,
.slide .mando.dosc,
.slide .curva,
.slide .fila-off,
.slide /* ══════════ mapa de los doce ══════════ */ .mapa,
.slide .mapa-det,
.slide .sep-lista,
.slide /* ══════════ repaso: los doce de un vistazo ══════════ */ .vistazo,
.slide /* ══════════ cuestionario ══════════ */ .quiz,
.slide /* ══════════ listas de cierre ══════════ */ .tarjetas,
.slide .dosl,
.slide .idx-grid,
.slide .idx-item{grid-template-columns:1fr!important}
}

/* CL-MEJORAS-FIN */