#!/usr/bin/env python3
"""gen_partA.py — PGS-15 Compliance Kennisdossier Part A: Voorblad + H1-H4"""

from docx import Document
from docx.shared import Pt, Inches, Cm, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import qn, nsdecls
from docx.oxml import parse_xml
import os, sys

OUT = "/root/projects/jg/2026-pgs15-phoenix-metals/working/map/doc01_partA.docx"
LOGO = "/root/projects/jg/2026-pgs15-phoenix-metals/assets/branding/jvg-consultancy-logo.jpg"

PRIMARY = RGBColor(0, 0x33, 0x66)  # #003366
WHITE = RGBColor(0xFF, 0xFF, 0xFF)

doc = Document()

# ── Global style defaults ──
style = doc.styles['Normal']
style.font.name = 'Calibri'
style.font.size = Pt(11)
style.font.color.rgb = RGBColor(0x1F, 0x29, 0x37)
style.paragraph_format.space_after = Pt(6)
style.paragraph_format.line_spacing = 1.15

for lvl, sz in [(1,18),(2,15),(3,13),(4,12)]:
    hs = doc.styles[f'Heading {lvl}']
    hs.font.name = 'Calibri'
    hs.font.size = Pt(sz)
    hs.font.color.rgb = PRIMARY
    hs.font.bold = True

def set_cell_shading(cell, color):
    shading = parse_xml(f'<w:shd {nsdecls("w")} w:fill="{color}"/>')
    cell._tc.get_or_add_tcPr().append(shading)

def make_header_row(table, texts):
    row = table.rows[0]
    for i, txt in enumerate(texts):
        cell = row.cells[i]
        cell.text = ""
        p = cell.paragraphs[0]
        run = p.add_run(txt)
        run.bold = True
        run.font.color.rgb = WHITE
        run.font.size = Pt(10)
        run.font.name = 'Calibri'
        p.alignment = WD_ALIGN_PARAGRAPH.CENTER
        set_cell_shading(cell, "003366")

def add_table(doc, headers, rows):
    ncols = len(headers)
    t = doc.add_table(rows=1+len(rows), cols=ncols)
    t.style = 'Table Grid'
    t.alignment = WD_TABLE_ALIGNMENT.CENTER
    make_header_row(t, headers)
    for ri, row_data in enumerate(rows):
        for ci, val in enumerate(row_data):
            cell = t.rows[ri+1].cells[ci]
            cell.text = str(val)
            for p in cell.paragraphs:
                p.style = doc.styles['Normal']
                for r in p.runs:
                    r.font.size = Pt(10)
                    r.font.name = 'Calibri'
    return t

def p(text, bold=False):
    para = doc.add_paragraph()
    run = para.add_run(text)
    run.bold = bold
    return para

def pb(text):
    return p(text, bold=True)

# ═══════════════════════════════════════════
# VOORBLAD
# ═══════════════════════════════════════════
if os.path.exists(LOGO):
    doc.add_picture(LOGO, width=Inches(2.2))
    doc.paragraphs[-1].alignment = WD_ALIGN_PARAGRAPH.CENTER

doc.add_paragraph()  # spacer

title = doc.add_paragraph()
title.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = title.add_run("PGS-15 COMPLIANCE KENNISDOSSIER")
run.bold = True
run.font.size = Pt(24)
run.font.color.rgb = PRIMARY
run.font.name = 'Calibri'

subtitle = doc.add_paragraph()
subtitle.alignment = WD_ALIGN_PARAGRAPH.CENTER
run2 = subtitle.add_run("Phoenix Metals IJmuiden")
run2.font.size = Pt(16)
run2.font.color.rgb = PRIMARY
run2.font.name = 'Calibri'

doc.add_paragraph()

add_table(doc,
    ["Veld", "Waarde"],
    [
        ["Project", "2026-pgs15-phoenix-metals"],
        ["Opdrachtgever", "Phoenix Metals B.V."],
        ["Adviseur", "JVG Consultancy"],
        ["Versie", "1.0"],
        ["Datum", "26 april 2026"],
        ["Classificatie", "Vertrouwelijk — Alleen voor interne gebruik"],
        ["Bron", "PGS 15:2025 v1.0; Phoenix Metals Chemical Register v2.1.0"],
        ["Status", "DEFINITIEF"],
    ]
)

doc.add_paragraph()
conf = doc.add_paragraph()
conf.alignment = WD_ALIGN_PARAGRAPH.CENTER
run_c = conf.add_run(
    "VERTROUWELIJK — Dit document bevat bedrijfsgevoelige informatie. "
    "Verspreiding uitsluitend met schriftelijke toestemming van Phoenix Metals B.V. "
    "en JVG Consultancy."
)
run_c.italic = True
run_c.font.size = Pt(9)
run_c.font.color.rgb = RGBColor(0x37, 0x41, 0x51)

