/* ============================================================
   components.css — componentes reutilizables
   ============================================================ */

/* ------------------------------------------------------------
   HEADER (igual en todas las páginas)
   ------------------------------------------------------------ */
.site-header {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 44px 48px;
}

/* Envuelve el botón + su desplegable: así el panel puede anclarse al
   borde derecho exacto del botón sin depender de offsets fijos. */
.menu-group {
  position: relative;
}

.icon-btn {
  position: relative;
  display: grid;
  place-items: center;
  width: 17px;
  height: 17px;
  color: var(--toggle);
  border-radius: var(--radius-sm);
  transition: transform 0.16s var(--ease);
}
/* Amplía el área clickable sin tocar el tamaño visual del icono:
   unos pocos px transparentes alrededor evitan clics fallidos en
   botones tan pequeños (17x17px). */
.icon-btn::before {
  content: "";
  position: absolute;
  inset: -10px;
  background: transparent;
}
/* Efecto de pulsación: se hunde un poco al hacer clic */
.icon-btn:active {
  transform: scale(0.8);
}

.icon-btn svg {
  width: 11.3px;
  height: 11.3px;
  fill: currentColor;
  /* En SVG el origen de transformación por defecto es la esquina
     superior izquierda del viewBox, no el centro como en HTML.
     Sin esto, rotate() gira alrededor de esa esquina y el icono
     se ve descentrado en vez de rotar limpiamente sobre sí mismo. */
  transform-origin: center;
}

/* El icono del menú es un "+" que gira 45º y se convierte en "×" */
.menu-toggle svg {
  transition: transform 0.4s var(--ease);
}
.menu-toggle[aria-expanded="true"] svg {
  transform: rotate(45deg);
}

/* El icono de modo gira 180º cada vez que se pulsa (acumulativo) */
.mode-toggle svg {
  transition: transform 0.5s var(--ease);
  transform: rotate(var(--mode-rotation, 0deg));
}

/* ------------------------------------------------------------
   MENÚ DESPLEGABLE
   ------------------------------------------------------------ */
.menu-panel {
  position: absolute;
  top: calc(100% + 22px);
  right: 0;
  min-width: 156px;
  padding: 10px 0;
  /* Bastante translúcido a propósito: si fuese casi opaco el desenfoque
     de lo que hay detrás no se apreciaría. Sobre el fondo plano del hero
     el efecto no se nota; se ve al abrirlo con el timeline por detrás. */
  background: color-mix(in srgb, var(--surface) 50%, transparent);
  backdrop-filter: blur(26px) saturate(1.6);
  -webkit-backdrop-filter: blur(26px) saturate(1.6);
  border: 1px solid var(--surface-border);
  border-radius: 14px;
  box-shadow: var(--surface-shadow);
  transform-origin: top right;

  /* estado cerrado */
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px) scale(0.96);
  transition: opacity 0.28s var(--ease), transform 0.28s var(--ease),
    visibility 0s linear 0.28s;
}

.menu-panel[data-open="true"] {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
  transition: opacity 0.28s var(--ease), transform 0.28s var(--ease),
    visibility 0s;
}

.menu-panel a {
  display: block;
  padding: 8px 20px;
  color: var(--text-body);
  font-size: var(--fs-ui);
  line-height: 1.6;

  /* entrada escalonada: cada item entra un poco después que el anterior */
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease),
    color 0.2s var(--ease);
}

.menu-panel[data-open="true"] a {
  opacity: 1;
  transform: translateY(0);
}
.menu-panel[data-open="true"] a:nth-child(1) { transition-delay: 0.06s, 0.06s, 0s; }
.menu-panel[data-open="true"] a:nth-child(2) { transition-delay: 0.12s, 0.12s, 0s; }
.menu-panel[data-open="true"] a:nth-child(3) { transition-delay: 0.18s, 0.18s, 0s; }

.menu-panel a:hover {
  color: var(--text-strong);
}

/* Efecto de pulsación en About / Projects / Writings.
   Selector con :active para ganar en especificidad a la regla de arriba
   (que fija transform: translateY(0) al abrir); con el menú abierto ese
   translateY es 0, así que basta con el scale. */
.menu-panel[data-open="true"] a:active {
  transform: scale(0.94);
  transition: transform 0.12s var(--ease);
}

/* ------------------------------------------------------------
   LAYOUT DE LA HOME
   ------------------------------------------------------------ */
.home {
  display: flex;
  align-items: center;
  min-height: 100svh;
  padding: 48px 24px;
}

.home__col {
  width: 100%;
  max-width: var(--col-width);
  margin: 0 auto;
}

/* ------------------------------------------------------------
   RETRATO ASCII
   ------------------------------------------------------------ */
.ascii {
  position: relative;
  z-index: 0;
  width: var(--ascii-width);
  aspect-ratio: 1140.8 / 1340;
  margin-top: 56px;
  margin-bottom: -30px;
  margin-left: -26px;
  -webkit-mask-image: radial-gradient(
    ellipse 52% 55% at 50% 44%,
    #000 0%,
    #000 58%,
    rgba(0, 0, 0, 0.8) 72%,
    rgba(0, 0, 0, 0.3) 86%,
    transparent 100%
  );
  mask-image: radial-gradient(
    ellipse 52% 55% at 50% 44%,
    #000 0%,
    #000 58%,
    rgba(0, 0, 0, 0.8) 72%,
    rgba(0, 0, 0, 0.3) 86%,
    transparent 100%
  );
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
}

.ascii img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
}

.ascii img.is-on {
  opacity: 1;
}

/* ------------------------------------------------------------
   TEXTO
   ------------------------------------------------------------ */
