/* YES Gestion Chantier - PWA Standalone */
const { useState, useEffect, useCallback } = React;
const {
  Home, Briefcase, FileText, Mail, Settings, Plus, ChevronLeft, Search,
  TrendingUp, TrendingDown, Calendar, MapPin, User, Phone,
  Building2, Euro, Clock, AlertCircle, CheckCircle2, Edit3, Trash2,
  Copy, Send, Download, Filter, MoreVertical, ChevronRight,
  Banknote, Package, Users, Receipt, ClipboardList, X, Save,
  PieChart, Activity, ArrowUpRight, ArrowDownRight
} = window.YESIcons;

// ============================================================
// CHARTE & THÈME YES
// ============================================================
const YES = {
  navy: '#1F4E79',
  navyDark: '#143656',
  blue: '#2E75B6',
  gold: '#C9A227',
  goldLight: '#E8C44C',
  lblue: '#DEEAF6',
  lgold: '#FFF2CC',
  red: '#C00000',
  green: '#3A7D44',
  bg: '#F7F8FA',
  card: '#FFFFFF',
  border: '#E5E7EB',
  text: '#1A1F36',
  textMuted: '#6B7280',
  textLight: '#9CA3AF',
};

// ============================================================
// HELPERS
// ============================================================
const fmtEur = (n) => {
  if (n === null || n === undefined || isNaN(n)) return '— €';
  return new Intl.NumberFormat('fr-FR', {
    style: 'currency',
    currency: 'EUR',
    minimumFractionDigits: 0,
    maximumFractionDigits: 0,
  }).format(n);
};

const fmtEur2 = (n) => {
  if (n === null || n === undefined || isNaN(n)) return '— €';
  return new Intl.NumberFormat('fr-FR', {
    style: 'currency',
    currency: 'EUR',
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  }).format(n);
};

const fmtPct = (n) => {
  if (n === null || n === undefined || isNaN(n)) return '— %';
  return (n * 100).toFixed(1).replace('.', ',') + ' %';
};

const fmtDate = (d) => {
  if (!d) return '—';
  try {
    return new Date(d).toLocaleDateString('fr-FR');
  } catch { return d; }
};

const todayISO = () => new Date().toISOString().split('T')[0];
const newId = () => 'id_' + Date.now().toString(36) + Math.random().toString(36).slice(2, 7);

// ============================================================
// STORAGE LAYER (localStorage natif, persistant entre sessions)
// ============================================================
const storage = {
  async get(key) {
    try {
      return localStorage.getItem(key);
    } catch (e) { return null; }
  },
  async set(key, value) {
    try {
      localStorage.setItem(key, value);
      return true;
    } catch (e) {
      console.warn('[storage] Quota localStorage atteint', e);
      return false;
    }
  },
  async list(prefix) {
    try {
      const keys = [];
      for (let i = 0; i < localStorage.length; i++) {
        const k = localStorage.key(i);
        if (!prefix || k.startsWith(prefix)) keys.push(k);
      }
      return keys;
    } catch (e) { return []; }
  },
  async delete(key) {
    try {
      localStorage.removeItem(key);
      return true;
    } catch (e) { return false; }
  }
};

// ============================================================
// DONNÉES D'EXEMPLE (Affaire Courbevoie pré-chargée)
// ============================================================
const SEED_AFFAIRE = {
  id: 'aff_courbevoie',
  ref: 'YES-DEV-DCE-COURB-004',
  indice: 1,
  nom: 'Courbevoie — Transformation bureaux',
  client: 'SOREHCO',
  moa: 'IMMOBILIÈRE 3F',
  moe: 'LGX INGÉNIERIE / H3M INGÉNIERIE',
  architecte: 'Atelier V. PLET',
  adresse: '37 rue de l\'Industrie / 3 rue Sainte-Marie, 92400 COURBEVOIE',
  lot: 'Lot 12 — Plomberie / CVC / VMC',
  responsable: 'Yacoub GUIDILEYE',
  phase: 'DCE / EXE',
  dateDevis: '2026-04-28',
  delaiMois: 6,
  statut: 'En attente OS',
  ventes: { A: 69249.63, B: 91326.04, C: 17503.96, D: 21920.37 },
  couts: {
    A: { matiere: 39422.84, mo: 21985.82, st: 2274.39, frais: 1450 },
    B: { matiere: 57989.56, mo: 21996.04, st: 2999.46, frais: 1100 },
    C: { matiere:  9581.50, mo:  5174.01, st:  958.15, frais:  200 },
    D: { matiere:  9599.20, mo:  6959.42, st: 2639.78, frais:  108.66 },
  },
  postes: {
    A: 'Plomberie sanitaire (10 logements)',
    B: 'Chauffage & production ECS (PAC R290)',
    C: 'VMC bâtiment transformé (Hygro B)',
    D: 'VMC bâtiment réhabilité + Études/DOE',
  },
  avancement: { A: 0, B: 0, C: 0, D: 0 },
  factureCumul: 0,
  reserves: [
    { code: 'R1', titre: 'Relevés des existants', actif: true },
    { code: 'R2', titre: 'Découvertes en cours de démolition', actif: true },
    { code: 'R3', titre: 'Aménagement PMR (en option) +860 € HT', actif: true },
    { code: 'R4', titre: 'Radiateurs crèche RDC + sous-sol', actif: true },
  ],
  engagements: [],
  situations: [],
};

const SEED_DDP = [
  {
    id: 'ddp_atlantic',
    affaireId: 'aff_courbevoie',
    ref: 'YES-DDP-COURB-001',
    fournisseur: 'ATLANTIC',
    contactFournisseur: 'Service prescription ATLANTIC',
    emailFournisseur: '',
    poste: 'Poste B — Chauffage / ECS',
    montantEstime: 35000,
    statut: 'À envoyer',
    dateEnvoi: null,
    dateRetour: null,
    lignes: [
      {
        ref: 'B.1.2',
        designation: 'PAC AIR/EAU ATLANTIC APTAE 18 R290 — 18 kW à +7/+35°C — GWP=3 — COP saisonnier ≥ 4,5 — triphasée 400V — ≤ 53 dB(A) à 1 m — MES fabricant + carnet sanitaire',
        unite: 'u', qte: 2, pu: 0
      },
      {
        ref: 'B.1.3',
        designation: 'Ballon tampon primaire 500 L acier émaillé — jaquette M1 100 mm — résistance 6×6 kW (36 kW) triphasée — 4 piquages Ø1"¼ — 3 doigts de gant — purgeur — trou d\'homme Ø400',
        unite: 'u', qte: 1, pu: 0
      },
      {
        ref: 'B.1.4',
        designation: 'Préparateur ECS ATLANTIC NEOFIRST 750 L — Secur\'Email — surface échange ≥ 4 m² — puissance 65 kW @ 80/60-10/45°C — anode Mg — conformité ACS — garantie cuve 5 ans',
        unite: 'u', qte: 1, pu: 0
      },
    ]
  },
  {
    id: 'ddp_aldes',
    affaireId: 'aff_courbevoie',
    ref: 'YES-DDP-COURB-003',
    fournisseur: 'ALDES',
    contactFournisseur: 'Service prescription ALDES',
    emailFournisseur: '',
    poste: 'Poste C+D — VMC',
    montantEstime: 9500,
    statut: 'À envoyer',
    dateEnvoi: null,
    dateRetour: null,
    lignes: [
      {
        ref: 'C.3.9',
        designation: 'Caisson VMC C4 ALDES EasyVEC Microwatt+ 600 BAT1 — moteur EC IP54 classe A — 600 m³/h @ 250 Pa — résistance feu C4 (400°C/½h) NF EN 12101-3 — pressostat embarqué',
        unite: 'u', qte: 1, pu: 0
      },
      {
        ref: 'C.2.1',
        designation: 'Entrée d\'air hygroréglable ALDES EHL acoustique 6-45 — 6 à 45 m³/h — Dnew = 39 dB — pour menuiseries — blanc RAL 9010 — auvent extérieur',
        unite: 'u', qte: 26, pu: 0
      },
    ]
  }
];

const SEED_COURRIERS = [
  {
    id: 'courrier_ddp',
    nom: 'Courrier d\'envoi DDP fournisseur',
    type: 'ddp',
    objet: 'Demande de prix — Affaire {{AFFAIRE}} — Phase études EXE',
    corps:
`Madame, Monsieur,

Yang Énergie Services / Groupyang intervient en qualité de sous-traitant CVC/Plomberie/VMC sur l'opération {{AFFAIRE}} à {{LIEU}}, sous maîtrise d'ouvrage {{MOA}} et donneur d'ordre {{CLIENT}}.

Dans le cadre de la phase études EXE, nous vous prions de nous adresser votre meilleure offre pour la fourniture des produits référencés dans le bordereau joint (détails techniques exhaustifs : marques, modèles, normes).

Conditions de retour :
• Délai de réponse : 15 jours calendaires
• Validité minimale : 3 mois ferme
• Règlement souhaité : virement 30 jours date de facture
• Livraison franco chantier
• Équivalences justifiées techniquement

Pour toute précision : 06 26 02 67 71 / 01 48 21 19 84.

Salutations distinguées,

Yacoub GUIDILEYE — Directeur
Yang Énergie Services / Groupyang
yacoub.guidileye@groupyang.fr`
  },
  {
    id: 'courrier_devis',
    nom: 'Mail d\'envoi devis client',
    type: 'devis',
    objet: 'Devis {{REF}} — {{AFFAIRE}} — {{LOT}} — Indice {{INDICE}}',
    corps:
`Bonjour,

Veuillez trouver ci-joint notre devis pour l'opération {{AFFAIRE}}.

Référence : {{REF}} — Indice {{INDICE}}
Date : {{DATE}}
Montant HT : {{MONTANT}}
TVA : Autoliquidation art. 283-2 nonies CGI
Délai d'exécution : {{DELAI}} mois (préparation incluse)
Validité de l'offre : 3 mois

Notre offre intègre les réserves contractuelles R1 à R4 jointes au devis. Toute évolution donnera lieu à un avenant contradictoire chiffré préalablement à l'exécution.

Nous restons à votre disposition pour tout échange complémentaire.

Cordialement,

Yacoub GUIDILEYE — Directeur
Yang Énergie Services / Groupyang
06 26 02 67 71 / 01 48 21 19 84
yacoub.guidileye@groupyang.fr`
  },
  {
    id: 'courrier_situation',
    nom: 'Envoi situation de travaux',
    type: 'situation',
    objet: 'Situation N°{{NUM_SIT}} — {{AFFAIRE}} — {{REF}}',
    corps:
`Bonjour,

Veuillez trouver ci-joint notre situation N°{{NUM_SIT}} pour l'affaire {{AFFAIRE}}.

Référence devis : {{REF}}
Date : {{DATE}}
Montant période HT : {{MONTANT_PERIODE}}
Cumul HT : {{CUMUL}}
TVA : Autoliquidation art. 283-2 nonies CGI
Règlement : virement 30 jours date de facture

Le détail ligne par ligne et le tableau d'avancement sont joints en annexe.

Bien cordialement,

Yacoub GUIDILEYE — Directeur
Yang Énergie Services / Groupyang
yacoub.guidileye@groupyang.fr`
  },
  {
    id: 'courrier_avenant',
    nom: 'Demande d\'avenant contradictoire',
    type: 'avenant',
    objet: 'Affaire {{AFFAIRE}} — Demande d\'avenant — {{MOTIF}}',
    corps:
`Bonjour,

Dans le cadre de l'affaire {{AFFAIRE}} (référence marché {{REF}}), nous vous sollicitons pour la mise en place d'un avenant contradictoire portant sur :

Objet : {{MOTIF}}
Articles CCTP concernés : {{ARTICLES}}
Référence aux réserves : {{RESERVES}}

Justification technique :
{{JUSTIFICATION}}

Montant proposé : {{MONTANT}} HT

Cette demande est formulée préalablement à toute exécution conformément aux réserves contractuelles. Nous joignons à la présente le détail chiffré et les pièces justificatives.

Dans l'attente de votre validation,

Yacoub GUIDILEYE — Directeur
Yang Énergie Services / Groupyang`
  }
];

