/* ============================================================
   duqe — estilos de blog (listado, tarjetas y artículo)
   Reutiliza tokens y tipografía de base.css
   ============================================================ */

/* ---- rejilla de entradas ----

   EL FILETE GRIS VA EN LA TARJETA, NO EN EL FONDO DEL CONTENEDOR.

   El truco de antes era el clásico: fondo gris en la rejilla, hueco de 1 px
   entre celdas y tarjetas blancas encima. Funciona de maravilla mientras la
   rejilla esté llena. Con una sola entrada publicada, ese fondo asomaba
   entero y pintaba una raya gris a todo lo ancho justo debajo de la
   destacada — cualquiera habría jurado que era un separador puesto a
   propósito. Y en la página de búsqueda con uno o dos resultados dejaba un
   bloque gris en las celdas sobrantes.

   Con el filete en la tarjeta (un box-shadow de 1 px hacia fuera, que se
   solapa con el de la vecina en el hueco de 1 px y se lee como una sola
   línea), una rejilla a medias simplemente tiene menos tarjetas. */
.posts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
}
/* Columnas ajustadas al número real de tarjetas. La clase la ponen
   home.php, index.php y single.php contando entradas. */
.posts--1 { grid-template-columns: minmax(0, 1fr); }
.posts--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.posts--1 .post { min-height: auto; }
/* Cinturón y tirantes: si alguna vez llegase vacía, que no ocupe sitio. */
.posts:empty { display: none; }

.post {
  background: var(--paper);
  box-shadow: 0 0 0 1px var(--line);
  padding: clamp(26px, 2.6vw, 38px);
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 304px;
  transition: background .3s var(--ease);
}
.post:hover { background: var(--paper-2); }
.post__cat {
  font-size: 11.5px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--muted); font-weight: 700;
}
.post__t {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(21px, 1.9vw, 27px); line-height: 1.06; letter-spacing: -0.02em;
}
.post__ex { color: var(--ink-2); font-size: 15px; line-height: 1.5; margin-top: auto; }
.post__meta { font-size: 13px; color: var(--faint); font-weight: 600; letter-spacing: 0.01em; }
/* El "Leer →" estaba a opacity:0 hasta el hover. El problema es que el
   separador " · " que lo precede lo imprime duqe_post_card() como texto
   suelto, así que toda tarjeta en reposo terminaba con un punto colgando:
   "16 Jul 2026 · 18 min ·". Dejando la flecha visible pero atenuada, el
   separador vuelve a separar algo y el hover sigue teniendo su gesto.
   El arreglo de raíz es quitar ese " · " final de la cadena de
   inc/template-helpers.php; si se hace, aquí se puede volver a opacity:0. */
/* El separador va pegado a la flecha y no dentro de la cadena traducible: así
   aparece y desaparece con ella en vez de quedarse colgando al final. */
/* El punto medio va como escape CSS y no como carácter literal: los .css
   del tema se sirven sin declarar charset, y un byte no ASCII dentro de
   `content` depende entonces de cómo lo interprete el navegador. El espacio
   que cierra el escape es obligatorio; el aire alrededor lo da el padding. */
.post__arrow::before { content: "\00B7 "; padding-inline: 6px 4px; color: var(--faint); }
.post__arrow { display: inline-block; font-family: var(--font-display); font-weight: 700; font-size: 15px; color: var(--faint); transition: color .3s var(--ease), transform .3s var(--ease); }
.post:hover .post__arrow { color: var(--ink); transform: translateX(3px); }

@media (max-width: 900px) { .posts { grid-template-columns: 1fr; } }

/* ---- cabecera de página de blog ---- */
.bloghead { padding: clamp(40px, 7vw, 96px) 0 clamp(36px, 5vw, 64px); }
.bloghead .eyebrow { display: block; margin-bottom: 26px; }
.bloghead h1 { font-size: clamp(34px, 4vw, 72px); font-weight: 800; line-height: 0.92; letter-spacing: -0.03em; }
.bloghead p { color: var(--ink-2); max-width: 50ch; margin-top: 26px; font-size: clamp(17px, 1.5vw, 20px); }