.home__name {
  position: relative;
  z-index: 1;
  margin-bottom: 14px;
  color: var(--text-strong);
  font-size: var(--fs-h1);
  font-weight: var(--fw-medium);
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.home__bio p + p {
  margin-top: 20px;
}

.home__bio strong {
  font-weight: var(--fw-medium);
  color: var(--text-body);
}

/* Enlace "Writings" con la animación de ola letra a letra */
.wave-link {
  display: inline-block; /* necesario para que transform (pulsación) aplique */
  font-weight: var(--fw-medium);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  transition: transform 0.14s var(--ease);
}
.wave-link:active {
  transform: scale(0.92);
}

.wave-link span,
.wave-text span {
  color: var(--wave-from);
  animation: wave 1.7s var(--ease) infinite;
}

@keyframes wave {
  0%,
  60%,
  100% {
    color: var(--wave-from);
  }
  30% {
    color: var(--wave-to);
  }
}

/* ------------------------------------------------------------
   FILA DE CONTACTO + POPOVERS
   ------------------------------------------------------------ */
.contact {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  margin-top: 132px;
}

.contact__item {
  position: relative;
}

.contact__trigger {
  display: inline-block;
  color: var(--text-muted);
  font-size: var(--fs-ui);
  font-weight: var(--fw-regular);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--text-muted) 45%, transparent);
  transition: color 0.2s var(--ease), transform 0.14s var(--ease);
}

.contact__trigger:hover {
  color: var(--text-strong);
}
.contact__trigger:active {
  transform: scale(0.92);
}

/* Popover: se abre hacia arriba, centrado sobre su disparador */
.popover {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  display: flex;
  align-items: center;
  gap: 22px;
  width: max-content;
  padding: 9px 16px;
  background: var(--surface);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  box-shadow: var(--surface-shadow);

  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, 6px) scale(0.96);
  transition: opacity 0.24s var(--ease), transform 0.24s var(--ease),
    visibility 0s linear 0.24s;
}

.popover[data-open="true"] {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0) scale(1);
  transition: opacity 0.24s var(--ease), transform 0.24s var(--ease),
    visibility 0s;
}

.popover__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--text-body);
  font-size: var(--fs-ui);
  font-weight: var(--fw-regular);
  white-space: nowrap;
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--text-body) 40%, transparent);
  transition: color 0.2s var(--ease), transform 0.14s var(--ease);
}
.popover__item:active {
  transform: scale(0.9);
}

.popover__item:hover {
  color: var(--text-strong);
}

.popover__item svg {
  flex: none;
  fill: none;
  stroke: currentColor;
}

.popover__item .icon-copy {
  fill: currentColor;
  stroke: none;
}

/* El glifo 𝕏 (doble trazo Unicode) se ve fino a este tamaño; un
   contorno muy fino del mismo color lo engorda un poco. */
.popover__label--x {
  -webkit-text-stroke: 0.2px currentColor;
}

/* Popover "Ask AI": mismo tamaño que Email/Socials (padding base),
   logos monocromos recoloreados con máscara. */
.popover--ai {
  gap: 18px;
}

.popover__logo {
  display: inline-flex;
  align-items: center;
  transition: transform 0.14s var(--ease), opacity 0.2s var(--ease);
}
/* El logo se pinta como máscara del SVG rellena con el color del tema,
   así ChatGPT/Claude/Gemini quedan todos del mismo tono. */