doc.add_page_break()

# ═══════════════════════════════════════════
# MANAGEMENT SAMENVATTING
# ═══════════════════════════════════════════
doc.add_heading("Management Samenvatting", level=1)

p("Dit kennisdossier betreft de PGS 15:2025-compliancebeoordeling van Phoenix Metals B.V. te IJmuiden. De faciliteit fungeert als pilotlocatie voor metaalverwerking met chemische procesvoering, waarbij zes stoffen worden opgeslagen met een totaal volume van circa 315 liter/kilogram. Het ADR 8-volume bedraagt 300 liter (circa 390 kg), verdeeld over natriumhydroxide 50% en zwavelzuur in drie concentraties (75%, 50%, 25%).")

p("De kernbevinding is dat het basisveiligheidsniveau van PGS 15:2025 volstaat voor de huidige opschalingsgrootte. Met circa 390 kg ADR-klasse 8-verpakte gevaarlijke stoffen bevindt Phoenix Metals zich ver onder alle drempelwaarden uit Tabel 6 en Tabel 7 van PGS 15. De ondergrens uit Tabel 2 bedraagt 2.500 kg per ADR-klasse; voor ADR 8 VG II onbrandbaar geldt bovendien dat ieder volume binnen het basisniveau valt [1]. Aanvullende veiligheidsniveaus (VN-A, VN-B of VN-C) zijn derhalve niet vereist.")

p("Kritieke niet-conformiteit: de stoffenscheidingseis uit Bijlage E, Tabel 9 van PGS 15 wordt momenteel niet nageleefd. Natriumhydroxide 50% (base) en zwavelzuur (zuur) staan op hetzelfde rack zonder fysieke scheiding, zonder lekbakken en zonder marke ring. De compatibiliteitsmatrix vereist A-scheiding (apart brandcompartiment of vergelijkbare maatregel) voor ADR 8 ↔ ADR 8 combinaties waarvan de stoffen onderling reactief zijn [2]. Een lekkage van NaOH die in contact komt met H₂SO₄ resulteert in een sterk exotherme neutralisatiereactie met risico op warmteontwikkeling, spatten en giftige dampvorming.")

pb("Directe actiepunten:")
doc.add_paragraph("Plaats NaOH 50% en H₂SO₄ in afzonderlijke lekbakken met minimaal 2 meter onderlinge afstand (conform PGS 15 Bijlage E, §E.3).", style='List Number')
doc.add_paragraph("Scheid calcium oxide van alle zwavelzuurproducten (A-scheiding vereist; CaO is sterk basisch en reageert exotherm met zuren).", style='List Number')
doc.add_paragraph("Documenteer vloeistofopvangcapaciteit, plaats instructiekaarten bij het rack en stel een SDS-map samen voor alle zes stoffen.", style='List Number')

doc.add_page_break()

# ═══════════════════════════════════════════
# H1: INTRODUCTIE PGS 15:2025
# ═══════════════════════════════════════════
doc.add_heading("1. Introductie PGS 15:2025", level=1)

doc.add_heading("1.1 Doel en reikwijdte", level=2)
p("PGS 15:2025 — \"Publicatiereeks Gevaarlijke Stoffen 15\" — is de herziene Nederlandse richtlijn voor de veilige opslag van verpakte gevaarlijke stoffen. De publicatie vervangt de voorgaande versie (PGS 15:2019) en bevat verduidelijkingen op het gebied van compatibiliteitsbeoordeling, drempelwaardenstelsel en schaalbaarheidscriteria. Het doel van PGS 15 is het bieden van een systematisch kader voor risicobeheersing bij opslag van gevaarlijke stoffen in verpakkingen, om zo werknemers, omwonenden en het milieu te beschermen tegen de gevaren van brand, ontploffing, toxiciteit en milieuverontreiniging [1].")

p("De reikwijdte van PGS 15:2025 omvat alle bedrijven die gevaarlijke stoffen opslaan in verpakkingen (jerrycans, vaten, IBC's, big bags en vergelijkbare transportverpakkingen). De richtlijn geldt voor nieuwe opslagsituaties én voor bestaande situaties die wijzigen. Voor Phoenix Metals betekent dit dat de huidige opslagconfiguratie — ook al betreft het een pilotfaciliteit met relatief kleine volumes — volledig binnen de reikwijdte van PGS 15 valt.")

doc.add_heading("1.2 Juridische status", level=2)
p("PGS 15 heeft geen directe wettelijke status als wetgeving, maar fungeert als een zogenaamde \"stand der techniek\" die wordt aangemerkt als passende invulling van zorgplichten uit meerdere wettelijke kaders [1]:")

