/* Colores: vienen de ../tokens.css (raíz de talleres, copiado de miweb; normativa en
   miweb/docs/colores.md). Aquí solo se usan los roles --color-*, nunca un
   hex suelto; las variantes se sacan con color-mix().
   Misma estructura que la portada de portfolio-web-ia: la impresora ocupa el
   sitio del diente de león. */
:root {
  color-scheme: dark;
  /* tira de logos, nombre y fecha: en ../portada/portada.css (común a todos los talleres) */
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
/* barra de scroll sin fondo: solo se ven la barrita y las flechas */
html { scrollbar-color: color-mix(in srgb, var(--color-text-muted) 45%, transparent) transparent; }
body {
  background:
    radial-gradient(900px circle at 0% 0%, var(--color-glow), transparent 60%),
    var(--color-bg);
  background-color: var(--color-bg);
  color: var(--color-text);
  font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}

/* evita que la primera pintura anime título/índice cuando se llega ya "impreso" */
.no-anim, .no-anim * { transition: none !important; }

/* una malla de celdas voronoi arriba a la derecha (en el sitio de las nubes
   de portfolio-web-ia), en la capa más al fondo (antes que el brillo y el
   canvas) para no tapar nunca la impresora ni el texto. Las celdas las genera
   js/voronoi.js; aquí solo el color. Cada celda lleva relleno y un trazo
   redondeado del mismo color para suavizar las esquinas; la opacidad va en el
   grupo para que relleno y trazo no se sumen donde se pisan */
.top-voronoi {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}
.top-voronoi svg {
  position: absolute;
  top: 0;
  right: 0;
  overflow: visible;
}
.vor path {
  stroke-width: 12px;   /* = ROUND en voronoi.js */
  stroke-linejoin: round;
}
.vor { opacity: 0.22; }
.vor path { fill: var(--color-border-strong); stroke: var(--color-border-strong); }


canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
  cursor: default;
}
/* hasta imprimir, toda la pantalla es clicable */
canvas.clickable { cursor: pointer; }

/* botón invisible sobre la pantallita "▶ IMPRIMIR" de la impresora (la
   dibuja el canvas; main.js coloca el botón encima). Solo se ve su foco */
.print-btn {
  position: fixed;
  z-index: 3;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
}
.print-btn:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 3px; }
.print-btn[hidden] { display: none; }

/* pantallas verticales o cuadradas: la impresora va abajo en el centro, así
   que el título se centra en el hueco entre el logo y la impresora
   (--scene-top lo pone main.js) */
@media (max-aspect-ratio: 5/4) {
  .message {
    top: var(--below-logo);
    bottom: calc(100% - var(--scene-top, 70%) + 0.5rem);
    padding-block: 0;
  }
}
/* dos líneas: "Primeros pasos con la impresión 3D:" entera en la primera y la
   segunda parte debajo, algo más pequeña. main.js reduce el tamaño para que
   la primera línea quepa; solo si no cabe ni así (móvil) se parte */
.message h1 {
  margin: 0;
  font-size: clamp(2rem, 5.5vw, 4rem);
  font-weight: 700;
  line-height: 1.1;
  text-shadow: 0 0 24px var(--color-bg), 0 0 8px var(--color-bg);
  color: var(--color-heading);
  opacity: 1;
  transition: opacity .9s ease;
}
.title-main {
  display: inline-block;
  white-space: nowrap;
}
.message h1.wrap .title-main { white-space: normal; }
.title-sub {
  display: block;
  margin-top: 0.35em;
  font-size: 0.72em;
}
body.printed .message h1,
body.printed .message .subtitle,
body.printed .message .subtitle-date {
  opacity: 0;
  transition-delay: .3s;
}

/* ---------- Índice (aparece al terminar de imprimir) ---------- */
.index {
  position: fixed;
  inset: 0;
  z-index: 2;
  opacity: 0;
  pointer-events: none;
  transition: opacity .9s ease;
}
body.printed .index {
  opacity: 1;
  pointer-events: auto;
  transition-delay: 1.1s;
}

