/* Blog InfectoLab — cuatro plantillas navegables
 * 1) Índice /blog/   2) Artículo /blog/<slug>/
 * 3) Autor /dr-samuel-navarro-alvarez/   4) Archivo temático /category/<slug>/
 * Datos: window.BLOG_DATA (src/blog-data.js). Sustituir por API/CMS.
 */

/* Hoja de estilo del blog.
 * Vive DENTRO del componente, como en pages-sucursales.jsx: viaja con el JSX,
 * no puede quedar desfasada respecto al marcado ni depender del caché de
 * styles.css. Mismo lenguaje visual que el bloque Blog del Home. */
function BlogStyles() {
  return <style>{`
/* ── Fundamentos ── */
.bl { --bl-navy:#1D2A4D; --bl-azul:#3953A4; --bl-aqua:#7EB9C7; --bl-amar:#FDC345;
  --bl-borde:#E3E6EE; --bl-fondo:#F5F6FA; --bl-tinta:#14182A; --bl-muted:#6B7180; }
.bl main, .bl { color: var(--bl-tinta); }
.bl-narrow { max-width: 720px; margin-left: auto; margin-right: auto; }
.bl-muted { color: var(--bl-muted); }

/* ── Hero editorial ── */
.bl-hero { position: relative; overflow: hidden; background: var(--bl-navy);
  padding: 76px 0 72px; }
.bl-hero::before { content:""; position:absolute; inset:0; z-index:0;
  background-image: radial-gradient(rgba(255,255,255,.05) 1.4px, transparent 1.4px);
  background-size: 30px 30px; }
.bl-hero::after { content:""; position:absolute; top:-180px; right:-140px;
  width:520px; height:520px; border-radius:50%; background: var(--bl-azul);
  opacity:.42; filter: blur(90px); pointer-events:none; }
.bl-hero > .container { position: relative; z-index: 1; }
.bl-kicker { display:inline-flex; align-items:center; gap:10px; color: var(--bl-amar);
  font-size: 12px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; }
.bl-kicker::before { content:""; width:26px; height:2px; background: var(--bl-amar); border-radius:2px; }
.bl-hero h1 { color:#fff; font-weight:900; font-size: clamp(34px,4.4vw,50px);
  line-height:1.06; letter-spacing:-.02em; margin: 18px 0 0; text-wrap: balance; }
.bl-hero .bl-lead { color: rgba(255,255,255,.74); font-size: 18.5px; line-height:1.6;
  max-width: 560px; margin: 18px 0 0; }
.bl-hero .bl-crumbs { margin-bottom: 22px; }
.bl-hero .bl-crumbs button { color: var(--bl-aqua); }
.bl-hero .bl-crumbs, .bl-hero .bl-crumbs .is-current { color: rgba(255,255,255,.6); }

/* ── Barra de filtros ── */
.bl-body-sec { padding: 56px 0 88px; background:#fff; }
.bl-toolbar { display:flex; flex-wrap:wrap; align-items:center; gap:12px; margin-bottom:18px; }
.bl-search { flex:1 1 300px; display:flex; align-items:center; gap:10px; height:50px;
  background:#fff; border:1.5px solid var(--bl-borde); border-radius:12px; padding:0 16px;
  color:#9AA0B1; transition:border-color .16s, box-shadow .16s; }
.bl-search:focus-within { border-color: var(--bl-azul); box-shadow:0 0 0 4px rgba(57,83,164,.10); }
.bl-search input { flex:1; border:0; outline:0; background:none; font:inherit; font-size:15.5px;
  color: var(--bl-tinta); height:100%; }
.bl-select { display:flex; align-items:center; gap:10px; }
.bl-select > span { font-size:11px; font-weight:800; letter-spacing:.12em;
  text-transform:uppercase; color: var(--bl-muted); }
.bl-select-wrap { position:relative; display:flex; align-items:center; }
.bl-select-wrap select { appearance:none; -webkit-appearance:none; height:50px; min-width:190px;
  padding:0 40px 0 16px; border:1.5px solid var(--bl-borde); border-radius:12px; background:#fff;
  font:inherit; font-size:15px; font-weight:600; color: var(--bl-tinta); cursor:pointer; }
.bl-select-wrap select:hover { border-color: var(--bl-azul); }
.bl-select-wrap svg { position:absolute; right:14px; pointer-events:none; color:#9AA0B1; }
.bl-clear { height:50px; padding:0 20px; border-radius:12px; border:1.5px solid var(--bl-borde);
  background:#fff; font:inherit; font-size:14.5px; font-weight:700; color: var(--bl-azul); cursor:pointer; }
.bl-clear:hover { border-color: var(--bl-azul); background:#F7F9FF; }

.bl-temas { display:flex; flex-wrap:wrap; gap:9px; margin: 0 0 40px; }
.bl-tema { border:1.5px solid var(--bl-borde); background:#fff; font:inherit; font-size:14px;
  font-weight:600; color:#4D4D4D; padding:9px 18px; border-radius:999px; cursor:pointer; transition:.16s; }
.bl-tema:hover { border-color: var(--bl-azul); color: var(--bl-azul); }
.bl-tema.is-on { background: var(--bl-navy); border-color: var(--bl-navy); color:#fff; }
.bl-count { font-size:14px; font-weight:600; color: var(--bl-muted); margin:0 0 22px; }

/* ── Tarjetas ── */
.bl-featured { margin-bottom: 46px; }
.bl-featured-lbl { display:inline-flex; align-items:center; gap:9px; font-size:11.5px;
  font-weight:800; letter-spacing:.14em; text-transform:uppercase; color: var(--bl-azul); margin-bottom:16px; }
.bl-featured-lbl::before { content:""; width:22px; height:2px; background: var(--bl-amar); border-radius:2px; }

.bl-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:26px; }
.bl-card { display:flex; flex-direction:column; min-width:0; background:#fff;
  border:1px solid var(--bl-borde); border-radius:16px; overflow:hidden;
  box-shadow:0 8px 28px rgba(26,42,94,.08); transition:transform .2s ease, box-shadow .2s ease, border-color .2s ease; }
.bl-card:hover { transform:translateY(-4px); box-shadow:0 14px 34px rgba(26,42,94,.14); border-color:#D7DCEA; }
.bl-thumb { position:relative; display:block; aspect-ratio:16/9; overflow:hidden; background:#E9EDF6; }
.bl-thumb img { width:100%; height:100%; object-fit:cover; display:block;
  transition:transform .5s cubic-bezier(.2,.6,.2,1); }
.bl-card:hover .bl-thumb img { transform:scale(1.04); }
.bl-thumb--contain { background:#fff; }
.bl-thumb--contain img { object-fit:contain; padding:10px; }
.bl-card:hover .bl-thumb--contain img { transform:none; }
.bl-play { position:absolute; left:14px; bottom:12px; display:inline-flex; align-items:center;
  gap:6px; padding:5px 11px 5px 9px; border-radius:999px; background: var(--bl-amar);
  color: var(--bl-navy); font-size:11px; font-weight:800; text-transform:uppercase; letter-spacing:.08em; }
.bl-card-body { display:flex; flex-direction:column; gap:10px; padding:22px 22px 24px; flex:1; }
.bl-card-meta { display:flex; flex-wrap:wrap; gap:8px; }
.bl-pill { border:0; background:rgba(126,185,199,.22); color:#30477F; font:inherit;
  font-size:11.5px; font-weight:700; letter-spacing:.02em; padding:5px 12px;
  border-radius:999px; cursor:pointer; }
.bl-pill:hover { background:rgba(126,185,199,.38); }
.bl-pill--ghost { background:#EFF1F7; color:#4D4D4D; cursor:default; }
.bl-card-title { font-size:18px; font-weight:800; line-height:1.28; color:#1A1F36; margin:0; }
.bl-card-title--big { font-size:clamp(24px,2.6vw,31px); line-height:1.16; letter-spacing:-.015em; }
.bl-card-ex { font-size:14.5px; line-height:1.62; color: var(--bl-muted); margin:0; flex:1; }
.bl-card-foot { display:flex; flex-wrap:wrap; align-items:center; gap:7px; font-size:12.5px;
  color: var(--bl-muted); padding-top:2px; }
.bl-byline { font-weight:700; color:#2A3148; }
.bl-dot { opacity:.45; }
.bl-read { align-self:flex-start; display:inline-flex; align-items:center; gap:7px; border:0;
  background:none; font:inherit; font-size:14.5px; font-weight:700; color: var(--bl-azul);
  cursor:pointer; padding:2px 0 0; }
.bl-read:hover { gap:11px; }
.bl-read svg { transition: transform .18s; }

/* Destacado a dos columnas */
@media (min-width: 981px) {
  .bl-card--big { display:grid; grid-template-columns:50% 1fr; gap:0; align-items:stretch;
    border-left:4px solid var(--bl-amar); }
  .bl-card--big .bl-thumb { aspect-ratio:auto; height:100%; min-height:330px; }
  .bl-card--big .bl-card-body { padding:38px 40px; justify-content:center; gap:14px; }
  .bl-card--big .bl-card-ex { flex:0 0 auto; font-size:15.5px; }
  .bl-card--big .bl-card-foot { margin-top:4px; }
}

/* ── Estado vacío ── */
.bl-empty { text-align:center; padding:72px 28px; color: var(--bl-muted);
  border:1.5px dashed #D7DCEA; border-radius:18px; background: var(--bl-fondo); }
.bl-empty h3 { font-size:21px; font-weight:800; color:#1A1F36; margin:16px 0 8px; }
.bl-empty p { margin:0 0 24px; }
.bl-empty .btn { display:inline-flex; }

/* ── Paginación ── */
.bl-pager { display:flex; justify-content:center; align-items:center; gap:9px; margin-top:52px; }
.bl-pg { min-width:46px; height:46px; border-radius:12px; border:1.5px solid var(--bl-borde);
  background:#fff; font:inherit; font-size:14.5px; font-weight:700; color:#2A3148; cursor:pointer;
  display:inline-flex; align-items:center; justify-content:center; transition:.16s; }
.bl-pg:hover:not(:disabled) { border-color: var(--bl-azul); color: var(--bl-azul); }
.bl-pg.is-active { background: var(--bl-navy); border-color: var(--bl-navy); color:#fff; }
.bl-pg:disabled { opacity:.32; cursor:default; }

/* ── Temas ── */
.bl-topics { margin-top:72px; padding-top:44px; border-top:1px solid var(--bl-borde); }
.bl-topics h2 { font-size:19px; font-weight:800; color:#1A1F36; margin:0 0 18px; }
.bl-topics-row { display:flex; flex-wrap:wrap; gap:10px; }
.bl-topic-chip { border:1.5px solid var(--bl-borde); background:#fff; font:inherit; font-size:14px;
  font-weight:600; color:#4D4D4D; padding:10px 20px; border-radius:999px; cursor:pointer; transition:.16s; }
.bl-topic-chip:hover { border-color: var(--bl-azul); color: var(--bl-azul); background:#F7F9FF; }

/* ── Migas ── */
.bl-crumbs { display:flex; flex-wrap:wrap; align-items:center; gap:9px; font-size:13.5px; color: var(--bl-muted); }
.bl-crumbs button { border:0; background:none; font:inherit; font-size:13.5px; font-weight:600;
  color: var(--bl-azul); cursor:pointer; padding:0; }
.bl-crumbs button:hover { text-decoration:underline; }
.bl-crumbs .is-current { color:#2A3148; font-weight:600; }

/* ── Artículo ── */
.bl-art-head { background: var(--bl-fondo); border-bottom:1px solid var(--bl-borde); padding:44px 0 48px; }
.bl-art-head h1 { font-size:clamp(31px,4vw,46px); font-weight:900; line-height:1.1;
  letter-spacing:-.02em; color:#14182A; margin:16px 0 0; text-wrap:balance; }
.bl-art-head .bl-lead { font-size:19px; line-height:1.6; color:#4D4D4D; margin:18px 0 0; }
.bl-authorbar { display:flex; flex-wrap:wrap; align-items:center; gap:14px 22px; margin-top:32px;
  padding-top:24px; border-top:1px solid var(--bl-borde); }
.bl-avatar { width:48px; height:48px; border-radius:999px; flex:0 0 auto; background: var(--bl-navy);
  color:#fff; font-size:15px; font-weight:800; display:flex; align-items:center; justify-content:center; }
.bl-photo { width:48px; height:48px; border-radius:999px; object-fit:cover; object-position:center 18%;
  flex:0 0 auto; border:2px solid #fff; box-shadow:0 0 0 1px var(--bl-borde); }
.bl-photo--xl { width:132px; height:132px; border-radius:18px; object-position:center 12%;
  box-shadow:0 10px 30px rgba(26,42,94,.16); border:0; }
.bl-avatar--xl { width:132px; height:132px; border-radius:18px; font-size:34px; }
.bl-authorlink { border:0; background:none; font:inherit; font-size:15.5px; font-weight:800;
  color: var(--bl-azul); cursor:pointer; padding:0; text-align:left; }
.bl-authorlink:hover { text-decoration:underline; }
.bl-authorrole { font-size:13px; color: var(--bl-muted); margin-top:3px; }
.bl-dates { font-size:13px; color: var(--bl-muted); line-height:1.6; margin-left:auto; }
.bl-dates b { color:#2A3148; font-weight:700; }
.bl-share { display:inline-flex; align-items:center; gap:8px; height:44px; padding:0 20px;
  border-radius:12px; border:1.5px solid var(--bl-borde); background:#fff; font:inherit;
  font-size:14.5px; font-weight:700; color:#2A3148; cursor:pointer; transition:.16s; }
.bl-share:hover { border-color: var(--bl-azul); color: var(--bl-azul); }

.bl-hero-img, .bl-hero-video { margin:32px 0 0; }
.bl-hero-img { border-radius:18px; overflow:hidden; border:1px solid var(--bl-borde);
  background:#fff; box-shadow:0 14px 34px rgba(26,42,94,.12); }
.bl-hero-img img { width:100%; height:auto; display:block; }
.bl-video-frame { position:relative; aspect-ratio:16/9; border-radius:18px; overflow:hidden;
  background:#14182A; box-shadow:0 14px 34px rgba(26,42,94,.16); }
.bl-video-frame iframe { position:absolute; inset:0; width:100%; height:100%; border:0; }
.bl-hero-img figcaption, .bl-hero-video figcaption { margin-top:11px; font-size:13px;
  color: var(--bl-muted); line-height:1.55; }
.bl-hero-video figcaption a { color: var(--bl-azul); font-weight:700; }

.bl-art-body { padding:52px 0 88px; background:#fff; }
.bl-toc { background: var(--bl-fondo); border:1px solid var(--bl-borde); border-left:3px solid var(--bl-amar);
  border-radius:0 14px 14px 0; padding:26px 30px; margin-bottom:44px; }
.bl-toc h2 { font-size:11.5px; font-weight:800; letter-spacing:.14em; text-transform:uppercase;
  color: var(--bl-muted); margin:0 0 14px; }
.bl-toc ol { margin:0; padding-left:20px; display:flex; flex-direction:column; gap:9px; }
.bl-toc a { color: var(--bl-azul); font-size:15px; font-weight:600; text-decoration:none; }
.bl-toc a:hover { text-decoration:underline; }

.bl-prose { font-size:17.5px; line-height:1.78; color:#2A3148; }
.bl-prose h2 { font-size:26px; font-weight:800; line-height:1.24; color:#14182A;
  margin:48px 0 16px; letter-spacing:-.012em; scroll-margin-top:90px; }
.bl-prose h2:first-child { margin-top:0; }
.bl-prose p { margin:0 0 20px; }
.bl-prose ul { margin:0 0 22px; padding-left:24px; display:flex; flex-direction:column; gap:10px; }
.bl-prose li::marker { color: var(--bl-azul); }
.bl-prose blockquote { margin:30px 0; padding:22px 28px; border-left:4px solid var(--bl-amar);
  background:#FFF7E2; border-radius:0 14px 14px 0; font-size:18.5px; font-weight:600;
  color:#14182A; font-style:italic; }
.bl-nota { margin:34px 0 0; padding:20px 24px; background: var(--bl-fondo);
  border:1px solid var(--bl-borde); border-radius:14px; font-size:14.5px; line-height:1.65; color:#4D4D4D; }
.bl-deflist { display:grid; grid-template-columns:minmax(190px,34%) 1fr; gap:1px;
  background: var(--bl-borde); border:1px solid var(--bl-borde); border-radius:14px;
  overflow:hidden; margin:0 0 26px; font-size:15px; }
.bl-deflist dt { background: var(--bl-fondo); padding:14px 18px; font-weight:700; color:#14182A; margin:0; }
.bl-deflist dd { background:#fff; padding:14px 18px; margin:0; color:#2A3148; }
.bl-figure { margin:36px 0; }
.bl-figure img { width:100%; height:auto; display:block; border-radius:14px;
  border:1px solid var(--bl-borde); background:#fff; }
.bl-figure figcaption { margin-top:11px; font-size:13.5px; color: var(--bl-muted);
  line-height:1.55; text-align:center; }
.bl-solo-video { font-size:16px; line-height:1.7; color:#4D4D4D; background: var(--bl-fondo);
  border:1px solid var(--bl-borde); border-radius:14px; padding:22px 26px; margin:0; }

.bl-refs, .bl-related { margin-top:52px; padding-top:34px; border-top:1px solid var(--bl-borde); }
.bl-refs h2, .bl-related h2 { font-size:19px; font-weight:800; color:#14182A; margin:0 0 18px; }
.bl-refs ol { margin:0; padding-left:20px; display:flex; flex-direction:column; gap:9px;
  font-size:14px; color: var(--bl-muted); line-height:1.6; word-break:break-word; }
.bl-rel-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(215px,1fr)); gap:18px; }
.bl-rel-card { text-align:left; background:#fff; border:1px solid var(--bl-borde); border-radius:14px;
  overflow:hidden; display:flex; flex-direction:column; gap:9px; padding:20px; font:inherit;
  cursor:pointer; transition:.18s; }
.bl-rel-card:hover { border-color: var(--bl-azul); transform:translateY(-2px);
  box-shadow:0 10px 26px rgba(26,42,94,.10); }
.bl-rel-thumb { display:block; aspect-ratio:16/9; overflow:hidden; background:#E9EDF6;
  margin:-20px -20px 4px; }
.bl-rel-thumb img { width:100%; height:100%; object-fit:cover; display:block; }
.bl-rel-k { font-size:10.5px; font-weight:800; letter-spacing:.12em; text-transform:uppercase;
  color: var(--bl-azul); }
.bl-rel-card b { font-size:15.5px; font-weight:700; color:#14182A; line-height:1.34; }
.bl-rel-go { display:inline-flex; align-items:center; gap:6px; font-size:13.5px; font-weight:700;
  color: var(--bl-azul); border:0; background:none; padding:0; font-family:inherit;
  cursor:pointer; align-self:flex-start; }
.bl-backrow { margin-top:56px; }
.bl-backrow .btn { display:inline-flex; }

/* ── Autor ── */
.bl-author-hero { padding:56px 0 64px; }
.bl-author-hero .bl-author-top { display:flex; align-items:center; gap:26px; margin-top:26px; flex-wrap:wrap; }
.bl-author-hero h1 { margin:0; color:#fff; }
.bl-author-role { font-size:16.5px; font-weight:700; color: var(--bl-amar); margin:10px 0 0; }
.bl-author-mail { display:inline-flex; align-items:center; gap:8px; margin-top:12px;
  font-size:14px; color:rgba(255,255,255,.72); text-decoration:none; }
.bl-author-mail:hover { color:#fff; }
.bl-author-bio { max-width:740px; margin-top:28px; }
.bl .bl-author-bio p { margin:0 0 14px; font-size:17px; line-height:1.72;
  color:rgba(255,255,255,.80); }
.bl .bl-author-bio p:last-child { margin-bottom:0; }
.bl .bl-author-hero .bl-crumbs button { color: var(--bl-aqua); }
.bl .bl-author-hero .bl-crumbs .is-current { color:rgba(255,255,255,.62); }
.bl-sec-h { font-size:25px; font-weight:800; color:#14182A; margin:0 0 6px; }
.bl-sec-sub { font-size:14.5px; color: var(--bl-muted); margin:0 0 24px; }

/* ── Perfil ampliado ── */
.bl-sr { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden;
  clip:rect(0 0 0 0); white-space:nowrap; border:0; }
.bl-author-intro { max-width:720px; margin:26px 0 0; font-size:17.5px; line-height:1.72;
  color:rgba(255,255,255,.82); }
.bl-author-ctas { display:flex; flex-wrap:wrap; gap:12px; margin-top:30px; }
.bl-cta-cita { display:inline-flex; align-items:center; gap:9px; background:var(--bl-amar);
  color:#30477F; font-size:15.5px; font-weight:800; padding:14px 26px; border-radius:10px;
  text-decoration:none; border:0; cursor:pointer; transition:transform .15s, background .15s;
  box-shadow:0 8px 20px -10px rgba(253,195,69,.9); }
.bl-cta-cita:hover { background:#E9AD24; transform:translateY(-2px); }
.bl-cta-ghost { display:inline-flex; align-items:center; gap:8px; border:1.5px solid rgba(255,255,255,.34);
  color:#fff; background:none; font:inherit; font-size:15.5px; font-weight:700; padding:13px 24px;
  border-radius:10px; text-decoration:none; cursor:pointer; transition:.15s; }
.bl-cta-ghost:hover { border-color:#fff; background:rgba(255,255,255,.08); }

.bl-author-info { background:#fff; padding:60px 0 8px; }
.bl-info-grid { display:grid; grid-template-columns:1.35fr .95fr; gap:56px; align-items:start; }
.bl-info-p { font-size:17px; line-height:1.75; color:#2A3148; margin:0 0 18px; }
.bl-info-h3 { font-size:19px; font-weight:800; color:#14182A; margin:34px 0 6px; }
.bl-info-nota { font-size:14px; color:var(--bl-muted); margin:0 0 16px; }
.bl-areas { list-style:none; padding:0; margin:0; display:grid; gap:11px; }
.bl-areas li { display:flex; align-items:center; gap:11px; font-size:16px; color:#2A3148; }
.bl-areas li svg { color:var(--bl-azul); flex:0 0 auto; }
.bl-area-link { border:0; background:none; font:inherit; font-size:16px; color:var(--bl-azul);
  font-weight:600; padding:0; cursor:pointer; }
.bl-area-link:hover { text-decoration:underline; }

.bl-info-side { display:flex; flex-direction:column; gap:20px; }
.bl-panel { background:var(--bl-fondo); border:1px solid var(--bl-borde); border-radius:16px; padding:26px 28px; }
.bl-panel h3 { font-size:12px; font-weight:800; letter-spacing:.14em; text-transform:uppercase;
  color:var(--bl-muted); margin:0 0 16px; }
.bl-panel p { font-size:15px; line-height:1.65; color:#2A3148; margin:0 0 18px; }
.bl-form { list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:15px; }
.bl-form li { display:flex; flex-direction:column; gap:2px; padding-left:15px; position:relative; }
.bl-form li::before { content:""; position:absolute; left:0; top:6px; width:5px; height:5px;
  border-radius:50%; background:var(--bl-amar); }
.bl-form b { font-size:15.5px; font-weight:700; color:#14182A; }
.bl-form span { font-size:13.5px; color:var(--bl-muted); }
.bl-panel--cita { background:#fff; border-left:3px solid var(--bl-amar); }
.bl-panel--cita .bl-cta-cita { width:100%; justify-content:center; }
.bl-opiniones { display:inline-block; margin-top:14px; font-size:14px; font-weight:700;
  color:var(--bl-azul); text-decoration:none; line-height:1.5; }
.bl-opiniones:hover { text-decoration:underline; }

.bl-author-cierre { margin-top:64px; padding:38px 40px; border-radius:20px;
  background:linear-gradient(120deg,#1D2A4D,#30477F); display:flex; flex-wrap:wrap;
  align-items:center; justify-content:space-between; gap:26px; }
.bl-author-cierre h2 { color:#fff; font-size:25px; font-weight:800; margin:0; line-height:1.25; }
.bl-author-cierre p { color:rgba(255,255,255,.72); font-size:15.5px; margin:8px 0 0; }
.bl-author-cierre .bl-author-ctas { margin-top:0; }

@media (max-width: 980px) {
  .bl-info-grid { grid-template-columns:1fr; gap:36px; }
}
@media (max-width: 760px) {
  .bl-author-ctas { flex-direction:column; align-items:stretch; }
  .bl-cta-cita, .bl-cta-ghost { justify-content:center; }
  .bl-author-info { padding-top:44px; }
  .bl-author-cierre { padding:30px 24px; margin-top:48px; }
  .bl-author-cierre h2 { font-size:22px; }
}

/* Portada editorial de marca */
.bl-cover { position:relative; width:100%; height:100%; overflow:hidden;
  display:flex; align-items:center; justify-content:center; }
.bl-cover-dots { position:absolute; inset:0;
  background-image: radial-gradient(rgba(255,255,255,.13) 1.5px, transparent 1.5px);
  background-size:22px 22px; }
.bl-cover-ini { position:relative; font-family:"Instrument Serif","Times New Roman",serif;
  font-style:italic; font-size:88px; line-height:1; color:rgba(255,255,255,.9);
  text-shadow:0 4px 24px rgba(0,0,0,.18); }
.bl-cover--big .bl-cover-ini { font-size:120px; }
.bl-cover-tema { position:absolute; left:16px; bottom:14px; font-size:10.5px; font-weight:800;
  letter-spacing:.16em; text-transform:uppercase; color:rgba(255,255,255,.72); }

/* ── Responsive ── */
@media (max-width: 980px) {
  .bl-grid { grid-template-columns:repeat(2,1fr); }
  .bl-dates { margin-left:0; width:100%; }
  .bl-hero { padding:56px 0 52px; }
}
@media (max-width: 760px) {
  .bl-grid { grid-template-columns:1fr; }
  .bl-toolbar { flex-direction:column; align-items:stretch; }
  .bl-search { flex:0 0 auto; }
  .bl-select { flex-direction:column; align-items:stretch; gap:7px; }
  .bl-select-wrap select { width:100%; }
  .bl-clear { width:100%; }
  .bl-deflist { grid-template-columns:1fr; }
  .bl-deflist dt { padding-bottom:5px; }
  .bl-prose { font-size:16.5px; }
  .bl-prose h2 { font-size:23px; margin-top:38px; }
  .bl-art-head { padding:32px 0 36px; }
  .bl-photo--xl, .bl-avatar--xl { width:104px; height:104px; font-size:27px; }
  .bl-share { width:100%; justify-content:center; }
  .bl-cover-ini { font-size:66px; }
  .bl-topics { margin-top:52px; }
}
  `}</style>;
}

