/*
  Editorial article-page design.
  Matches the approved blog-listing redesign's visual language (serif
  headlines, navy/green/light-background palette, restrained editorial
  tone) applied to the 80 individual article pages.

  Scope discipline: every rule is scoped under ".article-page" — a class
  added only to <main> on the 80 article HTML files by the controlled
  transform script (never added to /blog/ or its 8 listing pages, the
  homepage, or any service page). Verified: ".journal-page" (the listing
  pages' own scope class) and ".article-page" are mutually exclusive,
  added to different files. This file is linked ONLY from the 80 article
  pages, so even a bare selector here cannot affect any other page.
*/

.article-page { --a-navy: var(--color-heading); --a-muted: var(--color-text-muted); --a-green: var(--color-brand); --a-green-dark: var(--color-brand-hover); --a-line: var(--color-border); --a-bg: var(--color-surface-muted); --a-serif: Georgia, 'Times New Roman', serif; }

.article-page.blog-main { background: var(--color-background); }

/* Breathing room before the corporate footer. blog.css's shared
   ".article-main { padding: 44px 0 72px }" is the space after whichever
   column (main content or sidebar) ends last in document flow -- on
   mobile the sidebar stacks below the main content and ends the page, on
   desktop it's usually the main content/related-reading list. Measured
   on the real DNSSEC article: only 72px separated the last related-
   reading row from the footer at 1440px, and blog.css's own <=620px
   rule actually SHRINKS this to 54px, the opposite of what a long
   article needs right before a hard color change into the dark footer.
   Confirmed via computed styles, not assumed. */
.article-page .article-main { padding-bottom: 96px; }
@media (max-width: 620px) {
  .article-page .article-main { padding-bottom: 64px; }
}

/* Breadcrumb — same real links, lighter editorial tone. (A cosmetic
   headless-Chrome rasterization artifact affecting the "/" separator
   glyph was investigated here at length — confirmed present on the
   untouched original site too, confirmed absent from every computed-style
   check, and confirmed to disappear under a forced repaint. It is not a
   layout bug this stylesheet can fix; see the final QA report.) */
.article-page .breadcrumbs { font-family: var(--font-body); font-size: 13px; color: var(--color-text-muted); margin-bottom: 26px; }
.article-page .breadcrumbs a { color: var(--a-green-dark); text-decoration: none; }
.article-page .breadcrumbs a:hover { text-decoration: underline; }

/* Article header — real category, real H1, real date only */
.article-page .article-header { max-width: 800px; }
.article-page .article-topic { font-family: var(--font-body); margin: 0 0 14px; color: var(--a-green-dark); font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; }
.article-page .article-header h1 { font-family: var(--a-serif); font-weight: 700; letter-spacing: -.02em; color: var(--a-navy); font-size: clamp(2rem, 3.6vw, 3.1rem); line-height: 1.12; }
.article-page .article-lead { font-family: var(--font-body); max-width: 720px; color: var(--a-muted); font-size: 18px; line-height: 1.6; }
.article-page .article-meta { font-family: var(--font-body); color: var(--color-text-muted); font-size: 13px; }

/* Featured image — real image, original proportions, subtle frame */
.article-page .article-featured { max-width: 760px; margin: 30px 0 34px; background: var(--color-surface); border: 1px solid var(--color-border-box); border-radius: 4px; padding: 18px; box-sizing: border-box; }
.article-page .article-featured img { width: min(100%, 640px); }