.chips { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 34px; }
.chip {
  font-family: var(--font-body); font-weight: 600; font-size: 14px;
  padding: 9px 18px; border-radius: 100px; border: 1.5px solid var(--line);
  color: var(--ink-2); cursor: pointer; transition: all .2s var(--ease); background: transparent;
}
.chip:hover { border-color: var(--ink); color: var(--ink); }
.chip.is-on { background: var(--ink); color: var(--paper); border-color: var(--ink); }

/* ---- entrada destacada ---- */
.featured {
  display: grid; grid-template-columns: 1.1fr 0.9fr; gap: clamp(28px, 4vw, 64px);
  align-items: stretch; padding: clamp(34px, 4vw, 56px) 0; border-top: 1px solid var(--line-strong); border-bottom: 1px solid var(--line);
  margin-bottom: clamp(40px, 6vw, 72px);
}
.featured__media { border-radius: 16px; overflow: hidden; min-height: 320px; }
.featured__txt { display: flex; flex-direction: column; gap: 18px; align-self: center; }
.featured__txt .post__cat { color: var(--ink); }
.featured__txt h2 { font-size: clamp(32px, 4vw, 60px); font-weight: 800; line-height: 0.98; letter-spacing: -0.025em; }
.featured__txt p { color: var(--ink-2); font-size: 17px; line-height: 1.55; max-width: 48ch; }
.featured__meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; font-size: 14px; color: var(--faint); font-weight: 600; }
/* La firma era un .article__cat con tres declaraciones en un atributo style
   para deshacer las versales y el interletrado que esa clase le imponía.
   Ahora tiene la suya y la plantilla queda sin estilos en línea. */
.featured__by { color: var(--ink-2); font-weight: 700; }
@media (max-width: 860px) { .featured { grid-template-columns: 1fr; } .featured__media { min-height: 220px; } }

