/* =====================================================================
   MOTOR DE SCROLL CINEMATOGRAFICO
   ---------------------------------------------------------------------
   Usa animaciones CSS conducidas por scroll (animation-timeline). A
   diferencia de un IntersectionObserver, que solo DISPARA una animacion,
   aqui el progreso de la animacion ESTA ENLAZADO a la posicion del scroll:
   el usuario retrocede y la animacion retrocede con el.

   Ventaja tecnica decisiva: corre en el hilo del compositor, no en el
   principal. No hay listener de scroll, no hay jank, y se mantiene a
   60fps aunque el hilo principal este ocupado.

     view()   -> progreso del elemento al cruzar la ventana
     scroll() -> progreso de scroll de un contenedor

   Respaldo: donde no hay soporte (Safari, Firefox), scroll.js aplica el
   mismo efecto con rAF. La clase html.has-sdt distingue ambos caminos.
   ===================================================================== */

/* Registrada para poder entrar en un calc() dentro de animation-range:
   una propiedad personalizada sin tipo declarado se trata como cadena y el
   calculo no llega a resolverse. */
@property --cine-index{ syntax:'<number>'; inherits:false; initial-value:0; }

@supports (animation-timeline: view()){
  html.has-sdt [data-sc]{
    animation-timeline:view();
    animation-fill-mode:both;
    animation-timing-function:linear;   /* el scroll marca el ritmo */
  }

  /* ---------------- ENTRADA: aparece al cruzar el borde inferior ----- */
  html.has-sdt [data-sc="rise"]{
    animation-name:scRise;
    animation-range:entry 5% cover 26%;
  }
  @keyframes scRise{
    from{opacity:0;transform:translate3d(0,42px,0)}
    to  {opacity:1;transform:none}
  }

  html.has-sdt [data-sc="fade"]{
    animation-name:scFade;
    animation-range:entry 5% cover 22%;
  }
  @keyframes scFade{from{opacity:0}to{opacity:1}}

  html.has-sdt [data-sc="scale"]{
    animation-name:scScale;
    animation-range:entry 2% cover 30%;
  }
  @keyframes scScale{
    from{opacity:0;transform:translate3d(0,30px,0) scale(.94)}
    to  {opacity:1;transform:none}
  }

  /* Entrada que no toca la opacidad. Para un bloque que se apoya sobre la
     union de dos secciones: mientras fuese translucido dejaria ver esa
     union a traves de si mismo y la seccion se leeria partida. Solo se
     desplaza. */
  html.has-sdt [data-sc="lift"]{
    animation-name:scLift;
    animation-range:entry 5% cover 26%;
  }
  @keyframes scLift{
    from{transform:translate3d(0,26px,0) scale(.985)}
    to  {transform:none}
  }

  html.has-sdt [data-sc="left"]{
    animation-name:scLeft;
    animation-range:entry 5% cover 28%;
  }
  @keyframes scLeft{
    from{opacity:0;transform:translate3d(-48px,0,0)}
    to  {opacity:1;transform:none}
  }

  html.has-sdt [data-sc="right"]{
    animation-name:scRight;
    animation-range:entry 5% cover 28%;
  }
  @keyframes scRight{
    from{opacity:0;transform:translate3d(48px,0,0)}
    to  {opacity:1;transform:none}
  }

  /* ------------- SALIDA: el hero cede el paso a la siguiente seccion -- */
  /* El titulo escala y se difumina conforme el hero abandona la ventana.
     Es la transicion de seccion pedida: una capa entrega a la siguiente. */
  html.has-sdt [data-sc="hero-exit"]{
    animation-name:scHeroExit;
    animation-range:exit 0% exit 92%;
  }
  @keyframes scHeroExit{
    from{opacity:1;transform:none;filter:blur(0)}
    to  {opacity:0;transform:translate3d(0,-56px,0) scale(.92);filter:blur(7px)}
  }

  html.has-sdt [data-sc="hero-fade"]{
    animation-name:scHeroFade;
    animation-range:exit 0% exit 55%;
  }
  @keyframes scHeroFade{
    from{opacity:1;transform:none}
    to  {opacity:0;transform:translate3d(0,-26px,0)}
  }

  /* ------------------------- PARALLAX POR CAPAS ---------------------- */
  /* Velocidades distintas por profundidad. Recorridos cortos a proposito:
     el parallax exagerado marea y desalinea el contenido. */
  html.has-sdt [data-sc-parallax]{
    animation-name:scParallax;
    animation-timeline:view();
    animation-range:cover 0% cover 100%;
    animation-timing-function:linear;
    animation-fill-mode:both;
  }
  @keyframes scParallax{
    from{transform:translate3d(0,calc(var(--sc-depth,1) * -26px),0)}
    to  {transform:translate3d(0,calc(var(--sc-depth,1) *  26px),0)}
  }

  /* -------------------- BARRA DE PROGRESO DE LECTURA ----------------- */
  html.has-sdt .scroll-progress__bar{
    animation-name:scProgress;
    animation-timeline:scroll(root block);
    animation-timing-function:linear;
    animation-fill-mode:both;
    transform-origin:0 50%;
  }
  @keyframes scProgress{from{transform:scaleX(0)}to{transform:scaleX(1)}}

}

