/* ==========================================================================
   CENTRO DE MEMORIA — repositorio académico

   MISMA PIEL, OTRO ENFOQUE.
   Se consume la API de tokens `--pf-*` SIN CAMBIAR UN SOLO VALOR. Pero aquí no
   hay jerarquía editorial (ese es el muro de la portada, con su compás de 8):
   esto es un CATÁLOGO, y en un catálogo todas las fichas valen lo mismo. Lista
   uniforme, dato al frente.

   DOS LIENZOS, CLARO POR DEFECTO
   -------------------------------
   El sitio es oscuro; este portal NO. Un repositorio se usa para leer fichas y
   comparar metadatos durante minutos, así que arranca en CLARO —más legible y
   menos fatiga— y ofrece el oscuro con un interruptor.

   Para no repintar a mano cada regla se define una capa local `--repo-*`:
   los dos temas sólo cambian esas variables. `--pf-*` queda intacta
   (invariante 7 del tema: cambiar valores, no nombres).
   ========================================================================== */

.pf-repo{
	/* --- TEMA CLARO (el de por defecto) -------------------------------- */
	--repo-bg:       var(--pf-lectura);          /* #FAFAFA */
	--repo-panel:    #FFFFFF;
	--repo-panel-2:  #F4F4F5;
	--repo-linea:    rgba(0,0,0,.14);
	--repo-linea-f:  rgba(0,0,0,.26);
	--repo-tinta:    var(--pf-tinta-cl);         /* #111 */
	--repo-tinta-2:  var(--pf-tinta-cl-2);
	--repo-tinta-3:  var(--pf-tinta-cl-3);
	--repo-k:        var(--pf-k-os);             /* variante AA sobre claro */
	--repo-sombra:   0 1px 0 rgba(0,0,0,.04);

	background:var(--repo-bg);
	color:var(--repo-tinta);
	padding-bottom:var(--pf-s-9);
}

/* --- TEMA OSCURO (opt-in) ------------------------------------------------
   Dos selectores a propósito:
   · `html[data-repo-tema]` lo pone el guardia INLINE de la plantilla, antes de
     pintar: sin él, quien eligió oscuro vería un fogonazo blanco en cada carga.
   · `.pf-repo[data-tema]` es el estado que maneja el JS tras cargar.
   -------------------------------------------------------------------------- */
html[data-repo-tema="oscuro"] .pf-repo,
.pf-repo[data-tema="oscuro"]{
	--repo-bg:       var(--pf-muro);
	--repo-panel:    var(--pf-carbon);
	--repo-panel-2:  var(--pf-humo);
	--repo-linea:    var(--pf-linea);
	--repo-linea-f:  var(--pf-linea-f);
	--repo-tinta:    var(--pf-hueso);
	/* 🔴 Aquí NO sirve la escala de grises de la portada. Medido sobre el panel
	   (#121212): `--pf-gris-o` daba 2.82:1 en las etiquetas del metadato
	   («Autoría», «Fecha»), por debajo del mínimo AA. En la portada ese gris
	   viste texto decorativo; aquí es INFORMACIÓN de una ficha de catálogo y
	   tiene que leerse. Se sube un escalón toda la escala. */
	--repo-tinta-2:  #C7C7CC;                    /* ~11:1 sobre el panel */
	--repo-tinta-3:  var(--pf-gris);             /* ~5.5:1 — pasa AA */
	--repo-k:        var(--pf-k);
	--repo-sombra:   none;
}

/* 🔴 AL CAMBIAR DE TEMA SE SUSPENDEN LAS TRANSICIONES.
   Medido: con `transition` activa sobre un fondo que viene de `var()`, al
   cambiar la variable el navegador NO completa la interpolación y deja el color
   ANTERIOR pegado — la ficha se quedaba blanca con texto blanco (contraste
   1.12:1, texto invisible) devolviendo HTTP 200 y con aspecto plausible.
   Además, en un cambio de tema conmuta la paleta ENTERA: animar decenas de
   propiedades a la vez es ruido, no elegancia. El cambio debe ser instantáneo. */
.pf-repo.pf-sin-transicion,
.pf-repo.pf-sin-transicion *{
	transition:none !important;
}