// ============================================================
// COMPUTED HELPERS
// ============================================================
const calcAffaire = (a) => {
  const venteTotal = (a.ventes.A || 0) + (a.ventes.B || 0) + (a.ventes.C || 0) + (a.ventes.D || 0);
  const coutTotal = ['A','B','C','D'].reduce((s, k) => {
    const c = a.couts[k] || {};
    return s + (c.matiere || 0) + (c.mo || 0) + (c.st || 0) + (c.frais || 0);
  }, 0);
  const marge = venteTotal - coutTotal;
  const txMarge = venteTotal > 0 ? marge / venteTotal : 0;
  const avgAvanc = ['A','B','C','D'].reduce((s, k) => {
    const v = a.ventes[k] || 0;
    const av = a.avancement[k] || 0;
    return s + v * av;
  }, 0);
  const pctAvanc = venteTotal > 0 ? avgAvanc / venteTotal : 0;
  return { venteTotal, coutTotal, marge, txMarge, avgAvanc, pctAvanc };
};

// ============================================================
// COMPONENTS — UI BASE
// ============================================================
const Pill = ({ children, color = 'blue', size = 'sm' }) => {
  const colors = {
    blue: { bg: YES.lblue, text: YES.navy },
    gold: { bg: YES.lgold, text: '#8B6914' },
    green: { bg: '#D1FAE5', text: '#065F46' },
    red: { bg: '#FEE2E2', text: YES.red },
    grey: { bg: '#F3F4F6', text: YES.textMuted },
  };
  const c = colors[color] || colors.grey;
  const sz = size === 'sm' ? { fontSize: 11, padding: '3px 8px' } : { fontSize: 12, padding: '4px 10px' };
  return (
    <span style={{
      display: 'inline-block', borderRadius: 6, fontWeight: 600,
      background: c.bg, color: c.text, letterSpacing: 0.2, ...sz
    }}>
      {children}
    </span>
  );
};

const Card = ({ children, onClick, style = {} }) => (
  <div
    onClick={onClick}
    style={{
      background: YES.card,
      borderRadius: 12,
      padding: 16,
      boxShadow: '0 1px 3px rgba(31,49,86,0.04), 0 1px 2px rgba(31,49,86,0.02)',
      border: `1px solid ${YES.border}`,
      cursor: onClick ? 'pointer' : 'default',
      transition: 'transform 0.12s, box-shadow 0.12s',
      ...style
    }}
    onTouchStart={onClick ? (e) => e.currentTarget.style.transform = 'scale(0.98)' : undefined}
    onTouchEnd={onClick ? (e) => e.currentTarget.style.transform = 'scale(1)' : undefined}
  >
    {children}
  </div>
);

const Stat = ({ label, value, unit, color = YES.navy, icon: Icon, trend }) => (
  <div style={{
    background: YES.card,
    borderRadius: 10,
    padding: 12,
    border: `1px solid ${YES.border}`,
    flex: 1,
    minWidth: 0,
  }}>
    <div style={{
      fontSize: 11, color: YES.textMuted, fontWeight: 600,
      textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 6,
      display: 'flex', alignItems: 'center', gap: 6
    }}>
      {Icon && <Icon size={12} />}
      {label}
    </div>
    <div style={{ display: 'flex', alignItems: 'baseline', gap: 4 }}>
      <span style={{ fontSize: 18, fontWeight: 700, color, fontFamily: '"DM Mono", "SF Mono", Menlo, monospace' }}>
        {value}
      </span>
      {unit && <span style={{ fontSize: 11, color: YES.textMuted }}>{unit}</span>}
    </div>
    {trend !== undefined && trend !== null && (
      <div style={{
        fontSize: 11, fontWeight: 600, marginTop: 4,
        color: trend >= 0 ? YES.green : YES.red,
        display: 'flex', alignItems: 'center', gap: 2,
      }}>
        {trend >= 0 ? <ArrowUpRight size={12} /> : <ArrowDownRight size={12} />}
        {Math.abs(trend).toFixed(1)}%
      </div>
    )}
  </div>
);

const SectionTitle = ({ children, action }) => (
  <div style={{
    display: 'flex', alignItems: 'center', justifyContent: 'space-between',
    margin: '20px 0 12px 0', padding: '0 4px'
  }}>
    <h3 style={{
      fontSize: 11, fontWeight: 700, color: YES.textMuted,
      textTransform: 'uppercase', letterSpacing: 1.2, margin: 0
    }}>
      {children}
    </h3>
    {action}
  </div>
);

const Button = ({ children, onClick, variant = 'primary', icon: Icon, fullWidth, disabled, style = {} }) => {
  const variants = {
    primary: { bg: YES.navy, color: '#fff', border: YES.navy },
    secondary: { bg: '#fff', color: YES.navy, border: YES.border },
    gold: { bg: YES.gold, color: '#fff', border: YES.gold },
    danger: { bg: YES.red, color: '#fff', border: YES.red },
    ghost: { bg: 'transparent', color: YES.navy, border: 'transparent' },
  };
  const v = variants[variant] || variants.primary;
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      style={{
        background: disabled ? '#E5E7EB' : v.bg,
        color: disabled ? YES.textLight : v.color,
        border: `1px solid ${disabled ? '#E5E7EB' : v.border}`,
        padding: '11px 16px',
        borderRadius: 8,
        fontWeight: 600,
        fontSize: 14,
        cursor: disabled ? 'not-allowed' : 'pointer',
        display: 'inline-flex',
        alignItems: 'center',
        justifyContent: 'center',
        gap: 8,
        width: fullWidth ? '100%' : 'auto',
        transition: 'all 0.15s',
        WebkitTapHighlightColor: 'transparent',
        ...style
      }}
    >
      {Icon && <Icon size={16} strokeWidth={2.2} />}
      {children}
    </button>
  );
};

const Input = ({ label, value, onChange, type = 'text', placeholder, required, multiline, rows = 3 }) => (
  <div style={{ marginBottom: 14 }}>
    {label && (
      <label style={{
        display: 'block', fontSize: 12, fontWeight: 600,
        color: YES.textMuted, marginBottom: 6, letterSpacing: 0.3
      }}>
        {label} {required && <span style={{ color: YES.red }}>*</span>}
      </label>
    )}
    {multiline ? (
      <textarea
        value={value || ''}
        onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder}
        rows={rows}
        style={{
          width: '100%', padding: '10px 12px', fontSize: 14, lineHeight: 1.5,
          border: `1px solid ${YES.border}`, borderRadius: 8,
          background: '#FAFBFC', color: YES.text,
          fontFamily: 'inherit', resize: 'vertical', boxSizing: 'border-box',
        }}
      />
    ) : (
      <input
        type={type}
        value={value || ''}
        onChange={(e) => onChange(type === 'number' ? parseFloat(e.target.value) || 0 : e.target.value)}
        placeholder={placeholder}
        style={{
          width: '100%', padding: '11px 12px', fontSize: 14,
          border: `1px solid ${YES.border}`, borderRadius: 8,
          background: '#FAFBFC', color: YES.text,
          fontFamily: 'inherit', boxSizing: 'border-box',
        }}
      />
    )}
  </div>
);

