/* FicVault · capa de MOVIMIENTO (se carga DESPUÉS de componentes.css).
   Curvas y tiempos con nombre, vidrio con respaldo, ventanas y menús que entran y salen,
   cambio de tema en círculo y entrada escalonada. Todo respeta "reducir movimiento". */

/* ===== Movimiento · curvas, tiempos y materiales (vidrio) · tokens ===== */
:root{--ease-out:cubic-bezier(.23,1,.32,1);--ease-move:cubic-bezier(.77,0,.175,1);--ease-sheet:cubic-bezier(.32,.72,0,1);--t-press:.12s;--t-fast:.15s;--t-base:.2s;--t-enter:.22s;--t-exit:.14s;--t-sheet:.32s;--line-strong:rgba(31,29,27,.62);--glass:rgba(241,234,221,.74);--glass-line:rgba(31,29,27,.14);--glass-dark:rgba(24,22,20,.58);--blur:18px;--z-side:20;--z-bar:30;--z-top:40}
[data-theme="dark"]{--line-strong:rgba(239,232,218,.58);--glass:rgba(35,33,36,.74);--glass-line:rgba(239,232,218,.16);--glass-dark:rgba(12,11,12,.62)}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  :root{--glass:var(--bg);--glass-dark:#1d1b1a}
}
@media (prefers-reduced-transparency:reduce){
  :root{--glass:var(--bg);--glass-dark:#1d1b1a}
}
@media (prefers-contrast:more){
  :root{--glass:var(--bg);--glass-dark:#1d1b1a;--glass-line:var(--text)}
}

/* ===== Movimiento · respuesta al toque (feedback inmediato) ===== */
.fv-glass{background:var(--glass);border:1px solid var(--glass-line);-webkit-backdrop-filter:blur(var(--blur)) saturate(1.3);backdrop-filter:blur(var(--blur)) saturate(1.3)}
.fv-btn,.fv-ib,.fv-chip,.fv-opt,.fv-seg button,.fv-mi,.fv-fab{transition:background-color var(--t-fast) var(--ease-out),border-color var(--t-fast) var(--ease-out),color var(--t-fast) var(--ease-out),box-shadow var(--t-fast) var(--ease-out),transform var(--t-press) var(--ease-out)}
.fv-btn:active,.fv-pri:active,.fv-out:active,.fv-dg:active,.fv-dgf:active,.fv-fab:active{transform:scale(.97)}
.fv-ib:active{transform:scale(.92)}
.fv-chip:active,.fv-seg button:active{transform:scale(.97)}
.fv-opt:active{transform:scale(.99)}
.fv-in,.fv-sel,.fv-search{transition:border-color var(--t-fast) var(--ease-out),box-shadow var(--t-fast) var(--ease-out),background-color var(--t-fast) var(--ease-out)}
.fv-sw,.fv-sw i{transition:background-color var(--t-base) var(--ease-out),transform var(--t-base) var(--ease-out),box-shadow var(--t-fast) var(--ease-out)}
/* El punto del interruptor viaja con transform, no con left (no recalcula la página en cada cuadro) */
.fv-sw.on i,.fv-sw[aria-checked="true"] i{left:3px;transform:translateX(20px)}
.fv-bar i{transition:width .5s var(--ease-out)}
.fv-bar.ind i{animation-timing-function:var(--ease-move)}
.fv-in,.fv-sel,.fv-seg,.fv-chip,.fv-opt,.fv-search,.fv-box,.fv-rad{border-color:var(--line-strong)}
.fv-search{border-color:var(--text)}

/* ===== Movimiento · animaciones base ===== */
@keyframes fv-fade{from{opacity:0}to{opacity:1}}
@keyframes fv-pop{from{opacity:0;transform:translateY(8px) scale(.97)}to{opacity:1;transform:none}}
@keyframes fv-rise{from{transform:translateY(100%)}to{transform:none}}
@keyframes fv-slide-in{from{transform:translateX(100%)}to{transform:none}}

/* ===== Movimiento · ventanas y menús: entrada y salida ===== */
.fv-ov:not([hidden]) .fv-veil{animation:fv-fade var(--t-fast) var(--ease-out)}
.fv-ov:not([hidden]) .fv-win{animation:fv-pop var(--t-enter) var(--ease-out)}
.fv-mpop:not([hidden]) .fv-menu{animation:fv-pop var(--t-fast) var(--ease-out);transform-origin:100% 0}
.fv-toasts .fv-toast{animation:fv-pop var(--t-enter) var(--ease-out)}
html .fv-ov[hidden],html .fv-mpop[hidden]{display:flex!important;visibility:hidden;pointer-events:none;transition:visibility 0s linear var(--t-exit)}
html .fv-mpop[hidden]{display:block!important}
.fv-ov .fv-veil{transition:opacity var(--t-exit) var(--ease-out)}
.fv-ov[hidden] .fv-veil{opacity:0}
.fv-ov .fv-win{transition:opacity var(--t-exit) var(--ease-out),transform var(--t-exit) var(--ease-out)}
.fv-ov[hidden] .fv-win{opacity:0;transform:translateY(6px) scale(.985)}
.fv-mpop .fv-menu{transition:opacity var(--t-exit) var(--ease-out),transform var(--t-exit) var(--ease-out)}
.fv-mpop[hidden] .fv-menu{opacity:0;transform:scale(.97)}
@media (max-width:859px){
  .fv-ov:not([hidden]) .fv-win,.fv-mpop:not([hidden]) .fv-menu{animation:fv-rise var(--t-sheet) var(--ease-sheet)}
  .fv-ov .fv-win,.fv-mpop .fv-menu{transition:transform .22s var(--ease-sheet),opacity .22s var(--ease-sheet)}
  .fv-ov[hidden] .fv-win,.fv-mpop[hidden] .fv-menu{opacity:1;transform:translateY(100%)}
  html .fv-ov[hidden],html .fv-mpop[hidden]{transition:visibility 0s linear .22s}
}

/* ===== Movimiento · cambio de página y de tema (View Transitions) ===== */
/* El interruptor (@view-transition) también va escrito en el <head> de cada página (base_app.html, auth_base.html,
   home.html): si solo estuviera acá, la primera vez que se abre una pantalla Chrome cancelaba la transición. */
@view-transition{navigation:auto}
/* Cambio de pantalla: la vieja queda quieta debajo y la nueva aparece encima (160 ms). Antes las dos se fundían a la vez
   y a mitad de camino se veía el fondo vacío: con clics rápidos eso era un parpadeo. */
::view-transition-old(root){animation:none;mix-blend-mode:normal}
::view-transition-new(root){animation:fv-vt-in .16s var(--ease-out) both;mix-blend-mode:normal}
@keyframes fv-vt-out{to{opacity:0}}
@keyframes fv-vt-in{from{opacity:0}}
.fv-side{view-transition-name:fv-side}
::view-transition-group(fv-side){animation-duration:0s}
.fv-tabs{view-transition-name:fv-tabs}
html.fv-theme-vt::view-transition-old(root){animation:none;mix-blend-mode:normal;z-index:1}
html.fv-theme-vt::view-transition-new(root){animation:fv-reveal .55s var(--ease-move) both;mix-blend-mode:normal;z-index:2}

/* ===== Movimiento · entrada escalonada de la página ===== */
@keyframes fv-reveal{from{clip-path:circle(0 at var(--rx,50%) var(--ry,50%))}to{clip-path:circle(150vmax at var(--rx,50%) var(--ry,50%))}}
@keyframes fv-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes fv-mark{to{background-size:100% 100%}}
.fv-hero .hl{background-image:linear-gradient(var(--hl),var(--hl));background-repeat:no-repeat;background-position:0 0;background-size:0% 100%;animation:fv-mark .6s .3s var(--ease-move) forwards}
html.fv-enter .fv-stagger>*{animation:fv-in .42s var(--ease-out) both}
html.fv-enter .fv-stagger>*:nth-child(2){animation-delay:.03s}
html.fv-enter .fv-stagger>*:nth-child(3){animation-delay:.06s}
html.fv-enter .fv-stagger>*:nth-child(4){animation-delay:.09s}
html.fv-enter .fv-stagger>*:nth-child(5){animation-delay:.12s}
html.fv-enter .fv-stagger>*:nth-child(6){animation-delay:.15s}
html.fv-enter .fv-stagger>*:nth-child(7){animation-delay:.18s}
html.fv-enter .fv-stagger>*:nth-child(8){animation-delay:.21s}
html.fv-enter .fv-stagger>*:nth-child(9){animation-delay:.24s}
html.fv-enter .fv-stagger>*:nth-child(10){animation-delay:.27s}
html.fv-enter .fv-stagger>*:nth-child(n+11){animation-delay:.3s}
/* ===== /library · la ventana es la entrada (BIBLIOTECA-ANALISIS.md §5) =====
   Una sola entrada, solo al llegar desde afuera (html.fv-enter): el arco del saludo sube como una persiana, después
   aparece el texto y después el resto, junto. Sin escalonado por bloque: la biblioteca no es una lista más.
   De noche, detrás del dibujo se enciende la lámpara (fv-app.css, .fv-s-noche::before), una vez. */
@keyframes fv-persiana{from{clip-path:inset(100% 0 0 0)}to{clip-path:inset(0 0 0 0)}}
@keyframes fv-sube{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
html.fv-enter .fv-main.fv-inicio.fv-stagger>*{animation:fv-fade .3s .25s var(--ease-out) both}
html.fv-enter .fv-main.fv-inicio.fv-stagger>.fv-hero{animation:none}
html.fv-enter .fv-inicio .fv-saludo{animation:fv-persiana .7s var(--ease-move) both}
html.fv-enter .fv-inicio .fv-greet .tx{animation:fv-sube .4s .35s var(--ease-out) both}
html.fv-enter .fv-inicio .fv-tools{animation:fv-fade .3s .25s var(--ease-out) both}
html.fv-enter .fv-inicio .fv-hero .hl{animation-delay:.6s}
html.fv-enter .fv-inicio .fv-s-noche::before{animation:fv-fade .9s .9s var(--ease-out) both}

@media (prefers-reduced-motion:reduce){
  @view-transition{navigation:none}
  html.fv-enter .fv-main.fv-inicio.fv-stagger>*,html.fv-enter .fv-inicio .fv-saludo,html.fv-enter .fv-inicio .fv-greet .tx,
  html.fv-enter .fv-inicio .fv-tools,html.fv-enter .fv-inicio .fv-s-noche::before{animation:none}
  .fv-sw,.fv-sw i{transition:background-color var(--t-fast) linear}
  .fv-version-nueva{animation:fv-fade var(--t-base) linear}
  .fv-ov.fv-drawer[hidden] .fv-win{transform:none;opacity:0}
  .fv-hero .hl{animation:none;background-size:100% 100%}
  html.fv-enter .fv-stagger>*{animation:none}
  .fv-ov:not([hidden]) .fv-win,.fv-mpop:not([hidden]) .fv-menu,.fv-toasts .fv-toast{animation:fv-fade var(--t-base) linear!important}
  .fv-ov[hidden] .fv-win,.fv-mpop[hidden] .fv-menu{transform:none}
  .fv-btn:active,.fv-pri:active,.fv-out:active,.fv-ib:active,.fv-chip:active,.fv-opt:active,.fv-fab:active{transform:none}
}

/* ===== Movimiento · el aviso sale con un fundido corto (lo agrega fv-ui.js v2) ===== */
.fv-toasts .fv-toast.is-out{animation:none;opacity:0;transform:translateY(6px) scale(.98);transition:opacity var(--t-exit) var(--ease-out),transform var(--t-exit) var(--ease-out)}

/* ===== Movimiento · cambio de tema: toda la página se barre junta y, sin View Transitions, se funde ===== */
html.fv-theme-vt .fv-side,html.fv-theme-vt .fv-tabs{view-transition-name:none}
html.fv-theme-fade,html.fv-theme-fade *,html.fv-theme-fade *::before,html.fv-theme-fade *::after{transition:background-color .22s linear,color .22s linear,border-color .22s linear,fill .22s linear,stroke .22s linear,box-shadow .22s linear!important}

/* ===== Pulido · oct 2026 ===== */
/* Menú ⋯ (escritorio): nace del botón que lo abrió. fv-ui.js pone el origen y --pop-y (hacia el botón). */
@keyframes fv-menu-in{from{opacity:0;transform:translateY(var(--pop-y,-6px)) scale(.96)}to{opacity:1;transform:none}}
@media (min-width:860px){
  .fv-mpop:not([hidden]) .fv-menu{animation:fv-menu-in .16s var(--ease-out)}
}

/* Segmentado: la píldora oscura viaja hasta la opción elegida (fv-ui.js agrega .fv-seg-thumb). */
.fv-seg.has-thumb{position:relative;isolation:isolate}
.fv-seg-thumb{position:absolute;left:0;top:0;z-index:-1;border-radius:99px;background:var(--pri);opacity:0;pointer-events:none;
  transition:transform .26s var(--ease-out),width .26s var(--ease-out),opacity var(--t-fast) var(--ease-out)}
.fv-seg.is-still .fv-seg-thumb{transition:none}
.fv-seg.has-thumb button[aria-checked="true"],.fv-seg.has-thumb button[aria-pressed="true"],.fv-seg.has-thumb button.on{background:none}
.fv-seg.has-thumb button{transition:color .2s var(--ease-out),background-color var(--t-fast) var(--ease-out),transform var(--t-press) var(--ease-out)}

/* Portadas: llegan con un fundido corto sobre el color del papel, sin parpadeo. */
.fv-mc.has-img>img{transition:opacity .24s var(--ease-out)}
.fv-mc.has-img>img.is-wait{opacity:0}

/* Estante: el borde de la tabla tiene dos líneas, como un grabado, y el libro proyecta su sombra sobre ella. */
.fv-plank::before{content:"";position:absolute;left:0;right:0;top:5px;height:1px;background:var(--line);opacity:.6}
.fv-row{padding-top:10px;margin-top:-10px}

@media (prefers-reduced-motion:reduce){
  .fv-seg-thumb{transition:opacity .15s linear}
  .fv-mpop:not([hidden]) .fv-menu{animation:fv-fade var(--t-base) linear!important}
  .fv-mc.has-img>img{transition:none}
}

/* «Libros: variados / todos iguales»: cada portada se transforma a su nueva forma (fv-app.js) */
html.fv-formas-vt::view-transition-group(*){animation-duration:.42s;animation-timing-function:cubic-bezier(.32,.72,0,1)}
html.fv-formas-vt::view-transition-old(root),html.fv-formas-vt::view-transition-new(root){animation:none}
html.fv-formas-vt .fv-side,html.fv-formas-vt .fv-tabs{view-transition-name:none}
html.fv-formas-vt .fv-ov:not([hidden]){view-transition-name:fv-formas-panel}
html.fv-formas-vt::view-transition-group(fv-formas-panel){animation:none;z-index:10}