/* --- el interruptor de tema --------------------------------------------- */
.pf-repo__tema{
	display:inline-flex;align-items:center;gap:.45rem;cursor:pointer;
	background:transparent;border:1px solid var(--repo-linea);
	padding:.42rem .7rem;color:var(--repo-tinta-2);
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);
	letter-spacing:.06em;text-transform:uppercase;
	transition:border-color var(--pf-dur-micro) var(--pf-ease),
	           color var(--pf-dur-micro) var(--pf-ease);
}
.pf-repo__tema:hover,
.pf-repo__tema:focus-visible{border-color:var(--repo-k);color:var(--repo-k);outline:none}
.pf-repo__tema:focus-visible{outline:2px solid var(--repo-k);outline-offset:2px}
.pf-repo__tema svg{width:14px;height:14px;flex:0 0 auto}
/* Cada icono se muestra según el tema activo: el botón anuncia a DÓNDE lleva. */
.pf-repo__tema .pf-ico-luna{display:none}
html[data-repo-tema="oscuro"] .pf-repo__tema .pf-ico-luna,
.pf-repo[data-tema="oscuro"] .pf-repo__tema .pf-ico-luna{display:block}
html[data-repo-tema="oscuro"] .pf-repo__tema .pf-ico-sol,
.pf-repo[data-tema="oscuro"] .pf-repo__tema .pf-ico-sol{display:none}

/* --- masthead ----------------------------------------------------------- */
.pf-repo__mast{
	border-bottom:1px solid var(--repo-linea);
	padding:var(--pf-s-8) 0 var(--pf-s-7);
	background:var(--repo-bg);
}
.pf-repo__mast-top{
	display:flex;align-items:flex-start;justify-content:space-between;
	gap:var(--pf-s-4);margin-bottom:var(--pf-s-4);
}
.pf-repo__kick{
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);
	letter-spacing:.16em;text-transform:uppercase;color:var(--repo-k);
}
.pf-repo__t{
	margin:0 0 var(--pf-s-4);font-family:var(--pf-display);
	font-size:var(--pf-t-2xl);line-height:var(--pf-lh-tight);
	text-transform:uppercase;color:var(--repo-tinta);
}
.pf-repo__lead{
	margin:0 0 var(--pf-s-6);max-width:56ch;
	font-family:var(--pf-body);font-size:var(--pf-t-md);line-height:var(--pf-lh-body);
	color:var(--repo-tinta-2);
}
.pf-repo__cifras{
	display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;margin:0;
	background:var(--repo-linea);border:1px solid var(--repo-linea);
}
.pf-repo__cifras > div{background:var(--repo-panel);padding:var(--pf-s-4) var(--pf-s-5)}
.pf-repo__cifras dt{
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);letter-spacing:.12em;
	text-transform:uppercase;color:var(--repo-tinta-3);margin-bottom:.35rem;
}
.pf-repo__cifras dd{
	margin:0;font-family:var(--pf-display);font-size:var(--pf-t-xl);
	line-height:1;color:var(--repo-k);
}

/* --- layout ------------------------------------------------------------- */
.pf-repo__layout{
	display:grid;grid-template-columns:minmax(0,260px) minmax(0,1fr);
	gap:var(--pf-s-7);align-items:start;padding-top:var(--pf-s-7);
}

/* --- facetas ------------------------------------------------------------ */
.pf-repo__lado{
	position:sticky;top:var(--pf-s-6);display:grid;gap:var(--pf-s-6);min-width:0;
}
.pf-repo__lbl{
	display:block;margin:0 0 var(--pf-s-3);
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);letter-spacing:.14em;
	text-transform:uppercase;color:var(--repo-tinta-3);
}
.pf-repo__lbl::before{content:"[ ";color:var(--repo-k)}
.pf-repo__lbl::after{content:" ]";color:var(--repo-k)}

.pf-repo__campo{display:flex;border:1px solid var(--repo-linea);background:var(--repo-panel)}
.pf-repo__campo input{
	flex:1 1 auto;min-width:0;background:transparent;border:0;
	padding:.6rem .7rem;color:var(--repo-tinta);
	font-family:var(--pf-mono);font-size:var(--pf-t-sm);
}
.pf-repo__campo input:focus{outline:none;background:var(--repo-panel-2)}
.pf-repo__campo input::placeholder{color:var(--repo-tinta-3)}
.pf-repo__campo button{
	flex:0 0 auto;cursor:pointer;border:0;border-left:1px solid var(--repo-linea);
	background:var(--repo-k);color:var(--pf-sobre-k);
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);
	letter-spacing:.08em;text-transform:uppercase;padding:.6rem .9rem;
}
.pf-repo__campo button:hover{filter:brightness(1.08)}