// ============================================================
// SCREEN — DASHBOARD
// ============================================================
const DashboardScreen = ({ affaires, ddps, setScreen }) => {
  const totalCA = affaires.reduce((s, a) => s + calcAffaire(a).venteTotal, 0);
  const totalMarge = affaires.reduce((s, a) => s + calcAffaire(a).marge, 0);
  const txMargeMoy = totalCA > 0 ? totalMarge / totalCA : 0;
  const ddpsAEnvoyer = ddps.filter(d => d.statut === 'À envoyer').length;
  const ddpsEnAttente = ddps.filter(d => d.statut === 'Envoyée' && !d.dateRetour).length;

  return (
    <div style={{ padding: 16 }}>
      {/* Header brand */}
      <div style={{ marginBottom: 24, padding: '8px 4px' }}>
        <div style={{ fontSize: 11, color: YES.textMuted, fontWeight: 600, letterSpacing: 1.5, textTransform: 'uppercase' }}>
          Yang Énergie Services
        </div>
        <h1 style={{
          fontSize: 28, fontWeight: 800, color: YES.navy, margin: '4px 0 0 0',
          fontFamily: '"DM Sans", system-ui, sans-serif', letterSpacing: -0.5
        }}>
          Tableau de bord
        </h1>
      </div>

      {/* KPIs principaux */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 10 }}>
        <Stat label="CA actif" icon={Euro} value={fmtEur(totalCA)} />
        <Stat label="Marge brute" icon={TrendingUp} value={fmtEur(totalMarge)} color={totalMarge > 0 ? YES.green : YES.red} />
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <Stat label="Tx marge" icon={Activity} value={fmtPct(txMargeMoy)} color={txMargeMoy > 0.1 ? YES.green : YES.gold} />
        <Stat label="Affaires" icon={Briefcase} value={affaires.length} unit="actives" color={YES.navy} />
      </div>

      {/* Quick actions */}
      <SectionTitle>Actions rapides</SectionTitle>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <Card onClick={() => setScreen({ name: 'affaires' })}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
            <div style={{
              width: 38, height: 38, borderRadius: 9, background: YES.lblue,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <Briefcase size={20} color={YES.navy} />
            </div>
            <div>
              <div style={{ fontSize: 14, fontWeight: 700, color: YES.navy }}>Mes affaires</div>
              <div style={{ fontSize: 11, color: YES.textMuted }}>{affaires.length} en cours</div>
            </div>
          </div>
        </Card>
        <Card onClick={() => setScreen({ name: 'ddps' })}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
            <div style={{
              width: 38, height: 38, borderRadius: 9, background: YES.lgold,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <Package size={20} color={YES.gold} />
            </div>
            <div>
              <div style={{ fontSize: 14, fontWeight: 700, color: YES.navy }}>DDP</div>
              <div style={{ fontSize: 11, color: YES.textMuted }}>{ddpsAEnvoyer} à envoyer</div>
            </div>
          </div>
        </Card>
      </div>

      {/* Affaires en cours */}
      <SectionTitle action={
        <button
          onClick={() => setScreen({ name: 'affaires' })}
          style={{
            background: 'none', border: 'none', color: YES.blue,
            fontSize: 11, fontWeight: 700, letterSpacing: 0.5, cursor: 'pointer',
            textTransform: 'uppercase'
          }}
        >
          Voir tout →
        </button>
      }>
        Affaires en cours
      </SectionTitle>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {affaires.slice(0, 3).map(a => {
          const calc = calcAffaire(a);
          return (
            <Card key={a.id} onClick={() => setScreen({ name: 'affaire', id: a.id })}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 8 }}>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 10, color: YES.textMuted, fontWeight: 700, letterSpacing: 0.5, marginBottom: 2 }}>
                    {a.ref} · IND {a.indice}
                  </div>
                  <div style={{ fontSize: 15, fontWeight: 700, color: YES.navy, marginBottom: 4 }}>
                    {a.nom}
                  </div>
                  <div style={{ fontSize: 12, color: YES.textMuted, display: 'flex', alignItems: 'center', gap: 4 }}>
                    <Building2 size={11} /> {a.client}
                  </div>
                </div>
                <Pill color={a.statut.includes('attente') ? 'gold' : 'green'}>{a.statut}</Pill>
              </div>
              <div style={{
                display: 'grid', gridTemplateColumns: '1fr 1fr 1fr',
                gap: 8, paddingTop: 10, borderTop: `1px solid ${YES.border}`
              }}>
                <div>
                  <div style={{ fontSize: 10, color: YES.textLight }}>CA HT</div>
                  <div style={{ fontSize: 13, fontWeight: 700, color: YES.navy, fontFamily: '"DM Mono", monospace' }}>
                    {fmtEur(calc.venteTotal)}
                  </div>
                </div>
                <div>
                  <div style={{ fontSize: 10, color: YES.textLight }}>Marge</div>
                  <div style={{ fontSize: 13, fontWeight: 700, color: calc.marge > 0 ? YES.green : YES.red, fontFamily: '"DM Mono", monospace' }}>
                    {fmtPct(calc.txMarge)}
                  </div>
                </div>
                <div>
                  <div style={{ fontSize: 10, color: YES.textLight }}>Avancement</div>
                  <div style={{ fontSize: 13, fontWeight: 700, color: YES.navy, fontFamily: '"DM Mono", monospace' }}>
                    {fmtPct(calc.pctAvanc)}
                  </div>
                </div>
              </div>
            </Card>
          );
        })}
      </div>

      {/* DDP status */}
      {(ddpsAEnvoyer > 0 || ddpsEnAttente > 0) && (
        <>
          <SectionTitle>Demandes de prix</SectionTitle>
          <Card>
            <div style={{ display: 'flex', justifyContent: 'space-around' }}>
              <div style={{ textAlign: 'center' }}>
                <div style={{ fontSize: 28, fontWeight: 800, color: YES.gold, fontFamily: '"DM Sans", sans-serif' }}>
                  {ddpsAEnvoyer}
                </div>
                <div style={{ fontSize: 11, color: YES.textMuted, fontWeight: 600 }}>À envoyer</div>
              </div>
              <div style={{ width: 1, background: YES.border }} />
              <div style={{ textAlign: 'center' }}>
                <div style={{ fontSize: 28, fontWeight: 800, color: YES.blue, fontFamily: '"DM Sans", sans-serif' }}>
                  {ddpsEnAttente}
                </div>
                <div style={{ fontSize: 11, color: YES.textMuted, fontWeight: 600 }}>En attente</div>
              </div>
            </div>
          </Card>
        </>
      )}

      <div style={{ height: 90 }} />
    </div>
  );
};

// ============================================================
// SCREEN — AFFAIRES LIST
// ============================================================
const AffairesListScreen = ({ affaires, setScreen, setAffaires }) => {
  const [search, setSearch] = useState('');
  const [showForm, setShowForm] = useState(false);

  const filtered = affaires.filter(a =>
    !search ||
    a.nom.toLowerCase().includes(search.toLowerCase()) ||
    a.client.toLowerCase().includes(search.toLowerCase()) ||
    a.ref.toLowerCase().includes(search.toLowerCase())
  );

  return (
    <div style={{ padding: 16 }}>
      <h1 style={{
        fontSize: 28, fontWeight: 800, color: YES.navy, margin: '8px 0 16px 0',
        fontFamily: '"DM Sans", system-ui, sans-serif', letterSpacing: -0.5
      }}>
        Affaires
      </h1>

      <div style={{ position: 'relative', marginBottom: 16 }}>
        <Search size={16} style={{
          position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)',
          color: YES.textLight, pointerEvents: 'none'
        }} />
        <input
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          placeholder="Rechercher une affaire..."
          style={{
            width: '100%', padding: '11px 12px 11px 36px', fontSize: 14,
            border: `1px solid ${YES.border}`, borderRadius: 8,
            background: '#fff', boxSizing: 'border-box'
          }}
        />
      </div>

      <Button icon={Plus} variant="gold" fullWidth onClick={() => setShowForm(true)} style={{ marginBottom: 16 }}>
        Nouvelle affaire
      </Button>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {filtered.map(a => {
          const calc = calcAffaire(a);
          return (
            <Card key={a.id} onClick={() => setScreen({ name: 'affaire', id: a.id })}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 10 }}>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 10, color: YES.textMuted, fontWeight: 700, letterSpacing: 0.5 }}>
                    {a.ref} · IND {a.indice}
                  </div>
                  <div style={{ fontSize: 15, fontWeight: 700, color: YES.navy, margin: '2px 0' }}>
                    {a.nom}
                  </div>
                  <div style={{ fontSize: 12, color: YES.textMuted }}>{a.lot}</div>
                </div>
                <ChevronRight size={18} color={YES.textLight} />
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginTop: 8 }}>
                <Pill color="blue">{a.client}</Pill>
                <Pill color={a.statut.includes('attente') ? 'gold' : 'green'}>{a.statut}</Pill>
              </div>
              <div style={{
                marginTop: 12, paddingTop: 12, borderTop: `1px solid ${YES.border}`,
                display: 'flex', justifyContent: 'space-between', alignItems: 'center'
              }}>
                <div>
                  <div style={{ fontSize: 10, color: YES.textLight, fontWeight: 600 }}>CA HT</div>
                  <div style={{ fontSize: 16, fontWeight: 800, color: YES.navy, fontFamily: '"DM Mono", monospace' }}>
                    {fmtEur(calc.venteTotal)}
                  </div>
                </div>
                <div style={{ textAlign: 'right' }}>
                  <div style={{ fontSize: 10, color: YES.textLight, fontWeight: 600 }}>Marge</div>
                  <div style={{ fontSize: 16, fontWeight: 800, color: calc.marge > 0 ? YES.green : YES.red, fontFamily: '"DM Mono", monospace' }}>
                    {fmtPct(calc.txMarge)}
                  </div>
                </div>
              </div>
            </Card>
          );
        })}
        {filtered.length === 0 && (
          <div style={{
            textAlign: 'center', padding: 40, color: YES.textMuted, fontSize: 14
          }}>
            Aucune affaire trouvée
          </div>
        )}
      </div>

      {showForm && (
        <NewAffaireModal
          onClose={() => setShowForm(false)}
          onSave={(a) => {
            setAffaires([...affaires, a]);
            setShowForm(false);
            setScreen({ name: 'affaire', id: a.id });
          }}
        />
      )}

      <div style={{ height: 90 }} />
    </div>
  );
};

// ============================================================
// MODAL — NOUVELLE AFFAIRE
// ============================================================
const NewAffaireModal = ({ onClose, onSave }) => {
  const [form, setForm] = useState({
    ref: '', nom: '', client: '', moa: '', moe: '',
    adresse: '', lot: '', responsable: 'Yacoub GUIDILEYE',
    dateDevis: todayISO(), delaiMois: 6, statut: 'En préparation',
  });
  const upd = (k) => (v) => setForm({ ...form, [k]: v });

  const save = () => {
    if (!form.ref || !form.nom) return;
    const newAff = {
      id: newId(), indice: 0,
      ventes: { A: 0, B: 0, C: 0, D: 0 },
      couts: { A: {}, B: {}, C: {}, D: {} },
      postes: { A: 'Poste A', B: 'Poste B', C: 'Poste C', D: 'Poste D' },
      avancement: { A: 0, B: 0, C: 0, D: 0 },
      factureCumul: 0, reserves: [], engagements: [], situations: [],
      ...form
    };
    onSave(newAff);
  };

  return (
    <FullScreenModal title="Nouvelle affaire" onClose={onClose} onSave={save}>
      <Input label="Référence" required value={form.ref} onChange={upd('ref')} placeholder="YES-DEV-..." />
      <Input label="Nom de l'affaire" required value={form.nom} onChange={upd('nom')} />
      <Input label="Client / Donneur d'ordre" value={form.client} onChange={upd('client')} />
      <Input label="Maître d'ouvrage" value={form.moa} onChange={upd('moa')} />
      <Input label="Maîtrise d'œuvre" value={form.moe} onChange={upd('moe')} />
      <Input label="Adresse" value={form.adresse} onChange={upd('adresse')} multiline />
      <Input label="Lot" value={form.lot} onChange={upd('lot')} />
      <Input label="Responsable d'affaire" value={form.responsable} onChange={upd('responsable')} />
      <Input label="Date du devis" type="date" value={form.dateDevis} onChange={upd('dateDevis')} />
      <Input label="Délai d'exécution (mois)" type="number" value={form.delaiMois} onChange={upd('delaiMois')} />
    </FullScreenModal>
  );
};