/* La caja del índice ocupa todo el hueco libre (a la derecha de la
   impresora; empieza en --index-left, igual en todos los talleres, entre el borde de arriba y el pie) y centra las tarjetas dentro.
   Las columnas (--index-cols) y la escala del texto (--index-scale) las
   ajusta main.js midiendo, para que siempre quepan sin scroll. */
.index-grid {
  position: absolute;
  left: var(--index-left);         /* común a todos los talleres (portada.css) */
  right: min(7rem, 5vw);
  top: var(--below-logo);         /* por debajo de la franja de logos */
  bottom: 3.5rem;
  display: grid;
  grid-template-columns: repeat(var(--index-cols, 1), 1fr);
  align-content: center;
  gap: 1.1em;
  font-size: calc(var(--index-scale, 1) * 1rem);
}
/* verticales o cuadradas: la impresora ya no deja una columna libre a su
   derecha, así que el índice va centrado a lo ancho, por debajo del logo
   y por encima del pie (que en estrecho ocupa dos filas) */
@media (max-aspect-ratio: 5/4) {
  .index-grid {
    left: 0;
    right: 0;
    width: min(90%, 760px);
    margin-inline: auto;
    top: var(--below-logo);
    bottom: 4.25rem;
  }
}

/* Títulos y subtítulos en Plus Jakarta Sans 700; el texto sigue en Inter */
.message h1,
.content-header h1,
.index-card h3 {
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  letter-spacing: 0.01em; /* Plus Jakarta viene algo apretada en 700 */
}

/* Tarjetas de cristal (translúcidas, con desenfoque), esquinas rectas y sin
   borde. Título malva y descripción Paper. Al pasar por encima se alargan hacia
   la derecha (del 92 % al 100 %; el relleno derecho crece lo mismo para que el
   texto no salte), el fondo se aclara y el título pasa a naranja */
.index-card {
  display: block;
  width: 92%;
  background: var(--color-surface-glass);
  backdrop-filter: blur(8px);
  color: var(--color-text);
  padding: 1.5em 1.85em;
  text-decoration: none;
  transition: width .25s ease, padding-right .25s ease, background-color .25s ease;
}
a.index-card { cursor: pointer; }
a.index-card:hover,
a.index-card:focus-visible,
a.index-card:active {
  width: 100%;
  padding-right: calc(1.85em + 8%);
  background: var(--color-surface-glass-hover);
}
a.index-card:hover h3,
a.index-card:focus-visible h3,
a.index-card:active h3 {
  color: var(--color-accent);
}
a.index-card:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}
.index-card h3 {
  margin: 0 0 0.5em;
  font-size: 1.35em;
  font-weight: 700;
  color: var(--color-heading);
  transition: color .25s ease;
}
.index-card p {
  margin: 0;
  font-size: 0.9em;
  font-weight: 400;
  line-height: 1.5;
  color: inherit;
}

.byline {
  position: fixed;
  left: 50%;
  bottom: 1rem;
  transform: translateX(-50%);
  margin: 0;
  font-size: 0.75rem;
  color: var(--color-text-soft);
  opacity: 0;
  z-index: 2;
  pointer-events: none;
  text-align: center;
  transition: opacity .9s ease;
}
body.printed .byline {
  opacity: 0.65;
  transition-delay: .8s;
}

.credit {
  position: fixed;
  right: 1.25rem;
  bottom: 1rem;
  margin: 0;
  font-size: 0.8rem;
  color: var(--color-text-soft);
  opacity: 0.65;
  z-index: 2;
  pointer-events: none;
}
/* en una sola fila, nombre (centrado) y crédito (derecha) se pisan por
   debajo de ~800px: se apilan a la derecha, con "Imprimir otra" a la izquierda */
@media (max-width: 820px) {
  .byline {
    left: auto;
    right: 1rem;
    bottom: 2.35rem;
    transform: none;
    text-align: right;
  }
  .credit { right: 1rem; }
}
/* móviles muy estrechos: no caben el botón y el crédito lado a lado; el
   crédito es lo prescindible, y nombre y correo pasan a dos líneas */