/* ---- placeholder de imagen (rayado, monoespaciado) ---- */
.ph {
  position: relative; width: 100%; height: 100%; min-height: inherit;
  background:
    repeating-linear-gradient(135deg, #e7e3db 0 12px, #efece6 12px 24px);
  display: grid; place-items: center;
}
.ph::after {
  content: attr(data-label);
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: 12px; letter-spacing: 0.06em; color: var(--ink-2);
  background: var(--paper); padding: 8px 14px; border-radius: 100px; border: 1px solid var(--line-strong);
}

/* ---- artículo ----

   UN SOLO BORDE IZQUIERDO.

   Hasta septiembre de 2026 la entrada tenía tres ejes distintos: la portada
   centrada a 1040 px, la cabecera a 820 y el texto a 720. Los tres
   centrados, sí, pero a anchos distintos, así que ninguno se alineaba con
   ninguno: el título y la categoría colgaban 50 px a la izquierda del primer
   párrafo. Da sensación de descuido aunque nadie sepa decir por qué.

   Ahora la cabecera, la portada y el bloque índice+texto miden lo mismo
   (--art-w) y arrancan en el mismo punto. El texto empieza donde empieza su
   columna, que es la segunda de la rejilla: el índice ocupa justo el hueco
   que antes estaba vacío. Las medidas van en variables para que los cuatro
   números no se puedan desincronizar por accidente. */
.article {
  padding: clamp(36px, 5vw, 72px) 0 clamp(60px, 8vw, 110px);

  --toc-w: 232px;   /* ancho del índice lateral */
  --toc-gap: 56px;  /* separación entre el índice y el texto */
  --read-w: var(--prose-measure, 720px);  /* medida de lectura */
  --art-w: 1008px;  /* 232 + 56 + 720 = el bloque entero */
}
.article__head { max-width: var(--art-w); margin: 0 auto clamp(34px, 4vw, 52px); }
.article__cat { font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
/* El titular no se estira hasta los 1008: se queda en una medida legible,
   pero alineado al borde izquierdo del bloque, no centrado dentro de él. */
.article__head h1 { max-width: 880px; font-size: clamp(36px, 5.4vw, 72px); font-weight: 800; line-height: 1.0; letter-spacing: -0.025em; margin: 22px 0 24px; }
/* flex-wrap: en 390 px estos metadatos se partían en dos líneas y dejaban
   los puntos separadores descolgados al final de la primera. */
.article__meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 14px; font-size: 14.5px; color: var(--faint); font-weight: 600; }
.article__meta .av { flex: none; width: 34px; height: 34px; border-radius: 50%; background: var(--ink); color: var(--paper); display: grid; place-items: center; font-family: var(--font-display); font-weight: 700; font-size: 14px; }
/* Los "·" son decorativos (van aria-hidden en la plantilla): que no compitan
   con el dato que separan. */
.article__sep { opacity: .5; }
@media (max-width: 620px) {
  /* En pantallas estrechas el espacio ya separa de sobra. */
  .article__meta .article__sep { display: none; }
}
.article__cover { max-width: var(--art-w); margin: 0 auto clamp(36px, 5vw, 60px); border-radius: 18px; overflow: hidden; aspect-ratio: 16/8; }

/* Aquí vivía una segunda declaración de `.prose` —cuerpo, encabezados, cita,
   listas y enlaces—, y una tercera más abajo en el bloque de tamaños. Entre las
   tres y la de front-page.css, el motor tipográfico de todo el contenido largo
   del sitio estaba declarado en tres sitios que se pisaban por especificidad y
   por orden de carga, y ganaba el que ganase según la página. Ahora `.prose`
   se define **solo** en help.css, que es el archivo que llevaba ya la escala de
   las páginas legales y del contenido largo.

   Esto depende de que help.css se encole también en las entradas del blog. Lo
   hacía solo `if ( is_page() )` y una entrada es `is_single()`, así que hubo que
   ampliar la condición en functions.php ANTES de borrar esto. Si algún día
   alguien vuelve a estrechar ese encolado, los artículos se quedarán sin
   tipografía de golpe. */

.article__foot { max-width: 720px; margin: clamp(40px, 5vw, 64px) auto 0; padding-top: 28px; border-top: 1px solid var(--line); display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap; }
.backlink { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-display); font-weight: 600; }

/* ---- paginación (cuando hay muchas entradas) ---- */
.duqe-pagination { margin-top: clamp(40px, 6vw, 72px); }
.duqe-pagination .nav-links {
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  gap: 8px;
}
.duqe-pagination .page-numbers {
  font-family: var(--font-display); font-weight: 600; font-size: 15px;
  min-width: 44px; height: 44px; padding: 0 14px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--line); border-radius: 100px;
  color: var(--ink-2); transition: all .2s var(--ease);
}
.duqe-pagination a.page-numbers:hover { border-color: var(--ink); color: var(--ink); }
.duqe-pagination .page-numbers.current {
  background: var(--ink); color: var(--paper); border-color: var(--ink);
}
.duqe-pagination .page-numbers.dots { border-color: transparent; min-width: auto; padding: 0 4px; }
.duqe-pagination .prev, .duqe-pagination .next { padding: 0 22px; }

/* ---- formulario de búsqueda ---- */
.duqe-search { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 30px; }
.duqe-search__input {
  font-family: var(--font-body); font-size: 16px;
  padding: 13px 20px; border: 1.5px solid var(--line); border-radius: 100px;
  background: var(--paper); color: var(--ink); min-width: 260px; flex: 1;
}
/* Sin `outline: none`: `:focus-visible` es un subconjunto de `:focus`, y esta
   regla (0-2-0) le gana a la global de base.css (0-1-0), así que borraba el
   anillo de teclado del buscador. Solo se oscurece el borde. */