const BD = () => window.BLOG_DATA;
const findAuthor = (id) => BD().authors.find(a => a.id === id) || null;
const findTopic  = (id) => BD().topics.find(t => t.id === id) || null;
const topicBySlug = (slug) => BD().topics.find(t => t.slug === slug) || null;
const hasBody = (a) => Array.isArray(a.body) && a.body.length > 0;

const MESES = ["enero","febrero","marzo","abril","mayo","junio",
  "julio","agosto","septiembre","octubre","noviembre","diciembre"];
/* Fecha real de publicación. null = sin dato: no se inventa. */
function fmtFecha(iso) {
  if (!iso) return null;
  const d = new Date(iso);
  if (isNaN(d)) return null;
  return d.getUTCDate() + " de " + MESES[d.getUTCMonth()] + " de " + d.getUTCFullYear();
}
const esVideo = (a) => a.content_type === "video" || a.content_type === "entrevista";
const ctaDe = (a) => a.content_type === "entrevista" ? "Ver entrevista"
  : a.content_type === "video" ? "Ver video" : "Leer artículo";

/* Etiqueta de autoría honesta: null = no verificada */
function autoriaLabel(a) {
  const au = findAuthor(a.author_id);
  if (!au) return "InfectoLab";
  if (a.contributor_role === "entrevistado") return "Entrevista con " + au.name;
  if (a.contributor_role === "presentador") return "Presentado por " + au.name;
  return au.name;
}