@media (max-width: 440px) {
  .credit { display: none; }
  .byline { bottom: 0.9rem; line-height: 1.4; }
  .byline-sep { display: none; }
  .byline-part { display: block; }
}

.replant-btn {
  position: fixed;
  left: 1.5rem;
  bottom: 1.1rem;
  font: 500 0.8rem/1 inherit;
  font-family: inherit;
  letter-spacing: 2px; /* como las etiquetas de la portada de miweb */
  color: var(--color-text-on-button);
  background: var(--color-button);
  border: none;
  padding: 0.6rem 1rem;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  z-index: 2;
  transition: opacity .6s ease, color .2s ease, background-color .2s ease;
}
/* se ilumina: naranja con texto Ink */
.replant-btn:hover,
.replant-btn:focus-visible,
.replant-btn:active { background: var(--color-accent); color: var(--color-text-on-accent); }
.replant-btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; }
body.printed .replant-btn {
  opacity: 1;
  pointer-events: auto;
  /* el retraso es solo para aparecer tras imprimir; si fuera un transition-delay
     general, también retrasaría el color del hover */
  transition: opacity .6s ease .8s, color .2s ease, background-color .2s ease;
}

/* ---------- Páginas de contenido (una por cada tema del índice) ---------- */
body.content-page {
  overflow: auto;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  /* el degradado radial de .message está pensado para una pantalla fija;
     en una página larga con scroll dejaba ver el borde del círculo, así
     que aquí el fondo es plano */
  background: var(--color-bg);
  background-color: var(--color-bg);
}
.content-header {
  max-width: 760px;
  margin: 0 auto;
  padding: 2rem 1.5rem 1.5rem;
}
/* Navegación fija (Índice / Anterior / Siguiente): botones cuadrados de fondo
   liso --color-button (Powder Blue apagado) con texto Ink (5.9), como
   "Imprimir otra"; opacos, para que se lean aunque el
   contenido pase por debajo al hacer scroll. Al pasar por encima se iluminan
   (naranja con texto Ink); no se alargan */
.back-link,
.prev-link,
.next-link {
  position: fixed;
  z-index: 3;
  padding: 0.55rem 1rem;
  background: var(--color-button);
  color: var(--color-text-on-button);
  text-decoration: none;
  font-size: 0.85rem;
  font-weight: 500;
  letter-spacing: 2px; /* como las etiquetas de la portada de miweb */
  line-height: 1.2;
  transition: color .2s ease, background-color .2s ease;
}
.back-link { top: 1rem; left: 1rem; }
.prev-link { bottom: 1rem; left: 1rem; }
.next-link { bottom: 1rem; right: 1rem; }
.back-link:hover,
.prev-link:hover,
.next-link:hover,
.back-link:focus-visible,
.prev-link:focus-visible,
.next-link:focus-visible,
.back-link:active,
.prev-link:active,
.next-link:active { background: var(--color-accent); color: var(--color-text-on-accent); }
.back-link:focus-visible,
.prev-link:focus-visible,
.next-link:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; }

/* pantallas estrechas: el título ya ocupa todo el ancho, así que baja lo
   justo para quedar bajo "← Índice"; y abajo se reserva el hueco de
   Anterior/Siguiente para que el final del contenido no quede tapado */
@media (max-width: 720px) {
  .content-header { padding-top: 3.75rem; }
  body .content-body.no-scroll { padding-bottom: 4rem; }
  .content-body.no-scroll .hero-fold { min-height: calc(100dvh - 4rem); }
}
/* móvil: franjas del color del fondo, con borde recto, detrás de "← Índice"
   (arriba) y de Anterior / Siguiente (abajo), para que el texto pase por
   debajo sin verse. El fondo de estas páginas es liso, así que no se
   distinguen; los rellenos de .content-header (3.75rem) y .content-body
   (5rem, o 4rem en las no-scroll) dejan leer todo al final del scroll */