.ai-icon {
  display: block;
  width: 16px;
  height: 16px;
  background: var(--ai-logo);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
.popover__logo:hover {
  opacity: 0.7;
}
.popover__logo:active {
  transform: scale(0.88);
}

/* ------------------------------------------------------------
   TIMELINE (#about)
   Rejilla de 3 columnas: año | columna izquierda | columna derecha.
   Cada año es una fila con nombre (y2026, y2025...), así una tarjeta
   que dura varios años se coloca con `grid-row: y2025 / y2022` en vez
   de calcular píxeles a mano.
   ------------------------------------------------------------ */
.timeline {
  position: relative;
  display: grid;
  /* 1fr a cada lado: el bloque de las dos columnas queda centrado en la
     página, y las líneas siguen ocupando todo el ancho (1 / -1). */
  grid-template-columns:
    1fr
    var(--tl-left)
    var(--tl-col-gap)
    var(--tl-right)
    1fr;
  scroll-margin-top: 110px;
  /* Cada fila puede crecer con --x-YYYY (0 por defecto). Al expandir una
     burbuja corta, JS sube ese valor y las filas siguientes bajan, así el
     contenido de debajo se desplaza en vez de solaparse. */
  grid-template-rows:
    [y2026] calc(var(--h-2026) + var(--x-2026, 0px))
    [y2025] calc(var(--h-2025) + var(--x-2025, 0px))
    [y2024] calc(var(--h-2024) + var(--x-2024, 0px))
    [y2023] calc(var(--h-2023) + var(--x-2023, 0px))
    [y2022] calc(var(--h-2022) + var(--x-2022, 0px))
    [y2021] calc(var(--h-year) + var(--x-2021, 0px))
    [y2020] calc(var(--h-year) + var(--x-2020, 0px))
    [y2019] calc(var(--h-year) + var(--x-2019, 0px))
    [y2017] calc(var(--h-year) + var(--x-2017, 0px))
    [y2016] calc(var(--h-year) + var(--x-2016, 0px))
    [yend];
  max-width: var(--tl-max);
  margin: 0 auto;
  padding: 0 var(--tl-pad);
  /* Al crecer una fila (--x-YYYY), el resto baja con suavidad */
  transition: grid-template-rows 0.4s var(--ease);
}

/* Línea divisoria al inicio de cada año. Ocupa las 3 columnas y no
   afecta al flujo porque va anclada arriba y sin altura. */
.timeline__line {
  grid-column: 1 / -1;
  align-self: start;
  height: 0;
  border-top: 1px solid var(--tl-rule);
}

.timeline__year {
  grid-column: 1;
  align-self: start;
  justify-self: start;
  margin-top: 44px;
  color: var(--tl-year);
  font-size: var(--fs-body);
  font-weight: var(--fw-regular);
}

/* Pila de elementos dentro de una celda del año */
.tl-stack {
  display: flex;
  flex-direction: column;
  gap: var(--tl-stack-gap);
  min-height: 0;
}

.tl-stack--left {
  grid-column: 2;
}
.tl-stack--right {
  grid-column: 4;
}

/* Empuja un elemento al fondo de su año (p. ej. la píldora de AIGEA).
   Se hace a través de --offset, no de margin-top: .bubble y .pill
   declaran `margin-top: var(--offset, 0)` más abajo en este archivo y
   con la misma especificidad ganarían por orden. */
.tl-push {
  --offset: auto;
  margin-top: auto;
}

/* ---------- Burbuja ---------- */
.bubble {
  position: relative;
  display: block;
  padding: 16px 18px;
  /* Sin backdrop-filter: con ~30 burbujas/píldoras en la página, cada
     una es una capa que Safari en iOS tiene que recomponer en cada
     frame de scroll, y es la causa principal del scroll a tirones en
     el timeline. El fondo ya es semitransparente (82%), así que el
     blur apenas se notaba y no compensaba el coste. */
  background: var(--bubble-bg);
  border: 1px solid var(--bubble-border);
  border-radius: var(--tl-radius);
  margin-top: var(--offset, 0);
  transition: transform 0.16s var(--ease);
}
/* Cursor + efecto de pulsación: la burbuja abre un popup al hacer clic */
.bubble[data-modal-open] {
  cursor: pointer;
}
.bubble[data-modal-open]:active {
  transform: scale(0.985);
}

/* Las experiencias laborales y los proyectos van sobre un gris algo
   más marcado que la formación. */
.bubble--muted {
  background: var(--bubble-bg-muted);
  border-color: var(--bubble-border-muted);
}

/* position: relative sirve de bloque contenedor para el chevron.
   (El antiguo efecto sticky del texto se ha eliminado.) */
.bubble__inner {
  position: relative;
}

.bubble__head {
  display: flex;
  align-items: center;
  gap: 7px;
}

.bubble__logo {
  flex: none;
  width: auto;
  height: 12px;
  filter: var(--logo-filter);
}

.bubble__title {
  color: var(--tl-title);
  font-size: var(--fs-tl);
  font-weight: var(--fw-regular);
}

.bubble__subtitle {
  margin-top: 3px;
  color: var(--tl-subtitle);
  font-size: var(--fs-tl);
}

.bubble__place {
  color: var(--tl-place);
  font-size: var(--fs-tl);
}

.bubble__date {
  margin-top: 2px;
  color: var(--tl-date);
  font-size: var(--fs-date);
}

/* Los bullets viven ahora dentro del popup (modal) de cada burbuja. */
.bubble__bullets {
  display: flex;
  flex-direction: column;
  gap: 9px;
  margin-top: 22px;
  padding-bottom: 2px;
}

.bubble__bullet {
  color: var(--tl-subtitle);
  font-size: var(--fs-tl);
  line-height: 1.5;
}

/* Texto entre asteriscos: mismo color y tamaño, pero Inter Medium */
.b-em {
  font-weight: var(--fw-medium);
}

/* "See Pictures" dentro de una burbuja */
.bubble__seepics {
  display: inline-flex;
  align-items: center;
  margin-top: 16px;
  color: var(--tl-title);
  font-size: var(--fs-tl);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: opacity 0.2s var(--ease), transform 0.14s var(--ease);
}
.bubble__seepics:hover {
  opacity: 0.6;
}
.bubble__seepics:active {
  transform: scale(0.92);
}

/* ---------- Carrusel dentro de un modal ---------- */
.carousel {
  position: relative;
  margin-top: 20px;
}
.carousel__viewport {
  overflow: hidden;
  border-radius: 14px;
}
.carousel__track {
  display: flex;
  transition: transform 0.4s var(--ease);
}
.carousel__slide {
  flex: 0 0 100%;
}
.carousel__slide img {
  width: 100%;
  height: auto;
  display: block;
}
.carousel__btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--glass-bg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--glass-border);
  color: var(--tl-title);
  font-size: 16px;
  line-height: 1;
}
.carousel__btn--prev {
  left: 10px;
}
.carousel__btn--next {
  right: 10px;
}
/* Flechas con el mismo chevron que tenían las burbujas (rotado) */
.carousel__chev {
  width: 11px;
  height: 8px;
  fill: currentColor;
}
.carousel__btn--prev .carousel__chev {
  transform: rotate(90deg);
}
.carousel__btn--next .carousel__chev {
  transform: rotate(-90deg);
}
.carousel__dots {
  display: flex;
  justify-content: center;
  gap: 7px;
  margin-top: 14px;
}
.carousel__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--tl-subtitle);
  opacity: 0.35;
  transition: opacity 0.2s var(--ease);
}
.carousel__dot[aria-selected="true"] {
  opacity: 1;
}

/* ---------- Píldora de proyecto ---------- */
.pill {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 11px 18px;
  background: var(--bubble-bg-muted);
  border: 1px solid var(--bubble-border-muted);
  border-radius: var(--tl-radius);
  margin-top: var(--offset, 0);
}

.pill__head {
  display: flex;
  align-items: center;
  gap: 7px;
}

.pill__logo {
  flex: none;
  width: auto;
  height: 13px;
  filter: var(--logo-filter);
}

.pill__name {
  color: var(--tl-title);
  font-size: var(--fs-tl);
}

.pill__date {
  color: var(--tl-date);
  font-size: var(--fs-date);
  font-style: italic;
}

.pill__desc {
  margin-top: 2px;
  color: var(--tl-subtitle);
  font-size: var(--fs-tl);
}

.pill__link {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--tl-title);
  font-size: var(--fs-tl);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  transition: opacity 0.2s var(--ease), transform 0.14s var(--ease);
}

.pill__link:hover {
  opacity: 0.6;
}
.pill__link:active {
  transform: scale(0.92);
}

.pill__link svg {
  flex: none;
  fill: none;
  stroke: currentColor;
}

/* Icono ⓘ al extremo del pill: indica que abre un popup con más info. */
.pill__info {
  flex: none;
  display: inline-flex;
  align-items: center;
  color: var(--pill-info);
}
.pill__info svg {
  width: 12px;
  height: 12px;
  fill: currentColor;
}

/* Cursor + efecto de pulsación: el pill abre un popup al hacer clic */
.pill[data-modal-open] {
  cursor: pointer;
  transition: transform 0.16s var(--ease);
}
.pill[data-modal-open]:active {
  transform: scale(0.985);
}