/* Portada editorial de marca para los artículos sin imagen publicable.
 * No es un placeholder genérico ni una foto inventada: es una cubierta
 * tipográfica compuesta con la paleta y el motivo de puntos de InfectoLab. */
const COVER_TONOS = {
  infectologia: ["#30477F", "#3953A4"],
  examenes:     ["#3953A4", "#7EB9C7"],
  vacunas:      ["#1D2A4D", "#30477F"],
  "covid-19":   ["#30477F", "#4D4D4D"],
  t2dx:         ["#3953A4", "#30477F"],
  salud:        ["#30477F", "#7EB9C7"],
  nutricion:    ["#4D4D4D", "#30477F"],
};

function EditorialCover({ article, alto }) {
  const t = findTopic(article.topic_ids[0]);
  const [a, b] = COVER_TONOS[t ? t.id : "infectologia"] || COVER_TONOS.infectologia;
  const inicial = article.title.replace(/^[¿¡]/, "").trim().charAt(0).toUpperCase();
  return (
    <div className={"bl-cover" + (alto ? " bl-cover--big" : "")} aria-hidden="true"
      style={{ background: "linear-gradient(135deg, " + a + " 0%, " + b + " 100%)" }}>
      <span className="bl-cover-dots" />
      <span className="bl-cover-ini">{inicial}</span>
      {t && <span className="bl-cover-tema">{t.name}</span>}
    </div>
  );
}

