// JournalArticle.jsx — full editorial article, on ivory background
const ARTICLES = {
  "27": {
    edition: "N°27",
    date: "Avril 2026",
    category: "Mode",
    read: "5 min",
    title: "Le silencieux retour du tailleur",
    standfirst: "Pendant que la sphère tendances s'agite autour de pièces statement, le tailleur structuré reprend tranquillement sa place — et redessine la silhouette de demain.",
    hero: "assets/photo-metro-white.jpg",
    body: [
      ["", "Aucune communication n'a annoncé son retour. Pas de campagne fracassante, pas de polémique éditoriale. Le tailleur — l'objet de mode le plus codé du XXe siècle — est simplement réapparu dans les vestiaires, au début 2026, avec la lenteur d'une habitude qu'on retrouve."],
      ["Le signal", "À Milan comme à Tokyo, on l'a vu sur les épaules de fondatrices, de DA, de femmes de cinquante ans comme de jeunes femmes de vingt-cinq. Pas le tailleur sexy à épaules carrées des années quatre-vingt. Pas non plus le tailleur sage des cabinets juridiques. Une coupe ample, fluide, presque masculine — un héritage Helmut Lang revisité par une génération qui n'a pas connu Helmut Lang."],
      ["Le débat", "Faut-il y lire un retour à l'ordre, une réaction conservatrice après une décennie de fluidité vestimentaire ? Ou bien, plus simplement, le besoin d'une pièce qui tient — qui fait quelque chose de la silhouette sans la commenter ?"],
      ["Le vrai sujet", "Le tailleur revient parce qu'il est la seule pièce qui résout, en un seul geste, l'équation contemporaine : être professionnelle sans être uniformée, féminine sans être lue uniquement comme telle, élégante sans avoir l'air de chercher. C'est exactement ce que la dernière décennie n'a pas su faire avec ses pantalons cargo et ses robes oversize."],
      ["Le take", "Le tailleur ne revient pas. Il n'est jamais parti — il attendait simplement que l'époque ait fini de tester ses alternatives."],
    ],
    quote: "Le tailleur ne revient pas. Il n'est jamais parti.",
    related: ["26", "25"],
  },
  "26": {
    edition: "N°26",
    date: "Mars 2026",
    category: "Beauté",
    read: "7 min",
    title: "Beauté : la fin du « clean »",
    standfirst: "Pendant cinq ans, l'industrie a vendu la pureté comme valeur. La promesse s'effondre — et ce qui la remplace dit quelque chose d'inconfortable sur notre rapport au corps.",
    hero: "assets/photo-leaf.jpg",
    body: [
      ["", "Le « clean beauty » a été le storytelling dominant de la décennie. Sans paraben, sans silicone, sans sulfate, sans rien. Ce vide chimique allait avec une promesse morale — manger moins, posséder moins, polluer moins."],
      ["Le signal", "Depuis dix-huit mois, les marques qui croissent le plus vite assument l'inverse. Performance, technicité, ingrédients de synthèse étiquetés comme tels. La transparence ne se joue plus sur l'absence — elle se joue sur la précision."],
      ["Le débat", "Greenwashing inversé, ou mûrissement réel du marché ? Probablement les deux. Le consommateur a appris que « naturel » ne voulait rien dire scientifiquement. Et que « pur » était souvent un argument de prix."],
      ["Le vrai sujet", "Ce qui se joue n'est pas une affaire de chimie. C'est une fatigue culturelle. La génération qui a grandi dans le clean a grandi dans la culpabilité — chaque douche un acte politique, chaque crème un calcul. Cette charge devient insoutenable. La nouvelle posture n'est pas le retour au sale ; c'est le droit à la simple performance."],
      ["Le take", "Le clean ne meurt pas par scandale. Il meurt parce qu'il est devenu fatigant."],
    ],
    quote: "Le clean ne meurt pas par scandale. Il meurt parce qu'il est devenu fatigant.",
    related: ["27", "24"],
  },
  "25": {
    edition: "N°25",
    date: "Mars 2026",
    category: "Stratégie",
    read: "6 min",
    title: "Pourquoi vos campagnes lassent",
    standfirst: "Vous produisez plus, vous diffusez plus, vous mesurez plus. Et pourtant l'engagement décroît. Le problème n'est pas dans vos KPIs — il est dans votre rythme.",
    hero: "assets/photo-stairs.jpg",
    body: [
      ["", "Toutes les marques de notre portefeuille, sans exception, ont vu leur taux d'engagement organique chuter entre 2023 et 2025. Pas un peu — fortement. Et la première réaction des équipes a été d'augmenter le volume de production. C'est exactement la mauvaise."],
      ["Le signal", "Les comptes qui résistent ne sont pas ceux qui postent le plus. Ce sont ceux qui ont gardé une cadence — un rythme reconnaissable, presque éditorial. Un mardi qui ressemble à un mardi. Une voix qu'on entend même quand on ne lit pas."],
      ["Le débat", "Les outils d'analyse poussent à la sur-production. Les agences, payées au volume, suivent. Les marques s'épuisent à courir derrière une attention qui se reconfigure."],
      ["Le vrai sujet", "Le problème n'est pas la quantité, c'est la prévisibilité. Une marque qui poste tous les jours sans que personne ne sache pourquoi se traduit en bruit. Une marque qui poste deux fois par semaine, mais avec une intention narrative claire, devient un rendez-vous."],
      ["Le take", "Mieux vaut une voix qu'on attend qu'un volume qu'on subit."],
    ],
    quote: "Mieux vaut une voix qu'on attend qu'un volume qu'on subit.",
    related: ["26", "24"],
  },
  "24": {
    edition: "N°24",
    date: "Février 2026",
    category: "Culture",
    read: "8 min",
    title: "Lifestyle, mot vidé de son sens",
    standfirst: "On a tout appelé lifestyle. Le mot a fini par ne plus rien dire — et avec lui, des années de positionnements de marques s'effondrent en silence.",
    hero: "assets/photo-coffee.jpg",
    body: [
      ["", "Lifestyle : style de vie. À l'origine, le mot désignait une manière d'habiter le monde — choix de logement, choix de vacances, manière de manger. Aujourd'hui, il qualifie aussi bien une marque de bougies qu'un compte Instagram de runner. Le mot a perdu son centre de gravité."],
      ["Le signal", "Les marques qui se définissent comme « lifestyle » sans préciser font face à un plateau. Le consommateur n'a plus de point de repère pour les ranger mentalement. Quand tout est lifestyle, plus rien n'est lifestyle."],
      ["Le débat", "Faut-il abandonner le terme, ou le requalifier ? La majorité des fondateurs avec qui nous travaillons préfèrent le requalifier — par peur d'effrayer leurs investisseurs. Mais le requalifier sans le préciser ne résout rien."],
      ["Le vrai sujet", "La catégorie lifestyle a fonctionné tant qu'elle promettait une cohérence — un univers complet, ranged-by-mood. Aujourd'hui, ce qui crée la cohérence n'est plus l'univers de produits, mais la voix éditoriale qui les rassemble. Ce qui veut dire : revenir au texte avant de revenir à la photo."],
      ["Le take", "Le lifestyle n'est plus un secteur. C'est un effet — et l'effet ne s'achète pas, il se construit."],
    ],
    quote: "Le lifestyle n'est plus un secteur. C'est un effet.",
    related: ["27", "26"],
  },
};