/* ---------- Distinción (Dept. of State / Instagram) ---------- */
.award {
  position: relative; /* contiene el haz cromado ::after */
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: var(--offset, 0);
  color: var(--tl-title); /* texto en color base (negro/blanco), se mantiene */
  font-size: var(--fs-tl); /* = título de las burbujas */
  font-weight: var(--fw-medium);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  transition: opacity 0.2s var(--ease), transform 0.14s var(--ease);
}

.award:hover {
  opacity: 0.85;
}
.award:active {
  transform: scale(0.94);
}

.award__badge {
  flex: none;
  display: block;
  width: 20px;
  height: 20px;
  overflow: hidden;
  border-radius: 50%;
}

.award__img {
  width: 20px;
  height: 20px;
}

/* Sólo una de las dos versiones se muestra según el tema */
.award__img--dark {
  display: none;
}
[data-theme="dark"] .award__img--light {
  display: none;
}
[data-theme="dark"] .award__img--dark {
  display: block;
}

/* Logo de Instagram: máscara del SVG rellena con el color base (negro),
   igual que el texto. Pegado un poco más a la palabra. */
.award__logo--ig {
  flex: none;
  display: block;
  width: 22px;
  height: 22px;
  margin-right: -3px;
  background: currentColor;
  -webkit-mask: url("/assets/svg/logo-instagram.svg") center / contain no-repeat;
  mask: url("/assets/svg/logo-instagram.svg") center / contain no-repeat;
}

.award__text {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

.award__year {
  font-style: italic;
}

.award__plus {
  text-decoration: none;
}

/* ------------------------------------------------------------
   MODALES (liquid glass)
   ------------------------------------------------------------ */
.modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: 24px;
  padding-top: calc(24px + env(safe-area-inset-top, 0px));
  padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  background: var(--modal-scrim);
  opacity: 0;
  pointer-events: none;
  /* Evita que un arrastre sobre el scrim (fuera de la tarjeta) encadene
     scroll hacia la página de detrás. A diferencia de bloquear el
     touchmove a mano en JS, esto no interfiere con los gestos nativos
     de Safari (como el pull-to-refresh), así que es más seguro. */
  overscroll-behavior: contain;
  /* Al cerrar sí se desvanece (0.3s); al abrir NO — ver regla de abajo.
     Un fundido de opacidad al abrir es lo que dejaba ver el fondo sin
     difuminar a través de la tarjeta durante ese tramo de la animación. */
  transition: opacity 0.3s var(--ease);
}

.modal[data-open="true"] {
  opacity: 1;
  pointer-events: auto;
  transition: opacity 0s;
}

.modal__card {
  position: relative;
  /* 100% = ancho de la caja del modal (viewport menos su padding
     simétrico), NO vw. Así los márgenes izquierdo y derecho son siempre
     idénticos, sin depender de la barra de scroll. */
  width: min(100%, 560px);
  max-height: 88vh;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 26px 28px 24px;
  border-radius: 22px;
  /* Liquid glass: máxima distorsión de lo que queda detrás */
  background: var(--glass-bg);
  backdrop-filter: blur(34px) saturate(1.7);
  -webkit-backdrop-filter: blur(34px) saturate(1.7);
  border: 1px solid var(--glass-border);
  box-shadow: 0 12px 48px rgba(0, 0, 0, 0.18);
  transform: scale(0.96) translateY(10px);
  transition: transform 0.3s var(--ease);
  will-change: transform, backdrop-filter;
}

.modal[data-open="true"] .modal__card {
  transform: none;
}

.modal--image .modal__card {
  width: min(100%, 720px);
}

/* Popup de una burbuja: reutiliza las clases .bubble__* dentro de la
   tarjeta. Deja aire para la × y separa un poco los bullets. */
.modal--bubble .bubble__head {
  padding-right: 28px;
}
.modal--bubble .bubble__bullets {
  margin-top: 24px;
}

/* ---------- Móvil: los popups salen desde abajo (bottom sheet) ---------- */
@media (max-width: 640px) {
  .modal {
    place-items: end center; /* anclado al fondo, centrado a lo ancho */
    padding: 0;
  }
  .modal__card {
    width: 100%;
    /* Altura fija: el borde superior queda siempre a la misma altura
       (arriba), da igual el contenido. Si sobra, queda espacio abajo; si
       falta, hace scroll dentro. */
    height: 82vh;
    max-height: 82vh;
    border-radius: 22px 22px 0 0; /* solo esquinas superiores */
    padding-bottom: calc(30px + env(safe-area-inset-bottom, 0px));
    transform: translateY(100%); /* fuera de pantalla, abajo */
  }
  .modal[data-open="true"] .modal__card {
    transform: translateY(0); /* sube hasta su sitio */
  }
}

.modal__close {
  position: absolute;
  top: 18px;
  right: 20px;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  color: var(--tl-subtitle);
  font-size: 20px;
  line-height: 1;
  transition: color 0.2s var(--ease), transform 0.14s var(--ease);
}
.modal__close:hover {
  color: var(--tl-title);
}
.modal__close:active {
  transform: scale(0.82);
}

.modal__head {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding-right: 28px;
}

.modal__logo {
  flex: none;
  width: auto;
  height: 17px;
  margin-top: 1px;
  filter: var(--logo-filter);
}

.modal__badge {
  flex: none;
  display: block;
  width: 20px;
  height: 20px;
}
.modal__badge .award__img {
  width: 20px;
  height: 20px;
}

/* Título del popup = mismo tamaño y color que el título de las burbujas */
.modal__title {
  color: var(--tl-title);
  font-size: var(--fs-tl);
  font-weight: var(--fw-regular);
  letter-spacing: 0.03em;
}

/* Fecha = mismo tamaño y color que el subtítulo de las burbujas */
.modal__date {
  margin-top: 2px;
  color: var(--tl-subtitle);
  font-size: var(--fs-tl);
}

/* Cuerpo = mismo tamaño y color que el subtítulo de las burbujas */
.modal__body {
  margin-top: 22px;
  color: var(--tl-subtitle);
  font-size: var(--fs-tl);
  line-height: 1.55;
}

.modal__action {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 26px;
  color: var(--tl-title);
  font-size: var(--fs-tl);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: opacity 0.2s var(--ease), transform 0.14s var(--ease);
}
.modal__action:hover {
  opacity: 0.6;
}
.modal__action:active {
  transform: scale(0.92);
}
.modal__action svg {
  flex: none;
  fill: none;
  stroke: currentColor;
}

