// ── FULL EDITION · freemium teaser  ↔  WiseTip+ full article ──
// Edition #161 · "Earth Day 2026: the mint is still alive" · Markus, Barcelona
//
// Two readings of the SAME edition, switchable in-page:
//   • FREEMIUM  — the touch-point. Short version of 4 of 7 blocks. A taste
//                 that earns the subscribe click, then a paywall.
//   • WISETIP+  — the full article. Long, expanded version of all 7 of 7
//                 blocks, including the 3 members-only blocks.
// Every free block therefore has {short, long}: freemium shows short,
// premium shows long. Editorial hard-constraints respected throughout:
// children never named; wife's quote verbatim; Victor = Vienna; disclaimer
// verbatim; scene-first, short paragraphs.

const { useState: useFE } = React;

const FE_EDITION = {
  num: 161,
  phase: "E",
  editor: { name: "Markus", location: { en: "Barcelona, Spain", es: "Barcelona, España" }, color: "#4CB868" },
  coEditors: [
    { name: "Markus", city: { en: "Barcelona", es: "Barcelona" }, color: "#4CB868" },
    { name: "Victor", city: { en: "Vienna",    es: "Viena" },     color: "#3A5FA5" },
    { name: "Marian", city: { en: "London",    es: "Londres" },   color: "#7A4A8A" },
    { name: "Alex",   city: { en: "New York",  es: "Nueva York" },color: "#C45A3A" },
  ],
  date: { en: "April 8, 2026", es: "8 de abril de 2026" },
  readFree: { en: "1 min taste", es: "1 min de muestra" },
  readFull: { en: "9 min full read", es: "9 min lectura completa" },
  title: {
    en: "Earth Day 2026: the mint is still alive",
    es: "Día de la Tierra 2026: la hierbabuena sigue viva",
  },
  subtitle: {
    en: "The same question I've asked for four years — and one small plant that answered it.",
    es: "La misma pregunta que llevo cuatro años haciéndome — y una planta pequeña que la respondió.",
  },
  // ── the four shared blocks: short = freemium teaser, long = premium ──
  blocks: {
    opening: {
      short: {
        en: "This week I asked myself the same question I've asked for four years: what do I want my children to remember from these months?\n\nNot the achievements. The moments with the texture of having been real.",
        es: "Esta semana me hice la misma pregunta que llevo cuatro años haciéndome: ¿qué quiero que mis hijos recuerden de estos meses?\n\nNo los logros. Los momentos que tienen la textura de haber sido reales.",
      },
      long: {
        en: "This week I asked myself the same question I've asked for four years: what do I want my children to remember from these months?\n\nNot the achievements. Not the report cards, not the swimming badges, not the birthday that took three weeks to plan.\n\nThe moments with the texture of having been real. The ones nobody photographed because nobody thought to.\n\nI keep a short list. It's never the things I would have guessed in advance. This year the list has a plant on it — and I want to tell you why, because I think the reason is the whole point of this newsletter.",
        es: "Esta semana me hice la misma pregunta que llevo cuatro años haciéndome: ¿qué quiero que mis hijos recuerden de estos meses?\n\nNo los logros. No las notas, ni las medallas de natación, ni el cumpleaños que tardó tres semanas en organizarse.\n\nLos momentos que tienen la textura de haber sido reales. Los que nadie fotografió porque a nadie se le ocurrió.\n\nLlevo una lista corta. Nunca son las cosas que habría adivinado de antemano. Este año la lista tiene una planta — y quiero contarte por qué, porque creo que la razón es el sentido entero de esta newsletter.",
      },
    },
    story: {
      short: {
        en: "On the balcony there's a pot of mint we'd almost given up on. In January it was three brown stalks. I told the five-year-old it was probably finished.\n\nHe kept watering it anyway. Last Saturday there were green shoots.",
        es: "En el balcón hay una maceta de hierbabuena que casi dimos por perdida. En enero eran tres tallos marrones. Le dije al de cinco años que seguramente estaba muerta.\n\nÉl siguió regándola igual. El sábado pasado había brotes verdes.",
      },
      long: {
        en: "On the balcony there's a pot of mint we'd almost given up on. In January it was three brown stalks and a crust of dry soil. I told the five-year-old it was probably finished.\n\nHe kept watering it anyway. Not every day. When he remembered. A splash from his own cup, most of the water landing on the tiles.\n\nSome weeks he forgot entirely. I didn't remind him — I wanted to see what he'd do on his own, without me managing it.\n\nThen a cold snap in February, and I was sure that was that. He watered it the next morning regardless, standing in his socks on the freezing balcony.\n\nLast Saturday there were green shoots. Small ones, close to the soil, easy to miss.\n\nHe didn't say \u201cI told you so\u201d — he doesn't know that phrase yet. He just crouched down and looked at it for a long time, the way you look at something you helped without meaning to.\n\nThen he asked if we could put it in the salad. I said not yet. He accepted that with a patience he does not usually have for anything else.",
        es: "En el balcón hay una maceta de hierbabuena que casi dimos por perdida. En enero eran tres tallos marrones y una costra de tierra seca. Le dije al de cinco años que seguramente estaba muerta.\n\nÉl siguió regándola igual. No cada día. Cuando se acordaba. Un chorro de su propio vaso, casi toda el agua en las baldosas.\n\nAlgunas semanas se olvidó del todo. No se lo recordé — quería ver qué hacía por su cuenta, sin que yo lo gestionara.\n\nLuego una ola de frío en febrero, y di por hecho que ahí acababa. A la mañana siguiente la regó igual, de pie en calcetines en el balcón helado.\n\nEl sábado pasado había brotes verdes. Pequeños, pegados a la tierra, fáciles de no ver.\n\nNo dijo «te lo dije» — todavía no conoce esa frase. Solo se agachó y la miró un buen rato, como se mira algo que ayudaste sin querer.\n\nLuego preguntó si podíamos ponerla en la ensalada. Le dije que aún no. Lo aceptó con una paciencia que no suele tener para ninguna otra cosa.",
      },
    },
    reflection: {
      short: {
        en: "What's already there this month: conversations at the table, the stone they found in the park, the afternoon everything went wrong and then we laughed.\n\nNone of it planned. All of it counted.",
        es: "Lo que ya está ahí este mes: conversaciones en la mesa, la piedra que encontraron en el parque, la tarde en que todo salió mal y luego nos reímos.\n\nNada planeado. Todo contó.",
      },
      long: {
        en: "What's already there this month, without me arranging any of it: conversations at the table that ran long, the stone they found in the park and argued over, the afternoon everything went wrong and then we laughed until it didn't matter.\n\nNone of it planned. All of it counted.\n\nHere's what four years of watching has taught me: the moments that stick are almost never the ones we stage. They're the by-products. The plant we nearly threw out. The wrong turn on a walk that became the walk.\n\nWe spend so much effort building experiences for our children. And the thing they carry is usually something that happened in the margins of that effort, while we weren't looking.\n\nThat's not an argument for doing nothing. It's an argument for leaving room — for not filling every hour so full that the margins disappear.",
        es: "Lo que ya está ahí este mes, sin que yo organizara nada: conversaciones en la mesa que se alargaron, la piedra que encontraron en el parque y por la que discutieron, la tarde en que todo salió mal y luego nos reímos hasta que dejó de importar.\n\nNada planeado. Todo contó.\n\nEsto es lo que cuatro años de observar me han enseñado: los momentos que se quedan casi nunca son los que montamos. Son los subproductos. La planta que casi tiramos. El giro equivocado en un paseo que se convirtió en el paseo.\n\nDedicamos muchísimo esfuerzo a construir experiencias para nuestros hijos. Y lo que se llevan suele ser algo que pasó en los márgenes de ese esfuerzo, mientras no mirábamos.\n\nNo es un argumento para no hacer nada. Es un argumento para dejar espacio — para no llenar cada hora tanto que los márgenes desaparezcan.",
      },
    },
    practical_insight: {
      short: {
        en: "Earth Day is easy to perform and hard to live. The performable version is a recycled-cardboard craft, photographed, posted, forgotten by Friday.",
        es: "El Día de la Tierra es fácil de aparentar y difícil de vivir. La versión aparente es una manualidad de cartón reciclado, fotografiada, publicada y olvidada para el viernes.",
      },
      long: {
        en: "Earth Day is easy to perform and hard to live.\n\nThe performable version is a recycled-cardboard craft, photographed, posted, forgotten by Friday. It asks nothing of the child except forty minutes and a smile for the camera.\n\nThe lived version is slower: one plant, tended badly, by a child who forgets and remembers. It asks for months, and it accepts failure as part of the deal.\n\nHere's the practical part, the thing you can actually do this week:\n\nDon't add an Earth Day activity to the calendar. Instead, hand your child one living thing and step back. Let the caring be imperfect. Let them own whether it survives.\n\nThe forgetting is not a failure of the exercise — it is the exercise. A plant that lives because a child chose to return to it, again and again, on their own, teaches something no craft can: that care is a decision you make repeatedly, especially when no one is checking.\n\nThat's the version that survives the winter. In the pot, and in them.",
        es: "El Día de la Tierra es fácil de aparentar y difícil de vivir.\n\nLa versión aparente es una manualidad de cartón reciclado, fotografiada, publicada y olvidada para el viernes. No le pide nada al niño salvo cuarenta minutos y una sonrisa para la cámara.\n\nLa versión vivida es más lenta: una planta, cuidada mal, por un niño que olvida y recuerda. Pide meses, y acepta el fracaso como parte del trato.\n\nAquí está la parte práctica, lo que de verdad puedes hacer esta semana:\n\nNo añadas una actividad del Día de la Tierra al calendario. En su lugar, dale a tu hijo un ser vivo y apártate. Deja que el cuidado sea imperfecto. Deja que él decida si sobrevive.\n\nEl olvido no es un fallo del ejercicio — es el ejercicio. Una planta que vive porque un niño eligió volver a ella, una y otra vez, por su cuenta, enseña algo que ninguna manualidad puede: que cuidar es una decisión que se toma repetidamente, sobre todo cuando nadie mira.\n\nEsa es la versión que sobrevive al invierno. En la maceta, y en ellos.",
      },
    },
  },
  // ── premium-only blocks ──
  activity: {
    title: { en: "The Garden of One Thing", es: "El huerto de una sola cosa" },
    ages: "5–17",
    duration: { en: "45 min + a month of small moments", es: "45 min + un mes de momentos pequeños" },
    tags: ["outdoor", "calm", "fine-motor"],
    intro: {
      en: "Plant one thing. Not a garden — one. Then tend it badly, on purpose: let the child own whether it lives.",
      es: "Planta una sola cosa. No un huerto — una. Y cuídala mal, a propósito: deja que el niño decida si vive.",
    },
    materials: {
      en: ["One pot", "A handful of soil", "One herb seedling — mint, basil, whatever the shop has", "A sunny ledge", "A cup for water"],
      es: ["Una maceta", "Un puñado de tierra", "Un plantón de hierba — hierbabuena, albahaca, lo que haya", "Un alféizar con sol", "Un vaso para el agua"],
    },
    steps: {
      en: [
        "Let the child choose the one plant. Resist suggesting a \u201cbetter\u201d one.",
        "Plant it together, once. After that, it is theirs to remember.",
        "Do not remind them to water it. This is the hard part, and the whole point.",
        "On the last day of the month, cook with it — or just smell it together and name what changed.",
      ],
      es: [
        "Deja que el niño elija la planta. Resiste la tentación de sugerir una «mejor».",
        "Plantadla juntos, una vez. A partir de ahí, es suya para recordarla.",
        "No le recuerdes que la riegue. Esta es la parte difícil, y todo el sentido.",
        "El último día del mes, cocinad con ella — o solo oledla juntos y nombrad qué cambió.",
      ],
    },
    notice: {
      en: "Who remembers, who forgets, and what they say when it nearly dies. The forgetting is data, not failure.",
      es: "Quién se acuerda, quién olvida, y qué dicen cuando casi se muere. El olvido es información, no un fracaso.",
    },
    why: {
      en: "Ownership grows from consequence, not instruction. A plant that survives because a child chose to care is worth more than ten that thrive on your reminders.",
      es: "La responsabilidad crece desde la consecuencia, no desde la instrucción. Una planta que sobrevive porque un niño decidió cuidarla vale más que diez que prosperan con tus recordatorios.",
    },
  },
  resources: {
    audiobook: {
      title: { en: "Earth Day 2026 · the mint is still alive", es: "Día de la Tierra 2026 · la hierbabuena sigue viva" },
      narrator: { en: "Narrated by Markus", es: "Narrado por Markus" },
      meta: { en: "16:42 · ages 5–11 · listen before bed", es: "16:42 · edades 5–11 · escuchar antes de dormir" },
    },
    recipe: {
      title: { en: "Fresh Mint Lemonade", es: "Limonada de hierbabuena fresca" },
      role: { en: "Child's role: tears the leaves, tastes, decides if it needs more.", es: "Rol del niño: rompe las hojas, prueba, decide si falta." },
      meta: { en: "Ages all · 15 min · no heat needed", es: "Todas las edades · 15 min · sin fuego" },
    },
    ritual: {
      title: { en: "Three things on the table", es: "Tres cosas en la mesa" },
      body: {
        en: "Before dinner this week, each person names three things — one that grew this month, one that ended, one they want to start.",
        es: "Antes de cenar esta semana, cada uno nombra tres cosas — una que creció este mes, una que terminó, una que quiere empezar.",
      },
    },
    companions: {
      en: [
        { code: "A.001", name: "The Stone Journal" },
        { code: "A.013", name: "The Quiet Advent" },
      ],
      es: [
        { code: "A.001", name: "Diario de piedras" },
        { code: "A.013", name: "El Adviento tranquilo" },
      ],
    },
  },
  closing: {
    en: "The four of us write this together: Markus from Barcelona, Victor from Vienna, Marian from London, Alex from New York. Four households, one shared observation: children with present adults learn to be present.\n\nWe are not anti-screen. We are pro-intention. The difference matters.\n\nAnd from the very beginning, the line we keep returning to — my wife's, not mine: \u00abWe didn't take away their screens. We forgot the cable. They did the rest.\u00bb",
    es: "Los cuatro escribimos esto juntos: Markus desde Barcelona, Victor desde Viena, Marian desde Londres, Alex desde Nueva York. Cuatro casas, una observación compartida: los niños con adultos presentes aprenden a estar presentes.\n\nNo somos anti-pantallas. Somos pro-intención. La diferencia importa.\n\nY desde el principio, la frase a la que siempre volvemos — de mi mujer, no mía: \u00abNo les quitamos las pantallas. Olvidamos el cable. Ellos hicieron el resto.\u00bb",
  },
  disclaimer: {
    en: "Names of people and brands in these editions are changed. Whoever was there and reads this knows what we're talking about.",
    es: "Los nombres de personas y marcas en estas ediciones están cambiados. Quien estuvo allí y lo lee sabe de qué hablamos.",
  },
};