// ============================================================
// FULL SCREEN MODAL
// ============================================================
const FullScreenModal = ({ title, onClose, onSave, children, saveLabel = 'Enregistrer' }) => (
  <div style={{
    position: 'fixed', top: 0, left: 0, right: 0, bottom: 0,
    background: '#fff', zIndex: 1000, display: 'flex', flexDirection: 'column',
    animation: 'slideUp 0.3s ease-out'
  }}>
    <div style={{
      background: YES.navy, color: '#fff',
      padding: '12px 16px', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
    }}>
      <button onClick={onClose} style={{
        background: 'none', border: 'none', color: '#fff', cursor: 'pointer', padding: 6,
        display: 'flex', alignItems: 'center'
      }}>
        <X size={22} />
      </button>
      <h2 style={{ fontSize: 16, fontWeight: 700, margin: 0 }}>{title}</h2>
      <button onClick={onSave} style={{
        background: YES.gold, border: 'none', color: '#fff', cursor: 'pointer',
        padding: '6px 14px', borderRadius: 6, fontWeight: 700, fontSize: 13,
        display: 'flex', alignItems: 'center', gap: 4
      }}>
        <Save size={14} /> {saveLabel}
      </button>
    </div>
    <div style={{ flex: 1, overflowY: 'auto', padding: 16 }}>
      {children}
      <div style={{ height: 24 }} />
    </div>
  </div>
);

// ============================================================
// SCREEN — AFFAIRE DETAIL
// ============================================================
const AffaireDetailScreen = ({ affaire, setScreen, updateAffaire, deleteAffaire }) => {
  const [tab, setTab] = useState('synthese');
  const calc = calcAffaire(affaire);

  const tabs = [
    { id: 'synthese',  label: 'Synthèse',   icon: PieChart },
    { id: 'ventes',    label: 'Ventes',     icon: Euro },
    { id: 'mo',        label: 'M.O.',       icon: Users },
    { id: 'situation', label: 'Situation',  icon: ClipboardList },
    { id: 'marge',     label: 'Marge',      icon: TrendingUp },
  ];

  return (
    <div style={{ minHeight: '100vh', background: YES.bg }}>
      {/* Header */}
      <div style={{
        background: YES.navy, color: '#fff', padding: '12px 16px 18px 16px',
        boxShadow: '0 2px 8px rgba(0,0,0,0.06)'
      }}>
        <button
          onClick={() => setScreen({ name: 'affaires' })}
          style={{
            background: 'none', border: 'none', color: '#fff',
            display: 'flex', alignItems: 'center', gap: 4,
            padding: '4px 0', marginBottom: 10, cursor: 'pointer', fontSize: 13
          }}
        >
          <ChevronLeft size={18} /> Affaires
        </button>
        <div style={{ fontSize: 10, color: '#B8C5D9', fontWeight: 700, letterSpacing: 1, marginBottom: 4 }}>
          {affaire.ref} · INDICE {affaire.indice}
        </div>
        <h2 style={{ fontSize: 20, fontWeight: 700, margin: 0, lineHeight: 1.3 }}>
          {affaire.nom}
        </h2>
        <div style={{ fontSize: 13, color: '#B8C5D9', marginTop: 4 }}>
          {affaire.lot}
        </div>
      </div>

      {/* Tabs */}
      <div style={{
        display: 'flex', overflowX: 'auto', background: '#fff',
        borderBottom: `1px solid ${YES.border}`, position: 'sticky', top: 0, zIndex: 10,
        WebkitOverflowScrolling: 'touch', scrollbarWidth: 'none'
      }}>
        {tabs.map(t => (
          <button
            key={t.id}
            onClick={() => setTab(t.id)}
            style={{
              flex: '0 0 auto', padding: '12px 18px',
              background: 'none', border: 'none',
              fontSize: 13, fontWeight: 600,
              color: tab === t.id ? YES.navy : YES.textMuted,
              borderBottom: tab === t.id ? `2.5px solid ${YES.gold}` : '2.5px solid transparent',
              cursor: 'pointer',
              display: 'flex', alignItems: 'center', gap: 6,
              whiteSpace: 'nowrap', transition: 'all 0.15s'
            }}
          >
            <t.icon size={14} />
            {t.label}
          </button>
        ))}
      </div>

      <div style={{ padding: 16 }}>
        {tab === 'synthese' && <SyntheseTab affaire={affaire} calc={calc} updateAffaire={updateAffaire} deleteAffaire={deleteAffaire} setScreen={setScreen} />}
        {tab === 'ventes' && <VentesTab affaire={affaire} updateAffaire={updateAffaire} />}
        {tab === 'mo' && <MOTab affaire={affaire} updateAffaire={updateAffaire} />}
        {tab === 'situation' && <SituationTab affaire={affaire} updateAffaire={updateAffaire} />}
        {tab === 'marge' && <MargeTab affaire={affaire} calc={calc} />}
      </div>

      <div style={{ height: 90 }} />
    </div>
  );
};

// ============================================================
// TABS DE L'AFFAIRE
// ============================================================
const SyntheseTab = ({ affaire, calc, updateAffaire, deleteAffaire, setScreen }) => {
  const [confirmDelete, setConfirmDelete] = useState(false);

  return (
    <div>
      {/* KPIs */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 10 }}>
        <Stat label="CA HT" value={fmtEur(calc.venteTotal)} icon={Euro} color={YES.navy} />
        <Stat label="Marge brute" value={fmtEur(calc.marge)} icon={TrendingUp}
              color={calc.marge > 0 ? YES.green : YES.red} />
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 20 }}>
        <Stat label="Tx marge" value={fmtPct(calc.txMarge)} icon={Activity}
              color={calc.txMarge > 0.1 ? YES.green : YES.gold} />
        <Stat label="Avancement" value={fmtPct(calc.pctAvanc)} icon={Clock} color={YES.blue} />
      </div>

      {/* Infos */}
      <SectionTitle>Informations</SectionTitle>
      <Card>
        <InfoLine icon={Building2} label="Client" value={affaire.client} />
        <InfoLine icon={Building2} label="MOA" value={affaire.moa} />
        <InfoLine icon={Briefcase} label="MOE" value={affaire.moe} />
        <InfoLine icon={MapPin} label="Adresse" value={affaire.adresse} />
        <InfoLine icon={User} label="Responsable" value={affaire.responsable} />
        <InfoLine icon={Calendar} label="Date devis" value={fmtDate(affaire.dateDevis)} />
        <InfoLine icon={Clock} label="Délai" value={`${affaire.delaiMois} mois`} />
      </Card>

      {/* Réserves */}
      {affaire.reserves && affaire.reserves.length > 0 && (
        <>
          <SectionTitle>Réserves contractuelles</SectionTitle>
          {affaire.reserves.map(r => (
            <Card key={r.code} style={{ marginBottom: 8 }}>
              <div style={{ display: 'flex', alignItems: 'flex-start', gap: 12 }}>
                <div style={{
                  background: YES.lgold, color: '#8B6914', fontWeight: 700,
                  padding: '4px 8px', borderRadius: 6, fontSize: 12, minWidth: 32, textAlign: 'center'
                }}>
                  {r.code}
                </div>
                <div style={{ flex: 1, fontSize: 13, color: YES.text, lineHeight: 1.4 }}>
                  {r.titre}
                </div>
                {r.actif && <CheckCircle2 size={16} color={YES.green} />}
              </div>
            </Card>
          ))}
        </>
      )}

      {/* Actions */}
      <SectionTitle>Actions</SectionTitle>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        <Button icon={Mail} variant="primary" fullWidth onClick={() => setScreen({ name: 'courriers', preselectAffaire: affaire.id })}>
          Générer un courrier client
        </Button>
        <Button icon={Package} variant="secondary" fullWidth onClick={() => setScreen({ name: 'ddps', preselectAffaire: affaire.id })}>
          Voir les DDP de cette affaire
        </Button>
        <Button icon={Trash2} variant="danger" fullWidth onClick={() => setConfirmDelete(true)}>
          Supprimer cette affaire
        </Button>
      </div>

      {confirmDelete && (
        <ConfirmModal
          message={`Supprimer définitivement "${affaire.nom}" ?`}
          onConfirm={() => { deleteAffaire(affaire.id); setScreen({ name: 'affaires' }); }}
          onCancel={() => setConfirmDelete(false)}
        />
      )}
    </div>
  );
};

const InfoLine = ({ icon: Icon, label, value }) => (
  <div style={{
    display: 'flex', alignItems: 'center', gap: 10,
    padding: '8px 0', borderBottom: `1px solid ${YES.bg}`
  }}>
    <Icon size={14} color={YES.textMuted} />
    <div style={{ flex: 1, fontSize: 11, color: YES.textMuted, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5 }}>
      {label}
    </div>
    <div style={{ fontSize: 13, color: YES.text, fontWeight: 500, textAlign: 'right', maxWidth: '60%' }}>
      {value || '—'}
    </div>
  </div>
);

const VentesTab = ({ affaire, updateAffaire }) => {
  const [editing, setEditing] = useState(null);

  const updateVente = (k, v) => {
    updateAffaire({ ...affaire, ventes: { ...affaire.ventes, [k]: v } });
  };

  const total = (affaire.ventes.A || 0) + (affaire.ventes.B || 0) + (affaire.ventes.C || 0) + (affaire.ventes.D || 0);

  return (
    <div>
      <div style={{
        background: YES.navy, color: '#fff', padding: 16, borderRadius: 12, marginBottom: 16,
        textAlign: 'center'
      }}>
        <div style={{ fontSize: 11, color: '#B8C5D9', fontWeight: 600, letterSpacing: 1, textTransform: 'uppercase' }}>
          Total ventes HT
        </div>
        <div style={{ fontSize: 32, fontWeight: 800, fontFamily: '"DM Mono", monospace', marginTop: 4 }}>
          {fmtEur(total)}
        </div>
      </div>

      <SectionTitle>Ventilation par poste</SectionTitle>
      {['A', 'B', 'C', 'D'].map(k => (
        <Card key={k} style={{ marginBottom: 10 }} onClick={() => setEditing(k)}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
            <div style={{
              background: YES.lblue, color: YES.navy, fontWeight: 700,
              width: 32, height: 32, borderRadius: 8, display: 'flex',
              alignItems: 'center', justifyContent: 'center', fontSize: 14
            }}>
              {k}
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 13, fontWeight: 600, color: YES.text }}>
                {affaire.postes[k]}
              </div>
              <div style={{ fontSize: 18, fontWeight: 800, color: YES.navy, fontFamily: '"DM Mono", monospace' }}>
                {fmtEur(affaire.ventes[k] || 0)}
              </div>
            </div>
            <Edit3 size={16} color={YES.textLight} />
          </div>
        </Card>
      ))}

      {editing && (
        <FullScreenModal
          title={`Modifier vente — Poste ${editing}`}
          onClose={() => setEditing(null)}
          onSave={() => setEditing(null)}
        >
          <Input
            label="Désignation du poste"
            value={affaire.postes[editing]}
            onChange={(v) => updateAffaire({ ...affaire, postes: { ...affaire.postes, [editing]: v } })}
          />
          <Input
            label="Montant vente HT (€)"
            type="number"
            value={affaire.ventes[editing]}
            onChange={(v) => updateVente(editing, v)}
          />
          <SectionTitle>Coûts cibles</SectionTitle>
          {['matiere', 'mo', 'st', 'frais'].map(cle => (
            <Input
              key={cle}
              label={`Coût ${cle === 'matiere' ? 'matière' : cle === 'mo' ? 'main d\'œuvre' : cle === 'st' ? 'sous-traitance' : 'frais chantier'} (€)`}
              type="number"
              value={(affaire.couts[editing] || {})[cle] || 0}
              onChange={(v) => updateAffaire({
                ...affaire,
                couts: { ...affaire.couts, [editing]: { ...(affaire.couts[editing] || {}), [cle]: v } }
              })}
            />
          ))}
        </FullScreenModal>
      )}
    </div>
  );
};