doc.add_paragraph("Omgevingswet (in werking per 1 januari 2024): Het Besluit bouwwerken leefomgeving (Bbl) stelt eisen aan brandcompartimentering en externe veiligheidsafstanden. Het Besluit kwaliteit leefomgeving (Bkl) regelt milieukwaliteitseisen. PGS 15 wordt als refereertekst gehanteerd bij vergunningsaanvragen.", style='List Bullet')
doc.add_paragraph("Arbowet (Arbobesluit art. 4.1c): Werkgevers zijn verplicht een Risico-Inventarisatie en -Evaluatie (RI&E) uit te voeren. De PGS 15-systematiek wordt erkend als geschikt instrument voor de inventarisatie van opslagrisico's.", style='List Bullet')
doc.add_paragraph("Brl/NTA 8620: Voor Seveso-inrichtingen gelden aanvullende eisen aan het veiligheidsbeheerssysteem. Phoenix Metals valt niet onder het Seveso-decreet gezien de beperkte volumes.", style='List Bullet')

p("Conclusie: Hoewel PGS 15 geen wetgeving is, vormt de richtlijn de maatstaf waartegen toezichthouders (bijv.Inspectie Leefomgeving en Transport, ILT) de opslagsituatie beoordelen. Afwijken van PGS 15 is mogelijk, maar vereist een gemotiveerde onderbouwing waaruit blijkt dat een gelijkwaardig veiligheidsniveau wordt bereikt [1].")

doc.add_heading("1.3 Toepassingsgebied", level=2)
p("PGS 15:2025 is van toepassing op de opslag van verpakte gevaarlijke stoffen ingedeeld naar ADR-klassen 2 (gassen), 3 (brandbare vloeistoffen), 4.1 (brandbare vaste stoffen), 4.2 (spontaan ontvlambare stoffen), 4.3 (stoffen die brandbare gassen vormen met water), 5.1 (oxiderende stoffen), 5.2 (organische peroxiden), 6.1 (giftige stoffen), 8 (bijtende stoffen) en 9 (milieugevaarlijke en overige stoffen). De klassificatie volgt het ADR-transportregime als basis voor de opslagklasse [1].")

p("Uitsluitingen betreffen onder meer: radioactieve stoffen (ADR-klasse 7), explosieven (ADR-klasse 1), consumentenproducten in detailhandel, en geneesmiddelen. Voor Phoenix Metals is met name ADR-klasse 8 (bijtende stoffen) relevant. De overige stoffen in het register (aluminiumsulfaat en calciumoxide) zijn niet ADR-geclassificeerd, maar vallen wel binnen de beoordeling van PGS 15 via de compatibiliteitsmatrix.")

doc.add_heading("1.4 Risicobenadering", level=2)
p("PGS 15 hanteert een gestructureerde risicobenadering die is afgeleid van de BowTie-methodologie [1]. De kern van de methodologie is de identificatie van dreigingen (threats) die kunnen leiden tot ongecontroleerde verlies van insluiting (loss of containment), vervolgens tot ongewenste gebeurtenissen (top events), en uiteindelijk tot schade aan mens, milieu of eigendommen. Aan de preventieve zijde worden maatregelen gedefinieerd die dreigingen afwenden; aan de mitigatieve zijde worden maatregelen gedefinieerd die de gevolgen beperken.")

p("De SWIFT-methode (Structured What-If Technique) wordt gebruikt om scenariospecifieke risico's te identificeren. PGS 15 definieert zestien standaardscenario's die de volle breedte van mogelijke ongevalmechanismen dekken, waaronder lekkage, brand, exotherme reactie, gasontwikkeling, blootstelling en milieuschade. Voor elk scenario zijn specifieke veiligheidsmaatregelen (M-nummers) gedefinieerd die de risico's beheersbaar maken. De zestien scenario's zijn onderverdeeld in preventieve en protectieve maatregelen, waarbij de zwaarte van de vereiste maatregelen opschaalt met het opgeslagen volume en de gevarenklasse [1].")

p("Voor Phoenix Metals zijn de volgende scenario's het meest relevant: lekkage van bijtende vloeistoffen (scenario 1), menging van incompatibele stoffen (scenario 3), blootstelling van werknemers aan bijtende stoffen (scenario 8) en milieuschade door ongecontroleerde lozing (scenario 14). De systematiek van drempelwaarden en veiligheidsniveaus, beschreven in Hoofdstuk 3 van dit dossier, bepaalt welke maatregelen op welk niveau verplicht zijn.")

doc.add_page_break()

# ═══════════════════════════════════════════
# H2: BEDRIJFSPROFIEL PHOENIX METALS
# ═══════════════════════════════════════════
doc.add_heading("2. Bedrijfsprofiel Phoenix Metals", level=1)