.pf-repo__faceta ul{
	list-style:none;margin:0;padding:0;display:grid;gap:1px;
	background:var(--repo-linea);border:1px solid var(--repo-linea);
}
.pf-repo__faceta li{background:var(--repo-panel)}
.pf-repo__faceta li a{
	display:flex;align-items:center;justify-content:space-between;gap:.6rem;
	padding:.5rem .7rem;text-decoration:none;
	font-family:var(--pf-mono);font-size:var(--pf-t-sm);color:var(--repo-tinta-2);
	transition:background-color var(--pf-dur-micro) var(--pf-ease),color var(--pf-dur-micro) var(--pf-ease);
}
.pf-repo__faceta li a:hover{background:var(--repo-panel-2);color:var(--repo-tinta)}
.pf-repo__faceta li a em{font-style:normal;font-size:var(--pf-t-xs);color:var(--repo-tinta-3)}
.pf-repo__faceta li.es-activo a{background:var(--repo-k);color:var(--pf-sobre-k)}
.pf-repo__faceta li.es-activo a em{color:var(--pf-sobre-k);opacity:.75}

.pf-repo__anios{display:flex;flex-wrap:wrap;gap:.3rem}
.pf-repo__anios a{
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);text-decoration:none;
	border:1px solid var(--repo-linea);padding:.3rem .5rem;color:var(--repo-tinta-2);
	background:var(--repo-panel);
	transition:border-color var(--pf-dur-micro) var(--pf-ease),color var(--pf-dur-micro) var(--pf-ease);
}
.pf-repo__anios a:hover{border-color:var(--repo-k);color:var(--repo-k)}
.pf-repo__anios a.es-activo{background:var(--repo-k);border-color:var(--repo-k);color:var(--pf-sobre-k)}

.pf-repo__nota{
	margin:.6rem 0 0;font-family:var(--pf-mono);font-size:var(--pf-t-xs);
	line-height:1.5;color:var(--repo-tinta-3);
}

/* --- barra de resultados ------------------------------------------------ */
.pf-repo__res{min-width:0}
.pf-repo__barra{
	display:flex;flex-wrap:wrap;gap:var(--pf-s-4);align-items:center;justify-content:space-between;
	padding-bottom:var(--pf-s-4);border-bottom:1px solid var(--repo-linea);margin-bottom:var(--pf-s-5);
}
.pf-repo__cuenta{
	margin:0;font-family:var(--pf-mono);font-size:var(--pf-t-sm);color:var(--repo-tinta-2);
}
.pf-repo__cuenta strong{color:var(--repo-k);font-weight:600}
.pf-repo__barra-acc{display:flex;flex-wrap:wrap;gap:.4rem}
.pf-repo__orden,.pf-repo__exp{
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);text-decoration:none;
	border:1px solid var(--repo-linea);padding:.4rem .66rem;color:var(--repo-tinta-2);
	background:var(--repo-panel);
	transition:border-color var(--pf-dur-micro) var(--pf-ease),color var(--pf-dur-micro) var(--pf-ease);
}
.pf-repo__orden:hover,.pf-repo__exp:hover{border-color:var(--repo-k);color:var(--repo-k)}
.pf-repo__orden.es-activo{background:var(--repo-k);border-color:var(--repo-k);color:var(--pf-sobre-k)}
.pf-repo__exp{border-color:color-mix(in srgb,var(--repo-k) 45%,transparent);color:var(--repo-k)}

.pf-repo__aviso{
	margin:0 0 var(--pf-s-5);padding:.7rem .9rem;
	border:1px solid color-mix(in srgb,var(--repo-k) 45%,transparent);
	background:color-mix(in srgb,var(--repo-k) 7%,transparent);
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);line-height:1.6;color:var(--repo-tinta-2);
}
.pf-repo__aviso strong{color:var(--repo-k)}

.pf-repo__activos{display:flex;flex-wrap:wrap;gap:.4rem;align-items:center;margin-bottom:var(--pf-s-5)}
.pf-repo__activos .pf-repo__lbl{margin:0}
.pf-repo__activos a{
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);text-decoration:none;
	border:1px solid var(--repo-k);padding:.28rem .55rem;color:var(--repo-k);
}
.pf-repo__activos a:hover{background:var(--repo-k);color:var(--pf-sobre-k)}
.pf-repo__limpiar{border-color:var(--repo-linea-f)!important;color:var(--repo-tinta-3)!important}
.pf-repo__limpiar:hover{background:transparent!important;color:var(--repo-tinta)!important}

/* ==========================================================================
   LA LISTA — no es una retícula de cajas
   Un catálogo se escanea en vertical: el ojo baja por los titulares y sólo se
   detiene donde hace falta. Cada fila respira (no es una tabla apretada) y
   reserva un raíl derecho para el metadato y la descarga.
   ========================================================================== */
