// ─── Atlas Method — Articles Service Layer ────────────────────────────────────
//
// ARCHITECTURE OVERVIEW
// ─────────────────────
// This service is the single source of truth for all article data.
// Currently backed by localStorage + mock seed data.
//
// TO MIGRATE TO SUPABASE:
//   Replace _fetch / _mutate helpers with supabase.from('articles')... calls.
//   Auth token is passed as ArticlesService.setToken(jwt) before any call.
//
// TO MIGRATE TO FIREBASE:
//   Replace _fetch / _mutate helpers with getDoc / setDoc / updateDoc from Firestore.
//
// TO INTEGRATE PUBMED:
//   ArticlesService.importFromPubMed(pmid) already has the correct return shape.
//   Replace the mock with: fetch(`https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id=${pmid}&retmode=json`)
//
// TO INTEGRATE SEMANTIC SCHOLAR:
//   ArticlesService.importFromSemanticScholar(doi) — same pattern.
//   API: https://api.semanticscholar.org/graph/v1/paper/{doi}
//
// TO INTEGRATE AI SUMMARIES (Claude):
//   ArticlesService.generateAISummary(id) calls Anthropic API.
//   Endpoint: POST /api/ai/summarize with { articleId, sections }
//   The admin triggers this manually before publishing.

// ─── Data model ───────────────────────────────────────────────────────────────
// {
//   id: string                         unique slug
//   title: string
//   subtitle: string
//   category: 'fuerza'|'hipertrofia'|'nutricion'|'recuperacion'|'cognitivo'|'sueno'
//   tags: string[]
//   status: 'draft'|'reviewing'|'published'|'rejected'
//   readTime: number                   minutes
//   gems: number                       reward on first read
//   publishedAt: ISO string | null
//   updatedAt: ISO string
//   rejectionReason: string | null
//
//   — Content —
//   summary: string                    one-paragraph abstract
//   sections: [{ heading, body }]      article body
//   refs: string[]                     APA citations
//
//   — Study metadata (PubMed / Semantic Scholar) —
//   doi: string | null
//   pmid: string | null
//   semanticScholarId: string | null
//   authors: string[]
//   journal: string | null
//   publishYear: number | null
//   evidenceLevel: 'meta-analysis'|'rct'|'cohort'|'review'|'expert-opinion'
//
//   — AI fields —
//   aiSummary: string | null           Claude-generated plain-language summary
//   aiKeywords: string[]               extracted keywords
//   aiGeneratedAt: ISO string | null
//
//   — Images —
//   coverImage: string | null          URL (Supabase Storage / CDN)
//   figures: [{ url, caption }]        in-article figures (legacy)
//
//   — Rich body (preferred) —
//   blocks: Block[]                     typed content blocks, rendered in order.
// }
//
// ─── Block model (article.blocks) ─────────────────────────────────────────────
// A block-based body lets images, quotes, lists and citations sit exactly where
// they belong in the flow. Add an article = add a data entry with blocks; the
// reader renders every type with no UI changes. Legacy articles (only `sections`
// + `refs` + `figures`) are converted on the fly by ArticlesService.getBlocks().
//
//   { type:'lead',      text }                         intro paragraph (larger)
//   { type:'heading',   text }                         section subtitle
//   { type:'paragraph', text, cite?:number|number[] }  body text; cite → superscript ref number(s)
//   { type:'list',      ordered?:bool, items:string[] }
//   { type:'quote',     text, attribution? }           pull-quote
//   { type:'callout',   variant:'key'|'tip'|'warning', title?, text }  highlighted box
//   { type:'image',     src?, diagram?, alt?, caption?, credit? }
//         · src     = URL or data: URI (free-license images only)
//         · diagram = id of a built-in ORIGINAL SVG diagram (see ARTICLE_DIAGRAMS)
//   { type:'reference', n?, authors, year, title, journal, doi?, url?, raw? }
//         scientific source; collected into the numbered bibliography, and
//         referenced inline via a paragraph's `cite`.

const STORAGE_KEY = 'atlas.articles.v2';
const ADMIN_KEY   = 'atlas.admin.token';