.duqe-search__input:focus { border-color: var(--ink); }

/* ============================================================
   AJUSTES DE TAMAÑO (duqe) — titulares menos abrumadores
   Sobreescriben los tamaños de arriba. Para volver al diseño
   original, elimina este bloque.
   ============================================================ */

/* Cabecera del blog: "Menos pantalla, más vida" — era enorme (hasta 150px) */
.bloghead h1 { font-size: clamp(34px, 4vw, 72px); line-height: 0.98; }
.bloghead p { font-size: clamp(15px, 1vw, 17px); }
.bloghead { padding: clamp(16px, 2vw, 28px) 0 clamp(20px, 2.5vw, 32px); }

/* Entrada destacada */
.featured__txt h2 { font-size: clamp(22px, 2vw, 30px); }
.featured__txt p { font-size: 15px; }
.featured__media { min-height: 200px; }
.featured { padding: clamp(24px, 3vw, 40px) 0; gap: clamp(20px, 3vw, 40px); }

/* Título de la entrada individual */
.article__head h1 { font-size: clamp(26px, 2.6vw, 38px); }

/* Los cuatro tamaños de `.prose` que había aquí se han ido a help.css con el
   resto de la escala tipográfica. Ver la nota de arriba. */

/* Tarjetas de entrada: más compactas (menos alto y relleno) */
.post__t { font-size: clamp(17px, 1.2vw, 19px); }
.post { min-height: 180px; padding: clamp(20px, 1.8vw, 26px); gap: 10px; }
.post__ex { font-size: 14px; }
.post__meta { font-size: 12px; }

/* ============================================================
   ENTRADA: ÍNDICE LATERAL Y PROGRESO DE LECTURA
   ------------------------------------------------------------
   El ensayo del blog mide casi 11.000 px de scroll: doce pantallas sin un
   solo punto de referencia. Y los 288 px muertos a cada lado del texto no
   eran aire de diseño, era sitio desaprovechado. El índice y el progreso
   resuelven las dos cosas a la vez.

   ESTE BLOQUE ES AUTOSUFICIENTE A PROPÓSITO. El índice de la entrada
   comparte con el de las páginas legales el JavaScript —que solo busca los
   IDs #legal-content y #legal-toc-nav— pero NO las clases. Así el aspecto
   del índice del blog vive entero aquí, en una hoja que se encola siempre, y
   no depende de que help.css llegue a las entradas.

   El mismo motivo por el otro lado: como aquí no se escribe ni una regla
   .legal-toc ni .legal-layout (salvo el modificador --solo, comentado más
   abajo), las páginas legales no pueden verse afectadas por nada de esto.
   ============================================================ */

.article-layout {
  display: grid;
  grid-template-columns: var(--toc-w) minmax(0, var(--read-w));
  gap: var(--toc-gap);
  align-items: start;
  max-width: var(--art-w);
  margin-inline: auto;
}

/* El cuerpo NO se centra dentro de su columna: se pega al borde izquierdo,
   que es el eje de lectura de toda la página. (.prose lleva "margin: 0 auto"
   porque en el resto del sitio va suelto y centrado.)
   Es lo único que este archivo le dice a .prose, y es colocación, no
   tipografía: la escala del cuerpo de texto se decide en otro sitio. */
.article-layout .prose { max-width: var(--read-w); margin-inline: 0; }

/* Que la cabecera fija no tape el apartado al saltar a un ancla. */
.article-main .prose h2,
.article-main .prose h3 { scroll-margin-top: calc(var(--nav-h, 90px) + 6px); }

/* ---- El índice ----
   --nav-h es el alto real de la barra de navegación pegajosa. Hoy lo define
   help.css, que en las entradas puede no estar encolado: de ahí el valor de
   respaldo. Lo suyo es que ese número se mude a base.css y lo compartan la
   página y el blog, porque es el mismo número y ahora vive en dos sitios. */