/* Miniatura: imagen real cuando existe; si no, portada editorial.
 * Nunca una caja vacía. */
function Thumb({ article, alto }) {
  const conVideo = !!article.video;
  return (
    <div className={"bl-thumb" + (alto ? " bl-thumb--big" : "") + (article.image && article.image.fit === "contain" ? " bl-thumb--contain" : "")}>
      {article.image
        ? <img src={article.image.src} alt={article.image.alt} decoding="async"
            loading={alto ? "eager" : "lazy"} fetchpriority={alto ? "high" : undefined} />
        : <EditorialCover article={article} alto={alto} />}
      {conVideo && (
        <span className="bl-play" aria-hidden="true">
          <svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>
        </span>
      )}
    </div>
  );
}

/* ─────────────────────────  Tarjeta de artículo  ───────────────────────── */
function BlogCard({ article, openArticle, openTopic, destacado }) {
  const t = findTopic(article.topic_ids[0]);
  const fecha = fmtFecha(article.published_at);
  return (
    <article className={"bl-card" + (destacado ? " bl-card--big" : "")}>
      <Thumb article={article} alto={destacado} />
      <div className="bl-card-body">
      <div className="bl-card-meta">
        {t && (
          <button className="bl-pill" onClick={() => openTopic(t.slug)}>{t.name}</button>
        )}
        {article.content_type === "entrevista" && <span className="bl-pill bl-pill--ghost">Entrevista</span>}
        {article.content_type === "video" && <span className="bl-pill bl-pill--ghost">Video</span>}
      </div>
      <h3 className={destacado ? "bl-card-title bl-card-title--big" : "bl-card-title"}>{article.title}</h3>
      {article.excerpt && <p className="bl-card-ex">{article.excerpt}</p>}
      <div className="bl-card-foot">
        <span className="bl-byline">{autoriaLabel(article)}</span>
        {fecha && <><span className="bl-dot">·</span><time className="bl-date" dateTime={article.published_at}>{fecha}</time></>}
      </div>
      <button className="bl-read" onClick={() => openArticle(article.slug)}>
        {ctaDe(article)} <Icon name="arrow" size={15} />
      </button>
      </div>
    </article>
  );
}