const FE_BLOCKS = [
  { key: "opening",           name: { en: "Opening",            es: "Apertura" },      tier: "free" },
  { key: "story",             name: { en: "Story",              es: "Historia" },      tier: "free" },
  { key: "reflection",        name: { en: "Reflection",         es: "Reflexión" },     tier: "free" },
  { key: "practical_insight", name: { en: "Practical insight",  es: "Idea práctica" }, tier: "free" },
  { key: "activity",          name: { en: "Activity",           es: "Actividad" },     tier: "premium" },
  { key: "resources",         name: { en: "Resources",          es: "Recursos" },      tier: "premium" },
  { key: "closing",           name: { en: "Closing",            es: "Cierre" },        tier: "premium" },
];

const FE_T = {
  freeLabel:  { en: "Freemium", es: "Freemium" },
  plusLabel:  { en: "WiseTip+", es: "WiseTip+" },
  freeTag:    { en: "Free preview", es: "Vista gratis" },
  plusTag:    { en: "Full edition", es: "Edición completa" },
};

function FullEdition(props) {
  // Merge #161 (defined here) into the shared editions map so the reader can
  // render any of the ten full editions by num, each with its own layout.
  if (window.WS_EDITIONS_FULL && !window.WS_EDITIONS_FULL[161]) {
    FE_EDITION.layout = FE_EDITION.layout || "gutter";
    FE_EDITION.accent = FE_EDITION.accent || "#2E6B3A";
    FE_EDITION.badge = FE_EDITION.badge || { en: "Earth Day", es: "Día de la Tierra" };
    window.WS_EDITIONS_FULL[161] = FE_EDITION;
  }
  // Dual-mode: driven by router props when embedded in the app, or by its own
  // local state when opened as the standalone "Full Edition.html".
  const inApp = !!(props && props.nav);
  const [langS, setLangS] = useFE("en");
  const [darkS, setDarkS] = useFE(true);
  const [modeS, setModeS] = useFE("plus"); // "free" | "plus"

  const lang = inApp ? props.lang : langS;
  const setLang = inApp ? (props.setLang || (() => {})) : setLangS;
  const dark = inApp ? props.dark : darkS;
  const setDark = inApp ? (() => {}) : setDarkS;
  const theme = inApp ? props.theme : (dark ? window.WS_DARK : window.WS_LIGHT);
  // In-app, free/plus maps to the global reader tier (isMember).
  const mode = inApp ? (props.isMember ? "plus" : "free") : modeS;
  const setMode = inApp ? (m => props.setIsMember(m === "plus")) : setModeS;

  const ALL = window.WS_EDITIONS_FULL || {};
  const num = inApp && props.pageData && props.pageData.num ? props.pageData.num : 161;
  const ed = ALL[num] || FE_EDITION;
  const layout = ed.layout || "gutter";
  const accent = ed.accent || "#7DBE5A";
  const isPlus = mode === "plus";

  const visibleBlocks = isPlus ? FE_BLOCKS : FE_BLOCKS.filter(b => b.tier === "free");
  const freeCount = FE_BLOCKS.filter(b => b.tier === "free").length;

  return (
    <div style={{ background: theme.bg, color: theme.text, minHeight: "100vh" }}>
      <style>{window.WS_FONT_CSS}</style>

      {/* CONTROL BAR — standalone only (the app supplies its own global Nav) */}
      {!inApp && <div style={{
        position: "sticky", top: 0, zIndex: 20,
        background: theme.navBg, backdropFilter: "blur(14px)", WebkitBackdropFilter: "blur(14px)",
        borderBottom: `1px solid ${theme.border}`,
        padding: ".8rem clamp(1.25rem, 5vw, 3rem)",
        display: "flex", alignItems: "center", justifyContent: "space-between", gap: "1rem", flexWrap: "wrap",
      }}>
        <div style={{ display: "flex", alignItems: "baseline", gap: 10 }}>
          <span className="serif italic" style={{ fontSize: "1.3rem", color: theme.text, fontWeight: 500 }}>WiseTip</span>
          <span style={{ width: 4, height: 4, borderRadius: "50%", background: isPlus ? theme.gold : theme.sage, display: "inline-block" }}/>
          <span className="label-tiny" style={{ color: isPlus ? theme.gold : theme.sage }}>
            {isPlus ? (lang === "en" ? "Full article · 7 of 7" : "Artículo completo · 7 de 7") : (lang === "en" ? "Teaser · 4 of 7" : "Muestra · 4 de 7")}
          </span>
        </div>
        <div style={{ display: "flex", gap: 8, flexWrap: "wrap", alignItems: "center" }}>
          <ModeToggle theme={theme} dark={dark} mode={mode} setMode={setMode} lang={lang}/>
          <FESeg theme={theme} dark={dark} value={lang} onChange={setLang} options={[["en", "EN"], ["es", "ES"]]}/>
          <button onClick={() => setDark(!dark)} title="Toggle theme" style={{
            background: theme.sage3, border: `1px solid ${theme.border2}`, borderRadius: 16,
            color: theme.text2, padding: "6px 12px", fontSize: ".74rem",
          }}>{dark ? "☾" : "☀"}</button>
        </div>
      </div>}

      {/* HERO — layout-aware so no two editions read the same */}
      <EditionHero ed={ed} layout={layout} accent={accent} lang={lang} isPlus={isPlus} inApp={inApp} dark={dark} theme={theme}/>

      {/* MODE RIBBON */}
      <div style={{ background: theme.bg, padding: "0 clamp(1.5rem, 5vw, 5vw)" }}>
        <div className="wrap-sm" style={{
          marginTop: "-1.6rem", position: "relative", zIndex: 5,
          background: dark ? (isPlus ? "#1A2C14" : "#13301E") : "#FFFFFF",
          border: `1px solid ${isPlus ? theme.gold + "55" : theme.border2}`, borderRadius: 8,
          boxShadow: dark ? "0 18px 50px -20px rgba(0,0,0,.6)" : "0 18px 50px -24px rgba(46,107,58,.35)",
          padding: "1.1rem 1.4rem", display: "flex", justifyContent: "space-between", alignItems: "center", gap: "1rem", flexWrap: "wrap",
        }}>
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <span style={{
              width: 34, height: 34, borderRadius: "50%", background: isPlus ? theme.gold : theme.sage,
              color: dark ? "#050F07" : "#fff", display: "flex", alignItems: "center", justifyContent: "center",
              fontFamily: "'Cormorant Garamond',serif", fontSize: "1.1rem",
            }}>{isPlus ? "✦" : "◔"}</span>
            <div>
              <div className="label-tiny" style={{ color: isPlus ? theme.gold : theme.sage, marginBottom: 2 }}>
                {isPlus
                  ? (lang === "en" ? "You're reading the full WiseTip+ article" : "Estás leyendo el artículo completo de WiseTip+")
                  : (lang === "en" ? "You're reading the free teaser" : "Estás leyendo la muestra gratis")}
              </div>
              <div style={{ fontSize: ".84rem", color: theme.text2, fontWeight: 300 }}>
                {isPlus
                  ? (lang === "en" ? "All 7 blocks, each in its long form — plus Activity, Resources & Closing." : "Los 7 bloques, cada uno en su versión larga — más Actividad, Recursos y Cierre.")
                  : (lang === "en" ? "Short versions of 4 blocks. The full article is 2–3× longer." : "Versiones cortas de 4 bloques. El artículo completo es 2–3× más largo.")}
              </div>
            </div>
          </div>
          {!isPlus && (
            <button onClick={() => setMode("plus")} style={{
              background: theme.gold, border: "none", color: dark ? "#1A1206" : "#2A1E08",
              padding: "9px 18px", borderRadius: 20, fontSize: ".8rem", fontWeight: 600, whiteSpace: "nowrap",
            }}>{lang === "en" ? "Read the full article →" : "Leer el artículo completo →"}</button>
          )}
          {isPlus && (
            <button onClick={() => setMode("free")} style={{
              background: "transparent", border: `1px solid ${theme.border2}`, color: theme.text3,
              padding: "8px 16px", borderRadius: 20, fontSize: ".76rem", whiteSpace: "nowrap",
            }}>{lang === "en" ? "See the free teaser" : "Ver la muestra gratis"}</button>
          )}
        </div>
      </div>

      {/* BODY */}
      <article style={{ padding: "3rem clamp(1.5rem, 5vw, 5vw) 1rem" }}>
        <div className="wrap-sm">
          {visibleBlocks.map((b, i) => {
            const firstPremium = isPlus ? FE_BLOCKS.findIndex(x => x.tier === "premium") : -1;
            return (
              <React.Fragment key={b.key}>
                {isPlus && i === firstPremium && (
                  <div style={{ margin: "1.5rem 0 2.75rem", display: "flex", alignItems: "center", gap: 14 }}>
                    <span style={{ flex: 1, height: 1, background: theme.divider }}/>
                    <span className="label-tiny" style={{ color: theme.gold, whiteSpace: "nowrap" }}>
                      {lang === "en" ? "WiseTip+ · the members-only half" : "WiseTip+ · la mitad solo miembros"}
                    </span>
                    <span style={{ flex: 1, height: 1, background: theme.divider }}/>
                  </div>
                )}
                {(layout === "gutter" || layout === "duotone") ? (
                  <BlockShell theme={theme} idx={i} name={b.name[lang]} tier={b.tier} lang={lang} isPlus={isPlus} accent={accent} layout={layout}>
                    <BlockBody b={b} ed={ed} theme={theme} dark={dark} lang={lang} isPlus={isPlus} layout={layout} accent={accent}/>
                  </BlockShell>
                ) : (
                  <BlockFlow theme={theme} idx={i} name={b.name[lang]} tier={b.tier} lang={lang} isPlus={isPlus} accent={accent} layout={layout}>
                    <BlockBody b={b} ed={ed} theme={theme} dark={dark} lang={lang} isPlus={isPlus} layout={layout} accent={accent}/>
                  </BlockFlow>
                )}
              </React.Fragment>
            );
          })}

          {/* PAYWALL — freemium only */}
          {!isPlus && <Paywall theme={theme} dark={dark} lang={lang} onUnlock={() => setMode("plus")} ed={ed}/>}

          {/* DISCLAIMER */}
          <div style={{
            marginTop: "1.5rem", padding: "1.25rem 1.5rem",
            background: theme.sage3, border: `1px dashed ${theme.border2}`, borderRadius: 6,
            fontSize: ".82rem", color: theme.text3, lineHeight: 1.65,
          }}>{ed.disclaimer[lang]}</div>
        </div>
      </article>


    </div>
  );
}

