/* ============================================================
   Operion WTT — Overview sections: Dashboard + Synoptic (P&ID)
   ============================================================ */
(function () {
  const { useState } = React;
  const { Card, CardHead, KPI, Badge, SDot, Btn, Icon, Drawer, DList, DetailSection, ModeSwitch, Seg } = window;
  const h = React.createElement;

  const HOURS = Array.from({ length: 24 }, (_, i) => i).filter((i) => i % 4 === 0).map((i) => String(i).padStart(2, '0'));
  const xl24 = ['00', '04', '08', '12', '16', '20', ''];

  // ---- Status tile ----
  function StatusTile({ icon, label, status, value, sub }) {
    const inf = window.statusInfo(status);
    return h('div', { className: 'card', style: { padding: 16, display: 'flex', alignItems: 'center', gap: 12 } },
      h('span', { className: 'kpi-ic', style: { background: `var(--status-${inf.cls}-bg)`, color: `var(--status-${inf.cls})` } }, h(Icon, { name: icon, size: 20 })),
      h('div', { style: { flex: 1, minWidth: 0 } },
        h('div', { className: 'kpi-label' }, label),
        h('div', { style: { marginTop: 3 } }, value ? h('span', { className: 'mono', style: { fontWeight: 600, color: 'var(--fg-1)', fontSize: 15 } }, value) : h(Badge, { status }))),
      sub && h('div', { className: 'mono', style: { fontSize: 11, color: 'var(--fg-3)' } }, sub));
  }

  // ============================================================
  // DASHBOARD
  // ============================================================
  function Dashboard() {
    const s = window.useStore();
    const { t, tl, sim, toast } = window.useApp();
    const L = s.live, H = s.history;
    const runningPumps = s.pumps.filter((p) => p.state === 'run').length;
    const plantBadge = L.activeAlarms > 0 && s.alarms.some((a) => a.sev === 'critical' && a.state === 'open') ? 'alarm' : s.live.plantState;

    return h('div', { className: 'page' },
      // hero strip
      h('div', { className: 'card', style: { padding: 0, overflow: 'hidden', marginBottom: 'var(--gap)', background: 'var(--navy-950)', border: 'none' } },
        h('div', { style: { display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 24, padding: '20px 24px', color: '#fff', position: 'relative' } },
          h('div', { style: { position: 'absolute', inset: 0, backgroundImage: 'linear-gradient(rgba(110,151,196,.06) 1px,transparent 1px),linear-gradient(90deg,rgba(110,151,196,.06) 1px,transparent 1px)', backgroundSize: '28px 28px', maskImage: 'radial-gradient(ellipse 70% 100% at 20% 50%,#000,transparent)' } }),
          h('div', { style: { position: 'relative', display: 'flex', alignItems: 'center', gap: 16 } },
            h('div', { style: { width: 54, height: 54, borderRadius: 12, background: 'rgba(242,148,31,.16)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#F2941F' } }, h(Icon, { name: 'factory', size: 28 })),
            h('div', null,
              h('div', { style: { fontFamily: 'IBM Plex Mono,monospace', fontSize: 11, letterSpacing: '.12em', color: '#9DB2CC', textTransform: 'uppercase' } }, t('k.plantstate')),
              h('div', { style: { display: 'flex', alignItems: 'center', gap: 10, marginTop: 4 } },
                h('span', { style: { fontFamily: 'Titillium Web', fontWeight: 700, fontSize: 26, letterSpacing: '-.01em' } }, t('state.' + (plantBadge === 'alarm' ? 'alarm' : 'running'))),
                h(Badge, { status: plantBadge, pulse: plantBadge === 'alarm' })),
              h('div', { style: { fontSize: 12.5, color: '#9DB2CC', marginTop: 2 } }, tl({ it: 'Impianto Consortile Valdera', en: 'Valdera Consortium Plant', es: 'Planta Consorcial Valdera', fr: 'Station Valdera', de: 'Konsortialanlage Valdera' }), ' · 32.000 ', 'AE'))),
          h('div', { style: { position: 'relative', display: 'flex', gap: 28, marginLeft: 'auto', flexWrap: 'wrap' } },
            [[t('k.flowprimary'), L.flowPrimary, 'm³/h', '#6EC1E4'], [t('k.flowwaste'), L.flowWaste, 'm³/h', '#F7A845'], [t('c.efficiency'), L.efficiency, '%', '#5ED39A']].map((m, i) =>
              h('div', { key: i, style: { whiteSpace: 'nowrap' } },
                h('div', { style: { fontSize: 11.5, color: '#9DB2CC' } }, m[0]),
                h('div', { style: { fontFamily: 'IBM Plex Mono,monospace', fontWeight: 600, fontSize: 24, color: m[3], marginTop: 3, lineHeight: 1 } }, m[1], h('span', { style: { fontSize: 13, color: '#9DB2CC', marginLeft: 3 } }, m[2]))))),
          h('div', { style: { position: 'relative', display: 'flex', gap: 8, flexWrap: 'wrap' } },
            h('button', { className: 'sim-pill ' + (sim.running ? 'on' : 'off'), onClick: sim.toggle, style: { background: sim.running ? 'rgba(94,211,154,.16)' : 'rgba(255,255,255,.08)', color: sim.running ? '#5ED39A' : '#9DB2CC', border: '1px solid ' + (sim.running ? 'rgba(94,211,154,.4)' : 'rgba(255,255,255,.16)') } },
              h('span', { className: 'dot' }), sim.running ? t('sim.on') : t('sim.off')),
            h('button', { className: 'btn btn-accent btn-sm', onClick: sim.running ? sim.pause : sim.start }, h(Icon, { name: sim.running ? 'pause' : 'play', size: 14 }), sim.running ? t('sim.pause') : t('sim.start')),
            h('button', { className: 'btn btn-ghost-dark btn-sm', style: { background: 'rgba(255,255,255,.08)', color: '#EAF1F8', border: '1px solid rgba(255,255,255,.18)' }, onClick: sim.reset }, h(Icon, { name: 'reset', size: 14 }), t('sim.reset')),
            h('button', { className: 'btn btn-ghost-dark btn-sm', style: { background: 'rgba(211,58,44,.16)', color: '#FF9A8E', border: '1px solid rgba(211,58,44,.4)' }, onClick: sim.testAlarm }, h(Icon, { name: 'alert', size: 14 }), t('sim.testalarm'))))),

      // numeric KPI grid
      h('div', { className: 'grid g4', style: { marginBottom: 'var(--gap)' } },
        h(KPI, { icon: 'droplet', label: t('k.watertoday'), value: L.waterToday.toLocaleString(), unit: 'm³', delta: '+6.2% ' + t('c.deltatoday'), deltaDir: 'up', spark: H.flowPrimary, sparkColor: '#2E8BC0' }),
        h(KPI, { icon: 'recycle', label: t('k.wastetoday'), value: L.wasteToday.toLocaleString(), unit: 'm³', delta: '+3.1% ' + t('c.deltatoday'), deltaDir: 'up', spark: H.flowWaste, sparkColor: '#F2941F' }),
        h(KPI, { icon: 'gauge', label: t('k.efficiency'), value: L.efficiency, unit: '%', delta: '+0.4 ' + t('c.deltatoday'), deltaDir: 'up', spark: H.qualityOut, sparkColor: '#1E9E5A' }),
        h(KPI, { icon: 'zap', label: t('k.energy'), value: L.energyToday.toLocaleString(), unit: 'kWh', delta: '0.68 kWh/m³', deltaDir: 'flat', spark: H.energy, sparkColor: '#8B5CF6' })),

      // status tiles
      h('div', { className: 'grid g4', style: { marginBottom: 'var(--gap)' } },
        h(StatusTile, { icon: 'bell', label: t('k.activealarms'), status: L.activeAlarms > 3 ? 'alarm' : L.activeAlarms > 0 ? 'warn' : 'run', value: L.activeAlarms + ' ' + tl({ it: L.activeAlarms === 1 ? 'allarme' : 'attivi', en: 'active', es: 'activas', fr: 'actives', de: 'aktiv' }) }),
        h(StatusTile, { icon: 'alert', label: t('k.outofrange'), status: L.outOfRange > 0 ? 'warn' : 'run', value: String(L.outOfRange) }),
        h(StatusTile, { icon: 'droplets', label: t('k.outquality'), status: 'conform' }),
        h(StatusTile, { icon: 'layers', label: t('k.sludge'), status: 'run', value: L.sludgeToday + ' t' }),
        h(StatusTile, { icon: 'pump', label: t('k.pumps'), status: runningPumps >= 4 ? 'run' : 'warn', value: runningPumps + '/' + s.pumps.length, sub: t('st.run') }),
        h(StatusTile, { icon: 'power', label: t('k.disinfection'), status: 'run', value: 'UV + Cl₂' }),
        h(StatusTile, { icon: 'flask', label: t('k.reagents'), status: 'run', value: L.reagentsToday + ' kg' }),
        h(StatusTile, { icon: 'thermometer', label: t('p.do'), status: L.doO2 < 1.6 ? 'warn' : 'run', value: L.doO2 + ' mg/L' })),

      // realtime mini synoptic
      h(Card, { cls: 'flush', style: { marginBottom: 'var(--gap)' } },
        h(CardHead, { bordered: true, icon: 'synoptic', title: t('c.realtime'), sub: 'LIVE',
          right: h('div', { className: 'legend' },
            h('span', { className: 'li' }, h('span', { className: 'sw', style: { background: '#2E8BC0' } }), t('grp.primary')),
            h('span', { className: 'li' }, h('span', { className: 'sw', style: { background: '#F2941F' } }), t('grp.waste')),
            h('span', { className: 'li' }, h('span', { className: 'sw', style: { background: '#8B6F47' } }), tl({ it: 'Fanghi', en: 'Sludge', es: 'Fangos', fr: 'Boues', de: 'Schlamm' }))) }),
        h('div', { style: { padding: 16 } }, h(MiniFlow, { sim: sim.running }))),

      // charts grid
      h('div', { className: 'grid g2', style: { marginBottom: 'var(--gap)' } },
        h(Card, null, h(CardHead, { icon: 'chart', title: t('ch.hourlyflow'), sub: 'm³/h · 24h',
          right: h('div', { className: 'legend' }, h('span', { className: 'li' }, h('span', { className: 'sw', style: { background: '#2E8BC0' } }), t('grp.primary')), h('span', { className: 'li' }, h('span', { className: 'sw', style: { background: '#F2941F' } }), t('grp.waste'))) }),
          h(window.LineChart, { series: [{ data: H.flowPrimary, color: '#2E8BC0' }, { data: H.flowWaste, color: '#F2941F' }], xLabels: xl24, h: 190, fixedMax: 160 })),
        h(Card, null, h(CardHead, { icon: 'gauge', title: t('ch.quality'), sub: '% · 24h',
          right: h('div', { className: 'legend' }, h('span', { className: 'li' }, h('span', { className: 'sw', style: { background: '#1E9E5A' } }), t('c.outlet')), h('span', { className: 'li' }, h('span', { className: 'sw', style: { background: '#9AA6B2' } }), t('c.inlet'))) }),
          h(window.LineChart, { series: [{ data: H.qualityOut, color: '#1E9E5A' }, { data: H.qualityIn, color: '#9AA6B2' }], xLabels: xl24, h: 190, fixedMax: 100 }))),

      h('div', { className: 'grid g4', style: { marginBottom: 'var(--gap)' } },
        h(Card, null, h(CardHead, { icon: 'zap', title: t('ch.energy'), sub: 'kWh' }), h(window.AreaChart, { data: H.energy, color: '#8B5CF6', xLabels: xl24, h: 150 })),
        h(Card, null, h(CardHead, { icon: 'droplet', title: t('ch.turbidity'), sub: 'NTU' }), h(window.AreaChart, { data: H.turbidityOut, color: '#2E8BC0', xLabels: xl24, h: 150, fixedMax: 1.6 })),
        h(Card, null, h(CardHead, { icon: 'flask', title: t('ch.codbod'), sub: 'mg/L · out' }), h(window.LineChart, { series: [{ data: H.codOut, color: '#F2941F' }], xLabels: xl24, h: 150, fixedMax: 80 })),
        h(Card, null, h(CardHead, { icon: 'activity', title: t('ch.ph'), sub: '6–8' }), h(window.LineChart, { series: [{ data: H.ph, color: '#1E9E5A' }], xLabels: xl24, h: 150, fixedMin: 6, fixedMax: 9 }))),

      h('div', { className: 'grid g2' },
        h(Card, null, h(CardHead, { icon: 'layers', title: t('ch.sludgeprod'), sub: 't/d · 14d' }), h(window.BarChart, { data: H.sludge, color: '#8B6F47', h: 170 })),
        h(Card, { cls: 'flush' }, h(CardHead, { bordered: true, icon: 'bell', title: t('nav.alarms'), sub: s.alarms.filter((a) => a.state === 'open').length + ' ' + t('al.open'), right: h(GoBtn, { to: 'alarms' }) }),
          h(AlarmMini, null)))
    );
  }

  function GoBtn({ to }) {
    const { setRoute, t } = window.useApp();
    return h('button', { className: 'btn btn-ghost btn-sm', onClick: () => setRoute(to) }, t('a.viewall'), h(Icon, { name: 'chevRight', size: 14 }));
  }

  function AlarmMini() {
    const s = window.useStore();
    const { t, tl } = window.useApp();
    const open = s.alarms.filter((a) => a.state !== 'resolved').slice(0, 5);
    if (!open.length) return h(window.Empty, { msg: t('m.noalarms') });
    return h('div', null, open.map((a) => h('div', { key: a.id, style: { display: 'flex', alignItems: 'center', gap: 12, padding: '12px 22px', borderBottom: '1px solid var(--border)' } },
      h(SDot, { status: a.sev }),
      h('div', { style: { flex: 1, minWidth: 0 } },
        h('div', { style: { fontSize: 13.5, fontWeight: 600, color: 'var(--fg-1)' } }, tl(a)),
        h('div', { className: 'mono', style: { fontSize: 11, color: 'var(--fg-3)' } }, a.code, ' · ', a.ts)),
      h(Badge, { status: a.sev }))));
  }

  // ---- Mini flow (dashboard) ----
  function MiniFlow({ sim }) {
    const { t } = window.useApp();
    const steps = [
      { ic: 'droplet', l: t('grp.primary'), c: '#2E8BC0' },
      { ic: 'filter', l: t('nav.potable'), c: '#2E8BC0' },
      { ic: 'power', l: t('k.disinfection'), c: '#2E8BC0' },
      { ic: 'tank', l: tl_('Serbatoio', 'Storage'), c: '#2E8BC0' },
    ];
    const steps2 = [
      { ic: 'recycle', l: t('c.inlet'), c: '#F2941F' },
      { ic: 'beaker', l: tl_('Biologico', 'Biological'), c: '#F2941F' },
      { ic: 'layers', l: tl_('Sedim.', 'Settling'), c: '#F2941F' },
      { ic: 'droplets', l: t('c.outlet'), c: '#1E9E5A' },
    ];
    function tl_(it, en) { const lang = window.STORE.state.lang; return lang === 'it' ? it : en; }
    const Row = ({ arr }) => h('div', { style: { display: 'flex', alignItems: 'center', gap: 0, flexWrap: 'wrap' } },
      arr.map((st, i) => h(React.Fragment, { key: i },
        h('div', { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, minWidth: 80 } },
          h('div', { style: { width: 46, height: 46, borderRadius: 10, background: `color-mix(in srgb,${st.c} 12%,var(--bg-surface))`, border: `1.5px solid ${st.c}`, color: st.c, display: 'flex', alignItems: 'center', justifyContent: 'center' } }, h(Icon, { name: st.ic, size: 22 })),
          h('div', { style: { fontSize: 11, fontWeight: 600, color: 'var(--fg-2)', textAlign: 'center' } }, st.l)),
        i < arr.length - 1 && h('div', { style: { flex: 1, minWidth: 28, height: 3, position: 'relative', margin: '0 4px', marginBottom: 22 } },
          h('svg', { width: '100%', height: 3, style: { overflow: 'visible' } },
            h('line', { x1: 0, y1: 1.5, x2: '100%', y2: 1.5, stroke: st.c, strokeWidth: 3, strokeOpacity: 0.3 }),
            h('line', { x1: 0, y1: 1.5, x2: '100%', y2: 1.5, stroke: st.c, strokeWidth: 3, className: 'flow-dash' + (sim ? '' : ' '), style: sim ? null : { animationPlayState: 'paused' } }))))));
    return h('div', { className: sim ? '' : 'sim-paused', style: { display: 'flex', flexDirection: 'column', gap: 18 } },
      h(Row, { arr: steps }), h(Row, { arr: steps2 }));
  }

  // ============================================================
  // SYNOPTIC (full P&ID)
  // ============================================================
  function Synoptic() {
    const s = window.useStore();
    const { t, tl, sim } = window.useApp();
    const [sel, setSel] = useState(null);

    // node defs: {id,x,y,w,h,icon,label,kind,line,value,status}
    const NW = 118, NH = 56;
    const primary = [
      { id: 'CAP', x: 30, label: tl({ it: 'Captazione', en: 'Intake', es: 'Captación', fr: 'Captage', de: 'Entnahme' }), icon: 'droplet', kind: 'tank', val: '120 m³/h', st: 'run' },
      { id: 'P-101', x: 175, label: tl({ it: 'Pompe ingresso', en: 'Intake pumps', es: 'Bombas', fr: 'Pompes', de: 'Pumpen' }), icon: 'pump', kind: 'pump', val: '3.4 bar', st: 'run' },
      { id: 'GRG', x: 320, label: tl({ it: 'Grigliatura', en: 'Screening', es: 'Cribado', fr: 'Dégrillage', de: 'Rechen' }), icon: 'filter', kind: 'filter', val: 'OK', st: 'run' },
      { id: 'DISS', x: 465, label: tl({ it: 'Dissabbiatura', en: 'Grit removal', es: 'Desarenado', fr: 'Dessablage', de: 'Sandfang' }), icon: 'layers', kind: 'tank', val: 'OK', st: 'run' },
      { id: 'COAG', x: 610, label: tl({ it: 'Coag/Flocc', en: 'Coag/Flocc', es: 'Coag/Floc', fr: 'Coag/Floc', de: 'Koag/Flock' }), icon: 'beaker', kind: 'tank', val: '96%', st: 'run' },
      { id: 'DEC', x: 755, label: tl({ it: 'Decantazione', en: 'Settling', es: 'Decantación', fr: 'Décantation', de: 'Klärung' }), icon: 'tank', kind: 'tank', val: '93%', st: 'run' },
      { id: 'FILT', x: 900, label: tl({ it: 'Filtri sabbia/CA', en: 'Sand/AC filters', es: 'Filtros', fr: 'Filtres', de: 'Filter' }), icon: 'filter', kind: 'filter', val: 'Δp 0.4', st: 'run' },
      { id: 'UF', x: 1045, label: tl({ it: 'Ultrafiltraz.', en: 'Ultrafiltration', es: 'Ultrafiltr.', fr: 'Ultrafiltr.', de: 'Ultrafiltr.' }), icon: 'grid', kind: 'filter', val: '97%', st: 'run' },
      { id: 'RO', x: 1190, label: tl({ it: 'Osmosi inversa', en: 'Reverse osmosis', es: 'Ósmosis', fr: 'Osmose', de: 'Osmose' }), icon: 'grid', kind: 'filter', val: '12.4 bar', st: 'warn' },
      { id: 'UV', x: 1335, label: tl({ it: 'Disinfez. UV/Cl', en: 'UV/Cl disinfect', es: 'Desinf. UV/Cl', fr: 'Désinf. UV/Cl', de: 'UV/Cl' }), icon: 'power', kind: 'device', val: '99%', st: 'run' },
      { id: 'TK-05', x: 1480, label: tl({ it: 'Serbatoio trattata', en: 'Treated tank', es: 'Depósito', fr: 'Réservoir', de: 'Reinwasser' }), icon: 'tank', kind: 'tank', val: '81%', st: 'run' },
    ];
    const waste = [
      { id: 'WIN', x: 30, label: tl({ it: 'Ingresso refluo', en: 'WW inlet', es: 'Entrada', fr: 'Entrée', de: 'Zulauf' }), icon: 'recycle', kind: 'tank', val: '85 m³/h', st: 'run' },
      { id: 'GRG2', x: 175, label: tl({ it: 'Grigliatura', en: 'Screening', es: 'Cribado', fr: 'Dégrillage', de: 'Rechen' }), icon: 'filter', kind: 'filter', val: 'OK', st: 'run' },
      { id: 'DISO', x: 320, label: tl({ it: 'Diss./Disoleat.', en: 'Grit/de-oil', es: 'Desarenado', fr: 'Dessablage', de: 'Sandfang' }), icon: 'layers', kind: 'tank', val: 'OK', st: 'run' },
      { id: 'TK-02', x: 465, label: tl({ it: 'Equalizzazione', en: 'Equalization', es: 'Homogeneiz.', fr: 'Égalisation', de: 'Ausgleich' }), icon: 'tank', kind: 'tank', val: '88%', st: 'warn' },
      { id: 'PRIM', x: 610, label: tl({ it: 'Tratt. primario', en: 'Primary', es: 'Primario', fr: 'Primaire', de: 'Vorklärung' }), icon: 'tank', kind: 'tank', val: 'OK', st: 'run' },
      { id: 'TK-03', x: 755, label: tl({ it: 'Vasca biologica', en: 'Bio basin', es: 'Biológico', fr: 'Biologique', de: 'Belebung' }), icon: 'beaker', kind: 'tank', val: 'DO 2.1', st: 'run' },
      { id: 'BLOW', x: 900, label: tl({ it: 'Soffianti', en: 'Blowers', es: 'Soplantes', fr: 'Surpresseurs', de: 'Gebläse' }), icon: 'wind', kind: 'device', val: '2/2', st: 'run' },
      { id: 'TK-04', x: 1045, label: tl({ it: 'Sediment. sec.', en: 'Sec. settling', es: 'Decant. sec.', fr: 'Décant. sec.', de: 'Nachklärung' }), icon: 'tank', kind: 'tank', val: '55%', st: 'run' },
      { id: 'TERZ', x: 1190, label: tl({ it: 'Tratt. terziario', en: 'Tertiary', es: 'Terciario', fr: 'Tertiaire', de: 'Tertiär' }), icon: 'filter', kind: 'filter', val: '12 NTU', st: 'run' },
      { id: 'DIS2', x: 1335, label: tl({ it: 'Disinfezione', en: 'Disinfection', es: 'Desinfección', fr: 'Désinfection', de: 'Desinfektion' }), icon: 'power', kind: 'device', val: 'OK', st: 'run' },
      { id: 'SCAR', x: 1480, label: tl({ it: 'Scarico finale', en: 'Discharge', es: 'Vertido', fr: 'Rejet', de: 'Einleitung' }), icon: 'droplets', kind: 'tank', val: 'COD 42', st: 'run' },
    ];
    const sludge = [
      { id: 'TK-08', x: 755, label: tl({ it: 'Vasca fanghi', en: 'Sludge basin', es: 'Tanque fangos', fr: 'Bassin boues', de: 'Schlamm' }), icon: 'tank', kind: 'tank', val: '38%', st: 'run' },
      { id: 'ISP', x: 1045, label: tl({ it: 'Ispessitore', en: 'Thickener', es: 'Espesador', fr: 'Épaississeur', de: 'Eindicker' }), icon: 'layers', kind: 'tank', val: 'OK', st: 'run' },
      { id: 'CF', x: 1335, label: tl({ it: 'Centrifuga', en: 'Centrifuge', es: 'Centrífuga', fr: 'Centrifuge', de: 'Zentrifuge' }), icon: 'fan', kind: 'device', val: '22%', st: 'run' },
    ];

    const Y1 = 70, Y2 = 250, Y3 = 420;
    const allNodes = [...primary.map((n) => ({ ...n, y: Y1, line: 'primary' })), ...waste.map((n) => ({ ...n, y: Y2, line: 'waste' })), ...sludge.map((n) => ({ ...n, y: Y3, line: 'sludge' }))];

    function pipe(x1, y1, x2, y2, color, key, rev) {
      const midX = x1 + (x2 - x1) / 2;
      const d = y1 === y2 ? `M${x1} ${y1} H${x2}` : `M${x1} ${y1} H${midX} V${y2} H${x2}`;
      return h('g', { key },
        h('path', { d, fill: 'none', stroke: color, strokeWidth: 5, strokeOpacity: 0.22, strokeLinecap: 'round' }),
        h('path', { d, fill: 'none', stroke: color, strokeWidth: 3.2, strokeLinecap: 'round', className: 'flow-dash' + (rev ? ' rev' : ''), style: sim.running ? null : { animationPlayState: 'paused' } }));
    }

    function colorFor(line) { return line === 'primary' ? '#2E8BC0' : line === 'waste' ? '#F2941F' : '#8B6F47'; }

    const node = (n) => {
      const inf = window.statusInfo(n.st);
      const col = colorFor(n.line);
      return h('g', { key: n.id, className: 'pid-node', onClick: () => setSel(n), transform: `translate(${n.x},${n.y})` },
        h('rect', { className: 'pid-box', width: NW, height: NH, rx: 8, fill: 'var(--bg-surface)', stroke: col, strokeWidth: 1.5 }),
        h('rect', { width: 4, height: NH, rx: 2, fill: col }),
        h('circle', { cx: NW - 13, cy: 13, r: 5, fill: `var(--status-${inf.cls})`, className: n.st === 'alarm' ? '' : '' }),
        h('g', { transform: 'translate(11,11)', color: col }, h(Icon, { name: n.icon, size: 22 })),
        h('text', { x: 11, y: 48, fontSize: 11, fontWeight: 700, fill: 'var(--fg-1)', fontFamily: 'Titillium Web' }, n.id),
        h('text', { x: 42, y: 30, fontSize: 10.5, fill: 'var(--fg-2)', fontFamily: 'Titillium Web', fontWeight: 600 }, clip(n.label, 13)),
        h('text', { x: 42, y: 44, fontSize: 10, fill: 'var(--fg-3)', fontFamily: 'IBM Plex Mono,monospace' }, n.val));
    };
    function clip(str, n) { return str.length > n ? str.slice(0, n - 1) + '…' : str; }

    const pipes = [];
    const linePipe = (arr, y, color, off) => { for (let i = 0; i < arr.length - 1; i++) pipes.push(pipe(arr[i].x + NW, y + NH / 2, arr[i + 1].x, y + NH / 2, color, 'p' + off + i)); };
    linePipe(primary, Y1, '#2E8BC0', 'a');
    linePipe(waste, Y2, '#F2941F', 'b');
    // sludge taps from settling tanks down to sludge line
    pipes.push(pipe(755 + NW / 2, Y2 + NH, 755 + NW / 2, Y3, '#8B6F47', 'sl1'));
    pipes.push(pipe(1045 + NW / 2, Y2 + NH, 1045 + NW / 2, Y3, '#8B6F47', 'sl2', true));
    pipes.push(pipe(755 + NW, Y3 + NH / 2, 1045, Y3 + NH / 2, '#8B6F47', 'sl3'));
    pipes.push(pipe(1045 + NW, Y3 + NH / 2, 1335, Y3 + NH / 2, '#8B6F47', 'sl4'));
    // recirc sludge back (CF -> bio)
    pipes.push(pipe(1335 + NW / 2, Y3 + NH, 1335 + NW / 2, Y3 + NH + 22, '#8B6F47', 'rec1'));

    const VBW = 1612, VBH = Y3 + NH + 50;

    return h('div', { className: 'page' },
      h('div', { className: 'toolbar' },
        h('div', { className: 'legend', style: { gap: 22 } },
          h('span', { className: 'li' }, h('span', { className: 'sw', style: { background: '#2E8BC0', width: 16 } }), tl({ it: 'Linea acque primarie', en: 'Primary water line', es: 'Línea primaria', fr: 'Ligne eaux primaires', de: 'Primärlinie' })),
          h('span', { className: 'li' }, h('span', { className: 'sw', style: { background: '#F2941F', width: 16 } }), tl({ it: 'Linea acque reflue', en: 'Wastewater line', es: 'Línea residual', fr: 'Ligne eaux usées', de: 'Abwasserlinie' })),
          h('span', { className: 'li' }, h('span', { className: 'sw', style: { background: '#8B6F47', width: 16 } }), tl({ it: 'Linea fanghi', en: 'Sludge line', es: 'Línea fangos', fr: 'Filière boues', de: 'Schlammlinie' }))),
        h('span', { className: 'spacer' }),
        h(Badge, { status: sim.running ? 'run' : 'idle', label: sim.running ? t('sim.on') : t('sim.off'), pulse: sim.running }),
        h('button', { className: 'btn btn-ghost btn-sm', onClick: sim.running ? sim.pause : sim.start }, h(Icon, { name: sim.running ? 'pause' : 'play', size: 14 }), sim.running ? t('sim.pause') : t('sim.start'))),
      h('div', { className: 'synoptic-wrap', style: { padding: 8 } },
        h('div', { style: { overflowX: 'auto' } },
          h('svg', { viewBox: `0 0 ${VBW} ${VBH}`, style: { width: '100%', minWidth: 1100, height: 'auto', display: 'block' } },
            h('text', { x: 30, y: 24, fontSize: 12, fontWeight: 700, fill: '#2E8BC0', fontFamily: 'IBM Plex Mono,monospace', letterSpacing: '.08em' }, 'A · ' + tl({ it: 'ACQUE PRIMARIE', en: 'PRIMARY WATER', es: 'AGUA PRIMARIA', fr: 'EAUX PRIMAIRES', de: 'PRIMÄRWASSER' })),
            h('text', { x: 30, y: Y2 - 16, fontSize: 12, fontWeight: 700, fill: '#F2941F', fontFamily: 'IBM Plex Mono,monospace', letterSpacing: '.08em' }, 'B · ' + tl({ it: 'ACQUE REFLUE', en: 'WASTEWATER', es: 'AGUAS RESIDUALES', fr: 'EAUX USÉES', de: 'ABWASSER' })),
            h('text', { x: 30, y: Y3 - 16, fontSize: 12, fontWeight: 700, fill: '#8B6F47', fontFamily: 'IBM Plex Mono,monospace', letterSpacing: '.08em' }, 'C · ' + tl({ it: 'LINEA FANGHI', en: 'SLUDGE LINE', es: 'LÍNEA FANGOS', fr: 'FILIÈRE BOUES', de: 'SCHLAMMLINIE' })),
            pipes, allNodes.map(node)))),
      sel && h(NodeDrawer, { node: sel, onClose: () => setSel(null) }));
  }

  function NodeDrawer({ node, onClose }) {
    const { t, tl, toast } = window.useApp();
    const s = window.useStore();
    const [mode, setMode] = useState('auto');
    const pump = s.pumps.find((p) => p.id === node.id);
    const tank = s.tanks.find((x) => x.id === node.id);
    return h(Drawer, {
      title: node.label, sub: node.id, icon: node.icon, status: node.st, onClose,
      footer: [
        h(Btn, { key: 1, variant: 'run', icon: 'play', sm: true, onClick: () => { if (pump) window.STORE.setPumpState(node.id, 'run'); toast('run', t('toast.pumpstart'), node.id); } }, t('a.start')),
        h(Btn, { key: 2, variant: 'alarm', icon: 'pause', sm: true, onClick: () => { if (pump) window.STORE.setPumpState(node.id, 'idle'); toast('warn', t('toast.pumpstop'), node.id); } }, t('a.stop')),
        h(Btn, { key: 3, variant: 'ghost', icon: 'reset', sm: true, onClick: () => toast('info', t('a.reset'), node.id) }, t('a.reset')),
      ],
    },
      h('div', { className: 'row', style: { justifyContent: 'space-between', marginBottom: 16 } },
        h('span', { style: { fontSize: 13, color: 'var(--fg-2)' } }, t('c.mode')),
        h(ModeSwitch, { mode, onChange: setMode })),
      h(DList, { items: [
        [t('c.status'), h(Badge, { status: node.st })],
        [t('c.value'), node.val],
        pump && [t('c.runhours'), pump.hours.toLocaleString() + ' h'],
        pump && [t('c.current_a'), pump.amp + ' A'],
        tank && [t('c.level'), tank.lvl + '%'],
        tank && [t('c.capacity'), tank.cap + ' m³'],
        [t('c.lastmaint'), '12/05/26'],
        [t('m.connection'), h(Badge, { status: 'sim', label: t('st.sim') })],
      ].filter(Boolean) }),
      h(DetailSection, { title: t('c.action') },
        h('div', { style: { fontSize: 13, color: 'var(--fg-2)', lineHeight: 1.5 } },
          node.st === 'warn' ? tl({ it: 'Verificare parametri operativi e programmare controllo.', en: 'Check operating parameters and schedule inspection.', es: 'Verificar parámetros y programar control.', fr: 'Vérifier les paramètres et planifier un contrôle.', de: 'Betriebsparameter prüfen und Kontrolle planen.' })
            : tl({ it: 'Componente in funzione regolare. Nessuna azione richiesta.', en: 'Component operating normally. No action required.', es: 'Componente en funcionamiento normal.', fr: 'Composant en fonctionnement normal.', de: 'Komponente in normalem Betrieb.' }))));
  }

  window.Sections = window.Sections || {};
  Object.assign(window.Sections, { Dashboard, Synoptic });
})();