.pf-repo__lista{
	display:grid;gap:1px;background:var(--repo-linea);
	border:1px solid var(--repo-linea);
}

.pf-doc{
	display:grid;grid-template-columns:minmax(0,1fr) minmax(0,236px);
	gap:var(--pf-s-5);align-items:start;min-width:0;
	background:var(--repo-panel);padding:var(--pf-s-5) var(--pf-s-6);
	transition:background-color var(--pf-dur-micro) var(--pf-ease);
}
.pf-doc:hover{background:var(--repo-panel-2)}

.pf-doc__main{display:flex;flex-direction:column;gap:.55rem;min-width:0}
.pf-doc__cab{display:flex;flex-wrap:wrap;gap:.5rem;align-items:center}
.pf-doc__ruta{
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);text-decoration:none;
	color:var(--repo-k);border:1px solid color-mix(in srgb,var(--repo-k) 40%,transparent);
	padding:.2rem .45rem;
}
.pf-doc__ruta:hover{background:var(--repo-k);color:var(--pf-sobre-k)}
.pf-doc__medio,.pf-doc__reg{
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);color:var(--repo-tinta-3);
}
.pf-doc__t{
	margin:0;font-family:var(--pf-cond);font-weight:700;
	font-size:1.28rem;line-height:1.22;
}
.pf-doc__t a{color:var(--repo-tinta);text-decoration:none}
.pf-doc__t a:hover{color:var(--repo-k)}
.pf-doc__ex{
	margin:0;max-width:72ch;
	font-family:var(--pf-body);font-size:var(--pf-t-sm);
	line-height:1.62;color:var(--repo-tinta-2);
}
.pf-doc__tags{display:flex;flex-wrap:wrap;gap:.3rem;margin-top:.15rem}
.pf-doc__tags a{
	font-family:var(--pf-mono);font-size:.64rem;text-decoration:none;
	color:var(--repo-tinta-3);border:1px solid var(--repo-linea);padding:.18rem .4rem;
}
.pf-doc__tags a:hover{border-color:var(--repo-k);color:var(--repo-k)}

/* raíl derecho: el dato y la descarga, siempre en el mismo sitio */
.pf-doc__lado{
	display:flex;flex-direction:column;gap:.7rem;min-width:0;
	padding-left:var(--pf-s-5);border-left:1px solid var(--repo-linea);
}
.pf-doc__meta{display:grid;gap:.42rem;margin:0}
.pf-doc__meta > div{display:grid;grid-template-columns:5.2rem minmax(0,1fr);gap:.5rem;align-items:baseline}
.pf-doc__meta dt{
	font-family:var(--pf-mono);font-size:.62rem;letter-spacing:.08em;
	text-transform:uppercase;color:var(--repo-tinta-3);
}
.pf-doc__meta dd{
	margin:0;font-family:var(--pf-mono);font-size:var(--pf-t-xs);
	color:var(--repo-tinta);word-break:break-word;
}
.pf-doc__sha{
	font-family:var(--pf-mono);font-size:.62rem;color:var(--repo-tinta-3);cursor:help;
	padding-top:.5rem;border-top:1px solid var(--repo-linea);
}
.pf-doc__sha em{font-style:normal;color:var(--repo-tinta-2)}
.pf-doc__acc{display:flex;flex-wrap:wrap;gap:.35rem}
.pf-doc__b{
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);line-height:1;cursor:pointer;
	text-decoration:none;background:transparent;border:1px solid var(--repo-linea);
	padding:.4rem .62rem;color:var(--repo-tinta-2);
	transition:border-color var(--pf-dur-micro) var(--pf-ease),color var(--pf-dur-micro) var(--pf-ease);
}
.pf-doc__b:hover,.pf-doc__b:focus-visible{border-color:var(--repo-k);color:var(--repo-k);outline:none}
.pf-doc__b--leer{border-color:color-mix(in srgb,var(--repo-k) 45%,transparent);color:var(--repo-k)}
.pf-doc__b--leer:hover{background:var(--repo-k);color:var(--pf-sobre-k)}

/* --- paginación y estados ----------------------------------------------- */
.pf-repo__pag{display:flex;flex-wrap:wrap;gap:.35rem;margin-top:var(--pf-s-6)}
.pf-repo__pag a,.pf-repo__pag span{
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);text-decoration:none;
	border:1px solid var(--repo-linea);padding:.42rem .66rem;color:var(--repo-tinta-2);
	background:var(--repo-panel);
}
.pf-repo__pag a:hover{border-color:var(--repo-k);color:var(--repo-k)}
.pf-repo__pag .current{background:var(--repo-k);border-color:var(--repo-k);color:var(--pf-sobre-k)}