// ── mode toggle (Freemium / WiseTip+) ────────────────────────
function ModeToggle({ theme, dark, mode, setMode, lang }) {
  const opts = [["free", FE_T.freeLabel[lang]], ["plus", FE_T.plusLabel[lang]]];
  return (
    <div style={{ display: "flex", gap: 3, padding: 3, background: theme.sage3, borderRadius: 16, border: `1px solid ${theme.border}` }}>
      {opts.map(([v, l]) => {
        const on = mode === v;
        const plus = v === "plus";
        return (
          <button key={v} onClick={() => setMode(v)} style={{
            padding: "5px 13px", borderRadius: 13, border: "none",
            background: on ? (plus ? theme.gold : theme.sage) : "transparent",
            color: on ? (dark ? "#0A0A0A" : "#fff") : theme.text2,
            fontSize: ".72rem", fontWeight: on ? 600 : 400, whiteSpace: "nowrap",
          }}>{plus ? "✦ " : ""}{l}</button>
        );
      })}
    </div>
  );
}

// ── block shell (number + label gutter) ──────────────────────
function BlockShell({ theme, idx, name, tier, lang, isPlus, accent, layout, children }) {
  const isPrem = tier === "premium";
  const acc = accent || theme.sage;
  const duo = layout === "duotone";
  return (
    <div style={{ display: "grid", gridTemplateColumns: "112px 1fr", gap: "1.75rem", marginBottom: "2.75rem" }} className="fe-block">
      <div style={ duo ? { borderLeft: `2px solid ${isPrem ? theme.gold : acc}`, paddingLeft: 12 } : undefined }>
        <div className="mono" style={{ fontSize: ".68rem", color: theme.text3 }}>{String(idx + 1).padStart(2, "0")}</div>
        <div className="label-tiny" style={{ marginTop: 5, color: isPrem ? theme.gold : acc }}>{name}</div>
        <div style={{ fontSize: ".62rem", marginTop: 4, color: theme.text4, letterSpacing: ".05em" }}>
          {isPrem ? "WiseTip+" : (isPlus ? (lang === "en" ? "Full" : "Completo") : (lang === "en" ? "Teaser" : "Muestra"))}
        </div>
      </div>
      <div>{children}</div>
      <style>{`@media (max-width: 700px){ .fe-block{ grid-template-columns: 1fr !important; gap:.5rem !important; } }`}</style>
    </div>
  );
}