/* =====================================================================
   ESTADO INICIAL Y RESPALDO
   ===================================================================== */
/* Sin JavaScript (html sin .js) el contenido se ve completo: los estados
   ocultos solo existen cuando el motor esta activo. */
html.js.has-sdt [data-sc]{opacity:0}
html.js.has-sdt [data-sc="lift"]{opacity:1}

/* Estado base de la escena fija.
   Una animacion conducida por scroll NO aplica su relleno mientras su
   linea de tiempo esta inactiva —es decir, mientras el sujeto aun no
   entra en la ventana—. Sin este estado base los tres actos se pintarian
   superpuestos al llegar a la seccion. Con el, el primero espera visible
   y los otros dos ocultos, que es justo el fotograma del 0%. */
html.js.has-sdt [data-sc="hero-exit"],
html.js.has-sdt [data-sc="hero-fade"]{opacity:1}

/* Camino de respaldo (sin animation-timeline): scroll.js aplica el efecto. */
html.js.no-sdt [data-sc]{
  opacity:0;
  transform:translate3d(0,34px,0);
  transition:opacity .55s var(--ease-decel),transform .55s var(--ease-decel);
}
html.js.no-sdt [data-sc="fade"]{transform:none}
html.js.no-sdt [data-sc="left"]{transform:translate3d(-40px,0,0)}
html.js.no-sdt [data-sc="right"]{transform:translate3d(40px,0,0)}
html.js.no-sdt [data-sc="scale"]{transform:translate3d(0,26px,0) scale(.95)}
html.js.no-sdt [data-sc="hero-exit"],
html.js.no-sdt [data-sc="hero-fade"]{opacity:1;transform:none;transition:none}
html.js.no-sdt [data-sc="lift"]{opacity:1;transform:translate3d(0,26px,0) scale(.985)}
html.js.no-sdt [data-sc].is-in{opacity:1;transform:none}

/* =====================================================================
   COMPONENTES DE LA EXPERIENCIA
   ===================================================================== */

/* ------------------------ PROGRESO DE LECTURA ----------------------- */
.scroll-progress{
  position:fixed;top:0;left:0;right:0;height:3px;z-index:900;
  pointer-events:none;background:transparent;
}
.scroll-progress__bar{
  height:100%;width:100%;transform:scaleX(0);transform-origin:0 50%;
  background:linear-gradient(90deg,var(--primary),var(--accent));
}

/* ----------------------------- NAVBAR ------------------------------- */
/* Solo la portada tiene un hero oscuro a pantalla completa, asi que solo
   ella recibe --floating.

   La barra transparente es el estado EXCEPCIONAL (clase .is-top), no el
   estado por defecto. Si el observador no llega a ejecutarse —pestana en
   segundo plano, JavaScript bloqueado, error de red— la barra se queda
   solida y legible, en vez de quedarse transparente con texto blanco
   sobre un fondo claro. El fallo cae del lado que se puede leer. */