/* Reading column — constrained to a comfortable measure */
.article-page .article-content { max-width: 760px; font-family: var(--font-body); color: var(--a-muted); font-size: 17px; line-height: 1.75; }
.article-page .article-content h2 { font-family: var(--a-serif); font-weight: 700; letter-spacing: -.015em; color: var(--a-navy); font-size: 28px; line-height: 1.22; margin: 44px 0 14px; scroll-margin-top: 20px; }
.article-page .article-content h3 { font-family: var(--a-serif); font-weight: 700; color: var(--a-navy); font-size: 20px; line-height: 1.3; margin: 28px 0 10px; scroll-margin-top: 20px; }
.article-page .article-content p { margin: 0 0 19px; }
.article-page .article-content ul, .article-page .article-content ol { margin: 0 0 22px; padding-left: 22px; }
.article-page .article-content li { margin-bottom: 8px; }
.article-page .article-content li::marker { color: var(--a-green); }
.article-page .article-content a { color: var(--a-green-dark); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }
.article-page .article-content a:hover { color: var(--color-brand-hover); }
.article-page .article-content strong { color: var(--a-navy); }
.article-page .article-content code { font-family: 'Consolas', 'SFMono-Regular', Menlo, Monaco, monospace; font-size: .92em; color: var(--a-navy); background: var(--color-surface-muted); padding: .15em .4em; border-radius: 3px; }
.article-page .article-content pre { max-width: 100%; overflow-x: auto; margin: 0 0 22px; padding: 16px 18px; background: var(--color-heading); color: var(--color-white); border-radius: 5px; font-size: 14px; line-height: 1.55; }
.article-page .article-content pre code { background: none; color: inherit; padding: 0; font-size: 1em; }
.article-page .article-content blockquote { margin: 24px 0; padding: 4px 0 4px 20px; border-left: 3px solid var(--a-green); color: var(--a-navy); font-style: italic; }
.article-page .article-content table { width: 100%; max-width: 100%; margin: 0 0 24px; border-collapse: collapse; font-size: 15px; }
.article-page .article-content table :is(th, td) { padding: 10px 12px; border-bottom: 1px solid var(--a-line); text-align: left; vertical-align: top; }
.article-page .article-content th { color: var(--a-navy); font-family: var(--font-body); font-weight: 700; }
.article-page .article-content .table-scroll { max-width: 100%; overflow-x: auto; }

/* Existing summary callout and secondary diagram — refined, not replaced */
.article-page .article-note { max-width: 760px; margin: 28px 0; padding: 18px 20px; border: 1px solid var(--color-border-box); border-left: 4px solid var(--a-green); background: var(--color-surface); border-radius: 0 4px 4px 0; font-family: var(--font-body); font-size: 15px; line-height: 1.6; color: var(--a-muted); }
.article-page .article-note strong { color: var(--a-navy); }
.article-page .article-diagram { max-width: 760px; }
.article-page .article-diagram figcaption { font-family: var(--font-body); }

/* End-of-article utility navigation */
.article-page .article-back { width: 100%; max-width: min(760px, calc(100vw - 34px)); margin: 0 0 18px; box-sizing: border-box; }
.article-page .article-back a {
  display: inline-flex;
  min-height: 38px;
  align-items: center;
  gap: 8px;
  padding: 0 12px;
  border: 1px solid var(--color-border-box);
  border-radius: var(--radius-sm);
  color: var(--color-brand-hover);
  background: var(--color-surface);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
  transition: border-color var(--transition-fast), background-color var(--transition-fast), color var(--transition-fast);
}
.article-page .article-back a:hover { border-color: var(--color-brand); background: var(--color-media-green); color: var(--color-brand-hover); }
.article-page .article-back a:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }

/* Table of contents (inserted by article.js) — a distinct editorial card,
   not a plain anchor list. Deliberately NOT sticky (see the fuller note
   further down, near .blog-sidebar) — it sits in plain normal document
   flow like every other sidebar block. */
.article-page .toc-panel {
  font-family: var(--font-body);
  background: var(--color-surface);
  border: 1px solid var(--a-line);
  border-top: 3px solid var(--a-navy);
  border-radius: 4px;
  padding: 18px 20px 16px;
  box-shadow: var(--shadow-sm);
}
.article-page .toc-panel h2 {
  font-family: var(--font-body);
  margin: 0 0 12px;
  color: var(--a-green-dark);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
}
/* overflow-x:hidden is required here, not just tidiness: declaring only
   overflow-y forces the browser to auto-compute overflow-x as "auto" too
   (same CSS Overflow spec rule that caused the sticky bug above), and the
   .toc-list a links below deliberately use a negative margin to let their
   hover background bleed to the card's edges — genuinely extending a few
   px past this list's own box. Under an auto-forced overflow-x that
   produced a real, visible horizontal scrollbar (confirmed by measuring
   scrollWidth 10px wider than clientWidth); explicit overflow-x:hidden
   removes it, simply clipping the decorative bleed at the box edge
   instead of scrolling. */
