/* manueltorressahli.com — tokens and layout.
   Warm paper and a walnut brown for identity; a cold petrol accent so the
   page does not read as the clay-and-cream look everyone now associates with one AI
   company. Literata for reading, IBM Plex Sans for navigation and labels. */

:root {
  color-scheme: light;          /* el sitio es de papel claro y lo declara (D3) */
  --paper: #F7F4EE;
  --paper-2: #EFEAE1;
  --ink: #1C1A17;
  --walnut: #2A160C;
  --muted: #6B655C;
  --rule: #C9C1B2;              /* ≥ 1,6:1 sobre el papel; antes #D9D3C8 a 1,36:1 */
  --rule-soft: rgba(107, 101, 92, 0.6);   /* --muted al 60 %: al 40 % la píldora era
                                             casi invisible en un teléfono (V24) */
  --accent: #1F4E6E;
  --accent-2: #2E6E8E;
  --link-rule: rgba(31, 78, 110, 0.45);   /* subrayado permanente del enlace en prosa */
  --serif: "Literata", "Literata fallback", "Cambria", Georgia, serif;
  --sans: "IBM Plex Sans", "Plex fallback", "Segoe UI", system-ui, sans-serif;
  --measure: 44rem;             /* el único borde derecho de la página */
  --wide: 64rem;
  --gutter: 7rem;               /* columna de fecha + estado */

  /* Cuatro escalones bajo el cuerpo de texto. Antes había siete valores entre 0,74 y
     0,95 rem: pasos de medio píxel que nadie lee como jerarquía y que sí se ven como
     inconsistencia cuando dos caen uno al lado del otro (V14). */
  --fs-chip: 0.78rem;           /* píldora de estado, antetítulos */
  --fs-meta: 0.86rem;           /* fechas, referencias, atribuciones */
  --fs-sec: 0.94rem;            /* menú, apoyos, cuerpo secundario */
}

/* Alias métricos de las tipografías de reserva. Las webfonts se cargan en diferido y
   hasta que llegan la página se compone en Cambria y Segoe UI, cuyas métricas no
   coinciden con las de Literata e IBM Plex Sans: al intercambiarse, los párrafos se
   recomponían a la vista en cada carga fría (V18). Estos alias hacen que la reserva
   ocupe el mismo espacio que la definitiva, así que el intercambio no mueve nada.
   Medido con canvas en Chrome sobre las fuentes reales (2026-08-23): el ancho medio de
   Literata es 108,7 % del de Cambria y su ascenso/descenso 118/31 por em; el de IBM
   Plex Sans, 101,7 % del de Segoe UI, 103/28 por em. */
@font-face {
  font-family: "Literata fallback";
  src: local("Cambria"), local("Georgia"), local("Times New Roman");
  size-adjust: 108.7%;
  ascent-override: 108.6%;
  descent-override: 28.5%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Plex fallback";
  src: local("Segoe UI"), local("Arial");
  size-adjust: 101.7%;
  ascent-override: 101.2%;
  descent-override: 27.5%;
  line-gap-override: 0%;
}

* { box-sizing: border-box; }
html { font-size: 106.25%; }    /* relativo al tamaño elegido en el navegador */
body {
  margin: 0;
  min-height: 100dvh;           /* el pie no flota a media pantalla en las páginas
                                   cortas (Docencia, Vinculación, IA) — V19 */
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  line-height: 1.55;
}
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-2); text-decoration: underline; text-underline-offset: 0.15em; }
a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
img { max-width: 100%; height: auto; }

/* Enlace dentro de un texto corrido: subrayado permanente. El azul del enlace contra el
   negro del cuerpo da 1,96:1 y la técnica G183 pide 3:1 para distinguir por color solo,
   así que el color no puede ser la única marca (SC 1.4.1, nivel A — V04). Los enlaces
   sueltos (menú, fila de la portada, pie, el bloque de descarga del CV) quedan fuera:
   no están embebidos en un texto y la SC no los alcanza. */
p a, li a, .meta a, .artifact a, p.record a, details.legend a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
  text-decoration-color: var(--link-rule);
}
p a:hover, li a:hover, .meta a:hover, .artifact a:hover, p.record a:hover {
  text-decoration-color: currentColor;
}
.hero .links a, p.action a, nav.map a { text-decoration: none; }
.hero .links a:hover, nav.map a:hover { text-decoration: underline; }