.pf-repo__vacio{
	border:1px solid var(--repo-linea);background:var(--repo-panel);
	padding:var(--pf-s-7) var(--pf-s-5);text-align:center;
}
.pf-repo__vacio p{margin:0 0 .6rem;font-family:var(--pf-mono);font-size:var(--pf-t-sm);color:var(--repo-tinta-2)}
.pf-repo__vacio strong{color:var(--repo-tinta)}
.pf-repo__legal{
	margin:var(--pf-s-6) 0 0;padding-top:var(--pf-s-4);border-top:1px solid var(--repo-linea);
	font-family:var(--pf-mono);font-size:var(--pf-t-xs);line-height:1.6;color:var(--repo-tinta-3);
}

/* ==========================================================================
   RESPONSIVE — sólo dentro de media queries (regla del cliente).
   La regla base es la de escritorio y no se toca.
   ========================================================================== */
@media (max-width:980px){
	.pf-repo__layout{grid-template-columns:minmax(0,1fr);gap:var(--pf-s-6)}
	.pf-repo__lado{position:static;top:auto}
	.pf-repo__cifras{grid-template-columns:repeat(2,minmax(0,1fr))}
	/* La ficha se apila: el raíl pasa a ser un pie con línea superior. */
	.pf-doc{grid-template-columns:minmax(0,1fr);gap:var(--pf-s-4)}
	.pf-doc__lado{
		padding-left:0;border-left:0;
		padding-top:var(--pf-s-4);border-top:1px solid var(--repo-linea);
	}
	.pf-doc__meta{grid-template-columns:repeat(2,minmax(0,1fr))}
	.pf-doc__sha{border-top:0;padding-top:0}
}

@media (max-width:640px){
	.pf-repo__mast{padding:var(--pf-s-6) 0 var(--pf-s-5)}
	.pf-repo__mast-top{flex-direction:column;gap:var(--pf-s-3)}
	.pf-repo__lead{font-size:var(--pf-t-base)}
	.pf-repo__cifras > div{padding:var(--pf-s-3) var(--pf-s-4)}
	.pf-repo__cifras dd{font-size:var(--pf-t-lg)}
	.pf-doc{padding:var(--pf-s-4)}
	.pf-doc__t{font-size:1.1rem}
	.pf-doc__meta{grid-template-columns:minmax(0,1fr)}
	.pf-repo__barra{align-items:flex-start;flex-direction:column;gap:var(--pf-s-3)}
}

/* ==========================================================================
   LA PANTALLA DE ARRANQUE — la puerta de la Base de Conocimiento
   ==========================================================================

   Una consola que se escribe sola (~2,2 s) y se levanta descubriendo el portal.
   El texto y la coreografía los calcula `pf_repo_arranque()` en PHP; aquí sólo
   está la piel y el movimiento.

   🔴 SE LEVANTA SOLA, SIN JS. La salida es una animación con `forwards` que
   acaba en `visibility:hidden`. Si `pf-repo.js` no llega a cargarse, el telón
   se va igual. Ese script sólo puede ADELANTAR el final, nunca retrasarlo. Un
   telón a pantalla completa que se queda echado deja el archivo inaccesible
   devolviendo HTTP 200: no puede depender de que un script sobreviva.

   🔴 Y SIN JS NI SIQUIERA APARECE: por defecto va en `display:none` y sólo la
   enciende `html.pf-boot-on`, que pone el script en línea de la plantilla.

   🔴 NADA DE SCANLINES. La doctrina V2 (cabecera de `tokens.css`) prohíbe
   tramas y neón de noche. Lo «terminal» lo dan la retícula mono, el corchete,
   el cursor y UN acento —el mismo que `pf-acento.js` sortea en cada visita, que
   se recoge aquí con `var(--pf-k)`—, no una capa de rayas.

   DE NEGRO A CLARO. El portal es el único lienzo claro del sistema, así que la
   salida va de la noche al día. Es la idea, no un efecto: se entra por la
   consola y el archivo se abre a plena luz. El fundido es largo (340 ms) y con
   la curva del tema, justamente para que no sea un fogonazo.
   ========================================================================== */

/* Sin el interruptor del script en línea, esto no existe. */
.pf-boot{ display:none }