.pubnav--floating{
  transition:background var(--dur-base) var(--ease-standard),
             border-color var(--dur-base) var(--ease-standard),
             box-shadow var(--dur-base) var(--ease-standard);
}
html.js .pubnav--floating.is-top{
  background:transparent;border-bottom-color:transparent;box-shadow:none;
}
html.js .pubnav--floating:not(.is-top){
  background:var(--glass);
  backdrop-filter:saturate(180%) blur(16px);
  -webkit-backdrop-filter:saturate(180%) blur(16px);
  border-bottom-color:var(--border);
  box-shadow:var(--shadow-sm);
}
/* Sobre el hero oscuro, lo que se apoya DIRECTAMENTE en el hero va en
   claro. La marca y el boton de menu siempre; los enlaces solo cuando
   estan en la fila (>=860px). */
html.js .pubnav--floating.is-top .pubnav__title{color:#fff}
html.js .pubnav--floating.is-top .pubnav__sub{color:rgba(255,255,255,.72)}
html.js .pubnav--floating.is-top .pubnav__burger{
  color:rgba(255,255,255,.9);border-color:rgba(255,255,255,.3);
}
html.js .pubnav--floating.is-top .pubnav__burger:hover,
html.js .pubnav--floating.is-top .pubnav__burger[aria-expanded="true"]{
  background:rgba(255,255,255,.16);color:#fff;
}

/* Por debajo de 860px los enlaces viven en un panel desplegable con
   fondo propio (--surface). Aplicarles el texto claro del hero los
   dejaria en blanco sobre blanco: el panel se abriria vacio. De ahi que
   estas reglas esten acotadas al ancho en que los enlaces si estan
   apoyados sobre el hero. */
@media (min-width:860px){
  html.js .pubnav--floating.is-top .pubnav__link{color:rgba(255,255,255,.88)}
  html.js .pubnav--floating.is-top .pubnav__link:hover{background:rgba(255,255,255,.14);color:#fff}
  html.js .pubnav--floating.is-top .pubnav__link.is-active{background:rgba(255,255,255,.18);color:#fff}
  html.js .pubnav--floating.is-top .btn--ghost{
    background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.32);color:#fff;
  }
  html.js .pubnav--floating.is-top .theme-toggle{
    color:rgba(255,255,255,.88);border-color:rgba(255,255,255,.28);
  }
  html.js .pubnav--floating.is-top .theme-toggle:hover{background:rgba(255,255,255,.14)}
}

/* -------------------- SECCION FIJA (sticky) ------------------------- */
/* La seccion mide varias pantallas; su interior queda fijo mientras el
   scroll la recorre y los tres actos se relevan. Al terminar, el scroll
   continua con normalidad. */
/* =====================================================================
   ESCENA DE TRES ACTOS
   ---------------------------------------------------------------------
   Los actos se relevan solos cada 5 s. Antes la seccion media 300vh y el
   relevo lo marcaba el scroll: eran tres pantallas de recorrido para leer
   tres frases. Ahora ocupa una sola pantalla.

   El motor esta en public/assets/js/stage.js. Lo que aqui se define es
   como se ve cada estado; el JS solo pone y quita .is-active.
   ===================================================================== */
.stage{
  position:relative;
  padding-block:var(--space-7);
  display:grid;place-items:center;
  min-height:min(560px,78svh);
}

.stage__viewport{
  position:relative;width:100%;
  display:grid;
  align-items:center;
}

.stage-layer{
  grid-area:1 / 1;                      /* los tres actos se superponen */
  display:grid;place-items:center;align-content:center;
  padding:var(--space-5) var(--space-4);text-align:center;
  max-width:min(920px,92vw);
  margin-inline:auto;

  /* Fuera del turno: apagado y sin recibir foco ni lectura. El JS pone
     ademas inert/aria-hidden; esto es la parte visual. */
  opacity:0;
  transform:translate3d(0,18px,0);
  visibility:hidden;
  transition:opacity var(--dur-slow) var(--ease-decel),
             transform var(--dur-slow) var(--ease-decel),
             visibility 0s linear var(--dur-slow);
}
.stage-layer.is-active{
  opacity:1;transform:none;visibility:visible;
  transition-delay:0s;
}

/* Sin JavaScript no hay relevo posible: se muestran los tres, uno debajo
   de otro. La informacion no depende del movimiento. */
html:not(.js) .stage-layer{
  grid-area:auto;opacity:1;transform:none;visibility:visible;
  padding-block:var(--space-6);
}

.stage-layer__step{
  display:inline-flex;align-items:center;gap:.5rem;
  font-size:.76rem;font-weight:620;letter-spacing:.09em;text-transform:uppercase;
  color:var(--primary);margin-bottom:1.1rem;
}
.stage-layer__step i{
  width:22px;height:22px;border-radius:50%;display:grid;place-items:center;
  background:var(--primary-50);color:var(--primary);font-style:normal;font-size:.72rem;
}
.stage-layer__note{
  margin-top:1.4rem;font-size:1rem;line-height:1.75;color:var(--text-2);
  max-width:56ch;margin-inline:auto;
}
.stage-layer__note b{color:var(--text);font-weight:640}

/* --------------------------- CONTROLES ------------------------------ */
/* Contenido que se mueve solo necesita una forma de pararlo (WCAG 2.2.2).
   De ahi el boton de pausa y que cada punto sea pulsable. */
.stage-controls{
  display:flex;align-items:center;justify-content:center;gap:.75rem;
  margin-top:var(--space-6);
}
html:not(.js) .stage-controls{display:none}

.stage-dots{display:flex;gap:.5rem}
.stage-dot{
  width:34px;height:4px;border-radius:2px;border:0;padding:0;cursor:pointer;
  background:var(--border-strong);position:relative;overflow:hidden;
  transition:background var(--dur-fast) var(--ease-standard);
}
.stage-dot:hover{background:var(--text-3)}
.stage-dot::after{
  content:'';position:absolute;inset:0;transform-origin:0 50%;transform:scaleX(0);
  background:linear-gradient(90deg,var(--primary),var(--accent));
}
/* La barra se llena durante el turno del acto: el usuario ve cuanto le
   queda antes de que pase solo.

   Se dispara con la clase .is-running, que pone stage.js al arrancar el
   temporizador, y NO con aria-current: ese atributo ya viene escrito en el
   marcado del primer punto, asi que la barra empezaba a llenarse al cargar
   la pagina aunque la escena estuviera fuera de la vista y el relevo no
   hubiera arrancado. Lo que se veia no era el tiempo que faltaba. */
.stage-dot.is-running::after{
  /* El valor real lo fija stage.js en --stage-delay; este 5s es solo el
     respaldo si la variable no llegara a escribirse. */
  animation:stageDot var(--stage-delay,5s) linear forwards;
}
/* El punto en turno se distingue aunque su barra este parada. */
.stage-dot[aria-current="true"]{background:var(--text-3)}
.stage.is-paused .stage-dot.is-running::after{
  animation-play-state:paused;
}
@keyframes stageDot{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* Area tactil de 44px sin engordar la barra (Apple HIG). */
.stage-dot{position:relative}
.stage-dot::before{
  content:'';position:absolute;left:0;right:0;top:50%;
  height:44px;transform:translateY(-50%);
}

.stage-toggle{
  width:34px;height:34px;flex-shrink:0;
  display:grid;place-items:center;cursor:pointer;
  border:1px solid var(--border);border-radius:var(--radius-sm);
  background:transparent;color:var(--text-2);
  transition:background var(--dur-fast) var(--ease-standard),
             color var(--dur-fast) var(--ease-standard);
}
.stage-toggle:hover{background:var(--surface-3);color:var(--text)}
.stage-toggle svg{width:15px;height:15px;display:block}
.stage-toggle__pausa{display:block}
.stage-toggle__play{display:none}
.stage-toggle[aria-pressed="true"] .stage-toggle__pausa{display:none}
.stage-toggle[aria-pressed="true"] .stage-toggle__play{display:block}

/* Quien pide menos movimiento no recibe un relevo automatico: se muestra
   el primer acto y se navega con los puntos. */
@media (prefers-reduced-motion: reduce){
  .stage-layer{transition:none}
  .stage-dot[aria-current="true"]::after{animation:none;transform:scaleX(1)}
  .stage-dot.is-running::after{animation:none;transform:scaleX(1)}
}

/* ---------------------- TEXTO CINEMATOGRAFICO ----------------------- */
.cine-line{
  font-size:clamp(2rem,7vw,4.6rem);font-weight:730;
  letter-spacing:-.035em;line-height:1.04;
  max-width:16ch;margin-inline:auto;
  /* El reset global aplica p{color:var(--text-2)} como regla directa, que
     vence a cualquier color heredado. El titular declara el suyo. */
  color:var(--text);
}
.cine-line em{
  font-style:normal;
  background:linear-gradient(100deg,var(--primary-500),var(--accent));
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
/* Cada palabra entra por separado: el retardo lo fija el marcado. */
.cine-word{display:inline-block;will-change:transform,opacity}

/* ------------------------------ CAPAS ------------------------------- */
.layer{position:absolute;inset:0;pointer-events:none}
.layer--back{--sc-depth:.45}
.layer--mid{--sc-depth:.8}
.layer--front{--sc-depth:1.3}

/* =====================================================================
   PREFERENCIA DE MOVIMIENTO REDUCIDO
   Se retira TODO el movimiento ligado al scroll; el contenido queda
   visible y estatico, que es lo que la preferencia solicita.
   ===================================================================== */
@media (prefers-reduced-motion: reduce){
  html [data-sc],
  html [data-sc-parallax],
  html .scroll-progress__bar,
  html .cine-word{
    animation:none !important;
    transition:none !important;
    opacity:1 !important;
    transform:none !important;
    filter:none !important;
  }
  .scroll-progress{display:none}
  .stage-layer{grid-area:auto;margin-inline:auto;padding-block:var(--space-6)}
  html.js .pubnav--floating.is-top{background:var(--surface);border-bottom-color:var(--border)}
  html.js .pubnav--floating.is-top .pubnav__title{color:var(--text)}
  html.js .pubnav--floating.is-top .pubnav__link{color:var(--text-2)}
  html.js .pubnav--floating.is-top .pubnav__burger{color:var(--text-2);border-color:var(--border)}
  html.js .pubnav--floating.is-top .btn--ghost{background:transparent;border-color:var(--border);color:var(--text-2)}
}


/* -------------------------- TARJETAS -------------------------------- */
/* Rejilla normal: las cuatro caben de una mirada y el scroll de la pagina
   no cambia de eje a mitad del recorrido. */
.hcards{
  margin-top:var(--space-5);
  /* 240px, no los 200px del .grid-4 generico: con cuatro parrafos de tres
     lineas, por debajo de ese ancho el texto se parte demasiado. Cuatro
     columnas en escritorio, dos en tableta, una en movil. */
  grid-template-columns:repeat(auto-fit,minmax(min(240px,100%),1fr));
}
.hcard{
  background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius-lg);padding:var(--space-5);height:100%;
  display:flex;flex-direction:column;gap:.75rem;
  box-shadow:var(--shadow-sm);
  transition:transform var(--dur-base) var(--ease-standard),
             box-shadow var(--dur-base) var(--ease-standard),
             border-color var(--dur-base) var(--ease-standard);
}
.hcard:hover{
  transform:translateY(-4px);
  box-shadow:var(--shadow-lg);
  border-color:var(--primary-200);
}
@media (prefers-reduced-motion: reduce){
  .hcard{transition:none}
  .hcard:hover{transform:none}
}
.hcard__num{
  font-size:.75rem;font-weight:680;letter-spacing:.1em;color:var(--primary);
}
.hcard__icon{
  width:44px;height:44px;border-radius:var(--radius-sm);display:grid;place-items:center;
  background:var(--primary-50);color:var(--primary);
}
.hcard h3{font-size:1.05rem;font-weight:650;letter-spacing:-.015em}
.hcard p{font-size:.9rem;line-height:1.7;color:var(--text-2);margin:0}


/* --------------------------- SENAL DE SCROLL ------------------------ */
.scroll-cue{
  position:absolute;left:50%;bottom:1.7rem;transform:translateX(-50%);
  display:inline-flex;flex-direction:column;align-items:center;gap:.45rem;
  font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(255,255,255,.62);pointer-events:none;
}
.scroll-cue__line{
  width:1px;height:34px;background:linear-gradient(180deg,rgba(255,255,255,.5),transparent);
  animation:cueDrop 2.1s var(--ease-standard) infinite;
}
@keyframes cueDrop{
  0%  {transform:scaleY(0);transform-origin:50% 0}
  45% {transform:scaleY(1);transform-origin:50% 0}
  46% {transform:scaleY(1);transform-origin:50% 100%}
  100%{transform:scaleY(0);transform-origin:50% 100%}
}
@media (prefers-reduced-motion: reduce){.scroll-cue__line{animation:none;transform:scaleY(1)}}

/* En movil el bloque de cifras sube sobre el hero (margin-top negativo) y
   se planta justo encima de la senal: se veia la palabra DESPLACE cortada
   por detras de la tarjeta. Ahi sobra: en un telefono nadie duda de que la
   pagina se desplaza. */
@media (max-width:767px){
  .scroll-cue{display:none}
}

/* -------------------- HERO BAJO LA NAVBAR FLOTANTE ------------------ */
/* La navbar flota sobre el hero, asi que el hero recupera su altura y
   compensa con relleno para que el titulo no quede debajo de la barra. */
.hero--under-nav{
  --hero-fade:140px;
  margin-top:-68px;
  padding-top:calc(68px + 5.5rem);
  padding-bottom:6rem;
  min-height:100svh;
  display:flex;align-items:center;
}
@media (max-width:640px){
  .hero--under-nav{
    --hero-fade:100px;
    padding-top:calc(68px + 3.2rem);
    padding-bottom:4.5rem;
  }
}

/* Capas de profundidad del hero. Recorridos cortos: el parallax marcado
   desalinea el texto y marea. */
/* Sin sangrado lateral negativo: a 320px anadia 26px al ancho del
   documento y aparecia scroll horizontal. El margen extra que necesitan
   los halos se toma solo en vertical, que no afecta al ancho. */
.hero__layers{position:absolute;inset:-12% 0;z-index:-1;pointer-events:none;overflow:hidden}
.hero__blob{
  position:absolute;border-radius:50%;filter:blur(58px);opacity:.5;
  will-change:transform;
}
.hero__blob--a{width:44vw;height:44vw;left:-6%;top:-8%;background:rgba(56,189,248,.34);--sc-depth:.5}
.hero__blob--b{width:38vw;height:38vw;right:-4%;bottom:-10%;background:rgba(45,212,191,.30);--sc-depth:1}
.hero__blob--c{width:26vw;height:26vw;left:38%;top:42%;background:rgba(99,102,241,.24);--sc-depth:1.5}

/* =====================================================================
   CAPA DE ENVIO
   Los estados que muestra son reales (validacion, bytes subidos,
   respuesta del servidor); ver submit-flow.js.
   ===================================================================== */
.flow{
  position:fixed;inset:0;z-index:1200;display:grid;place-items:center;
  background:var(--scrim);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);
  opacity:0;transition:opacity var(--dur-base) var(--ease-standard);
}
.flow.is-open{opacity:1}
.flow__panel{
  background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius-lg);box-shadow:var(--shadow-xl);
  padding:var(--space-6) var(--space-6) var(--space-5);
  width:min(340px,88vw);text-align:center;
  transform:translate3d(0,14px,0) scale(.97);
  transition:transform var(--dur-slow) var(--ease-spring);
}
.flow.is-open .flow__panel{transform:none}

.flow__mark{width:56px;height:56px;margin:0 auto var(--space-4)}
.flow__mark svg{width:100%;height:100%;fill:none;stroke-linecap:round;stroke-linejoin:round}
.flow__ring{
  stroke:var(--primary);stroke-width:2.4;opacity:.35;
  stroke-dasharray:36 108;transform-origin:50% 50%;
  animation:flowSpin 1.05s linear infinite;
}
.flow__tick{
  stroke:var(--success);stroke-width:3.4;
  stroke-dasharray:40;stroke-dashoffset:40;
}
@keyframes flowSpin{to{transform:rotate(360deg)}}

/* Al confirmar, el anillo deja de girar, se completa y se traza la marca. */
.flow.is-done .flow__ring{
  animation:none;stroke:var(--success);opacity:1;stroke-dasharray:145;
  transition:stroke-dasharray var(--dur-slow) var(--ease-decel);
}
.flow.is-done .flow__tick{
  stroke-dashoffset:0;
  transition:stroke-dashoffset .42s var(--ease-decel) .16s;
}

.flow__title{font-size:1.02rem;font-weight:640;color:var(--text);margin-bottom:.3rem}
.flow__step{font-size:.865rem;color:var(--text-2);min-height:1.35em;
  font-variant-numeric:tabular-nums;margin-bottom:var(--space-4)}
.flow__bar{height:4px;border-radius:2px;background:var(--surface-3);overflow:hidden}
.flow__bar span{
  display:block;height:100%;transform:scaleX(0);transform-origin:0 50%;
  background:linear-gradient(90deg,var(--primary),var(--accent));
  transition:transform .3s var(--ease-decel);
}

@media (prefers-reduced-motion: reduce){
  .flow,.flow__panel{transition:none}
  .flow__ring{animation:none}
  .flow__tick{transition:none}
  .flow__bar span{transition:none}
}

/* =====================================================================
   LINEA DE TIEMPO DEL PQR / DEL CASO
   ---------------------------------------------------------------------
   El hilo se traza al ritmo del scroll y cada hito aparece al alcanzarlo.
   No es adorno: el trazo comunica que los estados ocurrieron en ese
   orden, que es exactamente lo que la lista representa.
   ===================================================================== */
@supports (animation-timeline: view()){
  html.has-sdt .timeline{
    view-timeline-name:--tl;
    view-timeline-axis:block;
  }
  /* El hilo crece de arriba abajo mientras la lista cruza la ventana. */
  html.has-sdt .timeline::before{
    transform-origin:50% 0;
    animation-name:tlThread;
    animation-timeline:--tl;
    animation-range:entry 30% cover 62%;
    animation-timing-function:linear;
    animation-fill-mode:both;
  }
  @keyframes tlThread{from{transform:scaleY(0)}to{transform:scaleY(1)}}

  html.has-sdt .timeline__item{
    animation-name:tlItem;
    animation-timeline:view();
    animation-range:entry 8% cover 24%;
    animation-timing-function:linear;
    animation-fill-mode:both;
  }
  @keyframes tlItem{
    from{opacity:0;transform:translate3d(14px,0,0)}
    to  {opacity:1;transform:none}
  }

  /* El punto del hito crece al llegar. */
  html.has-sdt .timeline__dot{
    animation-name:tlDot;
    animation-timeline:view();
    animation-range:entry 8% cover 22%;
    animation-timing-function:linear;
    animation-fill-mode:both;
  }
  @keyframes tlDot{
    from{transform:scale(.35)}
    to  {transform:scale(1)}
  }
}

/* Estado base: si la linea de tiempo esta inactiva —la lista aun no entro
   en la ventana— la animacion no aplica su relleno, asi que el estado
   inicial lo fija el CSS. Sin JavaScript no se oculta nada. */
html.js.has-sdt .timeline__item{opacity:0}
html.js.has-sdt .timeline::before{transform:scaleY(0);transform-origin:50% 0}

@media (prefers-reduced-motion: reduce){
  html .timeline__item,html .timeline__dot,html .timeline::before{
    animation:none !important;opacity:1 !important;transform:none !important;
  }
}

/* =====================================================================
   IMPRESION
   ---------------------------------------------------------------------
   Al imprimir no hay scroll, luego ninguna animacion conducida por el
   avanza: todo lo que dependa de ella se quedaria en su fotograma
   inicial y saldria en blanco. Un comprobante impreso incompleto no es
   un defecto estetico, es un documento invalido.
   ===================================================================== */
@media print{
  html [data-sc],
  html [data-sc-parallax],
  html .timeline__item,
  html .timeline__dot,
  html .timeline::before,
  html .cine-word,
  html .scroll-progress__bar{
    animation:none !important;
    transition:none !important;
    opacity:1 !important;
    transform:none !important;
    filter:none !important;
  }
  .scroll-progress,.scroll-cue,.flow,.stage-controls{display:none !important}
  /* Al imprimir se muestran los tres actos: un relevo temporizado no
     tiene sentido en papel y dejaria dos tercios del contenido fuera. */
  .stage-layer{grid-area:auto;opacity:1 !important;visibility:visible !important;
    transform:none !important;page-break-inside:avoid}
  .timeline::before{transform:none !important}
}