const MOTab = ({ affaire, updateAffaire }) => {
  const heures = affaire.mo?.heures || {};
  const semaines = Array.from({ length: 25 }, (_, i) => `S${i}`);
  const total = semaines.reduce((s, k) => s + (heures[k] || 0), 0);
  const tx = affaire.mo?.taux || 45;
  const cout = total * tx;
  const cibleH = ['A', 'B', 'C', 'D'].reduce((s, k) => s + ((affaire.couts[k] || {}).mo || 0) / tx, 0);

  return (
    <div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 16 }}>
        <Stat label="Heures saisies" value={total.toFixed(0)} unit="h" icon={Clock} color={YES.navy} />
        <Stat label="Cible" value={cibleH.toFixed(0)} unit="h" icon={TrendingUp} color={YES.gold} />
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 16 }}>
        <Stat label="Coût MO" value={fmtEur(cout)} icon={Euro} color={YES.navy} />
        <Stat label="Tx horaire" value={tx + ' €'} icon={Euro} color={YES.textMuted} />
      </div>

      <SectionTitle>Saisie heures par semaine</SectionTitle>
      <Card>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
          {semaines.map(s => (
            <div key={s} style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <div style={{
                width: 36, fontSize: 12, fontWeight: 700, color: YES.navy,
                background: YES.lblue, borderRadius: 4, padding: '3px 0', textAlign: 'center'
              }}>
                {s}
              </div>
              <input
                type="number"
                value={heures[s] || ''}
                onChange={(e) => {
                  const v = parseFloat(e.target.value) || 0;
                  updateAffaire({
                    ...affaire,
                    mo: { ...(affaire.mo || {}), heures: { ...heures, [s]: v }, taux: tx }
                  });
                }}
                style={{
                  flex: 1, padding: '6px 8px', fontSize: 13,
                  border: `1px solid ${YES.border}`, borderRadius: 6,
                  fontFamily: '"DM Mono", monospace', minWidth: 0
                }}
                placeholder="0"
              />
            </div>
          ))}
        </div>
      </Card>
    </div>
  );
};

const SituationTab = ({ affaire, updateAffaire }) => {
  const setAvanc = (k, v) => {
    updateAffaire({
      ...affaire,
      avancement: { ...affaire.avancement, [k]: Math.max(0, Math.min(1, v / 100)) }
    });
  };

  const venteTotal = ['A', 'B', 'C', 'D'].reduce((s, k) => s + (affaire.ventes[k] || 0), 0);
  const cumul = ['A', 'B', 'C', 'D'].reduce((s, k) => s + (affaire.ventes[k] || 0) * (affaire.avancement[k] || 0), 0);
  const periode = cumul - (affaire.factureCumul || 0);

  return (
    <div>
      <div style={{
        background: YES.navy, color: '#fff', padding: 16, borderRadius: 12, marginBottom: 16
      }}>
        <div style={{ fontSize: 11, color: '#B8C5D9', fontWeight: 600, letterSpacing: 1, textTransform: 'uppercase' }}>
          Montant période à facturer
        </div>
        <div style={{ fontSize: 30, fontWeight: 800, fontFamily: '"DM Mono", monospace', marginTop: 4 }}>
          {fmtEur(periode)}
        </div>
        <div style={{ fontSize: 11, color: '#B8C5D9', marginTop: 8 }}>
          Cumul situation : {fmtEur(cumul)} / {fmtEur(venteTotal)}
        </div>
      </div>

      <SectionTitle>Avancement par poste</SectionTitle>
      {['A', 'B', 'C', 'D'].map(k => {
        const pct = (affaire.avancement[k] || 0) * 100;
        const mt = (affaire.ventes[k] || 0) * (affaire.avancement[k] || 0);
        return (
          <Card key={k} style={{ marginBottom: 10 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
              <div style={{ fontSize: 13, fontWeight: 700, color: YES.navy }}>
                Poste {k} · {affaire.postes[k]}
              </div>
              <div style={{ fontSize: 14, fontWeight: 700, color: YES.gold, fontFamily: '"DM Mono", monospace' }}>
                {pct.toFixed(0)}%
              </div>
            </div>
            <input
              type="range" min="0" max="100" step="5"
              value={pct}
              onChange={(e) => setAvanc(k, parseFloat(e.target.value))}
              style={{ width: '100%', accentColor: YES.gold }}
            />
            <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 6, fontSize: 11, color: YES.textMuted }}>
              <span>Vente : {fmtEur(affaire.ventes[k] || 0)}</span>
              <span style={{ fontWeight: 700, color: YES.navy }}>Avancé : {fmtEur(mt)}</span>
            </div>
          </Card>
        );
      })}

      <SectionTitle>Cumul facturé</SectionTitle>
      <Card>
        <Input
          label="Cumul facturé à date (€)"
          type="number"
          value={affaire.factureCumul || 0}
          onChange={(v) => updateAffaire({ ...affaire, factureCumul: v })}
        />
      </Card>
    </div>
  );
};

const MargeTab = ({ affaire, calc }) => {
  return (
    <div>
      <div style={{
        background: calc.marge > 0 ? YES.green : YES.red,
        color: '#fff', padding: 16, borderRadius: 12, marginBottom: 16, textAlign: 'center'
      }}>
        <div style={{ fontSize: 11, opacity: 0.9, fontWeight: 600, letterSpacing: 1, textTransform: 'uppercase' }}>
          Marge brute prévisionnelle
        </div>
        <div style={{ fontSize: 32, fontWeight: 800, fontFamily: '"DM Mono", monospace', marginTop: 4 }}>
          {fmtEur(calc.marge)}
        </div>
        <div style={{ fontSize: 16, fontWeight: 600, marginTop: 4 }}>
          {fmtPct(calc.txMarge)}
        </div>
      </div>

      <SectionTitle>Décomposition par poste</SectionTitle>
      {['A', 'B', 'C', 'D'].map(k => {
        const v = affaire.ventes[k] || 0;
        const c = affaire.couts[k] || {};
        const coutTot = (c.matiere || 0) + (c.mo || 0) + (c.st || 0) + (c.frais || 0);
        const m = v - coutTot;
        const t = v > 0 ? m / v : 0;
        return (
          <Card key={k} style={{ marginBottom: 10 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
              <div style={{ fontSize: 13, fontWeight: 700, color: YES.navy }}>
                Poste {k}
              </div>
              <Pill color={t > 0.1 ? 'green' : t > 0 ? 'gold' : 'red'}>{fmtPct(t)}</Pill>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6, fontSize: 12 }}>
              <div style={{ color: YES.textMuted }}>Vente HT</div>
              <div style={{ textAlign: 'right', fontWeight: 600, fontFamily: '"DM Mono", monospace' }}>{fmtEur(v)}</div>
              <div style={{ color: YES.textMuted }}>Coût total</div>
              <div style={{ textAlign: 'right', fontFamily: '"DM Mono", monospace' }}>{fmtEur(coutTot)}</div>
              <div style={{ color: YES.textMuted, fontWeight: 700 }}>Marge</div>
              <div style={{ textAlign: 'right', fontWeight: 700, color: m > 0 ? YES.green : YES.red, fontFamily: '"DM Mono", monospace' }}>
                {fmtEur(m)}
              </div>
            </div>
          </Card>
        );
      })}

      {/* Alerte marge */}
      {calc.txMarge < 0.1 && (
        <Card style={{ borderLeft: `4px solid ${YES.red}`, marginTop: 16 }}>
          <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>
            <AlertCircle size={18} color={YES.red} style={{ flexShrink: 0, marginTop: 1 }} />
            <div style={{ fontSize: 12, lineHeight: 1.5 }}>
              <div style={{ fontWeight: 700, color: YES.red, marginBottom: 4 }}>Marge sous tension</div>
              <div style={{ color: YES.text }}>
                Tx marge {'<'} 10 % — la marge n'absorbe plus les aléas. Toute dérive coût = perte directe.
                Levier : négocier -3 à -5 % fournisseurs + tenir budget heures MO.
              </div>
            </div>
          </div>
        </Card>
      )}
    </div>
  );
};