/* ─────────────────────────  Paginación  ───────────────────────── */
function BlogPager({ page, total, onPage }) {
  if (total <= 1) return null;
  return (
    <nav className="bl-pager" aria-label="Paginación del listado">
      <button className="bl-pg" onClick={() => onPage(page - 1)} disabled={page <= 1} aria-label="Página anterior">
        <Icon name="chevron" size={16} style={{transform:"rotate(90deg)"}} />
      </button>
      {Array.from({ length: total }, (_, i) => i + 1).map(n => (
        <button key={n} className={"bl-pg" + (n === page ? " is-active" : "")}
          onClick={() => onPage(n)} aria-current={n === page ? "page" : undefined}>{n}</button>
      ))}
      <button className="bl-pg" onClick={() => onPage(page + 1)} disabled={page >= total} aria-label="Página siguiente">
        <Icon name="chevron" size={16} style={{transform:"rotate(-90deg)"}} />
      </button>
    </nav>
  );
}

/* ─────────────────────────  1. ÍNDICE  /blog/  ───────────────────────── */
function BlogIndexPage({ navigate, openArticle, openTopic, openAuthor, blogState, setBlogState }) {
  const { articles, pageSize } = BD();
  const { q, topic, author, page } = blogState;
  const set = (patch) => setBlogState({ ...blogState, page: 1, ...patch });

  const filtrando = q.trim() !== "" || topic !== "all" || author !== "all";

  const filtrados = articles.filter(a => {
    if (topic !== "all" && !a.topic_ids.includes(topic)) return false;
    if (author !== "all" && a.author_id !== author) return false;
    if (q.trim()) {
      const s = (a.title + " " + (a.excerpt || "")).toLowerCase();
      if (!s.includes(q.trim().toLowerCase())) return false;
    }
    return true;
  });

  const destacado = filtrando ? null : articles.find(a => hasBody(a)) || null;
  const lista = destacado ? filtrados.filter(a => a.id !== destacado.id) : filtrados;
  const totalPag = Math.max(1, Math.ceil(lista.length / pageSize));
  const pagina = Math.min(page, totalPag);
  const visibles = lista.slice((pagina - 1) * pageSize, pagina * pageSize);

  const autoresConArticulos = BD().authors.filter(au => articles.some(a => a.author_id === au.id));

  return (
    <main className="bl" data-screen-label="10 Blog índice"><BlogStyles />
      <section className="section bl-hero">
        <div className="container">
          <div className="bl-kicker">Blog</div>
          <h1 className="text-balance" style={{marginTop: 12}}>Blog InfectoLab</h1>
          <p className="bl-lead">
            Información sobre pruebas de laboratorio, enfermedades infecciosas y prevención.
          </p>
        </div>
      </section>

      <section className="section bl-body-sec">
        <div className="container">
          {/* Filtros */}
          <div className="bl-toolbar">
            <div className="bl-search">
              <Icon name="search" size={17} />
              <input type="search" value={q} placeholder="Buscar artículos"
                aria-label="Buscar artículos" onChange={(e) => set({ q: e.target.value })} />
            </div>
            <label className="bl-select">
              <span>Autor</span>
              <div className="bl-select-wrap">
                <select value={author} onChange={(e) => set({ author: e.target.value })}>
                  <option value="all">Todos los autores</option>
                  {autoresConArticulos.map(a => <option key={a.id} value={a.id}>{a.name}</option>)}
                </select>
                <Icon name="chevron" size={15} />
              </div>
            </label>
            {filtrando && (
              <button className="bl-clear" onClick={() => setBlogState({ q:"", topic:"all", author:"all", page:1 })}>
                Limpiar filtros
              </button>
            )}
          </div>

          <div className="bl-temas" role="group" aria-label="Filtrar por tema">
            <button className={"bl-tema" + (topic === "all" ? " is-on" : "")}
              onClick={() => set({ topic: "all" })} aria-pressed={topic === "all"}>Todos los temas</button>
            {BD().topics.filter(t => articles.some(a => a.topic_ids.includes(t.id))).map(t => (
              <button key={t.id} className={"bl-tema" + (topic === t.id ? " is-on" : "")}
                onClick={() => set({ topic: t.id })} aria-pressed={topic === t.id}>{t.name}</button>
            ))}
          </div>

          {/* Destacado */}
          {destacado && (
            <div className="bl-featured">
              <div className="bl-featured-lbl">Destacado</div>
              <BlogCard article={destacado} openArticle={openArticle} openTopic={openTopic} destacado />
            </div>
          )}

          {/* Resultados */}
          {filtrando && (
            <p className="bl-count" role="status">
              {lista.length === 0 ? "Sin resultados" : lista.length + (lista.length === 1 ? " artículo" : " artículos")}
            </p>
          )}

          {lista.length === 0 ? (
            <div className="bl-empty">
              <Icon name="search" size={28} />
              <h3>No encontramos artículos con esos filtros</h3>
              <p>Prueba con otro término o revisa el archivo completo del blog.</p>
              <button className="btn btn-primary" onClick={() => setBlogState({ q:"", topic:"all", author:"all", page:1 })}>
                Limpiar filtros
              </button>
            </div>
          ) : (
            <>
              <div className="bl-grid">
                {visibles.map(a => (
                  <BlogCard key={a.id} article={a} openArticle={openArticle} openTopic={openTopic} />
                ))}
              </div>
              <BlogPager page={pagina} total={totalPag} onPage={(n) => setBlogState({ ...blogState, page: n })} />
            </>
          )}

          {/* Archivos temáticos */}
          <div className="bl-topics">
            <h2>Explora por tema</h2>
            <div className="bl-topics-row">
              {BD().topics.filter(t => articles.some(a => a.topic_ids.includes(t.id))).map(t => (
                <button key={t.id} className="bl-topic-chip" onClick={() => openTopic(t.slug)}>{t.name}</button>
              ))}
            </div>
          </div>
        </div>
      </section>
    </main>
  );
}