html.pf-boot-on .pf-boot{
	display:grid;
	place-items:center;
	position:fixed;
	inset:0;
	/* Por encima de todo lo del tema: la barra de lectura (100) es el techo
	   actual, la cabecera va en 60 y el overlay del menú en 90. */
	z-index:200;
	padding:var(--pf-gutter);
	background:var(--pf-negro);

	/* El cuerpo de la consola. `--boot-ancho` llega en `ch` desde PHP: es la
	   línea más larga, para que el panel no crezca mientras se escribe. */
	--boot-fs:    clamp(.72rem, .66rem + .28vw, .84rem);
	--boot-panel: var(--pf-carbon);

	/* La salida. `--boot-fin` y `--boot-telon` los calcula PHP a partir de la
	   longitud real de las líneas. */
	animation: pf-boot-salida var(--boot-telon) var(--pf-ease) var(--boot-fin) forwards;
}

/* `visibility:hidden` al final, no sólo `opacity:0`: así deja de recibir
   clics aunque algo más fallara. */
@keyframes pf-boot-salida{
	from{ opacity:1; visibility:visible }
	99% { opacity:.02; visibility:visible }
	to  { opacity:0; visibility:hidden }
}

/* --- El panel ------------------------------------------------------------ */
/* El ancho lo manda el contenido, pero con un suelo.
   `--boot-ancho` viene de PHP en `ch` (la línea más larga, ya con su sangría).
   🔴 EL SUELO DE 22rem NO ES ESTÉTICO: la cabecera del panel va en versalitas
   con `letter-spacing:.16em` y es MÁS ANCHA que cualquier línea de la consola.
   Sin él, «BASE DE CONOCIMIENTO» se partía en tres renglones. */
.pf-boot__panel{
	width:min(100%, max(calc(var(--boot-ancho) + 3.4rem), 22rem));
	font-family:var(--pf-mono);
	font-size:var(--boot-fs);
	background:var(--boot-panel);
	border:1px solid var(--pf-linea-f);
	box-shadow:0 0 0 1px color-mix(in srgb, var(--pf-k) 12%, transparent), var(--pf-glow);
	animation:
		pf-boot-panel-entra 280ms var(--pf-ease) both,
		pf-boot-panel-sale  var(--boot-telon) var(--pf-ease) var(--boot-fin) forwards;
}
@keyframes pf-boot-panel-entra{
	from{ opacity:0; transform:translateY(9px) }
	to  { opacity:1; transform:translateY(0) }
}
/* Se va hacia arriba: la puerta que se abre, no la luz que se apaga. */
@keyframes pf-boot-panel-sale{
	from{ transform:translateY(0) }
	to  { transform:translateY(-10px) }
}

/* --- Cabecera del panel: el mismo cromo que `.pf-term` de la portada ----- */
.pf-boot__cab{
	display:flex; align-items:center; gap:.6rem;
	padding:.5rem .85rem;
	border-bottom:1px solid var(--pf-linea);
	font-weight:600; font-size:.64rem;
	letter-spacing:.16em; text-transform:uppercase;
	color:var(--pf-k-cl);
}
/* 🔴 UN ESCALÓN POR ENCIMA DE `.pf-term__cab .pf-n` DE LA PORTADA, a propósito.
   Allí el gris oscuro viste cromo decorativo; aquí es el nombre del medio en la
   puerta de su propio archivo, y medido daba 2,82:1 sobre el panel —el MISMO
   valor que ya se corrigió en las fichas del portal por quedar bajo AA—.
   Con `--pf-gris` sube a 5,45:1 y sigue siendo claramente secundario. */
.pf-boot__n{ margin-left:auto; color:var(--pf-gris); font-weight:400 }

/* --- El cuerpo ----------------------------------------------------------- */
.pf-boot__b{
	padding:1rem 1.05rem 1.1rem;
	line-height:1.85;
	overflow:hidden;      /* recorta el tapa-fondo cuando termina su recorrido */
}

/* Una línea.
   🔴 `letter-spacing:0` NO ES DECORATIVO. El tecleo avanza en `steps(--n)`,
   con --n = número de caracteres, contando con que cada uno ocupe exactamente
   un avance de la mono. Cualquier tracking desincroniza los pasos del texto y
   el efecto deja de caer en los límites de carácter. */
.pf-boot__l{
	display:block;
	position:relative;
	width:max-content;
	max-width:100%;
	white-space:pre;                       /* conserva el espacio tras el ">" */
	letter-spacing:0;
	opacity:0;
}

/* Línea escrita: el texto está maquetado desde el principio y lo tapa un
   bloque del color del panel que se retira a saltos.
   🔴 SE ANIMA `transform`, NO `width`. El ancho habría dado el mismo efecto
   provocando un reflujo por carácter; el protocolo del proyecto es
   transform + opacity. */