/* skip link */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 20;
  font-family: var(--sans); font-size: var(--fs-sec);
  background: var(--paper-2); color: var(--ink);
  border: 1px solid var(--rule); padding: 0.6rem 1rem;
}
.skip:focus { left: 0.5rem; top: 0.5rem; }

/* header */
.site-header {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  width: 100%; max-width: var(--wide); margin: 0 auto; padding: 1.1rem 1.25rem;
}
.brand {
  display: flex; align-items: center; gap: 0.7rem; white-space: nowrap;
  color: var(--walnut); font-family: var(--sans); font-weight: 500; letter-spacing: 0.01em;
}
.brand:hover { text-decoration: none; }
nav.main { font-family: var(--sans); font-size: var(--fs-sec); }
nav.main a {
  color: var(--ink); margin-left: 1.1rem; padding-bottom: 0.2rem;
  border-bottom: 2px solid transparent; white-space: nowrap;
}
nav.main a:hover { text-decoration: none; border-color: var(--rule); }
nav.main a.active, nav.main a[aria-current="page"] { border-color: var(--accent); }

/* page frame */
main {
  width: 100%; max-width: var(--wide); margin: 0 auto; padding: 1rem 1.25rem 4rem;
  flex: 1 0 auto;
}
main:focus { outline: none; }   /* el destino del skip link es focalizable, no visible */
.measure { max-width: var(--measure); }
h1, h2, h3, h4 { font-family: var(--sans); font-weight: 600; line-height: 1.2; letter-spacing: -0.005em; }
h1 { font-size: 2.1rem; margin: 1.6rem 0 0.6rem; }
h2 {
  font-size: 1.25rem; margin: 2.4rem 0 0.8rem; padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--rule); color: var(--walnut);
  max-width: var(--measure);    /* el filete no se prolonga sobre el aire */
}
/* El único encabezado cuyo filete no para en la medida: el que abre las tarjetas, que
   ocupan el ancho completo. Su filete y el borde de las tarjetas comparten borde. */
h2.wide { max-width: none; }
h3 { font-size: 1.05rem; margin: 1.4rem 0 0.3rem; }
h4 { font-size: 1rem; margin: 1.2rem 0 0.3rem; }
p { margin: 0 0 1rem; max-width: var(--measure); }
ul, ol { max-width: var(--measure); }
.lead { font-size: 1.15rem; line-height: 1.5; }
.muted { color: var(--muted); }
.small { font-size: var(--fs-sec); }
.kicker { font-family: var(--sans); font-size: var(--fs-chip); text-transform: uppercase; letter-spacing: 0.08em; color: var(--accent); }
/* El antetítulo va sobre su encabezado, como en la portada. */
p.kicker { margin: 0 0 0.15rem; }
.kicker.section-kicker { margin: 2.4rem 0 0.15rem; scroll-margin-top: 1rem; }
.kicker.section-kicker + h2, .kicker.section-kicker + h3 { margin-top: 0; }
details.legend { margin: 0.4rem 0 1.6rem; max-width: var(--measure); }
details.legend summary { font-family: var(--sans); font-size: var(--fs-sec); color: var(--accent); cursor: pointer; }
details.legend summary:hover { color: var(--accent-2); }
details.legend p { margin: 0.5rem 0 0; }
ul.legend-list { margin: 0.6rem 0 0; padding-left: 1.2rem; }
ul.legend-list li { margin-bottom: 0.2rem; }

/* mapa de página ("En esta página"). Una entrada por línea: los títulos de las líneas
   ocupan casi la medida entera y envolviéndolos en una fila con separación pequeña dos
   entradas cortas caían juntas al final, sin nada que las separara. */
nav.map { margin: 0.6rem 0 1.4rem; max-width: var(--measure); }
nav.map ul {
  list-style: none; margin: 0; padding: 0;
  font-family: var(--sans); font-size: var(--fs-sec);
}
nav.map li { margin-bottom: 0.25rem; }