.article-toc { position: sticky; top: var(--nav-h, 90px); }
/* Con la barra de admin de WordPress visible (32 px, 46 en móvil). */
.admin-bar .article-toc { top: calc(var(--nav-h, 90px) + 32px); }
@media screen and (max-width: 782px) {
  .admin-bar .article-toc { top: calc(var(--nav-h, 90px) + 46px); }
}

/* El <nav> lo rellena el JavaScript. Sin JavaScript se queda vacío, y
   entonces quedaría un rótulo "EN ESTE ARTÍCULO" presidiendo la nada:
   mientras no haya enlaces dentro, la caja no existe. (Si el navegador no
   entiende :has(), se ve el rótulo suelto — que es exactamente lo que se ve
   hoy en las páginas legales, así que no empeora nada.) */
.article-toc__inner:not(:has(.article-toc__nav a)) { display: none; }

.article-toc__title {
  display: block; font-family: var(--font-display); font-weight: 700;
  font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 16px;
}
.article-toc__nav { display: flex; flex-direction: column; gap: 2px; }
.article-toc__nav a {
  font-size: 14px; line-height: 1.4; color: var(--ink-2);
  padding: 7px 0 7px 14px; border-left: 2px solid var(--line);
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.article-toc__nav a:hover { color: var(--ink); border-left-color: var(--muted); }

/* EL APARTADO QUE SE ESTÁ LEYENDO.
   Es una de las dos únicas apariciones del rojo en toda la entrada (la otra
   es la barra de progreso), y aquí el color no decora: significa "estás
   aquí". El filo va en --red, que es color de forma; la letra en --red-ink,
   que es el que aguanta el contraste a 14 px. */
.article-toc__nav a.is-current {
  color: var(--red-ink); border-left-color: var(--red); font-weight: 600;
}
/* Si lo activo es un subapartado, su H2 padre se queda encendido en negro
   para no perder el contexto. Sin rojo: solo puede haber un "estás aquí". */
.article-toc__nav a.is-parent { color: var(--ink); border-left-color: var(--faint); }

/* Subapartados (H3): sangrados y un punto más discretos. */
.article-toc__nav a.toc-link--h3 { padding-left: 28px; font-size: 13.5px; color: var(--muted); }
.article-toc__nav a.toc-link--h3:hover { color: var(--ink); }
/* Va después de .is-current a propósito: si no, la regla de arriba, que
   tiene la misma especificidad y viene antes, perdería el color. */
.article-toc__nav a.toc-link--h3.is-current { color: var(--red-ink); }

.article-toc__back {
  display: block; margin-top: 26px; padding-top: 20px;
  border-top: 1px solid var(--line);
  font-family: var(--font-display); font-weight: 600; font-size: 13.5px;
  color: var(--muted); transition: color .2s var(--ease);
}
.article-toc__back:hover { color: var(--ink); }

/* ---- Sin índice ----
   interactions.js esconde el <aside> y pone .legal-layout--solo en el
   contenedor cuando el texto tiene menos apartados que los que pide
   data-toc-min. Aquí solo se atiende el caso de la entrada: el de las
   páginas de contenido lo resuelve help.css por su cuenta, porque allí el
   layout es flex y no rejilla. Este archivo no escribe ni una regla que
   pueda alcanzar a esas páginas. */
.article-toc[hidden] { display: none; }
.article-layout.legal-layout--solo { grid-template-columns: minmax(0, 1fr); }

/* Y, ya puestos, la cabecera y la portada se encogen a la medida de lectura
   para que sigan compartiendo borde con el texto. Si el navegador no
   entiende :has() simplemente no pasa nada: se queda el bloque alineado a la
   izquierda, que también está alineado, solo que más ancho. */
.article:has(.legal-layout--solo) { --art-w: var(--read-w); }

/* ---- Barra de progreso de lectura ----
   3 px, arriba del todo, sin porcentaje y sin animación de relleno. La
   cabecera anuncia "18 min de lectura" y hasta ahora no daba ninguna pista
   de cuánto llevabas, que es lo que convierte ese número en información en
   vez de en una advertencia. Un contador de "% leído" o un círculo que se
   rellena sería justo el enganche que esta marca rechaza: esto es una barra
   de estado. */
.readbar {
  position: fixed; inset: 0 0 auto 0; height: 3px;
  z-index: 60;              /* la cabecera del sitio está en 50 */
  pointer-events: none; background: transparent;
}
.readbar__fill {
  display: block; height: 100%; width: 0;
  background: var(--red);
  transition: width .1s linear;
}
.admin-bar .readbar { top: 32px; }
@media screen and (max-width: 782px) { .admin-bar .readbar { top: 46px; } }
@media (prefers-reduced-motion: reduce) { .readbar__fill { transition: none; } }

/* ---- "Sigue leyendo" ----
   Mismo aspecto que el .more h4 de front-page.css, pero en un <h2>: un <h4>
   detrás del <h1> del artículo se salta dos niveles de encabezado, y quien
   navega por encabezados con un lector de pantalla se pierde ese salto. */
.more__title {
  font-family: var(--font-display); font-weight: 800; font-size: 13px;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted);
  line-height: 1.2; margin-bottom: 28px;
}