.article-page .toc-list { list-style: none; margin: 0; padding: 0; max-height: min(50vh, 440px); overflow-y: auto; overflow-x: hidden; }
.article-page .toc-list li { margin: 0; }
.article-page .toc-list .toc-h2 { margin-top: 3px; }
.article-page .toc-list .toc-h2:first-child { margin-top: 0; }
.article-page .toc-list a {
  display: block;
  padding: 7px 10px;
  margin: 0 -10px;
  border-radius: 4px;
  color: var(--a-navy);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
  text-decoration: none;
  border-left: 2px solid transparent;
}
.article-page .toc-list a:hover,
.article-page .toc-list a:focus-visible {
  background: var(--a-bg);
  color: var(--a-green-dark);
  border-left-color: var(--a-green);
  outline: none;
}
.article-page .toc-list a.is-active {
  background: var(--color-media-green);
  color: var(--a-green-dark);
  border-left-color: var(--a-green);
  font-weight: 700;
}
/* Nested (H3) items: visually subordinate — smaller, muted, indented, and
   linked to their parent by a thin connecting rail rather than looking
   like a same-level sibling. */
.article-page .toc-list .toc-h3 { margin-left: 15px; padding-left: 11px; border-left: 1px solid var(--a-line); }
.article-page .toc-list .toc-h3 a { padding: 5px 8px; margin: 0 -8px; font-size: 12.5px; font-weight: 500; color: var(--a-muted); border-left: none; }
.article-page .toc-list .toc-h3 a:hover,
.article-page .toc-list .toc-h3 a:focus-visible { color: var(--a-green-dark); background: var(--a-bg); }
.article-page .toc-list .toc-h3 a.is-active { color: var(--a-green-dark); background: var(--color-media-green); font-weight: 600; }

/* Mobile collapsible TOC — same card language as the desktop panel, not a
   default-looking <details> disclosure. */
.article-page details.toc-mobile {
  margin: 20px 0 28px;
  border: 1px solid var(--a-line);
  border-top: 3px solid var(--a-navy);
  border-radius: 4px;
  background: var(--color-surface);
  overflow: hidden;
}
.article-page details.toc-mobile summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 14px 18px;
  font-family: var(--font-body);
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--a-green-dark);
  font-size: 12px;
}
.article-page details.toc-mobile summary::-webkit-details-marker { display: none; }
.article-page details.toc-mobile summary::after {
  content: '';
  flex: none;
  width: 8px; height: 8px;
  border-right: 2px solid var(--a-navy);
  border-bottom: 2px solid var(--a-navy);
  transform: rotate(-45deg);
  transition: transform .18s ease;
}
.article-page details.toc-mobile[open] summary::after { transform: rotate(45deg); }
.article-page details.toc-mobile summary:hover { background: var(--a-bg); }
.article-page details.toc-mobile .toc-list { padding: 4px 14px 14px; max-height: none; border-top: 1px solid var(--a-line); padding-top: 10px; }
.article-page details.toc-mobile .toc-list a { font-size: 14.5px; }

/* Related-reading list — replaces the old 2-column card grid (which
   produced an orphan third card and a lot of empty space whenever an
   article had 3 cards, and mixed a commercial "Servicio" card into the
   editorial reading list). A single-column row list has no card-count
   parity problem at all: 1, 2, 3+ rows all read cleanly, and it uses a
   real per-article thumbnail (sourced from articles.json, the same data
   already used for the listing pages — never a guessed path). */