/* acción principal de una página (la descarga del CV) */
p.action { max-width: var(--measure); margin: 1.2rem 0 1.8rem; }
p.action a {
  display: inline-block; font-family: var(--sans); font-size: var(--fs-sec); font-weight: 500;
  padding: 0.55rem 1.1rem; background: var(--paper-2);
  border: 1px solid var(--rule); border-left: 3px solid var(--accent);
}
p.action a:hover { background: #fff; border-color: var(--accent); }

/* hero */
.hero {
  display: grid; grid-template-columns: minmax(0, 1fr) 220px; gap: 0 2.5rem;
  grid-template-areas: "head img" "body img";
  align-items: start; margin-top: 1rem;
}
.hero-head { grid-area: head; }
.hero-body { grid-area: body; }
.hero img { grid-area: img; width: 220px; border-radius: 4px; filter: saturate(0.92); }
.hero h1 { margin-top: 0.6rem; }
.hero .links { font-family: var(--sans); font-size: var(--fs-sec); max-width: none; }
.hero .links a { margin-right: 1rem; padding: 0.3rem 0; display: inline-block; }

/* research line cards */
.lines { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: 1.25rem; margin-top: 1rem; }
.line { background: #fff; border: 1px solid var(--rule); border-top: 3px solid var(--accent); padding: 1.1rem 1.2rem 1rem; }
.line h3 { margin-top: 0.2rem; }
.line p { font-size: var(--fs-sec); margin-bottom: 0.6rem; max-width: none; }
.line .status { font-family: var(--sans); font-size: var(--fs-chip); color: var(--muted); }

/* contact */
p.contact-head { font-family: var(--sans); font-size: var(--fs-sec); color: var(--muted); margin-bottom: 0.2rem; }
p.contact-mail { font-family: var(--sans); font-size: var(--fs-sec); margin-bottom: 0.35rem; }

/* work items — un solo borde derecho por página: el ítem entero (título, filete y
   párrafo) termina donde termina el filete del h2 (V10). */
.item {
  display: grid; grid-template-columns: var(--gutter) minmax(0, 1fr); gap: 1.25rem;
  max-width: var(--measure); padding: 1.1rem 0; border-bottom: 1px solid var(--rule);
}
/* El último ítem de un grupo no cierra con filete: el h2 siguiente ya abre con el suyo
   y quedaban dos filetes de distinto largo a 40 px uno del otro (V10). */
.item:not(:has(+ .item)) { border-bottom: none; }
.item .when {
  display: flex; flex-direction: column; align-items: flex-start; gap: 0.35rem;
  font-family: var(--sans); font-size: var(--fs-meta); color: var(--muted); padding-top: 0.25rem;
}
.item .when .status {
  display: inline-block; padding: 0.1rem 0.5rem; white-space: nowrap;
  border: 1px solid var(--rule-soft); border-radius: 999px;
  font-size: var(--fs-chip); color: var(--ink); background: var(--paper-2);
}
.item h3, .item h4 { font-size: 1.15rem; margin: 0 0 0.3rem; max-width: none; }
.item .title-es { font-size: var(--fs-meta); color: var(--muted); font-style: italic; margin: -0.1rem 0 0.35rem; }
.item .with { font-size: var(--fs-sec); color: var(--muted); margin-bottom: 0.5rem; }
.item p.headline { margin-bottom: 0.5rem; max-width: none; }
.item .artifact { font-family: var(--sans); font-size: var(--fs-meta); }
p.artifact { font-family: var(--sans); font-size: var(--fs-meta); margin-bottom: 1rem; }

/* publications */
ol.pubs { padding-left: 1.6rem; max-width: var(--measure); }
ul.pubs.selected { list-style: none; padding-left: 0; }
p.record { margin: 1.6rem 0 0; padding: 0.8rem 1rem; border-left: 3px solid var(--accent); background: var(--paper-2); font-size: var(--fs-sec); }
ol.pubs li, ul.pubs li { margin-bottom: 0.8rem; padding-left: 0.2rem; max-width: none; }
ol.pubs .meta, ul.pubs .meta { color: var(--muted); font-size: var(--fs-meta); }
/* `anywhere` partía el DOI aunque hubiera un corte normal disponible: sólo el DOI, que
   no tiene otro sitio por donde partir, puede romperse en cualquier carácter (V15). */
.meta { overflow-wrap: break-word; }
.meta .doi { overflow-wrap: anywhere; }

/* entries (record) */
.entry { display: grid; grid-template-columns: 8.5rem minmax(0, 1fr); gap: 1.25rem; max-width: var(--measure); padding: 0.7rem 0; }
/* Sin fecha, el carril queda vacío pero la columna de contenido no se mueve (V17). */
.entry.nodate > * { grid-column: 2; }
.entry .when { font-family: var(--sans); font-size: var(--fs-meta); color: var(--muted); padding-top: 0.2rem; }
.entry h3.title, .entry h4.title {
  display: inline; font-family: var(--serif); font-size: 1rem; font-weight: 600;
  line-height: inherit; letter-spacing: normal; margin: 0; color: inherit;
}
.entry .meta { color: var(--muted); }
/* Separador entre el cargo y la institución: el único signo que los separaba era el
   cambio de color, y al envolver en 360 px el lector tenía que releer (V16). El
   interpunto es decorativo y no se anuncia. */
.entry .meta::before { content: " · "; content: " · " / ""; }
.entry p { margin: 0.2rem 0 0; font-size: var(--fs-sec); max-width: none; }
/* Una cursiva azul dentro de una entrada es un enlace, no la traducción de un título:
   se le quita la cursiva para que las dos cosas no compartan forma (V19). */
.entry a em, .entry em a { font-style: normal; }

/* footer */
.site-footer { border-top: 1px solid var(--rule); margin-top: 3rem; }
.site-footer .inner {
  max-width: var(--wide); margin: 0 auto; padding: 1.5rem 1.25rem 2.5rem;
  font-family: var(--sans); font-size: var(--fs-meta); color: var(--muted);
  display: flex; flex-wrap: wrap; justify-content: center; align-items: baseline;
  gap: 0.15rem 0.6rem; text-align: center;
}
/* El separador cuelga del span ANTERIOR: al envolver queda al final de la línea y
   nunca huérfano al principio de la siguiente. Es decorativo: NVDA y JAWS leen el
   contenido generado y anunciaban un "punto medio" por grupo (V22). */
.site-footer .inner span:not(:last-child)::after {
  content: "\00a0·"; content: "\00a0·" / ""; color: var(--muted);
}
.site-footer a { padding: 0.3rem 0; display: inline-block; }

/* cabecera intermedia: entre 761 y ~1100 px la marca se apila sobre el menú y el
   menú envuelve por ítems completos, nunca partiendo una etiqueta por dentro */
@media (max-width: 1100px) {
  .site-header { flex-direction: column; align-items: flex-start; gap: 0.6rem; }
  /* Las filas del menú se tocaban: un toque un píxel sobre "Docencia" activaba
     "Inicio", y el subrayado de página actual quedaba pegado a la fila siguiente y se
     leía como suyo (V08). Con esta separación cada ítem mide 44 px de alto, y con el
     escalón de tamaño de menos los siete caben en una sola fila a 768 px, donde antes
     "CV" quedaba huérfano en una segunda fila. */
  nav.main { display: flex; flex-wrap: wrap; gap: 0.75rem 0.85rem; font-size: var(--fs-meta); }
  nav.main a { margin-left: 0; padding: 0.7rem 0 0.5rem; }
}

@media (max-width: 760px) {
  html { font-size: 100%; }
  /* El retrato acompaña al nombre en la primera pantalla (V11). */
  .hero { grid-template-columns: minmax(0, 1fr) 120px; grid-template-areas: "head img" "body body"; gap: 0 1rem; }
  .hero img { width: 120px; }
  .hero h1 { font-size: 1.8rem; }
  .lines { grid-template-columns: 1fr; }
  .item, .entry { grid-template-columns: 1fr; gap: 0.2rem; }
  .entry.nodate > * { grid-column: auto; }
  .item .when { flex-direction: row; align-items: center; gap: 0.5rem; }
}

/* impresión: la página se circula en papel dentro de un comité (V23) */
@media print {
  :root {
    --paper: #fff; --paper-2: #fff; --ink: #000; --walnut: #000;
    --muted: #333; --accent: #000; --accent-2: #000; --rule: #999;
    --rule-soft: #999; --link-rule: #000;
  }
  @page { margin: 2cm; }
  body { background: #fff; color: #000; }
  .skip, nav.main, nav.map { display: none; }
  .line, p.record, p.action a, .item .when .status { background: transparent; }
  a { color: #000; }
  main { max-width: none; padding: 0; }
  /* El destino de un enlace externo no se pierde al imprimir; los internos y los de
     correo se leen solos. */
  main a[href^="http"]::after {
    content: " (" attr(href) ")"; content: " (" attr(href) ")" / "";
    font-size: 0.85em; word-break: break-all;
  }
  .site-footer a::after { content: none; }
  .item, .entry, .line { break-inside: avoid; }
}