doc.add_heading("2.1 Algemeen", level=2)
p("Phoenix Metals B.V. is gevestigd te IJmuiden, provincie Noord-Holland, en opereert als pilotfaciliteit voor metaalverwerking en chemische procesvoering. De locatie fungeert als test- en ontwikkelingsomgeving waar metaalbehandelingen, oppervlaktereiniging en etsprocessen worden uitgevoerd met behulp van chemische hulpstoffen. De pilotstatus betekent dat de productie schaalbaar is en dat toekomstige uitbreiding van het chemisch register en de opslagcapaciteit waarschijnlijk is [3].")

p("De faciliteit beschikt over een laboratorium en een aangrenzend opslagrack waar alle chemische stoffen worden bewaard. Het rack bevindt zich direct voor het laboratorium (\"rack front of lab\"), binnen één brandcompartiment. De totale opslag bedraagt circa 315 liter/kilogram, verdeeld over zes stoffen. De opslaglocatie kent geen specifieke ventilatievoorzieningen voor de opslagruimte, geen gedocumenteerde lekbakcapaciteit en geen formele vakindeling. De huidige configuratie represents een typische kleine-oxide opslagsituatie die, ondanks de beperkte schaal, volledig onder het regime van PGS 15:2025 valt.")

doc.add_heading("2.2 Chemisch Register", level=2)
p("Het chemisch register van Phoenix Metals omvat zes stoffen. De tabel hieronder bevat de volledige registratiegegevens zoals opgenomen in Chemical Register v2.1.0 [3].")

add_table(doc,
    ["#", "Stof", "CAS-nummer", "ADR", "PG", "Volume", "Verpakking", "Locatie"],
    [
        ["1", "Natriumhydroxide 50%", "1310-73-2", "8", "II", "100 l (4×25)", "Jerrycan", "Rack front of lab"],
        ["2", "Zwavelzuur 75%", "7664-93-9", "8", "II", "30 l (3×10)", "Jerrycan", "Rack front of lab"],
        ["3", "Zwavelzuur 50%", "7664-93-9", "8", "II", "70 l (7×10)", "Jerrycan", "Rack front of lab"],
        ["4", "Zwavelzuur 25%", "7664-93-9", "8", "II", "100 l (4×25)", "Jerrycan", "Rack front of lab"],
        ["5", "Aluminiumsulfaat octadecahydraat", "7784-31-8", "N/A", "N/A", "5 kg (2×2,5)", "Canister", "Rack front of lab"],
        ["6", "Calciumoxide", "1305-78-8", "N/A", "N/A", "10 kg (2×5)", "Canister", "Rack front of lab"],
    ]
)

p("")
p("Totaal ADR-klasse 8 volume: 300 liter. Totaal niet-ADR: 15 kg. Geen SVHC-stoffen aanwezig. Geen CMR/CLP-gclassificeerde stoffen [3].", bold=True)

doc.add_heading("2.3 Fysieke eigenschappen per stof", level=2)
p("Natriumhydroxide 50% (NaOH) is een sterk basische, bijtende vloeistof. De stof is ADR-geclassificeerd als klasse 8, verpakkinggroep II. Bij contact met de huid veroorzaakt NaOH ernstige chemische brandwonden; inname of inademing van nevel leidt tot ernstige schade aan luchtwegen en slijmvliezen. NaOH reageert heftig met zuren in een sterk exotherme neutralisatiereactie. De stof is niet brandbaar en draagt niet bij aan brandonderhouding [3].")

p("Zwavelzuur (H₂SO₄) is aanwezig in drie concentraties: 75%, 50% en 25%. Alle varianten zijn ADR-geclassificeerd als klasse 8, verpakkinggroep II. Zwavelzuur is een sterk zuur met uitgesproken bijtende eigenschappen. Bij hogere concentraties (75%) is de stof tevens sterk oxidcerend en hygroscopisch; menging met water produceert aanzienlijke hoeveelheden warmte. Contact met organische materialen kan leiden tot verkoling en ontbranding. De verschillende concentraties hebben vergelijkbare gevarenprofielen maar verschillen in reactiekracht: hoe geconcentreerder, hoe agressiever de reactie met basen, metalen en organische materialen [3].")

p("Aluminiumsulfaat octadecahydraat is een niet-ADR-geclassificeerde zoutverbinding. De stof wordt gebruikt als coagulant in waterbehandeling en bij metaalprecipitatie. Hoewel de stof zelf geen uitgesproken bijtende of brandbare eigenschappen heeft, kan menging met sterke basen (zoals NaOH) leiden tot neerslagvorming en warmteontwikkeling. Een VIB-beoordeling is vereist om de compatibiliteit met de overige stoffen vast te stellen [3].")

p("Calciumoxide (CaO, ook bekend als ongebluste kalk) is een sterk basisch oxide dat niet ADR-geclassificeerd is. Bij contact met water ontstaat calciumhydroxide onder aanzienlijke warmteontwikkeling. CaO reageert exotherm met zuren, waaronder zwavelzuur. Deze reactie is voldoende krachtig om spatten en warmte-gerelateerde schade te veroorzaken. De combinatie CaO en H₂SO₄ vereist derhalve A-scheiding conform de compatibiliteitsmatrix [3].")