.modal__photo {
  width: 100%;
  height: auto;
  margin-top: 20px;
  border-radius: 14px;
}

/* Pie de foto: mismo tamaño/color que el subtítulo, todo en itálica.
   Los nombres van en Inter Medium Italic; los cargos, Inter Italic. */
.modal__caption {
  margin-top: 16px;
  color: var(--tl-subtitle);
  font-size: var(--fs-tl);
  font-style: italic;
  line-height: 1.55;
}
.modal__caption .cap-name {
  font-weight: var(--fw-medium);
  font-style: italic;
}

/* ------------------------------------------------------------
   FOOTER
   ------------------------------------------------------------ */
.site-footer {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  max-width: var(--tl-max);
  margin: 0 auto;
  padding: 190px var(--tl-pad) 88px;
  color: var(--footer-text);
  font-size: var(--fs-date);
}

.site-footer__made {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--footer-text);
}

.site-footer__flag {
  width: 17px;
  height: auto;
}

.site-footer__right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
}

.clock {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--footer-text);
  font-size: var(--fs-date);
}

.clock__icon {
  width: 11px;
  height: 11px;
}

.site-footer__updated {
  color: var(--footer-updated);
  font-size: var(--fs-updated);
}

/* Enlace central del footer ("Go back to home page"), solo en páginas
   internas. Posicionado en absoluto para no alterar el space-between
   entre "Developed in the USA" y el reloj, que es lo que usa la home. */
.site-footer {
  position: relative;
}
.site-footer__back {
  position: absolute;
  left: 50%;
  bottom: 88px;
  transform: translateX(-50%);
  color: var(--footer-text);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  transition: color 0.2s var(--ease), transform 0.14s var(--ease);
}

/* En los artículos, la esquina izquierda del footer no lleva "Developed
   in the USA": lleva este enlace en su lugar (item normal del flex, no
   absoluto, para que ocupe el hueco de la bandera). */
.site-footer__corner {
  color: var(--footer-text);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  transition: color 0.2s var(--ease), transform 0.14s var(--ease);
}
.site-footer__corner:hover {
  color: var(--tl-title);
}
.site-footer__corner:active {
  transform: scale(0.94);
}
.site-footer__back:hover {
  color: var(--tl-title);
}
.site-footer__back:active {
  transform: translateX(-50%) scale(0.94);
}

/* ------------------------------------------------------------
   MASTHEAD (nombre arriba a la izquierda, páginas internas)
   ------------------------------------------------------------ */
.site-header__name {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 100;
  padding: 44px 48px;
  color: var(--text-strong);
  font-size: 0.875rem; /* 14px, un poco más grande que el --fs-ui de 12px */
  font-weight: var(--fw-medium);
  transition: opacity 0.2s var(--ease), transform 0.14s var(--ease);
}
.site-header__name:hover {
  opacity: 0.7;
}
.site-header__name:active {
  transform: scale(0.95);
}

/* ------------------------------------------------------------
   WRITINGS — índice
   ------------------------------------------------------------ */
.wr-main {
  max-width: 660px;
  margin: 0 auto;
  padding: 150px 24px 80px;
}

.wr-title {
  margin-bottom: 40px;
  color: var(--text-strong);
  font-size: var(--fs-h1);
  font-weight: var(--fw-medium);
  letter-spacing: -0.02em;
}

.wr-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: 28px;
  row-gap: 40px;
}

.wr-card {
  display: block;
}

/* ---------- Tarjeta 3D (estilo Apple TV): sólo se mueve la imagen ----------
   El contenedor se inclina siguiendo al puntero y lleva encima un brillo
   radial que también sigue al puntero. Las variables --rx/--ry/--mx/--my
   las escribe tilt.js; sin JS la tarjeta se queda plana y todo funciona. */
.wr-card__media {
  display: block;
  position: relative;
  border-radius: 6.5px;
  overflow: hidden;
  transform: perspective(900px)
    rotateX(var(--rx, 0deg))
    rotateY(var(--ry, 0deg))
    scale(var(--sc, 1));
  transform-style: preserve-3d;
  transition: transform 0.45s var(--ease), box-shadow 0.45s var(--ease);
  will-change: transform;
}

/* Estado activo: la transición se acorta para que siga al puntero sin
   sensación de retardo (la clase la pone/quita tilt.js). */
.wr-card__media.is-tilting {
  transition: transform 0.08s linear, box-shadow 0.3s var(--ease);
  box-shadow: 0 18px 40px -12px rgba(0, 0, 0, 0.28),
    0 6px 14px -6px rgba(0, 0, 0, 0.18);
}
[data-theme="dark"] .wr-card__media.is-tilting {
  box-shadow: 0 18px 40px -12px rgba(0, 0, 0, 0.7),
    0 6px 14px -6px rgba(0, 0, 0, 0.5);
}

/* Brillo que sigue al puntero */
.wr-card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(
    circle at var(--mx, 50%) var(--my, 50%),
    rgba(255, 255, 255, 0.38) 0%,
    rgba(255, 255, 255, 0.16) 28%,
    rgba(255, 255, 255, 0) 60%
  );
  opacity: var(--glare, 0);
  transition: opacity 0.3s var(--ease);
  pointer-events: none;
}

.wr-card__img {
  display: block;
  width: 100%;
  /* 16/9 = la proporción natural de las imágenes: prácticamente sin
     recorte lateral (antes 16/9.6 recortaba más de la cuenta). */
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--bubble-bg-muted);
}

/* El título sí reacciona al pasar por encima, pero no se mueve */
.wr-card:hover .wr-card__title {
  opacity: 0.75;
}
.wr-card__title {
  transition: opacity 0.2s var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  .wr-card__media,
  .wr-card__media.is-tilting {
    transform: none;
    transition: box-shadow 0.3s var(--ease);
  }
  .wr-card__media::after {
    display: none;
  }
}

.wr-card__title {
  margin-top: 14px;
  color: var(--text-strong);
  font-size: 0.9375rem; /* 15px */
  font-weight: var(--fw-medium);
  line-height: 1.35;
}