// ─── Seed data ────────────────────────────────────────────────────────────────
const SEED = [
  // ─── Concurrent training — cardio & hypertrophy ───────────────────────────
  {
    id: 'cardio-perdida-musculo',
    title: '¿El cardio te hace perder músculo?',
    subtitle: 'Lo que dice la ciencia sobre combinar fuerza y resistencia',
    category: 'hipertrofia', tags: ['cardio', 'hipertrofia', 'concurrente', 'ciencia'],
    status: 'published', readTime: 6, gems: 15,
    publishedAt: '2026-10-01T09:00:00Z', updatedAt: '2026-10-01T09:00:00Z',
    rejectionReason: null,
    summary: 'Para la mayoría de personas, combinar cardio y fuerza no reduce de forma relevante las ganancias de músculo ni de fuerza; solo quienes buscan potencia o fuerza máxima en las piernas deben afinar los detalles.',
    blocks: [
      { type: 'keypoints', items: [
        'Combinar cardio y fuerza no reduce de forma relevante el músculo ni la fuerza máxima.',
        'Sobre la fuerza explosiva y la modalidad (correr o bici), los resultados son contradictorios.',
        'Si las haces el mismo día y priorizas la fuerza, pesas primero.',
      ] },
      { type: 'heading', text: 'De dónde viene el miedo' },
      { type: 'paragraph', text: '"Si corres, te comes el músculo." Es uno de los mitos más repetidos del gimnasio, y tiene un origen real: la idea de que el entrenamiento de resistencia "interfiere" con las ganancias de fuerza se describió por primera vez en el trabajo de Hickson, en 1980. Desde entonces se le llama efecto interferencia. La pregunta es si, más de cuatro décadas y cientos de estudios después, ese efecto sigue en pie.' },
      { type: 'heading', text: 'Qué dicen los metaanálisis' },
      { type: 'paragraph', text: 'La revisión más citada sobre el tema, de Schumann y colaboradores, analizó 43 estudios y concluyó que combinar entrenamiento aeróbico y de fuerza no reduce de forma relevante las ganancias de fuerza máxima ni de masa muscular, en distintas edades, niveles de forma física y tipos de cardio, tanto carrera como bicicleta. Lo único que sí podría verse afectado es la fuerza explosiva, sobre todo cuando ambos entrenamientos se hacen en la misma sesión.' },
      { type: 'heading', text: 'El matiz: la fibra muscular y la carrera' },
      { type: 'paragraph', text: 'Lundberg y colaboradores, revisando 15 estudios, encontraron un efecto negativo pequeño sobre el crecimiento de las fibras musculares. Ese efecto aparecía en las fibras tipo I cuando el cardio era correr, pero no cuando era bicicleta. Los autores lo presentan como evidencia preliminar. Una explicación probable: correr tiene un componente excéntrico mayor que pedalear y genera más daño muscular.' },
      { type: 'heading', text: 'La evidencia más reciente (2026)' },
      { type: 'paragraph', text: 'Este año se ha publicado una revisión paraguas que analiza los metaanálisis existentes: 17 metaanálisis, 144 estudios y casi 1.500 participantes sanos. Su conclusión: comparado con entrenar solo fuerza, combinar fuerza y cardio da resultados equiparables en fuerza, potencia e hipertrofia, y además mejora significativamente la capacidad aeróbica. Los propios autores advierten que todavía hay pocos datos en deportistas de élite.' },
      { type: 'quote', text: 'Para la mayoría de personas, el cardio no te quita músculo: te suma salud sin restarte ganancias.' },
      { type: 'heading', text: 'Quién debería tener más cuidado' },
      { type: 'paragraph', text: 'El efecto no es igual para todos. Un metaanálisis que estudió el papel del sexo y del nivel de entrenamiento encontró una pequeña interferencia en la fuerza del tren inferior en hombres, pero no en mujeres. En la práctica, quien más tiene que afinar es quien busca potencia o fuerza máxima en las piernas, no quien entrena por salud o estética.' },
      { type: 'heading', text: 'Aplicación práctica' },
      { type: 'list', items: [
        'Pesas primero, cardio después (la revisión de 2026 no encontró diferencias claras según el orden, pero las tendencias apuntan a que hacer la fuerza antes favorece las ganancias de fuerza y masa muscular)',
        'Si te preocupan las piernas, la bici tiene menos impacto, aunque la evidencia sobre qué modalidad interfiere más es contradictoria',
        'Separa las sesiones cuando puedas, sobre todo si tu objetivo es la potencia',
        'Ajusta la dosis: unas sesiones de cardio a la semana no te frenan; un volumen muy alto puede pasar factura a tu recuperación.',
      ] },
      { type: 'reference', raw: 'Held S, Wolf L, Rappelt L, et al. (2026). Maximizing Adaptations in Concurrent Training: An Umbrella Review of Meta-analyses. Sports Medicine, 56(6):1489–1512.', doi: '10.1007/s40279-026-02401-y', ev: 'Revisión paraguas' },
      { type: 'reference', raw: 'Schumann M, Feuerbacher JF, Sünkeler M, et al. (2022). Compatibility of Concurrent Aerobic and Strength Training for Skeletal Muscle Size and Function. Sports Medicine, 52(3):601–612.', doi: '10.1007/s40279-021-01587-7', ev: 'Metaanálisis' },
      { type: 'reference', raw: 'Lundberg TR, Feuerbacher JF, Sünkeler M, Schumann M. (2022). The Effects of Concurrent Aerobic and Strength Training on Muscle Fiber Hypertrophy. Sports Medicine, 52(10):2391–2403.', doi: '10.1007/s40279-022-01688-x', ev: 'Metaanálisis' },
      { type: 'reference', raw: 'Huiberts RO, Wüst RCI, van der Zwaard S. (2023). Concurrent Strength and Endurance Training: The Impact of Sex and Training Status. Sports Medicine.', doi: '10.1007/s40279-023-01943-9', ev: 'Metaanálisis' },
      { type: 'reference', raw: 'Hickson RC. (1980). Interference of strength development by simultaneously training for strength and endurance. Eur J Appl Physiol, 45:255–263.', ev: 'Estudio histórico' },
    ],
    doi: null, pmid: null, semanticScholarId: null,
    authors: [], journal: 'Sports Medicine', publishYear: 2026,
    evidenceLevel: 'umbrella-review',
    aiSummary: null, aiKeywords: ['cardio', 'efecto interferencia', 'entrenamiento concurrente', 'hipertrofia', 'resistencia'], aiGeneratedAt: null,
    coverImage: 'https://images.unsplash.com/photo-1761971976282-b2bb051a5474?w=900&q=80&fit=crop', figures: [],  // eran design
  },
  // ─── First science-backed lesson in the block format ──────────────────────
  {
    id: 'frecuencia-entrenamiento',
    title: 'Frecuencia de entrenamiento: ¿Cuántas veces por semana entrenar cada músculo?',
    subtitle: 'Lo que dice la ciencia cuando se controla el volumen',
    category: 'hipertrofia', tags: ['frecuencia', 'volumen', 'ciencia'],
    status: 'published', readTime: 6, gems: 15,
    publishedAt: '2026-09-02T09:00:00Z', updatedAt: '2026-09-02T09:00:00Z',
    rejectionReason: null,
    summary: 'Para ganar músculo, la frecuencia importa poco si el volumen es el mismo; para ganar fuerza, repartir en más sesiones puede ayudar algo.',
    blocks: [
      { type: 'keypoints', items: [
        'Con el mismo volumen semanal, 1, 2 o 3 sesiones por músculo dan un crecimiento parecido.',
        'Para la fuerza, repartir en más sesiones puede ayudar algo.',
        'La frecuencia sirve para repartir el volumen con calidad.',
      ] },
      { type: 'heading', text: 'La pregunta mal planteada' },
      { type: 'paragraph', text: 'Durante años se ha discutido si es mejor entrenar un músculo una vez por semana o repartirlo en varias sesiones. Pero la ciencia reciente sugiere que la pregunta, tal como se plantea, lleva a confusión. Lo que de verdad importa no es cuántas veces, sino cuánto en total — y la frecuencia es solo una herramienta para repartir ese total.' },
      { type: 'heading', text: 'Qué dice la evidencia (volumen igualado)' },
      { type: 'paragraph', text: 'Cuando se iguala el volumen semanal —el mismo número total de series a la semana—, entrenar un músculo una, dos o tres veces por semana produce ganancias de masa muscular similares. Una revisión sistemática y metaanálisis concluyó que la frecuencia no afecta de forma significativa a la hipertrofia cuando el volumen está igualado, de modo que cada persona puede elegir la frecuencia por grupo muscular según su preferencia. Esto se ha confirmado con medidas directas de crecimiento: bajo volumen igualado, entrenar una vez por semana produce una hipertrofia similar a hacerlo dos o tres veces.' },
      { type: 'image', diagram: 'volumen-1-vs-3', caption: 'El mismo volumen semanal (p. ej. 12 series) repartido en 1 sesión o en 3 sesiones.', credit: 'Diagrama original · Atlas Method' },
      { type: 'heading', text: 'El matiz de 2024-2026: el metaanálisis más completo hasta la fecha' },
      { type: 'paragraph', text: 'El análisis más exhaustivo publicado hasta ahora revisó 67 estudios con 2.058 participantes y encontró que volumen y frecuencia tienen relaciones dosis-respuesta distintas. El volumen aumenta tanto la hipertrofia como la fuerza a medida que crece, aunque con rendimientos decrecientes; para la hipertrofia, el efecto de la frecuencia fue compatible con efectos insignificantes cuando el volumen se mantiene constante. Para la fuerza, más frecuencia sí parece aportar mejoras, también con rendimientos decrecientes.' },
      { type: 'quote', text: 'Para ganar músculo, la frecuencia importa poco si el volumen es el mismo; para ganar fuerza, repartir en más sesiones puede ayudar algo.' },
      { type: 'heading', text: 'Entonces, ¿por qué repartir en varias sesiones?' },
      { type: 'paragraph', text: 'Si el resultado en músculo es parecido, la frecuencia sigue siendo útil como herramienta práctica, no como fin. Repartir el volumen en más días permite hacer más series semanales sin sesiones eternas, mantener mejor la calidad de cada serie (menos fatiga acumulada dentro de la sesión), y encajar mejor el entrenamiento en la semana.' },
      { type: 'heading', text: 'Aplicación práctica' },
      { type: 'paragraph', text: 'Elige primero cuánto volumen necesita cada músculo. Después reparte ese volumen en las sesiones que mejor te encajen: si tu volumen es bajo, una vez por semana puede bastar; si es alto, repartirlo en 2-3 sesiones te ayudará a completarlo con calidad. La frecuencia es tu aliada para cumplir el volumen, no un número mágico en sí mismo.' },
      { type: 'reference', raw: 'Pelland JC, Remmert JF, Robinson ZP, Hinson SR, Zourdos MC, et al. (2026). The Resistance Training Dose-Response: Meta-Regressions Exploring the Effects of Weekly Volume and Frequency on Muscle Hypertrophy and Strength Gain. Sports Medicine, 56(2):481-505.', doi: '10.1007/s40279-025-02344-w', ev: 'Metaanálisis' },
      { type: 'reference', raw: 'Schoenfeld BJ, Grgic J, Krieger J. (2019). How many times per week should a muscle be trained to maximize muscle hypertrophy? A systematic review and meta-analysis. Journal of Sports Sciences.', doi: '10.1080/02640414.2018.1555906', ev: 'Metaanálisis' },
      { type: 'reference', raw: 'Grgic J, et al. (2018). Resistance training frequency and skeletal muscle hypertrophy: A review of available evidence. Journal of Science and Medicine in Sport.', doi: '10.1016/j.jsams.2018.09.223', ev: 'Revisión sistemática' },
    ],
    sections: [
      { heading: 'La pregunta mal planteada', body: 'Durante años se ha discutido si es mejor entrenar un músculo una vez por semana o repartirlo en varias sesiones. Pero la ciencia reciente sugiere que la pregunta, tal como se plantea, lleva a confusión. Lo que de verdad importa no es cuántas veces, sino cuánto en total — y la frecuencia es solo una herramienta para repartir ese total.' },
      { heading: 'Qué dice la evidencia (volumen igualado)', body: 'Cuando se iguala el volumen semanal —el mismo número total de series a la semana—, entrenar un músculo una, dos o tres veces por semana produce ganancias de masa muscular similares. Una revisión sistemática y metaanálisis concluyó que la frecuencia no afecta de forma significativa a la hipertrofia cuando el volumen está igualado, de modo que cada persona puede elegir la frecuencia por grupo muscular según su preferencia. Esto se ha confirmado con medidas directas de crecimiento: bajo volumen igualado, entrenar una vez por semana produce una hipertrofia similar a hacerlo dos o tres veces.' },
      { heading: 'El matiz de 2024-2026: el metaanálisis más completo hasta la fecha', body: 'El análisis más exhaustivo publicado hasta ahora revisó 67 estudios con 2.058 participantes y encontró que volumen y frecuencia tienen relaciones dosis-respuesta distintas. El volumen aumenta tanto la hipertrofia como la fuerza a medida que crece, aunque con rendimientos decrecientes; para la hipertrofia, el efecto de la frecuencia fue compatible con efectos insignificantes cuando el volumen se mantiene constante. Para la fuerza, más frecuencia sí parece aportar mejoras, también con rendimientos decrecientes.' },
      { heading: 'Entonces, ¿por qué repartir en varias sesiones?', body: 'Si el resultado en músculo es parecido, la frecuencia sigue siendo útil como herramienta práctica, no como fin. Repartir el volumen en más días permite hacer más series semanales sin sesiones eternas, mantener mejor la calidad de cada serie (menos fatiga acumulada dentro de la sesión), y encajar mejor el entrenamiento en la semana.' },
      { heading: 'Aplicación práctica', body: 'Elige primero cuánto volumen necesita cada músculo. Después reparte ese volumen en las sesiones que mejor te encajen: si tu volumen es bajo, una vez por semana puede bastar; si es alto, repartirlo en 2-3 sesiones te ayudará a completarlo con calidad. La frecuencia es tu aliada para cumplir el volumen, no un número mágico en sí mismo.' },
    ],
    refs: [
      'Pelland JC, Remmert JF, Robinson ZP, Hinson SR, Zourdos MC, et al. (2026). The Resistance Training Dose-Response: Meta-Regressions Exploring the Effects of Weekly Volume and Frequency on Muscle Hypertrophy and Strength Gain. Sports Medicine, 56(2):481-505.',
      'Schoenfeld BJ, Grgic J, Krieger J. (2019). How many times per week should a muscle be trained to maximize muscle hypertrophy? A systematic review and meta-analysis. Journal of Sports Sciences.',
      'Grgic J, et al. (2018). Resistance training frequency and skeletal muscle hypertrophy: A review of available evidence. Journal of Science and Medicine in Sport.',
    ],
    doi: null, pmid: null, semanticScholarId: null,
    authors: [], journal: 'Sports Medicine', publishYear: 2026,
    evidenceLevel: 'meta-analysis',
    aiSummary: null, aiKeywords: ['frecuencia', 'volumen', 'hipertrofia', 'fuerza', 'dosis-respuesta'], aiGeneratedAt: null,
    coverImage: 'https://images.unsplash.com/photo-1562771242-a02d9090c90c?w=900&q=80&fit=crop', figures: [],  // Alora Griffiths
  },
  {
    id: 'sobrecarga-progresiva',
    title: 'Sobrecarga progresiva',
    subtitle: 'Cómo seguir progresando',
    category: 'fuerza', tags: ['fundamental', 'principiante'],
    status: 'published', readTime: 6, gems: 15,
    publishedAt: '2026-01-10T10:00:00Z', updatedAt: '2026-10-31T10:00:00Z',
    rejectionReason: null,
    summary: 'Progresar es pedir un poco más con el tiempo. Subir peso o repeticiones funciona para ganar músculo; recortar el descanso no es buena vía.',
    blocks: [
      { type: 'lead', text: 'Para seguir progresando, el entrenamiento tiene que ir pidiendo un poco más con el tiempo. Eso es la sobrecarga progresiva, y se puede aplicar de varias formas.' },
      { type: 'keypoints', items: [
        'Subir el peso o subir las repeticiones hacen crecer parecido.',
        'Recortar el descanso no es buena forma de progresar para ganar músculo.',
        'La progresión se mide en semanas, no en cada sesión.',
      ] },
      { type: 'heading', text: 'Qué es' },
      { type: 'paragraph', text: 'Cuando un estímulo deja de ser exigente, las adaptaciones se frenan. Progresar es aumentar poco a poco la exigencia: más peso, más repeticiones con el mismo peso o más series.' },
      { type: 'heading', text: 'Peso o repeticiones: las dos funcionan' },
      { type: 'paragraph', cite: 1, text: 'En un ensayo con 43 personas entrenadas durante 8 semanas, subir el peso o subir las repeticiones dio un crecimiento muscular parecido. Subir el peso dio algo más de fuerza máxima.' },
      { type: 'table',
        caption: 'Formas de progresar y qué esperar',
        columns: ['Forma de progresar', 'Para ganar músculo', 'Para fuerza máxima'],
        rows: [
          ['Subir el peso', 'Funciona', 'Algo mejor'],
          ['Subir repeticiones con el mismo peso', 'Funciona', 'Algo menos'],
          ['Añadir series', 'Funciona, con rendimientos decrecientes', 'Funciona, con rendimientos decrecientes'],
          ['Recortar el descanso', 'Peor: menos de 60 s se asoció a algo menos de hipertrofia', 'No estudiado en ese análisis'],
        ],
        note: 'Fuentes: Plotkin 2022, Pelland 2026, Singer 2024.' },
      { type: 'heading', text: '¿Y recortar el descanso?' },
      { type: 'paragraph', cite: 2, text: 'No es buena vía para ganar músculo. Descansar al menos 60 segundos entre series se asoció a algo más de hipertrofia que descansos más cortos.' },
      { type: 'heading', text: '¿Hace falta periodizar?' },
      { type: 'paragraph', cite: 3, text: 'Con el mismo volumen, organizar el entrenamiento por fases no mejora la ganancia de músculo. Sí aporta algo de fuerza máxima, y en personas entrenadas variar las cargas a lo largo de la semana (periodización ondulante) dio algo más de fuerza que la lineal.' },
      { type: 'heading', text: 'Cómo hacerlo: la doble progresión' },
      { type: 'image', diagram: 'doble-progresion', caption: 'Doble progresión: primero repeticiones, luego peso.', credit: 'Diagrama original · Atlas Method' },
      { type: 'callout', variant: 'tip', title: 'En la práctica', text: 'Trabaja en un rango de repeticiones (por ejemplo, 8–12). Cuando llegues arriba con buena técnica en todas las series, sube el peso lo mínimo posible. Si un día no puedes progresar, mantener también vale. Si tu objetivo es la fuerza máxima, da prioridad a subir el peso.' },
      { type: 'reference', n: 1, raw: 'Plotkin D, Coleman M, Van Every D, et al. (2022). Progressive overload without progressing load? The effects of load or repetition progression on muscular adaptations. PeerJ, 10, e14142.', doi: '10.7717/peerj.14142', ev: 'Ensayo controlado' },
      { type: 'reference', n: 2, raw: 'Singer A, Wolf M, Generoso L, et al. (2024). Give it a rest: a systematic review with Bayesian meta-analysis on the effect of inter-set rest interval duration on muscle hypertrophy. Frontiers in Sports and Active Living, 6, 1429789.', doi: '10.3389/fspor.2024.1429789', ev: 'Metaanálisis' },
      { type: 'reference', n: 3, raw: 'Moesgaard L, Beck MM, Christiansen L, Aagaard P, Lundbye-Jensen J. (2022). Effects of periodization on strength and muscle hypertrophy in volume-equated resistance training programs: a systematic review and meta-analysis. Sports Medicine, 52(7), 1647–1666.', doi: '10.1007/s40279-021-01636-1', ev: 'Metaanálisis' },
      { type: 'reference', n: 4, raw: 'Pelland JC, Remmert JF, Robinson ZP, et al. (2026). The resistance training dose-response: meta-regressions exploring the effects of weekly volume and frequency on muscle hypertrophy and strength gain. Sports Medicine, 56(2), 481–505.', doi: '10.1007/s40279-025-02344-w', ev: 'Metaanálisis' },
    ],
    doi: null, pmid: null, semanticScholarId: null,
    authors: [], journal: null, publishYear: null,
    evidenceLevel: 'meta-analysis',
    aiSummary: null,
    aiKeywords: ['sobrecarga progresiva', 'doble progresión', 'descanso', 'periodización', 'volumen'],
    aiGeneratedAt: null,
    coverImage: 'https://images.unsplash.com/photo-1689514226984-15f849652eaa?w=900&q=80&fit=crop',  // Alex Saks
    figures: [],
  },
  {
    id: 'rpe-rir',
    title: 'RPE y RIR',
    subtitle: 'Medir el esfuerzo de cada serie',
    category: 'fuerza', tags: ['intermedio', 'autorregulación'],
    status: 'published', readTime: 6, gems: 15,
    publishedAt: '2026-01-14T10:00:00Z', updatedAt: '2026-10-31T10:00:00Z',
    rejectionReason: null,
    summary: 'El RIR y el RPE ayudan a ajustar el esfuerzo de cada serie. Estimarlos tiene error, y acercarse al fallo importa más para el músculo que para la fuerza máxima.',
    blocks: [
      { type: 'lead', text: 'El RPE y el RIR sirven para medir lo duro que ha sido una serie y ajustar la carga a cómo llegas cada día.' },
      { type: 'keypoints', items: [
        'RIR = repeticiones que te quedaban. RPE 8 equivale a RIR 2.',
        'Solemos subestimar en torno a una repetición las que nos quedan; con práctica se afina.',
        'Para ganar músculo, acercarse al fallo suma algo; para la fuerza máxima pesa más la carga.',
      ] },
      { type: 'heading', text: 'RPE: esfuerzo percibido' },
      { type: 'paragraph', cite: 1, text: 'En fuerza se usa una escala del 1 al 10 basada en las repeticiones que te quedaban al terminar: RPE 10 significa que no podías hacer ni una más; RPE 8, que te quedaban dos.' },
      { type: 'heading', text: 'RIR: repeticiones en reserva' },
      { type: 'paragraph', text: 'El RIR es el número de repeticiones que podrías haber hecho de más con buena técnica. Es la misma información que el RPE, contada al revés, y a mucha gente le resulta más intuitivo.' },
      { type: 'table',
        caption: 'Equivalencias RPE ↔ RIR',
        columns: ['RPE', 'RIR', 'Qué significa'],
        rows: [
          ['10', '0', 'No podías hacer ni una más'],
          ['9', '1', 'Te quedaba una'],
          ['8', '2', 'Te quedaban dos'],
          ['7', '3', 'Te quedaban tres'],
          ['5–6', '4–6', 'Esfuerzo moderado'],
        ],
        note: 'Escala de Zourdos et al. (2016).' },
      { type: 'heading', text: '¿Somos precisos estimándolo?' },
      { type: 'paragraph', cite: 2, text: 'No del todo. De media, la gente subestima en torno a una repetición las que le quedan. Se acierta algo más cuanto más cerca del fallo y con cargas más pesadas, y con práctica se afina.' },
      { type: 'heading', text: '¿Cuánto acercarse al fallo?' },
      { type: 'paragraph', cite: 3, text: 'Para ganar músculo, terminar las series más cerca del fallo parece dar algo más de hipertrofia. Para la fuerza máxima, la cercanía al fallo importa poco; pesa más la carga que uses. Eso no significa llegar siempre al fallo: dejar 1–3 repeticiones en reserva es un buen punto de partida para la mayoría.' },
      { type: 'image', diagram: 'proximidad-fallo', caption: 'Dónde situar el esfuerzo de tus series.', credit: 'Diagrama original · Atlas Method' },
      { type: 'heading', text: 'Autorregulación' },
      { type: 'callout', variant: 'tip', title: 'En la práctica', text: 'Si un día llegas cansado, baja el peso para mantener el RIR objetivo en lugar de forzar el número del programa. Si te sobra, súbelo. Así el esfuerzo se adapta a tu estado real.' },
      { type: 'reference', n: 1, raw: 'Zourdos MC, Klemp A, Dolan C, et al. (2016). Novel resistance training-specific rating of perceived exertion scale measuring repetitions in reserve. Journal of Strength and Conditioning Research, 30(1), 267–275.', doi: '10.1519/JSC.0000000000001049', ev: 'Estudio de validación' },
      { type: 'reference', n: 2, raw: 'Halperin I, Malleron T, Har-Nir I, et al. (2022). Accuracy in predicting repetitions to task failure in resistance exercise: a scoping review and exploratory meta-analysis. Sports Medicine, 52(2), 377–390.', doi: '10.1007/s40279-021-01559-x', ev: 'Metaanálisis exploratorio' },
      { type: 'reference', n: 3, raw: 'Robinson ZP, Pelland JC, Remmert JF, et al. (2024). Exploring the dose-response relationship between estimated resistance training proximity to failure, strength gain, and muscle hypertrophy: a series of meta-regressions. Sports Medicine, 54(9), 2209–2231.', doi: '10.1007/s40279-024-02069-2', ev: 'Metarregresión' },
    ],
    doi: '10.1519/JSC.0000000000001049', pmid: null, semanticScholarId: null,
    authors: [], journal: null, publishYear: null,
    evidenceLevel: 'meta-analysis',
    aiSummary: null,
    aiKeywords: ['RPE', 'RIR', 'autorregulación', 'proximidad al fallo', 'esfuerzo'],
    aiGeneratedAt: null,
    coverImage: 'https://images.unsplash.com/photo-1761839258420-5c3e2f2e2a74?w=900&q=80&fit=crop',  // Land O'Lakes, Inc.
    figures: [],
  },
  {
    id: 'hipertrofia-mecanismos',
    title: 'Mecanismos de hipertrofia',
    subtitle: 'Por qué crece el músculo',
    category: 'hipertrofia', tags: ['intermedio', 'ciencia'],
    status: 'published', readTime: 7, gems: 15,
    publishedAt: '2026-01-20T10:00:00Z', updatedAt: '2026-10-31T10:00:00Z',
    rejectionReason: null,
    summary: 'El músculo crece sobre todo por la tensión mecánica. El daño y la bomba no son necesarios, y cargas ligeras y pesadas dan un crecimiento parecido si te acercas al fallo.',
    blocks: [
      { type: 'lead', text: 'El músculo crece sobre todo como respuesta a la tensión mecánica: la fuerza que soportan sus fibras cuando trabajan contra una resistencia exigente.' },
      { type: 'keypoints', items: [
        'La tensión mecánica es el estímulo principal para crecer.',
        'Las agujetas y la bomba no son necesarias para ganar músculo.',
        'Cargas ligeras y pesadas hacen crecer parecido si las series se acercan al fallo.',
      ] },
      { type: 'heading', text: 'La tensión mecánica, el estímulo principal' },
      { type: 'paragraph', cite: 1, text: 'Cuando una fibra soporta tensión, la célula lo detecta y activa una cadena de señales (entre ellas, la vía mTOR). El resultado: más síntesis de proteína, más capacidad para fabricarla y nuevos núcleos en la fibra. Es la explicación con más respaldo actual.' },
      { type: 'image', diagram: 'tension-cascada', caption: 'Cómo la tensión mecánica se convierte en crecimiento.', credit: 'Diagrama original · Atlas Method' },
      { type: 'heading', text: '¿Y la bomba y las agujetas?' },
      { type: 'paragraph', cite: [2, 3], text: 'Durante años se habló de tres mecanismos. Hoy sabemos que el daño muscular no es necesario para crecer: al principio, buena parte de la síntesis de proteína se dedica a reparar, no a crecer. El estrés metabólico acompaña a las series exigentes, pero no se ha demostrado que cause hipertrofia por sí solo.' },
      { type: 'table',
        caption: 'Lo que se creía y lo que sabemos hoy',
        columns: ['Idea', 'Antes', 'Hoy'],
        rows: [
          ['Tensión mecánica', 'Uno de tres mecanismos', 'El estímulo principal'],
          ['Daño muscular (agujetas)', 'Necesario para crecer', 'No es necesario; al principio la síntesis se dedica a reparar'],
          ['Estrés metabólico (bomba)', 'Hace crecer a través de hormonas', 'No se ha demostrado que cause hipertrofia por sí solo'],
          ['Carga', '70–85 % del 1RM para crecer', 'Ligeras y pesadas, parecido si te acercas al fallo'],
        ] },
      { type: 'heading', text: 'El peso no lo es todo' },
      { type: 'paragraph', cite: 4, text: 'Para ganar músculo, cargas ligeras y pesadas dan resultados parecidos si las series se acercan lo suficiente al fallo. Las cargas altas sí son mejores para ganar fuerza máxima.' },
      { type: 'callout', variant: 'tip', title: 'En la práctica', text: 'Usa rangos de repeticiones variados según el ejercicio y tus preferencias, termina las series a pocas repeticiones del fallo y no uses las agujetas ni la bomba como señal de progreso: lo que cuenta es subir peso o repeticiones con el tiempo.' },
      { type: 'callout', variant: 'warning', title: 'Lo que todavía no sabemos', text: 'Muchos de estos mecanismos se conocen por estudios en animales o con pocas personas. Cómo se traducen exactamente al gimnasio sigue en estudio.' },
      { type: 'reference', n: 1, raw: 'Roberts MD, McCarthy JJ, Hornberger TA, et al. (2023). Mechanisms of mechanical overload-induced skeletal muscle hypertrophy: current understanding and future directions. Physiological Reviews, 103(4), 2679–2757.', doi: '10.1152/physrev.00039.2022', ev: 'Revisión' },
      { type: 'reference', n: 2, raw: 'Damas F, Phillips SM, Libardi CA, et al. (2016). Resistance training-induced changes in integrated myofibrillar protein synthesis are related to hypertrophy only after attenuation of muscle damage. Journal of Physiology, 594(18), 5209–5222.', doi: '10.1113/JP272472', ev: 'Ensayo' },
      { type: 'reference', n: 3, raw: 'Wackerhage H, Schoenfeld BJ, Hamilton DL, Lehti M, Hulmi JJ. (2019). Stimuli and sensors that initiate skeletal muscle hypertrophy following resistance exercise. Journal of Applied Physiology, 126(1), 30–43.', url: 'https://pubmed.ncbi.nlm.nih.gov/30335577/', ev: 'Revisión' },
      { type: 'reference', n: 4, raw: 'Schoenfeld BJ, Grgic J, Ogborn D, Krieger JW. (2017). Strength and hypertrophy adaptations between low- vs. high-load resistance training: a systematic review and meta-analysis. Journal of Strength and Conditioning Research, 31(12), 3508–3523.', url: 'https://pubmed.ncbi.nlm.nih.gov/28834797/', ev: 'Metaanálisis' },
    ],
    doi: null, pmid: null, semanticScholarId: null,
    authors: [], journal: null, publishYear: null,
    evidenceLevel: 'review',
    aiSummary: null,
    aiKeywords: ['hipertrofia', 'tensión mecánica', 'mTOR', 'daño muscular', 'fallo'],
    aiGeneratedAt: null,
    coverImage: 'https://images.unsplash.com/photo-1659614871735-e133639e4b28?w=900&q=80&fit=crop',  // engin akyurt
    figures: [],
  },
  {
    // Retirado del Aula: contenía la afirmación desactualizada "2× supera a 1×",
    // que contradecía el artículo de frecuencia. Pendiente de reescritura; los
    // enlaces se redirigen a 'frecuencia-entrenamiento'. status:'draft' lo oculta
    // (ArticlesService.getAll solo devuelve 'published').
    id: 'volumen-frecuencia',
    title: 'Volumen y frecuencia',
    subtitle: 'Cuánto y cuántas veces entrenar',
    category: 'hipertrofia', tags: ['intermedio', 'programación'],
    status: 'draft', readTime: 7, gems: 15,
    publishedAt: '2026-02-01T10:00:00Z', updatedAt: '2026-02-01T10:00:00Z',
    rejectionReason: null,
    summary: 'El volumen semanal y la frecuencia de entrenamiento son las dos variables con mayor impacto en el desarrollo muscular a largo plazo.',
    blocks: [
      { type: 'lead', text: 'El volumen semanal y la frecuencia de entrenamiento son las dos variables con mayor impacto en el desarrollo muscular a largo plazo.' },
      { type: 'heading', text: 'MEV, MAV y MRV' },
      { type: 'paragraph', cite: 1, text: 'El Volumen Mínimo Efectivo (MEV) es el mínimo para mantener músculo. El Volumen de Máxima Adaptación (MAV) es el óptimo para crecer. El Volumen Máximo Recuperable (MRV) es el máximo tolerable antes de comprometer la recuperación. La progresión correcta es MEV → MAV → MRV → deload.' },
      { type: 'image', diagram: 'mev-mav-mrv', caption: 'Los tres umbrales de volumen semanal y la ventana de crecimiento entre MEV y MRV.', credit: 'Diagrama original · Atlas Method' },
      { type: 'list', items: [
        'MEV — mínimo para no perder músculo',
        'MAV — rango óptimo para crecer',
        'MRV — techo recuperable; superarlo acumula fatiga',
      ] },
      { type: 'heading', text: 'Frecuencia óptima' },
      { type: 'paragraph', cite: 2, text: 'Entrenar cada músculo 2 veces por semana supera a 1 vez con el mismo volumen total. Para intermedios y avanzados, 2–3 veces por semana permite mejor distribución del estímulo y mayor volumen semanal tolerable.' },
      { type: 'heading', text: 'Progresión de volumen' },
      { type: 'paragraph', text: 'Lo más efectivo es empezar en el MEV e incrementar series semana a semana hasta aproximarse al MRV, para luego realizar un deload y reiniciar el ciclo con un MAV superior al anterior, aprovechando la supercompensación.' },
      { type: 'callout', variant: 'key', title: 'Regla práctica', text: 'Empieza en el MEV, sube series cada semana hacia el MRV y haz deload. Reparte ese volumen en 2–3 sesiones por músculo.' },
      { type: 'reference', authors: ['Ralston GW', 'Kilgore L', 'Wyatt FB', 'Baker JS'], year: 2017, title: 'The effect of weekly set volume on strength gain: a meta-analysis', journal: 'Sports Medicine', doi: '10.1007/s40279-017-0762-7' },
      { type: 'reference', authors: ['Schoenfeld BJ', 'Ogborn D', 'Krieger JW'], year: 2016, title: 'Effects of resistance training frequency on measures of muscle hypertrophy: a systematic review and meta-analysis', journal: 'Sports Medicine', doi: '10.1007/s40279-016-0543-8' },
    ],
    sections: [
      { heading: 'MEV, MAV y MRV', body: 'El Volumen Mínimo Efectivo (MEV) es el mínimo para mantener músculo. El Volumen de Máxima Adaptación (MAV) es el óptimo para crecer. El Volumen Máximo Recuperable (MRV) es el máximo tolerable antes de comprometer la recuperación. La progresión correcta es MEV → MAV → MRV → deload.' },
      { heading: 'Frecuencia óptima', body: 'Entrenar cada músculo 2 veces por semana supera a 1 vez con el mismo volumen total. Para intermedios y avanzados, 2–3 veces por semana permite mejor distribución del estímulo y mayor volumen semanal tolerable.' },
      { heading: 'Progresión de volumen', body: 'Lo más efectivo es empezar en el MEV e incrementar series semana a semana hasta aproximarse al MRV, para luego realizar un deload y reiniciar el ciclo con un MAV superior al anterior, aprovechando la supercompensación.' },
    ],
    refs: ['Ralston GW et al. (2017). The effect of weekly set volume on strength gain. J Strength Cond Res.', 'Schoenfeld BJ et al. (2016). Effects of resistance training frequency on muscle hypertrophy. Sports Med.'],
    doi: null, pmid: null, semanticScholarId: null,
    authors: ['Grant W. Ralston', 'Lon Kilgore'], journal: 'Journal of Strength and Conditioning Research', publishYear: 2017,
    evidenceLevel: 'meta-analysis',
    aiSummary: 'MEV (mantenimiento) → MAV (crecimiento) → MRV (límite). 2× por músculo/semana > 1×. Empieza bajo y sube series cada semana hasta el deload.',
    aiKeywords: ['volumen', 'frecuencia', 'MEV', 'MAV', 'MRV', 'series semanales'],
    aiGeneratedAt: '2026-02-02T10:00:00Z',
    coverImage: null,
    figures: [],
  },
  {
    id: 'nutricion-proteina',
    title: 'Proteína: cuánta y cuándo',
    subtitle: 'Lo que importa de verdad',
    category: 'nutricion', tags: ['fundamental', 'nutrición'],
    status: 'published', readTime: 6, gems: 15,
    publishedAt: '2026-02-10T10:00:00Z', updatedAt: '2026-10-31T10:00:00Z',
    rejectionReason: null,
    summary: 'Unos 1,6 g de proteína por kg al día cubren a la mayoría de quienes entrenan fuerza. Pesa más el total diario que el reparto o el momento exacto.',
    blocks: [
      { type: 'lead', text: 'La proteína es la materia prima del músculo. La buena noticia: lo que más importa es fácil de controlar.' },
      { type: 'keypoints', items: [
        'Unos 1,6 g por kg de peso al día es una buena referencia.',
        'Pesa más el total del día que el momento exacto.',
        'No hay un máximo claro aprovechable por comida.',
      ] },
      { type: 'heading', text: 'Cuánta' },
      { type: 'paragraph', cite: 1, text: 'En personas que entrenan fuerza, un metaanálisis situó en torno a 1,6 g por kg de peso al día el punto a partir del cual no se observan más beneficios en músculo. Por la incertidumbre del dato, llegar hasta unos 2,2 g/kg puede tener sentido para algunas personas.' },
      { type: 'table',
        caption: 'Cuánta proteína al día según tu peso',
        columns: ['Peso corporal', '1,6 g/kg (referencia)', '2,2 g/kg (límite alto)'],
        rows: [
          ['60 kg', '96 g', '132 g'],
          ['70 kg', '112 g', '154 g'],
          ['80 kg', '128 g', '176 g'],
          ['90 kg', '144 g', '198 g'],
        ],
        note: 'Cálculo: peso × g/kg. Orientativo para adultos sanos que entrenan fuerza.' },
      { type: 'heading', text: 'Cuándo' },
      { type: 'paragraph', cite: 2, text: 'Lo que más pesa es el total del día. Cuando se iguala la proteína diaria, tomarla justo después de entrenar o unas horas más tarde apenas cambia los resultados.' },
      { type: 'heading', text: '¿Hay un máximo por comida?' },
      { type: 'paragraph', cite: 3, text: 'Se decía que el cuerpo solo aprovecha 20–30 g por toma. Un estudio de 2023 encontró que 100 g tras entrenar producen una respuesta mayor y más duradera que 25 g. Repartir la proteína en varias comidas sigue siendo una forma cómoda de llegar al total, pero no hace falta obsesionarse con un límite por toma.' },
      { type: 'table',
        caption: 'Mitos frecuentes y lo que dice la evidencia',
        columns: ['Se decía', 'Hoy sabemos'],
        rows: [
          ['Solo se aprovechan 20–30 g por comida', '100 g dieron una respuesta mayor y más larga que 25 g'],
          ['Hay que tomarla justo al acabar de entrenar', 'Pesa más el total del día que el momento'],
        ],
        note: 'Fuentes: Trommelen 2023, Schoenfeld 2013.' },
      { type: 'heading', text: 'Fuentes de proteína' },
      { type: 'paragraph', text: 'Las proteínas animales y la soja aportan todos los aminoácidos esenciales. En dietas vegetales, combina fuentes variadas.' },
      { type: 'callout', variant: 'tip', title: 'En la práctica', text: 'Usa 1,6 g por kg al día como referencia y repártela en las comidas que te encajen, sin contar gramos por toma.' },
      { type: 'callout', variant: 'warning', title: 'Cuándo consultar', text: 'Si tienes una patología, sigues una dieta especial o buscas un plan concreto, consulta con un dietista-nutricionista.' },
      { type: 'reference', n: 1, raw: 'Morton RW, Murphy KT, McKellar SR, et al. (2018). A systematic review, meta-analysis and meta-regression of the effect of protein supplementation on resistance training-induced gains in muscle mass and strength in healthy adults. British Journal of Sports Medicine, 52(6), 376–384.', doi: '10.1136/bjsports-2017-097608', ev: 'Metaanálisis' },
      { type: 'reference', n: 2, raw: 'Schoenfeld BJ, Aragon AA, Krieger JW. (2013). The effect of protein timing on muscle strength and hypertrophy: a meta-analysis. Journal of the International Society of Sports Nutrition, 10, 53.', doi: '10.1186/1550-2783-10-53', ev: 'Metaanálisis' },
      { type: 'reference', n: 3, raw: 'Trommelen J, van Lieshout GAA, Nyakayiru J, et al. (2023). The anabolic response to protein ingestion during recovery from exercise has no upper limit in magnitude and duration in vivo in humans. Cell Reports Medicine, 4(12), 101324.', doi: '10.1016/j.xcrm.2023.101324', ev: 'Ensayo' },
    ],
    doi: null, pmid: null, semanticScholarId: null,
    authors: [], journal: null, publishYear: null,
    evidenceLevel: 'meta-analysis',
    aiSummary: null,
    aiKeywords: ['proteína', 'cantidad diaria', 'timing', 'leucina', 'fuentes'],
    aiGeneratedAt: null,
    coverImage: 'https://images.unsplash.com/photo-1490645935967-10de6ba17061?w=900&q=80&fit=crop',  // Brooke Lark
    figures: [],
  },
  {
    id: 'recuperacion-sueno',
    title: 'Dormir: la parte del entrenamiento que no se ve',
    subtitle: 'Qué dice la evidencia sobre el sueño, el músculo y el rendimiento',
    category: 'recuperacion', tags: ['sueño', 'recuperación', 'rendimiento'],
    status: 'published', readTime: 7, gems: 15,
    publishedAt: '2026-02-18T10:00:00Z', updatedAt: '2026-10-27T10:00:00Z',
    rejectionReason: null,
    summary: 'Una mala noche apenas afecta a tu fuerza máxima, pero dormir poco de forma habitual juega en contra de tu progreso. Qué dice la evidencia y cómo aplicarlo.',
    blocks: [
      { type: 'lead', text: 'Entrenas una hora, pero la adaptación ocurre en las otras veintitrés. De todo lo que pasa fuera del gimnasio, el sueño es probablemente lo que más se subestima.' },

      { type: 'keypoints', items: [
        'Intenta dormir 7 horas o más, con horarios regulares.',
        'Una mala noche apenas afecta a la fuerza máxima; dormir poco de forma habitual sí juega en contra.',
        'Deja la cafeína unas 6 horas antes de acostarte.',
      ] },

      { type: 'heading', text: '¿Cuánto hay que dormir?' },
      { type: 'paragraph', text: 'La Academia Americana de Medicina del Sueño y la Sleep Research Society recomiendan 7 horas o más por noche a los adultos sanos. No fijan un máximo: dormir más de 9 horas puede ser adecuado en adultos jóvenes o cuando estás recuperando sueño atrasado. No hay una cifra mágica, pero por debajo de 7 horas de forma habitual empiezan los problemas.', cite: 1 },

      { type: 'heading', text: 'Qué le pasa al músculo después de una mala noche' },
      { type: 'paragraph', text: 'En un estudio con 13 adultos jóvenes, una noche entera sin dormir redujo un 18 % la síntesis de proteína muscular (el proceso con el que el músculo se repara y crece), subió un 21 % el cortisol y bajó un 24 % la testosterona al día siguiente.', cite: 2 },
      { type: 'paragraph', text: 'Es importante leer bien este dato: fue una noche completa sin dormir, con pocos participantes y medido durante un solo día. No significa que una mala noche arruine tu progreso. Lo que importa es el patrón: dormir poco de forma habitual sí juega en tu contra.' },

      { type: 'heading', text: 'Y al rendimiento' },
      { type: 'paragraph', text: 'Una revisión con 77 estudios encontró que perder sueño una noche empeora el rendimiento en todos los tipos de ejercicio analizados. Hay matices útiles:', cite: 3 },
      { type: 'list', items: [
        'La fuerza máxima apenas se resiente (alrededor de un 3 % menos). Las series largas y la resistencia muscular se ven más afectadas, aunque ese dato viene de pocos estudios.',
        'Cuantas más horas llevas despierto, peor rindes. Después de dormir mal, una sesión por la tarde suele salir peor que una por la mañana.',
        'Si vas a dormir menos, mejor acostarte más tarde que levantarte antes. Recortar el final de la noche afectó más al rendimiento que recortar el principio.',
      ] },

      { type: 'heading', text: '¿Entrenar por la noche quita el sueño?' },
      { type: 'paragraph', text: 'En general, no. Un metaanálisis de 23 estudios no encontró que entrenar por la tarde-noche empeore el sueño. La excepción: un entrenamiento intenso que acaba menos de una hora antes de acostarte retrasó unos 14 minutos el momento de dormirse. Con dejar alrededor de una hora de margen es suficiente.', cite: 4 },

      { type: 'heading', text: 'Cuidado con la cafeína de la tarde' },
      { type: 'paragraph', text: 'En un estudio, 400 mg de cafeína (unas 2 o 3 tazas de café) tomados 6 horas antes de acostarse redujeron el sueño en más de una hora. Además, los participantes no notaron que habían dormido peor. Si tomas café o pre-entreno para entrenar por la tarde, tenlo en cuenta. La sensibilidad a la cafeína varía mucho de una persona a otra.', cite: 5 },

      { type: 'heading', text: 'En la práctica' },
      { type: 'list', items: [
        'Intenta dormir 7 horas o más, con horarios parecidos cada día.',
        'Deja la cafeína unas 6 horas antes de acostarte.',
        'Si entrenas fuerte por la noche, intenta terminar al menos una hora antes de dormir.',
        'Como pauta general, si has dormido mal no hace falta saltarte el entreno: mantén los ejercicios principales y, si lo notas, haz menos series o deja más repeticiones en reserva.',
      ] },

      { type: 'heading', text: 'Lo que todavía no sabemos' },
      { type: 'paragraph', text: 'La mayoría de los estudios miden una sola noche de mal sueño, en adultos jóvenes y sanos y, sobre todo, en hombres. Sabemos menos sobre el efecto de dormir algo menos de lo necesario durante meses sobre la ganancia muscular a largo plazo, y la respuesta varía de una persona a otra. La dirección de la evidencia es clara; el tamaño exacto del efecto en tu caso, no tanto.' },

      { type: 'reference', raw: 'Watson, N. F. et al. (2015). Recommended Amount of Sleep for a Healthy Adult: A Joint Consensus Statement of the American Academy of Sleep Medicine and Sleep Research Society. Sleep, 38(6), 843–844.', doi: '10.5665/sleep.4716', ev: 'Consenso' },
      { type: 'reference', raw: 'Lamon, S. et al. (2021). The effect of acute sleep deprivation on skeletal muscle protein synthesis and the hormonal environment. Physiological Reports, 9(1), e14660.', doi: '10.14814/phy2.14660', ev: 'Estudio' },
      { type: 'reference', raw: 'Craven, J. et al. (2022). Effects of Acute Sleep Loss on Physical Performance: A Systematic and Meta-Analytical Review. Sports Medicine, 52(11), 2669–2690.', doi: '10.1007/s40279-022-01706-y', ev: 'Metaanálisis' },
      { type: 'reference', raw: 'Stutz, J., Eiholzer, R. y Spengler, C. M. (2019). Effects of Evening Exercise on Sleep in Healthy Participants: A Systematic Review and Meta-Analysis. Sports Medicine, 49(2), 269–287.', doi: '10.1007/s40279-018-1015-0', ev: 'Metaanálisis' },
      { type: 'reference', raw: 'Drake, C. et al. (2013). Caffeine effects on sleep taken 0, 3, or 6 hours before going to bed. Journal of Clinical Sleep Medicine, 9(11), 1195–1200.', doi: '10.5664/jcsm.3170', ev: 'Estudio' },
    ],
    doi: null, pmid: null, semanticScholarId: null,
    authors: [], journal: null, publishYear: 2022,
    evidenceLevel: 'review',
    aiSummary: null,
    aiKeywords: ['sueño', 'descanso', 'recuperación', 'rendimiento', 'cafeína', 'testosterona', 'cortisol'],
    aiGeneratedAt: null,
    coverImage: 'https://images.unsplash.com/photo-1429117237875-aa29229d99f0?w=900&q=80&fit=crop',  // Quin Stevenson
    figures: [],
  },
  {
    id: 'deload',
    title: 'Deload: cuándo y cómo',
    subtitle: 'Bajar un poco para seguir subiendo',
    category: 'recuperacion', tags: ['intermedio', 'programación'],
    status: 'published', readTime: 5, gems: 15,
    publishedAt: '2026-03-01T10:00:00Z', updatedAt: '2026-10-31T10:00:00Z',
    rejectionReason: null,
    summary: 'La descarga es una práctica muy extendida pero poco estudiada. No hay una frecuencia demostrada; si buscas fuerza, mejor bajar la exigencia que parar del todo.',
    blocks: [
      { type: 'lead', text: 'Una descarga es un periodo corto en el que bajas la exigencia del entrenamiento para reducir la fatiga y llegar en mejores condiciones a la siguiente fase.' },
      { type: 'keypoints', items: [
        'Es muy habitual, pero apenas hay estudios.',
        'No hay una frecuencia demostrada: guíate por señales o planifícala tras un bloque duro.',
        'Si buscas fuerza, bajar la exigencia parece mejor que dejar de entrenar.',
      ] },
      { type: 'heading', text: 'Qué dice la evidencia' },
      { type: 'paragraph', cite: 1, text: 'Es una práctica muy extendida, pero apenas estudiada. Un consenso internacional de entrenadores e investigadores (2023) la define como una reducción planificada o según sensaciones de la carga de entrenamiento, pensada para disipar la fatiga y preparar el siguiente bloque.' },
      { type: 'image', diagram: 'descarga-bloques', caption: 'La descarga, entre dos bloques de trabajo.', credit: 'Diagrama original · Atlas Method' },
      { type: 'heading', text: 'El primer ensayo controlado (2024)' },
      { type: 'paragraph', cite: 2, text: '39 personas entrenadas siguieron 9 semanas de entrenamiento de alto volumen; la mitad dejó de entrenar fuerza una semana a mitad del programa. Esto sugiere que, si buscas fuerza, puede ser preferible una descarga activa (entrenar con menos exigencia) a dejar de entrenar del todo.' },
      { type: 'table',
        caption: 'Parar una semana frente a seguir entrenando (Coleman 2024)',
        columns: ['Resultado', 'Con una semana sin entrenar fuerza'],
        rows: [
          ['Crecimiento muscular', 'Igual'],
          ['Fuerza de piernas', 'Algo menor'],
          ['Resistencia local y salto', 'Sin diferencias'],
        ] },
      { type: 'heading', text: 'Cuándo' },
      { type: 'paragraph', text: 'No hay una frecuencia demostrada. También puedes planificarla al final de un bloque exigente.' },
      { type: 'paragraph', text: 'Señales prácticas para valorarla:' },
      { type: 'list', items: [
        'El rendimiento se estanca o baja varias sesiones seguidas.',
        'Las mismas cargas se sienten más duras.',
        'Duermes peor o tienes menos ganas de entrenar.',
      ] },
      { type: 'callout', variant: 'tip', title: 'Cómo hacerla', text: 'Reduce claramente el número de series, deja más repeticiones en reserva y mantén los mismos ejercicios para no perder la técnica.' },
      { type: 'callout', variant: 'warning', title: 'Lo que todavía no sabemos', text: 'Solo hay un ensayo controlado, de 9 semanas y en personas jóvenes entrenadas. No sabemos todavía cuál es la mejor frecuencia ni el mejor tipo de descarga.' },
      { type: 'reference', n: 1, raw: 'Bell L, Strafford BW, Coleman M, Androulakis Korakakis P, Nolan D. (2023). Integrating deloading into strength and physique sports training programmes: an international Delphi consensus approach. Sports Medicine – Open.', doi: '10.1186/s40798-023-00633-0', ev: 'Consenso' },
      { type: 'reference', n: 2, raw: 'Coleman M, Burke R, Augustin F, et al. (2024). Gaining more from doing less? The effects of a one-week deload period during supervised resistance training on muscular adaptations. PeerJ, 12, e16777.', doi: '10.7717/peerj.16777', ev: 'Ensayo controlado' },
    ],
    doi: null, pmid: null, semanticScholarId: null,
    authors: [], journal: null, publishYear: null,
    evidenceLevel: 'review',
    aiSummary: null,
    aiKeywords: ['deload', 'descarga', 'fatiga', 'fuerza', 'volumen'],
    aiGeneratedAt: null,
    coverImage: 'https://images.unsplash.com/photo-1600026453194-11ae289732b8?w=900&q=80&fit=crop',  // Michael DeMoya
    figures: [],
  },
  {
    id: 'hrv-monitoreo',
    title: 'HRV como herramienta de recuperación',
    subtitle: 'Útil para conocerte, no un semáforo',
    category: 'recuperacion', tags: ['avanzado', 'tecnología'],
    status: 'published', readTime: 5, gems: 15,
    publishedAt: '2026-03-10T10:00:00Z', updatedAt: '2026-10-31T10:00:00Z',
    rejectionReason: null,
    summary: 'La HRV refleja en parte tu estado de recuperación, pero entrenar guiándose por ella apenas mejora los resultados frente a un plan fijo. Úsala como tendencia, junto a tus sensaciones.',
    blocks: [
      { type: 'lead', text: 'La variabilidad de la frecuencia cardiaca (HRV) se ha popularizado con los relojes y anillos inteligentes. Te explicamos qué mide y cuánto puedes fiarte de ella.' },
      { type: 'keypoints', items: [
        'La HRV baja con la fatiga, pero también con el estrés, el alcohol o un mal sueño.',
        'Guiarse por la HRV apenas mejoró los resultados frente a un plan fijo.',
        'Mira la tendencia de varios días, no el dato de un día.',
      ] },
      { type: 'heading', text: 'Qué mide' },
      { type: 'paragraph', text: 'La HRV es la variación del tiempo entre latidos. Refleja en parte el estado del sistema nervioso autónomo y suele bajar con estrés, mal sueño, enfermedad o fatiga, pero también con alcohol o simplemente por medirla en condiciones distintas.' },
      { type: 'heading', text: 'Qué dice la evidencia' },
      { type: 'paragraph', cite: 1, text: 'Un metaanálisis de 8 estudios (199 personas) comparó entrenar según la HRV con seguir un plan fijo. Las diferencias en VO2máx y en rendimiento de resistencia fueron pequeñas y no significativas. Casi toda la evidencia es de deportes de resistencia; en entrenamiento de fuerza hay muy poca.' },
      { type: 'heading', text: 'Cómo usarla si la mides' },
      { type: 'paragraph', cite: 2, text: 'Mídela siempre en las mismas condiciones, por ejemplo al despertar. Mira la tendencia de varios días frente a tu valor habitual, no el dato de un solo día, y combínala con cómo te sientes y cómo rindes.' },
      { type: 'image', diagram: 'hrv-tendencia', caption: 'El dato diario varía mucho; la tendencia es lo que cuenta.', credit: 'Diagrama original · Atlas Method' },
      { type: 'table',
        caption: 'Cómo combinar HRV y sensaciones',
        columns: ['', 'Te encuentras bien', 'Rindes peor o duermes mal'],
        rows: [
          ['HRV en tu rango habitual', 'Sigue el plan', 'Valora bajar la intensidad'],
          ['HRV baja varios días', 'Sigue el plan y vigila', 'Baja la intensidad'],
        ],
        note: 'Pauta práctica, no un protocolo validado en estudios.' },
      { type: 'callout', variant: 'tip', title: 'En la práctica', text: 'La HRV es una herramienta para conocerte, no un semáforo. Si solo baja el número y te encuentras bien, no hace falta cambiar el plan.' },
      { type: 'reference', n: 1, raw: 'Manresa-Rocamora A, Sarabia JM, Javaloyes A, Flatt AA, Moya-Ramón M. (2021). Heart rate variability-guided training for enhancing cardiac-vagal modulation, aerobic fitness, and endurance performance: a methodological systematic review with meta-analysis. International Journal of Environmental Research and Public Health, 18(19), 10299.', doi: '10.3390/ijerph181910299', ev: 'Metaanálisis' },
      { type: 'reference', n: 2, raw: 'Plews DJ, Laursen PB, Kilding AE, Buchheit M. (2012). Heart rate variability in elite triathletes, is variation in variability the key to effective training? A case comparison. European Journal of Applied Physiology, 112(11), 3729–3741.', url: 'https://pubmed.ncbi.nlm.nih.gov/22367011/', ev: 'Estudio de casos' },
    ],
    doi: null, pmid: null, semanticScholarId: null,
    authors: [], journal: null, publishYear: null,
    evidenceLevel: 'meta-analysis',
    aiSummary: null,
    aiKeywords: ['HRV', 'recuperación', 'tendencia', 'autorregulación', 'sistema nervioso autónomo'],
    aiGeneratedAt: null,
    coverImage: 'https://images.unsplash.com/photo-1600784694429-aafecca51fab?w=900&q=80&fit=crop',  // Luismi Sánchez
    figures: [],
  },
  // ─── Draft article — only visible in admin ────────────────────────────────
  {
    id: 'periodizacion-bloques',
    title: 'Periodización por bloques',
    subtitle: 'Estructurar el año de entrenamiento',
    category: 'fuerza', tags: ['avanzado', 'programación'],
    status: 'reviewing', readTime: 12, gems: 15,
    publishedAt: null, updatedAt: '2026-04-20T14:00:00Z',
    rejectionReason: null,
    summary: 'La periodización por bloques organiza el entrenamiento en fases concentradas (acumulación, transmutación, realización) para maximizar las adaptaciones específicas en cada período.',
    sections: [
      { heading: 'Bloques de acumulación', body: 'Alto volumen, intensidad moderada (65–75% 1RM). El objetivo es desarrollar la base aeróbica, muscular y técnica para los bloques posteriores. Duración típica: 3–4 semanas.' },
      { heading: 'Bloques de transmutación', body: 'Volumen moderado, intensidad alta (80–90% 1RM). Se transforma la capacidad construida en fuerza específica. Duración: 2–3 semanas.' },
      { heading: 'Bloques de realización', body: 'Bajo volumen, intensidad máxima (90–100% 1RM). Pico de rendimiento para competición o test. Duración: 1–2 semanas, siempre seguidas de deload.' },
    ],
    refs: ['Issurin VB (2010). New horizons for the methodology and physiology of training periodization. Sports Med, 40(3).'],
    doi: '10.2165/11319770-000000000-00000', pmid: '20121287', semanticScholarId: null,
    authors: ['Vladimir B. Issurin'], journal: 'Sports Medicine', publishYear: 2010,
    evidenceLevel: 'review',
    aiSummary: null, aiKeywords: [], aiGeneratedAt: null,
    coverImage: null, figures: [],
  },
];

