#!/usr/bin/env python3
"""
PGS-15 Phoenix Metals — Master Generator Script
Genereert: D3 v2.0, D4 v2.0, Kennisdossier, Audit Toolkit v3.0 (4x), eLearning HTML, Quiz HTML+JSON, SCORM zip
"""

import os, json, zipfile, datetime
from docx import Document
from docx.shared import Inches, Pt, Cm, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.enum.section import WD_ORIENT

# ─── Paths ───
BASE = "/root/projects/jg/2026-pgs15-phoenix-metals"
DOCX_DIR = f"{BASE}/deliverables/docx"
HTML_DIR = f"{BASE}/deliverables/html"
SCORM_DIR = f"{BASE}/deliverables/scorm"
LOG_DIR = f"{BASE}/logs"
LOGO_PATH = "/root/projects/jg/assets/branding/jvg-logo-white-medium.png"
LOGO_B64_PATH = "/root/projects/jg/assets/branding/logo-white-base64.txt"

for d in [DOCX_DIR, HTML_DIR, SCORM_DIR, LOG_DIR]:
    os.makedirs(d, exist_ok=True)

# Read base64 logo
try:
    with open(LOGO_B64_PATH, 'r') as f:
        LOGO_B64 = f.read().strip()
except:
    LOGO_B64 = ""

NOW = datetime.datetime.now().strftime("%d %B %Y")
NOW_ISO = datetime.datetime.now().strftime("%Y-%m-%d")

# ─── DOCX Helpers ───
def make_doc(title, subtitle=""):
    doc = Document()
    # Default font
    style = doc.styles['Normal']
    style.font.name = 'Calibri'
    style.font.size = Pt(11)
    style.paragraph_format.space_after = Pt(6)
    # Headers
    for level in range(1, 4):
        hs = doc.styles[f'Heading {level}']
        hs.font.color.rgb = RGBColor(0, 51, 102)
        hs.font.name = 'Calibri'
    # Add header with logo
    section = doc.sections[0]
    section.top_margin = Cm(2.5)
    section.bottom_margin = Cm(2)
    section.left_margin = Cm(2.5)
    section.right_margin = Cm(2.5)
    # Header
    header = section.header
    if os.path.exists(LOGO_PATH):
        hp = header.paragraphs[0]
        hp.alignment = WD_ALIGN_PARAGRAPH.RIGHT
        run = hp.add_run()
        run.add_picture(LOGO_PATH, width=Inches(1.5))
    # Footer
    footer = section.footer
    fp = footer.paragraphs[0]
    fp.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = fp.add_run("JvG Consultancy — ")
    run.font.size = Pt(8)
    run.font.color.rgb = RGBColor(128, 128, 128)
    run2 = fp.add_run(title)
    run2.font.size = Pt(8)
    run2.font.color.rgb = RGBColor(128, 128, 128)
    # Title page
    doc.add_paragraph("")
    doc.add_paragraph("")
    tp = doc.add_paragraph()
    tp.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = tp.add_run(title)
    run.bold = True
    run.font.size = Pt(24)
    run.font.color.rgb = RGBColor(0, 51, 102)
    if subtitle:
        sp = doc.add_paragraph()
        sp.alignment = WD_ALIGN_PARAGRAPH.CENTER
        run = sp.add_run(subtitle)
        run.font.size = Pt(14)
        run.font.color.rgb = RGBColor(80, 80, 80)
    dp = doc.add_paragraph()
    dp.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = dp.add_run(f"Phoenix Metals B.V. — Plant One Rotterdam\n{NOW}")
    run.font.size = Pt(11)
    run.font.color.rgb = RGBColor(100, 100, 100)
    doc.add_paragraph("")
    conf = doc.add_paragraph()
    conf.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = conf.add_run("CONFIDENTIAL — JvG Consultancy")
    run.font.size = Pt(9)
    run.font.color.rgb = RGBColor(180, 0, 0)
    doc.add_page_break()
    return doc

def add_table(doc, headers, rows, col_widths=None):
    table = doc.add_table(rows=1 + len(rows), cols=len(headers))
    table.style = 'Light Grid Accent 1'
    table.alignment = WD_TABLE_ALIGNMENT.CENTER
    # Header row
    for i, h in enumerate(headers):
        cell = table.rows[0].cells[i]
        cell.text = h
        for p in cell.paragraphs:
            for r in p.runs:
                r.bold = True
                r.font.size = Pt(9)
    # Data rows
    for ri, row in enumerate(rows):
        for ci, val in enumerate(row):
            cell = table.rows[ri + 1].cells[ci]
            cell.text = str(val)
            for p in cell.paragraphs:
                for r in p.runs:
                    r.font.size = Pt(9)
    return table

def add_bullet(doc, text, level=0):
    p = doc.add_paragraph(text, style='List Bullet')
    p.paragraph_format.left_indent = Cm(1.27 + level * 0.63)
    return p