.wr-card__meta {
  margin-top: 4px;
  color: var(--tl-subtitle);
  font-size: var(--fs-tl);
}

.wr-card__meta time {
  font-style: italic;
}

/* Color de categoría por tarjeta (opcional): igual mecanismo que en el
   artículo — cada tarjeta puede fijar --cat-l/--cat-d inline; si no lo
   hace, se queda en el gris por defecto de .wr-card__meta. */
.wr-card__cat {
  color: var(--cat-l, inherit);
}
[data-theme="dark"] .wr-card__cat {
  color: var(--cat-d, inherit);
}

.wr-card__sep {
  margin: 0 1px;
}

/* ------------------------------------------------------------
   /PROJECTS — lista de proyectos (work) e investigación (research)
   ------------------------------------------------------------ */
.proj-main {
  max-width: 430px;
  margin: 0 auto;
  padding: 150px 24px 80px;
}

/* El título vive en un contenedor de 480px pero tiene que arrancar en
   el mismo borde izquierdo que el <h1> de /writings, cuyo contenedor
   (.wr-main) mide 660px. Centrados ambos, la diferencia es siempre
   (660-480)/2 = 90px, sin importar el ancho de ventana — así que basta
   un margen negativo fijo. Por debajo de 708px (660 + 2×24 de padding)
   .wr-main deja de estar centrado y pasa a ocupar todo el ancho, así
   que ahí se anula el desplazamiento. */
.proj-title {
  margin-left: -90px;
  margin-bottom: 130px;
}
@media (max-width: 708px) {
  .proj-title {
    margin-left: 0;
  }
}

.proj-section + .proj-section {
  margin-top: 44px;
}

.proj-label {
  margin-bottom: 6px;
  color: #413f3f;
  font-size: var(--fs-tl);
}

/* Un poco más de aire entre "research" y sus tarjetas que en "work". */
.proj-label--research {
  margin-bottom: 14px;
}

.proj-list {
  display: flex;
  flex-direction: column;
}

.proj-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 2px;
  color: inherit;
  text-decoration: none;
  transition: opacity 0.2s var(--ease);
}
/* Línea separadora fina: arranca a la altura del texto (después del logo),
   no por debajo del icono. El offset = ancho del icono + gap. */
.proj-item::after {
  content: "";
  position: absolute;
  left: 38px;
  right: 0;
  bottom: 0;
  border-bottom: 1px solid var(--bubble-border);
}
.proj-list .proj-item:last-child::after {
  border-bottom: none;
}
a.proj-item:hover {
  opacity: 0.7;
}
a.proj-item:active {
  transform: scale(0.99);
}

.proj-item__icon {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
}
.proj-item__icon img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.proj-item__icon svg {
  width: 16px;
  height: 16px;
  color: var(--text-muted);
}

/* AIGEA y /thelab quedaban un pelín grandes frente al resto de logos. */
.proj-item__icon img.proj-item__icon--sm {
  width: 76%;
  height: 76%;
  margin: auto;
}

/* Icono de "papel" de las tarjetas de research. Su propio contenedor
   (.proj-item--soon .proj-item__icon, más abajo) es más grande que el
   de los logos de "work", así que este porcentaje es sobre esa caja. */
.proj-item__icon--paper {
  display: block;
  width: 78%;
  height: 78%;
  margin: auto;
  background: #696969;
  -webkit-mask: url("/assets/svg/icon-paper.svg") no-repeat center / contain;
  mask: url("/assets/svg/icon-paper.svg") no-repeat center / contain;
}
[data-theme="dark"] .proj-item__icon--paper {
  background: #ededed;
}

/* Logos que no llevan color propio (todos menos AIGEA, que ya trae su
   paleta en el propio SVG): se pintan planos en gris con mask-image,
   igual que .ai-icon en el popover "Ask AI". */
.proj-item__icon--mono {
  display: block;
  width: 100%;
  height: 100%;
  background: #696969;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
[data-theme="dark"] .proj-item__icon--mono {
  background: #ededed;
}
.proj-item__icon--mono.proj-item__icon--sm {
  width: 76%;
  height: 76%;
  margin: auto;
}

.proj-item__text {
  display: flex;
  flex: 1;
  min-width: 0;
  flex-direction: column;
  gap: 0;
}

/* Misma tipografía que .bubble__title/.bubble__subtitle en /#about:
   Inter Regular, 12px. Los colores son los pedidos para esta página en
   concreto (no los tokens --tl-title/--tl-subtitle del timeline). */
.proj-item__title {
  color: #383838;
  font-family: var(--font-sans);
  font-size: var(--fs-tl);
  font-weight: var(--fw-regular);
}
[data-theme="dark"] .proj-item__title {
  color: #e4e4e4;
}

.proj-item__desc {
  margin-top: 1px;
  color: #828282;
  font-family: var(--font-sans);
  font-size: var(--fs-tl);
  font-weight: var(--fw-regular);
  line-height: 1.4;
}
[data-theme="dark"] .proj-item__desc {
  color: #8c8c8c;
}

.proj-item__arrow {
  flex: none;
  width: 8px;
  height: 8px;
  color: #d0d0d0;
}
[data-theme="dark"] .proj-item__arrow {
  color: #525252;
}

/* Investigaciones aún no publicadas: tarjeta gris redondeada. Cada una es
   una unidad independiente (una sola fila), así que no lleva línea propia
   por dentro — la línea separadora (ver ::before de abajo) flota en el
   hueco entre dos tarjetas, no pegada al borde de ninguna. */
.proj-item--soon {
  padding: 12px 16px;
  border-radius: 18px;
  background: #dedede;
  cursor: default;
}
[data-theme="dark"] .proj-item--soon {
  background: #0e0e0e;
}
.proj-item--soon::after {
  display: none;
}
.proj-item--soon + .proj-item--soon {
  margin-top: 17px;
}
/* Centrada en el hueco de 17px entre tarjetas (8.5px a cada lado). */
.proj-item--soon + .proj-item--soon::before {
  content: "";
  position: absolute;
  top: -8.5px;
  left: 60px;
  right: 20px;
  border-top: 1px solid var(--bubble-border);
}
/* Icono del paper: caja algo más grande que la de los logos de "work"
   para que el icon-paper (arriba) se vea más grande. */
.proj-item--soon .proj-item__icon {
  width: 32px;
  height: 32px;
}
/* El icono queda al mismo margen por la izquierda (12px) que ya tiene la
   tarjeta por arriba y por abajo — el tamaño del icono no cambia, solo su
   posición. El texto pega al icono con ese mismo margen (12px), en vez
   del gap heredado de "work". */
.proj-item--soon {
  padding-left: 12px;
  gap: 12px;
}
/* La línea flotante entre tarjetas se recalcula: 12 (padding) + 32 (icono)
   + 12 (gap) = 56px, para seguir arrancando justo después del icono. */
.proj-item--soon + .proj-item--soon::before {
  left: 56px;
}

/* Las tarjetas de research sobresalen un poco por ambos lados frente a
   "work" — con las esquinas tan redondeadas, queda mejor así que exactas
   al mismo ancho. */
.proj-list--research {
  margin-left: -14px;
  margin-right: -14px;
}

/* Subtítulo de research: un punto menos que el título (11px) y color
   propio. Va después de la regla dark para ganar en ambos temas. */
.proj-item--soon .proj-item__desc {
  font-size: calc(var(--fs-tl) - 1px);
  color: #828080;
}

@media (max-width: 640px) {
  .wr-grid {
    grid-template-columns: 1fr;
    row-gap: 32px;
  }
  .wr-main {
    padding-top: 120px;
  }
  .proj-main {
    padding-top: 120px;
  }
  .site-header__name {
    padding: 24px 24px;
  }
}

/* ------------------------------------------------------------
   TOGGLE DE IDIOMA (sólo en los artículos)
   Pastilla estilo iOS: el "pulgar" oscuro se desliza al otro lado.
   Cada opción es un enlace real a la otra versión del artículo, así
   funciona sin JS y es rastreable por Google.
   ------------------------------------------------------------ */
.lang-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 2px;
  border-radius: var(--radius-full);
  background: color-mix(in srgb, var(--surface) 55%, transparent);
  backdrop-filter: blur(18px) saturate(1.5);
  -webkit-backdrop-filter: blur(18px) saturate(1.5);
  border: 1px solid var(--surface-border);
  box-shadow: var(--surface-shadow);
}