// ── flowing block shell (manuscript / letter / feature) ──────
function BlockFlow({ theme, idx, name, tier, lang, isPlus, accent, layout, children }) {
  const isPrem = tier === "premium";
  const labelColor = isPrem ? theme.gold : (accent || theme.sage);
  const center = layout === "feature" || layout === "manuscript";
  return (
    <div style={{ marginBottom: "2.75rem" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: "1.1rem", justifyContent: center ? "center" : "flex-start" }}>
        <span className="mono" style={{ fontSize: ".66rem", color: theme.text3 }}>{String(idx + 1).padStart(2, "0")}</span>
        <span style={{ width: 24, height: 1, background: labelColor, opacity: .55 }}/>
        <span className="label-tiny" style={{ color: labelColor }}>{name}</span>
        <span style={{ fontSize: ".6rem", color: theme.text4, letterSpacing: ".05em" }}>{isPrem ? "WiseTip+" : (isPlus ? (lang === "en" ? "Full" : "Completo") : (lang === "en" ? "Teaser" : "Muestra"))}</span>
      </div>
      <div>{children}</div>
    </div>
  );
}

// ── EDITION HERO — five visual treatments keyed off ed.layout ─
function EditionHero({ ed, layout, accent, lang, isPlus, inApp, dark, theme }) {
  const pad = inApp
    ? "clamp(5.5rem, 9vh, 7.5rem) clamp(1.5rem, 5vw, 5vw) clamp(3rem, 7vh, 5rem)"
    : "clamp(3rem, 8vh, 6rem) clamp(1.5rem, 5vw, 5vw) clamp(3rem, 7vh, 5rem)";
  const badge = ed.badge ? ed.badge[lang] : null;
  const tierPill = (
    <Pill color={isPlus ? "#C8A85A" : accent} bd={isPlus ? "#C8A85A66" : accent + "66"} style={{ whiteSpace: "nowrap" }}>
      {isPlus ? (lang === "en" ? "WiseTip+ · full 7 blocks" : "WiseTip+ · 7 bloques") : (lang === "en" ? "Free · 4-block teaser" : "Gratis · muestra 4 bloques")}
    </Pill>
  );
  const Byline = ({ onDark }) => (
    <div style={{ display: "flex", alignItems: "center", gap: 14, paddingTop: "1.5rem", borderTop: `1px solid ${onDark ? "rgba(255,255,255,.1)" : theme.divider}` }}>
      <div style={{ width: 46, height: 46, borderRadius: "50%", background: `${ed.editor.color}28`, border: `1.5px solid ${ed.editor.color}77`, display: "flex", alignItems: "center", justifyContent: "center", fontFamily: "'Cormorant Garamond',serif", fontSize: "1.4rem", color: ed.editor.color }}>{ed.editor.name[0]}</div>
      <div style={{ textAlign: "left" }}>
        <div style={{ fontSize: ".96rem", color: onDark ? "#F0EBE0" : theme.text, fontWeight: 500 }}>{ed.editor.name}</div>
        <div style={{ fontSize: ".74rem", color: onDark ? "rgba(240,235,224,.5)" : theme.text3 }}>{ed.editor.location[lang]} · {ed.date[lang]} · {isPlus ? ed.readFull[lang] : ed.readFree[lang]}</div>
      </div>
    </div>
  );

  // ── MANUSCRIPT — centered, ruled, literary ──
  if (layout === "manuscript") {
    const bg = dark ? "#12251A" : "#ECE5D6";
    const tx = dark ? "#EDE7D8" : "#1B2B1E";
    return (
      <header style={{ background: bg, color: tx, padding: pad, textAlign: "center" }}>
        <div className="wrap-sm" style={{ margin: "0 auto" }}>
          <div style={{ display: "flex", justifyContent: "center", gap: 8, marginBottom: "1.5rem", flexWrap: "wrap" }}>
            <Pill color={accent} bd={accent + "66"}>#{ed.num}</Pill>
            {badge && <Pill color={accent} bd={accent + "66"}>{badge}</Pill>}
            {tierPill}
          </div>
          <div style={{ width: 54, height: 1, background: accent, margin: "0 auto 1.5rem", opacity: .6 }}/>
          <h1 className="serif" style={{ fontWeight: 400, fontSize: "clamp(2rem,5vw,3.6rem)", lineHeight: 1.12, letterSpacing: "-.01em", marginBottom: "1rem", color: tx }}>{ed.title[lang]}</h1>
          <p className="serif italic" style={{ fontSize: "clamp(1.05rem,2.2vw,1.3rem)", fontWeight: 300, lineHeight: 1.6, color: dark ? "rgba(237,231,216,.72)" : "rgba(27,43,30,.7)", maxWidth: 560, margin: "0 auto 1.5rem" }}>{ed.subtitle[lang]}</p>
          <div className="mono" style={{ fontSize: ".74rem", letterSpacing: ".08em", color: dark ? "rgba(237,231,216,.55)" : "rgba(27,43,30,.6)" }}>{ed.editor.name} · {ed.editor.location[lang]} · {ed.date[lang]}</div>
        </div>
      </header>
    );
  }

  // ── DUOTONE — split accent panel + dark title panel ──
  if (layout === "duotone") {
    return (
      <header style={{ display: "grid", gridTemplateColumns: "minmax(0,38%) 1fr" }} className="fe-duo-hero">
        <div style={{ background: accent, color: "#0B160E", padding: pad, display: "flex", flexDirection: "column", justifyContent: "flex-end", position: "relative", overflow: "hidden" }}>
          <Grain amount={.06}/>
          <div style={{ position: "relative" }}>
            <div className="serif" style={{ fontSize: "clamp(3rem,7vw,5rem)", fontWeight: 300, lineHeight: .9 }}>#{ed.num}</div>
            {badge && <div className="label-tiny" style={{ marginTop: 12, color: "rgba(11,22,14,.7)" }}>{badge}</div>}
          </div>
        </div>
        <div style={{ background: dark ? "#0B1C12" : "#0E2318", color: "#F0EBE0", padding: pad, position: "relative", overflow: "hidden" }}>
          <Particles count={12} theme={{ sage: "#7DBE5A", sage3: "rgba(125,190,90,.08)" }}/>
          <div style={{ position: "relative", maxWidth: 640 }}>
            <div style={{ marginBottom: "1.5rem" }}>{tierPill}</div>
            <h1 className="serif" style={{ fontStyle: "italic", fontWeight: 300, fontSize: "clamp(2rem,4.5vw,3.6rem)", lineHeight: 1.06, letterSpacing: "-.015em", marginBottom: "1.1rem" }}>{ed.title[lang]}</h1>
            <p style={{ color: "rgba(240,235,224,.6)", fontSize: "clamp(1rem,2vw,1.15rem)", lineHeight: 1.7, fontWeight: 300, marginBottom: "2rem", maxWidth: 560 }}>{ed.subtitle[lang]}</p>
            <Byline onDark={true}/>
          </div>
        </div>
        <style>{`@media (max-width:760px){ .fe-duo-hero{ grid-template-columns:1fr !important; } }`}</style>
      </header>
    );
  }

  // ── DARK-FOREST family: gutter / feature / letter ──
  const centered = layout === "feature";
  const compact = layout === "letter";
  return (
    <header style={{ position: "relative", overflow: "hidden", background: dark ? "#0B1C12" : "#0E2318", color: "#F0EBE0", padding: pad, textAlign: centered ? "center" : "left" }}>
      <Particles count={compact ? 10 : 18} theme={{ sage: "#7DBE5A", sage3: "rgba(125,190,90,.08)" }}/>
      <Trees theme={{ sage: "#7DBE5A" }} dark={true}/>
      <Grain amount={.05}/>
      <div className="wrap-sm" style={{ position: "relative", margin: centered ? "0 auto" : undefined }}>
        <div style={{ display: "flex", gap: 8, marginBottom: compact ? "1.25rem" : "1.75rem", flexWrap: "wrap", justifyContent: centered ? "center" : "flex-start" }}>
          <Pill color={accent} bd={accent + "66"} style={{ whiteSpace: "nowrap" }}>#{ed.num}</Pill>
          {badge && <Pill color="#C8A85A" bd="#C8A85A66" style={{ whiteSpace: "nowrap" }}>★ {badge}</Pill>}
          {tierPill}
        </div>
        {compact && <div className="mono" style={{ fontSize: ".72rem", color: accent, marginBottom: "1rem", letterSpacing: ".08em" }}>{lang === "en" ? "A letter from" : "Una carta desde"} {ed.editor.location[lang]}</div>}
        <h1 className="serif" style={{ fontStyle: "italic", fontWeight: 300, fontSize: centered ? "clamp(2.6rem,7vw,5rem)" : (compact ? "clamp(1.9rem,4.5vw,3.2rem)" : "clamp(2.2rem,6vw,4.2rem)"), color: "#F0EBE0", lineHeight: 1.04, letterSpacing: "-.015em", marginBottom: "1.25rem", maxWidth: centered ? 900 : undefined, marginLeft: centered ? "auto" : undefined, marginRight: centered ? "auto" : undefined }}>{ed.title[lang]}</h1>
        <p style={{ color: "rgba(240,235,224,.6)", fontSize: "clamp(1rem,2.2vw,1.18rem)", lineHeight: 1.7, fontWeight: 300, marginBottom: "2.25rem", maxWidth: 600, marginLeft: centered ? "auto" : undefined, marginRight: centered ? "auto" : undefined }}>{ed.subtitle[lang]}</p>
        <div style={{ display: "flex", justifyContent: centered ? "center" : "flex-start" }}><Byline onDark={true}/></div>
      </div>
    </header>
  );
}