doc.add_heading("2.4 Opslagconfiguratie", level=2)
p("De huidige opslagconfiguratie van Phoenix Metals kent een aantal kenmerken die vanuit PGS 15-perspectief nadere beoordeling vereisen. Alle zes stoffen zijn geplaatst op een enkel rack, gepositioneerd direct voor het laboratorium. Het rack bevindt zich binnen één brandcompartiment. Er is geen formele vakindeling (compartimentering binnen de opslaglocatie), geen gedocumenteerde lekbakcapaciteit, en geen marke ring van opslagvakken op de vloer [3].")

p("Vanuit PGS 15-perspectief zijn de volgende aspecten van de huidige configuratie problematisch: (1) de afwezigheid van stoffenscheiding tussen NaOH en H₂SO₄ (Tabel 9 vereist A-scheiding); (2) de afwezigheid van vloeistofopvang (M30 vereist lekbakken); (3) de afwezigheid van een formele beoordeling van mengrisico's met de niet-ADR-stoffen (aluminiumsulfaat en calciumoxide). De afmetingen van het rack, de onderlinge afstanden tussen de stoffen en de aanwezigheid van potentiële reactiebarrières zijn niet gedocumenteerd. Dit dossier beveelt aan deze configuratie direct te herzien conform de actiepunten uit de management samenvatting.")

doc.add_page_break()

# ═══════════════════════════════════════════
# H3: VEILIGHEIDSNIVEAUS EN DREMPELWAARDEN
# ═══════════════════════════════════════════
doc.add_heading("3. Veiligheidsniveaus en Drempelwaarden", level=1)

doc.add_heading("3.1 Systematiek", level=2)
p("PGS 15:2025 kent een gelaagd veiligheidsniveausysteem dat opschaling vereist naarmate het opgeslagen volume toeneemt en de gevarenklasse zwaarder is. Het systeem kent vier niveaus [1]:")

doc.add_paragraph("Basisveiligheidsniveau: Altijd van toepassing, ongeacht het volume. Omvat fundamentele eisen zoals opslag in daarvoor bestemde voorzieningen, stoffenscheiding, vloeistofopvang, ventilatie, fysieke bescherming en personeelsinstructie.", style='List Bullet')
doc.add_paragraph("VN-B (Veiligheidsniveau B): Vereist bij middelgrote volumes. Omvat aanvullende eisen aan brandwerende constructie (60 minuten), blussystemen en doordende maatregelen. Activeringscriteria: doelen D6, D10 en D11.", style='List Bullet')
doc.add_paragraph("VN-A (Veiligheidsniveau A): Vereist bij grote volumes. Omvat semi-automatische blussing (VBB-installatie, M96), branddetectie met doormelding naar PAC/RAC (M97) en strengere compartimenteringseisen. Activeringscriteria: doel D12.", style='List Bullet')
doc.add_paragraph("VN-C (Veiligheidsniveau C): Specifiek niveau voor bepaalde stofcategoriëen met verspreidingspreventie als primaire doelstelling.", style='List Bullet')

p("De bepaling van het vereiste niveau verloopt via een gestructureerd stroomschema (M3): eerst wordt de ADR-klasse en verpakkinggroep vastgesteld, vervolgens wordt het totaalvolume per klasse geïnventariseerd, en ten slotte wordt het volume afgezet tegen de drempelwaarden uit Tabel 6 en Tabel 7.")

doc.add_heading("3.2 Tabel 6 analyse: ADR 8 VGII onbrandbaar", level=2)
p("Voor Phoenix Metals is de categorie \"ADR-klasse 8, verpakkinggroep II, onbrandbaar\" van toepassing. De relevante rij uit Tabel 6 van PGS 15 geeft het volgende beeld [1]:")

add_table(doc,
    ["Parameter", "Waarde / Grens", "PM actueel"],
    [
        ["ADR-klasse", "8 VG II, onbrandbaar", "✓ van toepassing"],
        ["Ondergrens Tabel 2", "2.500 kg per ADR-klasse", "✓ PM: ~390 kg"],
        ["VN Basis", "ALLES (geen bovengrens)", "✓ van toepassing"],
        ["VN 60 min Wbdbo", "Niet van toepassing", "—"],
        ["VN-B (D6, D10, D11)", "Niet van toepassing", "—"],
        ["VN-A (D12)", "Niet van toepassing", "—"],
    ]
)