# ═══════════════════════════════════════════════════════
# 1. D3 v2.0 — Veiligheidsinfo & Documentatie
# ═══════════════════════════════════════════════════════
def gen_d3():
    doc = make_doc("PGS-15 Veiligheidsinfo & Documentatie", "D3 v2.0 — Phoenix Metals B.V.")
    doc.add_heading("Inhoudsopgave", level=1)
    toc = ["1. Management Summary", "2. Opslaginstructies per Stof", "3. SDS-Vereisten", "4. Tank- en Leidingetikettering", "5. Documentbeheer", "6. PGS 15:2025 Paragraafreferenties"]
    for t in toc:
        doc.add_paragraph(t)
    doc.add_page_break()

    # 1. Management Summary
    doc.add_heading("1. Management Summary", level=1)
    doc.add_paragraph("Dit document (D3 v2.0) bevat de volledige veiligheidsinformatie en documentatiestructuur voor Phoenix Metals B.V., conform PGS 15:2025. Het omvat opslaginstructies per stof, SDS-vereisten, etikettering van tanks en leidingen, en een documentbeheersysteem met 11 verplichte documenttypen.")
    doc.add_paragraph("Belangrijke wijzigingen t.o.v. v1.0:")
    add_bullet(doc, "Volledige uitlijning op PGS 15:2025 Nieuwe Stijl (scenario's S1-S16, maatregelen M1-M167)")
    add_bullet(doc, "Uitgebreide GHS/CLP-etiketteringsspecificaties toegevoegd")
    add_bullet(doc, "Documentbeheer uitgebreid naar 11 verplichte typen")
    add_bullet(doc, "SVHC-monitoring structuur geïntegreerd")

    # 2. Opslaginstructies per Stof
    doc.add_heading("2. Opslaginstructies per Stof", level=1)

    # H2SO4
    doc.add_heading("2.1 Zwavelzuur (H₂SO₄)", level=2)
    add_table(doc,
        ["Parameter", "Waarde"],
        [
            ["ADR-klasse", "8 (Bijtend)"],
            ["UN-nummer", "UN 1830 (>51%) / UN 2796 (≤51%)"],
            ["Verpakkingsgroep", "II"],
            ["CAS-nummer", "7664-93-9"],
            ["H-zinnen", "H290: Kan corrosief zijn voor metalen\nH314: Veroorzaakt ernstige huidverbrandingen en oogletsel"],
            ["Concentraties op voorraad", "25% (4×25L), 50% (7×10L), 75% (3×10L)"],
            ["Totale voorraad", "200 L"],
            ["Veiligheidsniveau", "Basis (onbrandbaar, dedicated opslag)"],
            ["Wbdbo-eis", "Geen (onbrandbaar ADR-8 VG II)"],
            ["Opvangcapaciteit", "110% grootste verpakking of 10% totaal"],
        ]
    )
    doc.add_paragraph("")
    doc.add_heading("Opslagvereisten H₂SO₄", level=3)
    add_bullet(doc, "Vorstvrij, droog en goed geventileerd opslaan")
    add_bullet(doc, "GESCHEIDEN van basen (NaOH) — PGS 15:2025 Bijlage E, §7.3")
    add_bullet(doc, "GESCHEIDEN van oxiderende stoffen (ADR-klasse 5.1)")
    add_bullet(doc, "GESCHEIDEN van brandbare stoffen (ADR-klasse 3)")
    add_bullet(doc, "Neutralisatiemiddel beschikbaar: natriumcarbonaat (soda)")
    add_bullet(doc, "Opvangvoorziening bestand tegen zwavelzuur (geen onbeschermd metaal)")
    add_bullet(doc, "Nooddouche + oogdoucher vereist binnen 10 seconde loopafstand")
    add_bullet(doc, "PBM's: zuurbestendige handschoenen (nitril), veiligheidsbril/face shield, beschermende kleding")
    add_bullet(doc, "Condenscorrosie voorkomen bij buitenopslag")

    # NaOH
    doc.add_heading("2.2 Natriumhydroxide (NaOH 50%)", level=2)
    add_table(doc,
        ["Parameter", "Waarde"],
        [
            ["ADR-klasse", "8 (Bijtend)"],
            ["UN-nummer", "UN 1824"],
            ["Verpakkingsgroep", "II"],
            ["CAS-nummer", "1310-73-2"],
            ["H-zinnen", "H290: Kan corrosief zijn voor metalen\nH314: Veroorzaakt ernstige huidverbrandingen en oogletsel"],
            ["Concentratie", "50% oplossing"],
            ["Hoeveelheid", "4×25L = 100L"],
            ["Veiligheidsniveau", "Basis (onbrandbaar, dedicated opslag)"],
            ["Kristallisatiepunt", "~12°C — temperatuurbewaking + verwarmingstracing vereist"],
            ["Minimale opslagtemperatuur", ">15°C aanbevolen"],
        ]
    )
    doc.add_paragraph("")
    doc.add_heading("Opslagvereisten NaOH", level=3)
    add_bullet(doc, "Vorstvrij opslaan: >15°C aanbevolen (kristallisatierisico bij <12°C)")
    add_bullet(doc, "Temperatuurbewaking met alarm bij <12°C (PGS 15:2025 M30)")
    add_bullet(doc, "Verwarmingstracing op leidingen bij outside opslag")
    add_bullet(doc, "GESCHEIDEN van zuren (H₂SO₄) — PGS 15:2025 Bijlage E")
    add_bullet(doc, "GESCHEIDEN van amfotere metalen (aluminium, zink)")
    add_bullet(doc, "Neutralisatiemiddel beschikbaar: citroenzuur of azijnzuuroplossing")
    add_bullet(doc, "PBM's: bijtwerende handschoenen (nitril/neopreen), veiligheidsbril, beschermkleding")

    # Vanadium
    doc.add_heading("2.3 Vanadiumoplossingen", level=2)
    add_table(doc,
        ["Parameter", "Waarde"],
        [
            ["ADR-klasse", "9 (Milieugevaarlijk)"],
            ["UN-nummer", "UN 3082 (waarschijnlijk)"],
            ["Verpakkingsgroep", "III"],
            ["CAS-nummer", "To be confirmed (vanadium compound specifiek)"],
            ["Toxiciteit", "Acuut toxisch bij inademing (vanadiumpentoxide)"],
            ["Milieugevaarlijkheid", "Ja — 'Dode boom/vis' symbool verplicht (ADR 5.2.1.8.3)"],
            ["Veiligheidsniveau", "Basis (onbrandbaar/niet brandonderhoudend)"],
            ["Bluswateropvang", "100% van nominale capaciteit (bij veiligheidsniveau A)"],
        ]
    )
    doc.add_paragraph("")
    doc.add_heading("Opslagvereisten Vanadium", level=3)
    add_bullet(doc, "SDS nog ontbrekend — ACTION: correcte MSDS vanadiumconcentraat aanvragen")
    add_bullet(doc, "GESCHEIDEN van stoffen waarmee reactie mogelijk is (op basis van SDS)")
    add_bullet(doc, "Milieugevaarlijk: voorkomen lozing naar riool/oppervlaktewater")
    add_bullet(doc, "Absorptiemateriaal beschikbaar voor lekkage")
    add_bullet(doc, "PBM's: handschoenen, veiligheidsbril, beschermende kleding, evt. adembescherming")

    doc.add_page_break()

    # 3. SDS-Vereisten
    doc.add_heading("3. SDS-Vereisten", level=1)
    doc.add_heading("3.1 Wettelijk kader", level=2)
    doc.add_paragraph("SDS (Safety Data Sheets / Veiligheidsinformatiebladen) zijn verplicht conform REACH art. 31 en CLP-verordening EG 1272/2008. PGS 15:2025 M137 vereist dat SDS beschikbaar zijn voor alle opgeslagen gevaarlijke stoffen.")
    
    doc.add_heading("3.2 SDS-overzicht Phoenix Metals", level=2)
    add_table(doc,
        ["Stof", "SDS Beschikbaar", "Leverancier", "Status", "Actie"],
        [
            ["H₂SO₄ 25%", "Ja", "RCI Labscan", "Actueel", "Geen"],
            ["H₂SO₄ 50%", "Ja", "RCI Labscan", "Actueel", "Geen"],
            ["H₂SO₄ 75%", "Ja", "RCI Labscan", "Actueel", "Geen"],
            ["NaOH 50%", "Ja", "Merck/Millipore", "Actueel", "Geen"],
            ["Vanadiumconcentraat", "❌ NEE", "—", "Ontbrekend", "⚠️ ACTIE: SDS aanvragen"],
            ["Aluminiumsulfaat", "Niet geregistreerd als gevaarlijk", "—", "—", "Controleren"],
            ["Calciumoxide", "Niet geregistreerd als gevaarlijk", "—", "—", "Controleren"],
        ]
    )

    doc.add_heading("3.3 SDS-beheereisen", level=2)
    add_bullet(doc, "Taal: Nederlands (officiële taal lidstaat conform REACH)")
    add_bullet(doc, "Actualiteit: maximaal 5 jaar, herzien bij nieuwe informatie")
    add_bullet(doc, "Toegankelijkheid: digitaal én fysiek beschikbaar voor alle medewerkers")
    add_bullet(doc, "REACH 16-sectie formaat verplicht")
    add_bullet(doc, "Archivering: vervallen SDS bewaren voor 10 jaar (Arbowet)")
    add_bullet(doc, "SVHC-monitoring: controleer ECHA-candidaatlijst 2x/jaar op nieuwe SVHC-stoffen")

    doc.add_page_break()

    # 4. Tank- en Leidingetikettering
    doc.add_heading("4. Tank- en Leidingetikettering", level=1)
    doc.add_heading("4.1 Tanketikettering (PGS 15:2025 §7.2, M135-M136)", level=2)
    doc.add_paragraph("Elke tank en opslageenheid moet voorzien zijn van een etiket met minimaal de volgende elementen conform CLP en PGS 15:2025:")
    
    add_table(doc,
        ["Element", "Vereiste", "Specificatie"],
        [
            ["Productnaam", "Verplicht", "Volledige chemische naam"],
            ["CAS-nummer", "Verplicht", "Uniek identificatienummer"],
            ["GHS-pictogrammen", "Verplicht", "Minimaal 10×10 cm, conform NEN-EN-ISO 20560"],
            ["Signaalwoord", "Verplicht", "GEVAAR of WAARSCHUWING"],
            ["H-zinnen", "Verplicht", "Alle relevante H-zinnen"],
            ["P-zinnen", "Verplicht", "Relevante voorzorgsmaatregelen"],
            ["UN-nummer", "Verplicht", "ADR-classificatie"],
            ["Tankinhoud", "Verplicht", "Volume in liters"],
            ["Leverancier", "Verplicht", "Naam + contactgegevens"],
            ["Noodtelefoon", "Verplicht", "24/7 bereikbaar nummer"],
        ]
    )

    doc.add_heading("4.2 GHS-pictogrammen per stof", level=2)
    add_table(doc,
        ["Stof", "GHS-pictogram(men)", "Signaalwoord"],
        [
            ["H₂SO₄", "GHS05 (Corrosief) + GHS07 (Exclamatie)", "GEVAAR"],
            ["NaOH 50%", "GHS05 (Corrosief)", "GEVAAR"],
            ["Vanadiumoplossing", "GHS07 (Exclamatie) + GHS09 (Milieu)", "WAARSCHUWING"],
        ]
    )

    doc.add_heading("4.3 Leidingetikettering", level=2)
    add_bullet(doc, "Stofnaam duidelijk leesbaar op leiding")
    add_bullet(doc, "Stroomrichtingspijl")
    add_bullet(doc, "Gevarensymbolen conform NEN-EN-ISO 20560")
    add_bullet(doc, "Kleurcodering: conform Arboregeling art. 8.12-8.14")
    add_bullet(doc, "Etikettering op relevante afstanden (bijv. bij elke verbinding, klep en wanddoorvoer)")

    doc.add_heading("4.4 Waarschuwingsborden opslagvoorziening", level=2)
    add_bullet(doc, "ADR-etiket klasse 8 (corrosief): minimaal 20×20 cm aan buitenzijde — PGS 15:2025 M135")
    add_bullet(doc, "Verbodsbord 'Vuur, open vlam en roken verboden' (NEN-EN-ISO 7010) — PGS 15:2025 M68/M134")
    add_bullet(doc, "Toegangsbeperking: 'Alleen bevoegd personeel' — PGS 15:2025 M36")
    add_bullet(doc, "Calamiteiteninstructie zichtbaar bij toegang — PGS 15:2025 M121")

    doc.add_page_break()

    # 5. Documentbeheer
    doc.add_heading("5. Documentbeheer — 11 Verplichte Documenttypen", level=1)
    doc.add_paragraph("PGS 15:2025 vereist dat de volgende documenttypen actueel, toegankelijk en gecontroleerd zijn:")
    
    add_table(doc,
        ["#", "Documenttype", "PGS 15:2025 Maatregel", "Verantwoordelijke", "Frequentie update"],
        [
            ["1", "Stoffenlijst (gevaarlijke stoffen register)", "M116", "HSE Manager", "Continu (bij wijziging)"],
            ["2", "Veiligheidsinformatiebladen (VIB/SDS)", "M137 / REACH art. 31", "HSE Manager", "Max 5 jaar / bij nieuwe info"],
            ["3", "Plattegrond opslaglocatie", "M116", "Facility Manager", "Bij wijziging opslag"],
            ["4", "Calamiteiteninstructie", "M121", "HSE Manager", "Jaarlijks / bij wijziging"],
            ["5", "Lekkage-instructie", "M120", "HSE Manager", "Jaarlijks"],
            ["6", "Noodplan (intern)", "M115", "HSE Manager", "Jaarlijks"],
            ["7", "RI&E (Risico-inventarisatie)", "Arbowet art. 5", "HSE Manager + Arbocoördinator", "Jaarlijks of bij wijziging"],
            ["8", "Keuringsrapporten", "M36", "Facility Manager", "Per keuring"],
            ["9", "UPD (Uitgangspuntendocument VBB)", "M99", "VBB-ontwerper", "Bij installatie/wijziging"],
            ["10", "Brandwerendheidsrapportage (Wbdbo)", "M21/M24/M25", "Bouwkundig adviseur", "Bij wijziging constructie"],
            ["11", "Opleidings- en trainingsrecords", "§7.4.3 / M85", "HR / HSE Manager", "Per trainingssessie"],
        ]
    )

    doc.add_heading("5.1 Documentcontrol-procedure", level=2)
    add_bullet(doc, "Alle documenten voorzien van versienummer, datum en goedkeuringsstatus")
    add_bullet(doc, "Documenteigenaar verantwoordelijk voor actualiteit")
    add_bullet(doc, "Verouderde versies naar archief (niet verwijderen)")
    add_bullet(doc, "Jaarlijkse documentenreview door HSE Manager")
    add_bullet(doc, "Stoffenlijst + plattegrond als hardcopy aan brandweer (M116-M118)")

    doc.add_page_break()

    # 6. Paragraafreferenties
    doc.add_heading("6. PGS 15:2025 Paragraafreferenties", level=1)
    add_table(doc,
        ["Onderwerp", "PGS 15:2025 Paragraaf", "Maatregel(en)"],
        [
            ["Opslaginstructies", "§7.3 (Scheiding & Vakindeling)", "M21, M29, M30"],
            ["SDS-vereisten", "§7.5 (Administratieve eisen)", "M137"],
            ["Etikettering", "§7.5.3 (Signalering)", "M135, M136"],
            ["Tanketikettering", "§7.2 + NEN-EN-ISO 20560", "M135"],
            ["Leidingetikettering", "§7.2 + Arboregeling 8.12-8.14", "M136"],
            ["Opvangcapaciteit", "§7.1 (Opvangvoorzieningen)", "M29, M30, M32"],
            ["Scheiding zuren/basen", "§7.3 + Bijlage E", "—"],
            ["Brandveiligheid", "§7.2 (Brandpreventie)", "M68, M71-M73, M95-M99, M134"],
            ["Arbeidsveiligheid", "§7.3 (Arbeidsveiligheid)", "M85, M88, M120"],
            ["Documenten", "§7.5 (Administratief)", "M115-M118, M120, M121, M137"],
            ["Scenariostudie", "§6 (Scenariostudie)", "S1-S16, D1-D13"],
            ["Maatregelen", "§6-§7", "M1-M167, MW1"],
        ]
    )

    doc.save(f"{DOCX_DIR}/PGS15_Veiligheidsinfo_Documentatie_Phoenix_Metals_D3_v2.0.docx")
    print("✅ D3 v2.0 gegenereerd")