.article-page .related-articles {
  width: 100%;
  max-width: min(760px, calc(100vw - 34px));
  box-sizing: border-box;
  margin-top: 38px;
  padding-top: 26px;
  border-top: 1px solid var(--color-border);
}
.article-page .related-articles h2 {
  margin: 0 0 16px;
  color: var(--color-heading);
  font-family: var(--font-heading);
  font-size: 1.35rem;
  line-height: 1.3;
}
.article-page .related-reading-list {
  width: 100%;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.article-page .related-reading-item { display: flex; min-width: 0; }
.article-page .related-reading-row {
  display: grid;
  flex: 1;
  min-height: 92px;
  box-sizing: border-box;
  grid-template-columns: 92px minmax(0, 1fr);
  align-items: center;
  gap: 14px;
  padding: 10px;
  border: 1px solid var(--color-border-box);
  border-radius: var(--radius-md);
  color: var(--color-heading);
  background: var(--color-surface);
  text-decoration: none;
  transition: border-color var(--transition-fast), background-color var(--transition-fast), box-shadow var(--transition-fast);
}
/*
  Checkpoint "interacción de tarjeta unificada" (2026-09-27): mismos
  tokens de marca que el resto del sitio ("--color-brand"/
  "--color-media-green", en vez de los equivalentes locales
  "--a-green"/"--a-green-dark" del artículo — casi idénticos pero no
  el mismo valor exacto). Se añade el mismo zoom de miniatura ya usado
  en el resto de tarjetas con imagen.
*/
.article-page .related-reading-row:hover,
.article-page .related-reading-row:focus-visible {
  background: var(--color-media-green);
  outline: none;
  border-color: var(--color-brand);
  box-shadow: var(--shadow-sm);
}
.article-page .related-reading-row:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.article-page .related-reading-thumb { display: block; width: 92px; height: 70px; overflow: hidden; border-radius: var(--radius-sm); border: 1px solid var(--color-border); background: var(--color-surface-muted); transition: border-color var(--transition-fast); }
.article-page .related-reading-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform var(--transition-fast); }
.article-page .related-reading-row:hover .related-reading-thumb,
.article-page .related-reading-row:focus-visible .related-reading-thumb { border-color: var(--color-brand); }
.article-page .related-reading-row:hover .related-reading-thumb img,
.article-page .related-reading-row:focus-visible .related-reading-thumb img { transform: scale(1.02); }
.article-page .related-reading-body { min-width: 0; }
.article-page .related-reading-topic { display: block; margin-bottom: 5px; color: var(--color-brand-hover); font-family: var(--font-body); font-size: 10px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.article-page .related-reading-title { display: block; font-family: var(--font-heading); font-weight: 700; color: var(--color-heading); font-size: 15px; line-height: 1.35; transition: color var(--transition-fast); }
.article-page .related-reading-row:hover .related-reading-title,
.article-page .related-reading-row:focus-visible .related-reading-title { color: var(--color-brand-hover); }

@media (prefers-reduced-motion: reduce) {
  .article-page .article-back a {
    transition: none;
  }
  .article-page .related-reading-row,
  .article-page .related-reading-thumb,
  .article-page .related-reading-thumb img,
  .article-page .related-reading-title {
    transition: none;
  }
}

/* Restrained commercial service note — visually distinct from the
   editorial reading list above/below it (a panel with a label, not
   another "article card"). Only present on articles where a verified,
   relevant ANYSRV service already exists; reuses the exact text and
   destination already verified for that article's sidebar CTA (never
   a new or invented claim).
   Checkpoint "unificación del sistema de precio en todo el sitio"
   (2026-09-26): el fondo pasa del verde tenue anterior (var(--color-media-green)) a
   blanco con el borde estructural ya usado en el resto del sitio
   ("--color-border", tokens.css) — con el precio navy/azul aprobado
   ahora dentro de esta nota (".service-price", componente
   compartido), un fondo verde detrás competía con el azul del precio.
   La etiqueta "Servicio relacionado" sigue en verde (mismo acento ya
   usado en ".article-topic" y el resto de etiquetas del artículo) —
   solo el fondo del panel se neutraliza, no el lenguaje editorial del
   artículo. Variante ".article-service-note--generic" (sin
   "--color-border" propio, mismo look): usada en artículos sin un
   servicio comercial directamente relevante, con un CTA genérico de
   contacto y SIN componente de precio — nunca se inventa un precio
   cuando no aplica un servicio priced. */
.article-page .article-service-note {
  display: grid;
  width: 100%;
  max-width: min(760px, calc(100vw - 34px));
  box-sizing: border-box;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "label label" "title price" "description action";
  align-items: center;
  gap: 8px 24px;
  margin: 0 0 38px;
  padding: 22px 24px;
  background: var(--color-surface);
  border: 1px solid var(--color-border-box);
  border-radius: var(--radius-md);
  transition: border-color var(--transition-fast), background-color var(--transition-fast), box-shadow var(--transition-fast);
}
.article-page .article-service-note__label { grid-area: label; }
.article-page .article-service-note h2 { grid-area: title; min-width: 0; margin: 0; font-family: var(--font-heading); font-size: 1.15rem; line-height: 1.3; color: var(--color-heading); }
.article-page .article-service-note > p:not(.article-service-note__label) { grid-area: description; min-width: 0; margin: 0; font-family: var(--font-body); font-size: 14px; line-height: 1.55; color: var(--color-text-muted); }
.article-page .article-service-note > .service-price { grid-area: price; justify-self: end; }
.article-page .article-service-note > .btn { grid-area: action; justify-self: end; align-self: start; min-height: 44px; }
.article-page .article-service-note--generic {
  grid-template-areas: "label label" "title action" "description action";
}
/*
  Checkpoint "interacción de tarjeta unificada" (2026-09-27): la nota
  de servicio entera reacciona igual que el resto de tarjetas
  interactivas del sitio al pasar el ratón o el foco de teclado sobre
  el CTA que contiene — borde → "--color-brand", fondo con el mismo
  tinte verde muy sutil. El precio (si lo hay) no cambia de color:
  sigue azul/navy y legible, como en el resto del sistema.
*/
.article-page .article-service-note:hover,
.article-page .article-service-note:focus-within {
  border-color: var(--color-brand);
  background: var(--color-media-green);
}

@media (prefers-reduced-motion: reduce) {
  .article-page .article-service-note {
    transition: none;
  }
}
.article-page .article-service-note p.article-service-note__label { margin: 0; color: var(--color-brand-hover); font-family: var(--font-body); font-size: 11px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
.article-page .article-service-note .btn { font-family: var(--font-body); }

/* Price component embedded in the note: same shared ".service-price"
   as the homepage/hero/dominios, sized at its restrained base scale
   (not the bolder homepage-only override) — deliberately smaller than
   the homepage service cards, per the "editorial recommendation, not
   promotional banner" brief. */
.article-page .article-service-note .service-price { display: flex; width: fit-content; min-height: 42px; align-items: center; margin: 0; }

@media (max-width: 620px) {
  .article-page .article-service-note,
  .article-page .article-service-note--generic {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "label" "title" "description" "price" "action";
    gap: 8px;
    margin-bottom: 30px;
    padding: 18px;
  }
  .article-page .article-service-note > .service-price,
  .article-page .article-service-note > .btn { justify-self: start; }
  .article-page .article-service-note > .btn { margin-top: 4px; }
}

@media (max-width: 620px) {
  .article-page .related-reading-list { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .article-page .related-reading-row { grid-template-columns: 84px minmax(0, 1fr); gap: 12px; }
  .article-page .related-reading-thumb { width: 84px; height: 60px; }
  .article-page .related-reading-title { font-size: 15px; }
}

/* Sidebar (TOC card + existing recommendations). Plain normal document
   flow, deliberately not sticky (see the note on .toc-panel below for
   why) — overrides blog.css's shared "position: sticky; top: 22px" so
   every sidebar block simply starts after the previous one ends. */
.article-page .blog-sidebar { position: static; border-top: 0; padding-top: 0; gap: 0; }
/* A little more vertical room per panel than the shared default (20px)
   for clearer separation between sidebar sections -- still just a
   single 1px divider, no new borders or card treatment added. */
.article-page .sidebar-panel { padding: 24px 0; border: 0; border-radius: 0; background: none; box-shadow: none; border-bottom: 1px solid var(--a-line); }
.article-page .sidebar-panel:last-child { border-bottom: 0; }
.article-page .sidebar-panel h2 { font-family: var(--a-serif); font-size: 17px; color: var(--a-navy); }
.article-page .sidebar-panel h2::after { display: none; }
.article-page .sidebar-categories a { font-family: var(--font-body); border-radius: 3px; }

/* "Últimos artículos" — titles were previously inheriting the shared
   blog.css defaults (700-weight but undersized next to the small,
   pale-gray var(--color-text-muted) metadata line), which read as flat/low-contrast.
   Titles are now clearly the primary element; the category/type label
   is a small but genuinely legible, brand-green uppercase tag instead
   of pale gray, consistent with the eyebrow-label pattern already used
   elsewhere on this page (.article-topic, .toc-panel h2). */
.article-page .sidebar-list { gap: 0; }
.article-page .sidebar-list a { font-family: var(--font-body); font-size: 16px; font-weight: 600; line-height: 1.35; color: var(--a-navy); }
.article-page .sidebar-list a:hover { color: var(--a-green-dark); }
.article-page .sidebar-list a:focus-visible { outline: 2px solid var(--a-green); outline-offset: 3px; border-radius: 2px; }
.article-page .sidebar-list small { display: block; margin-top: 7px; font-family: var(--font-body); font-size: 13px; font-weight: 700; color: var(--a-green-dark); letter-spacing: .02em; }
.article-page .sidebar-list li { padding-bottom: 16px; margin-bottom: 16px; border-bottom: 1px solid var(--a-line); }
.article-page .sidebar-list li:last-child { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }

/* "También te puede interesar" (sidebar, thumbnail cards) — same
   direction, lighter touch since it already had reasonable contrast:
   slightly larger/darker title, slightly more legible topic label. */
.article-page .sidebar-related-card { font-family: var(--font-body); }
.article-page .sidebar-related-card strong { font-size: 14.5px; line-height: 1.33; color: var(--a-navy); transition: color 200ms ease; }
.article-page .sidebar-related-topic { font-size: 10.5px; color: var(--a-green-dark); }
.article-page .sidebar-related-card:hover strong { color: var(--color-brand-hover); }
.article-page .sidebar-related-card:focus-visible { outline: 2px solid var(--color-brand); outline-offset: 3px; border-radius: 4px; }

@media (prefers-reduced-motion: reduce) {
  .article-page .sidebar-related-card strong {
    transition: none;
  }
}

/* The TOC card sits outside the bordered/divided panel rhythm above (it's
   already visually self-contained, with its own full border on every
   edge). Re-declared explicitly since it comes after the generic
   .sidebar-panel border-bottom rule above.

   NOT sticky (deliberately). A prior version made only .toc-panel sticky
   while its parent (.blog-sidebar) and siblings (the CTA and related-
   articles panels) stayed in normal, non-sticky flow. That caused a real,
   reproducible overlap bug: position:sticky reserves an element's space
   in the document flow at its ORIGINAL (unstuck) position — following
   siblings lay themselves out relative to that original flow position,
   not relative to where the sticky element is currently painted. Once
   scrolled, the visually-pinned TOC card and the normally-scrolling CTA/
   related-articles panels ended up rendering on top of each other.
   Confirmed via real top-level Chrome scrolling (bounding-rect
   measurement at multiple scroll positions, not a screenshot artifact):
   e.g. on the VPS article at 1440px and 1024px, scrolling to y=400
   produced toc.bottom=547 while cta.top=275 — a large, real overlap.
   Fixed by removing sticky entirely: the whole sidebar now stays in
   plain normal flow, so every block starts exactly where the previous
   one ends, with no possibility of this class of bug. */
.article-page .toc-panel { border-bottom: 1px solid var(--a-line); margin-bottom: 22px; }

@media (max-width: 980px) {
  .article-page .article-layout { gap: 28px; }
}
@media (max-width: 820px) {
  .article-page .toc-panel { display: none; } /* desktop sidebar TOC hidden; mobile uses the collapsible <details> instead */
}
@media (min-width: 821px) {
  .article-page details.toc-mobile { display: none; } /* mobile collapsible hidden; desktop uses the sidebar TOC instead */
}
@media (max-width: 620px) {
  .article-page .article-featured { padding: 10px; }
  .article-page .article-content { font-size: 16px; line-height: 1.68; }
  .article-page .article-content h2 { font-size: 23px; margin-top: 34px; }
  .article-page .article-content h3 { font-size: 18px; }
}

/*
  PHASE 4B additions — ported from the proven EN/AR Journal article
  template (the EN/AR Journal reference project's article.css), restyled with
  this project's own existing article idiom (--a-navy/--a-green/
  --a-muted, Georgia display serif for headings, var(--font-body) for
  UI chrome) rather than copied verbatim, since this file already has
  its own established visual language. Behavior/structure matches the
  reference 1:1; only literal colors/radii/shadows are ES-native.
  This file loads ONLY on the 80 article pages (see the file-scope
  note at the top), so the reading-progress selector below is safely
  scoped to article pages.
*/

/* Reading progress — fixed hairline above everything, including the
   pinned header, so it never depends on the header's own stacking.
   A native <progress> element driven by article.js setting its .value
   IDL property (not .style.width): under this project's strict CSP
   (style-src 'self', no 'unsafe-inline') any inline-style write is
   blocked -- confirmed via real WebKit/Firefox testing, where the old
   div+.style.width version silently froze at 0% in both. .value is
   plain element state, never gated by style-src, so this is CSP-safe
   in every engine while keeping the exact same visual hairline. */
.reading-progress {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  position: fixed;
  top: 0; left: 0; right: 0;
  width: 100%;
  height: 3px;
  border: none;
  z-index: 10000;
  background: transparent;
  pointer-events: none;
}
.reading-progress::-webkit-progress-bar { background: transparent; }
.reading-progress::-webkit-progress-value {
  background: var(--a-green);
  transition: width 120ms linear;
}
.reading-progress::-moz-progress-bar {
  background: var(--a-green);
  transition: width 120ms linear;
}
@media (prefers-reduced-motion: reduce) {
  .reading-progress::-webkit-progress-value { transition: none; }
  .reading-progress::-moz-progress-bar { transition: none; }
}

/* Article meta line — now "{tipo de contenido} · {autor} · {N min de
   lectura}" (no date: see the project's date-honesty policy, only
   rendered when dateVerified === true and never here by default). */
.article-page .article-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5em; }

/* Share row — compact circular icon buttons, real networks only
   (Facebook/LinkedIn/X/WhatsApp) plus copy-link and native-share,
   matching the proven reference's exact button set. */
.article-page .share-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.article-page .article-content + .share-row { margin-top: 30px; }
.article-page .share-row__label { font-family: var(--font-body); font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--a-muted); margin-right: 2px; }
.article-page .share-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px;
  border-radius: 50%;
  border: 1px solid var(--a-line);
  background: var(--color-surface);
  color: var(--a-green-dark);
  transition: background-color 200ms ease, border-color 200ms ease, color 200ms ease;
}
.article-page .share-btn:hover { background: var(--color-media-green); border-color: var(--a-green); }
.article-page .share-btn[hidden] { display: none; }
.article-page .share-row__feedback { font-family: var(--font-body); font-size: 13px; color: var(--a-green-dark); font-weight: 700; }
@media (prefers-reduced-motion: reduce) {
  .article-page .share-btn { transition: none; }
}