@media (max-width: 720px) {
  body.content-page::before,
  body.content-page::after {
    content: "";
    position: fixed;
    left: 0;
    right: 0;
    height: 3.75rem;
    background: var(--color-bg);
    z-index: 2; /* por debajo de los botones (3) */
    pointer-events: none;
  }
  body.content-page::before { top: 0; }
  body.content-page::after { bottom: 0; }
}
.content-header h1 {
  margin: 0 0 1rem;
  text-align: center;
  font-size: clamp(1.8rem, 4vw, 2.75rem);
  font-weight: 700;
  line-height: 1.15;
  color: var(--color-heading);
}
.content-header h1.no-wrap {
  white-space: nowrap;
  font-size: clamp(1rem, 3vw, 2.75rem);
}
.content-header .lead {
  margin: 0.75rem 0 0;
  text-align: center;
  color: var(--color-text);
  font-size: 1.05rem;
  font-weight: 500;
  line-height: 1.6;
}

.content-body {
  max-width: 760px;
  margin: 0 auto;
  padding: 0 1.5rem 5rem;
  color: var(--color-text);
  font-size: 1rem;
  line-height: 1.75;
}
.content-body.wide { max-width: 1000px; }
.content-body p { margin: 0 0 1.25rem; }
.content-body.no-scroll { padding-bottom: 0; }

/* Pantalla que ocupa exactamente una pantalla (dvh tiene en cuenta las barras del
   navegador); la usa ¿Y ahora qué? */
.hero-fold {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
}

/* ---------- ¿Y ahora qué? (solo título + imagen, cabe en una pantalla) ---------- */
.next-steps-fold { padding-bottom: 1.5rem; }
.next-steps-fold .content-header { padding-bottom: 0; }
/* el hueco libre se reparte a partes iguales: título · enlace · foto · borde
   de abajo, así el enlace queda centrado entre el título y la foto */
.next-steps-block {
  flex: 1;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.next-steps-link {
  margin: auto 0;
  padding-block: 0.75rem; /* separación mínima si la pantalla va justa */
  font-size: 1.3rem;
  font-weight: 500;
  color: var(--color-text);
  text-align: center;
  text-decoration: none;
  transition: color .2s ease;
}
.next-steps-link:hover { color: var(--color-accent); }
.next-steps-link:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 4px; border-radius: 4px; }
.next-steps-photo {
  display: block;
  margin: 0 0 auto;
  max-width: 100%;
  border-radius: 16px;
  transition: transform .2s ease;
}
.next-steps-photo:hover { transform: translateY(-3px); }
.next-steps-photo:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 4px; }
.next-steps-image {
  display: block;
  max-width: 100%;
  /* deja sitio al título y al enlace de encima para que todo quepa en una pantalla */
  max-height: calc(100dvh - 12rem);
  width: auto;
  height: auto;
  border-radius: 16px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.5);
}

/* Subtítulos de sección, todos iguales: mismo tamaño, negrita, color
   --color-subheading (el Slate de las fichas, aclarado para que se lea) */
.section-title {
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  letter-spacing: 0.01em;
  font-size: clamp(1.25rem, 3vw, 1.6rem);
  font-weight: 700;
  color: var(--color-subheading);
  max-width: 640px;
  margin: 0 auto 2.5rem;
  text-align: center;
}

/* ---------- Apartados de texto ---------- */
/* mismo aire entre apartados que en Evolución (10rem) */
.guide-section {
  max-width: 720px;
  margin: 6rem auto 10rem;
}
.guide-section a {
  color: var(--color-accent);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--color-accent) 40%, transparent);
  text-underline-offset: 0.2em;
}
.guide-section a:hover { text-decoration-color: currentColor; }

/* subtítulo que viene después de un párrafo dentro del mismo bloque: aire
   por encima para que se lea como apartado nuevo */
.guide-section p + .section-title { margin-top: 3rem; }

/* pasos numerados (como en portfolio-web-ia): solo el número en azul claro
   y en negrita, sin círculo, en la misma línea que el texto. El número va
   posicionado a la izquierda (no con grid/flex) para que la negrita, los
   enlaces o la cursiva del texto no se partan en columnas */