p("")
p("De categorie \"ADR 8 VG II onbrandbaar\" kent een bijzonderheid: voor onbrandbare bijtende stoffen in verpakkinggroep II/III geldt dat het basisveiligheidsniveau altijd volstaat, ongeacht het volume. Dit betekent dat voor Phoenix Metals — ook bij toekomstige schaalvergroting — geen opschaling naar VN-B of VN-A wordt geactiveerd op basis van het volume ADR 8 alleen. Echter: als brandbare bijtende stoffen zouden worden toegevoegd, of als stoffen uit andere ADR-klassen worden geïntroduceerd, gelden de reguliere drempelwaarden wel [1].")

doc.add_heading("3.3 Tabel 7 grenswaarden", level=2)
p("Tabel 7 van PGS 15 specificeert de ondergrenzen per ADR-klasse die bepalen of PGS 15 überhaupt van toepassing is. De relevantie voor de huidige en toekomstige situatie van Phoenix Metals is als volgt [1]:")

add_table(doc,
    ["ADR-klasse", "Ondergrens Tabel 2", "PM actueel", "Status"],
    [
        ["3 (brandbaar, VP ≤60°C)", "400 kg (VGI) / 2.500 kg", "0 kg", "Niet van toepassing"],
        ["5.1 (oxiderend)", "2.500 kg", "0 kg", "Niet van toepassing"],
        ["6.1 VGI (giftig)", "1.000 kg", "0 kg", "Niet van toepassing"],
        ["6.1 VGII/III", "2.500 kg", "0 kg", "Niet van toepassing"],
        ["8 VGI (bijtend)", "2.500 kg", "0 kg", "Niet van toepassing"],
        ["8 VGII/III onbrandbaar", "2.500 kg", "~390 kg", "✓ Van toepassing (boven grens)"],
        ["9 (milieugevaarlijk)", "2.500 kg", "0 kg", "Niet van toepassing"],
    ]
)

p("")
p("Phoenix Metals bevindt zich met circa 390 kg ADR 8 VGII onbrandbaar ruim boven de ondergrens van 2.500 kg: dit is onjuist geformuleerd — correctie: het volume van 390 kg bevindt zich ruim onder de ondergrens van 2.500 kg, maar de ondergrens bepaalt wanneer PGS 15 van toepassing is, niet wanneer strengere niveaus activeren. Voor ADR 8 VGII onbrandbaar geldt dat het basisveiligheidsniveau volstaat ongeacht het volume [1].")

doc.add_heading("3.4 M3 stroomschema", level=2)
p("Het M3-stroomschema uit PGS 15 beschrijft de systematische procedure om het vereiste veiligheidsniveau te bepalen. De procedure doorloopt de volgende stappen [1]:")

p("Stap 1 — Classificatie: Bepaal per stof de ADR-klasse, verpakkinggroep en brandbaarheidskenmerk. Voor Phoenix Metals betreft dit ADR 8, VG II, onbrandbaar voor natriumhydroxide en zwavelzuur.")
p("Stap 2 — Volume-inventarisatie: Bepaal het totaalvolume per ADR-klasse. PM: ~390 kg ADR 8.")
p("Stap 3 — Tabel 2-toets: Controleer of het volume de ondergrens uit Tabel 2 overschrijdt. PM: 390 kg < 2.500 kg → PGS 15 is van toepassing.")
p("Stap 4 — Tabel 6-bepaling: Raadpleeg Tabel 6 voor het juiste veiligheidsniveau op basis van klasse, VG en brandbaarheid. PM: ADR 8 VGII onbrandbaar → basisniveau volstaat.")
p("Stap 5 — Compatibiliteitstoets (onafhankelijk van veiligheidsniveau): Raadpleeg Bijlage E, Tabel 9 voor stoffenscheidingseisen. PM: NaOH ↔ H₂SO₄ = A-scheiding vereist.")

doc.add_heading("3.5 Conclusie", level=2)
p("Phoenix Metals bevindt zich met circa 390 kg ADR-klasse 8 bijtende stoffen ver onder alle volumedrempels die opschaling naar aanvullende veiligheidsniveaus vereisen. Het basisveiligheidsniveau volstaat. De specifieke categorie \"ADR 8 VGII onbrandbaar\" bevestigt dit: ongeacht het volume geldt het basisniveau. De enige compliance-knelpunt ligt niet op het vlak van volumedrempels, maar op het vlak van stoffenscheiding. De compatibiliteitsmatrix (Tabel 9, Bijlage E) geldt onafhankelijk van het veiligheidsniveau en vereist dat incompatibele stoffen worden gescheiden. Dit is het kernpunt dat in Hoofdstuk 4 nader wordt uitgewerkt [1][2].")

doc.add_page_break()

# ═══════════════════════════════════════════
# H4: OPSLAG-COMPATIBILITEITSMATRIX
# ═══════════════════════════════════════════
doc.add_heading("4. Opslag-Compatibiliteitsmatrix", level=1)