// ─── In-memory store (localStorage-backed) ───────────────────────────────────
// Adding a new article = adding an entry to SEED. On load we merge any SEED
// article whose id isn't already stored, so new monthly content appears without
// wiping user reading state (which lives in the main store, not here).
//
// SEED_VERSION lets us also *refresh* existing seed articles when their content
// changes (e.g. improved references). On a version bump we replace seed-origin
// articles with the latest SEED and keep any user-created ones. Bump this
// whenever SEED content changes. Reading progress is unaffected.
const SEED_VERSION = '2026-10-31';
const SEED_VER_KEY = 'atlas.articles.seedver';
let _articles = (function () {
  let stored = null;
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (raw) stored = JSON.parse(raw);
  } catch (e) {}
  if (!Array.isArray(stored) || !stored.length) {
    try { localStorage.setItem(SEED_VER_KEY, SEED_VERSION); } catch (e) {}
    return SEED.map(a => ({ ...a }));
  }
  let seedVer = null;
  try { seedVer = localStorage.getItem(SEED_VER_KEY); } catch (e) {}
  const seedIds = new Set(SEED.map(a => a.id));
  if (seedVer !== SEED_VERSION) {
    // Content update: take fresh SEED, preserve user-created (non-seed) articles.
    const userCreated = stored.filter(a => !seedIds.has(a.id));
    const merged = [...SEED.map(a => ({ ...a })), ...userCreated];
    try {
      localStorage.setItem(STORAGE_KEY, JSON.stringify(merged));
      localStorage.setItem(SEED_VER_KEY, SEED_VERSION);
    } catch (e) {}
    return merged;
  }
  const ids = new Set(stored.map(a => a.id));
  const additions = SEED.filter(a => !ids.has(a.id)).map(a => ({ ...a }));
  return additions.length ? [...stored, ...additions] : stored;
})();