// ── per-block body ───────────────────────────────────────────
function BlockBody({ b, ed, theme, dark, lang, isPlus, layout, accent }) {
  if (b.key === "activity")  return <ActivityBlock a={ed.activity} theme={theme} dark={dark} lang={lang}/>;
  if (b.key === "resources") return <ResourcesBlock r={ed.resources} theme={theme} dark={dark} lang={lang}/>;

  if (b.key === "closing") {
    const text = ed.closing[lang];
    return (
      <div>
        <p className="serif italic" style={{
          fontSize: "1.18rem", lineHeight: 1.7, fontWeight: 300, color: dark ? "#E8DED0" : theme.text,
          borderLeft: `3px solid ${theme.sage}`, paddingLeft: "1.25rem", whiteSpace: "pre-line", marginBottom: "1.75rem",
        }}>{text}</p>
        <div style={{ display: "flex", gap: "1.25rem", flexWrap: "wrap" }}>
          {ed.coEditors.map(e => (
            <div key={e.name} style={{ display: "flex", alignItems: "center", gap: 9 }}>
              <span style={{
                width: 30, height: 30, borderRadius: "50%", background: `${e.color}22`, border: `1px solid ${e.color}77`,
                display: "flex", alignItems: "center", justifyContent: "center",
                fontFamily: "'Cormorant Garamond',serif", fontSize: ".95rem", color: e.color,
              }}>{e.name[0]}</span>
              <span style={{ fontSize: ".8rem", color: theme.text2 }}>{e.name} · <span style={{ color: theme.text3 }}>{e.city[lang]}</span></span>
            </div>
          ))}
        </div>
      </div>
    );
  }

  // shared blocks: short (freemium) or long (premium)
  const variant = isPlus ? "long" : "short";
  const text = ed.blocks[b.key][variant][lang];
  if (b.key === "opening") {
    if (layout === "manuscript" || layout === "feature") {
      return (
        <p className="serif" style={{ fontStyle: layout === "manuscript" ? "normal" : "italic", fontSize: layout === "feature" ? "1.42rem" : "1.3rem", lineHeight: 1.75, fontWeight: 300, color: dark ? "#E8DED0" : theme.text, whiteSpace: "pre-line" }}>
          <span style={{ float: "left", fontFamily: "'Cormorant Garamond',serif", fontSize: "3.6rem", lineHeight: .8, paddingRight: ".09em", marginTop: ".06em", color: accent || theme.sage, fontWeight: 500 }}>{text.charAt(0)}</span>
          {text.slice(1)}
        </p>
      );
    }
    return <p className="serif italic" style={{ fontSize: "1.35rem", lineHeight: 1.7, fontWeight: 300, color: dark ? "#E8DED0" : theme.text, whiteSpace: "pre-line" }}>{text}</p>;
  }
  return <p style={{ fontSize: "1.08rem", lineHeight: 1.85, fontWeight: 300, color: theme.text2, whiteSpace: "pre-line" }}>{text}</p>;
}