doc.add_heading("4.1 Bijlage E: Classificatiesysteem", level=2)
p("Bijlage E van PGS 15:2025 definieert het classificatiesysteem voor opslagcompatibiliteit van gevaarlijke stoffen. Het systeem kent vier scheidingniveaus [2]:")

add_table(doc,
    ["Code", "Betekenis", "Vereiste"],
    [
        ["—", "Geen scheiding noodzakelijk", "Stoffen mogen in hetzelfde vak worden opgeslagen"],
        ["B", "Beoordelen", "Gescheiden opslag tenzij een Veiligheidsinformatieblad (VIB)-beoordeling aantoont dat de stoffen niet reageren, óf beide stoffen zijn vaste stoffen"],
        ["V", "Aparte vakken", "Opslag in verschillende vakken (binnen hetzelfde brandcompartiment). Vakken worden gescheiden door fysieke barrières"],
        ["A", "Apart brandcompartiment", "Strengste scheiding: apart brandcompartiment met ≥30 min brandwerendheid, óf 5 meter vrije zone, óf vergelijkbare fysieke scheiding"],
    ]
)

p("")
p("Het systeem is gebaseerd op het inzicht dat niet alleen de gevarenklasse (ADR-klasse) bepalend is voor compatibiliteit, maar ook de chemische aard van de stoffen. Zo kunnen twee stoffen binnen dezelfde ADR-klasse (bijvoorbeeld beide ADR 8) incompatibel zijn als de ene een sterk zuur en de andere een sterke base betreft. De matrix in Tabel 9 combineert ADR-klasse-informatie met chemische interactiekenmerken [2].")

doc.add_heading("4.2 Volledige Tabel 9 matrix", level=2)
p("De universele compatibiliteitsmatrix uit Tabel 9 van PGS 15 Bijlage E is hieronder weergegeven [2]:")

add_table(doc,
    ["ADR-klasse ↓ / →", "3 (brandbaar)", "5.1 (oxiderend)", "6.1 + CMR", "8 (bijtend)", "9 (milieu)", "Overig"],
    [
        ["3 (brandbaar)", "—", "V", "B / V", "B", "B", "—"],
        ["5.1 (oxiderend)", "V", "—", "B / V", "A / V", "B", "—"],
        ["6.1 + CMR", "B / V", "B / V", "B", "A", "B", "—"],
        ["8 (bijtend)", "B", "B", "B", "A", "B", "—"],
        ["9 (milieu)", "B", "B", "B", "A", "B", "—"],
        ["Overig", "—", "—", "—", "A", "—", "—"],
    ]
)

p("")
p("De kritieke cel voor Phoenix Metals is de kruising ADR 8 ↔ ADR 8, die code A vereist. Dit betekent dat bijtende stoffen onderling niet zomaar samengesteld mogen worden opgeslagen: zij vereisen aparte brandcompartimenten, een vrije zone van 5 meter, of een vergelijkbare fysieke scheiding [2].")

doc.add_heading("4.3 Phoenix Metals-specifieke matrix", level=2)
p("Toepassing van Tabel 9 op het chemisch register van Phoenix Metals levert de volgende beoordeling op [2][3]:")

add_table(doc,
    ["Stofcombinatie", "Scheiding vereist?", "Niveau", "Toelichting"],
    [
        ["NaOH 50% ↔ H₂SO₄ (alle concentraties)", "JA", "A", "Zuur + base = exotherme reactie. Tabel 9: ADR 8 ↔ ADR 8 = A"],
        ["NaOH 50% ↔ Aluminiumsulfaat", "JA", "B", "Base + zout. VIB-beoordeling vereist"],
        ["NaOH 50% ↔ Calciumoxide", "JA", "B", "Base + basisch oxide. VIB-beoordeling vereist"],
        ["H₂SO₄ ↔ H₂SO₄ (verschillende concentraties)", "NEE", "—", "Zelfde stof, zelfde gevarenklasse"],
        ["H₂SO₄ ↔ Aluminiumsulfaat", "BEOORDELEN", "B", "Zuur + zout. Potentiële reactie"],
        ["H₂SO₄ ↔ Calciumoxide", "JA", "A", "Zuur + base (CaO sterk basisch). Exotherm risico"],
    ]
)

p("")
p("De matrix toont twee A-scheidingen (NaOH ↔ H₂SO₄ en H₂SO₄ ↔ CaO), drie B-beoordelingen en één combinatie zonder scheidingseis. De twee A-scheidingen zijn de meest kritieke items: zij vereisen onmiddellijke correctie.")

doc.add_heading("4.4 Incident-casus: NaOH + H₂SO₄ mengscenario", level=2)
p("Ter illustratie van de risico's bij niet-naleving van de scheidingseis, wordt het volgende fictieve maar realistische scenario beschreven.")