// ============================================================
// SCREEN — DDPs
// ============================================================
const DDPsListScreen = ({ ddps, affaires, setScreen, setDdps, preselectAffaire }) => {
  const [search, setSearch] = useState('');
  const [filter, setFilter] = useState('all');
  const [showForm, setShowForm] = useState(false);

  let filtered = ddps;
  if (preselectAffaire) filtered = filtered.filter(d => d.affaireId === preselectAffaire);
  if (filter !== 'all') filtered = filtered.filter(d => d.statut === filter);
  if (search) filtered = filtered.filter(d =>
    d.fournisseur.toLowerCase().includes(search.toLowerCase()) ||
    d.ref.toLowerCase().includes(search.toLowerCase())
  );

  const statuts = ['all', 'À envoyer', 'Envoyée', 'Reçue', 'Engagée'];

  return (
    <div style={{ padding: 16 }}>
      <h1 style={{
        fontSize: 28, fontWeight: 800, color: YES.navy, margin: '8px 0 16px 0',
        fontFamily: '"DM Sans", system-ui, sans-serif', letterSpacing: -0.5
      }}>
        Demandes de prix
      </h1>

      <div style={{ position: 'relative', marginBottom: 12 }}>
        <Search size={16} style={{
          position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)',
          color: YES.textLight
        }} />
        <input
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          placeholder="Rechercher fournisseur..."
          style={{
            width: '100%', padding: '11px 12px 11px 36px', fontSize: 14,
            border: `1px solid ${YES.border}`, borderRadius: 8,
            background: '#fff', boxSizing: 'border-box'
          }}
        />
      </div>

      <div style={{ display: 'flex', gap: 6, marginBottom: 16, overflowX: 'auto', scrollbarWidth: 'none' }}>
        {statuts.map(s => (
          <button
            key={s}
            onClick={() => setFilter(s)}
            style={{
              padding: '6px 12px', fontSize: 12, fontWeight: 600,
              border: `1px solid ${filter === s ? YES.navy : YES.border}`,
              background: filter === s ? YES.navy : '#fff',
              color: filter === s ? '#fff' : YES.text,
              borderRadius: 16, cursor: 'pointer', whiteSpace: 'nowrap'
            }}
          >
            {s === 'all' ? 'Tous' : s}
          </button>
        ))}
      </div>

      <Button icon={Plus} variant="gold" fullWidth onClick={() => setShowForm(true)} style={{ marginBottom: 16 }}>
        Nouvelle DDP
      </Button>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {filtered.map(d => {
          const aff = affaires.find(a => a.id === d.affaireId);
          const total = d.lignes.reduce((s, l) => s + (l.qte || 0) * (l.pu || 0), 0);
          return (
            <Card key={d.id} onClick={() => setScreen({ name: 'ddp', id: d.id })}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 10, color: YES.textMuted, fontWeight: 700, letterSpacing: 0.5 }}>
                    {d.ref}
                  </div>
                  <div style={{ fontSize: 16, fontWeight: 700, color: YES.navy, margin: '2px 0' }}>
                    {d.fournisseur}
                  </div>
                  <div style={{ fontSize: 12, color: YES.textMuted }}>{d.poste}</div>
                  {aff && (
                    <div style={{ fontSize: 11, color: YES.textLight, marginTop: 4 }}>
                      📂 {aff.nom}
                    </div>
                  )}
                </div>
                <Pill color={d.statut === 'À envoyer' ? 'gold' : d.statut === 'Envoyée' ? 'blue' : 'green'}>
                  {d.statut}
                </Pill>
              </div>
              <div style={{
                marginTop: 10, paddingTop: 10, borderTop: `1px solid ${YES.border}`,
                display: 'flex', justifyContent: 'space-between', alignItems: 'center'
              }}>
                <div style={{ fontSize: 11, color: YES.textMuted }}>
                  {d.lignes.length} ligne{d.lignes.length > 1 ? 's' : ''} ·
                  {total > 0 ? ` ${fmtEur(total)}` : ` est. ${fmtEur(d.montantEstime)}`}
                </div>
                <ChevronRight size={16} color={YES.textLight} />
              </div>
            </Card>
          );
        })}
      </div>

      {showForm && (
        <NewDDPModal
          affaires={affaires}
          preselectAffaire={preselectAffaire}
          onClose={() => setShowForm(false)}
          onSave={(d) => {
            setDdps([...ddps, d]);
            setShowForm(false);
            setScreen({ name: 'ddp', id: d.id });
          }}
        />
      )}

      <div style={{ height: 90 }} />
    </div>
  );
};

const NewDDPModal = ({ affaires, preselectAffaire, onClose, onSave }) => {
  const [form, setForm] = useState({
    ref: '', fournisseur: '', contactFournisseur: '', emailFournisseur: '',
    poste: '', montantEstime: 0, affaireId: preselectAffaire || affaires[0]?.id || ''
  });
  const upd = (k) => (v) => setForm({ ...form, [k]: v });

  const save = () => {
    if (!form.fournisseur || !form.affaireId) return;
    onSave({
      id: newId(),
      ...form,
      statut: 'À envoyer',
      dateEnvoi: null,
      dateRetour: null,
      lignes: []
    });
  };

  return (
    <FullScreenModal title="Nouvelle DDP" onClose={onClose} onSave={save}>
      <div style={{ marginBottom: 14 }}>
        <label style={{
          display: 'block', fontSize: 12, fontWeight: 600,
          color: YES.textMuted, marginBottom: 6
        }}>
          Affaire <span style={{ color: YES.red }}>*</span>
        </label>
        <select
          value={form.affaireId}
          onChange={(e) => upd('affaireId')(e.target.value)}
          style={{
            width: '100%', padding: '11px 12px', fontSize: 14,
            border: `1px solid ${YES.border}`, borderRadius: 8,
            background: '#FAFBFC', boxSizing: 'border-box'
          }}
        >
          {affaires.map(a => <option key={a.id} value={a.id}>{a.nom}</option>)}
        </select>
      </div>
      <Input label="Référence DDP" required value={form.ref} onChange={upd('ref')} placeholder="YES-DDP-..." />
      <Input label="Fournisseur" required value={form.fournisseur} onChange={upd('fournisseur')} />
      <Input label="Poste rattaché" value={form.poste} onChange={upd('poste')} placeholder="Poste B — Chauffage" />
      <Input label="Contact fournisseur" value={form.contactFournisseur} onChange={upd('contactFournisseur')} />
      <Input label="Email fournisseur" type="email" value={form.emailFournisseur} onChange={upd('emailFournisseur')} />
      <Input label="Montant estimé (€)" type="number" value={form.montantEstime} onChange={upd('montantEstime')} />
    </FullScreenModal>
  );
};

// ============================================================
// SCREEN — DDP DETAIL
// ============================================================
const DDPDetailScreen = ({ ddp, affaires, setScreen, updateDdp, deleteDdp }) => {
  const aff = affaires.find(a => a.id === ddp.affaireId);
  const [showLigne, setShowLigne] = useState(null);
  const [showSendModal, setShowSendModal] = useState(false);
  const [confirmDelete, setConfirmDelete] = useState(false);
  const total = ddp.lignes.reduce((s, l) => s + (l.qte || 0) * (l.pu || 0), 0);

  const addLigne = () => setShowLigne({ ref: '', designation: '', unite: 'u', qte: 1, pu: 0, _new: true });

  return (
    <div style={{ minHeight: '100vh', background: YES.bg }}>
      <div style={{
        background: YES.navy, color: '#fff', padding: '12px 16px 18px 16px'
      }}>
        <button
          onClick={() => setScreen({ name: 'ddps' })}
          style={{
            background: 'none', border: 'none', color: '#fff',
            display: 'flex', alignItems: 'center', gap: 4,
            padding: '4px 0', marginBottom: 10, cursor: 'pointer', fontSize: 13
          }}
        >
          <ChevronLeft size={18} /> DDP
        </button>
        <div style={{ fontSize: 10, color: '#B8C5D9', fontWeight: 700, letterSpacing: 1, marginBottom: 4 }}>
          {ddp.ref}
        </div>
        <h2 style={{ fontSize: 20, fontWeight: 700, margin: 0 }}>{ddp.fournisseur}</h2>
        <div style={{ fontSize: 13, color: '#B8C5D9', marginTop: 4 }}>{ddp.poste}</div>
        {aff && <div style={{ fontSize: 12, color: '#B8C5D9', marginTop: 4 }}>📂 {aff.nom}</div>}
      </div>

      <div style={{ padding: 16 }}>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 16 }}>
          <Stat label="Lignes" value={ddp.lignes.length} icon={ClipboardList} />
          <Stat label="Total HT" value={fmtEur(total)} icon={Euro} color={YES.gold} />
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 16 }}>
          <Button icon={Mail} variant="primary" fullWidth onClick={() => setShowSendModal(true)}>
            Envoyer DDP
          </Button>
          <Button icon={Plus} variant="gold" fullWidth onClick={addLigne}>
            Ligne
          </Button>
        </div>

        <SectionTitle>Statut</SectionTitle>
        <Card>
          {['À envoyer', 'Envoyée', 'Reçue', 'Engagée'].map(s => (
            <button
              key={s}
              onClick={() => updateDdp({ ...ddp, statut: s, dateEnvoi: s === 'Envoyée' && !ddp.dateEnvoi ? todayISO() : ddp.dateEnvoi })}
              style={{
                width: '100%', padding: 12, background: 'none',
                border: 'none', borderBottom: `1px solid ${YES.bg}`,
                display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                cursor: 'pointer', fontSize: 14, fontWeight: 500,
                color: ddp.statut === s ? YES.navy : YES.textMuted
              }}
            >
              <span>{s}</span>
              {ddp.statut === s && <CheckCircle2 size={18} color={YES.gold} />}
            </button>
          ))}
        </Card>

        <SectionTitle action={
          <button onClick={addLigne} style={{
            background: 'none', border: 'none', color: YES.gold,
            fontSize: 11, fontWeight: 700, cursor: 'pointer'
          }}>+ Ajouter</button>
        }>
          Bordereau ({ddp.lignes.length})
        </SectionTitle>

        {ddp.lignes.map((l, idx) => (
          <Card key={idx} style={{ marginBottom: 8 }} onClick={() => setShowLigne({ ...l, _idx: idx })}>
            <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>
              <div style={{
                background: YES.lblue, color: YES.navy, fontWeight: 700,
                padding: '3px 7px', borderRadius: 5, fontSize: 11, flexShrink: 0
              }}>
                {l.ref || `L${idx + 1}`}
              </div>
              <div style={{ flex: 1, fontSize: 12, color: YES.text, lineHeight: 1.4 }}>
                {l.designation}
              </div>
            </div>
            <div style={{
              display: 'flex', justifyContent: 'space-between', marginTop: 8,
              paddingTop: 8, borderTop: `1px solid ${YES.bg}`, fontSize: 12
            }}>
              <span style={{ color: YES.textMuted }}>{l.qte} {l.unite} × {fmtEur2(l.pu)}</span>
              <span style={{ fontWeight: 700, color: YES.navy, fontFamily: '"DM Mono", monospace' }}>
                {fmtEur2((l.qte || 0) * (l.pu || 0))}
              </span>
            </div>
          </Card>
        ))}

        {ddp.lignes.length === 0 && (
          <Card>
            <div style={{ textAlign: 'center', padding: 20, color: YES.textMuted }}>
              <Package size={32} color={YES.textLight} style={{ margin: '0 auto 8px' }} />
              <div style={{ fontSize: 13 }}>Aucune ligne</div>
              <div style={{ fontSize: 11, marginTop: 4 }}>Ajoutez les références à chiffrer</div>
            </div>
          </Card>
        )}

        <Button icon={Trash2} variant="danger" fullWidth style={{ marginTop: 24 }} onClick={() => setConfirmDelete(true)}>
          Supprimer la DDP
        </Button>

        <div style={{ height: 90 }} />
      </div>

      {showLigne && (
        <LigneModal
          ligne={showLigne}
          onClose={() => setShowLigne(null)}
          onSave={(l) => {
            const newLignes = [...ddp.lignes];
            if (showLigne._new) {
              const { _new, ...clean } = l;
              newLignes.push(clean);
            } else {
              const { _idx, ...clean } = l;
              newLignes[showLigne._idx] = clean;
            }
            updateDdp({ ...ddp, lignes: newLignes });
            setShowLigne(null);
          }}
          onDelete={!showLigne._new ? () => {
            const newLignes = ddp.lignes.filter((_, i) => i !== showLigne._idx);
            updateDdp({ ...ddp, lignes: newLignes });
            setShowLigne(null);
          } : null}
        />
      )}

      {showSendModal && (
        <SendDDPModal ddp={ddp} affaire={aff} onClose={() => setShowSendModal(false)} />
      )}

      {confirmDelete && (
        <ConfirmModal
          message={`Supprimer définitivement la DDP "${ddp.fournisseur}" ?`}
          onConfirm={() => { deleteDdp(ddp.id); setScreen({ name: 'ddps' }); }}
          onCancel={() => setConfirmDelete(false)}
        />
      )}
    </div>
  );
};