function _persist() {
  try { localStorage.setItem(STORAGE_KEY, JSON.stringify(_articles)); } catch (e) {}
}

const _delay = (ms = 60) => new Promise(r => setTimeout(r, ms));

// ─── Admin token (dev only — replace with real JWT from Supabase Auth) ────────
let _adminToken = null;
try { _adminToken = sessionStorage.getItem(ADMIN_KEY); } catch (e) {}

// ─── Public API ───────────────────────────────────────────────────────────────
// TODO: When adding Supabase, wrap each method body with:
//   const { data, error } = await supabase.from('articles').select(...)
// TODO: When adding Firebase, wrap with:
//   const snap = await getDocs(query(collection(db,'articles'), where(...)))

const ArticlesService = {

  // ── Auth (dev stub) ─────────────────────────────────────────────────────────
  login(password) {
    // TODO: Replace with supabase.auth.signInWithPassword({ email, password })
    if (password === 'atlas2026') {
      _adminToken = 'dev-token';
      try { sessionStorage.setItem(ADMIN_KEY, _adminToken); } catch (e) {}
      return true;
    }
    return false;
  },
  logout() {
    _adminToken = null;
    try { sessionStorage.removeItem(ADMIN_KEY); } catch (e) {}
  },
  isAdmin() { return !!_adminToken; },

  // ── Read ─────────────────────────────────────────────────────────────────────
  async getAll({ status = 'published', category = 'all' } = {}) {
    // TODO: fetch('/api/articles?status=' + status + '&category=' + category)
    await _delay();
    return _articles.filter(a =>
      (status === 'all' || a.status === status) &&
      (category === 'all' || a.category === category)
    ).sort((a, b) => (b.publishedAt || '').localeCompare(a.publishedAt || ''));
  },

  async getById(id) {
    // TODO: fetch('/api/articles/' + id)
    await _delay();
    return _articles.find(a => a.id === id) || null;
  },

  // Synchronous read of the in-memory catalogue. Used where a component needs to
  // resolve an article (e.g. a title, or whether it exists) during render without
  // awaiting — e.g. the Coach's "Leer en Aula" chips, which must only ever link
  // to real published articles.
  getAllSync({ status = 'published', category = 'all' } = {}) {
    return _articles.filter(a =>
      (status === 'all' || a.status === status) &&
      (category === 'all' || a.category === category)
    );
  },
  getByIdSync(id) { return _articles.find(a => a.id === id) || null; },

  // Normalize an article's body to the block model. Returns article.blocks when
  // present; otherwise derives blocks from the legacy sections/figures/refs so
  // old articles render through the same rich reader with no content loss.
  getBlocks(article) {
    if (!article) return [];
    if (Array.isArray(article.blocks) && article.blocks.length) return article.blocks;
    const out = [];
    for (const s of (article.sections || [])) {
      if (s.heading) out.push({ type: 'heading', text: s.heading });
      if (s.body)    out.push({ type: 'paragraph', text: s.body });
    }
    for (const f of (article.figures || [])) {
      out.push({ type: 'image', src: f.url || null, caption: f.caption });
    }
    (article.refs || []).forEach((raw, i) => {
      out.push(i === 0
        ? { type: 'reference', raw, authors: article.authors, year: article.publishYear, journal: article.journal, doi: article.doi }
        : { type: 'reference', raw });
    });
    return out;
  },

  // The ordered list of reference blocks (for the numbered bibliography and for
  // resolving a paragraph's inline `cite` numbers).
  getReferences(article) {
    return this.getBlocks(article).filter(b => b.type === 'reference');
  },

  // "Nuevo" tag window: an article counts as new for its first 2 weeks.
  NEW_WINDOW_DAYS: 14,
  isNew(article) {
    if (!article || !article.publishedAt) return false;
    const t = Date.parse(article.publishedAt);
    if (isNaN(t)) return false;
    return (Date.now() - t) < this.NEW_WINDOW_DAYS * 86400000;
  },

  async search(query) {
    // TODO: supabase.from('articles').textSearch('fts', query)
    await _delay(30);
    const q = query.toLowerCase();
    return _articles.filter(a =>
      a.status === 'published' && (
        a.title.toLowerCase().includes(q) ||
        a.subtitle.toLowerCase().includes(q) ||
        a.summary.toLowerCase().includes(q) ||
        a.tags.some(t => t.toLowerCase().includes(q)) ||
        (a.aiKeywords || []).some(k => k.toLowerCase().includes(q))
      )
    );
  },

  // ── Admin: write ─────────────────────────────────────────────────────────────
  async submit(article) {
    // TODO: POST /api/articles  (requires auth header)
    if (!ArticlesService.isAdmin()) throw new Error('Not authorized');
    await _delay();
    const newArticle = {
      ...article,
      id: article.id || article.title.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''),
      status: 'reviewing',
      publishedAt: null,
      updatedAt: new Date().toISOString(),
      aiSummary: null, aiKeywords: [], aiGeneratedAt: null,
    };
    _articles = [newArticle, ..._articles];
    _persist();
    return newArticle;
  },

  async update(id, patch) {
    // TODO: PATCH /api/articles/:id
    if (!ArticlesService.isAdmin()) throw new Error('Not authorized');
    await _delay();
    _articles = _articles.map(a => a.id === id ? { ...a, ...patch, updatedAt: new Date().toISOString() } : a);
    _persist();
  },

  async approve(id) {
    // TODO: PATCH /api/articles/:id/publish
    if (!ArticlesService.isAdmin()) throw new Error('Not authorized');
    await _delay();
    _articles = _articles.map(a =>
      a.id === id ? { ...a, status: 'published', publishedAt: new Date().toISOString(), updatedAt: new Date().toISOString(), rejectionReason: null } : a
    );
    _persist();
  },

  async reject(id, reason) {
    // TODO: PATCH /api/articles/:id/reject  { reason }
    if (!ArticlesService.isAdmin()) throw new Error('Not authorized');
    await _delay();
    _articles = _articles.map(a =>
      a.id === id ? { ...a, status: 'rejected', rejectionReason: reason, updatedAt: new Date().toISOString() } : a
    );
    _persist();
  },

  async delete(id) {
    // TODO: DELETE /api/articles/:id
    if (!ArticlesService.isAdmin()) throw new Error('Not authorized');
    await _delay();
    _articles = _articles.filter(a => a.id !== id);
    _persist();
  },

  // ── PubMed import (stub — replace with real fetch) ───────────────────────────
  async importFromPubMed(pmid) {
    // TODO: Replace mock with real API call:
    // const res = await fetch(`https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id=${pmid}&retmode=json`)
    // const data = await res.json()
    // Map PubMed fields → Atlas article schema
    await _delay(800);
    return {
      id: '', title: `Artículo PubMed ${pmid}`,
      subtitle: 'Importado desde PubMed — editar antes de publicar',
      category: 'fuerza', tags: [], status: 'draft',
      readTime: 8, gems: 15,
      summary: 'Resumen pendiente de redacción.',
      sections: [{ heading: 'Resumen del estudio', body: 'Por completar.' }],
      refs: [`PMID: ${pmid}`],
      doi: null, pmid, semanticScholarId: null,
      authors: [], journal: null, publishYear: null,
      evidenceLevel: 'review',
      aiSummary: null, aiKeywords: [], aiGeneratedAt: null,
      coverImage: null, figures: [],
    };
  },

  // ── Semantic Scholar import (stub) ───────────────────────────────────────────
  async importFromSemanticScholar(doi) {
    // TODO: const res = await fetch(`https://api.semanticscholar.org/graph/v1/paper/${encodeURIComponent(doi)}?fields=title,authors,year,venue,abstract`)
    await _delay(800);
    return { id: '', title: `Paper DOI: ${doi}`, subtitle: 'Importado — completar campos', category: 'fuerza', tags: [], status: 'draft', readTime: 8, gems: 15, summary: 'Resumen pendiente.', sections: [], refs: [`DOI: ${doi}`], doi, pmid: null, semanticScholarId: null, authors: [], journal: null, publishYear: null, evidenceLevel: 'review', aiSummary: null, aiKeywords: [], aiGeneratedAt: null, coverImage: null, figures: [] };
  },

  // ── AI summary generation (stub — replace with Claude API call) ───────────────
  async generateAISummary(id) {
    // TODO: POST /api/ai/summarize  { articleId }
    // Backend calls: anthropic.messages.create({ model: 'claude-opus-4-7', messages: [{ role: 'user', content: `Summarize in 2 sentences for an athlete: ${article.sections.map(s=>s.body).join(' ')}` }] })
    await _delay(1200);
    const article = _articles.find(a => a.id === id);
    if (!article) throw new Error('Article not found');
    const mockSummaries = {
      'sobrecarga-progresiva': 'Aumenta el estímulo cada semana: más peso, más reps o más series. Sin progresión, no hay adaptación.',
      'rpe-rir': 'RPE 8 = RIR 2. Autorregula la carga según cómo llegas ese día, no solo según el número del programa.',
    };
    const summary = mockSummaries[id] || `Resumen IA generado: ${article.title} — ${article.summary.slice(0, 80)}...`;
    _articles = _articles.map(a =>
      a.id === id ? { ...a, aiSummary: summary, aiGeneratedAt: new Date().toISOString() } : a
    );
    _persist();
    return summary;
  },

  // ── Image upload (stub — replace with Supabase Storage) ──────────────────────
  async uploadCoverImage(id, file) {
    // TODO: const { data } = await supabase.storage.from('article-images').upload(`covers/${id}`, file)
    // const url = supabase.storage.from('article-images').getPublicUrl(`covers/${id}`).data.publicUrl
    await _delay(600);
    const url = URL.createObjectURL(file);
    _articles = _articles.map(a => a.id === id ? { ...a, coverImage: url } : a);
    _persist();
    return url;
  },

  // ── Reset to seed data (dev utility) ─────────────────────────────────────────
  reset() {
    _articles = SEED.map(a => ({ ...a }));
    _persist();
  },
};

// Expose globally
Object.assign(window, { ArticlesService });