/* ─────────────────────────  2. ARTÍCULO  /blog/<slug>/  ───────────────────────── */
function ShareLink({ url }) {
  const [ok, setOk] = React.useState(false);
  const copiar = () => {
    const done = () => { setOk(true); setTimeout(() => setOk(false), 2200); };
    if (navigator.clipboard && navigator.clipboard.writeText) {
      navigator.clipboard.writeText(url).then(done).catch(() => {});
    } else {
      const ta = document.createElement("textarea");
      ta.value = url; document.body.appendChild(ta); ta.select();
      try { document.execCommand("copy"); done(); } catch (e) {}
      document.body.removeChild(ta);
    }
  };
  return (
    <button className="bl-share" onClick={copiar}>
      <Icon name={ok ? "check" : "link"} size={15} /> {ok ? "Enlace copiado" : "Compartir enlace"}
    </button>
  );
}

function ArticleBody({ blocks }) {
  return (
    <div className="bl-prose">
      {blocks.map((b, i) => {
        if (b.type === "h2") return <h2 key={i} id={"sec-" + i}>{b.text}</h2>;
        if (b.type === "p") return <p key={i}>{b.text}</p>;
        if (b.type === "quote") return <blockquote key={i}>{b.text}</blockquote>;
        if (b.type === "nota") return <aside key={i} className="bl-nota">{b.text}</aside>;
        if (b.type === "list") return <ul key={i}>{b.items.map((x, j) => <li key={j}>{x}</li>)}</ul>;
        if (b.type === "figure") return (
          <figure key={i} className="bl-figure">
            <img src={b.src} alt={b.alt} loading="lazy" decoding="async" />
            {(b.caption || b.credit) && (
              <figcaption>{b.caption}{b.credit ? (b.caption ? " · " : "") + b.credit : ""}</figcaption>
            )}
          </figure>
        );
        if (b.type === "deflist") return (
          <dl key={i} className="bl-deflist">
            {b.items.map(([k, v], j) => <React.Fragment key={j}><dt>{k}</dt><dd>{v}</dd></React.Fragment>)}
          </dl>
        );
        return null;
      })}
    </div>
  );
}