const LigneModal = ({ ligne, onClose, onSave, onDelete }) => {
  const [form, setForm] = useState(ligne);
  const upd = (k) => (v) => setForm({ ...form, [k]: v });
  return (
    <FullScreenModal
      title={ligne._new ? 'Nouvelle ligne' : 'Modifier ligne'}
      onClose={onClose}
      onSave={() => onSave(form)}
    >
      <Input label="Référence" value={form.ref} onChange={upd('ref')} placeholder="B.1.2" />
      <Input label="Désignation technique" multiline rows={6}
             value={form.designation} onChange={upd('designation')}
             placeholder="Marque + Modèle + Caractéristiques + Normes + Accessoires inclus..." />
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <Input label="Unité" value={form.unite} onChange={upd('unite')} placeholder="u, ml, ens" />
        <Input label="Quantité" type="number" value={form.qte} onChange={upd('qte')} />
      </div>
      <Input label="Prix unitaire HT (€)" type="number" value={form.pu} onChange={upd('pu')} />
      {onDelete && (
        <Button icon={Trash2} variant="danger" fullWidth style={{ marginTop: 20 }} onClick={onDelete}>
          Supprimer cette ligne
        </Button>
      )}
    </FullScreenModal>
  );
};

const SendDDPModal = ({ ddp, affaire, onClose }) => {
  const [email, setEmail] = useState(ddp.emailFournisseur || '');
  const objet = `Demande de prix — ${affaire ? affaire.nom : 'Affaire'} — ${ddp.fournisseur}`;
  const corps =
`Madame, Monsieur,

Yang Énergie Services / Groupyang intervient en qualité de sous-traitant CVC/Plomberie/VMC sur l'opération ${affaire ? affaire.nom : ''} (${affaire ? affaire.adresse : ''}), sous maîtrise d'ouvrage ${affaire ? affaire.moa : ''} et donneur d'ordre ${affaire ? affaire.client : ''}.

Dans le cadre de la phase études EXE, nous vous prions de nous adresser votre meilleure offre pour la fourniture des produits suivants :

${ddp.lignes.map((l, i) => `${i + 1}. [${l.ref}] ${l.designation}\n   Quantité : ${l.qte} ${l.unite}`).join('\n\n')}

Conditions de retour :
• Délai de réponse : 15 jours calendaires
• Validité minimale : 3 mois ferme
• Règlement : virement 30 jours date de facture
• Livraison franco chantier
• Équivalences justifiées techniquement

Documents attendus : fiches techniques, DOP, attestations conformité, garanties.

Pour toute précision : 06 26 02 67 71 / 01 48 21 19 84.

Salutations distinguées,

Yacoub GUIDILEYE — Directeur
Yang Énergie Services / Groupyang
yacoub.guidileye@groupyang.fr`;

  const mailto = () => {
    const url = `mailto:${email}?subject=${encodeURIComponent(objet)}&body=${encodeURIComponent(corps)}`;
    window.location.href = url;
  };

  const copy = () => {
    navigator.clipboard?.writeText(corps);
    alert('Corps du mail copié dans le presse-papier');
  };

  return (
    <FullScreenModal title="Envoyer la DDP" onClose={onClose} onSave={mailto} saveLabel="Envoyer">
      <Input label="Email du destinataire" type="email" value={email} onChange={setEmail} placeholder="contact@fournisseur.fr" />
      <SectionTitle>Aperçu</SectionTitle>
      <Card>
        <div style={{ fontSize: 11, color: YES.textMuted, fontWeight: 600 }}>Objet</div>
        <div style={{ fontSize: 13, fontWeight: 600, color: YES.navy, marginBottom: 12 }}>{objet}</div>
        <div style={{ fontSize: 11, color: YES.textMuted, fontWeight: 600 }}>Corps</div>
        <div style={{
          fontSize: 12, color: YES.text, whiteSpace: 'pre-wrap', lineHeight: 1.5,
          marginTop: 4, maxHeight: 300, overflowY: 'auto'
        }}>
          {corps}
        </div>
      </Card>
      <Button icon={Copy} variant="secondary" fullWidth style={{ marginTop: 12 }} onClick={copy}>
        Copier le corps du mail
      </Button>
    </FullScreenModal>
  );
};

// ============================================================
// SCREEN — COURRIERS
// ============================================================
const CourriersScreen = ({ courriers, affaires, ddps, setCourriers, preselectAffaire }) => {
  const [active, setActive] = useState(null);
  const [filledData, setFilledData] = useState({});

  if (active) {
    return <CourrierEditor
      template={active}
      affaires={affaires}
      preselectAffaire={preselectAffaire}
      onClose={() => setActive(null)}
    />;
  }

  return (
    <div style={{ padding: 16 }}>
      <h1 style={{
        fontSize: 28, fontWeight: 800, color: YES.navy, margin: '8px 0 16px 0',
        fontFamily: '"DM Sans", system-ui, sans-serif', letterSpacing: -0.5
      }}>
        Courriers types
      </h1>

      <SectionTitle>Modèles disponibles</SectionTitle>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {courriers.map(c => (
          <Card key={c.id} onClick={() => setActive(c)}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
              <div style={{
                width: 44, height: 44, borderRadius: 10,
                background: YES.lblue, display: 'flex', alignItems: 'center', justifyContent: 'center'
              }}>
                <Mail size={22} color={YES.navy} />
              </div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 14, fontWeight: 700, color: YES.navy }}>{c.nom}</div>
                <div style={{ fontSize: 11, color: YES.textMuted, marginTop: 2 }}>
                  Type · {c.type}
                </div>
              </div>
              <ChevronRight size={18} color={YES.textLight} />
            </div>
          </Card>
        ))}
      </div>

      <div style={{ height: 90 }} />
    </div>
  );
};

const CourrierEditor = ({ template, affaires, preselectAffaire, onClose }) => {
  const [affaireId, setAffaireId] = useState(preselectAffaire || affaires[0]?.id || '');
  const aff = affaires.find(a => a.id === affaireId);
  const calc = aff ? calcAffaire(aff) : { venteTotal: 0 };

  const placeholders = {
    AFFAIRE: aff?.nom || '',
    REF: aff?.ref || '',
    INDICE: aff?.indice || '',
    LIEU: aff?.adresse || '',
    MOA: aff?.moa || '',
    CLIENT: aff?.client || '',
    LOT: aff?.lot || '',
    DATE: aff?.dateDevis ? fmtDate(aff.dateDevis) : todayISO(),
    DELAI: (aff?.delaiMois || '') + '',
    MONTANT: fmtEur2(calc.venteTotal),
    MOTIF: '[À COMPLÉTER : motif]',
    ARTICLES: '[À COMPLÉTER : articles CCTP]',
    RESERVES: '[R1/R2/R4]',
    JUSTIFICATION: '[À COMPLÉTER : justification technique]',
    NUM_SIT: '[N° situation]',
    MONTANT_PERIODE: '[Montant période]',
    CUMUL: '[Cumul]',
  };

  let objet = template.objet;
  let corps = template.corps;
  Object.entries(placeholders).forEach(([k, v]) => {
    objet = objet.replaceAll(`{{${k}}}`, v);
    corps = corps.replaceAll(`{{${k}}}`, v);
  });

  const copy = () => {
    const txt = `${objet}\n\n${corps}`;
    navigator.clipboard?.writeText(txt);
    alert('Courrier copié dans le presse-papier');
  };

  const send = () => {
    const url = `mailto:?subject=${encodeURIComponent(objet)}&body=${encodeURIComponent(corps)}`;
    window.location.href = url;
  };

  return (
    <div style={{ minHeight: '100vh', background: YES.bg }}>
      <div style={{
        background: YES.navy, color: '#fff', padding: '12px 16px',
        display: 'flex', alignItems: 'center', gap: 8
      }}>
        <button onClick={onClose} style={{
          background: 'none', border: 'none', color: '#fff', cursor: 'pointer',
          padding: 6, display: 'flex', alignItems: 'center'
        }}>
          <ChevronLeft size={22} />
        </button>
        <h2 style={{ fontSize: 16, fontWeight: 700, margin: 0, flex: 1 }}>{template.nom}</h2>
      </div>

      <div style={{ padding: 16 }}>
        <SectionTitle>Affaire à associer</SectionTitle>
        <Card>
          <select
            value={affaireId}
            onChange={(e) => setAffaireId(e.target.value)}
            style={{
              width: '100%', padding: '10px 12px', fontSize: 14,
              border: `1px solid ${YES.border}`, borderRadius: 8,
              background: '#fff', boxSizing: 'border-box'
            }}
          >
            <option value="">— Sans affaire —</option>
            {affaires.map(a => <option key={a.id} value={a.id}>{a.nom}</option>)}
          </select>
        </Card>

        <SectionTitle>Objet</SectionTitle>
        <Card>
          <div style={{ fontSize: 14, fontWeight: 600, color: YES.navy }}>{objet}</div>
        </Card>

        <SectionTitle>Corps du message</SectionTitle>
        <Card>
          <div style={{
            fontSize: 13, color: YES.text, whiteSpace: 'pre-wrap', lineHeight: 1.5
          }}>
            {corps}
          </div>
        </Card>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginTop: 20 }}>
          <Button icon={Copy} variant="secondary" onClick={copy}>Copier</Button>
          <Button icon={Send} variant="primary" onClick={send}>Envoyer</Button>
        </div>

        <div style={{ height: 90 }} />
      </div>
    </div>
  );
};