// ── PAYWALL (freemium) ───────────────────────────────────────
function Paywall({ theme, dark, lang, onUnlock, ed }) {
  const lockedBlocks = FE_BLOCKS.filter(b => b.tier === "premium");
  return (
    <div style={{ position: "relative", marginTop: ".5rem", marginBottom: "1rem" }}>
      {/* faded preview of what's behind the wall */}
      <div style={{
        position: "relative", maxHeight: 150, overflow: "hidden",
        maskImage: "linear-gradient(180deg, rgba(0,0,0,.5), transparent)",
        WebkitMaskImage: "linear-gradient(180deg, rgba(0,0,0,.5), transparent)",
      }}>
        <div style={{ display: "grid", gridTemplateColumns: "112px 1fr", gap: "1.75rem" }} className="fe-block">
          <div>
            <div className="mono" style={{ fontSize: ".68rem", color: theme.text3 }}>05</div>
            <div className="label-tiny" style={{ marginTop: 5, color: theme.gold }}>{lang === "en" ? "Activity" : "Actividad"}</div>
          </div>
          <div>
            <div className="serif italic" style={{ fontSize: "1.7rem", color: theme.text }}>{ed.activity.title[lang]}</div>
            <p style={{ fontSize: "1.05rem", color: theme.text2, marginTop: 8, fontWeight: 300 }}>{ed.activity.intro[lang]}</p>
          </div>
        </div>
      </div>

      {/* the wall */}
      <div style={{
        marginTop: "-1rem", position: "relative", zIndex: 2,
        background: dark ? "linear-gradient(180deg, #14301D, #0F2417)" : "linear-gradient(180deg, #fff, #F4F1E8)",
        border: `1px solid ${theme.gold}55`, borderRadius: 12,
        boxShadow: dark ? "0 24px 60px -24px rgba(0,0,0,.7)" : "0 24px 60px -28px rgba(46,107,58,.4)",
        padding: "clamp(1.75rem, 4vw, 2.75rem)", textAlign: "center",
      }}>
        <span style={{
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          width: 46, height: 46, borderRadius: "50%", background: `${theme.gold}22`, border: `1px solid ${theme.gold}77`,
          color: theme.gold, fontSize: "1.2rem", marginBottom: "1rem",
        }}>✦</span>
        <div className="label-tiny" style={{ color: theme.gold, marginBottom: ".6rem" }}>
          {lang === "en" ? "The other 3 blocks are for members" : "Los otros 3 bloques son para miembros"}
        </div>
        <h3 className="serif italic" style={{ fontWeight: 400, fontSize: "clamp(1.5rem, 3.5vw, 2.1rem)", color: theme.text, lineHeight: 1.15, marginBottom: ".85rem", maxWidth: 520, marginLeft: "auto", marginRight: "auto" }}>
          {lang === "en" ? "Keep reading the full article" : "Sigue leyendo el artículo completo"}
        </h3>
        <p style={{ fontSize: ".95rem", color: theme.text2, fontWeight: 300, lineHeight: 1.6, maxWidth: 460, margin: "0 auto 1.5rem" }}>
          {lang === "en"
            ? "WiseTip+ expands every block to its full length and unlocks the three that make the edition usable at home:"
            : "WiseTip+ amplía cada bloque a su versión completa y desbloquea los tres que hacen la edición útil en casa:"}
        </p>

        {/* what you unlock */}
        <div style={{ display: "flex", flexDirection: "column", gap: 10, maxWidth: 420, margin: "0 auto 1.75rem", textAlign: "left" }}>
          {[
            { g: "🌱", t: lang === "en" ? "The Activity" : "La Actividad", d: lang === "en" ? "Materials, steps, what to notice, why it works." : "Materiales, pasos, qué observar, por qué funciona." },
            { g: "🎧", t: lang === "en" ? "Resources" : "Recursos", d: lang === "en" ? "Audiobook, recipe & table ritual." : "Audiolibro, receta y ritual de mesa." },
            { g: "✍", t: lang === "en" ? "The Closing" : "El Cierre", d: lang === "en" ? "The four editors' shared sign-off." : "El cierre compartido de los cuatro editores." },
          ].map((x, i) => (
            <div key={i} style={{ display: "flex", gap: 12, alignItems: "flex-start" }}>
              <span style={{ fontSize: "1.05rem", width: 24, textAlign: "center", flexShrink: 0 }}>{x.g}</span>
              <div>
                <div style={{ fontSize: ".92rem", color: theme.text, fontWeight: 500 }}>{x.t}</div>
                <div style={{ fontSize: ".82rem", color: theme.text3, fontWeight: 300, lineHeight: 1.45 }}>{x.d}</div>
              </div>
            </div>
          ))}
          <div style={{ display: "flex", gap: 12, alignItems: "flex-start" }}>
            <span style={{ fontSize: "1.05rem", width: 24, textAlign: "center", flexShrink: 0 }}>＋</span>
            <div>
              <div style={{ fontSize: ".92rem", color: theme.text, fontWeight: 500 }}>{lang === "en" ? "Longer versions of the 4 free blocks" : "Versiones largas de los 4 bloques gratis"}</div>
              <div style={{ fontSize: ".82rem", color: theme.text3, fontWeight: 300, lineHeight: 1.45 }}>{lang === "en" ? "Each block, 2–3× the depth you just read." : "Cada bloque, 2–3× la profundidad que acabas de leer."}</div>
            </div>
          </div>
        </div>

        <button onClick={onUnlock} style={{
          background: theme.gold, border: "none", color: dark ? "#1A1206" : "#2A1E08",
          padding: "12px 26px", borderRadius: 24, fontSize: ".92rem", fontWeight: 600, cursor: "pointer",
        }}>{lang === "en" ? "Unlock the full edition →" : "Desbloquear la edición completa →"}</button>
        <div style={{ fontSize: ".72rem", color: theme.text4, marginTop: ".9rem" }}>
          {lang === "en" ? "Preview — flips to the WiseTip+ reading." : "Vista previa — cambia a la lectura WiseTip+."}
        </div>
      </div>
    </div>
  );
}

