// ── ARCHIVE + ARTICLE PAGES ─────────────────────────────────

// Simulated full archive (uses milestones + filler editions).
const FILLER_EDITIONS = (() => {
  const seasons = ["winter","spring","summer","autumn"];
  const phases = [
    { phase:"A", from: 1,  to: 25 },
    { phase:"B", from: 26, to: 50 },
    { phase:"C", from: 51, to: 75 },
    { phase:"D", from: 76, to: 99 },
    { phase:"E", from: 100, to: (window.WS_CURRENT && window.WS_CURRENT.num || 191) },
  ];
  const editors = ["markus","alex","victor","marian"];
  const titlesEN = ["The morning routine that didn't","One sentence at the breakfast table","On boredom","The screen vs. the cousin","What I tell other parents","The night the wifi went out","Why we kept a paper journal","The smaller, the better","Quiet anger","Saturday rules","On being copied","The tantrum that taught me"];
  const titlesES = ["La rutina matutina que no","Una frase en el desayuno","Sobre el aburrimiento","La pantalla vs. el primo","Lo que digo a otros padres","La noche que se cayó el WiFi","Por qué llevamos diario","Cuanto más pequeño, mejor","Rabia silenciosa","Reglas del sábado","Sobre ser copiado","La rabieta que me enseñó"];
  const items = [];
  for (let n = 1; n <= (window.WS_CURRENT && window.WS_CURRENT.num || 191); n++) {
    const phase = phases.find(p => n >= p.from && n <= p.to).phase;
    items.push({
      num: n, phase,
      editor: editors[n % 4],
      season: seasons[Math.floor(((n - 1) / 13)) % 4],
      title: { en: titlesEN[n % titlesEN.length], es: titlesES[n % titlesES.length] },
      excerpt: { en: "A short letter from the editor's kitchen — small, honest, repeatable.",
                 es: "Una carta corta desde la cocina del editor — pequeña, honesta, repetible." },
      tier: n % 10 === 0 ? "free" : (n > 5 ? "freemium" : "free"),
      isMilestone: false,
    });
  }
  // overlay milestones
  WS_MILESTONES.forEach(m => {
    const idx = items.findIndex(x => x.num === m.num);
    if (idx >= 0) items[idx] = { ...items[idx], title: m.title, excerpt: m.excerpt, isMilestone: true, badge: m.badge };
  });
  // overlay REAL newsletters (full editions we have parsed content for)
  // overlay ALL editions — real titles + slugs from API (data-editions-api.jsx)
  (window.WS_ALL_EDITIONS || []).forEach(api => {
    const idx = items.findIndex(x => x.num === api.num);
    if (idx < 0) return;
    const it = items[idx];
    items[idx] = { ...it,
      title:   { en: api.title.en || it.title.en, es: api.title.es || it.title.es },
      editor:  api.editor || it.editor,
      slug_en: api.slug_en,
      slug_es: api.slug_es,
    };
  });
  (window.WS_NEWSLETTERS || []).forEach(n => {
    const idx = items.findIndex(x => x.num === n.num);
    const patch = {
      title: n.title,
      excerpt: n.subtitle && (n.subtitle.en || n.subtitle.es) ? n.subtitle : (items[idx]?.excerpt),
      editor: n.editor,
      isMilestone: n.isMilestone || items[idx]?.isMilestone,
      tier: n.isFree ? "free" : "freemium",
      hasFullContent: true,
    };
    if (idx >= 0) items[idx] = { ...items[idx], ...patch };
  });
  // overlay FULL editions (rich short/long reader with per-edition layouts)
  (window.WS_EDITIONS_FULL ? Object.values(window.WS_EDITIONS_FULL) : []).forEach(ed => {
    const idx = items.findIndex(x => x.num === ed.num);
    if (idx < 0) return;
    items[idx] = { ...items[idx],
      title: ed.title,
      excerpt: ed.subtitle || items[idx].excerpt,
      editor: (ed.editor && ed.editor.name) ? ed.editor.name.toLowerCase() : items[idx].editor,
      isMilestone: ed.milestone || items[idx].isMilestone,
      tier: ed.milestone ? "free" : "freemium",
      hasFullContent: true, fullReader: true,
    };
  });
  // overlay CURRENT edition — correct editor from data.jsx (filler cycles wrong)
  if (window.WS_CURRENT) {
    const idx = items.findIndex(x => x.num === window.WS_CURRENT.num);
    if (idx >= 0) items[idx] = { ...items[idx],
      editor: window.WS_CURRENT.editor || items[idx].editor,
    };
  }
  return items;
})();
window.WS_ARCHIVE = FILLER_EDITIONS;