// ============================================================
// SCREEN — SETTINGS
// ============================================================
const SettingsScreen = ({ resetData }) => {
  const [confirm, setConfirm] = useState(false);

  return (
    <div style={{ padding: 16 }}>
      <h1 style={{
        fontSize: 28, fontWeight: 800, color: YES.navy, margin: '8px 0 16px 0',
        fontFamily: '"DM Sans", system-ui, sans-serif', letterSpacing: -0.5
      }}>
        Paramètres
      </h1>

      <SectionTitle>Profil</SectionTitle>
      <Card>
        <InfoLine icon={User} label="Nom" value="Yacoub GUIDILEYE" />
        <InfoLine icon={Briefcase} label="Fonction" value="Directeur" />
        <InfoLine icon={Building2} label="Société" value="Yang Énergie Services / Groupyang" />
        <InfoLine icon={MapPin} label="Adresse" value="14 rue des Frères Lumières, 77100 Meaux" />
        <InfoLine icon={Mail} label="Email perso" value="yacoub.guidileye@groupyang.fr" />
        <InfoLine icon={Mail} label="Email YES" value="yes@groupyang.fr" />
        <InfoLine icon={Phone} label="Mobile" value="06 26 02 67 71" />
        <InfoLine icon={Phone} label="Bureau" value="01 48 21 19 84" />
      </Card>

      <SectionTitle>Identifiants société</SectionTitle>
      <Card>
        <InfoLine label="SIRET" value="830 010 187" icon={Receipt} />
        <InfoLine label="TVA intra" value="FR27830010187" icon={Receipt} />
        <InfoLine label="APE" value="4322B" icon={Briefcase} />
        <InfoLine label="Capital social" value="15 000 €" icon={Banknote} />
        <InfoLine label="IBAN" value="FR76 1695 8000 0199 8104 6954 397" icon={Banknote} />
        <InfoLine label="BIC" value="QNTOFRP1XXX" icon={Banknote} />
      </Card>

      <SectionTitle>Données</SectionTitle>
      <Card>
        <div style={{ fontSize: 12, color: YES.textMuted, lineHeight: 1.5, marginBottom: 12 }}>
          Les données sont stockées localement sur l'appareil. Vous pouvez les réinitialiser
          pour repartir des données d'exemple Courbevoie.
        </div>
        <Button icon={Trash2} variant="danger" fullWidth onClick={() => setConfirm(true)}>
          Réinitialiser les données
        </Button>
      </Card>

      <SectionTitle>Application</SectionTitle>
      <Card>
        <div style={{ fontSize: 12, color: YES.textMuted, lineHeight: 1.6 }}>
          <strong style={{ color: YES.navy }}>YES Gestion Chantier v1.0</strong><br />
          Application mobile pour le suivi des affaires, demandes de prix et courriers types.<br />
          © 2026 Yang Énergie Services / Groupyang
        </div>
      </Card>

      {confirm && (
        <ConfirmModal
          message="Réinitialiser toutes les données ? Cette action est irréversible."
          onConfirm={() => { resetData(); setConfirm(false); }}
          onCancel={() => setConfirm(false)}
        />
      )}

      <div style={{ height: 90 }} />
    </div>
  );
};

const ConfirmModal = ({ message, onConfirm, onCancel }) => (
  <div style={{
    position: 'fixed', top: 0, left: 0, right: 0, bottom: 0,
    background: 'rgba(0,0,0,0.5)', zIndex: 2000,
    display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 24
  }}>
    <div style={{
      background: '#fff', borderRadius: 14, padding: 22,
      maxWidth: 400, width: '100%'
    }}>
      <div style={{
        width: 44, height: 44, borderRadius: 22, background: '#FEE2E2',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        margin: '0 auto 14px'
      }}>
        <AlertCircle size={22} color={YES.red} />
      </div>
      <div style={{ fontSize: 14, color: YES.text, textAlign: 'center', marginBottom: 18, lineHeight: 1.5 }}>
        {message}
      </div>
      <div style={{ display: 'flex', gap: 10 }}>
        <Button variant="secondary" fullWidth onClick={onCancel}>Annuler</Button>
        <Button variant="danger" fullWidth onClick={onConfirm}>Confirmer</Button>
      </div>
    </div>
  </div>
);

// ============================================================
// BOTTOM NAVIGATION
// ============================================================
const BottomNav = ({ screen, setScreen }) => {
  const items = [
    { id: 'home',     label: 'Accueil',   icon: Home },
    { id: 'affaires', label: 'Affaires',  icon: Briefcase },
    { id: 'ddps',     label: 'DDP',       icon: Package },
    { id: 'courriers',label: 'Courriers', icon: Mail },
    { id: 'settings', label: 'Réglages',  icon: Settings },
  ];
  return (
    <nav style={{
      position: 'fixed', bottom: 0, left: 0, right: 0,
      background: '#fff',
      borderTop: `1px solid ${YES.border}`,
      display: 'flex', justifyContent: 'space-around',
      paddingTop: 6, paddingBottom: 'max(6px, env(safe-area-inset-bottom))',
      zIndex: 100, boxShadow: '0 -2px 12px rgba(0,0,0,0.04)'
    }}>
      {items.map(it => {
        const active = screen.name === it.id ||
                       (it.id === 'affaires' && screen.name === 'affaire') ||
                       (it.id === 'ddps' && screen.name === 'ddp');
        return (
          <button
            key={it.id}
            onClick={() => setScreen({ name: it.id })}
            style={{
              flex: 1, background: 'none', border: 'none', cursor: 'pointer',
              padding: '6px 0', display: 'flex', flexDirection: 'column',
              alignItems: 'center', gap: 2,
              color: active ? YES.navy : YES.textMuted,
              WebkitTapHighlightColor: 'transparent',
              transition: 'color 0.15s'
            }}
          >
            <it.icon size={20} strokeWidth={active ? 2.4 : 1.8} />
            <span style={{ fontSize: 10, fontWeight: active ? 700 : 500 }}>{it.label}</span>
          </button>
        );
      })}
    </nav>
  );
};

// ============================================================
// MAIN APP
// ============================================================
function App() {
  const [loaded, setLoaded] = useState(false);
  const [screen, setScreen] = useState({ name: 'home' });
  const [affaires, setAffaires] = useState([]);
  const [ddps, setDdps] = useState([]);
  const [courriers, setCourriers] = useState(SEED_COURRIERS);

  // Load data
  useEffect(() => {
    (async () => {
      try {
        const a = await storage.get('app:affaires');
        const d = await storage.get('app:ddps');
        if (a) setAffaires(JSON.parse(a));
        else setAffaires([SEED_AFFAIRE]);
        if (d) setDdps(JSON.parse(d));
        else setDdps(SEED_DDP);
      } catch (e) {
        setAffaires([SEED_AFFAIRE]);
        setDdps(SEED_DDP);
      }
      setLoaded(true);
    })();
  }, []);

  // Persist affaires
  useEffect(() => {
    if (loaded) storage.set('app:affaires', JSON.stringify(affaires));
  }, [affaires, loaded]);

  // Persist ddps
  useEffect(() => {
    if (loaded) storage.set('app:ddps', JSON.stringify(ddps));
  }, [ddps, loaded]);

  const updateAffaire = (a) => {
    setAffaires(affaires.map(x => x.id === a.id ? a : x));
  };
  const deleteAffaire = (id) => {
    setAffaires(affaires.filter(a => a.id !== id));
  };
  const updateDdp = (d) => {
    setDdps(ddps.map(x => x.id === d.id ? d : x));
  };
  const deleteDdp = (id) => {
    setDdps(ddps.filter(d => d.id !== id));
  };
  const resetData = () => {
    setAffaires([SEED_AFFAIRE]);
    setDdps(SEED_DDP);
    setScreen({ name: 'home' });
  };

  if (!loaded) {
    return (
      <div style={{
        minHeight: '100vh', background: YES.navy, color: '#fff',
        display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column'
      }}>
        <div style={{ fontSize: 28, fontWeight: 800, marginBottom: 8, letterSpacing: -0.5 }}>YES</div>
        <div style={{ fontSize: 11, opacity: 0.7, letterSpacing: 2, textTransform: 'uppercase' }}>
          Gestion Chantier
        </div>
      </div>
    );
  }

  // Inject fonts + global styles
  return (
    <>
      <style>{`
        @import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500;700&display=swap');

        * { box-sizing: border-box; -webkit-font-smoothing: antialiased; }
        body { margin: 0; font-family: 'DM Sans', system-ui, -apple-system, sans-serif; }

        @keyframes slideUp {
          from { transform: translateY(100%); }
          to { transform: translateY(0); }
        }

        button { font-family: inherit; }
        input, select, textarea { font-family: inherit; }
        input:focus, select:focus, textarea:focus {
          outline: none; border-color: ${YES.navy} !important;
          box-shadow: 0 0 0 3px ${YES.lblue} !important;
        }

        ::-webkit-scrollbar { display: none; }
      `}</style>

      <div style={{
        minHeight: '100vh', background: YES.bg, color: YES.text,
        fontFamily: '"DM Sans", system-ui, sans-serif',
        maxWidth: 480, margin: '0 auto', position: 'relative',
        paddingBottom: 0
      }}>
        {screen.name === 'home' && <DashboardScreen affaires={affaires} ddps={ddps} setScreen={setScreen} />}
        {screen.name === 'affaires' && <AffairesListScreen affaires={affaires} setScreen={setScreen} setAffaires={setAffaires} />}
        {screen.name === 'affaire' && (() => {
          const a = affaires.find(x => x.id === screen.id);
          if (!a) return <div style={{ padding: 16 }}>Affaire introuvable</div>;
          return <AffaireDetailScreen affaire={a} setScreen={setScreen} updateAffaire={updateAffaire} deleteAffaire={deleteAffaire} />;
        })()}
        {screen.name === 'ddps' && <DDPsListScreen ddps={ddps} affaires={affaires} setScreen={setScreen} setDdps={setDdps} preselectAffaire={screen.preselectAffaire} />}
        {screen.name === 'ddp' && (() => {
          const d = ddps.find(x => x.id === screen.id);
          if (!d) return <div style={{ padding: 16 }}>DDP introuvable</div>;
          return <DDPDetailScreen ddp={d} affaires={affaires} setScreen={setScreen} updateDdp={updateDdp} deleteDdp={deleteDdp} />;
        })()}
        {screen.name === 'courriers' && <CourriersScreen courriers={courriers} affaires={affaires} ddps={ddps} setCourriers={setCourriers} preselectAffaire={screen.preselectAffaire} />}
        {screen.name === 'settings' && <SettingsScreen resetData={resetData} />}

        <BottomNav screen={screen} setScreen={setScreen} />
      </div>
    </>
  );
}

// ============================================================
// RENDER
// ============================================================
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