function BlogArticlePage({ slug, navigate, openArticle, openTopic, openAuthor, openStudy }) {
  const article = BD().articles.find(a => a.slug === slug);

  if (!article) {
    return (
      <main className="bl" data-screen-label="11 Artículo"><BlogStyles /><section className="section"><div className="container bl-empty">
        <h1>No encontramos ese artículo</h1>
        <button className="btn btn-primary" onClick={() => navigate("blog")}>Volver al blog</button>
      </div></section></main>
    );
  }

  const autor = findAuthor(article.author_id);
  const temas = article.topic_ids.map(findTopic).filter(Boolean);
  const cuerpo = hasBody(article) ? article.body : [];
  const secciones = cuerpo.map((b, i) => ({ ...b, i })).filter(b => b.type === "h2");
  const fecha = fmtFecha(article.published_at);
  const relacionados = BD().articles.filter(a =>
    a.id !== article.id && a.topic_ids.some(t => article.topic_ids.includes(t))).slice(0, 3);
  const estudios = (article.related_study_ids || [])
    .map(id => (window.STUDIES || []).find(s => s.id === id)).filter(Boolean);
  const shareUrl = window.location.origin + window.location.pathname + "#/blog/" + article.slug + "/";

  return (
    <main className="bl" data-screen-label="11 Artículo">
      <BlogStyles />
      <section className="section bl-art-head">
        <div className="container bl-narrow">
          <nav className="bl-crumbs" aria-label="Ruta de navegación">
            <button onClick={() => navigate("home")}>Inicio</button><span>/</span>
            <button onClick={() => navigate("blog")}>Blog</button>
            {temas[0] && <><span>/</span><button onClick={() => openTopic(temas[0].slug)}>{temas[0].name}</button></>}
          </nav>

          <div className="bl-card-meta" style={{marginTop: 20}}>
            {temas.map(t => <button key={t.id} className="bl-pill" onClick={() => openTopic(t.slug)}>{t.name}</button>)}
          </div>

          <h1 className="text-balance" style={{marginTop: 16}}>{article.title}</h1>
          <p className="bl-lead">{article.excerpt}</p>

          {article.video ? (
            <figure className="bl-hero-video">
              <div className="bl-video-frame">
                <iframe src={"https://www.youtube-nocookie.com/embed/" + article.video.id}
                  title={article.video.title} loading="lazy" allowFullScreen
                  allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" />
              </div>
              <figcaption>
                {article.video.title}
                {article.image && article.image.credit ? " · " + article.image.credit : ""}
                {" · "}
                <a href={article.video.url} target="_blank" rel="noopener noreferrer">Ver en YouTube</a>
              </figcaption>
            </figure>
          ) : article.image ? (
            <figure className="bl-hero-img">
              <img src={article.image.src} alt={article.image.alt} decoding="async" />
              {article.image.credit && <figcaption>{article.image.credit}</figcaption>}
            </figure>
          ) : null}

          <div className="bl-authorbar">
            {autor ? (
              <>
                {autor.official_photo
                  ? <img className="bl-photo" src={autor.official_photo.src} alt={autor.official_photo.alt} decoding="async" />
                  : <div className="bl-avatar" aria-hidden="true">{autor.name.replace(/^Dr[a]?\.\s*/, "").split(" ").slice(0,2).map(w => w[0]).join("")}</div>}
                <div>
                  <button className="bl-authorlink" onClick={() => openAuthor(autor.id)}>{autor.name}</button>
                  <div className="bl-authorrole">
                    {article.contributor_role === "entrevistado" ? "Entrevistado" :
                     article.contributor_role === "presentador" ? "Presentador" : "Autor"}
                    {autor.roles[0] ? " · " + autor.roles[0] : ""}
                    {article.medio ? " · " + article.medio : ""}
                  </div>
                </div>
              </>
            ) : (
              <div>
                <div className="bl-authorlink" style={{cursor:"default"}}>InfectoLab</div>
                <div className="bl-authorrole">Contenido editorial</div>
              </div>
            )}
            {fecha && (
              <div className="bl-dates">
                <div><b>Publicación:</b> <time dateTime={article.published_at}>{fecha}</time></div>
                {article.reviewed_at && <div><b>Última revisión:</b> {fmtFecha(article.reviewed_at)}</div>}
              </div>
            )}
            <ShareLink url={shareUrl} />
          </div>
        </div>
      </section>

      <section className="section bl-art-body">
        <div className="container bl-narrow">
          {secciones.length >= 4 && (
            <nav className="bl-toc" aria-label="Contenido del artículo">
              <h2>Contenido</h2>
              <ol>{secciones.map(s => (
                <li key={s.i}><a href={"#sec-" + s.i}>{s.text}</a></li>
              ))}</ol>
            </nav>
          )}

          {cuerpo.length > 0
            ? <ArticleBody blocks={cuerpo} />
            : <p className="bl-solo-video">Este contenido se publicó como video. Reprodúcelo arriba o ábrelo en YouTube; no existe una versión escrita en la fuente.</p>}

          {article.references.length > 0 && (
            <section className="bl-refs">
              <h2>Referencias</h2>
              <ol>{article.references.map((r, i) => <li key={i}>{r}</li>)}</ol>
            </section>
          )}

          {estudios.length > 0 && (
            <section className="bl-related">
              <h2>Estudios relacionados</h2>
              <div className="bl-rel-grid">
                {estudios.map(s => (
                  <button key={s.id} className="bl-rel-card" onClick={() => openStudy(s.id)}>
                    <span className="bl-rel-k">Estudio</span>
                    <b>{s.name}</b>
                    <span className="bl-rel-go">Ver ficha del estudio <Icon name="arrow" size={14} /></span>
                  </button>
                ))}
              </div>
            </section>
          )}

          {relacionados.length > 0 && (
            <section className="bl-related">
              <h2>Artículos relacionados</h2>
              <div className="bl-rel-grid">
                {relacionados.map(a => (
                  <button key={a.id} className="bl-rel-card bl-rel-card--art" onClick={() => openArticle(a.slug)}>
                    {a.image && <span className="bl-rel-thumb"><img src={a.image.src} alt={a.image.alt} loading="lazy" /></span>}
                    <span className="bl-rel-k">{(findTopic(a.topic_ids[0]) || {}).name}</span>
                    <b>{a.title}</b>
                    <span className="bl-rel-go">{ctaDe(a)} <Icon name="arrow" size={14} /></span>
                  </button>
                ))}
              </div>
            </section>
          )}

          <div className="bl-backrow">
            <button className="btn btn-ghost" onClick={() => navigate("blog")}>← Volver al blog</button>
          </div>
        </div>
      </section>
    </main>
  );
}

/* CTA externo a Doctoralia. Pestaña nueva, anunciada de forma accesible. */
function CitaCTA({ url }) {
  return (
    <a className="bl-cta-cita" href={url} target="_blank" rel="noopener noreferrer">
      <Icon name="calendar" size={17} />
      Agendar cita en Doctoralia
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
        strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
        <path d="M14 4h6v6" /><path d="M20 4 11 13" />
        <path d="M19 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h5" />
      </svg>
      <span className="bl-sr">(abre en una pestaña nueva)</span>
    </a>
  );
}