function Archive({ theme, dark, lang, isMember, nav }) {
  const [phase, setPhase] = useState("all");
  const [editor, setEditor] = useState("all");
  const [layout, setLayout] = useState("grid");
  const [query, setQuery] = useState("");
  const [season, setSeason] = useState("all");

  const phases = [
    { id:"all", label: lang==="en"?"All":"Todas", range: `1–${(window.WS_CURRENT && window.WS_CURRENT.num || 191)}` },
    { id:"A",   label: lang==="en"?"Phase A · Essays":"Fase A · Ensayos", range:"1–25" },
    { id:"B",   label: lang==="en"?"Phase B · + Activity":"Fase B · + Actividad", range:"26–50" },
    { id:"C",   label: lang==="en"?"Phase C · + Audio":"Fase C · + Audio", range:"51–75" },
    { id:"D",   label: lang==="en"?"Phase D · + Recipes":"Fase D · + Recetas", range:"76–99" },
    { id:"E",   label: lang==="en"?"Phase E · Full":"Fase E · Completa", range:`100–${(window.WS_CURRENT && window.WS_CURRENT.num || 191)}` },
  ];

  const list = WS_ARCHIVE.filter(x =>
    (phase === "all" || x.phase === phase) &&
    (editor === "all" || (x.editor || '').toLowerCase() === editor.toLowerCase()) &&
    (season === "all" || x.season === season) &&
    (!query || (x.title.en+x.title.es).toLowerCase().includes(query.toLowerCase()))
  ).sort((a,b) => b.num - a.num);

  return (
    <div style={{ background: theme.bg, color: theme.text, paddingTop:"5rem" }}>
      {/* HEADER */}
      <div style={{
        background: dark ? theme.panel : "#0E2318",
        color:"#F0EBE0", padding:"4rem clamp(1.5rem, 5vw, 5vw) 3rem",
      }}>
        <div className="wrap">
          <Eyebrow theme={{ sage:"#9DC872" }} color="#9DC872">{lang==="en"?`Edition archive · ${(window.WS_CURRENT && window.WS_CURRENT.num || 191)} · two languages`:`Archivo · ${(window.WS_CURRENT && window.WS_CURRENT.num || 191)} · dos idiomas`}</Eyebrow>
          <h1 className="serif" style={{
            fontStyle:"italic", fontWeight:300, fontSize:"clamp(2.2rem, 5vw, 4rem)",
            color:"#F0EBE0", lineHeight: 1.02, marginTop:".75rem", marginBottom:"1rem", maxWidth: 900,
          }}>{lang==="en"
            ? <>Three years of <em>small, honest letters</em> — searchable, filterable.</>
            : <>Tres años de <em>cartas pequeñas y honestas</em> — buscables, filtrables.</>}</h1>
          <div style={{ display:"flex", gap: "2rem", flexWrap:"wrap", marginTop:"1.5rem" }}>
            {[
              [String((window.WS_CURRENT && window.WS_CURRENT.num || 191)), lang==="en"?"editions":"ediciones"],
              ["4", lang==="en"?"editors":"editores"],
              ["49", lang==="en"?"audiobooks":"audiolibros"],
              ["322", lang==="en"?"canonical files · EN+ES":"archivos · EN+ES"],
            ].map(([n,l]) => (
              <div key={l}>
                <div className="serif" style={{ fontSize:"2.2rem", color:"#F0EBE0", fontWeight: 300, lineHeight: 1 }}>{n}</div>
                <div className="label-tiny" style={{ color:"#9DC872", marginTop: 4 }}>{l}</div>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* FILTER BAR */}
      <div style={{
        background: dark ? theme.bg2 : theme.bg2,
        borderBottom: `1px solid ${theme.border}`,
        padding:"1.25rem clamp(1.5rem, 5vw, 5vw)",
        position:"sticky", top: 0, zIndex: 5,
        backdropFilter:"blur(14px)", WebkitBackdropFilter:"blur(14px)",
      }}>
        <div className="wrap" style={{ display:"flex", flexDirection:"column", gap:".9rem" }}>
          {/* phase strip */}
          <div style={{ display:"flex", gap: 6, flexWrap:"wrap", alignItems:"center" }}>
            <span className="label-tiny" style={{ color: theme.text3, marginRight: 6 }}>{lang==="en"?"Format phases":"Fases"}</span>
            {phases.map(p => (
              <button key={p.id} onClick={() => setPhase(p.id)} style={{
                padding:"6px 12px", borderRadius: 18,
                background: phase === p.id ? theme.sage : theme.sage3,
                color: phase === p.id ? (dark?"#050F07":"#fff") : theme.text2,
                border:`1px solid ${phase === p.id ? theme.sage : theme.border2}`,
                fontSize:".72rem", cursor:"pointer", display:"flex", alignItems:"center", gap: 6,
              }}>
                <span>{p.label}</span>
                <span className="mono" style={{ opacity: .6, fontSize:".62rem" }}>{p.range}</span>
              </button>
            ))}
          </div>

          {/* season / tag filter */}
          <div style={{ display:"flex", gap: 6, flexWrap:"wrap", alignItems:"center" }}>
            <span className="label-tiny" style={{ color: theme.text3, marginRight: 6 }}>{lang==="en"?"Season":"Temporada"}</span>
            {[
              {id:"all",    en:"All seasons",  es:"Todas"},
              {id:"spring", en:"Spring 🌱",    es:"Primavera 🌱"},
              {id:"summer", en:"Summer ☀",     es:"Verano ☀"},
              {id:"autumn", en:"Autumn 🍂",    es:"Otoño 🍂"},
              {id:"winter", en:"Winter ❄",    es:"Invierno ❄"},
            ].map(s => (
              <button key={s.id} onClick={() => setSeason(s.id)} style={{
                padding:"5px 12px", borderRadius: 18,
                background: season === s.id ? theme.sage : "transparent",
                color: season === s.id ? (dark?"#050F07":"#fff") : theme.text2,
                border:`1px solid ${season === s.id ? theme.sage : theme.border2}`,
                fontSize:".72rem", cursor:"pointer",
              }}>{s[lang]}</button>
            ))}
          </div>
          {/* editor + search + layout */}
          <div style={{ display:"flex", gap:"1rem", flexWrap:"wrap", alignItems:"center" }}>
            <div style={{ display:"flex", gap: 6, alignItems:"center" }}>
              <span className="label-tiny" style={{ color: theme.text3, marginRight: 6 }}>{lang==="en"?"Editor":"Editor"}</span>
              <button onClick={() => setEditor("all")} style={{
                padding:"5px 12px", borderRadius: 16,
                background: editor === "all" ? theme.sage : "transparent",
                color: editor === "all" ? (dark?"#050F07":"#fff") : theme.text2,
                border:`1px solid ${editor === "all" ? theme.sage : theme.border2}`,
                fontSize:".72rem", cursor:"pointer",
              }}>{lang==="en"?"All":"Todos"}</button>
              {WS_EDITORS.map(e => (
                <button key={e.id} onClick={() => setEditor(e.id)} style={{
                  padding:"5px 12px", borderRadius: 16,
                  background: editor === e.id ? `${e.color}30` : "transparent",
                  border:`1px solid ${editor === e.id ? e.color : theme.border2}`,
                  color: editor === e.id ? e.color : theme.text2,
                  fontSize:".72rem", cursor:"pointer",
                  display:"flex", alignItems:"center", gap: 6,
                }}>
                  <span style={{ width: 8, height: 8, borderRadius:"50%", background: e.color, display:"inline-block" }}/>
                  {e.name}
                </button>
              ))}
            </div>

            <div style={{ flex: 1, minWidth: 180 }}>
              <input value={query} onChange={e => setQuery(e.target.value)}
                placeholder={lang==="en"?`Search ${(window.WS_CURRENT && window.WS_CURRENT.num || 191)} editions…`:`Buscar ${(window.WS_CURRENT && window.WS_CURRENT.num || 191)} ediciones…`}
                style={{
                  width:"100%", padding:"8px 14px",
                  background: theme.inputBg, border:`1px solid ${theme.inputBd}`,
                  borderRadius: 18, color: theme.text, fontSize:".82rem", outline:"none",
                }}/>
            </div>

            <div style={{ display:"flex", gap: 4, padding: 3, background: theme.sage3, borderRadius: 16, border:`1px solid ${theme.border}` }}>
              {["grid","list"].map(v => (
                <button key={v} onClick={() => setLayout(v)} style={{
                  padding:"5px 10px", borderRadius: 14,
                  background: layout === v ? theme.sage : "transparent",
                  color: layout === v ? (dark?"#050F07":"#fff") : theme.text2,
                  border:"none", fontSize:".7rem", cursor:"pointer",
                }}>{v}</button>
              ))}
            </div>
          </div>
        </div>
      </div>

      {/* RESULTS */}
      <div className="section" style={{ padding:"3rem clamp(1.5rem, 5vw, 5vw)" }}>
        <div className="wrap">
          <div style={{ fontSize:".82rem", color: theme.text3, marginBottom:"1.25rem" }}>
            {list.length} {lang==="en"?"results":"resultados"}
          </div>

          {layout === "grid" ? (
            <div className="grid-4" style={{ gap: ".75rem" }}>
              {list.slice(0, 60).map(e => <ArchiveCard key={e.num} e={e} theme={theme} dark={dark} lang={lang} nav={nav} isMember={isMember}/>)}
            </div>
          ) : (
            <div style={{
              background: dark ? theme.panel : "#fff",
              border: `1px solid ${theme.border}`, borderRadius: 6, overflow:"hidden",
            }}>
              {list.slice(0, 100).map((e, i) => <ArchiveRow key={e.num} e={e} i={i} last={i === Math.min(99, list.length - 1)} theme={theme} dark={dark} lang={lang} nav={nav} isMember={isMember}/>)}
            </div>
          )}

          {list.length > 60 && layout === "grid" && (
            <div style={{ marginTop:"2rem", textAlign:"center" }}>
              <button style={{
                background:"transparent", color: theme.sage,
                border: `1px solid ${theme.border2}`, padding:"10px 22px", borderRadius: 22,
                fontSize:".82rem", cursor:"pointer",
              }}>{lang==="en"?`Load ${list.length - 60} more →`:`Cargar ${list.length - 60} más →`}</button>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function ArchiveCard({ e, theme, dark, lang, nav, isMember }) {
  const ed = WS_EDITORS.find(x => x.id === (e.editor || '').toLowerCase()) || WS_EDITORS[0];
  const isLocked = e.tier === "freemium" && !isMember;
  const _goToEdition = () => {
    const slug = lang === 'en' ? e.slug_en : e.slug_es;
    if (slug) { window.location.href = '/' + lang + '/' + slug + '/'; return; }
    nav(e.fullReader ? 'edition' : 'article', { num: e.num });
  };
  return (
    <button onClick={_goToEdition} style={{
      background: dark ? theme.panel : "#fff",
      border: `1px solid ${e.isMilestone ? `${theme.gold}55` : theme.border}`,
      borderRadius: 6, padding:"1.1rem 1.1rem 1rem",
      display:"flex", flexDirection:"column", gap:".7rem",
      cursor:"pointer", textAlign:"left", color:"inherit", font:"inherit",
      position:"relative", minHeight: 200,
    }}>
      {e.isMilestone && (
        <span style={{
          position:"absolute", top: 8, right: 8,
          fontSize:".56rem", padding:"3px 8px", borderRadius: 10,
          background: theme.gold2, color: theme.gold, letterSpacing:".14em", textTransform:"uppercase",
        }}>★</span>
      )}
      <div style={{ display:"flex", justifyContent:"space-between", alignItems:"baseline" }}>
        <span className="serif" style={{ fontSize:"1.6rem", color: theme.sage, fontWeight: 300 }}>#{e.num}</span>
        <span className="mono" style={{ fontSize:".62rem", color: theme.text3 }}>{e.phase}</span>
      </div>
      {e.hasFullContent && (
        <span style={{
          alignSelf:"flex-start", fontSize:".56rem", padding:"2px 7px", borderRadius: 8,
          background: theme.sage3, color: theme.sage, border:`1px solid ${theme.border2}`,
          letterSpacing:".12em", textTransform:"uppercase",
        }}>{lang==="en"?"Full edition":"Edición completa"}</span>
      )}
      <h3 className="serif italic" style={{ fontWeight: 400, fontSize:"1rem", color: theme.text, lineHeight: 1.2, flex: 1 }}>
        {e.title[lang]}
      </h3>
      <div style={{ display:"flex", justifyContent:"space-between", alignItems:"center", paddingTop:".5rem", borderTop:`1px solid ${theme.divider}` }}>
        <span style={{ display:"flex", alignItems:"center", gap: 6 }}>
          <span style={{ width: 8, height: 8, borderRadius:"50%", background: ed.color, display:"inline-block" }}/>
          <span style={{ fontSize:".7rem", color: theme.text2 }}>{ed.name}</span>
        </span>
        <span style={{ fontSize:".68rem", color: isLocked ? theme.gold : theme.text3 }}>
          {isLocked ? "🔒" : "→"}
        </span>
      </div>
    </button>
  );
}

function ArchiveRow({ e, i, last, theme, dark, lang, nav, isMember }) {
  const ed = WS_EDITORS.find(x => x.id === (e.editor || '').toLowerCase()) || WS_EDITORS[0];
  const isLocked = e.tier === "freemium" && !isMember;
  const _goToEdition = () => {
    const slug = lang === 'en' ? e.slug_en : e.slug_es;
    if (slug) { window.location.href = '/' + lang + '/' + slug + '/'; return; }
    nav(e.fullReader ? 'edition' : 'article', { num: e.num });
  };
  return (
    <button onClick={_goToEdition} style={{
      width:"100%", background:"transparent", border:"none",
      padding:".95rem 1.25rem", display:"grid",
      gridTemplateColumns:"56px 1fr 140px 80px 30px", gap:"1rem", alignItems:"center",
      cursor:"pointer", textAlign:"left", color:"inherit", font:"inherit",
      borderBottom: last ? "none" : `1px solid ${theme.divider}`,
    }}>
      <span className="serif" style={{ fontSize:"1.15rem", color: theme.sage, fontWeight: 300 }}>
        #{e.num}{e.isMilestone && <span style={{ color: theme.gold }}> ★</span>}
      </span>
      <span style={{ fontSize:".92rem", color: theme.text, fontFamily:"'Cormorant Garamond',serif", fontStyle:"italic" }}>
        {e.title[lang]}
      </span>
      <span style={{ display:"flex", alignItems:"center", gap: 6 }}>
        <span style={{ width: 8, height: 8, borderRadius:"50%", background: ed.color, display:"inline-block" }}/>
        <span style={{ fontSize:".78rem", color: theme.text2 }}>{ed.name}</span>
      </span>
      <span className="mono" style={{ fontSize:".68rem", color: theme.text3 }}>{e.phase} · {e.season}</span>
      <span style={{ color: isLocked ? theme.gold : theme.text3, fontSize:".82rem" }}>
        {isLocked ? "🔒" : "→"}
      </span>
    </button>
  );
}

// ─── ARTICLE PAGE ─────────────────────────────────────────
function Article({ theme, dark, lang, isMember, pageData, nav, setIsMember }) {
  const num = pageData?.num || (window.WS_CURRENT && window.WS_CURRENT.num || 191);
  // Prefer a real parsed newsletter; fall back to the archive stub.
  const real = (window.WS_NEWSLETTERS || []).find(n => n.num === num);
  const stub = WS_ARCHIVE.find(e => e.num === num) || WS_ARCHIVE[0];
  const editorId = (real ? real.editor : stub.editor);
  const editor = WS_EDITORS.find(e => e.id === (editorId || '').toLowerCase()) || WS_EDITORS[0];

  // Block definitions in canonical order.
  const BLOCK_DEFS = [
    { key:"opening",           name:{en:"Opening",es:"Apertura"} },
    { key:"story",             name:{en:"Story",es:"Historia"} },
    { key:"reflection",        name:{en:"Reflection",es:"Reflexión"} },
    { key:"practical_insight", name:{en:"Practical insight",es:"Idea práctica"} },
    { key:"activity",          name:{en:"Activity",es:"Actividad"} },
    { key:"resources",         name:{en:"Resources",es:"Recursos"} },
    { key:"closing",           name:{en:"Closing",es:"Cierre"} },
  ];

  const title    = real ? real.title    : stub.title;
  const subtitle = real ? real.subtitle : null;
  const phase    = real ? real.phase    : stub.phase;
  const isMilestone = real ? real.isMilestone : stub.isMilestone;
  const dateLabel = real ? (real.date[lang] || real.date.en) : (stub.season ? `${stub.season} · ed.${num}` : `ed.${num}`);

  // Which blocks are free vs premium for THIS edition (from source data).
  const freemiumSet = new Set(real ? real.freemiumBlocks : ["opening","story","reflection","practical_insight"]);

  // Build the renderable block list: only blocks that actually have content.
  const blockText = (key) => {
    if (real) {
      const b = real.blocks[key];
      return (b && (b[lang] || b.en || "")) || "";
    }
    // stub fallback content
    const fb = {
      opening:   { en:"There was a moment last week I almost missed. The kind that's gone before you've finished noticing it.", es:"Hubo un momento la semana pasada que casi me perdí. De los que se van antes de que termines de notarlos." },
      story:     { en:"We were in the kitchen. The pasta was overcooked. My oldest was explaining a meme I'd never see. None of it was special. All of it was.", es:"Estábamos en la cocina. La pasta pasada. Mi mayor explicaba un meme que nunca veré. Nada era especial. Todo lo era." },
      reflection:{ en:"Three years of doing this and what I keep coming back to is the same idea: presence isn't a state, it's a posture.", es:"Tres años haciendo esto y lo que sigue volviendo es la misma idea: presencia no es un estado, es una postura." },
      practical_insight:{ en:"This week's small ask: leave the phone in another room during dinner. As an experiment. See if anything changes by Friday.", es:"Pedido pequeño esta semana: deja el móvil en otra habitación durante la cena. Como experimento. Mira si algo cambia para el viernes." },
      activity:  { en:"This Week · No Plan. No Agenda. A simple offline activity. Nothing on the calendar after school. See what they invent.", es:"Esta semana · Sin plan. Sin agenda. Una actividad sin pantallas. Nada en la agenda. Mira lo que inventan." },
      resources: { en:"", es:"" },
      closing:   { en:"That's what I take from this week. Less than you'd think. Enough to put on the table.", es:"Eso me llevo esta semana. Menos de lo que esperarías. Suficiente para poner en la mesa." },
    };
    return (fb[key] && (fb[key][lang] || fb[key].en)) || "";
  };

  const renderBlocks = BLOCK_DEFS
    .map((d, i) => ({ ...d, idx: i, text: blockText(d.key), isFree: freemiumSet.has(d.key) }))
    .filter(b => b.text || !b.isFree); // keep premium blocks even if empty (to show lock), drop empty free ones

  const freeCount = renderBlocks.filter(b => b.isFree).length;
  const totalCount = renderBlocks.length;
  // index of the first premium block — where we draw the WiseTip+ divider
  const firstPremiumIdx = renderBlocks.findIndex(b => !b.isFree);

  return (
    <div style={{ background: theme.bg, color: theme.text, paddingTop:"5rem" }}>
      {/* HEADER */}
      <div style={{
        background: dark ? theme.panel : "#0E2318",
        color:"#F0EBE0", padding:"4rem clamp(1.5rem, 5vw, 5vw) 4rem",
      }}>
        <div className="wrap-sm">
          <button onClick={() => nav("archive")} style={{
            background:"none", border:"none", color:"#9DC872", cursor:"pointer",
            fontSize:".78rem", marginBottom:"1.75rem", letterSpacing:".06em",
          }}>← {lang==="en"?"Archive":"Archivo"}</button>

          <div style={{ display:"flex", gap: 8, marginBottom:"1.5rem", flexWrap:"wrap" }}>
            <Pill color="#9DC872" bd="#9DC87266">#{num}</Pill>
            <Pill color="#C8A85A" bd="#C8A85A66">{phase}</Pill>
            {isMilestone && <Pill color="#C8A85A" bd="#C8A85A66">★ {lang==="en"?"Milestone":"Hito"}</Pill>}
            {real && <Pill color="#9DC872" bd="#9DC87266">{lang==="en"?"Full edition":"Edición completa"}</Pill>}
          </div>

          <h1 className="serif" style={{
            fontStyle:"italic", fontWeight:300, fontSize:"clamp(2rem, 5vw, 3.8rem)",
            color:"#F0EBE0", lineHeight: 1.08, letterSpacing:"-.01em", marginBottom:"1.25rem",
          }}>{title[lang] || title.en}</h1>

          {subtitle && (subtitle[lang] || subtitle.en) && (
            <p style={{ color:"rgba(240,235,224,.55)", fontSize:"1.1rem", lineHeight: 1.7, fontWeight: 300, marginBottom:"2rem", maxWidth: 620 }}>
              {subtitle[lang] || subtitle.en}
            </p>
          )}

          <div style={{
            display:"flex", alignItems:"center", gap: 14, paddingTop:"1.25rem",
            borderTop:"1px solid rgba(255,255,255,.08)",
          }}>
            <div style={{
              width: 44, height: 44, borderRadius:"50%",
              background: `${editor.color}28`, border:`1.5px solid ${editor.color}66`,
              display:"flex", alignItems:"center", justifyContent:"center",
              fontFamily:"'Cormorant Garamond',serif", fontSize:"1.3rem", color: editor.color,
            }}>{editor.name[0]}</div>
            <div>
              <div style={{ fontSize:".92rem", color:"#F0EBE0", fontWeight: 500 }}>{editor.name}</div>
              <div style={{ fontSize:".74rem", color:"rgba(240,235,224,.4)" }}>
                {editor.location[lang]} · {dateLabel}
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* BODY */}
      <div style={{ padding:"3.5rem clamp(1.5rem, 5vw, 5vw)" }}>
        <div className="wrap-sm">
          {/* TIER BANNER — clear signal of which version is being shown */}
          <div style={{
            marginBottom:"2.5rem", padding:"14px 18px",
            background: isMember ? `${theme.sage}15` : theme.gold2,
            border: `1px solid ${isMember ? theme.border2 : theme.lockedBd}`,
            borderRadius: 6, display:"flex", justifyContent:"space-between", alignItems:"center", gap:"1rem", flexWrap:"wrap",
          }}>
            <div>
              <div className="label-tiny" style={{ color: isMember ? theme.sage : theme.gold, marginBottom: 2 }}>
                {isMember
                  ? (lang==="en"?"WiseTip+ · full edition":"WiseTip+ · edición completa")
                  : (lang==="en"?"Free reader · freemium version":"Lectura libre · versión freemium")}
              </div>
              <div style={{ fontSize:".84rem", color: theme.text2, fontWeight: 300 }}>
                {isMember
                  ? (lang==="en"?`Reading all ${totalCount} blocks of this edition.`:`Leyendo los ${totalCount} bloques de esta edición.`)
                  : (lang==="en"?`Reading ${freeCount} of ${totalCount} blocks. The rest is WiseTip+.`:`Leyendo ${freeCount} de ${totalCount} bloques. El resto es WiseTip+.`)}
              </div>
            </div>
            <div style={{ display:"flex", gap: 6 }}>
              {!isMember && setIsMember && (
                <button onClick={() => setIsMember(true)} style={{
                  background:"transparent", color: theme.gold, border:`1px solid ${theme.gold}66`,
                  padding:"6px 12px", borderRadius: 16, fontSize:".74rem", cursor:"pointer",
                }}>{lang==="en"?"Preview as WiseTip+":"Vista como WiseTip+"}</button>
              )}
              <button onClick={() => nav("membership")} style={{
                background: isMember ? "transparent" : theme.sage, color: isMember ? theme.sage : (dark?"#050F07":"#fff"),
                border: isMember ? `1px solid ${theme.border2}` : "none",
                padding:"6px 14px", borderRadius: 16, fontSize:".76rem", fontWeight: 600, cursor:"pointer",
              }}>{isMember ? (lang==="en"?"Manage":"Gestionar") : (lang==="en"?"See plans":"Ver planes")} →</button>
            </div>
          </div>

          {/* BLOCKS — data-driven, gated per edition */}
          {renderBlocks.map((b, i) => {
            const numLabel = String(b.idx + 1).padStart(2, "0");
            const showDivider = i === firstPremiumIdx && firstPremiumIdx > 0;
            const locked = !b.isFree && !isMember;
            const isOpening = b.key === "opening";
            return (
              <React.Fragment key={b.key}>
                {showDivider && (
                  <div style={{ margin:"3rem 0 2rem", display:"flex", alignItems:"center", gap: 14 }}>
                    <span style={{ flex: 1, height: 1, background: theme.divider }}/>
                    <span className="label-tiny" style={{ color: theme.gold }}>
                      {lang==="en"?"WiseTip+ continues below":"WiseTip+ continúa abajo"}
                    </span>
                    <span style={{ flex: 1, height: 1, background: theme.divider }}/>
                  </div>
                )}
                <ArticleBlock theme={theme} dark={dark} num={numLabel} name={b.name[lang]} tier={b.isFree ? "free" : "premium"}>
                  {locked ? (
                    <LockedBlock theme={theme} label={`${b.name[lang]} · WiseTip+`} onUnlock={() => nav("membership")}/>
                  ) : isOpening ? (
                    <p className="serif italic" style={{ fontSize:"1.25rem", lineHeight: 1.75, fontWeight: 300, color: dark?"#E8DED0":theme.text, whiteSpace:"pre-line" }}>
                      {b.text}
                    </p>
                  ) : b.key === "closing" ? (
                    <p className="serif italic" style={{
                      fontSize:"1.15rem", lineHeight: 1.7, fontWeight: 300, color: dark?"#E8DED0":theme.text,
                      borderLeft: `3px solid ${theme.sage}`, paddingLeft:"1.25rem", whiteSpace:"pre-line",
                    }}>{b.text}</p>
                  ) : (
                    <p style={{ fontSize:"1.05rem", lineHeight: 1.85, fontWeight: 300, color: theme.text2, whiteSpace:"pre-line" }}>
                      {b.text}
                    </p>
                  )}
                </ArticleBlock>
              </React.Fragment>
            );
          })}

          {/* DISCLAIMER */}
          <div style={{
            marginTop:"3rem", padding:"1.25rem 1.5rem",
            background: theme.sage3, border:`1px dashed ${theme.border2}`, borderRadius: 6,
            fontSize:".82rem", color: theme.text3, lineHeight: 1.65,
          }}>
            {real ? (real.disclaimer[lang] || real.disclaimer.en) : (lang==="en"
              ? "Names of people and brands in these editions are changed. Whoever was there and reads this knows what we're talking about."
              : "Los nombres de personas y marcas están cambiados. Quien estuvo allí y lo lee sabe de qué hablamos.")}
          </div>

          {/* DOWNSTREAM CTA */}
          <div style={{
            marginTop:"3rem", display:"grid", gridTemplateColumns:"1fr 1fr", gap:".75rem",
          }} className="grid-2">
            <button onClick={() => nav("audiobooks")} style={{
              background: theme.sage3, border:`1px solid ${theme.border}`, borderRadius: 6,
              padding:"1rem 1.25rem", textAlign:"left", cursor:"pointer",
            }}>
              <div className="label-tiny" style={{ color: theme.sage, marginBottom: 4 }}>{lang==="en"?"Listen instead":"Escucha mejor"}</div>
              <div style={{ fontSize:".88rem", color: theme.text, fontFamily:"'Cormorant Garamond',serif", fontStyle:"italic" }}>
                {lang==="en"?"Hear this edition narrated →":"Escucha esta edición narrada →"}
              </div>
            </button>
            <button onClick={() => nav("tailor")} style={{
              background: theme.sage3, border:`1px solid ${theme.border}`, borderRadius: 6,
              padding:"1rem 1.25rem", textAlign:"left", cursor:"pointer",
            }}>
              <div className="label-tiny" style={{ color: theme.gold, marginBottom: 4 }}>{lang==="en"?"Make it personal":"Hazla personal"}</div>
              <div style={{ fontSize:".88rem", color: theme.text, fontFamily:"'Cormorant Garamond',serif", fontStyle:"italic" }}>
                {lang==="en"?"Turn it into your child's audiobook →":"Convierte en audiolibro de tu hijo →"}
              </div>
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

function ArticleBlock({ theme, dark, num, name, tier, children }) {
  return (
    <div style={{ display:"grid", gridTemplateColumns:"110px 1fr", gap:"1.5rem", marginBottom:"2rem" }} className="article-block">
      <div>
        <div className="mono" style={{ fontSize:".68rem", color: theme.text3 }}>{num}</div>
        <div className="label-tiny" style={{ marginTop: 4, color: tier === "premium" ? theme.gold : theme.sage }}>{name}</div>
        <div style={{ fontSize:".64rem", marginTop: 4, color: theme.text4, letterSpacing:".05em" }}>
          {tier === "premium" ? "WiseTip+" : "Free"}
        </div>
      </div>
      <div>{children}</div>
      <style>{`
        @media (max-width: 700px) {
          .article-block { grid-template-columns: 1fr !important; gap: .5rem !important; }
        }
      `}</style>
    </div>
  );
}

Object.assign(window, { Archive, Article });