/* Author / publisher block — organizational attribution only, same as
   the reference (no invented named person). */
.article-page .author-block { display: flex; align-items: center; gap: 14px; margin-top: 30px; padding-top: 22px; border-top: 1px solid var(--a-line); max-width: 760px; }
.article-page .author-block__avatar { flex: none; width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: var(--color-media-green); color: var(--a-green-dark); font-family: var(--font-body); font-weight: 800; font-size: 13px; }
.article-page .author-block__name { font-family: var(--font-body); font-weight: 700; color: var(--a-navy); font-size: 14.5px; }
.article-page .author-block__bio { font-family: var(--font-body); font-size: 13px; color: var(--a-muted); margin-top: 2px; }

/* Previous / next pager — deterministic articles.json order; a missing
   side (first/last article) simply omits that half of the grid. */
.article-page .article-pager { max-width: 760px; display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 16px; margin: 36px 0 0; padding-top: 26px; border-top: 1px solid var(--a-line); }
.article-page .article-pager a { display: block; padding: 14px 16px; border: 1px solid var(--color-border-box); border-radius: 4px; text-decoration: none; transition: border-color 200ms ease, background-color 200ms ease; }
.article-page .article-pager a:hover { border-color: var(--a-green); background: var(--color-media-green); }
.article-page .article-pager__label { font-family: var(--font-body); font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--a-green-dark); }
.article-page .article-pager__title { display: block; margin-top: 6px; font-family: var(--a-serif); font-weight: 700; color: var(--a-navy); font-size: 15px; line-height: 1.35; }
.article-page .article-pager--next { text-align: right; grid-column: 2; }
.article-page .article-pager--prev { grid-column: 1; }
@media (prefers-reduced-motion: reduce) {
  .article-page .article-pager a { transition: none; }
}

@media (max-width: 620px) {
  .article-page .article-pager { grid-template-columns: minmax(0, 1fr); }
  .article-page .article-pager--next { text-align: left; grid-column: 1; }
}