# ═══════════════════════════════════════════════════════
# 2. D4 v2.0 — Master SOP Opslagveiligheid
# ═══════════════════════════════════════════════════════
def gen_d4():
    doc = make_doc("PGS-15 Master SOP Opslagveiligheid", "D4 v2.0 — Phoenix Metals B.V.")
    
    doc.add_heading("Inhoudsopgave", level=1)
    toc_items = [
        "1. Management Summary", "2. Doel en Toepassingsgebied", "3. Definities en Afkortingen",
        "4. Verantwoordelijkheden (RASCI)", "5. Procedures",
        "  5.1 P-01: Tankniveaubewaking", "  5.2 P-02: Temperatuurbewaking", "  5.3 P-03: Lekdetectie",
        "  5.4 P-04: Inventarisatie Stoffen", "  5.5 P-05: Laad- en Losoperaties",
        "  5.6 P-06: Inspectie Verpakkingen", "  5.7 P-07: Onderhoud Opslagvoorzieningen",
        "  5.8 P-08: Incidentmanagement", "  5.9 P-09: Noodprocedure Lekkage",
        "  5.10 P-10: Noodprocedure Brand", "  5.11 P-11: SVHC-Monitoring",
        "  5.12 P-12: Etikettering en Signalering", "  5.13 P-13: Documentbeheer",
        "  5.14 P-14: Opleiding en Training", "  5.15 P-15: Interne Audit",
        "6. KPI's", "7. Toelichtend Stuk", "8. Referenties"
    ]
    for t in toc_items:
        doc.add_paragraph(t)
    doc.add_page_break()

    # 1. Management Summary
    doc.add_heading("1. Management Summary", level=1)
    doc.add_paragraph("Deze Master SOP (D4 v2.0) definieert de operationele procedures voor PGS 15:2025-conforme opslag van gevaarlijke stoffen bij Phoenix Metals B.V., Plant One Rotterdam. Het omvat 15 procedures, een RASCI-matrix, KPI's en een toelichtend stuk met implementatieplan.")
    doc.add_paragraph("Kernpunten:")
    add_bullet(doc, "Alle opslag conform PGS 15:2025 Nieuwe Stijl: basisveiligheidsniveau voor H₂SO₄, NaOH en vanadiumoplossingen")
    add_bullet(doc, "Strikte scheiding zuren (H₂SO₄) en basen (NaOH) — PGS 15:2025 Bijlage E")
    add_bullet(doc, "Temperatuurbewaking NaOH: alarm bij <12°C (kristallisatiepreventie)")
    add_bullet(doc, "15 procedures volledig uitgewerkt met verantwoordelijkheden, stappen en frequenties")
    add_bullet(doc, "RASCI-matrix voor alle procedures toegevoegd")
    add_bullet(doc, "KPI's gekoppeld aan PGS 15:2025 maatregelen")

    # 2. Doel
    doc.add_heading("2. Doel en Toepassingsgebied", level=1)
    doc.add_heading("2.1 Doel", level=2)
    doc.add_paragraph("Zorgen voor veilige, conforme opslag van gevaarlijke stoffen conform PGS 15:2025, ter bescherming van medewerkers, omgeving en bedrijfscontinuïteit.")
    doc.add_heading("2.2 Toepassingsgebied", level=2)
    add_bullet(doc, "Alle opslag van gevaarlijke stoffen bij Phoenix Metals B.V., Plant One Rotterdam")
    add_bullet(doc, "Alle medewerkers, contractanten en bezoekers")
    add_bullet(doc, "ADR-klasse 8 stoffen: H₂SO₄ (25%, 50%, 75%), NaOH 50%")
    add_bullet(doc, "ADR-klasse 9 stoffen: vanadiumoplossingen (UN 3082)")
    doc.add_heading("2.3 Bindendheid", level=2)
    doc.add_paragraph("Deze SOP is BINDEND voor alle medewerkers, contractanten en bezoekers. Overtreding kan leiden tot toegangsverbod en/of disciplinaire maatregelen.")

    # 3. Definities
    doc.add_heading("3. Definities en Afkortingen", level=1)
    add_table(doc,
        ["Term/Afkorting", "Definitie"],
        [
            ["PGS 15:2025", "Publicatiereeks Gevaarlijke Stoffen 15, versie 2025 — Opslag van verpakte gevaarlijke stoffen"],
            ["ADR", "Accord européen relatif au transport international des marchandises Dangereuses par Route"],
            ["SDS/VIB", "Safety Data Sheet / Veiligheidsinformatieblad"],
            ["CLP", "Classification, Labelling and Packaging (EG 1272/2008)"],
            ["REACH", "Registration, Evaluation, Authorisation and Restriction of Chemicals (EG 1907/2006)"],
            ["SVHC", "Substance of Very High Concern (ECHA-kandidaatlijst)"],
            ["ZZS", "Zeer Zorgwekkende Stoffen (RIVM-lijst)"],
            ["Wbdbo", "Weerstand tegen branddoorslag en brandoverslag"],
            ["VBB", "Vastopgestelde brandbeheersings- en brandblussysteem"],
            ["PBM", "Persoonlijke BeschermingsMiddelen"],
            ["RI&E", "Risico-Inventarisatie en -Evaluatie"],
            ["CAPA", "Corrective and Preventive Action"],
            ["RASCI", "Responsible, Accountable, Supporting, Consulted, Informed"],
        ]
    )

    # 4. RASCI
    doc.add_heading("4. Verantwoordelijkheden — RASCI-Matrix", level=1)
    doc.add_paragraph("R = Responsible (uitvoerder), A = Accountable (eindverantwoordelijke), S = Supporting, C = Consulted, I = Informed")
    add_table(doc,
        ["Procedure", "HSE Manager", "Plant Manager", "Operator", "Facility Mgr", "HR"],
        [
            ["P-01 Niveaubewaking", "A", "I", "R", "S", "—"],
            ["P-02 Temperatuurbewaking", "A", "I", "R", "S", "—"],
            ["P-03 Lekdetectie", "A", "I", "R", "S", "—"],
            ["P-04 Inventarisatie", "R", "A", "S", "—", "—"],
            ["P-05 Laad/Los", "A", "I", "R", "S", "—"],
            ["P-06 Inspectie verpakkingen", "C", "I", "R", "A", "—"],
            ["P-07 Onderhoud", "C", "I", "S", "R/A", "—"],
            ["P-08 Incidentmanagement", "R/A", "I", "R", "S", "I"],
            ["P-09 Nood lekkage", "R/A", "I", "R", "S", "I"],
            ["P-10 Nood brand", "R/A", "I", "R", "S", "I"],
            ["P-11 SVHC-monitoring", "R/A", "I", "—", "—", "—"],
            ["P-12 Etikettering", "A", "I", "R", "S", "—"],
            ["P-13 Documentbeheer", "R/A", "I", "S", "S", "—"],
            ["P-14 Opleiding", "R", "A", "I", "—", "S"],
            ["P-15 Interne audit", "R/A", "I", "C", "C", "C"],
        ]
    )

    doc.add_page_break()

    # 5. Procedures
    doc.add_heading("5. Procedures", level=1)
    
    procedures = [
        ("5.1 P-01: Tankniveaubewaking", "PGS 15:2025 M30", [
            "Doel: Voorkomen overloop en onbeheerd verlies van gevaarlijke stoffen",
            "Frequentie: Continue (automatisch) + dagelijkse visuele check",
            "Stappen:",
            "  1. Niveausensor uitlezen per tank (continue monitoring)",
            "  2. High-level alarm bij 90% vullingsgraad",
            "  3. High-high interlock bij 95% vullingsgraad — pomp/levering stopt automatisch",
            "  4. Dagelijkse visuele controle door operator",
            "  5. Afwijkingen direct melden aan HSE Manager",
            "Records: Loggen in SCADA/DCS, wekelijkse rapportage"
        ]),
        ("5.2 P-02: Temperatuurbewaking", "PGS 15:2025 M30", [
            "Doel: Voorkomen kristallisatie NaOH en ongewenste temperatuurstijging",
            "Frequentie: Continue (automatisch)",
            "Stappen:",
            "  1. Temperatuursensor per tank (NaOH-prioriteit)",
            "  2. Alarm bij NaOH <12°C — automatische tracing inschakelen",
            "  3. Alarm bij H₂SO₄ >40°C — ventilatie/koeling activeren",
            "  4. Controle tracing-verwarming voor winters seizoen (oktober-maart)",
            "  5. Loggen in SCADA/DCS",
            "Records: Temperatuurlog 24/7, maandelijkse rapportage"
        ]),
        ("5.3 P-03: Lekdetectie", "PGS 15:2025 M29", [
            "Doel: Direct detecteren van lekkage uit tanks en leidingen",
            "Type: Dubbelwandig (interstitiële sensor) of enkelwandig (bekkensensor)",
            "Frequentie: Continue + maandelijkse functionele test",
            "Stappen:",
            "  1. Sensorstatus uitlezen (continue monitoring)",
            "  2. Bij alarm: direct visuele inspectie + indammen",
            "  3. Lekkage classificeren: klein (<1L), middel (1-50L), groot (>50L)",
            "  4. Noodprocedure P-09 activeren indien nodig",
            "  5. Incident rapporteren via P-08",
            "Records: Sensortest maandelijks, incidentrapport per gebeurtenis"
        ]),
        ("5.4 P-04: Inventarisatie Stoffen", "PGS 15:2025 M116-M117", [
            "Doel: Actueel overzicht van alle opgeslagen gevaarlijke stoffen",
            "Frequentie: Continue bij wijziging, minimaal maandelijks volledige inventarisatie",
            "Stappen:",
            "  1. Bij ontvangst: stof registreren in Chemicals Master Register",
            "  2. SDS toevoegen aan digitaal archief",
            "  3. Locatie toewijzen conform scheidingsschema (zuren vs basen)",
            "  4. Maandelijks: fysieke telling vs register",
            "  5. Afwijkingen rapporteren en corrigeren",
            "Records: Chemicals Master Register (v2.1.0+), maandelijks rapport"
        ]),
        ("5.5 P-05: Laad- en Losoperaties", "PGS 15:2025 M134", [
            "Doel: Veilig laden en lossen van gevaarlijke stoffen",
            "Frequentie: Per operatie",
            "Stappen:",
            "  1. Pre-check: PBM's aan, nooddouche bereikbaar, lekkagemateriaal paraat",
            "  2. Identificatie stof + verificatie tegen SDS/leveringsbon",
            "  3. Verpakking inspecteren op beschadiging (P-06)",
            "  4. Correcte locatie bepalen (zuur-vak vs base-vak)",
            "  5. Laad/los volgens protocol met minimum 2 personen aanwezig",
            "  6. Na afloop: lekdetectie check, administratie bijwerken",
            "  7. Bij incident: P-08/P-09 activeren",
            "Records: Laad/los-formulier per operatie"
        ]),
        ("5.6 P-06: Inspectie Verpakkingen", "PGS 15:2025 M45", [
            "Doel: Tijdig detecteren van beschadigde, gecorrodeerde of lekkende verpakkingen",
            "Frequentie: Bij ontvangst + wekelijkse visuele ronde",
            "Stappen:",
            "  1. Visuele inspectie: scheuren, deuken, corrosie, lekkage, etiketbeschadiging",
            "  2. Etiket controle: leesbaarheid, juiste GHS-pictogrammen",
            "  3. Bij afwijking: verpakking isoleren, niet gebruiken",
            "  4. Beschadigde verpakking overpompen naar veilige container",
            "  5. Incident rapporteren via P-08",
            "Records: Inspectielijst wekelijks"
        ]),
        ("5.7 P-07: Onderhoud Opslagvoorzieningen", "PGS 15:2025 M36-M38", [
            "Doel: Opslagvoorzieningen in optimale staat houden",
            "Frequentie: Maandelijks visueel, kwartaals preventief, jaarlijks uitgebreid",
            "Stappen:",
            "  1. Maandelijks: visuele check constructie, opvangbakken, ventilatie",
            "  2. Kwartaals: sensoren calibreren, tracing testen, blussers checken",
            "  3. Jaarlijks: uitgebreide keuring door gecertificeerd inspectiebedrijf",
            "  4. Gebreken direct verhelpen (M36)",
            "  5. Keuringsrapport archiveren",
            "Records: Onderhoudslog, keuringsrapporten"
        ]),
        ("5.8 P-08: Incidentmanagement", "PGS 15:2025 M120-M121", [
            "Doel: Gestructureerd omgaan met alle incidenten",
            "Frequentie: Per incident + kwartaals evaluatie",
            "Stappen:",
            "  1. Direct: veiligheid waarborgen — indammen, evacueren indien nodig",
            "  2. Melden: aan HSE Manager binnen 15 minuten",
            "  3. Classificeren: near-miss, incident, ernstig incident",
            "  4. Onderzoek: root-cause analyse binnen 48 uur",
            "  5. Correctieve actie: CAPA-formulier, eigenaar + deadline",
            "  6. Communicatie: betrokkenen informeren, lessen delen",
            "  7. Afsluiten: verificatie uitgevoerde acties",
            "Records: Incidentenregister, CAPA-formulieren, kwartaalevaluatie"
        ]),
        ("5.9 P-09: Noodprocedure Lekkage", "PGS 15:2025 M119-M120", [
            "Doel: Veilig en snel reageren bij lekkage van gevaarlijke stoffen",
            "Alarmsignalen: lekdetectie alarm, visuele lekkage, geur",
            "Stappen:",
            "  1. ALARM — waarschuw collega's, evacueer directe omgeving",
            "  2. PBM's aantrekken (zuur/base-bestendig)",
            "  3. Bron indammen: lekvrije bak, absorptiemateriaal",
            "  4. NOOIT vrijkomen zuur en base mengen — exotherme reactie!",
            "  5. H₂SO₄-lekkage: neutraliseren met soda (natriumcarbonaat)",
            "  6. NaOH-lekkage: neutraliseren met citroenzuur-oplossing",
            "  7. Grote lekkage (>50L): brandweer bellen (112), P-10 activeren",
            "  8. Opruimen: gemorste stof in geschikt afvalvat",
            "  9. Ventileren tot dampen verdwenen",
            "  10. Incident rapporteren via P-08",
            "Records: Noodprocedure-formulier, incidentrapport"
        ]),
        ("5.10 P-10: Noodprocedure Brand", "PGS 15:2025 M95, M115", [
            "Doel: Veilig reageren bij brand in of nabij opslagvoorziening",
            "Stappen:",
            "  1. ALARM — brandalarm activeren, evacueren via vluchtroutes",
            "  2. Brandweer bellen (112) — opgeven: locatie, stoffen, hoeveelheden",
            "  3. NOOIT blussen met water op zuur-lekkage (spatgevaar)",
            "  4. Poederblusser (6 kg) gebruiken voor kleine branden",
            "  5. Bij grote brand: niet zelf blussen — evacueren en wachten op brandweer",
            "  6. Calamiteitenploeg ondersteunt brandweer met stofinformatie",
            "  7. Stoffenlijst + plattegrond beschikbaar stellen (M116)",
            "Records: Brandrapport, evaluatie"
        ]),
        ("5.11 P-11: SVHC-Monitoring", "PGS 15:2025 M137", [
            "Doel: Tijdig identificeren van SVHC/ZZS-stoffen in opslag",
            "Frequentie: 2x/jaar (januari + juli) + bij nieuwe leveringen",
            "Stappen:",
            "  1. ECHA-kandidaatlijst raadplegen op nieuwe SVHC-stoffen",
            "  2. RIVM ZZS-lijst raadplegen",
            "  3. Alle opgeslagen stoffen toetsen tegen beide lijsten",
            "  4. Bij match: SDS actualiseren, autorisatiedossier opstellen (REACH art. 58)",
            "  5. Vervanging onderzoeken (substitutie principe)",
            "  6. Resultaten rapporteren aan Plant Manager",
            "Records: SVHC-monitoring rapport 2x/jaar"
        ]),
        ("5.12 P-12: Etikettering en Signalering", "PGS 15:2025 M135-M136", [
            "Doel: Alle tanks, leidingen en opslaglocaties correct gelabeld",
            "Frequentie: Maandelijks controle, direct bij wijziging",
            "Zie D3 v2.0 §4 voor volledige etiketteringsspecificaties"
        ]),
        ("5.13 P-13: Documentbeheer", "PGS 15:2025 M115-M121, M137", [
            "Doel: Alle 11 verplichte documenttypen actueel en toegankelijk houden",
            "Zie D3 v2.0 §5 voor volledig overzicht en beheersprocedure"
        ]),
        ("5.14 P-14: Opleiding en Training", "PGS 15:2025 §7.4.3, M85", [
            "Doel: Alle medewerkers deskundig en bekend met gevaren",
            "Frequentie: Bij indiensttreding + jaarlijkse herhaling",
            "Inhoud: PGS-15 basis, stofspecifieke gevaren, PBM-gebruik, noodprocedures, lekkage-afhandeling",
            "Records: Trainingsmatrix, deelnamecertificaten"
        ]),
        ("5.15 P-15: Interne Audit", "PGS 15:2025", [
            "Doel: Regelmatig toetsen van PGS 15:2025 naleving",
            "Frequentie: Minimaal jaarlijks + bij significante wijzigingen",
            "Zie Audit Procedure v3.0 en Audit Checklist v3.0"
        ]),
    ]
    
    for title, ref, steps in procedures:
        doc.add_heading(title, level=2)
        p = doc.add_paragraph(f"Referentie: {ref}")
        p.runs[0].italic = True
        for s in steps:
            if s.startswith("  "):
                add_bullet(doc, s.strip(), level=1)
            else:
                doc.add_paragraph(s)
        doc.add_paragraph("")

    doc.add_page_break()

    # 6. KPI's
    doc.add_heading("6. KPI's", level=1)
    add_table(doc,
        ["#", "KPI", "Doelwaarde", "Meetfrequentie", "Bron"],
        [
            ["1", "PGS-15 conformiteitspercentage", "≥95%", "Kwartaals", "Interne audit P-15"],
            ["2", "Incidenten lekkage gevaarlijke stoffen", "<3/jaar", "Continu", "Incidentenregister P-08"],
            ["3", "SDS-beschikbaarheid", "100%", "Maandelijks", "Inventarisatie P-04"],
            ["4", "Temperatuuralarms NaOH opgevolgd", "100%", "Maandelijks", "SCADA-log P-02"],
            ["5", "Niveaubewaking interlocks functioneel", "100%", "Maandelijks", "Functionele test P-01"],
            ["6", "Lekdetectie functionele tests", "12/jaar (maandelijks)", "Maandelijks", "Testrapport P-03"],
            ["7", "Opleidingsdekking PGS-15", "100% medewerkers", "Jaarlijks", "Trainingsmatrix P-14"],
            ["8", "Documenten actueel (11 typen)", "100%", "Kwartaals", "Documentenreview P-13"],
            ["9", "Correctieve acties afgerond binnen deadline", "≥90%", "Kwartaals", "CAPA-register P-08"],
            ["10", "SVHC-monitoring uitgevoerd", "2x/jaar", "Semi-jaarlijks", "Monitoringrapport P-11"],
        ]
    )

    doc.add_page_break()

    # 7. Toelichtend stuk
    doc.add_heading("7. Toelichtend Stuk — Implementatie", level=1)
    doc.add_heading("7.1 Implementatie in 5 fasen", level=2)
    
    phases = [
        ("Fase 1: Voorbereiding (Week 1-2)", [
            "Huidige situatie-analyse (gap-analyse t.o.v. PGS 15:2025)",
            "Benodigde materialen/resources inventariseren",
            "Scheidingsplan opstellen (zuur vs base vakken)",
            "Etikettering en signalering bestellen"
        ]),
        ("Fase 2: Fysieke implementatie (Week 3-6)", [
            "Opvangvoorzieningen plaatsen/verifiëren",
            "Scheidingsmaatregelen implementeren",
            "Etikettering aanbrengen (tanks, leidingen, borden)",
            "Nooddouche en oogdoucher installeren/verifiëren",
            "Temperatuursensoren + tracing NaOH installeren"
        ]),
        ("Fase 3: Documentatie (Week 5-7)", [
            "SDS complete set verzamelen (incl. vanadium)",
            "Stoffenlijst actualiseren",
            "Plattegrond opslag updaten",
            "Calamiteiteninstructie + lekkage-instructie opstellen",
            "Alle 11 documenttypen compleet maken"
        ]),
        ("Fase 4: Training (Week 7-8)", [
            "Alle medewerkers trainen op PGS-15 procedures",
            "Noodoefening lekkage uitvoeren",
            "Competenties vastleggen in trainingsmatrix"
        ]),
        ("Fase 5: Validatie en Go-Live (Week 9-10)", [
            "Interne audit uitvoeren (P-15)",
            "Bevindingen verhelpen",
            "Go-Live: alle procedures formeel van kracht",
            "Eerste kwartaalrapportage opzetten"
        ]),
    ]
    
    for phase_title, items in phases:
        doc.add_heading(phase_title, level=3)
        for item in items:
            add_bullet(doc, item)

    doc.add_heading("7.2 Budgetraming", level=2)
    add_table(doc,
        ["Post", "Ramingsbasis", "Geschat bedrag"],
        [
            ["Opvangvoorzieningen", "Materiaal + plaatsing", "€ 5.000 - 10.000"],
            ["Scheidingsmaatregelen", "Muurtjes/lekkeerbakken", "€ 2.000 - 5.000"],
            ["Etikettering + signalering", "Borden, pictogrammen, labels", "€ 1.000 - 3.000"],
            ["Temperatuurbewaking + tracing", "Sensoren + verwarming", "€ 3.000 - 8.000"],
            ["Nooddouche + oogdoucher", "Installatie + aansluiting", "€ 2.000 - 5.000"],
            ["Training materialen", "eLearning, quiz, docent", "€ 2.000 - 5.000"],
            ["Consultancy (JvG)", "Begeleiding implementatie", "€ 8.000 - 15.000"],
            ["TOTAAL", "", "€ 23.000 - 51.000"],
        ]
    )

    doc.add_heading("7.3 Risicoanalyse implementatie", level=2)
    add_table(doc,
        ["Risico", "Kans", "Impact", "Mitigatie"],
        [
            ["SDS vanadium ontbreekt", "Hoog", "Medium", "Direct aanvragen bij leverancier; tijdelijk werkverbod"],
            ["Budget overschrijding", "Medium", "Medium", "10% buffer inbegrepen; fasering moge