.steps-list {
  list-style: none;
  counter-reset: step;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.steps-list > li {
  counter-increment: step;
  position: relative;
  padding-left: 2.25rem;
  color: var(--color-text);
  line-height: 1.7;
}
.steps-list > li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  color: var(--color-accent-soft);
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.7rem;
}

/* listas de viñetas (como en portfolio-web-ia): la viñeta es una rayita que,
   al pasar por encima, se alarga y pasa a naranja, y el texto se aclara */
.feature-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.feature-list li {
  display: flex;
  align-items: center;
  gap: 1rem;
  color: var(--color-text-soft);
  font-size: 0.95rem;
  font-weight: 400;
  transition: color .25s ease;
}
.feature-list li::before {
  content: '';
  width: 28px;
  height: 1px;
  flex: 0 0 auto;
  background: var(--color-border-strong);
  transition: width .25s ease, background-color .25s ease;
}
.feature-list li:hover {
  color: var(--color-text);
}
.feature-list li:hover::before {
  width: 44px;
  background: var(--color-accent);
}
/* variante para textos largos (varias líneas): la rayita se alinea con la
   primera línea en vez de quedar centrada contra todo el párrafo */
.feature-list.stacked li { align-items: flex-start; }
.feature-list.stacked li::before { margin-top: 0.6em; }
/* la lista, como bloque centrado bajo la frase, con el texto alineado a la izquierda */
.feature-list.centered-list {
  width: fit-content;
  max-width: 100%;
  margin: 0.5rem auto 0;
}

/* comprobación entre dos pasos: sin número (no cuenta como paso), alineada
   con el texto de los pasos y destacada en azul claro y cursiva */
.steps-list > li.step-check {
  counter-increment: none;
  color: var(--color-accent-soft);
  font-weight: 700;
  font-style: italic;
}
.steps-list > li.step-check::before { content: none; }

/* párrafo centrado bajo un subtítulo */
.content-body p.centered-text { text-align: center; }

/* enlace destacado en azul claro dentro del texto, sin subrayado; al pasar, a naranja */
.guide-section a.soft-link {
  color: var(--color-accent-soft);
  font-weight: 500;
  text-decoration: none;
  transition: color .2s ease;
}
.guide-section a.soft-link:hover,
.guide-section a.soft-link:focus-visible {
  color: var(--color-accent);
}

/* captura de una web, a todo el ancho del bloque; enlaza a esa web */
.screenshot-link {
  display: block;
  margin-top: 1.5rem;
}
.screenshot-link:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 3px;
}
.screenshot {
  display: block;
  width: 100%;
  height: auto;
}

/* recuadro de palabras clave: bloque de cristal plano, sin borde; la
   etiqueta y las palabras se reparten a lo ancho */
.content-body p.keywords {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  margin: 2.5rem 0 0;
  padding: 1rem 1.5rem;
  background: var(--color-surface-glass);
  color: var(--color-text);
}
.keywords strong { color: var(--color-accent-soft); }

/* ---------- Qué es la impresión 3D ---------- */
/* esquema del proceso (idea → objeto), a todo el ancho del bloque */
.process-figure {
  display: block;
  width: 100%;
  height: auto;
  margin: 0.5rem 0 0;
}
/* frase bajo el esquema del proceso: centrada y con aire por encima */
.content-body p.process-summary {
  margin: 3rem 0 0;
  text-align: center;
}
/* los pasos del proceso, centrados bajo el subtítulo "Proceso" */
.content-body p.process-steps {
  margin-bottom: 1.5rem;
  text-align: center;
}
/* las dos impresoras del lab, una al lado de la otra */
.printer-types {
  display: flex;
  justify-content: center;
  gap: 2rem;
}
.printer-types figure {
  margin: 0;
  max-width: calc(50% - 1rem);
}
.printer-types img {
  display: block;
  width: auto;
  max-width: 100%;
  height: min(40dvh, 320px);
  object-fit: contain;
}
/* pie de foto: texto secundario, centrado bajo la imagen */
.printer-types figcaption {
  margin-top: 0.75rem;
  text-align: center;
  font-size: 0.9rem;
  color: var(--color-text-soft);
}
/* imagen grande (esquema de la impresora): cabe entera en una pantalla */
.guide-figure {
  display: block;
  max-width: 100%;
  max-height: calc(100dvh - 14rem);
  width: auto;
  height: auto;
  margin: 0 auto;
}