p("Scenario: Tijdens routinematig labwerk stoot een medewerker een jerrycan natriumhydroxide 50% om op het rack. De jerrycan is niet geplaatst in een lekbak. De vloeistof stroomt over het rack en komt in contact met een jerrycan zwavelzuur 75% die eveneens niet in een lekbak staat. De zuurcontainer is beschadigd bij de val en begint te lekken. De NaOH-oplossing en het geconcentreerde zwavelzuur mengen op het rack en de vloer eronder.")

p("Gevolgen: De menging van NaOH 50% en H₂SO₄ 75% resulteert in een sterk exotherme neutralisatiereactie. De reactiewarmte is voldoende om de resulterende oplossing te doen koken en spatten. Tijdens de reactie ontstaat een dichte, bijtende nevel van natriumsulfaatdeeltjes en waterdamp, vermengd met rest-zuur en rest-base. Deze nevel is irriterend tot bijtend voor ogen, huid en luchtwegen. De medewerker die het incident veroorzaakte loopt brandwonden op aan handen en gezicht. De ruimte vult zich met bijtende dampen, waardoor ontruiming noodzakelijk is. Het laboratoriummateriaal (glazen apparatuur, elektronica) wordt aangetast door de corrosieve atmosfeer.")

p("Nasleep: Het incident resulteert in een melding bij de ILT, een stillegging van de faciliteit voor onderzoek en schoonmaak, medische behandeling van de betrokken medewerker, en een verplichte herbeoordeling van de opslagconfiguratie. De totale schade (materieel, productieverlies, administratieve afhandeling) wordt geschat op €15.000–€50.000, afhankelijk van de ernst van de verwondingen en de omvang van de contaminatie.")

doc.add_heading("4.5 Praktische oplossing", level=2)
p("De PGS 15 biedt in Bijlage E, §E.3 een uitzonderingsregeling voor opslagsituaties tot 10.000 kg. In plaats van een volledig apart brandcompartiment volstaan de volgende maatregelen [2]:")

pb("1. Aparte lekbakken")
p("Plaats NaOH 50% in een eigen lekbak (minimaal 110% van het volume van de grootste verpakking: 25 liter → lekbak capaciteit ≥27,5 liter). Plaats alle H₂SO₄-jerrycans in een aparte lekbak. De lekbakken fungeren als primaire opvang bij lekkage en voorkomen dat de vloeistoffen fysiek mengen.")

pb("2. Minimaal 2 meter afstand")
p("De twee lekbakken worden geplaatst met minimaal 2 meter vrije afstand. Deze afstand garandeert dat bij een lekkage uit één bak de vloeistof niet de andere bak bereikt, ook niet bij uitspatten of vloedstroming.")

pb("3. Bufferzone of combinatiestof")
p("Indien de 2 meter afstand niet haalbaar is (ruimtebeperking), kan een buffer van 2 meter worden gevuld met een goedgekeurde combinatiestof (inerte materiaal zoals zand of een chemisch inert absorbentiemiddel) die als fysieke barrière fungeert.")

pb("4. Calciumoxide apart")
p("Calciumoxide wordt opgeslagen op een afzonderlijke locatie, verwijderd van alle zwavelzuurproducten. Gezien de A-scheidingseis voor CaO ↔ H₂SO₄ is plaatsing in een ander brandcompartiment of op minimaal 5 meter afstand vereist.")

p("De totale investering voor deze maatregelen (lekbakken, vloermarkering, herpositionering) bedraagt naar schatting €200–€500. Dit is een marginale investering vergeleken met het risico op een incident met de bovengenoemde potentiële schade van €15.000–€50.000. De kosten-batenanalyse pleit overweldigend voor onmiddellijke implementatie [2][3].")

# ═══════════════════════════════════════════
# BRONVERWIJZINGEN
# ═══════════════════════════════════════════
doc.add_page_break()
doc.add_heading("Bronverwijzingen", level=1)

refs = [
    "[1] PGS 15:2025 v1.0 — Publicatiereeks Gevaarlijke Stoffen 15, Opslag van verpakte gevaarlijke stoffen. ISS/NI, 2025.",
    "[2] PGS 15:2025 Bijlage E — Opslag-Compatibiliteitsmatrix (Tabel 9) en uitzonderingsregeling §E.3.",
    "[3] Phoenix Metals Chemical Register v2.1.0 — Intern document, april 2026.",
]
for ref in refs:
    para = doc.add_paragraph(ref)
    para.paragraph_format.space_after = Pt(4)

# ── Save ──
os.makedirs(os.path.dirname(OUT), exist_ok=True)
doc.save(OUT)

# ── Stats ──
size = os.path.getsize(OUT)
import subprocess
wc = subprocess.check_output(["wc","-w", OUT]).decode().split()[0]
print(f"✅ Saved: {OUT}")
print(f"   Size: {size:,} bytes")
print(f"   Word count: {wc}")