/* ---- Estados vacíos (blog sin entradas, búsqueda sin resultados) ----
   Eran una .posts de una columna con border:none y background:none escritos
   como atributos style dentro de la plantilla, y el mensaje iba dentro de un
   .post — o sea, disfrazado de tarjeta que no se puede pulsar. */
.blog-empty {
  max-width: 60ch;
  padding: clamp(32px, 5vw, 56px) 0;
  border-top: 1px solid var(--line-strong);
}
.blog-empty__title {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(20px, 2vw, 26px); letter-spacing: -0.02em;
  line-height: 1.15; color: var(--ink);
}
.blog-empty__text { margin-top: 12px; color: var(--ink-2); font-size: 16px; line-height: 1.6; }

/* ---- Índice en pantallas medianas y pequeñas ---- */
@media (max-width: 1080px) {
  /* La columna del índice estorba antes de que estorbe el texto. */
  .article { --toc-w: 200px; --toc-gap: 40px; }
}
@media (max-width: 860px) {
  /* El índice deja de ser columna y pasa arriba, metido en una caja. Con los
     subapartados dentro serían once líneas antes del primer párrafo, así que
     aquí se queda solo con los apartados de primer nivel y funciona como
     sumario. El enlace de "todas las entradas" tampoco pinta nada: el pie y
     el final del artículo ya lo ofrecen. */
  .article-layout { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .article-toc { position: static; }
  .article-toc__inner { background: var(--paper-2); border-radius: 14px; padding: 18px 20px; }
  .article-toc__nav a { padding: 6px 0 6px 14px; }
  .article-toc__nav a.toc-link--h3 { display: none; }
  .article-toc__back { display: none; }
}


/* ---------- marca en las cabeceras del blog ----------
   El mismo filete rojo de las cabeceras de página, para que el blog no
   parezca de otro sitio. Ver la nota larga en help.css. */
.bloghead .eyebrow, .article__cat {
  position: relative; display: inline-block; padding-top: 16px;
}
.bloghead .eyebrow::before, .article__cat::before {
  content: ""; position: absolute; top: 0; left: 0;
  width: 34px; height: 3px; background: var(--red); border-radius: 2px;
}
/* El chip de la categoría en uso: relleno rojo, que es un estado — el mismo
   criterio que el idioma activo del selector. Blanco sobre --red-ink da
   5,88:1, y hace falta de sobra porque la etiqueta va pequeña. */
.chip.is-on { background: var(--red-ink); color: #fff; border-color: var(--red-ink); }
.chip.is-on:hover { background: var(--red); border-color: var(--red); }