/* ─────────────────────────  3. AUTOR  /dr-samuel-navarro-alvarez/  ───────────────────────── */
function AuthorPage({ authorId, navigate, openArticle, openTopic }) {
  const autor = findAuthor(authorId) || findAuthor("samuel-navarro");
  const propios = BD().articles.filter(a => a.author_id === autor.id);
  const articulos  = propios.filter(a => a.contributor_role === "autor");
  const videos     = propios.filter(a => a.contributor_role === "presentador");
  const entrevistas = propios.filter(a => a.contributor_role === "entrevistado");
  const iniciales = autor.name.replace(/^Dr[a]?\.\s*/, "").split(" ").slice(0, 2).map(w => w[0]).join("");

  return (
    <main className="bl" data-screen-label="12 Autor"><BlogStyles />
      <section className="section bl-hero bl-author-hero">
        <div className="container">
          <nav className="bl-crumbs" aria-label="Ruta de navegación">
            <button onClick={() => navigate("home")}>Inicio</button><span>/</span>
            <button onClick={() => navigate("blog")}>Blog</button><span>/</span>
            <span className="is-current">{autor.name}</span>
          </nav>
          <div className="bl-author-top">
            {/* Foto oficial publicada por el propio doctor. Si no existe, monograma
                tipográfico: nunca una fotografía generada. */}
            {autor.official_photo
              ? <img className="bl-photo bl-photo--xl" src={autor.official_photo.src} alt={autor.official_photo.alt} decoding="async" />
              : <div className="bl-avatar bl-avatar--xl" aria-hidden="true">{iniciales}</div>}
            <div>
              <h1 style={{marginTop: 0}}>{autor.name}</h1>
              <p className="bl-author-role">{autor.headline || autor.roles[0]}</p>
              {autor.contact_email && (
                <a className="bl-author-mail" href={"mailto:" + autor.contact_email}>
                  <Icon name="mail" size={15} /> {autor.contact_email}
                </a>
              )}
            </div>
          </div>

          {autor.intro && <p className="bl-author-intro">{autor.intro}</p>}

          {(autor.doctoralia || true) && (
            <div className="bl-author-ctas">
              {autor.doctoralia && <CitaCTA url={autor.doctoralia.url} />}
              <a className="bl-cta-ghost" href="#contenido-autor"
                onClick={(e) => { e.preventDefault(); const t = document.getElementById("contenido-autor");
                  if (t) t.scrollIntoView({ behavior: "smooth", block: "start" }); }}>
                Ver artículos y videos
              </a>
            </div>
          )}
        </div>
      </section>

      <section className="section bl-author-info">
        <div className="container">
          <div className="bl-info-grid">
            <div className="bl-info-main">
              <h2 className="bl-sec-h">Acerca del doctor</h2>
              {autor.verified_bio.length > 0
                ? autor.verified_bio.map((p, i) => <p key={i} className="bl-info-p">{p}</p>)
                : <p className="bl-muted">Biografía por confirmar con el profesional.</p>}

              {autor.areas && autor.areas.length > 0 && (
                <>
                  <h3 className="bl-info-h3">Áreas de atención</h3>
                  <p className="bl-info-nota">Atención a personas adultas.</p>
                  <ul className="bl-areas">
                    {autor.areas.map((a, i) => (
                      <li key={i}>
                        <Icon name="check" size={15} />
                        {a.topic
                          ? <button className="bl-area-link" onClick={() => openTopic((findTopic(a.topic) || {}).slug)}>{a.nombre}</button>
                          : <span>{a.nombre}</span>}
                      </li>
                    ))}
                  </ul>
                </>
              )}
            </div>

            <aside className="bl-info-side">
              {autor.formacion && autor.formacion.length > 0 && (
                <div className="bl-panel">
                  <h3>Formación</h3>
                  <ul className="bl-form">
                    {autor.formacion.map((f, i) => (
                      <li key={i}><b>{f.titulo}</b><span>{f.institucion}</span></li>
                    ))}
                  </ul>
                </div>
              )}

              {autor.doctoralia && (
                <div className="bl-panel bl-panel--cita">
                  <h3>Consulta</h3>
                  <p>{autor.doctoralia.consulta}</p>
                  <CitaCTA url={autor.doctoralia.url} />
                  <a className="bl-opiniones" href={autor.doctoralia.url} target="_blank" rel="noopener noreferrer">
                    Conoce las opiniones de sus pacientes en Doctoralia
                    <span className="bl-sr">(abre en una pestaña nueva)</span>
                  </a>
                </div>
              )}
            </aside>
          </div>
        </div>
      </section>

      <section className="section bl-body-sec" id="contenido-autor">
        <div className="container">
          {articulos.length > 0 && (
            <>
              <h2 className="bl-sec-h">Artículos</h2>
              <p className="bl-sec-sub">Contenidos escritos firmados por el especialista.</p>
              <div className="bl-grid">{articulos.map(a => (
                <BlogCard key={a.id} article={a} openArticle={openArticle} openTopic={openTopic} />
              ))}</div>
            </>
          )}

          {videos.length > 0 && (
            <>
              <h2 className="bl-sec-h" style={{marginTop: articulos.length ? 56 : 0}}>Videos</h2>
              <p className="bl-sec-sub">Videos del canal de InfectoLab presentados por el especialista.</p>
              <div className="bl-grid">{videos.map(a => (
                <BlogCard key={a.id} article={a} openArticle={openArticle} openTopic={openTopic} />
              ))}</div>
            </>
          )}

          {entrevistas.length > 0 && (
            <>
              <h2 className="bl-sec-h" style={{marginTop: 56}}>Entrevistas en medios</h2>
              <p className="bl-sec-sub">Participaciones como entrevistado. El medio se indica en cada ficha.</p>
              <div className="bl-grid">{entrevistas.map(a => (
                <BlogCard key={a.id} article={a} openArticle={openArticle} openTopic={openTopic} />
              ))}</div>
            </>
          )}

          <div className="bl-author-cierre">
            <div>
              <h2>¿Necesitas una consulta con el Dr. Navarro?</h2>
              <p>Revisa su disponibilidad y agenda directamente en su perfil de Doctoralia.</p>
            </div>
            <div className="bl-author-ctas">
              {autor.doctoralia && <CitaCTA url={autor.doctoralia.url} />}
              <button className="bl-cta-ghost" onClick={() => navigate("blog")}>Volver al blog</button>
            </div>
          </div>
        </div>
      </section>
    </main>
  );
}

/* ─────────────────────────  4. ARCHIVO TEMÁTICO  /category/<slug>/  ───────────────────────── */
function CategoryPage({ topicSlug, navigate, openArticle, openTopic, catPage, setCatPage }) {
  const tema = topicBySlug(topicSlug) || BD().topics[0];
  const { pageSize } = BD();
  const lista = BD().articles.filter(a => a.topic_ids.includes(tema.id));
  const totalPag = Math.max(1, Math.ceil(lista.length / pageSize));
  const pagina = Math.min(catPage, totalPag);
  const visibles = lista.slice((pagina - 1) * pageSize, pagina * pageSize);

  return (
    <main className="bl" data-screen-label="13 Categoría"><BlogStyles />
      <section className="section bl-hero">
        <div className="container">
          <nav className="bl-crumbs" aria-label="Ruta de navegación">
            <button onClick={() => navigate("home")}>Inicio</button><span>/</span>
            <button onClick={() => navigate("blog")}>Blog</button><span>/</span>
            <span className="is-current">{tema.name}</span>
          </nav>
          <div className="bl-kicker">Archivo temático</div>
          <h1 className="text-balance" style={{marginTop: 12}}>{tema.name}</h1>
          <p className="bl-lead">{tema.intro}</p>
        </div>
      </section>

      <section className="section bl-body-sec">
        <div className="container">
          <p className="bl-count">{lista.length === 1 ? "1 artículo" : lista.length + " artículos"}</p>
          {lista.length === 0 ? (
            <div className="bl-empty">
              <h3>Este archivo aún no tiene artículos</h3>
              <button className="btn btn-primary" onClick={() => navigate("blog")}>Ver todo el blog</button>
            </div>
          ) : (
            <>
              <div className="bl-grid">
                {visibles.map(a => <BlogCard key={a.id} article={a} openArticle={openArticle} openTopic={openTopic} />)}
              </div>
              <BlogPager page={pagina} total={totalPag} onPage={setCatPage} />
            </>
          )}

          <div className="bl-topics">
            <h2>Otros temas</h2>
            <div className="bl-topics-row">
              {BD().topics.filter(t => t.id !== tema.id && BD().articles.some(a => a.topic_ids.includes(t.id))).map(t => (
                <button key={t.id} className="bl-topic-chip" onClick={() => openTopic(t.slug)}>{t.name}</button>
              ))}
            </div>
          </div>
        </div>
      </section>
    </main>
  );
}

Object.assign(window, { BlogIndexPage, BlogArticlePage, AuthorPage, CategoryPage, BlogCard });