// ── ACTIVITY — fully built premium block ─────────────────────
function ActivityBlock({ a, theme, dark, lang }) {
  return (
    <div style={{
      background: dark ? theme.panel : "#fff",
      border: `1px solid ${theme.border2}`, borderRadius: 8, overflow: "hidden",
    }}>
      <div style={{ padding: "1.5rem 1.6rem 1.25rem", borderBottom: `1px solid ${theme.divider}` }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 12, flexWrap: "wrap" }}>
          <h3 className="serif italic" style={{ fontWeight: 400, fontSize: "1.7rem", color: theme.text, lineHeight: 1.1 }}>{a.title[lang]}</h3>
          <span className="mono" style={{ fontSize: ".7rem", color: theme.text3, whiteSpace: "nowrap" }}>{a.ages} · {a.duration[lang]}</span>
        </div>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginTop: ".85rem" }}>
          {a.tags.map(t => {
            const tag = (window.WS_NEEDS_TAGS || []).find(x => x.id === t);
            if (!tag) return null;
            return <span key={t} style={{ fontSize: ".64rem", padding: "2px 9px", borderRadius: 10, background: `${tag.hue}1c`, color: tag.hue, border: `1px solid ${tag.hue}55` }}>{tag.glyph} {tag.label[lang]}</span>;
          })}
        </div>
        <p className="serif italic" style={{ fontSize: "1.12rem", lineHeight: 1.65, color: dark ? "#E8DED0" : theme.text, marginTop: "1rem", fontWeight: 300 }}>{a.intro[lang]}</p>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 0 }} className="grid-2">
        <div style={{ padding: "1.4rem 1.6rem", borderRight: `1px solid ${theme.divider}` }}>
          <div className="label-tiny" style={{ color: theme.sage, marginBottom: ".9rem" }}>{lang === "en" ? "You need" : "Necesitas"}</div>
          <ul style={{ listStyle: "none", display: "flex", flexDirection: "column", gap: 9 }}>
            {a.materials[lang].map((m, i) => (
              <li key={i} style={{ display: "flex", gap: 9, alignItems: "flex-start", fontSize: ".88rem", color: theme.text2, lineHeight: 1.45 }}>
                <span style={{ color: theme.sage, marginTop: 2 }}>—</span>{m}
              </li>
            ))}
          </ul>
        </div>
        <div style={{ padding: "1.4rem 1.6rem" }}>
          <div className="label-tiny" style={{ color: theme.sage, marginBottom: ".9rem" }}>{lang === "en" ? "How it goes" : "Cómo va"}</div>
          <ol style={{ listStyle: "none", display: "flex", flexDirection: "column", gap: 12 }}>
            {a.steps[lang].map((s, i) => (
              <li key={i} style={{ display: "flex", gap: 11, alignItems: "flex-start" }}>
                <span style={{ flexShrink: 0, width: 22, height: 22, borderRadius: "50%", background: theme.sage3, border: `1px solid ${theme.border2}`, color: theme.sage, fontSize: ".7rem", display: "flex", alignItems: "center", justifyContent: "center", fontFamily: "'JetBrains Mono',monospace" }}>{i + 1}</span>
                <span style={{ fontSize: ".88rem", color: theme.text2, lineHeight: 1.5 }}>{s}</span>
              </li>
            ))}
          </ol>
        </div>
      </div>

      <div style={{ padding: "1.3rem 1.6rem", borderTop: `1px solid ${theme.divider}`, display: "grid", gridTemplateColumns: "1fr 1fr", gap: "1.4rem" }} className="grid-2">
        <div>
          <div className="label-tiny" style={{ color: theme.gold, marginBottom: ".5rem" }}>{lang === "en" ? "What to notice" : "Qué observar"}</div>
          <p style={{ fontSize: ".86rem", color: theme.text2, lineHeight: 1.6, fontWeight: 300 }}>{a.notice[lang]}</p>
        </div>
        <div>
          <div className="label-tiny" style={{ color: theme.gold, marginBottom: ".5rem" }}>{lang === "en" ? "Why it works" : "Por qué funciona"}</div>
          <p style={{ fontSize: ".86rem", color: theme.text2, lineHeight: 1.6, fontWeight: 300 }}>{a.why[lang]}</p>
        </div>
      </div>
    </div>
  );
}