/* ---------- Scroll por secciones (páginas con <html class="snap">) ---------- */
/* Solo en ordenador (ratón y pantalla con altura suficiente): cada
   .snap-slide ocupa una pantalla con su contenido centrado y el scroll salta
   de una a otra. En móvil y tablet el scroll es normal y valen los márgenes
   de siempre. js/secciones.js marca la sección activa para el fundido. */
/* la flechita de js/secciones.js solo existe en ordenador con encaje */
.scroll-hint { display: none; }
@media (min-width: 900px) and (min-height: 640px) and (hover: hover) and (pointer: fine) {
  html.snap {
    scroll-snap-type: y mandatory;
    scroll-behavior: smooth;    /* teclado y flechas: desplazamiento animado, no a saltos */
  }
  html.snap .content-body { padding-bottom: 0; }
  html.snap .snap-slide {
    min-height: 100dvh;
    scroll-snap-align: start;
    scroll-snap-stop: always;   /* una sección por gesto, sin saltarse ninguna */
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-block: 3.75rem;     /* hueco para Índice (arriba) y Anterior/Siguiente (abajo) */
  }

  /* la pantalla con el título no se centra: el título va a la misma altura
     que en el resto de páginas (mismo padding de .content-header) y lo que
     viene debajo se centra en el hueco que queda */
  html.snap .snap-slide:has(> .content-header) {
    padding-top: 0;
    justify-content: flex-start;
  }
  /* dentro de una pantalla sobran los márgenes grandes entre apartados */
  html.snap .snap-slide .guide-section { max-width: 860px; margin: 0 auto; }
  /* bajo el título, el bloque no se centra en el hueco (quedaba demasiado
     aire entre título y subtítulo): el aire que sobra se reparte un tercio
     entre título y bloque (la cabecera crece, con el título arriba) y dos
     tercios debajo del bloque (::after). Si el bloque es alto y no sobra
     nada, quedan al menos 2rem bajo el título */
  html.snap .snap-slide:has(> .content-header) > .content-header { flex: 1 0 auto; }
  html.snap .snap-slide:has(> .content-header)::after { content: ""; flex: 2 0 auto; }
  html.snap .snap-slide > .content-header ~ .guide-section { margin: 2rem auto 0; }

  /* fundido: la sección activa entera, las demás atenuadas mientras pasan */
  html.snap.snap-fade .snap-slide {
    opacity: 0.25;
    transition: opacity .9s cubic-bezier(.4, 0, .2, 1);
  }
  html.snap.snap-fade .snap-slide.is-active { opacity: 1; }

  /* mientras queden secciones por debajo (html.snap-pending, lo pone
     js/secciones.js) no se ven Anterior/Siguiente, sino una flechita centrada
     que baja a la siguiente; en la última sección vuelven los botones */
  .prev-link,
  .next-link { transition: color .2s ease, background-color .2s ease, opacity .25s ease, visibility .25s; }
  html.snap-pending .prev-link,
  html.snap-pending .next-link { opacity: 0; visibility: hidden; }
  .scroll-hint {
    position: fixed;
    z-index: 3;
    bottom: 1rem;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    padding: 0.3rem;
    border: 0;
    background: none;
    color: var(--color-text-soft);
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transition: color .2s ease, opacity .25s ease, visibility .25s;
  }
  .scroll-hint svg { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
  html.snap-pending .scroll-hint { opacity: 1; visibility: visible; }
  .scroll-hint:hover,
  .scroll-hint:focus-visible { color: var(--color-accent); }
  .scroll-hint:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; }
}
@media (prefers-reduced-motion: reduce) {
  html.snap.snap-fade .snap-slide { transition: none; }
  html.snap { scroll-behavior: auto; }
}
