/* ============================================================
   Operion WTT — Mock data model + live simulation store
   window.STORE  (external store, React subscribes via useStore)
   window.DATA   (static reference data builders)
   ============================================================ */
(function () {
  const rnd = (a, b) => a + Math.random() * (b - a);
  const clamp = (v, a, b) => Math.max(a, Math.min(b, v));
  const r1 = (v) => Math.round(v * 10) / 10;
  const r2 = (v) => Math.round(v * 100) / 100;

  function seed(n, base, amp, drift = 0) {
    const out = [];
    let v = base;
    for (let i = 0; i < n; i++) {
      v += rnd(-amp, amp) + drift;
      out.push(r1(v));
    }
    return out;
  }

  // ---------- Static reference data ----------
  function nowParts() {
    const d = new Date();
    return d;
  }

  // Quality streams (analysis) — 5 streams x params
  const qualityStreams = [
    { id: 'prim_in', labelIt: 'Acqua primaria ingresso', labelEn: 'Primary inlet', labelEs: 'Entrada primaria', labelFr: 'Entrée primaire', labelDe: 'Primärzulauf' },
    { id: 'potable', labelIt: 'Acqua potabile/trattata', labelEn: 'Potable / treated', labelEs: 'Agua potable', labelFr: 'Eau potable', labelDe: 'Trinkwasser' },
    { id: 'waste_in', labelIt: 'Refluo ingresso', labelEn: 'Wastewater inlet', labelEs: 'Entrada residual', labelFr: 'Entrée eaux usées', labelDe: 'Abwasserzulauf' },
    { id: 'waste_out', labelIt: 'Refluo uscita', labelEn: 'Wastewater outlet', labelEs: 'Salida residual', labelFr: 'Sortie eaux usées', labelDe: 'Abwasserablauf' },
    { id: 'discharge', labelIt: 'Scarico finale', labelEn: 'Final discharge', labelEs: 'Vertido final', labelFr: 'Rejet final', labelDe: 'Endeinleitung' },
  ];

  function streamLabel(s, lang) {
    return s['label' + lang.charAt(0).toUpperCase() + lang.slice(1)] || s.labelIt;
  }

  // Sensors — primary water
  function primarySensors() {
    return [
      { id: 'AI-101', key: 'p.ph', pos: 'Vasca captazione', val: 7.4, unit: '', min: 6.5, max: 8.5, dec: 1 },
      { id: 'AI-102', key: 'p.turbidity', pos: 'Linea ingresso', val: 18, unit: 'NTU', min: 0, max: 40, dec: 1 },
      { id: 'AI-103', key: 'p.conductivity', pos: 'Linea ingresso', val: 612, unit: 'µS/cm', min: 200, max: 1200, dec: 0 },
      { id: 'TI-104', key: 'p.temp', pos: 'Vasca captazione', val: 14.6, unit: '°C', min: 4, max: 28, dec: 1 },
      { id: 'FI-105', key: 'c.flow', pos: 'Mandata pompe', val: 120, unit: 'm³/h', min: 40, max: 180, dec: 0 },
      { id: 'PI-106', key: 'c.pressure', pos: 'Collettore', val: 3.4, unit: 'bar', min: 1.5, max: 6, dec: 1 },
      { id: 'LI-107', key: 'c.level', pos: 'Vasca captazione', val: 72, unit: '%', min: 20, max: 95, dec: 0 },
      { id: 'AI-108', key: 'p.chlorine', pos: 'Pre-clorazione', val: 0.18, unit: 'mg/L', min: 0.05, max: 0.6, dec: 2 },
    ];
  }

  // Potabilization stages
  function potableStages() {
    return [
      { id: 'POT-1', it: 'Coagulazione', en: 'Coagulation', es: 'Coagulación', fr: 'Coagulation', de: 'Koagulation', state: 'run', mode: 'auto', flow: 118, eff: 96, pin: 3.2, pout: 3.0, qin: 18, qout: 9.1 },
      { id: 'POT-2', it: 'Flocculazione', en: 'Flocculation', es: 'Floculación', fr: 'Floculation', de: 'Flockung', state: 'run', mode: 'auto', flow: 118, eff: 95, pin: 3.0, pout: 2.9, qin: 9.1, qout: 5.4 },
      { id: 'POT-3', it: 'Sedimentazione', en: 'Sedimentation', es: 'Sedimentación', fr: 'Sédimentation', de: 'Sedimentation', state: 'run', mode: 'auto', flow: 116, eff: 93, pin: 2.9, pout: 2.7, qin: 5.4, qout: 2.6 },
      { id: 'POT-4', it: 'Filtrazione sabbia', en: 'Sand filtration', es: 'Filtración arena', fr: 'Filtration sable', de: 'Sandfiltration', state: 'run', mode: 'auto', flow: 114, eff: 92, pin: 2.7, pout: 2.3, qin: 2.6, qout: 1.3 },
      { id: 'POT-5', it: 'Carbone attivo', en: 'Activated carbon', es: 'Carbón activo', fr: 'Charbon actif', de: 'Aktivkohle', state: 'run', mode: 'auto', flow: 114, eff: 90, pin: 2.3, pout: 2.0, qin: 1.3, qout: 1.0 },
      { id: 'POT-6', it: 'Ultrafiltrazione', en: 'Ultrafiltration', es: 'Ultrafiltración', fr: 'Ultrafiltration', de: 'Ultrafiltration', state: 'run', mode: 'auto', flow: 112, eff: 97, pin: 2.0, pout: 1.4, qin: 1.0, qout: 0.4 },
      { id: 'POT-7', it: 'Osmosi inversa', en: 'Reverse osmosis', es: 'Ósmosis inversa', fr: 'Osmose inverse', de: 'Umkehrosmose', state: 'warn', mode: 'auto', flow: 88, eff: 98, pin: 12.4, pout: 1.1, qin: 0.4, qout: 0.2 },
      { id: 'POT-8', it: 'Disinfezione UV', en: 'UV disinfection', es: 'Desinfección UV', fr: 'Désinfection UV', de: 'UV-Desinfektion', state: 'run', mode: 'auto', flow: 112, eff: 99, pin: 1.4, pout: 1.3, qin: 0.2, qout: 0.2 },
      { id: 'POT-9', it: 'Dosaggio ipoclorito', en: 'Hypochlorite dosing', es: 'Dosis hipoclorito', fr: 'Dosage hypochlorite', de: 'Hypochloritdosierung', state: 'run', mode: 'auto', flow: 112, eff: 99, pin: 1.3, pout: 1.3, qin: 0.2, qout: 0.2 },
      { id: 'POT-10', it: 'Accumulo acqua trattata', en: 'Treated water storage', es: 'Acumulación tratada', fr: 'Stockage eau traitée', de: 'Reinwasserspeicher', state: 'run', mode: 'auto', flow: 112, eff: 100, pin: 1.3, pout: 1.2, qin: 0.2, qout: 0.2 },
    ];
  }

  // Wastewater process steps
  function wasteSteps() {
    return [
      { id: 'WW-1', it: 'Ingresso refluo', en: 'Wastewater inlet', es: 'Entrada residual', fr: 'Entrée', de: 'Zulauf', state: 'run' },
      { id: 'WW-2', it: 'Grigliatura', en: 'Screening', es: 'Cribado', fr: 'Dégrillage', de: 'Rechen', state: 'run' },
      { id: 'WW-3', it: 'Dissabbiatura', en: 'Grit removal', es: 'Desarenado', fr: 'Dessablage', de: 'Sandfang', state: 'run' },
      { id: 'WW-4', it: 'Disoleazione', en: 'De-oiling', es: 'Desengrasado', fr: 'Déshuilage', de: 'Entölung', state: 'run' },
      { id: 'WW-5', it: 'Equalizzazione', en: 'Equalization', es: 'Homogeneización', fr: 'Égalisation', de: 'Ausgleich', state: 'warn' },
      { id: 'WW-6', it: 'Trattamento primario', en: 'Primary treatment', es: 'Tratamiento primario', fr: 'Traitement primaire', de: 'Vorklärung', state: 'run' },
      { id: 'WW-7', it: 'Trattamento biologico', en: 'Biological treatment', es: 'Tratamiento biológico', fr: 'Traitement biologique', de: 'Biologie', state: 'run' },
      { id: 'WW-8', it: 'Ossidazione', en: 'Oxidation', es: 'Oxidación', fr: 'Oxydation', de: 'Oxidation', state: 'run' },
      { id: 'WW-9', it: 'Nitrificazione', en: 'Nitrification', es: 'Nitrificación', fr: 'Nitrification', de: 'Nitrifikation', state: 'run' },
      { id: 'WW-10', it: 'Denitrificazione', en: 'Denitrification', es: 'Desnitrificación', fr: 'Dénitrification', de: 'Denitrifikation', state: 'run' },
      { id: 'WW-11', it: 'Sedimentazione sec.', en: 'Secondary settling', es: 'Decantación sec.', fr: 'Décantation sec.', de: 'Nachklärung', state: 'run' },
      { id: 'WW-12', it: 'Filtrazione terziaria', en: 'Tertiary filtration', es: 'Filtración terciaria', fr: 'Filtration tertiaire', de: 'Tertiärfiltration', state: 'run' },
      { id: 'WW-13', it: 'Disinfezione finale', en: 'Final disinfection', es: 'Desinfección final', fr: 'Désinfection finale', de: 'Enddesinfektion', state: 'run' },
      { id: 'WW-14', it: 'Scarico finale', en: 'Final discharge', es: 'Vertido final', fr: 'Rejet final', de: 'Endeinleitung', state: 'run' },
    ];
  }

  // Wastewater parameters (in/out/limit)
  function wasteParams() {
    return [
      { key: 'p.cod', in: 450, out: 42, limit: 125, unit: 'mg/L', trend: 'down' },
      { key: 'p.bod', in: 220, out: 18, limit: 25, unit: 'mg/L', trend: 'down' },
      { key: 'p.tss', in: 190, out: 12, limit: 35, unit: 'mg/L', trend: 'down' },
      { key: 'p.ph', in: 7.6, out: 7.2, limit: 9.5, unit: '', trend: 'flat' },
      { key: 'p.ntot', in: 48, out: 9.4, limit: 15, unit: 'mg/L', trend: 'down' },
      { key: 'p.nh4', in: 32, out: 1.8, limit: 15, unit: 'mg/L', trend: 'down' },
      { key: 'p.ptot', in: 7.2, out: 1.1, limit: 2, unit: 'mg/L', trend: 'down' },
      { key: 'p.oils', in: 14, out: 0.6, limit: 10, unit: 'mg/L', trend: 'down' },
      { key: 'p.temp', in: 18.4, out: 17.9, limit: 30, unit: '°C', trend: 'flat' },
      { key: 'p.conductivity', in: 1180, out: 980, limit: 2500, unit: 'µS/cm', trend: 'flat' },
    ];
  }

  // Tanks / basins
  function tanks() {
    return [
      { id: 'TK-01', it: 'Vasca acqua grezza', en: 'Raw water basin', es: 'Tanque agua bruta', fr: 'Bassin eau brute', de: 'Rohwasserbecken', lvl: 72, cap: 1500, agit: false, line: 'primary' },
      { id: 'TK-02', it: 'Vasca equalizzazione', en: 'Equalization basin', es: 'Tanque homogeneización', fr: 'Bassin d’égalisation', de: 'Ausgleichsbecken', lvl: 88, cap: 2000, agit: true, line: 'waste', alarm: 'high' },
      { id: 'TK-03', it: 'Vasca biologica', en: 'Biological basin', es: 'Tanque biológico', fr: 'Bassin biologique', de: 'Belebungsbecken', lvl: 64, cap: 3200, agit: true, line: 'waste' },
      { id: 'TK-04', it: 'Sedimentatore', en: 'Settling tank', es: 'Decantador', fr: 'Décanteur', de: 'Klärbecken', lvl: 55, cap: 1800, agit: false, line: 'waste' },
      { id: 'TK-05', it: 'Serbatoio acqua trattata', en: 'Treated water tank', es: 'Depósito tratada', fr: 'Réservoir eau traitée', de: 'Reinwassertank', lvl: 81, cap: 2500, agit: false, line: 'primary' },
      { id: 'TK-06', it: 'Serbatoio antincendio', en: 'Fire-water tank', es: 'Depósito incendios', fr: 'Réserve incendie', de: 'Löschwassertank', lvl: 95, cap: 600, agit: false, line: 'primary' },
      { id: 'TK-07', it: 'Serbatoio reagenti', en: 'Reagent tank', es: 'Depósito reactivos', fr: 'Réservoir réactifs', de: 'Reagenztank', lvl: 42, cap: 50, agit: false, line: 'chem' },
      { id: 'TK-08', it: 'Vasca fanghi', en: 'Sludge basin', es: 'Tanque de fangos', fr: 'Bassin boues', de: 'Schlammbecken', lvl: 38, cap: 800, agit: true, line: 'sludge' },
      { id: 'TK-09', it: 'Pozzetto scarico finale', en: 'Final discharge sump', es: 'Arqueta de vertido', fr: 'Regard de rejet', de: 'Ablaufschacht', lvl: 28, cap: 120, agit: false, line: 'waste' },
    ];
  }

  // Pumps
  function pumps() {
    return [
      { id: 'P-101', it: 'Pompa captazione 1', en: 'Intake pump 1', es: 'Bomba captación 1', fr: 'Pompe captage 1', de: 'Entnahmepumpe 1', state: 'run', mode: 'auto', hours: 12840, amp: 18.4, flow: 62, line: 'primary' },
      { id: 'P-102', it: 'Pompa captazione 2', en: 'Intake pump 2', es: 'Bomba captación 2', fr: 'Pompe captage 2', de: 'Entnahmepumpe 2', state: 'run', mode: 'auto', hours: 11260, amp: 17.9, flow: 58, line: 'primary' },
      { id: 'P-201', it: 'Pompa sollevamento refluo', en: 'Wastewater lift pump', es: 'Bomba elevación', fr: 'Pompe de relevage', de: 'Hebepumpe', state: 'run', mode: 'auto', hours: 9870, amp: 22.1, flow: 85, line: 'waste' },
      { id: 'P-301', it: 'Pompa ricircolo fanghi', en: 'Sludge recirc. pump', es: 'Bomba recirculación', fr: 'Pompe recirculation', de: 'Rücklaufpumpe', state: 'run', mode: 'auto', hours: 7430, amp: 9.6, flow: 34, line: 'sludge' },
      { id: 'P-302', it: 'Pompa spurgo fanghi', en: 'Sludge purge pump', es: 'Bomba purga', fr: 'Pompe d’extraction', de: 'Überschusspumpe', state: 'idle', mode: 'auto', hours: 3210, amp: 0, flow: 0, line: 'sludge' },
      { id: 'P-401', it: 'Pompa dosaggio chimici', en: 'Chemical dosing pump', es: 'Bomba dosificación', fr: 'Pompe de dosage', de: 'Dosierpumpe', state: 'run', mode: 'auto', hours: 5640, amp: 1.2, flow: 0.4, line: 'chem' },
      { id: 'P-501', it: 'Pompa controlavaggio filtri', en: 'Filter backwash pump', es: 'Bomba contralavado', fr: 'Pompe lavage filtre', de: 'Rückspülpumpe', state: 'fault', mode: 'manual', hours: 2180, amp: 0, flow: 0, line: 'primary' },
    ];
  }

  function valves() {
    return [
      { id: 'V-101', it: 'Valvola ingresso', en: 'Inlet valve', es: 'Válvula entrada', fr: 'Vanne entrée', de: 'Zulaufventil', open: 100, state: 'open' },
      { id: 'V-102', it: 'Valvola bypass', en: 'Bypass valve', es: 'Válvula bypass', fr: 'Vanne bypass', de: 'Bypassventil', open: 0, state: 'closed' },
      { id: 'V-201', it: 'Valvola scarico', en: 'Discharge valve', es: 'Válvula vertido', fr: 'Vanne rejet', de: 'Ablaufventil', open: 100, state: 'open' },
      { id: 'V-301', it: 'Valvola ricircolo', en: 'Recirc. valve', es: 'Válvula recirc.', fr: 'Vanne recirc.', de: 'Rücklaufventil', open: 65, state: 'partial' },
      { id: 'V-501', it: 'Valvola controlavaggio', en: 'Backwash valve', es: 'Válvula contralavado', fr: 'Vanne lavage', de: 'Rückspülventil', open: 0, state: 'closed' },
      { id: 'V-401', it: 'Valvola dosaggio', en: 'Dosing valve', es: 'Válvula dosis', fr: 'Vanne dosage', de: 'Dosierventil', open: 40, state: 'partial' },
    ];
  }

  // Chemicals
  function chemicals() {
    return [
      { id: 'CH-1', it: 'Ipoclorito di sodio', en: 'Sodium hypochlorite', es: 'Hipoclorito de sodio', fr: 'Hypochlorite de sodium', de: 'Natriumhypochlorit', tank: 'TK-07a', lvl: 64, qty: 3200, dose: 2.4, unit: 'L/h', daily: 58, minPct: 20, supplier: 'ChimItalia Srl', pump: true, mode: 'auto' },
      { id: 'CH-2', it: 'Cloruro ferrico', en: 'Ferric chloride', es: 'Cloruro férrico', fr: 'Chlorure ferrique', de: 'Eisenchlorid', tank: 'TK-07b', lvl: 48, qty: 2400, dose: 4.1, unit: 'L/h', daily: 98, minPct: 25, supplier: 'AquaChem SpA', pump: true, mode: 'auto' },
      { id: 'CH-3', it: 'Polielettrolita', en: 'Polyelectrolyte', es: 'Polielectrolito', fr: 'Polyélectrolyte', de: 'Polyelektrolyt', tank: 'TK-07c', lvl: 31, qty: 620, dose: 0.8, unit: 'kg/h', daily: 19, minPct: 30, supplier: 'PoliDos Srl', pump: true, mode: 'auto' },
      { id: 'CH-4', it: 'Soda caustica', en: 'Caustic soda', es: 'Sosa cáustica', fr: 'Soude caustique', de: 'Natronlauge', tank: 'TK-07d', lvl: 72, qty: 1800, dose: 1.1, unit: 'L/h', daily: 26, minPct: 20, supplier: 'ChimItalia Srl', pump: false, mode: 'manual' },
      { id: 'CH-5', it: 'Acido cloridrico', en: 'Hydrochloric acid', es: 'Ácido clorhídrico', fr: 'Acide chlorhydrique', de: 'Salzsäure', tank: 'TK-07e', lvl: 18, qty: 360, dose: 0.6, unit: 'L/h', daily: 14, minPct: 25, supplier: 'AquaChem SpA', pump: true, mode: 'auto' },
      { id: 'CH-6', it: 'Antischiuma', en: 'Antifoam', es: 'Antiespumante', fr: 'Antimousse', de: 'Entschäumer', tank: 'TK-07f', lvl: 55, qty: 210, dose: 0.2, unit: 'L/h', daily: 5, minPct: 20, supplier: 'PoliDos Srl', pump: true, mode: 'auto' },
      { id: 'CH-7', it: 'Antincrostante osmosi', en: 'RO antiscalant', es: 'Antiincrustante', fr: 'Antitartre osmose', de: 'Antiscalant', tank: 'TK-07g', lvl: 81, qty: 480, dose: 0.3, unit: 'L/h', daily: 7, minPct: 30, supplier: 'MembraTech', pump: true, mode: 'auto' },
    ];
  }

  // Sludge line metrics
  function sludge() {
    return {
      cards: [
        { it: 'Volume fanghi prodotto', en: 'Sludge volume produced', es: 'Volumen producido', fr: 'Volume produit', de: 'Schlammvolumen', val: 4.8, unit: 't', delta: 0.3 },
        { it: 'Secco', en: 'Dryness', es: 'Sequedad', fr: 'Siccité', de: 'Trockenheit', val: 22.4, unit: '%', delta: 0.6 },
        { it: 'Ore centrifuga', en: 'Centrifuge hours', es: 'Horas centrífuga', fr: 'Heures centrifuge', de: 'Zentrifugenstunden', val: 6.2, unit: 'h', delta: 0.4 },
        { it: 'Polielettrolita', en: 'Polyelectrolyte', es: 'Polielectrolito', fr: 'Polyélectrolyte', de: 'Polyelektrolyt', val: 19, unit: 'kg', delta: -2 },
        { it: 'Cassone fanghi', en: 'Sludge skip', es: 'Contenedor', fr: 'Benne à boues', de: 'Schlammcontainer', val: 78, unit: '%', delta: 5 },
        { it: 'Prossimo ritiro', en: 'Next pickup', es: 'Próxima retirada', fr: 'Enlèvement', de: 'Abholung', txt: '18/06 09:00' },
      ],
      stages: [
        { it: 'Fanghi primari', en: 'Primary sludge', es: 'Fangos primarios', fr: 'Boues primaires', de: 'Primärschlamm', state: 'run' },
        { it: 'Fanghi biologici', en: 'Biological sludge', es: 'Fangos biológicos', fr: 'Boues biologiques', de: 'Bioschlamm', state: 'run' },
        { it: 'Ricircolo fanghi', en: 'Sludge recirculation', es: 'Recirculación', fr: 'Recirculation', de: 'Rücklauf', state: 'run' },
        { it: 'Spurgo fanghi', en: 'Sludge purge', es: 'Purga', fr: 'Extraction', de: 'Überschuss', state: 'idle' },
        { it: 'Ispessitore', en: 'Thickener', es: 'Espesador', fr: 'Épaississeur', de: 'Eindicker', state: 'run' },
        { it: 'Digestore', en: 'Digester', es: 'Digestor', fr: 'Digesteur', de: 'Faulturm', state: 'run' },
        { it: 'Disidratazione', en: 'Dewatering', es: 'Deshidratación', fr: 'Déshydratation', de: 'Entwässerung', state: 'run' },
        { it: 'Centrifuga', en: 'Centrifuge', es: 'Centrífuga', fr: 'Centrifugeuse', de: 'Zentrifuge', state: 'run' },
        { it: 'Cassone fanghi', en: 'Sludge skip', es: 'Contenedor', fr: 'Benne', de: 'Container', state: 'warn' },
      ],
    };
  }

  // Energy
  function energy() {
    return {
      total: 1842, specific: 0.68, peak: 312, cost: 446, co2: 738,
      byDept: [
        { it: 'Pompe', en: 'Pumps', es: 'Bombas', fr: 'Pompes', de: 'Pumpen', kwh: 642 },
        { it: 'Soffianti', en: 'Blowers', es: 'Soplantes', fr: 'Surpresseurs', de: 'Gebläse', kwh: 518 },
        { it: 'Osmosi inversa', en: 'Reverse osmosis', es: 'Ósmosis', fr: 'Osmose', de: 'Umkehrosmose', kwh: 388 },
        { it: 'Disinfezione UV', en: 'UV disinfection', es: 'UV', fr: 'UV', de: 'UV', kwh: 142 },
        { it: 'Centrifuga', en: 'Centrifuge', es: 'Centrífuga', fr: 'Centrifugeuse', de: 'Zentrifuge', kwh: 96 },
        { it: 'Ausiliari', en: 'Auxiliaries', es: 'Auxiliares', fr: 'Auxiliaires', de: 'Hilfssysteme', kwh: 56 },
      ],
    };
  }

  // Maintenance assets
  function maintenance() {
    return [
      { id: 'P-101', it: 'Pompa captazione 1', en: 'Intake pump 1', dept: 'primary', state: 'run', hours: 12840, last: '12/03/26', next: '12/07/26', prio: 'low', tech: 'M. Rossi' },
      { id: 'B-201', it: 'Soffiante biologico', en: 'Bio blower', dept: 'waste', state: 'warn', hours: 18420, last: '02/02/26', next: '20/06/26', prio: 'high', tech: 'L. Bianchi' },
      { id: 'F-301', it: 'Filtro sabbia', en: 'Sand filter', dept: 'primary', state: 'run', hours: 9600, last: '28/04/26', next: '28/08/26', prio: 'low', tech: 'M. Rossi' },
      { id: 'UV-401', it: 'Lampada UV', en: 'UV lamp', dept: 'primary', state: 'run', hours: 7100, last: '10/05/26', next: '10/06/26', prio: 'medium', tech: 'A. Verdi' },
      { id: 'CMP-1', it: 'Compressore aria', en: 'Air compressor', dept: 'aux', state: 'run', hours: 14200, last: '15/01/26', next: '15/07/26', prio: 'low', tech: 'L. Bianchi' },
      { id: 'CF-1', it: 'Centrifuga fanghi', en: 'Sludge centrifuge', dept: 'sludge', state: 'run', hours: 8800, last: '20/03/26', next: '20/06/26', prio: 'medium', tech: 'A. Verdi' },
      { id: 'AI-101', it: 'Sensore pH', en: 'pH sensor', dept: 'lab', state: 'run', hours: 4300, last: '01/06/26', next: '01/09/26', prio: 'low', tech: 'S. Conti' },
      { id: 'AI-102', it: 'Sensore torbidità', en: 'Turbidity sensor', dept: 'lab', state: 'warn', hours: 4300, last: '01/04/26', next: '16/06/26', prio: 'medium', tech: 'S. Conti' },
      { id: 'MCC-1', it: 'Quadro elettrico MCC', en: 'MCC switchboard', dept: 'aux', state: 'run', hours: 26000, last: '10/02/26', next: '10/08/26', prio: 'low', tech: 'G. Ferri' },
      { id: 'PLC-1', it: 'PLC principale', en: 'Main PLC', dept: 'aux', state: 'run', hours: 31200, last: '05/05/26', next: '05/11/26', prio: 'low', tech: 'G. Ferri' },
    ];
  }

  // Initial alarms
  function alarms() {
    return [
      { id: 'ALM-2041', area: 'waste', code: 'LSH-302', it: 'Livello vasca equalizzazione alto', en: 'Equalization basin high level', es: 'Nivel alto homogeneización', fr: 'Niveau haut bassin égalisation', de: 'Hoher Füllstand Ausgleichsbecken', sev: 'warning', state: 'open', ts: '15/06 08:42', op: '—', act: 'Verificare pompa sollevamento P-201' },
      { id: 'ALM-2040', area: 'primary', code: 'PAH-106', it: 'Pressione osmosi inversa elevata', en: 'Reverse osmosis high pressure', es: 'Presión alta ósmosis', fr: 'Pression haute osmose', de: 'Hoher Druck Umkehrosmose', sev: 'warning', state: 'ack', ts: '15/06 07:15', op: 'M. Rossi', act: 'Controllare membrane / antincrostante' },
      { id: 'ALM-2039', area: 'aux', code: 'F-501', it: 'Pompa controlavaggio in blocco', en: 'Backwash pump fault', es: 'Avería bomba contralavado', fr: 'Défaut pompe lavage', de: 'Störung Rückspülpumpe', sev: 'critical', state: 'open', ts: '15/06 06:58', op: '—', act: 'Reset quadro, verificare protezione termica' },
      { id: 'ALM-2038', area: 'chem', code: 'LSL-407', it: 'Serbatoio acido cloridrico basso', en: 'HCl tank low level', es: 'Nivel bajo HCl', fr: 'Niveau bas HCl', de: 'Niedriger Füllstand HCl', sev: 'warning', state: 'open', ts: '15/06 05:30', op: '—', act: 'Programmare riordino reagente' },
      { id: 'ALM-2037', area: 'lab', code: 'AIC-102', it: 'Sensore torbidità offline', en: 'Turbidity sensor offline', es: 'Sensor turbidez sin conexión', fr: 'Capteur turbidité hors ligne', de: 'Trübungssensor offline', sev: 'info', state: 'ack', ts: '15/06 04:12', op: 'S. Conti', act: 'Verificare comunicazione Modbus' },
      { id: 'ALM-2036', area: 'sludge', code: 'LSH-801', it: 'Cassone fanghi quasi pieno', en: 'Sludge skip nearly full', es: 'Contenedor casi lleno', fr: 'Benne presque pleine', de: 'Container fast voll', sev: 'warning', state: 'open', ts: '14/06 22:40', op: '—', act: 'Programmare ritiro fanghi' },
      { id: 'ALM-2035', area: 'waste', code: 'QIC-COD', it: 'COD uscita prossimo al limite', en: 'Outlet COD near limit', es: 'DQO cerca del límite', fr: 'DCO proche limite', de: 'CSB nahe Grenzwert', sev: 'info', state: 'resolved', ts: '14/06 18:05', op: 'L. Bianchi', act: 'Aumentare ricircolo fanghi' },
    ];
  }

  function reports() {
    return [
      { id: 'R1', it: 'Produzione acqua trattata', en: 'Treated water production', es: 'Producción de agua', fr: 'Production eau traitée', de: 'Reinwasserproduktion', cat: 'prod' },
      { id: 'R2', it: 'Trattamento reflui', en: 'Wastewater treatment', es: 'Tratamiento de aguas', fr: 'Traitement eaux usées', de: 'Abwasserbehandlung', cat: 'prod' },
      { id: 'R3', it: 'Qualità acqua', en: 'Water quality', es: 'Calidad del agua', fr: 'Qualité eau', de: 'Wasserqualität', cat: 'quality' },
      { id: 'R4', it: 'Limiti di scarico', en: 'Discharge limits', es: 'Límites de vertido', fr: 'Limites de rejet', de: 'Einleitgrenzwerte', cat: 'compliance' },
      { id: 'R5', it: 'Consumi energetici', en: 'Energy consumption', es: 'Consumo energético', fr: 'Consommation énergie', de: 'Energieverbrauch', cat: 'energy' },
      { id: 'R6', it: 'Consumi chimici', en: 'Chemical consumption', es: 'Consumo químico', fr: 'Consommation chimique', de: 'Chemikalienverbrauch', cat: 'energy' },
      { id: 'R7', it: 'Fanghi prodotti', en: 'Sludge produced', es: 'Fangos producidos', fr: 'Boues produites', de: 'Schlammproduktion', cat: 'prod' },
      { id: 'R8', it: 'Allarmi', en: 'Alarms', es: 'Alarmas', fr: 'Alarmes', de: 'Alarme', cat: 'ops' },
      { id: 'R9', it: 'Manutenzioni', en: 'Maintenance', es: 'Mantenimiento', fr: 'Maintenance', de: 'Wartung', cat: 'ops' },
      { id: 'R10', it: 'Efficienza impianto', en: 'Plant efficiency', es: 'Eficiencia de planta', fr: 'Efficacité station', de: 'Anlageneffizienz', cat: 'prod' },
      { id: 'R11', it: 'Costi operativi', en: 'Operating costs', es: 'Costes operativos', fr: 'Coûts d’exploitation', de: 'Betriebskosten', cat: 'energy' },
      { id: 'R12', it: 'Conformità normativa', en: 'Regulatory compliance', es: 'Conformidad normativa', fr: 'Conformité réglementaire', de: 'Behördliche Konformität', cat: 'compliance' },
    ];
  }

  function users() {
    return [
      { name: 'Marco Rossi', role: 'admin', email: 'm.rossi@valdera.it', active: true },
      { name: 'Laura Bianchi', role: 'manager', email: 'l.bianchi@valdera.it', active: true },
      { name: 'Andrea Verdi', role: 'operator', email: 'a.verdi@valdera.it', active: true },
      { name: 'Giulio Ferri', role: 'maint', email: 'g.ferri@valdera.it', active: true },
      { name: 'Sara Conti', role: 'lab', email: 's.conti@valdera.it', active: true },
      { name: 'Paolo Neri', role: 'supervisor', email: 'p.neri@valdera.it', active: false },
      { name: 'Elena Gallo', role: 'readonly', email: 'e.gallo@valdera.it', active: true },
    ];
  }

  const roles = [
    { id: 'admin', it: 'Amministratore', en: 'Administrator', es: 'Administrador', fr: 'Administrateur', de: 'Administrator' },
    { id: 'manager', it: 'Responsabile impianto', en: 'Plant manager', es: 'Responsable de planta', fr: 'Responsable station', de: 'Anlagenleiter' },
    { id: 'operator', it: 'Operatore', en: 'Operator', es: 'Operador', fr: 'Opérateur', de: 'Bediener' },
    { id: 'maint', it: 'Manutentore', en: 'Maintenance tech', es: 'Mantenedor', fr: 'Technicien', de: 'Wartungstechniker' },
    { id: 'lab', it: 'Laboratorio', en: 'Laboratory', es: 'Laboratorio', fr: 'Laboratoire', de: 'Labor' },
    { id: 'supervisor', it: 'Supervisore', en: 'Supervisor', es: 'Supervisor', fr: 'Superviseur', de: 'Supervisor' },
    { id: 'readonly', it: 'Solo lettura', en: 'Read only', es: 'Solo lectura', fr: 'Lecture seule', de: 'Nur Lesen' },
  ];

  const permissions = [
    { id: 'view', it: 'Visualizzazione dashboard', en: 'Dashboard view', es: 'Ver panel', fr: 'Voir tableau', de: 'Dashboard ansehen' },
    { id: 'command', it: 'Comando impianto', en: 'Plant command', es: 'Mando de planta', fr: 'Commande station', de: 'Anlagensteuerung' },
    { id: 'params', it: 'Modifica parametri', en: 'Edit parameters', es: 'Editar parámetros', fr: 'Modifier paramètres', de: 'Parameter ändern' },
    { id: 'alarms', it: 'Gestione allarmi', en: 'Alarm management', es: 'Gestión de alarmas', fr: 'Gestion alarmes', de: 'Alarmverwaltung' },
    { id: 'maint', it: 'Gestione manutenzione', en: 'Maintenance mgmt', es: 'Gestión mant.', fr: 'Gestion maintenance', de: 'Wartungsverwaltung' },
    { id: 'reports', it: 'Accesso report', en: 'Reports access', es: 'Acceso a informes', fr: 'Accès rapports', de: 'Berichtszugriff' },
    { id: 'users', it: 'Gestione utenti', en: 'User management', es: 'Gestión usuarios', fr: 'Gestion utilisateurs', de: 'Benutzerverwaltung' },
    { id: 'settings', it: 'Accesso impostazioni', en: 'Settings access', es: 'Acceso ajustes', fr: 'Accès paramètres', de: 'Einstellungszugriff' },
  ];

  // role -> permission matrix
  const permMatrix = {
    admin: ['view', 'command', 'params', 'alarms', 'maint', 'reports', 'users', 'settings'],
    manager: ['view', 'command', 'params', 'alarms', 'maint', 'reports', 'settings'],
    operator: ['view', 'command', 'alarms', 'reports'],
    maint: ['view', 'maint', 'alarms', 'reports'],
    lab: ['view', 'params', 'reports'],
    supervisor: ['view', 'alarms', 'reports'],
    readonly: ['view'],
  };

  // ---------- Live state ----------
  function freshLive() {
    return {
      plantState: 'running',
      flowPrimary: 120,
      flowWaste: 85,
      waterToday: 2184,
      wasteToday: 1536,
      efficiency: 94,
      energyToday: 1842,
      reagentsToday: 227,
      activeAlarms: 4,
      outOfRange: 2,
      outQuality: 'conform',
      doO2: 2.1,
      chlorine: 0.3,
      turbidityOut: 0.8,
      codOut: 42,
      phOut: 7.2,
      sludgeToday: 4.8,
    };
  }

  function freshHistory() {
    return {
      flowPrimary: seed(24, 118, 6),
      flowWaste: seed(24, 84, 5),
      energy: seed(24, 76, 8),
      turbidityIn: seed(24, 18, 2),
      turbidityOut: seed(24, 0.8, 0.15).map((v) => Math.max(0.2, v)),
      codIn: seed(24, 450, 25),
      codOut: seed(24, 42, 5),
      ph: seed(24, 7.3, 0.12),
      sludge: seed(14, 4.6, 0.4),
      reagents: seed(24, 9.5, 1.2),
      qualityIn: seed(24, 62, 4),
      qualityOut: seed(24, 96, 1.2).map((v) => Math.min(99.5, v)),
    };
  }

  // ---------- External store ----------
  const STORE = {
    version: 0,
    listeners: new Set(),
    simRunning: true,
    state: {
      lang: 'it',
      live: freshLive(),
      history: freshHistory(),
      tanks: tanks(),
      pumps: pumps(),
      valves: valves(),
      chemicals: chemicals(),
      alarms: alarms(),
      maintenance: maintenance(),
      potableStages: potableStages(),
      wasteSteps: wasteSteps(),
      wasteParams: wasteParams(),
      primarySensors: primarySensors(),
      clock: new Date(),
      plcStatus: 'sim', // online | offline | sim
    },
    subscribe(fn) { STORE.listeners.add(fn); return () => STORE.listeners.delete(fn); },
    getVersion() { return STORE.version; },
    emit() { STORE.version++; STORE.listeners.forEach((l) => l()); },
    set(patch) { Object.assign(STORE.state, patch); STORE.emit(); },

    // simulation tick
    tick() {
      const s = STORE.state;
      s.clock = new Date();
      if (STORE.simRunning) {
        const L = s.live;
        L.flowPrimary = r1(clamp(L.flowPrimary + rnd(-4, 4), 95, 145));
        L.flowWaste = r1(clamp(L.flowWaste + rnd(-3, 3), 62, 105));
        L.waterToday = Math.round(L.waterToday + L.flowPrimary / 30);
        L.wasteToday = Math.round(L.wasteToday + L.flowWaste / 30);
        L.efficiency = r1(clamp(L.efficiency + rnd(-0.4, 0.4), 91, 96.5));
        L.energyToday = Math.round(L.energyToday + rnd(2, 6));
        L.reagentsToday = Math.round(L.reagentsToday + rnd(0.2, 0.8));
        L.doO2 = r2(clamp(L.doO2 + rnd(-0.15, 0.15), 1.4, 2.8));
        L.chlorine = r2(clamp(L.chlorine + rnd(-0.04, 0.04), 0.12, 0.5));
        L.turbidityOut = r2(clamp(L.turbidityOut + rnd(-0.08, 0.08), 0.3, 1.4));
        L.codOut = Math.round(clamp(L.codOut + rnd(-2.5, 2.5), 30, 70));
        L.phOut = r2(clamp(L.phOut + rnd(-0.05, 0.05), 6.8, 7.8));

        // tanks drift
        s.tanks.forEach((t) => { t.lvl = Math.round(clamp(t.lvl + rnd(-2.4, 2.4), 8, 98)); });
        // running pumps amp jitter
        s.pumps.forEach((p) => { if (p.state === 'run') { p.amp = r1(clamp(p.amp + rnd(-0.6, 0.6), 0.5, 30)); p.flow = Math.round(clamp(p.flow + rnd(-2, 2), 0, 120)); } });
        // sensors jitter
        s.primarySensors.forEach((sn) => { sn.val = +(sn.val + rnd(-1, 1) * (sn.max - sn.min) * 0.01).toFixed(sn.dec); sn.val = clamp(sn.val, sn.min * 0.6, sn.max * 1.1); });

        // history shift
        const H = s.history;
        const push = (arr, v) => { arr.push(v); if (arr.length > 24) arr.shift(); };
        push(H.flowPrimary, L.flowPrimary);
        push(H.flowWaste, L.flowWaste);
        push(H.energy, r1(rnd(70, 86)));
        push(H.turbidityOut, L.turbidityOut);
        push(H.codOut, L.codOut);
        push(H.ph, L.phOut);
        push(H.qualityOut, r1(L.efficiency + rnd(1, 3)));
        push(H.reagents, r1(rnd(8, 11)));

        // occasional non-critical warning (~3%)
        if (Math.random() < 0.03) {
          STORE.spawnAlarm({ sev: 'warning', area: 'waste', it: 'Oscillazione portata refluo', en: 'Wastewater flow oscillation', es: 'Oscilación de caudal', fr: 'Oscillation de débit', de: 'Durchflussschwankung', code: 'FIC-201', act: 'Monitorare vasca equalizzazione', auto: true });
        }
      }
      STORE.emit();
    },

    spawnAlarm(a) {
      const s = STORE.state;
      const id = 'ALM-' + Math.floor(2042 + Math.random() * 900);
      const d = new Date();
      const ts = String(d.getDate()).padStart(2, '0') + '/' + String(d.getMonth() + 1).padStart(2, '0') + ' ' + String(d.getHours()).padStart(2, '0') + ':' + String(d.getMinutes()).padStart(2, '0');
      s.alarms.unshift({ id, state: 'open', op: '—', ts, ...a });
      s.live.activeAlarms = s.alarms.filter((x) => x.state !== 'resolved').length;
      STORE.emit();
    },

    ackAlarm(id, op) {
      const a = STORE.state.alarms.find((x) => x.id === id);
      if (a && a.state === 'open') { a.state = 'ack'; a.op = op || 'M. Rossi'; }
      STORE.emit();
    },
    resolveAlarm(id, op) {
      const a = STORE.state.alarms.find((x) => x.id === id);
      if (a) { a.state = 'resolved'; a.op = op || 'M. Rossi'; }
      STORE.state.live.activeAlarms = STORE.state.alarms.filter((x) => x.state !== 'resolved').length;
      STORE.emit();
    },
    togglePump(id) {
      const p = STORE.state.pumps.find((x) => x.id === id);
      if (!p) return null;
      if (p.state === 'fault') { p.state = 'idle'; p.amp = 0; p.flow = 0; STORE.emit(); return 'reset'; }
      if (p.state === 'run') { p.state = 'idle'; p.amp = 0; p.flow = 0; STORE.emit(); return 'stop'; }
      p.state = 'run'; p.amp = r1(rnd(8, 22)); p.flow = Math.round(rnd(30, 80)); STORE.emit(); return 'start';
    },
    setPumpState(id, st) {
      const p = STORE.state.pumps.find((x) => x.id === id);
      if (!p) return;
      p.state = st;
      if (st === 'run') { p.amp = r1(rnd(8, 22)); p.flow = Math.round(rnd(30, 80)); }
      else { p.amp = 0; p.flow = 0; }
      STORE.emit();
    },
    setPumpMode(id, mode) { const p = STORE.state.pumps.find((x) => x.id === id); if (p) p.mode = mode; STORE.emit(); },
    setValve(id, open) {
      const v = STORE.state.valves.find((x) => x.id === id);
      if (!v) return;
      v.open = open;
      v.state = open >= 99 ? 'open' : open <= 1 ? 'closed' : 'partial';
      STORE.emit();
    },
    toggleChemPump(id) { const c = STORE.state.chemicals.find((x) => x.id === id); if (c) c.pump = !c.pump; STORE.emit(); },
    setChemDose(id, dose) { const c = STORE.state.chemicals.find((x) => x.id === id); if (c) c.dose = dose; STORE.emit(); },
    setLang(lang) { STORE.state.lang = lang; STORE.emit(); },
    setSim(running) { STORE.simRunning = running; STORE.emit(); },
    reset() {
      STORE.state.live = freshLive();
      STORE.state.history = freshHistory();
      STORE.state.tanks = tanks();
      STORE.state.pumps = pumps();
      STORE.state.valves = valves();
      STORE.state.chemicals = chemicals();
      STORE.state.alarms = alarms();
      STORE.emit();
    },
    restoreParams() {
      STORE.state.live = freshLive();
      // clear non-critical generated alarms
      STORE.state.alarms = STORE.state.alarms.filter((a) => !a.auto);
      STORE.state.live.activeAlarms = STORE.state.alarms.filter((x) => x.state !== 'resolved').length;
      STORE.emit();
    },
  };

  // Analysis values per stream (computed reference)
  function analysisFor(streamId) {
    const base = {
      prim_in: { 'p.ph': 7.4, 'p.turbidity': 18, 'p.conductivity': 612, 'p.cod': '—', 'p.bod': '—', 'p.tss': 24, 'p.chlorine': 0.18, 'p.do': '—', 'p.nh4': 0.4, 'p.ptot': 0.2, 'p.hardness': 24, 'p.nitrates': 12, 'p.temp': 14.6, 'p.bacteria': '320 UFC' },
      potable: { 'p.ph': 7.6, 'p.turbidity': 0.4, 'p.conductivity': 380, 'p.cod': '—', 'p.bod': '—', 'p.tss': 1, 'p.chlorine': 0.32, 'p.do': '—', 'p.nh4': 0.05, 'p.ptot': '—', 'p.hardness': 18, 'p.nitrates': 6, 'p.temp': 15.1, 'p.bacteria': '0 UFC' },
      waste_in: { 'p.ph': 7.6, 'p.turbidity': '—', 'p.conductivity': 1180, 'p.cod': 450, 'p.bod': 220, 'p.tss': 190, 'p.chlorine': '—', 'p.do': 0.3, 'p.nh4': 32, 'p.ptot': 7.2, 'p.hardness': '—', 'p.nitrates': '—', 'p.temp': 18.4, 'p.bacteria': '—' },
      waste_out: { 'p.ph': 7.2, 'p.turbidity': 2.1, 'p.conductivity': 980, 'p.cod': 42, 'p.bod': 18, 'p.tss': 12, 'p.chlorine': 0.2, 'p.do': 2.1, 'p.nh4': 1.8, 'p.ptot': 1.1, 'p.hardness': '—', 'p.nitrates': 9, 'p.temp': 17.9, 'p.bacteria': '180 UFC' },
      discharge: { 'p.ph': 7.2, 'p.turbidity': 1.8, 'p.conductivity': 970, 'p.cod': 38, 'p.bod': 14, 'p.tss': 10, 'p.chlorine': 0.15, 'p.do': 6.8, 'p.nh4': 1.4, 'p.ptot': 0.9, 'p.hardness': '—', 'p.nitrates': 8, 'p.temp': 17.6, 'p.bacteria': '95 UFC' },
    };
    return base[streamId] || {};
  }

  window.STORE = STORE;
  window.DATA = {
    qualityStreams, streamLabel, roles, permissions, permMatrix,
    sludge: sludge(), energy: energy(), reports: reports(), users: users(),
    analysisFor,
    fmt: { r1, r2, clamp },
  };
})();
