// descriptions-2026.jsx — Pattern descriptions produits + Scope du projet (iter 11)
//
// Logique unique :
//   description = state.description_overrides[code] ?? catalog.default_description ?? ''
//   isModified  = state.description_overrides[code] != null
//
// Pas de migration BD requise : on stocke override + scope dans state.description_overrides /
// state.scope_text / state.scope_locked / state.scope_generated_at — donc dans la colonne `data`
// JSONB de la table submissions. Compatible 100% rétrocompat.
//
// Exposé :
//   window.RaycastDescriptions = {
//     getLineDescription, isLineModified,
//     ProductDescription, OptionDescriptionEditor, ProjectScope,
//     getDefaultDescriptionFor, buildAutoScope
//   }

(function () {
  const { useState, useEffect } = React;

  // ============================================================================
  // CATALOGUE DESCRIPTIONS PAR DÉFAUT (Phase 2 — admissibles LogisVert + Roulez Vert)
  // ============================================================================
  // Source : PRODUCT_DESCRIPTIONS_SUBVENTIONS.md (zip Phase 2, 20 mai 2026)
  // Chaque description longue contient :
  //   • Marque + modèle + SKU + certifications (CSA, UL, IEC normes exactes)
  //   • Mention RBQ 5590-9402 sous-cat. 11.2 et 13.5 + maître électricien CMEQ
  //   • Mention numéro de série à inscrire après livraison (panneaux + onduleur)
  //   • Référence DA + DT formulaire E.12-07 déposée AVANT achat équipement
  //   • Pour les bornes : mention "figure sur la liste officielle TEQ"
  //
  // Le texte est rédigé pour qu'un dossier déposé sur le portail LogisVert ou Roulez Vert
  // contienne déjà toutes les preuves attendues.
  const FALLBACK_DESCRIPTIONS = {
    // Forfaits install — descriptions LogisVert-admissibles (Phase 2)
    "FS-SOLO":             "Forfait d'installation Solo (Fox ESS ou Sigenergy) — Raycom Électrique inc. (RBQ 5590-9402 sous-cat. 13.5 énergie photovoltaïque et 11.2, maître électricien CMEQ). Installation d'un (1) onduleur hybride, raccordement AC au panneau électrique principal avec disjoncteur bipolaire dédié, mise à la terre conforme CEC 2024, scan ProJoy PEFS (rapid shutdown obligatoire au Canada). Inclut demande d'autorisation Hydro-Québec (DA) et demande de travaux (DT) sur formulaire E.12-07 déposées AVANT l'achat de l'équipement (exigence d'admissibilité LogisVert), configuration de l'application mobile, mise en service complète, documentation technique. Garantie main-d'œuvre Raycom 2 ans en sus des garanties manufacturier.",
    "FS-SOLO-DIM":         "Forfait Solo avec DIM (Fox ESS ou Sigenergy) — installation d'un (1) onduleur hybride + panneau intelligent DIM (Hub G2, LoadHub ou Gateway 3) pour gestion de charge Hydro-Québec et monitoring. Raccordement complet, DA/DT E.12-07 avant achat, application mobile configurée, garantie MO Raycom 2 ans. RBQ 5590-9402 sous-cat. 13.5 + 11.2, membre CMEQ.",
    "FS-SOLO-DIM-BAT":     "Forfait Solo avec DIM + autoconsommation batteries (Fox/Sig) — installation d'un (1) onduleur hybride + DIM + intégration batteries en mode autoconsommation (autocharge solaire, économie pointe). DA/DT E.12-07 avant achat, configuration modes économiques + pointe critique. Garantie MO Raycom 2 ans. RBQ 5590-9402.",
    "FS-SOLO-DIM-BAT-BU":  "Forfait Solo avec DIM + batteries + panneau de backup partiel (Fox/Sig) — Solo complet avec sub-panel 100 A dédié aux charges critiques (frigo, chauffage, prises essentielles) commuté automatiquement en panne. DA/DT, app mobile, garantie MO 2 ans. RBQ 5590-9402.",
    "FS-DUO":              "Forfait Duo (Fox/Sig) — installation de deux (2) onduleurs hybrides en parallèle pour systèmes 12-24 kW, raccordement AC complet, mise à la terre CEC 2024, scan ProJoy PEFS. DA/DT E.12-07 avant achat. Garantie MO Raycom 2 ans. RBQ 5590-9402.",
    "FS-DUO-DIM":          "Forfait Duo avec DIM (Fox/Sig) — Duo complet + panneau intelligent DIM pour gestion HQ. RBQ 5590-9402, garantie MO 2 ans.",
    "FS-DUO-DIM-BAT":      "Forfait Duo avec DIM + autoconsommation batteries (Fox/Sig). DA/DT, garantie MO 2 ans. RBQ 5590-9402.",
    "FS-DUO-DIM-BAT-BU":   "Forfait Duo avec DIM + batteries + panneau backup partiel (Fox/Sig). Sub-panel charges critiques, garantie MO 2 ans. RBQ 5590-9402.",
    "FS-TRIO":             "Forfait Trio (Fox/Sig) — installation de trois (3) onduleurs hybrides en parallèle pour grands systèmes 36-40 kW, raccordement triphasé AC complet. DA/DT E.12-07, scan ProJoy, garantie MO 2 ans. RBQ 5590-9402.",
    "FS-TRIO-DIM":         "Forfait Trio avec DIM (Fox/Sig). RBQ 5590-9402, garantie MO 2 ans.",
    "FS-TRIO-DIM-BAT":     "Forfait Trio avec DIM + batteries (Fox/Sig). DA/DT, garantie MO 2 ans. RBQ 5590-9402.",
    "FS-TRIO-DIM-BAT-BU":  "Forfait Trio complet + backup partiel (Fox/Sig) — pour grands systèmes commerciaux/multilog avec charges critiques. RBQ 5590-9402, garantie MO 2 ans.",
    "TES-SOLO":            "Forfait d'installation Tesla Solo — Raycom Électrique inc., certifié Tesla Energy installer (RBQ 5590-9402 sous-cat. 13.5, maître électricien CMEQ). Installation d'un (1) Powerwall 3 (onduleur hybride intégré 11,5 kW continu, batterie LiFePO4 13,5 kWh utilisables) et d'un Gateway 3 (commutation et monitoring 200 A), raccordement complet AC au panneau principal, mise à la terre CEC 2024, scan Tesla One pré-installation, mise en service avec activation cloud Tesla, configuration de l'application Tesla One au compte client. Inclut DA + DT formulaire E.12-07 déposées avant l'achat (admissibilité LogisVert pour la portion solaire — la batterie est facturée séparément). Garantie Tesla 10 ans + garantie MO Raycom 2 ans.",
    "TES-SOLO-BU":         "Forfait Tesla Solo + panneau backup partiel — PW3 + GW3 + sub-panel 100 A dédié aux charges critiques (frigo, chauffage, prises essentielles). Activation cloud Tesla, DA/DT, garantie MO Raycom 2 ans. RBQ 5590-9402.",
    "TES-SOLO-FBU":        "Installation d'un Tesla Powerwall 3 avec Gateway 3, panneau principal entièrement basculé en backup.\n\nInclus : transport, visites Zone 1, câblage AC, disjoncteurs et protections, filage/boîte/MALT, câblages EPO/RSD/PV/RS485, certification E.12-07, demande Hydro-Québec, mise en service, garantie main-d'œuvre 2 ans.",
    "TES-DUO":             "Forfait Tesla Duo — installation de deux (2) Powerwall 3 + Gateway 3 + stacking kit. 27 kWh stockage, 23 kW puissance crête, DA/DT E.12-07. Activation Tesla One, garantie MO Raycom 2 ans. RBQ 5590-9402.",
    "TES-DUO-BU":          "Forfait Tesla Duo + backup partiel — 2× PW3 + GW3 + sub-panel charges critiques. Garantie MO Raycom 2 ans. RBQ 5590-9402.",
    "TES-DUO-FBU":         "Forfait Tesla Duo + Full Home Backup — 2× PW3 + GW3 maison entière commutée en panne. RBQ 5590-9402, garantie MO 2 ans.",
    "TES-TRIO":            "Forfait Tesla Trio — installation de trois (3) Powerwall 3 + Gateway 3 + 2× stacking kits. 40,5 kWh stockage, 34,5 kW puissance crête. DA/DT, activation Tesla One. RBQ 5590-9402, garantie MO 2 ans.",
    "TES-TRIO-BU":         "Forfait Tesla Trio + backup partiel — 3× PW3 + GW3 + sub-panel charges critiques. RBQ 5590-9402, garantie MO 2 ans.",
    "TES-TRIO-FBU":        "Forfait Tesla Trio + Full Home Backup — 3× PW3 + GW3 maison entière, idéal multilog. RBQ 5590-9402, garantie MO 2 ans.",

    // Services électriques
    "OPT-ENTREE-200A":     "Remplacement d'entrée électrique 200A. Ce que ça représente : remplacement complet de l'entrée électrique existante (100A ou 150A) par une entrée de 200A. On augmente la capacité électrique de la propriété pour supporter les charges d'aujourd'hui — borne de recharge VÉ, thermopompe, batterie, solaire, plinthes — et on remet l'installation aux normes courantes. Inclus : transport et déplacement Zone 1, nouveau panneau principal 200A avec disjoncteur principal, socle de compteur conforme Hydro-Québec, mât de branchement (aérien) ou adaptation de l'entrée souterraine, conducteurs d'entrée, mise à la terre et continuité des masses (MALT), transfert des circuits existants vers le nouveau panneau, disjoncteurs DDFT et de défaut d'arc (DDA) où requis, demande de débranchement/rebranchement Hydro-Québec, permis et inspection, mise en service, garantie main-d'œuvre 2 ans.",

    // Bornes EV — descriptions Roulez Vert-admissibles (figure sur liste officielle TEQ)
    "tesla_gen3_nacs":     "Borne de recharge Tesla Wall Connector Gen 3 — connectique NACS, puissance 11,5 kW continu (48 A), Wi-Fi intégré, contrôle via application Tesla One. Borne niveau 2 certifiée CSA, UL et Intertek, figure sur la liste officielle Transition Énergétique Québec (TEQ) — admissible à Roulez Vert (600 $ résid · 5 000 $/borne multilog + ZEV 1 400 $). Installation par maître électricien Raycom (RBQ 5590-9402), CEC 2024 conforme, disjoncteur bipolaire 60 A dédié, mise à la terre, sectionneur extérieur si extérieur (NEMA 3R/4X).",
    "tesla_universal":     "Borne Tesla Universal Wall Connector — connecteur NACS + adaptateur J1772 (compatible TOUS véhicules électriques nord-américains), 11,5 kW continu (48 A), câble 24 pi intégré, Wi-Fi. Certifiée CSA/UL/Intertek, figure sur la liste officielle TEQ — admissible Roulez Vert. Installation Raycom RBQ 5590-9402, CEC 2024, disjoncteur 60 A dédié.",
    "flo_x3":              "Borne FLO Home X3 — connectique J1772, puissance 7,7 kW (32 A), monitoring FLO Smart Charge via application FLO. Certifiée CSA et Intertek, niveau 2, figure sur la liste officielle TEQ — admissible Roulez Vert. Installation Raycom RBQ 5590-9402, CEC 2024 conforme, disjoncteur bipolaire dédié.",
    "flo_x6":              "Borne FLO Home X6 — connectique J1772, puissance 9,6 kW (40 A), Wi-Fi intégré, app FLO. Certifiée CSA et Intertek niveau 2, figure sur la liste officielle TEQ — admissible Roulez Vert. Installation Raycom CEC 2024, disjoncteur 50 A dédié.",
    "flo_x8":              "Borne FLO Home X8 — connectique J1772, puissance 19,2 kW (80 A), pour véhicules acceptant haute puissance (Ford F-150 Lightning, Hummer EV, etc.). Certifiée CSA/Intertek niveau 2, figure sur la liste officielle TEQ — admissible Roulez Vert. Installation Raycom CEC 2024 avec disjoncteur 100 A dédié, sectionneur extérieur si applicable.",
    "sigenergy_v2x":       "Borne Sigenergy V2X (Vehicle-to-Grid) — connectique NACS ou CCS1, 11,5 kW bidirectionnel, certifiée pour recharge V2X (Vehicle-to-Home / Vehicle-to-Grid). Permet d'injecter l'énergie du véhicule au réseau et bénéficier du crédit Hydro-Québec 0,15 $/kWh injecté (estim. 300 $/an pour 20 000 km/an). Figure sur la liste officielle TEQ — admissible Roulez Vert + V2X HQ. Installation Raycom RBQ 5590-9402, CEC 2024, disjoncteur dédié + communication HQ.",

    // DCC
    "OPT-DCC-12":          "Contrôleur de charge dynamique RVE DCC-12 — délestage automatique pour respecter le 200 A du panneau, homologué Hydro-Québec.",
    "OPT-DCC-10-40A":      "Contrôleur RVE DCC-10 avec disjoncteur 40 A intégré, certifié Hydro-Québec.",
    "OPT-DCC-10-50A":      "Contrôleur RVE DCC-10 avec disjoncteur 50 A intégré.",
    "OPT-DCC-10-60A":      "Contrôleur RVE DCC-10 avec disjoncteur 60 A intégré.",

    // Options électriques (sélection — les plus fréquentes)
    "OPT-PANNEAU-RECUP":   "Mise à niveau du panneau électrique principal de 100 A à 200 A avec réutilisation des disjoncteurs existants compatibles. Inclut visite Hydro-Québec, permis CSA et CMEQ.",
    "OPT-PANNEAU-NEUFS":   "Mise à niveau du panneau électrique principal de 100 A à 200 A avec 40 disjoncteurs neufs. Inclut visite Hydro-Québec, permis CSA et CMEQ.",
    "OPT-ENTREE-NEUVE":    "Installation d'une entrée électrique neuve avec panneau (sans disjoncteurs). Coordination Hydro-Québec pour déplacement compteur.",
    "OPT-SPA-240V":        "Branchement spa 240 V avec disjoncteur dédié 50 A, GFCI haute-courant, conformité Code section 64.",
    "OPT-GENERATRICE-TRANSFERT": "Branchement génératrice fixe avec interrupteur de transfert automatique, conformité CSA C22.1.",

    // Services vendeur
    "OPT-LEVAGE-PW3":      "Levage spécialisé d'un Tesla Powerwall 3 dans un emplacement à accès difficile (escalier, sous-sol bas, accès étroit) — équipement de levage hydraulique inclus.",
    "OPT-LEVAGE-FOX-AIO":  "Levage spécialisé Fox AIO dans un emplacement à accès difficile.",
    "OPT-URGENCE-247":     "Service d'urgence 24/7 pour panne onduleur (intervention sous 4 h en jour ouvrable, 8 h soir/fin de semaine).",
    "OPT-DEMOLITION":      "Démolition et évacuation de l'ancien système solaire / batterie / borne (incluant disposition responsable des composants).",
    "OPT-HAUTEUR":         "Câblage en hauteur avec échafaudage requis (plafond > 4 m, accès en hauteur sans échelle suffisante).",
    "OPT-GRENIER":         "Travail dans grenier ou vide sanitaire (espace restreint, ventilation limitée, isolation à traverser).",
    "OPT-HIVER":           "Travail extérieur hivernal avec accommodations spéciales (températures < −15 °C, déneigement de toiture, sécurité accrue)."
  };

  // ============================================================================
  // HELPERS
  // ============================================================================

  /**
   * Retrouve un produit du catalogue 2026 par son code.
   * @returns {object|null} { code, label, default_description, ... }
   */
  function findCatalogItem(code) {
    if (!code) return null;
    const D = window.RAYCOM_DATA_2026;
    if (!D) return null;
    // Forfaits install
    const forfait = D.forfaits_install.find(f => f.code === code);
    if (forfait) return forfait;
    // Options électriques
    const opt = D.options_electriques.find(o => o.code === code);
    if (opt) return opt;
    // Services vendeur
    const sv = D.services_vendeur.find(s => s.code === code);
    if (sv) return sv;
    // Bornes (modeles + dcc)
    if (D.borne_ev.modeles[code]) return { code, ...D.borne_ev.modeles[code] };
    if (D.borne_ev.dcc[code]) return { code, ...D.borne_ev.dcc[code] };
    return null;
  }

  function getDefaultDescriptionFor(code) {
    const item = findCatalogItem(code);
    if (item?.default_description) return item.default_description;
    if (FALLBACK_DESCRIPTIONS[code]) return FALLBACK_DESCRIPTIONS[code];
    return "";
  }

  /**
   * Règle unique de résolution de la description d'une ligne.
   * @param {string} code - Code Raycom (ex: "FS-SOLO", "OPT-DCC-12", etc.)
   * @param {object} state - State complet de la soumission
   * @returns {string}
   */
  function getLineDescription(code, state) {
    const overrides = state?.description_overrides || {};
    if (overrides[code] != null) return overrides[code];
    return getDefaultDescriptionFor(code);
  }

  function isLineModified(code, state) {
    const overrides = state?.description_overrides || {};
    return overrides[code] != null;
  }

  function setLineOverride(state, setState, code, text) {
    const overrides = { ...(state.description_overrides || {}) };
    if (text == null || text === "") {
      delete overrides[code]; // retour au catalogue
    } else {
      overrides[code] = text;
    }
    setState({ ...state, description_overrides: overrides });
  }

  // ============================================================================
  // AUTO SCOPE GENERATOR (template — V2 via Claude API)
  // ============================================================================
  function buildAutoScope(state, calc) {
    const D = window.RAYCOM_DATA_2026;
    const parts = [];
    const c = state.client || {};

    if (calc?.solarCalc && calc.solar_sell > 0) {
      const kw = calc.solarCalc.kw;
      const np = calc.solarCalc.panneaux;
      const pitch = D.pitch_brackets_ui.find(p => p.key === state.solar.pitch_key)?.label?.toLowerCase() || state.solar.pitch_key;
      const roof = D.roof_types.find(r => r.key === state.solar.roof_type)?.label?.toLowerCase() || state.solar.roof_type;
      parts.push(`l'installation d'un système solaire photovoltaïque de ${kw} kW (${np} panneaux Thornova 500W) sur toiture ${roof} à pente ${pitch}, incluant fixations, racking, onduleur(s), câblage AC et DC, mise à la terre conforme et mise en service complète`);
    }
    if (calc?.battery_sell > 0) {
      parts.push(`l'ajout d'un système de stockage d'énergie ${state.solar?.battery_brand?.toUpperCase() || ""} avec gestion intelligente de l'autoconsommation et du backup`);
    }
    if (calc?.borneCalc && calc.borneCalc.qty > 0) {
      parts.push(`${calc.borneCalc.qty} borne(s) de recharge VÉ ${calc.borneCalc.modele_label || ""} avec câblage et disjoncteur dédié`);
    }
    if ((state.options_electriques || []).length > 0) {
      parts.push(`des options électriques additionnelles selon le contexte du chantier`);
    }

    if (parts.length === 0) {
      return "Soumission préparée par Raycom Électrique pour les travaux décrits ci-dessous. Garantie main-d'œuvre 2 ans.";
    }

    const adresse = c.address_civic && c.address_street
      ? `au ${c.address_civic} ${c.address_street}, ${c.address_city || "QC"}`
      : `à l'adresse ${c.address_city || ""}`;

    return `Soumission pour ${parts.join(" + ")} ${adresse}. Travaux exécutés par Raycom Électrique (RBQ 5590-9402-01, membre CMEQ) avec garantie main-d'œuvre Raycom 2 ans. Inclut demande d'autorisation Hydro-Québec (DA/DT, formulaire E.12-07), permis municipal d'installation, transport et 2 visites incluses. Toutes les références à des subventions sont des estimations basées sur les programmes en vigueur — le client est responsable du dépôt de sa demande.`;
  }

  // ============================================================================
  // CHIP COMPONENT
  // ============================================================================
  function Chip({ variant, children }) {
    const cls = `r26-chip r26-chip-${variant || "default"}`;
    return <span className={cls}>{children}</span>;
  }

  // ============================================================================
  // PRODUCT DESCRIPTION (read-only display with chip)
  // ============================================================================
  function ProductDescription({ code, state, showChip = true, hidden = false }) {
    const text = getLineDescription(code, state);
    const modified = isLineModified(code, state);
    if (!text) return null;
    return (
      <div style={{ fontSize: 12, color: "var(--r26-ink-2)", marginTop: 6, paddingLeft: 12, borderLeft: "3px solid var(--r26-accent)", lineHeight: 1.55 }}>
        {text}
        {showChip && (
          <div style={{ marginTop: 6, display: "flex", gap: 6, flexWrap: "wrap" }}>
            {modified
              ? <Chip variant="modified">✎ Modifiée</Chip>
              : <Chip variant="default">✓ Catalogue</Chip>}
            {hidden && <Chip variant="internal">👁 Interne (hors PDF)</Chip>}
            <Chip variant="default">{text.split(/\s+/).length} mots</Chip>
          </div>
        )}
      </div>
    );
  }

  // ============================================================================
  // OPTION DESCRIPTION EDITOR (collapsible — pour Step 5)
  // ============================================================================
  function OptionDescriptionEditor({ code, label, state, setState }) {
    const [editing, setEditing] = useState(false);
    const current = getLineDescription(code, state);
    const modified = isLineModified(code, state);
    const defaultText = getDefaultDescriptionFor(code);
    const [draft, setDraft] = useState(current);

    useEffect(() => { setDraft(current); }, [code, current]);

    if (!defaultText && !modified) {
      // Pas de description disponible — afficher un placeholder
      return (
        <div style={{ marginTop: 6, padding: 10, borderRadius: 8, background: "#fef9c3", border: "1px solid #fde047", fontSize: 11, color: "#854d0e" }}>
          ⚠ Aucune description catalogue pour <b>{code}</b> — éditer pour en créer une.
          <button className="r26-btn r26-btn-ghost" style={{ marginLeft: 8, padding: "4px 8px", fontSize: 11 }} onClick={() => setEditing(true)}>Créer</button>
        </div>
      );
    }

    if (!editing) {
      return (
        <div style={{ marginTop: 6, padding: 10, borderRadius: 8, background: "var(--r26-bg)", borderLeft: "3px solid var(--r26-accent)" }}>
          <div style={{ fontSize: 12, color: "var(--r26-ink-2)", lineHeight: 1.5 }}>{current}</div>
          <div style={{ marginTop: 6, display: "flex", gap: 6, alignItems: "center" }}>
            {modified
              ? <Chip variant="modified">✎ Modifiée pour cette soumission</Chip>
              : <Chip variant="default">✓ Description catalogue</Chip>}
            <button className="r26-btn r26-btn-ghost" style={{ marginLeft: "auto", padding: "4px 10px", fontSize: 11 }} onClick={() => setEditing(true)}>Personnaliser…</button>
          </div>
        </div>
      );
    }

    return (
      <div style={{ marginTop: 6, padding: 12, borderRadius: 8, background: "#fff", border: "2px solid var(--r26-accent)", boxShadow: "0 0 0 4px rgba(59,130,246,.10)" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }}>
          <span style={{ fontSize: 12, fontWeight: 700, color: "var(--r26-primary)" }}>Description — {label || code}</span>
          {modified
            ? <Chip variant="modified">Modifiée</Chip>
            : <Chip variant="default">Catalogue</Chip>}
          <span style={{ flex: 1 }} />
          <button className="r26-btn r26-btn-ghost" style={{ padding: "4px 8px", fontSize: 11 }} onClick={() => { setDraft(current); setEditing(false); }}>↑ Replier</button>
        </div>
        <textarea
          className="r26-textarea"
          value={draft}
          onChange={(e) => setDraft(e.target.value)}
          rows={4}
          style={{ fontSize: 12 }}
        />
        <div style={{ display: "flex", alignItems: "center", marginTop: 8, gap: 8 }}>
          <span style={{ fontSize: 11, color: "var(--r26-ink-3)" }}>{draft.length} caractères · {draft.trim().split(/\s+/).filter(Boolean).length} mots</span>
          <span style={{ flex: 1 }} />
          {modified && (
            <button className="r26-btn r26-btn-ghost" style={{ padding: "6px 10px", fontSize: 11 }}
                    onClick={() => { setLineOverride(state, setState, code, null); setDraft(defaultText); setEditing(false); }}>
              ↺ Restaurer catalogue
            </button>
          )}
          <button className="r26-btn r26-btn-primary" style={{ padding: "6px 12px", fontSize: 11 }}
                  onClick={() => { setLineOverride(state, setState, code, draft); setEditing(false); }}>
            Enregistrer
          </button>
        </div>
      </div>
    );
  }

  // ============================================================================
  // PROJECT SCOPE (top of Step 6 + PDF) — generate / edit / lock
  // ============================================================================
  function ProjectScope({ state, setState, calc }) {
    const [editing, setEditing] = useState(false);
    const [draft, setDraft] = useState(state.scope_text || "");

    useEffect(() => { setDraft(state.scope_text || ""); }, [state.scope_text]);

    const generate = () => {
      const txt = buildAutoScope(state, calc);
      setState({ ...state, scope_text: txt, scope_locked: false, scope_generated_at: new Date().toISOString() });
      setDraft(txt);
    };

    const save = (lock = false) => {
      setState({ ...state, scope_text: draft, scope_locked: lock, scope_generated_at: state.scope_generated_at || new Date().toISOString() });
      setEditing(false);
    };

    const restoreAuto = () => {
      const txt = buildAutoScope(state, calc);
      setDraft(txt);
    };

    // État VIDE
    if (!state.scope_text && !editing) {
      return (
        <div className="r26-card">
          <div className="r26-card-head">
            <div className="title">📝 Scope du projet</div>
            <div className="num">Optionnel mais recommandé</div>
          </div>
          <div className="r26-card-body" style={{ textAlign: "center", padding: "30px 20px" }}>
            <p style={{ fontSize: 13, color: "var(--r26-ink-2)", marginBottom: 14 }}>
              Un paragraphe narratif en haut de la soumission qui résume le projet en quelques phrases.
              Le client comprend immédiatement le périmètre des travaux.
            </p>
            <button className="r26-btn r26-btn-primary" onClick={generate}>✦ Générer le scope automatiquement</button>
          </div>
        </div>
      );
    }

    // Mode ÉDITION
    if (editing) {
      return (
        <div className="r26-card">
          <div className="r26-card-head">
            <div className="title">📝 Scope du projet — édition</div>
            <button className="r26-btn r26-btn-ghost" style={{ padding: "4px 10px", fontSize: 11, marginLeft: "auto" }} onClick={() => setEditing(false)}>Annuler</button>
          </div>
          <div className="r26-card-body">
            <textarea className="r26-textarea" value={draft} onChange={e => setDraft(e.target.value)} rows={6} />
            <div style={{ display: "flex", alignItems: "center", gap: 8, marginTop: 10 }}>
              <span style={{ fontSize: 11, color: "var(--r26-ink-3)" }}>{draft.trim().split(/\s+/).filter(Boolean).length} mots · {draft.length} caractères</span>
              <span style={{ flex: 1 }} />
              <button className="r26-btn r26-btn-ghost" onClick={restoreAuto}>↺ Restaurer auto</button>
              <button className="r26-btn r26-btn-ghost" onClick={() => save(false)}>Enregistrer (modifiable)</button>
              <button className="r26-btn r26-btn-primary" onClick={() => save(true)}>✓ Valider et verrouiller</button>
            </div>
          </div>
        </div>
      );
    }

    // Mode LECTURE
    return (
      <div className="r26-card">
        <div className="r26-card-head">
          <div className="title">📝 Scope du projet</div>
          {state.scope_locked
            ? <Chip variant="default">✓ Validé</Chip>
            : <Chip variant="modified">✦ Généré (non validé)</Chip>}
          <button className="r26-btn r26-btn-ghost" style={{ padding: "4px 10px", fontSize: 11, marginLeft: "auto" }} onClick={() => setEditing(true)}>Modifier</button>
        </div>
        <div className="r26-card-body">
          <div style={{ fontSize: 13, color: "var(--r26-primary)", lineHeight: 1.6, padding: "10px 14px", borderLeft: "3px solid var(--r26-accent)", background: "#eff6ff", borderRadius: 4 }}>
            {state.scope_text}
          </div>
          <div style={{ marginTop: 8, fontSize: 11, color: "var(--r26-ink-3)" }}>
            {state.scope_generated_at && `Généré ${new Date(state.scope_generated_at).toLocaleDateString("fr-CA")}`}
            {" · "}
            {state.scope_text.trim().split(/\s+/).filter(Boolean).length} mots
          </div>
        </div>
      </div>
    );
  }

  // ============================================================================
  // EXPORT
  // ============================================================================
  window.RaycastDescriptions = {
    getLineDescription, isLineModified, setLineOverride,
    getDefaultDescriptionFor, findCatalogItem,
    buildAutoScope,
    ProductDescription, OptionDescriptionEditor, ProjectScope,
    Chip,
    FALLBACK_DESCRIPTIONS
  };
})();