.pf-boot__l--cmd{
	color:var(--pf-gris);                  /* ver la nota de jerarquía abajo */
	animation: pf-boot-aparece 1ms linear var(--d) forwards;
}
.pf-boot__l--cmd::after{
	content:"";
	position:absolute; inset:0;
	background:var(--boot-panel);
	transform:translateX(0);
	/* `steps(var(--n))`: la sustitución de la variable es textual, así que
	   llega a `steps()` como entero. Si por lo que sea no resolviera, el
	   fallback es un barrido continuo — se ve peor, no se rompe. */
	animation: pf-boot-teclea var(--u) steps(var(--n), end) var(--d) forwards;
}
@keyframes pf-boot-teclea{
	to{ transform:translateX(101%) }       /* 101%: margen anti-subpíxel */
}
@keyframes pf-boot-aparece{
	to{ opacity:1 }
}

/* Línea de resultado: no se teclea, APARECE. Lo escrito es entrada; esto es
   lo que responde el sistema, y distinguirlos es lo que hace que se lea como
   una consola y no como una animación de texto.

   🔴 JERARQUÍA: el dato pesa más que el teatro. La línea escrita va en gris
   —es la máquina hablando sola— y la respuesta en hueso, que es donde están
   las cifras reales del archivo. El acento se reserva para el cursor, el
   corchete de la cabecera y el reloj: UN SOLO acento, doctrina V2. Poner las
   seis líneas en verde de terminal habría sido el gesto obvio y habría
   contradicho la piel de todo el sitio. */
.pf-boot__l--out{
	color:var(--pf-hueso);
	padding-left:2ch;                      /* alineada bajo el texto del "> " */
	animation: pf-boot-responde var(--u) var(--pf-ease) var(--d) forwards;
}
@keyframes pf-boot-responde{
	from{ opacity:0; transform:translateY(4px) }
	to  { opacity:1; transform:translateY(0) }
}

/* --- El cursor ----------------------------------------------------------- */
.pf-boot__cursor{
	display:block;
	width:1ch; height:1.05em;
	background:var(--pf-k);
	opacity:0;
	animation: pf-boot-parpadeo 1s linear var(--d) infinite;
}
@keyframes pf-boot-parpadeo{
	0%,49%  { opacity:1 }
	50%,100%{ opacity:0 }
}

/* --- El reloj de la secuencia -------------------------------------------
   NO es una barra de progreso: no hay nada cargándose, el portal ya está
   entero detrás. Es el tiempo que falta para entrar, y por eso termina
   exactamente cuando empieza a levantarse el telón. */
.pf-boot__reloj{
	height:2px;
	background:var(--pf-linea);
	overflow:hidden;
}
.pf-boot__reloj i{
	display:block; height:100%;
	background:var(--pf-k);
	transform:scaleX(0); transform-origin:left center;
	animation: pf-boot-reloj var(--boot-fin) linear forwards;
}
@keyframes pf-boot-reloj{
	to{ transform:scaleX(1) }
}

/* --- Salida adelantada (clic, tecla, rueda) ------------------------------
   `pf-repo.js` pone esta clase. Manda sobre los retardos calculados: el telón
   se va ya, sin esperar a que termine la secuencia.

   🔴 SE HACE CON UNA ANIMACIÓN, NO CON UNA TRANSICIÓN, Y NO ES CAPRICHO.
   La primera versión era `animation:none` + `opacity:0` + `transition`. Medido:
   la animación se cancelaba pero la opacidad se quedaba CLAVADA en 1 y el telón
   no se iba. Es la tercera vez que este proyecto tropieza con lo mismo (ver
   `.pf-sin-transicion` aquí arriba y el `transition:padding` de la cabecera):
   una transición necesita que el navegador pille el cambio de valor entre dos
   fotogramas, y cuando el valor de partida lo estaba imponiendo otra animación
   con `forwards`, ese cambio no siempre se registra.

   Una animación no depende de eso: declara su propio estado final y lo mantiene
   con `forwards`. Nombre de fotogramas DISTINTO a propósito —reutilizar
   `pf-boot-salida` cambiándole la duración no garantiza que el navegador la
   reinicie—. */
@keyframes pf-boot-corte{
	99%{ visibility:visible }
	to { opacity:0; visibility:hidden }
}
html.pf-boot-on .pf-boot.es-fin{
	animation: pf-boot-corte 200ms linear forwards;
}

/* ==========================================================================
   prefers-reduced-motion
   No se escribe nada, no parpadea nada, no se desplaza nada: la consola sale
   entera y puesta, se sostiene un tercio del tiempo y se va con un fundido
   plano de opacidad. Se conserva el momento; se quita el movimiento.
   ========================================================================== */