// ── RESOURCES — fully built premium block ────────────────────
function ResourcesBlock({ r, theme, dark, lang }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: ".85rem" }}>
      <div style={{ background: dark ? theme.panel : "#fff", border: `1px solid ${theme.border}`, borderRadius: 8, padding: "1.25rem 1.4rem", display: "flex", alignItems: "center", gap: "1.1rem", flexWrap: "wrap" }}>
        <button style={{ flexShrink: 0, width: 46, height: 46, borderRadius: "50%", background: theme.sage, border: "none", color: dark ? "#050F07" : "#fff", fontSize: "1rem", display: "flex", alignItems: "center", justifyContent: "center" }}>▶</button>
        <div style={{ flex: 1, minWidth: 180 }}>
          <div className="label-tiny" style={{ color: theme.sage, marginBottom: 3 }}>🎧 {lang === "en" ? "Audiobook" : "Audiolibro"}</div>
          <div className="serif italic" style={{ fontSize: "1.1rem", color: theme.text, lineHeight: 1.15 }}>{r.audiobook.title[lang]}</div>
          <div style={{ fontSize: ".74rem", color: theme.text3, marginTop: 3 }}>{r.audiobook.narrator[lang]} · {r.audiobook.meta[lang]}</div>
        </div>
        <div style={{ flexShrink: 0 }}><Waveform color={theme.sage} bars={22} height={32}/></div>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: ".85rem" }} className="grid-2">
        <div style={{ background: theme.sage3, border: `1px solid ${theme.border}`, borderRadius: 8, padding: "1.25rem 1.4rem" }}>
          <div className="label-tiny" style={{ color: theme.gold, marginBottom: 6 }}>🍳 {lang === "en" ? "Recipe" : "Receta"}</div>
          <div className="serif italic" style={{ fontSize: "1.12rem", color: theme.text, lineHeight: 1.2, marginBottom: 6 }}>{r.recipe.title[lang]}</div>
          <p style={{ fontSize: ".84rem", color: theme.text2, lineHeight: 1.55, fontWeight: 300, marginBottom: 8 }}>{r.recipe.role[lang]}</p>
          <div style={{ fontSize: ".72rem", color: theme.text3 }} className="mono">{r.recipe.meta[lang]}</div>
        </div>
        <div style={{ background: theme.sage3, border: `1px solid ${theme.border}`, borderRadius: 8, padding: "1.25rem 1.4rem" }}>
          <div className="label-tiny" style={{ color: theme.gold, marginBottom: 6 }}>◇ {lang === "en" ? "Table ritual" : "Ritual de mesa"}</div>
          <div className="serif italic" style={{ fontSize: "1.12rem", color: theme.text, lineHeight: 1.2, marginBottom: 6 }}>{r.ritual.title[lang]}</div>
          <p style={{ fontSize: ".84rem", color: theme.text2, lineHeight: 1.55, fontWeight: 300 }}>{r.ritual.body[lang]}</p>
        </div>
      </div>

      <div style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap", padding: ".25rem 0" }}>
        <span className="label-tiny" style={{ color: theme.text3 }}>{lang === "en" ? "Pairs with" : "Combina con"}</span>
        {r.companions[lang].map(c => (
          <span key={c.code} style={{ display: "inline-flex", alignItems: "center", gap: 7, fontSize: ".8rem", color: theme.text2, background: theme.sage3, border: `1px solid ${theme.border}`, borderRadius: 16, padding: "5px 12px" }}>
            <span className="mono" style={{ fontSize: ".66rem", color: theme.sage }}>{c.code}</span>{c.name}
          </span>
        ))}
      </div>
    </div>
  );
}

// ── small segmented control ──────────────────────────────────
function FESeg({ theme, dark, value, onChange, options }) {
  return (
    <div style={{ display: "flex", gap: 3, padding: 3, background: theme.sage3, borderRadius: 16, border: `1px solid ${theme.border}` }}>
      {options.map(([v, l]) => (
        <button key={v} onClick={() => onChange(v)} style={{
          padding: "5px 12px", borderRadius: 13, border: "none",
          background: value === v ? theme.sage : "transparent",
          color: value === v ? (dark ? "#050F07" : "#fff") : theme.text2,
          fontSize: ".72rem", fontWeight: value === v ? 600 : 400,
        }}>{l}</button>
      ))}
    </div>
  );
}

// Export for the in-app router (Homepage.html loads this before app.jsx).
Object.assign(window, { FullEdition });

// Self-render only when opened as the standalone "Full Edition.html",
// which sets window.WS_SELF_RENDER = "edition" before this script runs.
if (window.WS_SELF_RENDER === "edition") {
  ReactDOM.createRoot(document.getElementById("root")).render(<FullEdition/>);
}