const JournalArticle = () => {
  const [id, setId] = React.useState("27");
  React.useEffect(() => {
    const url = new URL(window.location.href);
    const q = url.searchParams.get("id");
    if (q && ARTICLES[q]) setId(q);
    window.scrollTo(0, 0);
  }, []);
  const a = ARTICLES[id];
  const fontFamily = '"Helvetica Neue", Helvetica, Arial, sans-serif';

  return (
    <article style={{ fontFamily, color: "#0A0A0A", background: "#EDE8D8", paddingTop: 76 }}>
      {/* HERO IMAGE */}
      <section style={{ position: "relative", width: "100%", height: "70vh", minHeight: 600, overflow: "hidden" }}>
        <img src={a.hero} alt="" style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }} />
        <div style={{ position: "absolute", inset: 0, background: "linear-gradient(180deg, rgba(0,0,0,.20) 0%, rgba(0,0,0,.15) 60%, rgba(0,0,0,.50) 100%)" }} />
        <div style={{ position: "absolute", left: 56, right: 56, bottom: 80, color: "#fff" }}>
          <div style={{ fontSize: 12, letterSpacing: ".22em", textTransform: "uppercase", opacity: .85, marginBottom: 24, fontWeight: 700, display: "flex", gap: 24 }}>
            <span>{a.edition}</span><span>·</span><span>{a.date}</span><span>·</span><span>{a.category}</span><span>·</span><span>{a.read}</span>
          </div>
          <h1 style={{ fontSize: "clamp(48px, 6.4vw, 124px)", lineHeight: .95, letterSpacing: "-0.025em", fontWeight: 700, margin: 0, maxWidth: 1500 }}>
            {a.title}
          </h1>
        </div>
      </section>

      {/* STANDFIRST */}
      <section style={{ background: "#EDE8D8", padding: "120px 56px 80px" }}>
        <div style={{ maxWidth: 1000, margin: "0 auto" }}>
          <p style={{ fontSize: "clamp(28px, 2.4vw, 38px)", lineHeight: 1.35, fontWeight: 400, letterSpacing: "-0.005em", margin: 0, fontStyle: "italic" }}>
            {a.standfirst}
          </p>
        </div>
      </section>

      {/* BODY */}
      <section style={{ background: "#EDE8D8", padding: "0 56px 120px" }}>
        <div style={{ maxWidth: 800, margin: "0 auto" }}>
          {a.body.map(([h, p], i) => (
            <div key={i} style={{ marginBottom: 60 }}>
              {h && (
                <div style={{ fontSize: 12, letterSpacing: ".24em", textTransform: "uppercase", opacity: .55, fontWeight: 700, marginBottom: 18 }}>
                  {h}
                </div>
              )}
              <p style={{ fontSize: 22, lineHeight: 1.6, fontWeight: 400, margin: 0 }}>{p}</p>
            </div>
          ))}
        </div>
      </section>

      {/* PULL QUOTE */}
      {a.quote && (
        <section style={{ background: "#3D1520", color: "#fff", padding: "180px 56px", textAlign: "center" }}>
          <div style={{ maxWidth: 1300, margin: "0 auto" }}>
            <div style={{ fontSize: 12, letterSpacing: ".24em", textTransform: "uppercase", opacity: .55, fontWeight: 700, marginBottom: 48 }}>
              Le take
            </div>
            <p style={{ fontSize: "clamp(40px, 5vw, 76px)", lineHeight: 1.15, letterSpacing: "-0.02em", fontWeight: 700, fontStyle: "italic", margin: 0 }}>
              « {a.quote} »
            </p>
          </div>
        </section>
      )}

      {/* RELATED */}
      {a.related && a.related.length > 0 && (
        <section style={{ background: "#EDE8D8", padding: "180px 56px" }}>
          <div style={{ maxWidth: 1600, margin: "0 auto" }}>
            <div style={{ fontSize: 12, letterSpacing: ".22em", textTransform: "uppercase", opacity: .55, marginBottom: 48, fontWeight: 700 }}>
              À lire aussi
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 32 }}>
              {a.related.map(rid => {
                const r = ARTICLES[rid];
                if (!r) return null;
                return (
                  <a key={rid} href={`article.html?id=${rid}`} style={{ color: "inherit", textDecoration: "none", display: "block" }}>
                    <div style={{ width: "100%", aspectRatio: "16/10", overflow: "hidden", marginBottom: 22, background: "#000" }}>
                      <img src={r.hero} alt="" style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }} />
                    </div>
                    <div style={{ fontSize: 12, letterSpacing: ".22em", textTransform: "uppercase", opacity: .55, fontWeight: 700, marginBottom: 14 }}>
                      {r.edition} · {r.date} · {r.category}
                    </div>
                    <div style={{ fontSize: 30, fontWeight: 700, lineHeight: 1.15, letterSpacing: "-0.005em" }}>{r.title}</div>
                  </a>
                );
              })}
            </div>
            <div style={{ marginTop: 80, textAlign: "center" }}>
              <a href="index.html#journal" style={{ color: "#0A0A0A", fontSize: 12, letterSpacing: ".22em", textTransform: "uppercase", fontWeight: 700, textDecoration: "none", borderBottom: "1px solid #0A0A0A", paddingBottom: 4 }}>
                ← Toutes les éditions
              </a>
            </div>
          </div>
        </section>
      )}
    </article>
  );
};

window.JournalArticle = JournalArticle;
window.ARTICLES = ARTICLES;