/* El pulgar que se desliza */
.lang-toggle__thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: calc(50% - 2px);
  height: calc(100% - 4px);
  border-radius: var(--radius-full);
  background: var(--text-strong);
  transition: transform 0.32s var(--ease);
}
.lang-toggle[data-lang="es"] .lang-toggle__thumb {
  transform: translateX(100%);
}

.lang-toggle__opt {
  position: relative;
  z-index: 1;
  min-width: 30px;
  padding: 3px 8px;
  color: var(--text-muted);
  font-size: 10px;
  font-weight: var(--fw-medium);
  letter-spacing: 0.06em;
  text-align: center;
  transition: color 0.28s var(--ease);
}
/* La opción activa va sobre el pulgar oscuro */
.lang-toggle[data-lang="en"] .lang-toggle__opt[data-l="en"],
.lang-toggle[data-lang="es"] .lang-toggle__opt[data-l="es"] {
  color: var(--bg);
}
.lang-toggle__opt:active {
  transform: scale(0.9);
}

/* ------------------------------------------------------------
   ARTÍCULO
   ------------------------------------------------------------ */
.art-col {
  max-width: var(--art-col);
  margin: 0 auto;
  padding: 0 24px;
}

.art-wide {
  max-width: var(--art-hero);
  margin: 0 auto;
  padding: 0 24px;
}

.art-head {
  padding-top: 150px;
}

.art-kicker {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin-bottom: 10px;
  font-size: 12px;
}

/* La categoría (OPINION, EDITORIAL, ARTICLE…) lleva un color propio por
   artículo. --cat-l/--cat-d los define cada página en un <style> corto
   dentro del <head>; si un artículo no los define, cae en --accent. */
.art-kicker__cat {
  color: var(--cat-l, var(--accent));
  font-weight: 600;
  letter-spacing: normal;
  text-transform: uppercase;
}
[data-theme="dark"] .art-kicker__cat {
  color: var(--cat-d, var(--accent));
}

.art-kicker__date {
  color: var(--tl-subtitle);
}