@media (prefers-reduced-motion: reduce){
	html.pf-boot-on .pf-boot{
		animation: pf-boot-salida 200ms linear 700ms forwards;
	}
	html.pf-boot-on .pf-boot__panel,
	html.pf-boot-on .pf-boot__l,
	html.pf-boot-on .pf-boot__l--cmd::after,
	html.pf-boot-on .pf-boot__cursor,
	html.pf-boot-on .pf-boot__reloj i{
		animation:none;
	}
	html.pf-boot-on .pf-boot__panel,
	html.pf-boot-on .pf-boot__l{
		opacity:1;
		transform:none;
	}
	/* El tapa-fondo del tecleo se retira de golpe: sin él, el texto queda
	   cubierto para siempre. */
	html.pf-boot-on .pf-boot__l--cmd::after{ display:none }
	/* El cursor se queda encendido y quieto. */
	html.pf-boot-on .pf-boot__cursor{ opacity:1 }
	/* El reloj se pinta lleno: ya no mide nada que se pueda seguir. */
	html.pf-boot-on .pf-boot__reloj i{ transform:scaleX(1) }
	/* La salida adelantada se queda, pero instantánea. */
	html.pf-boot-on .pf-boot.es-fin{ animation: pf-boot-corte 1ms linear forwards }
}

/* --- Aviso de registro duplicado ----------------------------------------
   Seis piezas las publicó el sitio ORIGINAL bajo dos URLs. En el catálogo
   salen las dos (es un inventario: su trabajo es decir qué hay), pero la copia
   lo declara y enlaza la de referencia. Sin esto, un investigador se encuentra
   dos fichas idénticas y cita la copia sin saberlo.
   Se pinta como nota al margen, no como error: no hay nada roto. */
.pf-doc__dup{
	margin:.5rem 0 0;
	padding:.45rem .6rem;
	border-left:2px solid var(--repo-k);
	background:var(--repo-panel-2);
	font-family:var(--pf-mono);
	font-size:var(--pf-t-xs);
	line-height:1.5;
	color:var(--repo-tinta-2);
}
.pf-doc__dup a{ color:var(--repo-k); text-underline-offset:2px }

/* ==========================================================================
   GALERÍA DE MEDIOS — el material de archivo como piezas sueltas
   Usa los tokens --repo-* del portal, así que funciona en claro y en oscuro.
   ========================================================================== */
.pf-repo__medios{
	display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:14px;
}
.pf-medio{
	display:flex;flex-direction:column;overflow:hidden;
	background:var(--repo-panel);border:1px solid var(--repo-linea);border-radius:12px;
	box-shadow:var(--repo-sombra);
	transition:transform .15s var(--pf-ease),border-color .15s var(--pf-ease),box-shadow .15s var(--pf-ease);
}
.pf-medio:hover{ transform:translateY(-3px);border-color:var(--repo-k); }
.pf-medio__thumb{
	position:relative;aspect-ratio:4/3;overflow:hidden;
	background:var(--repo-panel-2);display:flex;align-items:center;justify-content:center;
}
.pf-medio__img{ width:100%;height:100%;object-fit:cover;display:block; }
.pf-medio__ico{ font-size:34px;opacity:.85; }
.pf-medio__ext{
	position:absolute;top:7px;left:7px;
	font-family:var(--pf-mono);font-size:10px;letter-spacing:.04em;
	background:rgba(0,0,0,.6);color:#fff;padding:2px 6px;border-radius:5px;
}
.pf-medio__body{ padding:10px 11px;display:flex;flex-direction:column;gap:6px;flex:1; }
.pf-medio__nombre{
	margin:0;font-family:var(--pf-mono);font-size:11.5px;line-height:1.3;
	color:var(--repo-tinta);word-break:break-all;
}
.pf-medio__player{ width:100%;height:34px; }
.pf-medio__src{ margin:0;font-size:11.5px;line-height:1.35;color:var(--repo-tinta-3); }
.pf-medio__src a{ color:var(--repo-tinta-2);text-decoration:none; }
.pf-medio__src a:hover{ color:var(--repo-k);text-decoration:underline; }
.pf-medio__dl{
	margin-top:auto;display:flex;align-items:center;justify-content:space-between;gap:8px;padding-top:4px;
}
.pf-medio__dl a{
	font-family:var(--pf-mono);font-size:11.5px;font-weight:600;
	color:var(--repo-k);text-decoration:none;
}
.pf-medio__dl a:hover{ text-decoration:underline; }
.pf-medio__dim{ font-family:var(--pf-mono);font-size:10px;color:var(--repo-tinta-3); }