.art-title {
  margin-bottom: 6px;
  color: var(--text-strong);
  font-size: 28px;
  font-weight: var(--fw-medium);
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.art-tagline {
  margin-bottom: 14px;
  color: var(--text-body);
  font-size: 16px;
  font-weight: var(--fw-regular);
  line-height: 1.45;
}

.art-author {
  color: var(--tl-subtitle);
  font-size: 13px;
  font-weight: var(--fw-medium);
}

/* Imagen de cabecera, con las esquinas redondeadas */
.art-hero {
  margin: 34px auto 52px;
}
.art-hero img {
  width: 100%;
  /* height:auto es imprescindible: los atributos width/height del <img>
     (que se mantienen para reservar espacio y evitar saltos de layout)
     harían la altura definida y anularían el aspect-ratio. */
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 6px;
  background: var(--bubble-bg-muted);
}

.art-body {
  color: var(--text-body);
  font-size: 14px;
  line-height: 1.8;
}
.art-body p + p {
  margin-top: 18px;
}
.art-body strong {
  font-weight: var(--fw-medium);
  color: var(--text-strong);
}
.art-body a {
  color: var(--text-strong);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.art-body h2 {
  margin: 34px 0 12px;
  color: var(--text-strong);
  font-size: 18px;
  font-weight: var(--fw-medium);
  line-height: 1.35;
}
/* Frase de cierre del artículo */
.art-closing {
  margin-top: 26px;
  color: var(--text-strong);
  font-weight: var(--fw-medium);
}

.art-body blockquote {
  margin: 26px 0;
  padding-left: 18px;
  border-left: 2px solid var(--tl-rule);
  color: var(--tl-subtitle);
}

/* ---------- Firma ----------
   El SVG se usa como máscara: así el trazo puede pintarse con un color
   plano y, después, con un degradado de luz que lo recorre.
   El "se está firmando" es un clip-path que se abre de izquierda a
   derecha, que es como se escribe la firma. */
.art-sign {
  display: flex;
  justify-content: flex-end;
  margin: 96px auto 0;
}

.signature {
  width: 190px;
  aspect-ratio: 250.843 / 27.507;
  background-color: var(--signature);
  -webkit-mask: url("/assets/svg/signature-ignacio.svg") no-repeat center / contain;
  mask: url("/assets/svg/signature-ignacio.svg") no-repeat center / contain;
  /* estado inicial: sin firmar */
  clip-path: inset(0 100% 0 0);
}

.signature.is-signing {
  clip-path: inset(0 0 0 0);
  transition: clip-path 2.2s cubic-bezier(0.55, 0.1, 0.35, 1);
}

/* Al terminar el trazo, un halo de luz lo recorre */
.signature.is-glowing {
  background-image: linear-gradient(
    100deg,
    rgba(255, 255, 255, 0) 30%,
    rgba(255, 255, 255, 0.55) 45%,
    rgba(255, 255, 255, 0.9) 50%,
    rgba(255, 255, 255, 0.55) 55%,
    rgba(255, 255, 255, 0) 70%
  );
  background-size: 260% 100%;
  background-repeat: no-repeat;
  animation: sign-glow 3.2s ease-in-out infinite;
}

@keyframes sign-glow {
  0% {
    background-position: 150% 0;
  }
  55%,
  100% {
    background-position: -60% 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .signature {
    clip-path: none;
    transition: none;
  }
  .signature.is-glowing {
    animation: none;
    background-image: none;
  }
}

@media (max-width: 640px) {
  .art-head {
    padding-top: 110px;
  }
  /* El bloque de cabecera (kicker, título, subtítulo, autor) va más
     apretado en móvil: menos aire entre cada línea. */
  .art-kicker {
    margin-bottom: 6px;
  }
  .art-title {
    margin-bottom: 4px;
    font-size: 24px;
  }
  .art-tagline {
    margin-bottom: 8px;
    font-size: 15px;
  }
  .art-hero {
    margin: 22px auto 38px;
  }
  .art-sign {
    margin-top: 64px;
  }
  .signature {
    width: 150px;
  }
  /* Un punto menos que en desktop (14px) */
  .art-body {
    font-size: 13px;
  }
}

/* ------------------------------------------------------------
   RESPONSIVE
   ------------------------------------------------------------ */
/* ============================================================
   MÓVIL / IPAD: el timeline pasa a UNA columna y las tarjetas se
   reordenan según --mo (definido en el HTML). El desktop no se toca:
   allí las tarjetas siguen colocándose por grid-row/column y `order`
   se ignora en los ítems de grid con colocación explícita.
   `display: contents` disuelve las columnas (.tl-stack) para que todas
   las tarjetas queden como hermanas y puedan intercalarse por --mo.
   ============================================================ */
@media (max-width: 1200px) {
  .timeline {
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-width: 560px;
    padding: 0 28px;
    transition: none; /* la transición de grid-rows no aplica en flex */
  }

  .tl-stack {
    display: contents;
  }

  /* orden desde la variable --mo de cada elemento */
  .timeline > *,
  .tl-stack > * {
    order: var(--mo, 500);
  }

  /* neutraliza el posicionamiento de escritorio de las tarjetas */
  .timeline .bubble,
  .timeline .pill {
    width: 100% !important;
    margin: 0 !important;
    flex: none !important;
    min-height: 0 !important;
  }

  .timeline .award {
    margin: 0 !important;
    align-self: start; /* enlace de texto, no ocupa todo el ancho */
  }

  /* Separadores de año a lo ancho, con aire por encima de cada grupo */
  .timeline__line {
    width: 100%;
    margin: 22px 0 2px !important;
  }
  .timeline > .timeline__line:first-of-type {
    margin-top: 4px !important;
  }

  .timeline__year {
    margin: 0 0 4px !important;
  }

  /* elementos que no van en la versión móvil */
  .m-hide {
    display: none !important;
  }
}

@media (max-width: 640px) {
  :root {
    --fs-h1: 1.875rem; /* 30px */
    --ascii-width: 210px;
  }

  .site-header {
    padding: 24px 24px;
  }

  /* El panel se ancla a .menu-group (que envuelve el botón ×): right: 0
     alinea su borde derecho con el borde derecho de la ×, y el top lo
     acerca un poco más al botón. */
  .menu-panel {
    top: calc(100% + 12px);
    right: 0;
  }

  .home {
    padding: 96px 24px 64px;
  }

  .contact {
    margin-top: 88px;
  }

  /* En pantallas estrechas los popovers de los extremos se anclan al borde
     para no salirse de la pantalla. */
  .contact__item:first-child .popover {
    left: 0;
    transform: translate(0, 6px) scale(0.96);
  }
  .contact__item:first-child .popover[data-open="true"] {
    transform: translate(0, 0) scale(1);
  }
  .contact__item:last-child .popover {
    left: auto;
    right: 0;
    transform: translate(0, 6px) scale(0.96);
  }
  .contact__item:last-child .popover[data-open="true"] {
    transform: translate(0, 0) scale(1);
  }
}

/* ------------------------------------------------------------
   /404 — página no encontrada
   ------------------------------------------------------------ */
.nf-main {
  max-width: 620px;
  margin: 0 auto;
  padding: 190px 24px 100px;
}

.nf-content {
  max-width: 420px;
}

.nf-code {
  display: inline-block;
  margin-bottom: 14px;
  color: var(--text-muted);
  font-size: var(--fs-ui);
  font-weight: var(--fw-medium);
  letter-spacing: 0.08em;
}

.nf-message {
  color: var(--text-strong);
  font-size: var(--fs-h1);
  font-weight: var(--fw-regular);
  line-height: 1.35;
  letter-spacing: -0.01em;
  margin-bottom: 28px;
}

.nf-back {
  color: var(--text-muted);
  font-size: var(--fs-ui);
}
.nf-back a {
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  transition: color 0.2s var(--ease);
}
.nf-back a:hover {
  color: var(--text-strong);
}

@media (max-width: 640px) {
  .nf-main {
    padding-top: 120px;
  }
}
